]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/WwwText.pm
wwwtext: show thread endpoint w/ indexlevel=basic
[public-inbox.git] / lib / PublicInbox / WwwText.pm
index b8beb97c6d5983e9c319a2f7733a4e232fc7f884..cbe82b730f765a585e3fbf019a98f5183afa3405 100644 (file)
@@ -1,15 +1,21 @@
-# Copyright (C) 2016 all contributors <meta@public-inbox.org>
+# Copyright (C) 2016-2020 all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
-#
-# serves the /$INBOX/_/* endpoints from :text/* of the git tree
+
+# used for displaying help texts and other non-mail content
 package PublicInbox::WwwText;
 use strict;
 use warnings;
 package PublicInbox::WwwText;
 use strict;
 use warnings;
+use bytes (); # only for bytes::length
 use PublicInbox::Linkify;
 use PublicInbox::WwwStream;
 use PublicInbox::Hval qw(ascii_html);
 use PublicInbox::Linkify;
 use PublicInbox::WwwStream;
 use PublicInbox::Hval qw(ascii_html);
+use URI::Escape qw(uri_escape_utf8);
 our $QP_URL = 'https://xapian.org/docs/queryparser.html';
 our $WIKI_URL = 'https://en.wikipedia.org/wiki';
 our $QP_URL = 'https://xapian.org/docs/queryparser.html';
 our $WIKI_URL = 'https://en.wikipedia.org/wiki';
+my $hl = eval {
+       require PublicInbox::HlMod;
+       PublicInbox::HlMod->new
+};
 
 # /$INBOX/_/text/$KEY/ # KEY may contain slashes
 # For now, "help" is the only supported $KEY
 
 # /$INBOX/_/text/$KEY/ # KEY may contain slashes
 # For now, "help" is the only supported $KEY
