]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/View.pm
view: do not redundantly obfuscate addresses
[public-inbox.git] / lib / PublicInbox / View.pm
index 980f265a06ddb99d9736242473e28a1db7ee894c..33b323dce248670dc1da248b795419470b4c0019 100644 (file)
@@ -10,7 +10,8 @@ use bytes (); # only for bytes::length
 use PublicInbox::MsgTime qw(msg_datestamp);
 use PublicInbox::Hval qw(ascii_html obfuscate_addrs prurl mid_href);
 use PublicInbox::Linkify;
-use PublicInbox::MID qw/id_compress mids mids_for_index references/;
+use PublicInbox::MID qw(id_compress mids mids_for_index references
+                       $MID_EXTRACT);
 use PublicInbox::MsgIter;
 use PublicInbox::Address;
 use PublicInbox::WwwStream;
@@ -18,7 +19,7 @@ use PublicInbox::Reply;
 use PublicInbox::ViewDiff qw(flush_diff);
 use POSIX qw(strftime);
 use Time::Local qw(timegm);
-use PublicInbox::SearchMsg qw(subject_normalized);
+use PublicInbox::Smsg qw(subject_normalized);
 use constant COLS => 72;
 use constant INDENT => '  ';
 use constant TCHILD => '` ';
@@ -26,22 +27,14 @@ sub th_pfx ($) { $_[0] == 0 ? '' : TCHILD };
 
 sub msg_page_i {
        my ($nr, $ctx) = @_;
-       my $more = $ctx->{more};
-       if ($nr == 1) {
-               # $more cannot be true w/o $smsg being defined:
-               $ctx->{mhref} = $more ? '../'.mid_href($ctx->{smsg}->{mid}).'/'
-                                     : '';
-               multipart_text_as_html(delete $ctx->{mime}, $ctx);
-               ${delete $ctx->{obuf}} .= '</pre><hr>';
-       } elsif ($more) {
-               ++$ctx->{end_nr};
-               # fake an EOF if {more} retrieval fails fails;
-               eval { msg_page_more($ctx, $nr) };
-       } elsif ($nr == $ctx->{end_nr}) {
+       if (my $more = delete $ctx->{more}) { # unlikely
+               # fake an EOF if $more retrieval fails;
+               eval { msg_page_more($ctx, $nr, @$more) };
+       } elsif (my $hdr = delete $ctx->{hdr}) {
                # fake an EOF if generating the footer fails;
                # we want to at least show the message if something
                # here crashes:
-               eval { html_footer($ctx) };
+               eval { html_footer($ctx, $hdr) };
        } else {
                undef
        }
@@ -53,40 +46,37 @@ sub msg_page {
        my ($ctx) = @_;
        my $mid = $ctx->{mid};
        my $ibx = $ctx->{-inbox};
-       my ($first);
-       my $smsg;
+       my ($smsg, $first, $next);
        if (my $over = $ibx->over) {
                my ($id, $prev);
-               $smsg = $over->next_by_mid($mid, \$id, \$prev);
-               $first = $ibx->msg_by_smsg($smsg) if $smsg;
-               if ($first) {
-                       my $next = $over->next_by_mid($mid, \$id, \$prev);
-                       $ctx->{more} = [ $id, $prev, $next ] if $next;
-               }
-               return unless $first;
+               $smsg = $over->next_by_mid($mid, \$id, \$prev) or return;
+               $first = $ibx->msg_by_smsg($smsg) or return;
+               $next = $over->next_by_mid($mid, \$id, \$prev);
+               $ctx->{more} = [ $id, $prev, $next ] if $next;
        } else {
                $first = $ibx->msg_by_mid($mid) or return;
        }
-       my $mime = $ctx->{mime} = PublicInbox::MIME->new($first);
+       my $mime = PublicInbox::MIME->new($first);
        $ctx->{-obfs_ibx} = $ibx->{obfuscate} ? $ibx : undef;
        my $hdr = $ctx->{hdr} = $mime->header_obj;
-       _msg_page_prepare_obuf($hdr, $ctx, 0);
-       $ctx->{end_nr} = 2;
+       $ctx->{obuf} = _msg_page_prepare_obuf($hdr, $ctx, 0);
        $ctx->{smsg} = $smsg;
+       # $next cannot be true w/o $smsg being defined:
+       $ctx->{mhref} = $next ? '../'.mid_href($smsg->{mid}).'/' : '';
+       multipart_text_as_html($mime, $ctx);
+       $ctx->{-html_tip} = (${delete $ctx->{obuf}} .= '</pre><hr>');
        PublicInbox::WwwStream->response($ctx, 200, \&msg_page_i);
 }
 
-sub msg_page_more {
-       my ($ctx, $nr) = @_;
-       my ($id, $prev, $smsg) = @{$ctx->{more}};
+sub msg_page_more { # cold
+       my ($ctx, $nr, $id, $prev, $smsg) = @_;
        my $ibx = $ctx->{-inbox};
-       $smsg = $ibx->smsg_mime($smsg);
        my $next = $ibx->over->next_by_mid($ctx->{mid}, \$id, \$prev);
-       $ctx->{more} = $next ? [ $id, $prev, $next ] : undef;
-       return '' unless $smsg;
+       $ctx->{more} = [ $id, $prev, $next ] if $next;
+       $smsg = $ibx->smsg_mime($smsg) or return '';
        $ctx->{mhref} = '../' . mid_href($smsg->{mid}) . '/';
        my $mime = delete $smsg->{mime};
-       _msg_page_prepare_obuf($mime->header_obj, $ctx, $nr);
+       $ctx->{obuf} = _msg_page_prepare_obuf($mime->header_obj, $ctx, $nr);
        multipart_text_as_html($mime, $ctx);
        ${delete $ctx->{obuf}} .= '</pre><hr>';
 }
@@ -310,7 +300,7 @@ sub _th_index_lite {
        if (my $smsg = $node->{smsg}) {
                # delete saves about 200KB on a 1K message thread
                if (my $refs = delete $smsg->{references}) {
-                       ($$irt) = ($refs =~ m/<([^>]+)>\z/);
+                       ($$irt) = ($refs =~ m/$MID_EXTRACT\z/o);
                }
        }
        my $irt_map = $mapping->{$$irt} if defined $$irt;
@@ -492,17 +482,6 @@ sub multipart_text_as_html {
        msg_iter($_[0], \&add_text_body, $_[1], 1);
 }
 
-sub flush_quote {
-       my ($s, $l, $quot) = @_;
-
-       my $rv = $l->to_html($$quot);
-
-       # we use a <span> here to allow users to specify their own
-       # color for quoted text
-       $$quot = undef;
-       $$s .= qq(<span\nclass="q">) . $rv . '</span>'
-}
-
 sub attach_link ($$$$;$) {
        my ($ctx, $ct, $p, $fn, $err) = @_;
        my ($part, $depth, @idx) = @$p;
@@ -514,9 +493,6 @@ sub attach_link ($$$$;$) {
        # spotting MUA problems:
        $ct =~ s/;.*// unless $err;
        $ct = ascii_html($ct);
-       my $desc = $part->header('Content-Description');
-       $desc = $fn unless defined $desc;
-       $desc = '' unless defined $desc;
        my $sfn;
        if (defined $fn && $fn =~ /\A$PublicInbox::Hval::FN\z/o) {
                $sfn = $fn;
@@ -528,10 +504,13 @@ sub attach_link ($$$$;$) {
        my $rv = $ctx->{obuf};
        $$rv .= qq($nl<a\nhref="$ctx->{mhref}$idx-$sfn">);
        if ($err) {
-               $$rv .= "[-- Warning: decoded text below may be mangled --]\n";
+               $$rv .= <<EOF;
+[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
+EOF
        }
        $$rv .= "[-- Attachment #$idx: ";
        my $ts = "Type: $ct, Size: $size bytes";
+       my $desc = $part->header('Content-Description') // $fn // '';
        $desc = ascii_html($desc);
        $$rv .= ($desc eq '') ? "$ts --]" : "$desc --]\n[-- $ts --]";
        $$rv .= "</a>\n";
@@ -553,6 +532,9 @@ sub add_text_body { # callback for msg_iter
        # link generation in diffs with the extra '%0D'
        $s =~ s/\r\n/\n/sg;
 
+       # will be escaped to `&#8226;' in HTML
+       obfuscate_addrs($ibx, $s, "\x{2022}") if $ibx->{obfuscate};
+
        # always support diff-highlighting, but we can't linkify hunk
        # headers for solver unless some coderepo are configured:
        my $diff;
@@ -586,8 +568,8 @@ sub add_text_body { # callback for msg_iter
        $s .= "\n" unless $s =~ /\n\z/s;
 
        # split off quoted and unquoted blocks:
-       my @sections = split(/((?:^>[^\n]*\n)+)/sm, $s);
-       $s = '';
+       my @sections = PublicInbox::MsgIter::split_quotes($s);
+       undef $s; # free memory
        my $rv = $ctx->{obuf};
        if (defined($fn) || $depth > 0 || $err) {
                # badly-encoded message with $err? tell the world about it!
@@ -597,17 +579,19 @@ sub add_text_body { # callback for msg_iter
        my $l = $ctx->{-linkify} //= PublicInbox::Linkify->new;
        foreach my $cur (@sections) {
                if ($cur =~ /\A>/) {
-                       flush_quote($rv, $l, \$cur);
+                       # we use a <span> here to allow users to specify
+                       # their own color for quoted text
+                       $$rv .= qq(<span\nclass="q">);
+                       $$rv .= $l->to_html($cur);
+                       $$rv .= '</span>';
                } elsif ($diff) {
-                       flush_diff($rv, $ctx, \$cur);
+                       flush_diff($ctx, \$cur);
                } else {
                        # regular lines, OK
                        $$rv .= $l->to_html($cur);
-                       $cur = undef;
                }
+               undef $cur; # free memory
        }
-
-       obfuscate_addrs($ibx, $$rv) if $ibx->{obfuscate};
 }
 
 sub _msg_page_prepare_obuf {
@@ -686,7 +670,7 @@ sub _msg_page_prepare_obuf {
        }
        $rv .= _parent_headers($hdr, $over);
        $rv .= "\n";
-       $ctx->{obuf} = \$rv;
+       \$rv;
 }
 
 sub SKEL_EXPAND () {
@@ -769,9 +753,8 @@ sub _parent_headers {
 
 # returns a string buffer via ->getline
 sub html_footer {
-       my ($ctx) = @_;
+       my ($ctx, $hdr) = @_;
        my $ibx = $ctx->{-inbox};
-       my $hdr = delete $ctx->{hdr};
        my $upfx = '../';
        my $skel = " <a\nhref=\"$upfx\">index</a>";
        my $rv = '<pre>';
@@ -899,20 +882,20 @@ sub missing_thread {
 sub dedupe_subject {
        my ($prev_subj, $subj, $val) = @_;
 
-       my $omit = ''; # '"' denotes identical text omitted
+       my $omit; # '"' denotes identical text omitted
        my (@prev_pop, @curr_pop);
        while (@$prev_subj && @$subj && $subj->[-1] eq $prev_subj->[-1]) {
                push(@prev_pop, pop(@$prev_subj));
                push(@curr_pop, pop(@$subj));
-               $omit ||= $val;
+               $omit //= $val;
        }
        pop @$subj if @$subj && $subj->[-1] =~ /^re:\s*/i;
        if (scalar(@curr_pop) == 1) {
-               $omit = '';
+               $omit = undef;
                push @$prev_subj, @prev_pop;
                push @$subj, @curr_pop;
        }
-       $omit;
+       $omit // '';
 }
 
 sub skel_dump { # walk_thread callback
@@ -1067,7 +1050,7 @@ sub acc_topic { # walk_thread callback
 sub dump_topics {
        my ($ctx) = @_;
        my $order = delete $ctx->{order}; # [ ds, subj1, subj2, subj3, ... ]
-       if (!@$order) {
+       unless ($order) {
                $ctx->{-html_tip} = '<pre>[No topics in range]</pre>';
                return 404;
        }