/[suikacvs]/messaging/manakai/lib/Message/MIME/Encoding.pm
Suika

Contents of /messaging/manakai/lib/Message/MIME/Encoding.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.9 - (show annotations) (download)
Sat Jul 27 04:44:25 2002 UTC (22 years, 4 months ago) by wakaba
Branch: MAIN
CVS Tags: before-dis2-200411, manakai-release-0-3-2, manakai-release-0-3-1, manakai-release-0-4-0, manakai-200612, msg-0-1, HEAD
Branch point for: branch-suikawiki-1, experimental-xml-parser-200401, stable
Changes since 1.8: +24 -27 lines
2002-07-26  Wakaba <w@suika.fam.cx>

	* Entity.pm:
	- (fill_missing_fields): New option.
	- (fill_source, fill_destination): New options.
	- (hook_stringify_fill_fields): Option removed.
	* Header.pm:
	- (_header_cmp): Removed.
	- (@header_order, %header_order): Removed.
	- (_scan_sort): Use Message::Header::* namespace packages to sort.

1
2 =head1 NAME
3
4 Message::MIME::Encoding --- Encoding (MIME CTE, HTTP encodings, etc) definitions
5
6 =cut
7
8 package Message::MIME::Encoding;
9 use strict;
10 use vars qw($VERSION);
11 $VERSION=do{my @r=(q$Revision: 1.8 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
12
13 our %ENCODER = (
14 '7bit' => sub { ($_[1], decide_coderange (@_)) },
15 '8bit' => sub { ($_[1], decide_coderange (@_)) },
16 binary => sub { ($_[1], decide_coderange (@_)) },
17 base64 => \&encode_base64,
18 'quoted-printable' => \&encode_qp,
19 'x-gzip64' => sub {
20 if (eval {require Compress::Zlib}) {
21 ((encode_base64 (Compress::Zlib::memGzip ($_[1])))[0], 'x-gzip64');
22 } else {
23 Carp::carp "gzip64 encode: $@";
24 ($_[1], 'binary');
25 }
26 },
27 'x-uu' => \&uuencode,
28 'x-uue' => \&uuencode,
29 'x-uuencode' => \&uuencode,
30 'x-uuencoded' => \&uuencode,
31 );
32 our %DECODER = (
33 '7bit' => sub { ($_[1], 'binary') },
34 '8bit' => sub { ($_[1], 'binary') },
35 binary => sub { ($_[1], 'binary') },
36 base64 => \&decode_base64,
37 'quoted-printable' => \&decode_qp,
38 'x-gzip64' => sub {
39 my ($t, $e) = uncompress_gzip ($_[0], (decode_base64 ($_[0], $_[1]))[0]);
40 if ($e eq 'identity') { return ($t, 'binary') }
41 else { return ($_[1], 'x-gzip64') }
42 },
43 'x-uu' => \&uudecode,
44 'x-uue' => \&uudecode,
45 'x-uuencode' => \&uudecode,
46 'x-uuencoded' => \&uudecode,
47 );
48
49 sub decide_coderange ($$\%) {
50 my $yourself = shift;
51 my $s = shift;
52 my $option = shift;
53 if (!defined $option->{mt_is_text}) {
54 my $mt; $mt = ($yourself->content_type)[0] if ref $yourself;
55 $option->{mt_is_text} = 1
56 if $mt eq 'text' || $mt eq 'multipart' || $mt eq 'message';
57 }
58 if (!defined $option->{linebreak_strict}) {
59 $option->{linebreak_strict} = $yourself->{option}->{linebreak_strict};
60 }
61 return 'binary' if $s =~ /\x00/;
62 if ($option->{mt_is_text}) {
63 if ($option->{linebreak_strict}) {
64 return 'binary' if $s =~ /\x0D(?!\x0A)/s;
65 return 'binary' if $s =~ /(?<!\x0D)\x0A/s;
66 }
67 } else {
68 return 'binary';
69 #return 'binary' if $s =~ /\x0D|\x0A/s;
70 ## RFC 2045: nor is labelling unencoded non-line-oriented data as
71 ## anything other than "binary" allowed.
72 }
73 return 'binary' if $s =~ /[^\x0D\x0A]{999}/;
74 return '8bit' if $s =~ /[\x80-\xFF]/;
75 '7bit';
76 }
77
78 ## Original: MIME::QuotedPrint Revision: 2.3 1997/12/02 10:24:27
79 ## by Gisle Aas
80 sub encode_qp ($$) {
81 my $yourself = shift;
82 my $s = shift;
83 my $nl = "\x0D\x0A";
84 my $enl = "=0D=0A";
85 unless ($yourself->{option}->{linebreak_strict}) {
86 $nl = Message::Util::decide_newline ($s);
87 $enl = $nl; $enl =~ s/\x0D/=0D/s; $enl =~ s/\x0A/=0A/s;
88 }
89 my $mt_is_text = 0;
90 my $mt; $mt = ($yourself->content_type)[0] if ref $yourself;
91 $mt_is_text = 1 if $mt eq 'text' || $mt eq 'multipart' || $mt eq 'message';
92 ## RFC 2045 [^\x09\x20\x21-\x3C\x3E-\x7E]
93 ## - RFC 2049 "mail-safe" [^\x09\x20\x25-\x3C\x3E\x3F\x41-\x5A\x5F\x61-\x7A]
94 $s =~ s/([^\x09\x20\x25-\x3C\x3E\x3F\x41-\x5A\x5F\x61-\x7A])/sprintf('=%02X', ord($1))/eg; # rule #2,#3
95 if ($mt_is_text) {
96 $s =~ s/([\x09\x20])(?=$enl|$)/
97 sprintf '=%02X', ord($1)
98 #join('', map { sprintf('=%02X', ord($_)) } split('', $1) )
99 /egm; # rule #3 (encode whitespace at eol)
100 $s =~ s/${enl}From/$nl=46rom/g;
101 $s =~ s/${enl}-/$nl=2D/g;
102 $s =~ s/$enl/$nl/g;
103 } else {
104 $s =~ s/([\x09\x20])$/
105 sprintf '=%02X', ord($1)
106 #join('', map { sprintf('=%02X', ord($_)) } split('', $1) )
107 /egm; # rule #3 (encode whitespace at eol)
108 }
109
110 # rule #5 (lines must be shorter than 76 chars, but we are not allowed
111 # to break =XX escapes. This makes things complicated :-( )
112 my $brokenlines = "";
113 $brokenlines .= $1.'='.$nl
114 while $s =~ s/(.*?^[^$nl]{73} (?:
115 [^=$nl]{2} (?! [^=$nl]{0,1} $) # 75 not followed by .?\n
116 |[^=$nl] (?! [^=$nl]{0,2} $) # 74 not followed by .?.?\n
117 | (?! [^=$nl]{0,3} $) # 73 not followed by .?.?.?\n
118 ))//xsm;
119 ($brokenlines.$s, 'quoted-printable');
120 }
121
122
123 ## Original: MIME::QuotedPrint Revision: 2.3 1997/12/02 10:24:27
124 ## by Gisle Aas
125 sub decode_qp ($$) {
126 my $yourself = shift;
127 my $s = shift;
128 $s =~ s/[\x09\x20]+(\x0D?\x0A)/$1/g; # rule #3 (trailing space must be deleted)
129 $s =~ s/[\x09\x20]+$//g;
130 $s =~ s/=\x0D?\x0A//g; # rule #5 (soft line breaks)
131 $s =~ s/=([0-9A-Fa-f][0-9A-Fa-f])/pack('C', hex($1))/ge;
132 ## Strictly, smallcases are not allowed
133 ($s, 'binary');
134 }
135
136 sub encode_base64 ($$;%) {
137 require MIME::Base64;
138 my ($yourself, $s, %option) = @_;
139 $s = MIME::Base64::encode ($s);
140 $s =~ s/\x0D(?!\x0A)/\x0D\x0A/gs;
141 $s =~ s/(?<!\x0D)\x0A/\x0D\x0A/gs;
142 ($s, 'base64');
143 }
144
145 sub decode_base64 ($$;%) {
146 require MIME::Base64;
147 my ($yourself, $s, %option) = @_;
148 $s = MIME::Base64::decode ($s);
149 ($s, 'binary');
150 }
151
152 sub uuencode ($$;%) {
153 my $yourself = shift;
154 my $s = shift; my %p = @_;
155 my %option = (mode => 644, ## mode as (if:-)) decimal number
156 filename => '', preamble => '', postamble => '',
157 newline => "\x0D\x0A");
158 for (grep {/^-/} keys %p) {$option{substr ($_, 1)} = $p{$_}}
159
160 my $r = '';
161 if (length $option{preamble}) {
162 $option{preamble} .= $option{newline}
163 unless $option{preamble} =~ /$option{newline}$/s;
164 $r .= $option{preamble} . $option{newline};
165 }
166 $option{filename} = 'encoded-data' unless length $option{filename};
167 $r .= sprintf 'begin %03d %s%s', @option{'mode', 'filename', 'newline'};
168 my $u = pack 'u', $s;
169 $u =~ s/\x0D?\x0A/$option{newline}/g;
170 $r .= $u;
171 $r .= 'end' . $option{newline};
172 if (length $option{postamble}) {
173 $option{postamble} .= $option{newline}
174 unless $option{postamble} =~ /$option{newline}$/s;
175 $r .= $option{newline} . $option{postamble};
176 }
177 ($r, 'x-uuencode');
178 }
179
180 sub uudecode ($$) {
181 my $yourself = shift;
182 my $s = shift;
183 my @s = split /\x0D?\x0A/, $s;
184
185 ## Taken from MIME::Decoder::UU by Eryq (<eryq@zeegee.com>),
186 ## Revision: 5.403 / Date: 2000/11/04 19:54:49
187 my ($mode, $filename, @preamble) = (0, '');
188 while (defined ($_ = shift (@s))) {
189 if (/^begin(.*)/) { ### found it: now decode it...
190 my $modefile = $1;
191 if ($modefile =~ /^(?:\s+(\d+))?(?:\s+(.*?\S))?\s*\Z/) {
192 ($mode, $filename) = ($1, $2);
193 }
194 last; ### decoded or not, we're done
195 }
196 push @preamble, $_;
197 }
198 if (!defined ($_)) { # hit eof!
199 Carp::carp "uu decode: No begin found";
200 return ($s, 'x-uuencode');
201 }
202
203 ### Decode:
204 my $r = '';
205 while (defined ($_ = shift (@s))) {
206 last if /^end/;
207 next if /[a-z]/;
208 next unless int((((ord() - 32) & 077) + 2) / 3) == int(length() / 4);
209 $r .= (unpack('u', $_));
210 }
211 return ($r, 'binary', -filename => $filename, -mode => $mode,
212 -preamble => join ("\x0D\x0A", @preamble),
213 -postamble => join ("\x0D\x0A", @s));
214 }
215
216 sub uncompress_gzip ($$) {
217 my $yourself = shift;
218 my ($s) = @_;
219 if (eval {require Compress::Zlib}) {
220 ## Taken from Namazu <http://www.namazu.org/>, filter/gzip.pl
221 my $flags = unpack('C', substr($s, 3, 1));
222 $s = substr($s, 10);
223 $s = substr($s, 2) if ($flags & 0x04);
224 $s =~ s/^[^\0]*\0// if ($flags & 0x08);
225 $s =~ s/^[^\0]*\0// if ($flags & 0x10);
226 $s = substr($s, 2) if ($flags & 0x02);
227
228 my $zl = Compress::Zlib::inflateInit
229 (-WindowBits => - Compress::Zlib::MAX_WBITS());
230 my ($inf, $stat) = $zl->inflate ($s);
231 if ($stat == Compress::Zlib::Z_OK() || $stat == Compress::Zlib::Z_STREAM_END()) {
232 return ($inf, 'identity');
233 } else {
234 Carp::carp 'uncompress_gzip: Bad compressed data';
235 }
236 } else {
237 Carp::carp "gzip64 decode: $@";
238 }
239 ($_[1], 'gzip'); ## failue
240 }
241
242 =head1 SEE ALSO
243
244 For charset ENCODINGs, see Message::MIME::Charset.
245
246 =head1 LICENSE
247
248 Copyright 2002 wakaba E<lt>w@suika.fam.cxE<gt>.
249
250 This program is free software; you can redistribute it and/or modify
251 it under the terms of the GNU General Public License as published by
252 the Free Software Foundation; either version 2 of the License, or
253 (at your option) any later version.
254
255 This program is distributed in the hope that it will be useful,
256 but WITHOUT ANY WARRANTY; without even the implied warranty of
257 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
258 GNU General Public License for more details.
259
260 You should have received a copy of the GNU General Public License
261 along with this program; see the file COPYING. If not, write to
262 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
263 Boston, MA 02111-1307, USA.
264
265 =head1 CHANGE
266
267 See F<ChangeLog>.
268 $Date: 2002/07/20 03:11:47 $
269
270 =cut
271
272 1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24