0: #!/usr/bin/perl -w
1: ##############################################################################
2: ## -*-perl-*-
3: ##
4: ## ydecode - A better, faster yEnc decoder.
5: ##
6: ## REVISION HISTORY
7: ##
8: ## 1.0 2002/02/27 Initial release.
9: ## 1.1 2002/03/02 Fixed miscellaneous translation bugs.
10: ## 1.2 2002/03/12 Code around utf8 badness by working at the byte level.
11: ## 1.3 2002/11/05 Precompute mapping for a slight speedup (robobunny).
12: ##############################################################################
13:
14: package Convert::yEnc;
15:
16: use strict;
17: use String::CRC32;
18: use Exporter;
19: use vars qw(@ISA @EXPORT_OK);
20: @ISA = qw(Exporter);
21: @EXPORT_OK = qw(decode);
22:
23: sub decode($)
24: {
25: my $fh = shift;
26:
27: my $size;
28: my $name;
29: my $part;
30: my $offset;
31: my $pSize;
32: my $decoded;
33: my @ymap = map { ($_-42+256)%256 } (0..255);
34:
35: my $decoding = 0;
36: binmode($fh);
37: while(<$fh>) {
38: chomp;
39: if (!$decoding) {
40: if (/^=ybegin/) {
41: if (/ size=(\d+)/) {
42: $size = $1;
43: }
44: else {
45: die "size field in ybegin is mandatory.\n";
46: }
47:
48: if (/ part=(\d+)/) {
49: $part = $1;
50: }
51: else {
52: undef $part;
53: }
54:
55: if (/ name=(.*)$/) {
56: $name = $1;
57: $name =~ s/\s+$//g;
58: print "Found attachment $name of size $size.\n";
59: }
60: else {
61: die "name field in ybegin is mandatory.\n";
62: }
63:
64: if (defined $part) {
65: my $line = <$fh>;
66: chomp $line;
67: $line =~ s/\s+$//g;
68: if ($line =~ /^=ypart/) {
69: if ($line =~ / begin=(\d+)/) {
70: $offset = $1 - 1;
71: }
72: else {
73: print "Part $part has no begin field - ignoring.\n";
74: undef $part;
75: }
76: if ($line =~ / end=(\d+)/) {
77: $pSize = $1 - $offset;
78: }
79: else {
80: print "Part $part has no end field - ignoring.\n";
81: undef $part;
82: }
83: print "File $name is multipart.\n" if ($part == 1);
84: print "Processing part $part.\n";
85: }
86: else {
87: print "ybegin with part= field not followed"
88: ." by ypart=. Treating as a single part.\n";
89: undef $part;
90: }
91: }
92:
93: undef $decoded;
94: $decoding = 1 if (defined $size);
95: }
96: }
97: else {
98: if (/^=yend/) {
99: $decoding = 0;
100:
101: my $endSize;
102: if (/size=(\d+)/) {
103: $endSize = $1;
104: }
105: else {
106: print "Size is mandatory in yend, ignoring encoded stuff.\n";
107: next;
108: }
109:
110: my $crc;
111: if (defined $part) {
112: if (/ pcrc32=([0-9a-f]+)/i) {
113: $crc = $1;
114: }
115: }
116: else {
117: if (/ crc32=([0-9a-f]+)/i) {
118: $crc = $1;
119: }
120: }
121:
122: if (defined $crc) {
123: my $realCRC = crc32($decoded);
124: if (hex($crc) != $realCRC) {
125: print "CRCs mismatch. Expected ", $crc;
126: print " got ", sprintf("%x", $realCRC), ".\n";
127: next;
128: }
129: }
130:
131: my $decodedSize = length($decoded);
132: if (defined $part) {
133: if ($decodedSize != $pSize) {
134: die "Size mismatch. Expected $pSize, got $decodedSize.\n";
135: }
136:
137: print "Writing part $part to $name...";
138: if ($part == 1) {
139: open(FH,"> $name") or die "Can't write to file $name\n";
140: }
141: else {
142: open(FH,"+< $name") or die "Can't append to $name\n";
143: }
144: binmode(FH);
145: seek(FH, $offset, 0);
146: print FH $decoded;
147: close(FH);
148: print "done.\n";
149: }
150: else {
151: if ($endSize != $size) {
152: die "begin/end size mismatch. Expected $size, got $endSize.\n";
153: }
154: if ($decodedSize != $endSize) {
155: die "Size mismatch. Expected $endSize, got $decodedSize.\n";
156: }
157:
158: print "Writing $name...";
159: open(FH, "> $name") or die "Can't write to file $name\n";
160: binmode(FH);
161: print FH $decoded;
162: close(FH);
163: print "done.\n";
164: }
165: }
166: else {
167: my $line = $_;
168:
169: # Remove extraneous trailing 0x0d's, if possible.
170: $line =~ s/\x0d$//;
171:
172: # Work with bytes, to protect against utf8 hardship.
173: my @bytes = unpack("C*", $line);
174: my @uline;
175: foreach (my $i=0; $i<scalar(@bytes); $i++) {
176: if ($bytes[$i] == ord('=')) {
177: $i++;
178: $bytes[$i] -= 64;
179: }
180: push @uline, $ymap[$bytes[$i]];
181: }
182: $decoded .= pack("C*", @uline);
183: }
184: }
185: }
186: }
187:
188: 1;
189:
190: package main;
191:
192: use strict;
193: use Getopt::Std;
194:
195: my %opt;
196:
197: my $error = !getopts('w', \%opt);
198: if ($error) {
199: print << "EOU";
200:
201: Usage: ydecode [-w] < file
202:
203: where
204: -w Print out warranty information
205:
206: EOU
207: }
208: elsif ($opt{'w'}) {
209: print << "EOW";
210: ------------------------------------------------------------------------------
211: BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
212: FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
213: OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
214: PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
215: OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
216: MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
217: TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
218: PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
219: REPAIR OR CORRECTION.
220:
221: IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
222: WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
223: REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
224: INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
225: OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
226: TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
227: YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
228: PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
229: POSSIBILITY OF SUCH DAMAGES.
230: EOW
231: }
232: else {
233: Convert::yEnc::decode(\*STDIN);
234: }
235:
236: __END__
237: =pod
238:
239: =head1 NAME
240:
241: ydecode - A better, faster yEnc decoder.
242:
243: =head1 SYNOPSIS
244:
245: ydecode [-w] < file
246: -w Print out warranty information
247:
248: =head1 DESCRIPTION
249:
250: C<ydecode> decodes yEnc data from the standard input and
251: writes out the embedded file(s) to the current working directory.
252:
253: =head1 EXAMPLES
254:
255: ydecode < file
256:
257: cat 00000005.ntx | ydecode
258:
259:
260: =head1 INSTALLATION
261:
262: You will need the following module(s), if you don't already have them:
263:
264: String::CRC32
265:
266: Getopt::Std
267:
268: =head1 AUTHOR
269:
270: Gerard Lanois <gerard@lanois.com>
271:
272: Courtesy of Gerard's Perl Page, http://home.san.rr.com/lanois/perl/
273:
274: =head1 CREDITS
275:
276: This is based on yencdecoder.pl, yenc format decoder - v1.0 - 20020224
277: by Hellstorm a.k.a. Jaume Bacardit Peñarroya) - <helly@he11storm.net>
278:
279: =head1 LICENSE
280:
281: ydecode - Copyright (C) 2002 Gerard Lanois <gerard@lanois.com>
282:
283: This program is free software; you can redistribute it and/or modify
284: it under the terms of the GNU General Public License as published by
285: the Free Software Foundation; either version 2 of the License, or
286: (at your option) any later version.
287:
288: This program is distributed in the hope that it will be useful,
289: but WITHOUT ANY WARRANTY; without even the implied warranty of
290: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
291: GNU General Public License for more details.
292:
293: You should have received a copy of the GNU General Public License
294: along with this program; if not, write to the Free Software
295: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
296:
297: =cut
298:
In reply to ydecode - A better, faster yEnc decoder. by perldoc
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |