diff options
author | Eric Wong (Contractor, The Linux Foundation) <e@80x24.org> | 2018-03-23 20:29:24 +0000 |
---|---|---|
committer | Eric Wong (Contractor, The Linux Foundation) <e@80x24.org> | 2018-03-27 02:34:20 +0000 |
commit | 007cb8774e7013e2aaca32003bbd1653e3d8582f (patch) | |
tree | 24645e152f6c386730dfdc9925b5dd5ca7740752 | |
parent | 26895bbd94dc93b76274652f9ea35626fd63a5fa (diff) | |
download | public-inbox-007cb8774e7013e2aaca32003bbd1653e3d8582f.tar.gz |
This needs tests and further refinement, but current tests pass.
-rw-r--r-- | lib/PublicInbox/Mbox.pm | 12 | ||||
-rw-r--r-- | lib/PublicInbox/SearchMsg.pm | 7 | ||||
-rw-r--r-- | lib/PublicInbox/View.pm | 107 | ||||
-rw-r--r-- | lib/PublicInbox/WWW.pm | 7 | ||||
-rw-r--r-- | t/psgi_v2.t | 12 |
5 files changed, 118 insertions, 27 deletions
diff --git a/lib/PublicInbox/Mbox.pm b/lib/PublicInbox/Mbox.pm index 79e09a70..c14037f4 100644 --- a/lib/PublicInbox/Mbox.pm +++ b/lib/PublicInbox/Mbox.pm @@ -26,13 +26,6 @@ sub subject_fn ($) { $fn eq '' ? 'no-subject' : $fn; } -sub smsg_for ($$$) { - my ($head, $db, $mid) = @_; - my $doc_id = $head->get_docid; - my $doc = $db->get_document($doc_id); - PublicInbox::SearchMsg->wrap($doc, $mid)->load_expand; -} - sub mb_stream { my ($more) = @_; bless $more, 'PublicInbox::Mbox'; @@ -47,7 +40,7 @@ sub getline { return msg_str($ctx, $cur); } for (; !defined($cur) && $head != $tail; $head++) { - my $smsg = smsg_for($head, $db, $ctx->{mid}); + my $smsg = PublicInbox::SearchMsg->get($head, $db, $ctx->{mid}); next if $smsg->type ne 'mail'; my $mref = $ctx->{-inbox}->msg_by_smsg($smsg) or next; $cur = Email::Simple->new($mref); @@ -71,7 +64,8 @@ sub emit_raw { $srch->retry_reopen(sub { ($head, $tail, $db) = $srch->each_smsg_by_mid($mid); for (; !defined($first) && $head != $tail; $head++) { - my $smsg = smsg_for($head, $db, $mid); + my @args = ($head, $db, $mid); + my $smsg = PublicInbox::SearchMsg->get(@args); next if $smsg->type ne 'mail'; my $mref = $ibx->msg_by_smsg($smsg) or next; $first = Email::Simple->new($mref); diff --git a/lib/PublicInbox/SearchMsg.pm b/lib/PublicInbox/SearchMsg.pm index dd3d58d0..b944868f 100644 --- a/lib/PublicInbox/SearchMsg.pm +++ b/lib/PublicInbox/SearchMsg.pm @@ -24,6 +24,13 @@ sub wrap { bless { doc => $doc, mime => undef, mid => $mid }, $class; } +sub get { + my ($class, $head, $db, $mid) = @_; + my $doc_id = $head->get_docid; + my $doc = $db->get_document($doc_id); + load_expand(wrap($class, $doc, $mid)) +} + sub get_val ($$) { my ($doc, $col) = @_; Search::Xapian::sortable_unserialise($doc->get_value($col)); diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm index 18882afd..34ab3e58 100644 --- a/lib/PublicInbox/View.pm +++ b/lib/PublicInbox/View.pm @@ -9,7 +9,7 @@ use warnings; use PublicInbox::MsgTime qw(msg_datestamp); use PublicInbox::Hval qw/ascii_html obfuscate_addrs/; use PublicInbox::Linkify; -use PublicInbox::MID qw/mid_clean id_compress mid_mime mid_escape/; +use PublicInbox::MID qw/mid_clean id_compress mid_mime mid_escape mids/; use PublicInbox::MsgIter; use PublicInbox::Address; use PublicInbox::WwwStream; @@ -21,18 +21,23 @@ use constant TCHILD => '` '; sub th_pfx ($) { $_[0] == 0 ? '' : TCHILD }; # public functions: (unstable) + sub msg_html { - my ($ctx, $mime) = @_; + my ($ctx, $mime, $more) = @_; my $hdr = $mime->header_obj; my $ibx = $ctx->{-inbox}; - my $obfs_ibx = $ibx->{obfuscate} ? $ibx : undef; - my $tip = _msg_html_prepare($hdr, $ctx, $obfs_ibx); + my $obfs_ibx = $ctx->{-obfs_ibx} = $ibx->{obfuscate} ? $ibx : undef; + my $tip = _msg_html_prepare($hdr, $ctx, $more, 0); + my $end = 2; PublicInbox::WwwStream->response($ctx, 200, sub { my ($nr, undef) = @_; if ($nr == 1) { $tip . multipart_text_as_html($mime, '', $obfs_ibx) . '</pre><hr>' - } elsif ($nr == 2) { + } elsif ($more && @$more) { + ++$end; + msg_html_more($ctx, $more, $nr); + } elsif ($nr == $end) { # fake an EOF if generating the footer fails; # we want to at least show the message if something # here crashes: @@ -46,6 +51,63 @@ sub msg_html { }); } +sub msg_page { + my ($ctx) = @_; + my $mid = $ctx->{mid}; + my $ibx = $ctx->{-inbox}; + my ($first, $more, $head, $tail, $db); + if (my $srch = $ibx->search) { + $srch->retry_reopen(sub { + ($head, $tail, $db) = $srch->each_smsg_by_mid($mid); + for (; !defined($first) && $head != $tail; $head++) { + my @args = ($head, $db, $mid); + my $smsg = PublicInbox::SearchMsg->get(@args); + next if $smsg->type ne 'mail'; + $first = $ibx->msg_by_smsg($smsg); + } + if ($head != $tail) { + $more = [ $head, $tail, $db ]; + } + }); + } else { + $first = $ibx->msg_by_mid($mid) or return; + } + $first ? msg_html($ctx, PublicInbox::MIME->new($first), $more) : undef; +} + +sub msg_html_more { + my ($ctx, $more, $nr) = @_; + my $str = eval { + my $mref; + my ($head, $tail, $db) = @$more; + for (; !defined($mref) && $head != $tail; $head++) { + my $smsg = PublicInbox::SearchMsg->get($head, $db, + $ctx->{mid}); + next if $smsg->type ne 'mail'; + $mref = $ctx->{-inbox}->msg_by_smsg($smsg); + } + if ($head == $tail) { # done + @$more = (); + } else { + $more->[0] = $head; + } + if ($mref) { + my $mime = PublicInbox::MIME->new($mref); + _msg_html_prepare($mime->header_obj, $ctx, $more, $nr) . + multipart_text_as_html($mime, '', + $ctx->{-obfs_ibx}) . + '</pre><hr>' + } else { + ''; + } + }; + if ($@) { + warn "Error lookup up additional messages: $@\n"; + $str = '<pre>Error looking up additional messages</pre>'; + } + $str; +} + # /$INBOX/$MESSAGE_ID/#R sub msg_reply { my ($ctx, $hdr) = @_; @@ -529,17 +591,26 @@ sub add_text_body { } sub _msg_html_prepare { - my ($hdr, $ctx, $obfs_ibx) = @_; + my ($hdr, $ctx, $more, $nr) = @_; my $srch = $ctx->{srch} if $ctx; my $atom = ''; - my $rv = "<pre\nid=b>"; # anchor for body start - + my $obfs_ibx = $ctx->{-obfs_ibx}; + my $rv = ''; + my $mids = mids($hdr); + my $multiple = scalar(@$mids) > 1; # zero, one, infinity + if ($nr == 0) { + if ($more) { + $rv .= +"<pre>WARNING: multiple messages refer to this Message-ID\n</pre>"; + } + $rv .= "<pre\nid=b>"; # anchor for body start + } else { + $rv .= '<pre>'; + } if ($srch) { $ctx->{-upfx} = '../'; } my @title; - my $mid = mid_clean($hdr->header_raw('Message-ID')); - $mid = PublicInbox::Hval->new_msgid($mid); foreach my $h (qw(From To Cc Subject Date)) { my $v = $hdr->header($h); defined($v) && ($v ne '') or next; @@ -564,8 +635,20 @@ sub _msg_html_prepare { } $title[0] ||= '(no subject)'; $ctx->{-title_html} = join(' - ', @title); - $rv .= 'Message-ID: <' . $mid->as_html . '> '; - $rv .= "(<a\nhref=\"raw\">raw</a>)\n"; + foreach (@$mids) { + my $mid = PublicInbox::Hval->new_msgid($_) ; + my $mhtml = $mid->as_html; + if ($multiple) { + my $href = $mid->{href}; + $rv .= "Message-ID: "; + $rv .= "<a\nhref=\"../$href/\">"; + $rv .= "<$mhtml></a> "; + $rv .= "(<a\nhref=\"../$href/raw\">raw</a>)\n"; + } else { + $rv .= "Message-ID: <$mhtml> "; + $rv .= "(<a\nhref=\"raw\">raw</a>)\n"; + } + } $rv .= _parent_headers($hdr, $srch); $rv .= "\n"; } diff --git a/lib/PublicInbox/WWW.pm b/lib/PublicInbox/WWW.pm index f86363c6..7bf866f1 100644 --- a/lib/PublicInbox/WWW.pm +++ b/lib/PublicInbox/WWW.pm @@ -225,13 +225,8 @@ sub get_mid_txt { # /$INBOX/$MESSAGE_ID/ -> HTML content (short quotes) sub get_mid_html { my ($ctx) = @_; - my $x = mid2blob($ctx) or return r404($ctx); - require PublicInbox::View; - require PublicInbox::MIME; - my $mime = PublicInbox::MIME->new($x); - searcher($ctx); - PublicInbox::View::msg_html($ctx, $mime); + PublicInbox::View::msg_page($ctx) || r404($ctx); } # /$INBOX/$MESSAGE_ID/t/ diff --git a/t/psgi_v2.t b/t/psgi_v2.t index 1e45c263..eaa3218c 100644 --- a/t/psgi_v2.t +++ b/t/psgi_v2.t @@ -127,6 +127,18 @@ test_psgi(sub { $www->call(@_) }, sub { @from_ = ($raw =~ m/^From /mg); is(scalar(@from_), 3, 'three From_ lines in t.mbox.gz'); }; + + local $SIG{__WARN__} = 'DEFAULT'; + $res = $cb->(GET('/v2test/a-mid@b/')); + $raw = $res->content; + like($raw, qr/^hello world$/m, 'got first message'); + like($raw, qr/^hello world!$/m, 'got second message'); + like($raw, qr/^hello ghosts$/m, 'got third message'); + @from_ = ($raw =~ m/>From: /mg); + is(scalar(@from_), 3, 'three From: lines'); + foreach my $mid ('a-mid@b', $new_mid, $third) { + like($raw, qr/<\Q$mid\E>/s, "Message-ID $mid shown"); + } }); done_testing(); |