X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FWwwAttach.pm;h=f795618ebcfce92dabba15eb1f6bc323a0bbac91;hb=95bdac7f09c69036efed537a4d03d5bdd2ae4eb6;hp=33bfce27eb915ba220da5505ea64f76dce11c563;hpb=4b313dc74bc9bb84a542b7ec920cdb92879e7523;p=public-inbox.git diff --git a/lib/PublicInbox/WwwAttach.pm b/lib/PublicInbox/WwwAttach.pm index 33bfce27..f795618e 100644 --- a/lib/PublicInbox/WwwAttach.pm +++ b/lib/PublicInbox/WwwAttach.pm @@ -1,43 +1,48 @@ -# Copyright (C) 2016 all contributors +# Copyright (C) 2016-2020 all contributors # License: AGPL-3.0+ # For retrieving attachments from messages in the WWW interface package PublicInbox::WwwAttach; # internal package use strict; use warnings; -use Email::MIME; +use bytes (); # only for bytes::length use Email::MIME::ContentType qw(parse_content_type); -$Email::MIME::ContentType::STRICT_PARAMS = 0; +use PublicInbox::MIME; use PublicInbox::MsgIter; +sub get_attach_i { # msg_iter callback + my ($part, $depth, @idx) = @{$_[0]}; + my $res = $_[1]; + return if join('.', @idx) ne $res->[3]; # $idx + $res->[0] = 200; + my $ct = $part->content_type; + $ct = parse_content_type($ct) if $ct; + + # discrete == type, we remain Debian wheezy-compatible + if ($ct && (($ct->{discrete} || '') eq 'text')) { + # display all text as text/plain: + my $cset = $ct->{attributes}->{charset}; + if ($cset && ($cset =~ /\A[a-zA-Z0-9_\-]+\z/)) { + $res->[1]->[1] .= qq(; charset=$cset); + } + } else { # TODO: allow user to configure safe types + $res->[1]->[1] = 'application/octet-stream'; + } + $part = $part->body; + push @{$res->[1]}, 'Content-Length', bytes::length($part); + $res->[2]->[0] = $part; +} + # /$LISTNAME/$MESSAGE_ID/$IDX-$FILENAME sub get_attach ($$$) { my ($ctx, $idx, $fn) = @_; my $res = [ 404, [ 'Content-Type', 'text/plain' ], [ "Not found\n" ] ]; my $mime = $ctx->{-inbox}->msg_by_mid($ctx->{mid}) or return $res; - $mime = Email::MIME->new($mime); - msg_iter($mime, sub { - my ($part, $depth, @idx) = @{$_[0]}; - return if join('.', @idx) ne $idx; - $res->[0] = 200; - my $ct = $part->content_type; - $ct = parse_content_type($ct) if $ct; - - # discrete == type, we remain Debian wheezy-compatible - if ($ct && (($ct->{discrete} || '') eq 'text')) { - # display all text as text/plain: - my $cset = $ct->{attributes}->{charset}; - if ($cset && ($cset =~ /\A[\w-]+\z/)) { - $res->[1]->[1] .= qq(; charset=$cset); - } - } else { # TODO: allow user to configure safe types - $res->[1]->[1] = 'application/octet-stream'; - } - $part = $part->body; - push @{$res->[1]}, 'Content-Length', bytes::length($part); - $res->[2]->[0] = $part; - }); - $res; + $mime = PublicInbox::MIME->new($mime); + $res->[3] = $idx; + msg_iter($mime, \&get_attach_i, $res, 1); + pop @$res; # cleanup before letting PSGI server see it + $res } 1;