3 # Decoder: process one or more RFC822 messages containing MIME encoded
4 # files (as produced by encoder), into the constituant files.
6 # Written by Ewen McNeill, 19/11/1997.
8 # This program scans the supplied directory for files; each file is
9 # considered to be a message. If the message is in a suitable format
10 # then, the enclosed ZIP file will be extracted into a temporary file,
11 # and then decompressed into the received directory. Each file that
12 # is successfully processed is then moved into the processed directory.
14 #---------------------------------------------------------------------------
18 use Cwd
; # So we know where we are!
19 use DirHandle
; # Scanning directories
20 use Mail
::Header
; # Internet mail messages
21 use MIME
::Base64
; # MIME encoding.
24 require "recvconf.ph"; # Configuration of receive tools.
26 #---------------------------------------------------------------------------
30 # DecodeMessage -- expects to receive a filename
32 # The file is assumed to be in the incoming directory. It is treated as
33 # a RFC822 message, the headers read in, and scanned for suitable things.
35 # If it is suitable, then the enclosed file is extracted into the temporary
36 # directory, and the file is unzipped into the load directory.
38 # Returns 1 if message processed successfully; 0 otherwise.
43 die "No filename" if (! defined($filename));
45 #print "Processing: $filename\n";
47 if (! open(MSG
, "<$RecvConf::downloaded/$filename"))
49 warn "Unable to open \"$RecvConf::downloaded/$filename\" -- skipping\n";
53 my $message = new Mail
::Header
(\
*MSG
);
54 if (! defined($message))
56 warn "Unable to create new Internet Message Header object\n";
61 my $subject = $message->get('Subject');
62 my $mime = $message->get('MIME-Version');
63 my $content = $message->get('Content-Type');
64 my $encoding= $message->get('Content-Transfer-Encoding');
66 if (!defined($subject) || !defined($mime) || !defined($content) ||
69 warn "Required header fields missing from file ($filename) -- skipping\n";
74 if ($subject !~ /^Transfer of ".*"$/)
76 warn "Subject line invalid in file ($filename) -- skipping\n";
82 warn "Unexpected MIME version in file ($filename) -- skipping\n";
86 if ($content !~ /^application\/x-zip
-compressed
; name
="\S+\.zip"$/)
88 warn "Unexpected Content-Type in file ($filename) -- skipping\n";
89 warn "Content: $content\n";
93 if ($encoding !~ /^base64$/)
95 warn "Unexpected encoding in file ($filename) -- skipping\n";
100 # Okay, looks like our message. The rest of it should be a base64
101 # encoded file, so we'll pull that into an scalar, and decode it.
103 my $base64len = -s
"$RecvConf::downloaded/$filename";
105 read MSG
, $base64text, $base64len;
106 my $rawtext = decode_base64
($base64text);
110 if (!defined($rawtext) || !defined($base64text))
112 warn "Error decoding file from message in file ($filename) -- skipping\n";
116 # Now we'd better save that somewhere. We used a fixed filename because
117 # (a) it makes us less vulnerable to attacks from outside, and (b) it
118 # makes life easier for decoding, and (c) it ensures the old ones go
121 if (! open(ZIP
, ">$RecvConf::tempdir/received.zip"))
123 warn "Unable to open temporary file: $RecvConf::tempdir/received.zip\n";
127 # Switch it into binary mode -- important since we're about to write
128 # binary data out to it!
131 if (! print ZIP
$rawtext)
133 warn "Unable to write data out to temporary file. Abandoning file.\n";
135 unlink("$RecvConf::tempdir/received.zip") ||
136 warn "Stray temporary file remains -- unable to remove\n";
142 warn "Unable to close temporary zip file. Abandoning.\n";
143 unlink("$RecvConf::tempdir/received.zip") ||
144 warn "Stray temporary file remains -- unable to remove\n";
148 # We've got it in a temporary file, now we need to extract the file out
149 # of the zip, and into the destination directory. We get the zip program
150 # to do most of this hard work, and assume it worked unless the zip program
153 # WARNING: Do NOT extract directories. Make certain they are junked, not
154 # only to ensure the files end up where we want them, but to reduce the
157 # NOTE: we use the overwrite flag to avoid things hanging on files existing
158 # and to get the (hopefully) latest copy in the directory.
160 # WARNING: pkunzip doesn't appear to have a way to fix the output directory
161 # somewhere other than "current directory"; and it is not possible to
162 # reliably change directories then give a full path to the ZIP 'cause
163 # chances are on a Windows system it'll have spaces in it.
165 # Thus: Infozip 5.1 or greater is required.
167 # Note: remove -q if you want to see zip at work.
169 my $zipfile = "$RecvConf::tempdir/received.zip";
171 my $rc = system("unzip -o -j -q $zipfile -d $RecvConf::recvdir");
173 unlink("$RecvConf::tempdir/received.zip") ||
174 warn "Unable to remove temporary file -- stray remains\n";
178 warn "Unzip failed. Abandoning file ($filename)\n";
182 { # Unzipped successfully, move file into processed directory
183 unlink("$RecvConf::downloadprocessed/$filename") &&
184 warn "Removed old copy of \"$RecvConf::downloadprocessed/$filename\"\n";
185 rename("$RecvConf::downloaded/$filename",
186 "$RecvConf::downloadprocessed/$filename") ||
187 warn "Unable to rename \"$filename\" into processed directory\n";
194 #---------------------------------------------------------------------------
198 die "No download directory" if (! defined($RecvConf::downloaded
));
199 die "No processed directory" if (! defined($RecvConf::downloadprocessed
));
200 die "No received directory" if (! defined($RecvConf::recvdir
));
201 die "No temporary directory" if (! defined($RecvConf::tempdir
));
203 my $numprocessed = 0;
204 my $dir = new DirHandle
$RecvConf::downloaded
;
207 #print "Scanning directory: ", $RecvConf::downloaded, "\n";
209 while (defined($file = $dir->read))
211 if (-f
"$RecvConf::downloaded/$file")
212 { if (decodemessage
($file))
219 warn "Unable to read from directory: ", $RecvConf::downloaded
, "\n";
220 print "0 files processed.\n";
224 if ($numprocessed != 1)
225 { print "$numprocessed files processsed.\n"; }
227 { print "1 file processed.\n"; }