diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/PublicInbox/Feed.pm | 6 | ||||
-rw-r--r-- | lib/PublicInbox/View.pm | 39 | ||||
-rw-r--r-- | lib/PublicInbox/WWW.pm | 11 | ||||
-rw-r--r-- | lib/PublicInbox/WwwAttach.pm | 46 |
4 files changed, 83 insertions, 19 deletions
diff --git a/lib/PublicInbox/Feed.pm b/lib/PublicInbox/Feed.pm index 0b864c2c..e2df97b1 100644 --- a/lib/PublicInbox/Feed.pm +++ b/lib/PublicInbox/Feed.pm @@ -315,10 +315,10 @@ sub add_to_feed { my $mid = $header_obj->header_raw('Message-ID'); defined $mid or return 0; $mid = PublicInbox::Hval->new_msgid($mid); - my $href = $mid->as_href; + my $href = $midurl.$mid->as_href; my $content = qq(<pre\nstyle="white-space:pre-wrap">) . - PublicInbox::View::multipart_text_as_html($mime) . + PublicInbox::View::multipart_text_as_html($mime, $href) . '</pre>'; my $date = $header_obj->header('Date'); my $updated = feed_updated($date); @@ -346,7 +346,7 @@ sub add_to_feed { my $h = '[a-f0-9]'; my (@uuid5) = ($add =~ m!\A($h{8})($h{4})($h{4})($h{4})($h{12})!o); my $id = 'urn:uuid:' . join('-', @uuid5); - $fh->write(qq!</div></content><link\nhref="$midurl$href/"/>!. + $fh->write(qq!</div></content><link\nhref="$href/"/>!. "<id>$id</id></entry>"); 1; } diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm index 42601677..326da4cb 100644 --- a/lib/PublicInbox/View.pm +++ b/lib/PublicInbox/View.pm @@ -10,7 +10,6 @@ use URI::Escape qw/uri_escape_utf8/; use Date::Parse qw/str2time/; use Encode qw/find_encoding/; use Encode::MIME::Header; -use Email::MIME::ContentType qw/parse_content_type/; use PublicInbox::Hval qw/ascii_html/; use PublicInbox::Linkify; use PublicInbox::MID qw/mid_clean id_compress mid2path mid_mime/; @@ -27,7 +26,7 @@ sub msg_html { $footer = defined($footer) ? "\n$footer" : ''; my $hdr = $mime->header_obj; headers_to_html_header($hdr, $ctx) . - multipart_text_as_html($mime) . + multipart_text_as_html($mime, '') . '</pre><hr /><pre>' . html_footer($hdr, 1, $ctx, 'R/') . $footer . @@ -125,7 +124,7 @@ sub index_entry { my $mhref = "${path}$href/"; # scan through all parts, looking for displayable text - msg_iter($mime, sub { index_walk($fh, $_[0]) }); + msg_iter($mime, sub { index_walk($fh, $mhref, $_[0]) }); $rv = "\n" . html_footer($hdr, 0, $ctx, "$path$href/R/"); if (defined $irt) { @@ -211,8 +210,8 @@ sub emit_thread_html { } sub index_walk { - my ($fh, $p) = @_; - my $s = add_text_body($p); + my ($fh, $upfx, $p) = @_; + my $s = add_text_body($upfx, $p); return if $s eq ''; @@ -222,13 +221,13 @@ sub index_walk { } sub multipart_text_as_html { - my ($mime) = @_; + my ($mime, $upfx) = @_; my $rv = ""; # scan through all parts, looking for displayable text msg_iter($mime, sub { my ($p) = @_; - $p = add_text_body($p); + $p = add_text_body($upfx, $p); $rv .= $p; $rv .= "\n" if $p ne ''; }); @@ -249,8 +248,8 @@ sub flush_quote { $$s .= qq(<span\nclass="q">) . $rv . '</span>' } -sub attach_link ($$$) { - my ($ct, $p, $fn) = @_; +sub attach_link ($$$$) { + my ($upfx, $ct, $p, $fn) = @_; my ($part, $depth, @idx) = @$p; my $nl = $idx[-1] > 1 ? "\n" : ''; my $idx = join('.', @idx); @@ -262,29 +261,37 @@ sub attach_link ($$$) { $desc = $fn unless defined $desc; $desc = '' unless defined $desc; $desc = ': '.$desc if $desc; - "$nl<b>[-- Attachment #$idx$desc --]\n" . - "[-- Type: $ct, Size: $size bytes --]</b>" + my $sfn; + if (defined $fn && $fn =~ /\A[\w-]+\.[a-z0-9]+\z/) { + $sfn = $fn; + } elsif ($ct eq 'text/plain') { + $sfn = 'a.txt'; + } else { + $sfn = 'a.bin'; + } + qq($nl<a\nhref="$upfx$idx-$sfn">[-- Attachment #$idx$desc --]\n) . + "[-- Type: $ct, Size: $size bytes --]</a>" } sub add_text_body { - my ($p) = @_; # from msg_iter: [ Email::MIME, depth, @idx ] + my ($upfx, $p) = @_; # from msg_iter: [ Email::MIME, depth, @idx ] my ($part, $depth, @idx) = @$p; my $ct = $part->content_type; my $fn = $part->filename; if (defined $ct && $ct =~ m!\btext/x?html\b!i) { - return attach_link($ct, $p, $fn); + return attach_link($upfx, $ct, $p, $fn); } my $s = eval { $part->body_str }; # badly-encoded message? tell the world about it! - return attach_link($ct, $p, $fn) if $@; + return attach_link($upfx, $ct, $p, $fn) if $@; my @lines = split(/^/m, $s); $s = ''; - if (defined($fn) || $depth > 1 || $idx[0] > 1) { - $s .= attach_link($ct, $p, $fn); + if (defined($fn) || $depth > 0) { + $s .= attach_link($upfx, $ct, $p, $fn); $s .= "\n\n"; } my @quot; diff --git a/lib/PublicInbox/WWW.pm b/lib/PublicInbox/WWW.pm index 465dcb26..f87f4171 100644 --- a/lib/PublicInbox/WWW.pm +++ b/lib/PublicInbox/WWW.pm @@ -23,6 +23,7 @@ use PublicInbox::GitHTTPBackend; our $INBOX_RE = qr!\A/([\w\.\-]+)!; our $MID_RE = qr!([^/]+)!; our $END_RE = qr!(T/|t/|R/|t\.mbox(?:\.gz)?|t\.atom|raw|)!; +our $ATTACH_RE = qr!(\d[\.\d]*)-([\w-]+\.[a-z0-9]+)!i; sub new { my ($class, $pi_config) = @_; @@ -73,6 +74,10 @@ sub call { } elsif ($path_info =~ m!$INBOX_RE/$MID_RE/$END_RE\z!o) { msg_page($self, $ctx, $1, $2, $3); + } elsif ($path_info =~ m!$INBOX_RE/$MID_RE/$ATTACH_RE\z!o) { + my ($idx, $fn) = ($3, $4); + invalid_inbox_mid($self, $ctx, $1, $2) || + get_attach($ctx, $idx, $fn); # in case people leave off the trailing slash: } elsif ($path_info =~ m!$INBOX_RE/$MID_RE/(T|t|R)\z!o) { my ($inbox, $mid, $suffix) = ($1, $2, $3); @@ -442,4 +447,10 @@ sub news_www { $self->{news_www} = PublicInbox::NewsWWW->new($self->{pi_config}); } +sub get_attach { + my ($ctx, $idx, $fn) = @_; + require PublicInbox::WwwAttach; + PublicInbox::WwwAttach::get_attach($ctx, $idx, $fn); +} + 1; diff --git a/lib/PublicInbox/WwwAttach.pm b/lib/PublicInbox/WwwAttach.pm new file mode 100644 index 00000000..5cf56a80 --- /dev/null +++ b/lib/PublicInbox/WwwAttach.pm @@ -0,0 +1,46 @@ +# Copyright (C) 2016 all contributors <meta@public-inbox.org> +# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> + +# For retrieving attachments from messages in the WWW interface +package PublicInbox::WwwAttach; # internal package +use strict; +use warnings; +use Email::MIME; +use Email::MIME::ContentType qw(parse_content_type); +$Email::MIME::ContentType::STRICT_PARAMS = 0; +use PublicInbox::MID qw(mid2path); +use PublicInbox::MsgIter; + +# /$LISTNAME/$MESSAGE_ID/$IDX-$FILENAME +sub get_attach ($$$) { + my ($ctx, $idx, $fn) = @_; + my $path = mid2path($ctx->{mid}); + + my $res = [ 404, [ 'Content-Type', 'text/plain' ], [ "Not found\n" ] ]; + my $mime = $ctx->{git}->cat_file("HEAD:$path") 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; +} + +1; |