Re: [PATCH] Sync up MIME-Base64 to latest on CPAN
[p5sagit/p5-mst-13.2.git] / ext / MIME / Base64 / QuotedPrint.pm
CommitLineData
6fba102d 1#
ea0e37e4 2# $Id: QuotedPrint.pm,v 2.13 2003/05/13 18:22:09 gisle Exp $
6fba102d 3
4package MIME::QuotedPrint;
5
6=head1 NAME
7
8MIME::QuotedPrint - Encoding and decoding of quoted-printable strings
9
10=head1 SYNOPSIS
11
12 use MIME::QuotedPrint;
13
14 $encoded = encode_qp($decoded);
15 $decoded = decode_qp($encoded);
16
17=head1 DESCRIPTION
18
19This module provides functions to encode and decode strings into the
20Quoted-Printable encoding specified in RFC 2045 - I<MIME (Multipurpose
21Internet Mail Extensions)>. The Quoted-Printable encoding is intended
22to represent data that largely consists of bytes that correspond to
23printable characters in the ASCII character set. Non-printable
24characters (as defined by english americans) are represented by a
25triplet consisting of the character "=" followed by two hexadecimal
26digits.
27
28The following functions are provided:
29
30=over 4
31
32=item encode_qp($str)
33
6a63fb82 34=item encode_qp($str, $eol)
6fba102d 35
6a63fb82 36This function will return an encoded version of the string given as
37argument. The second argument is the line ending sequence to use (it
38is optional and defaults to C<"\n">).
6fba102d 39
40=item decode_qp($str);
41
42This function will return the plain text version of the string given
6a63fb82 43as argument. Lines with be "\n" terminated.
6fba102d 44
45=back
46
47
48If you prefer not to import these routines into your namespace you can
49call them as:
50
51 use MIME::QuotedPrint ();
52 $encoded = MIME::QuotedPrint::encode($decoded);
53 $decoded = MIME::QuotedPrint::decode($encoded);
54
55=head1 COPYRIGHT
56
6a63fb82 57Copyright 1995-1997,2002-2003 Gisle Aas.
6fba102d 58
59This library is free software; you can redistribute it and/or
60modify it under the same terms as Perl itself.
61
62=cut
63
64use strict;
65use vars qw(@ISA @EXPORT $VERSION);
95635e5f 66if (ord('A') == 193) { # on EBCDIC machines we need translation help
46891979 67 require Encode;
95635e5f 68}
6fba102d 69
70require Exporter;
71@ISA = qw(Exporter);
72@EXPORT = qw(encode_qp decode_qp);
73
b1387238 74use Carp qw(croak);
75
ea0e37e4 76$VERSION = "2.20";
6fba102d 77
6a63fb82 78use MIME::Base64; # try to load XS version of encode_qp
79unless (defined &encode_qp) {
80 *encode_qp = \&old_encode_qp;
81 *decode_qp = \&old_decode_qp;
82}
83
84sub old_encode_qp ($;$)
6fba102d 85{
86 my $res = shift;
b9e0df4c 87 if ($] >= 5.006) {
88 require bytes;
89 if (bytes::length($res) > length($res) ||
90 ($] >= 5.008 && $res =~ /[^\0-\xFF]/)) {
91 croak("The Quoted-Printable encoding is only defined for bytes");
92 }
93 }
b1387238 94
6a63fb82 95 my $eol = shift;
96 $eol = "\n" unless defined($eol) || length($eol);
97
95635e5f 98 # Do not mention ranges such as $res =~ s/([^ \t\n!-<>-~])/sprintf("=%02X", ord($1))/eg;
99 # since that will not even compile on an EBCDIC machine (where ord('!') > ord('<')).
100 if (ord('A') == 193) { # EBCDIC style machine
101 if (ord('[') == 173) {
102 $res =~ s/([^ \t\n!"#\$%&'()*+,\-.\/0-9:;<>?\@A-Z[\\\]^_`a-z{|}~])/sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('cp1047',$1))))/eg; # rule #2,#3
103 $res =~ s/([ \t]+)$/
104 join('', map { sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('cp1047',$_)))) }
105 split('', $1)
106 )/egm; # rule #3 (encode whitespace at eol)
107 }
108 elsif (ord('[') == 187) {
109 $res =~ s/([^ \t\n!"#\$%&'()*+,\-.\/0-9:;<>?\@A-Z[\\\]^_`a-z{|}~])/sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('posix-bc',$1))))/eg; # rule #2,#3
110 $res =~ s/([ \t]+)$/
111 join('', map { sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('posix-bc',$_)))) }
112 split('', $1)
113 )/egm; # rule #3 (encode whitespace at eol)
114 }
115 elsif (ord('[') == 186) {
116 $res =~ s/([^ \t\n!"#\$%&'()*+,\-.\/0-9:;<>?\@A-Z[\\\]^_`a-z{|}~])/sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('cp37',$1))))/eg; # rule #2,#3
117 $res =~ s/([ \t]+)$/
118 join('', map { sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('cp37',$_)))) }
119 split('', $1)
120 )/egm; # rule #3 (encode whitespace at eol)
121 }
122 }
123 else { # ASCII style machine
124 $res =~ s/([^ \t\n!"#\$%&'()*+,\-.\/0-9:;<>?\@A-Z[\\\]^_`a-z{|}~])/sprintf("=%02X", ord($1))/eg; # rule #2,#3
125 $res =~ s/([ \t]+)$/
126 join('', map { sprintf("=%02X", ord($_)) }
127 split('', $1)
128 )/egm; # rule #3 (encode whitespace at eol)
129 }
6fba102d 130
131 # rule #5 (lines must be shorter than 76 chars, but we are not allowed
132 # to break =XX escapes. This makes things complicated :-( )
133 my $brokenlines = "";
6a63fb82 134 $brokenlines .= "$1=$eol"
6fba102d 135 while $res =~ s/(.*?^[^\n]{73} (?:
136 [^=\n]{2} (?! [^=\n]{0,1} $) # 75 not followed by .?\n
137 |[^=\n] (?! [^=\n]{0,2} $) # 74 not followed by .?.?\n
138 | (?! [^=\n]{0,3} $) # 73 not followed by .?.?.?\n
139 ))//xsm;
140
141 "$brokenlines$res";
142}
143
144
6a63fb82 145sub old_decode_qp ($)
6fba102d 146{
147 my $res = shift;
6a63fb82 148 $res =~ s/\r\n/\n/g; # normalize newlines
149 $res =~ s/[ \t]+\n/\n/g; # rule #3 (trailing space must be deleted)
150 $res =~ s/=\n//g; # rule #5 (soft line breaks)
95635e5f 151 if (ord('A') == 193) { # EBCDIC style machine
152 if (ord('[') == 173) {
153 $res =~ s/=([\da-fA-F]{2})/Encode::encode('cp1047',Encode::decode('iso-8859-1',pack("C", hex($1))))/ge;
154 }
155 elsif (ord('[') == 187) {
156 $res =~ s/=([\da-fA-F]{2})/Encode::encode('posix-bc',Encode::decode('iso-8859-1',pack("C", hex($1))))/ge;
157 }
158 elsif (ord('[') == 186) {
159 $res =~ s/=([\da-fA-F]{2})/Encode::encode('cp37',Encode::decode('iso-8859-1',pack("C", hex($1))))/ge;
160 }
161 }
162 else { # ASCII style machine
163 $res =~ s/=([\da-fA-F]{2})/pack("C", hex($1))/ge;
164 }
6fba102d 165 $res;
166}
167
168# Set up aliases so that these functions also can be called as
169#
170# MIME::QuotedPrint::encode();
171# MIME::QuotedPrint::decode();
172
173*encode = \&encode_qp;
174*decode = \&decode_qp;
175
1761;