]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/View.pm
Merge remote-tracking branch 'origin/search'
[public-inbox.git] / lib / PublicInbox / View.pm
index c40a2a75c8ab119345c5fd7bfdcd97ce74fd2d3d..47082431ec8fa375580c7b85afa95117ea0496a9 100644 (file)
@@ -9,7 +9,7 @@ use Encode qw/find_encoding/;
 use Encode::MIME::Header;
 use Email::MIME::ContentType qw/parse_content_type/;
 use PublicInbox::Hval;
-use PublicInbox::MID qw/mid_clean mid_compressed/;
+use PublicInbox::MID qw/mid_clean mid_compressed mid2path/;
 use Digest::SHA;
 require POSIX;
 
@@ -31,7 +31,7 @@ sub msg_html {
        } else {
                $footer = '';
        }
-       headers_to_html_header($mime, $full_pfx) .
+       headers_to_html_header($mime, $full_pfx, $srch) .
                multipart_text_as_html($mime, $full_pfx) .
                '</pre><hr />' . PRE_WRAP .
                html_footer($mime, 1, $full_pfx, $srch) . $footer .
@@ -138,40 +138,34 @@ sub thread_html {
        my $mid = mid_compressed($ctx->{mid});
        my $res = $srch->get_thread($mid);
        my $rv = '';
-       require PublicInbox::GitCatFile;
-       my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
-       my $nr = scalar @{$res->{msgs}};
+       my $msgs = load_results($ctx, $res);
+       my $nr = scalar @$msgs;
        return $rv if $nr == 0;
-       my @msgs;
-       while (my $smsg = shift @{$res->{msgs}}) {
-               my $m = $smsg->mid;
-
-               # Duplicated from WWW.pm
-               my ($x2, $x38) = ($m =~ /\A([a-f0-9]{2})([a-f0-9]{38})\z/);
+       require PublicInbox::Thread;
+       my $th = PublicInbox::Thread->new(@$msgs);
+       $th->thread;
+       $th->order(*PublicInbox::Thread::sort_ts);
+       my $state = [ undef, { root_anchor => anchor_for($mid) }, undef, 0 ];
+       thread_entry(\$rv, $state, $_, 0) for $th->rootset;
+       my $final_anchor = $state->[3];
+       my $next = "<a\nid=\"s$final_anchor\">end of thread</a>\n";
 
-               unless (defined $x38) {
-                       require Digest::SHA;
-                       $m = Digest::SHA::sha1_hex($m);
-                       ($x2, $x38) = ($m =~ /\A([a-f0-9]{2})([a-f0-9]{38})\z/);
-               }
+       $rv .= "</pre><hr />" . PRE_WRAP . $next . $foot . "</pre>";
+}
 
-               # FIXME: duplicated code from Feed.pm
-               my $mime = eval {
-                       my $str = $git->cat_file("HEAD:$x2/$x38");
-                       Email::MIME->new($str);
-               };
-               unless ($@) {
-                       my $t = eval { str2time($mime->header('Date')) };
-                       defined($t) or $t = 0;
-                       $mime->header_set('X-PI-TS', $t);
-                       push @msgs, $mime;
-               }
-       }
+sub subject_path_html {
+       my (undef, $ctx, $foot, $srch) = @_;
+       my $path = $ctx->{subject_path};
+       my $res = $srch->get_subject_path($path);
+       my $rv = '';
+       my $msgs = load_results($ctx, $res);
+       my $nr = scalar @$msgs;
+       return $rv if $nr == 0;
        require PublicInbox::Thread;
-       my $th = PublicInbox::Thread->new(@msgs);
+       my $th = PublicInbox::Thread->new(@$msgs);
        $th->thread;
        $th->order(*PublicInbox::Thread::sort_ts);
-       my $state = [ undef, { root_anchor => anchor_for($mid) }, undef, 0 ];
+       my $state = [ undef, { root_anchor => 'dummy' }, undef, 0 ];
        thread_entry(\$rv, $state, $_, 0) for $th->rootset;
        my $final_anchor = $state->[3];
        my $next = "<a\nid=\"s$final_anchor\">end of thread</a>\n";
@@ -207,14 +201,17 @@ sub index_walk {
        # Drop signatures
        $s =~ s/^-- \n.*\z//ms and $$more = 'more...';
 
-       # kill any leading or trailing whitespace
-       $s =~ s/\A\s+//s;
+       # kill any leading or trailing whitespace lines
+       $s =~ s/^\s*$//sgm;
        $s =~ s/\s+\z//s;
 
        if (length $s) {
                # add prefix:
                $s =~ s/^/$pfx/sgm;
 
+               # kill per-line trailing whitespace
+               $s =~ s/[ \t]+$//sgm;
+
                $rv .= $s . "\n";
        }
        $rv;
@@ -235,7 +232,7 @@ sub enc_for {
 }
 
 sub multipart_text_as_html {
-       my ($mime, $full_pfx) = @_;
+       my ($mime, $full_pfx, $srch) = @_;
        my $rv = "";
        my $part_nr = 0;
        my $enc_msg = enc_for($mime->header("Content-Type"));
@@ -339,7 +336,7 @@ sub add_text_body_full {
 }
 
 sub headers_to_html_header {
-       my ($mime, $full_pfx) = @_;
+       my ($mime, $full_pfx, $srch) = @_;
 
        my $rv = "";
        my @title;
@@ -347,18 +344,21 @@ sub headers_to_html_header {
                my $v = $mime->header($h);
                defined($v) && length($v) or next;
                $v = PublicInbox::Hval->new_oneline($v);
-               $rv .= "$h: " . $v->as_html . "\n";
 
                if ($h eq 'From') {
                        my @from = Email::Address->parse($v->raw);
-                       $v = $from[0]->name;
-                       unless (defined($v) && length($v)) {
-                               $v = '<' . $from[0]->address . '>';
-                       }
-                       $title[1] = ascii_html($v);
+                       $title[1] = ascii_html($from[0]->name);
                } elsif ($h eq 'Subject') {
                        $title[0] = $v->as_html;
+                       if ($srch) {
+                               my $path = $srch->subject_path($v->raw);
+                               $rv .= "$h: <a\nhref=\"../s/$path.html\">";
+                               $rv .= $v->as_html . "</a>\n";
+                               next;
+                       }
                }
+               $rv .= "$h: " . $v->as_html . "\n";
+
        }
 
        my $header_obj = $mime->header_obj;
@@ -510,6 +510,9 @@ sub hash_subj {
 sub thread_replies {
        my ($dst, $root, $res) = @_;
        my @msgs = map { $_->mini_mime } @{$res->{msgs}};
+       foreach (@{$res->{msgs}}) {
+               print STDERR "smsg->path: <", $_->path, ">\n";
+       }
        require PublicInbox::Thread;
        $root->header_set('X-PI-TS', '0');
        my $th = PublicInbox::Thread->new($root, @msgs);
@@ -532,7 +535,7 @@ sub thread_entry {
        my ($dst, $state, $node, $level) = @_;
        # $state = [ $search_res, $seen, undef, 0 (msg_nr) ];
        # $seen is overloaded with 3 types of fields:
-       #       1) "root" => Message-ID,
+       #       1) "root_anchor" => anchor_for(Message-ID),
        #       2) seen subject hashes: sha1(subject) => 1
        #       3) anchors hashes: "#$sha1_hex" (same as $seen in index_entry)
        if (my $mime = $node->message) {
@@ -545,4 +548,29 @@ sub thread_entry {
        thread_entry($dst, $state, $node->next, $level) if $node->next;
 }
 
+sub load_results {
+       my ($ctx, $res) = @_;
+
+       require PublicInbox::GitCatFile;
+       my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
+       my @msgs;
+       while (my $smsg = shift @{$res->{msgs}}) {
+               my $m = $smsg->mid;
+               my $path = mid2path($m);
+
+               # FIXME: duplicated code from Feed.pm
+               my $mime = eval {
+                       my $str = $git->cat_file("HEAD:$path");
+                       Email::MIME->new($str);
+               };
+               unless ($@) {
+                       my $t = eval { str2time($mime->header('Date')) };
+                       defined($t) or $t = 0;
+                       $mime->header_set('X-PI-TS', $t);
+                       push @msgs, $mime;
+               }
+       }
+       \@msgs;
+}
+
 1;