Update for ext/MIME/Base64/
[p5sagit/p5-mst-13.2.git] / ext / MIME / Base64 / QuotedPrint.pm
CommitLineData
6fba102d 1#
b9e0df4c 2# $Id: QuotedPrint.pm,v 2.4 2002/12/28 05:50:05 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
34This function will return an encoded version of the string given as
35argument.
36
37Note that encode_qp() does not change newlines C<"\n"> to the CRLF
38sequence even though this might be considered the right thing to do
39(RFC 2045 (Q-P Rule #4)).
40
41=item decode_qp($str);
42
43This function will return the plain text version of the string given
44as argument.
45
46=back
47
48
49If you prefer not to import these routines into your namespace you can
50call them as:
51
52 use MIME::QuotedPrint ();
53 $encoded = MIME::QuotedPrint::encode($decoded);
54 $decoded = MIME::QuotedPrint::decode($encoded);
55
56=head1 COPYRIGHT
57
58Copyright 1995-1997 Gisle Aas.
59
60This library is free software; you can redistribute it and/or
61modify it under the same terms as Perl itself.
62
63=cut
64
65use strict;
66use vars qw(@ISA @EXPORT $VERSION);
95635e5f 67if (ord('A') == 193) { # on EBCDIC machines we need translation help
46891979 68 require Encode;
95635e5f 69}
6fba102d 70
71require Exporter;
72@ISA = qw(Exporter);
73@EXPORT = qw(encode_qp decode_qp);
74
b1387238 75use Carp qw(croak);
76
b9e0df4c 77$VERSION = sprintf("%d.%02d", q$Revision: 2.4 $ =~ /(\d+)\.(\d+)/);
6fba102d 78
6fba102d 79sub encode_qp ($)
80{
81 my $res = shift;
b9e0df4c 82 if ($] >= 5.006) {
83 require bytes;
84 if (bytes::length($res) > length($res) ||
85 ($] >= 5.008 && $res =~ /[^\0-\xFF]/)) {
86 croak("The Quoted-Printable encoding is only defined for bytes");
87 }
88 }
b1387238 89
95635e5f 90 # Do not mention ranges such as $res =~ s/([^ \t\n!-<>-~])/sprintf("=%02X", ord($1))/eg;
91 # since that will not even compile on an EBCDIC machine (where ord('!') > ord('<')).
92 if (ord('A') == 193) { # EBCDIC style machine
93 if (ord('[') == 173) {
94 $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
95 $res =~ s/([ \t]+)$/
96 join('', map { sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('cp1047',$_)))) }
97 split('', $1)
98 )/egm; # rule #3 (encode whitespace at eol)
99 }
100 elsif (ord('[') == 187) {
101 $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
102 $res =~ s/([ \t]+)$/
103 join('', map { sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('posix-bc',$_)))) }
104 split('', $1)
105 )/egm; # rule #3 (encode whitespace at eol)
106 }
107 elsif (ord('[') == 186) {
108 $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
109 $res =~ s/([ \t]+)$/
110 join('', map { sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('cp37',$_)))) }
111 split('', $1)
112 )/egm; # rule #3 (encode whitespace at eol)
113 }
114 }
115 else { # ASCII style machine
116 $res =~ s/([^ \t\n!"#\$%&'()*+,\-.\/0-9:;<>?\@A-Z[\\\]^_`a-z{|}~])/sprintf("=%02X", ord($1))/eg; # rule #2,#3
117 $res =~ s/([ \t]+)$/
118 join('', map { sprintf("=%02X", ord($_)) }
119 split('', $1)
120 )/egm; # rule #3 (encode whitespace at eol)
121 }
6fba102d 122
123 # rule #5 (lines must be shorter than 76 chars, but we are not allowed
124 # to break =XX escapes. This makes things complicated :-( )
125 my $brokenlines = "";
126 $brokenlines .= "$1=\n"
127 while $res =~ s/(.*?^[^\n]{73} (?:
128 [^=\n]{2} (?! [^=\n]{0,1} $) # 75 not followed by .?\n
129 |[^=\n] (?! [^=\n]{0,2} $) # 74 not followed by .?.?\n
130 | (?! [^=\n]{0,3} $) # 73 not followed by .?.?.?\n
131 ))//xsm;
132
133 "$brokenlines$res";
134}
135
136
137sub decode_qp ($)
138{
139 my $res = shift;
140 $res =~ s/[ \t]+?(\r?\n)/$1/g; # rule #3 (trailing space must be deleted)
141 $res =~ s/=\r?\n//g; # rule #5 (soft line breaks)
95635e5f 142 if (ord('A') == 193) { # EBCDIC style machine
143 if (ord('[') == 173) {
144 $res =~ s/=([\da-fA-F]{2})/Encode::encode('cp1047',Encode::decode('iso-8859-1',pack("C", hex($1))))/ge;
145 }
146 elsif (ord('[') == 187) {
147 $res =~ s/=([\da-fA-F]{2})/Encode::encode('posix-bc',Encode::decode('iso-8859-1',pack("C", hex($1))))/ge;
148 }
149 elsif (ord('[') == 186) {
150 $res =~ s/=([\da-fA-F]{2})/Encode::encode('cp37',Encode::decode('iso-8859-1',pack("C", hex($1))))/ge;
151 }
152 }
153 else { # ASCII style machine
154 $res =~ s/=([\da-fA-F]{2})/pack("C", hex($1))/ge;
155 }
6fba102d 156 $res;
157}
158
159# Set up aliases so that these functions also can be called as
160#
161# MIME::QuotedPrint::encode();
162# MIME::QuotedPrint::decode();
163
164*encode = \&encode_qp;
165*decode = \&decode_qp;
166
1671;