@@ -24,14 +30,14 @@ sub get_text {
        my $have_tslash = ($key =~ s!/\z!!) if !$raw;
 
        my $txt = '';
        my $have_tslash = ($key =~ s!/\z!!) if !$raw;
 
        my $txt = '';
-       if (!_default_text($ctx, $key, \$txt)) {
+       my $hdr = [ 'Content-Type', 'text/plain', 'Content-Length', undef ];
+       if (!_default_text($ctx, $key, $hdr, \$txt)) {
                $code = 404;
                $txt = "404 Not Found ($key)\n";
        }
        if ($raw) {
                $code = 404;
                $txt = "404 Not Found ($key)\n";
        }
        if ($raw) {
-               return [ $code, [ 'Content-Type', 'text/plain',
-                                 'Content-Length', bytes::length($txt) ],
-                       [ $txt ] ]
+               $hdr->[3] = bytes::length($txt);
+               return [ $code, $hdr, [ $txt ] ]
        }
 
        # enforce trailing slash for "wget -r" compatibility
        }
 
        # enforce trailing slash for "wget -r" compatibility
@@ -47,21 +53,25 @@ sub get_text {
        # Follow git commit message conventions,
        # first line is the Subject/title
        my ($title) = ($txt =~ /\A([^\n]*)/s);
        # Follow git commit message conventions,
        # first line is the Subject/title
        my ($title) = ($txt =~ /\A([^\n]*)/s);
-       _do_linkify($txt);
+       $ctx->{txt} = \$txt;
        $ctx->{-title_html} = ascii_html($title);
        $ctx->{-title_html} = ascii_html($title);
-
        my $nslash = ($key =~ tr!/!/!);
        $ctx->{-upfx} = '../../../' . ('../' x $nslash);
        my $nslash = ($key =~ tr!/!/!);
        $ctx->{-upfx} = '../../../' . ('../' x $nslash);
-
-       PublicInbox::WwwStream->response($ctx, $code, sub {
-               my ($nr, undef) = @_;
-               $nr == 1 ? '<pre>'.$txt.'</pre>' : undef
-       });
+       PublicInbox::WwwStream->response($ctx, $code, \&_do_linkify);
 }
 
 sub _do_linkify {
 }
 
 sub _do_linkify {
+       my ($nr, $ctx) = @_;
+       return unless $nr == 1;
        my $l = PublicInbox::Linkify->new;
        my $l = PublicInbox::Linkify->new;
-       $_[0] = $l->linkify_2(ascii_html($l->linkify_1($_[0])));
+       my $txt = delete $ctx->{txt};
+       $l->linkify_1($$txt);
+       if ($hl) {
+               $hl->do_hl_text($txt);
+       } else {
+               $$txt = ascii_html($$txt);
+       }
+       '<pre>' . $l->linkify_2($$txt) . '</pre>';
 }
 
 sub _srch_prefix ($$) {
 }
 
 sub _srch_prefix ($$) {
@@ -88,9 +98,104 @@ sub _srch_prefix ($$) {
        1;
 }
 
        1;
 }
 
+sub _colors_help ($$) {
+       my ($ctx, $txt) = @_;
+       my $ibx = $ctx->{-inbox};
+       my $env = $ctx->{env};
+       my $base_url = $ibx->base_url($env);
+       $$txt .= "color customization for $base_url\n";
+       $$txt .= <<EOF;
+
+public-inbox provides a stable set of CSS classes for users to
+customize colors for highlighting diffs and code.
+
+Users of browsers such as dillo, Firefox, or some browser
+extensions may start by downloading the following sample CSS file
+to control the colors they see:
+
+       ${base_url}userContent.css
+
+CSS sample
+----------
+```css
+EOF
+       $$txt .= PublicInbox::UserContent::sample($ibx, $env) . "```\n";
+}
+
+# git-config section names are quoted in the config file, so escape them
+sub dq_escape ($) {
+       my ($name) = @_;
+       $name =~ s/\\/\\\\/g;
+       $name =~ s/"/\\"/g;
+       $name;
+}
+
+sub URI_PATH () { '^A-Za-z0-9\-\._~/' }
+
+# n.b. this is a perfect candidate for memoization
+sub inbox_config ($$$) {
+       my ($ctx, $hdr, $txt) = @_;
+       my $ibx = $ctx->{-inbox};
+       push @$hdr, 'Content-Disposition', 'inline; filename=inbox.config';
+       my $name = dq_escape($ibx->{name});
+       $$txt .= <<EOS;
+; example public-inbox config snippet for "$name"
+; see public-inbox-config(5) manpage for more details:
+; https://public-inbox.org/public-inbox-config.html
+[publicinbox "$name"]
+       inboxdir = /path/to/top-level-inbox
+       ; note: public-inbox before v1.2.0 used "mainrepo"
+       ; instead of "inboxdir", both remain supported after 1.2
+       mainrepo = /path/to/top-level-inbox
+       url = https://example.com/$name/
+       url = http://example.onion/$name/
+EOS
+       for my $k (qw(address listid infourl)) {
+               defined(my $v = $ibx->{$k}) or next;
+               $$txt .= "\t$k = $_\n" for @$v;
+       }
+
+       for my $k (qw(filter newsgroup obfuscate replyto watchheader)) {
+               defined(my $v = $ibx->{$k}) or next;
+               $$txt .= "\t$k = $v\n";
+       }
+       $$txt .= "\tnntpmirror = $_\n" for (@{$ibx->nntp_url});
+
+       # note: this doesn't preserve cgitrc layout, since we parse cgitrc
+       # and drop the original structure
+       if (defined(my $cr = $ibx->{coderepo})) {
+               $$txt .= "\tcoderepo = $_\n" for @$cr;
+
+               my $pi_config = $ctx->{www}->{pi_config};
+               for my $cr_name (@$cr) {
+                       my $urls = $pi_config->{"coderepo.$cr_name.cgiturl"};
+                       my $path = "/path/to/$cr_name";
+                       $cr_name = dq_escape($cr_name);
+
+                       $$txt .= qq([coderepo "$cr_name"]\n);
+                       if ($urls && scalar(@$urls)) {
+                               $$txt .= "\t; ";
+                               $$txt .= join(" ||\n\t;\t", map {;
+                                       my $cpath = $path;
+                                       if ($path !~ m![a-z0-9_/\.\-]!i) {
+                                               $cpath = dq_escape($cpath);
+                                       }
+                                       qq(git clone $_ "$cpath");
+                               } @$urls);
+                               $$txt .= "\n";
+                       }
+                       $$txt .= "\tdir = $path\n";
+                       $$txt .= "\tcgiturl = https://example.com/";
+                       $$txt .= uri_escape_utf8($cr_name, URI_PATH)."\n";
+               }
+       }
+       1;
+}
 
 
-sub _default_text ($$$) {
-       my ($ctx, $key, $txt) = @_;
+sub _default_text ($$$$) {
+       my ($ctx, $key, $hdr, $txt) = @_;
+       return _colors_help($ctx, $txt) if $key eq 'color';
+       return inbox_config($ctx, $hdr, $txt) if $key eq 'config';
        return if $key ne 'help'; # TODO more keys?
 
        my $ibx = $ctx->{-inbox};
        return if $key ne 'help'; # TODO more keys?
 
        my $ibx = $ctx->{-inbox};
@@ -134,7 +239,7 @@ search
     in other search engines.
 
     We also support search prefixes to limit the scope of the
     in other search engines.
 
     We also support search prefixes to limit the scope of the
-    search to certain fields using prefixes.
+    search to certain fields.
 
     Prefixes supported in this installation include:
 
 
     Prefixes supported in this installation include:
 
@@ -142,11 +247,20 @@ EOF
                _srch_prefix($srch, $txt);
 
                $$txt .= <<EOF;
                _srch_prefix($srch, $txt);
 
                $$txt .= <<EOF;
+
+    Most prefixes are probabilistic, meaning they support stemming
+    and wildcards ('*').  Ranges (such as 'd:') and boolean prefixes
+    do not support stemming or wildcards.
     The upstream Xapian query parser documentation fully explains
     the query syntax:
 
        $QP_URL
 
     The upstream Xapian query parser documentation fully explains
     the query syntax:
 
        $QP_URL
 
+EOF
+       } # $srch
+       my $over = $ibx->over;
+       if ($over) {
+               $$txt .= <<EOF;
 message threading
 -----------------
 
 message threading
 -----------------
 
@@ -178,6 +292,10 @@ message threading
        $WIKI_URL/Atom_(standard)
        https://tools.ietf.org/html/rfc4287
 
        $WIKI_URL/Atom_(standard)
        https://tools.ietf.org/html/rfc4287
 
+      Atom Threading Extensions (RFC4685) is supported:
+
+       https://tools.ietf.org/html/rfc4685
+
     Finally, the gzipped mbox for a thread is available for
     downloading and importing into your favorite mail client:
 
     Finally, the gzipped mbox for a thread is available for
     downloading and importing into your favorite mail client:
 
@@ -188,6 +306,10 @@ message threading
 
        $WIKI_URL/Mbox
 
 
        $WIKI_URL/Mbox
 
+EOF
+       } # $over
+
+       $$txt .= <<EOF;
 contact
 -------
 
 contact
 -------
 
@@ -196,7 +318,6 @@ contact
 
 EOF
        # TODO: support admin contact info in ~/.public-inbox/config
 
 EOF
        # TODO: support admin contact info in ~/.public-inbox/config
-       }
        1;
 }
 
        1;
 }