File Coverage

blib/lib/MIME/QuotedPrint/Perl.pm
Criterion Covered Total %
statement 34 34 100.0
branch 9 10 90.0
condition 3 6 50.0
subroutine 4 4 100.0
pod 2 2 100.0
total 52 56 92.8


line stmt bran cond sub pod time code
1              
2             package MIME::QuotedPrint::Perl;
3              
4             # $Id: Perl.pm,v 1.2 2004/01/14 12:52:44 gisle Exp $
5              
6 2     2   1039 use strict;
  2         4  
  2         66  
7 2     2   9 use vars qw(@ISA @EXPORT $VERSION);
  2         3  
  2         2787  
8             if (ord('A') == 193) { # on EBCDIC machines we need translation help
9             require Encode;
10             }
11              
12             require Exporter;
13             @ISA = qw(Exporter);
14             @EXPORT = qw(encode_qp decode_qp);
15              
16             $VERSION = "1.00";
17              
18             my $RE_Z = "\\z";
19             $RE_Z = "\$" if $] < 5.005;
20              
21             sub encode_qp ($;$)
22             {
23 41     41 1 577 my $res = shift;
24 41 50       97 if ($] >= 5.006) {
25 41         172 require bytes;
26 41 100 33     98 if (bytes::length($res) > length($res) ||
      66        
27             ($] >= 5.008 && $res =~ /[^\0-\xFF]/))
28             {
29 2         26 require Carp;
30 2         467 Carp::croak("The Quoted-Printable encoding is only defined for bytes");
31             }
32             }
33              
34 39         1805 my $eol = shift;
35 39 100       83 $eol = "\n" unless defined $eol;
36              
37             # Do not mention ranges such as $res =~ s/([^ \t\n!-<>-~])/sprintf("=%02X", ord($1))/eg;
38             # since that will not even compile on an EBCDIC machine (where ord('!') > ord('<')).
39 39         36 if (ord('A') == 193) { # EBCDIC style machine
40             if (ord('[') == 173) {
41             $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
42             $res =~ s/([ \t]+)$/
43             join('', map { sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('cp1047',$_)))) }
44             split('', $1)
45             )/egm; # rule #3 (encode whitespace at eol)
46             }
47             elsif (ord('[') == 187) {
48             $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
49             $res =~ s/([ \t]+)$/
50             join('', map { sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('posix-bc',$_)))) }
51             split('', $1)
52             )/egm; # rule #3 (encode whitespace at eol)
53             }
54             elsif (ord('[') == 186) {
55             $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
56             $res =~ s/([ \t]+)$/
57             join('', map { sprintf("=%02X", ord(Encode::encode('iso-8859-1',Encode::decode('cp37',$_)))) }
58             split('', $1)
59             )/egm; # rule #3 (encode whitespace at eol)
60             }
61             }
62             else { # ASCII style machine
63 39         131 $res =~ s/([^ \t\n!"#\$%&'()*+,\-.\/0-9:;<>?\@A-Z[\\\]^_`a-z{|}~])/sprintf("=%02X", ord($1))/eg; # rule #2,#3
  31         121  
64 39 100       83 $res =~ s/\n/=0A/g unless length($eol);
65 39         116 $res =~ s/([ \t]+)$/
66 7         22 join('', map { sprintf("=%02X", ord($_)) }
  16         55  
67             split('', $1)
68             )/egm; # rule #3 (encode whitespace at eol)
69             }
70              
71 39 100       77 return $res unless length($eol);
72              
73             # rule #5 (lines must be shorter than 76 chars, but we are not allowed
74             # to break =XX escapes. This makes things complicated :-( )
75 38         42 my $brokenlines = "";
76 38         287 $brokenlines .= "$1=$eol"
77             while $res =~ s/(.*?^[^\n]{73} (?:
78             [^=\n]{2} (?! [^=\n]{0,1} $) # 75 not followed by .?\n
79             |[^=\n] (?! [^=\n]{0,2} $) # 74 not followed by .?.?\n
80             | (?! [^=\n]{0,3} $) # 73 not followed by .?.?.?\n
81             ))//xsm;
82 38         112 $res =~ s/\n$RE_Z/$eol/o;
83              
84 38         128 "$brokenlines$res";
85             }
86              
87              
88             sub decode_qp ($)
89             {
90 46     46 1 215 my $res = shift;
91 46         60 $res =~ s/\r\n/\n/g; # normalize newlines
92 46         117 $res =~ s/[ \t]+\n/\n/g; # rule #3 (trailing space must be deleted)
93 46         91 $res =~ s/=\n//g; # rule #5 (soft line breaks)
94 46         43 if (ord('A') == 193) { # EBCDIC style machine
95             if (ord('[') == 173) {
96             $res =~ s/=([\da-fA-F]{2})/Encode::encode('cp1047',Encode::decode('iso-8859-1',pack("C", hex($1))))/ge;
97             }
98             elsif (ord('[') == 187) {
99             $res =~ s/=([\da-fA-F]{2})/Encode::encode('posix-bc',Encode::decode('iso-8859-1',pack("C", hex($1))))/ge;
100             }
101             elsif (ord('[') == 186) {
102             $res =~ s/=([\da-fA-F]{2})/Encode::encode('cp37',Encode::decode('iso-8859-1',pack("C", hex($1))))/ge;
103             }
104             }
105             else { # ASCII style machine
106 46         119 $res =~ s/=([\da-fA-F]{2})/pack("C", hex($1))/ge;
  49         166  
107             }
108 46         118 $res;
109             }
110              
111             1;
112              
113             __END__