Commit Diff
Diff:
b580c2f17bea00c92c35a0e72d435b910379cbca
f3481d062eb9757f517e16c8fef8430a19c3a5bb
Commit:
f3481d062eb9757f517e16c8fef8430a19c3a5bb
Tree:
fac99f6b2f4d5292b3bdcc22de174c8a544a9824
Author:
Omar Polo <op@omarpolo.com>
Date:
Tue Sep 13 19:30:08 2022 UTC
Message:
don't rely on filter-export anymore

Instead, parse the output of `mshow -t' and extract, one by one, the
interesting parts. This allows to generate a better listing (we know
name and size!) and to decide how to call the files (the extension is
important for httpd!)
commit - b580c2f17bea00c92c35a0e72d435b910379cbca
commit + f3481d062eb9757f517e16c8fef8430a19c3a5bb
blob - 6b9c9f1df418f69a0e51538f76672171d03ab8c1
blob + d19290066cb6830ca48bb06011b3b311f94a599f
--- mexp
+++ mexp
@@ -30,6 +30,22 @@ my $tid;
# fattr for File::Temp
pledge("stdio rpath wpath cpath proc exec fattr") or die "pledge: $!";
+sub export_part {
+ my ($fh, $n, $fname) = @_;
+
+ my $pid = fork;
+ die "fork: $!" unless defined $pid;
+ if ($pid == 0) {
+ open \*STDOUT, '>&', $fh
+ or die "can't redirect stdout: $!";
+ exec 'mshow', '-F', '-O', $fname, $n
+ or die "can't exec mshow: $!";
+ }
+
+ waitpid $pid, 0;
+ die "mshow exited with $? ($n, $fname)" if $?;
+}
+
my $tid;
while (<>) {
my ($level, $fname, $mid, $date, $from, $subj) = parse;
@@ -38,16 +54,12 @@ while (<>) {
die "unknown tid" unless defined $tid;
my $dest = "$outdir/mail/$mid.html";
- next if -f $dest;
+ # next if -f $dest;
open(my $fh, '>', "$dest") or die "can't open $dest: $!";
initpage $fh, $subj;
- my ($pfh, $parts) = tempfile "/tmp/gotmark.parts.XXXXXXXXXX";
-
- $ENV{'PARTS_PATH'} = $parts;
- $ENV{'MESSAGE_ID'} = $mid;
open(my $mshow, "-|", "mshow", "-nNA", "text/plain", $fname)
or die "can't exec mshow: $!";
@@ -75,13 +87,50 @@ while (<>) {
print $fh "</pre>";
# generate the listing for the exported parts
+ open(my $parts, '-|', 'mshow', '-t', $fname)
+ or die "can't exec mshow: $!";
+
my $part_seen = 0;
- while (<$pfh>) {
+ while (<$parts>) {
+ my ($n, $mime, $size, $name) =
+ m/(\d+): ([^ ]+) size=(\d+) name="(.*)"/ or next;
+
+ next if $mime =~ m(application/application/pgp-signature);
+ next if $mime =~ m(audio/*);
+ next if $mime =~ m(video/*);
+
+ my $ext = "bin";
+ if ($mime =~ m(image/*)) {
+ if ($mime eq "image/gif") {
+ $ext = "gif";
+ } elsif ($mime eq "image/jpeg") {
+ $ext = "jpg";
+ } elsif ($mime eq "image/png") {
+ $ext = "png";
+ } else {
+ # skip other image types for now.
+ next;
+ }
+ }
+
+ # text/* is bundled in the body by mshow(1).
+
if (!$part_seen) {
$part_seen = 1;
say $fh "<ul class='parts'>";
}
- print $fh $_;
+
+ my ($p, $path) = tempfile "$outdir/parts/$mid.XXXXXXXXXX";
+ export_part($p, $n, $fname);
+ close($p);
+ rename $path, "$path.$ext"
+ or die "can' rename $path as $path.ext";
+ chmod 0644, "$path.$ext";
+
+ $path =~ s,^.*/parts/,/parts/,;
+
+ my $url = san("$path.$ext");
+ say $fh "<li><a href='$url'>$name ($size)</a></li>";
}
say $fh "</ul>" if $part_seen;
@@ -97,7 +146,7 @@ while (<>) {
close($text);
close($mshow);
- close($pfh);
+ close($parts);
close($fh);
unlink $parts;
Omar Polo