]> Sergey Matveev's repositories - public-inbox.git/blob - lib/PublicInbox/WwwText.pm
b5874cf6bad534a20daf060452884b463628440a
[public-inbox.git] / lib / PublicInbox / WwwText.pm
1 # Copyright (C) 2016-2018 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3
4 # used for displaying help texts and other non-mail content
5 package PublicInbox::WwwText;
6 use strict;
7 use warnings;
8 use PublicInbox::Linkify;
9 use PublicInbox::WwwStream;
10 use PublicInbox::Hval qw(ascii_html);
11 our $QP_URL = 'https://xapian.org/docs/queryparser.html';
12 our $WIKI_URL = 'https://en.wikipedia.org/wiki';
13
14 # /$INBOX/_/text/$KEY/ # KEY may contain slashes
15 # For now, "help" is the only supported $KEY
16 sub get_text {
17         my ($ctx, $key) = @_;
18         my $code = 200;
19
20         $key = 'help' if !defined $key; # this 302s to _/text/help/
21
22         # get the raw text the same way we get mboxrds
23         my $raw = ($key =~ s!/raw\z!!);
24         my $have_tslash = ($key =~ s!/\z!!) if !$raw;
25
26         my $txt = '';
27         if (!_default_text($ctx, $key, \$txt)) {
28                 $code = 404;
29                 $txt = "404 Not Found ($key)\n";
30         }
31         if ($raw) {
32                 return [ $code, [ 'Content-Type', 'text/plain',
33                                   'Content-Length', bytes::length($txt) ],
34                         [ $txt ] ]
35         }
36
37         # enforce trailing slash for "wget -r" compatibility
38         if (!$have_tslash && $code == 200) {
39                 my $url = $ctx->{-inbox}->base_url($ctx->{env});
40                 $url .= "_/text/$key/";
41
42                 return [ 302, [ 'Content-Type', 'text/plain',
43                                 'Location', $url ],
44                         [ "Redirecting to $url\n" ] ];
45         }
46
47         # Follow git commit message conventions,
48         # first line is the Subject/title
49         my ($title) = ($txt =~ /\A([^\n]*)/s);
50         _do_linkify($txt);
51         $ctx->{-title_html} = ascii_html($title);
52
53         my $nslash = ($key =~ tr!/!/!);
54         $ctx->{-upfx} = '../../../' . ('../' x $nslash);
55
56         PublicInbox::WwwStream->response($ctx, $code, sub {
57                 my ($nr, undef) = @_;
58                 $nr == 1 ? '<pre>'.$txt.'</pre>' : undef
59         });
60 }
61
62 sub _do_linkify {
63         my $l = PublicInbox::Linkify->new;
64         $_[0] = $l->linkify_2(ascii_html($l->linkify_1($_[0])));
65 }
66
67 sub _srch_prefix ($$) {
68         my ($srch, $txt) = @_;
69         my $pad = 0;
70         my $htxt = '';
71         my $help = $srch->help;
72         my $i;
73         for ($i = 0; $i < @$help; $i += 2) {
74                 my $pfx = $help->[$i];
75                 my $n = length($pfx);
76                 $pad = $n if $n > $pad;
77                 $htxt .= $pfx . "\0";
78                 $htxt .= $help->[$i + 1];
79                 $htxt .= "\f\n";
80         }
81         $pad += 2;
82         my $padding = ' ' x ($pad + 8);
83         $htxt =~ s/^/$padding/gms;
84         $htxt =~ s/^$padding(\S+)\0/"        $1".
85                                 (' ' x ($pad - length($1)))/egms;
86         $htxt =~ s/\f\n/\n/gs;
87         $$txt .= $htxt;
88         1;
89 }
90
91
92 sub _default_text ($$$) {
93         my ($ctx, $key, $txt) = @_;
94         return if $key ne 'help'; # TODO more keys?
95
96         my $ibx = $ctx->{-inbox};
97         my $base_url = $ibx->base_url($ctx->{env});
98         $$txt .= "public-inbox help for $base_url\n";
99         $$txt .= <<EOF;
100
101 overview
102 --------
103
104     public-inbox uses Message-ID identifiers in URLs.
105     One may look up messages by substituting Message-IDs
106     (without the leading '<' or trailing '>') into the URL.
107     Forward slash ('/') characters in the Message-IDs
108     need to be escaped as "%2F" (without quotes).
109
110     Thus, it is possible to retrieve any message by its
111     Message-ID by going to:
112
113         $base_url<Message-ID>/
114
115         (without the '<' or '>')
116
117     Message-IDs are described at:
118
119         $WIKI_URL/Message-ID
120
121 EOF
122
123         # n.b. we use the Xapian DB for any regeneratable,
124         # order-of-arrival-independent data.
125         my $srch = $ibx->search;
126         if ($srch) {
127                 $$txt .= <<EOF;
128 search
129 ------
130
131     This public-inbox has search functionality provided by Xapian.
132
133     It supports typical AND, OR, NOT, '+', '-' queries present
134     in other search engines.
135
136     We also support search prefixes to limit the scope of the
137     search to certain fields.
138
139     Prefixes supported in this installation include:
140
141 EOF
142                 _srch_prefix($srch, $txt);
143
144                 $$txt .= <<EOF;
145
146     Most prefixes are probabilistic, meaning they support stemming
147     and wildcards ('*').  Ranges (such as 'd:') and boolean prefixes
148     do not support stemming or wildcards.
149     The upstream Xapian query parser documentation fully explains
150     the query syntax:
151
152         $QP_URL
153
154 message threading
155 -----------------
156
157     Message threading is enabled for this public-inbox,
158     additional endpoints for message threads are available:
159
160     * $base_url<Message-ID>/T/#u
161
162       Loads the thread belonging to the given <Message-ID>
163       in flat chronological order.  The "#u" anchor
164       focuses the browser on the given <Message-ID>.
165
166     * $base_url<Message-ID>/t/#u
167
168       Loads the thread belonging to the given <Message-ID>
169       in threaded order with nesting.  For deep threads,
170       this requires a wide display or horizontal scrolling.
171
172     Both of these HTML endpoints are suitable for offline reading
173     using the thread overview at the bottom of each page.
174
175     Users of feed readers may follow a particular thread using:
176
177     * $base_url<Message-ID>/t.atom
178
179       Which loads the thread in Atom Syndication Standard
180       described at Wikipedia and RFC4287:
181
182         $WIKI_URL/Atom_(standard)
183         https://tools.ietf.org/html/rfc4287
184
185       Atom Threading Extensions (RFC4685) is supported:
186
187         https://tools.ietf.org/html/rfc4685
188
189     Finally, the gzipped mbox for a thread is available for
190     downloading and importing into your favorite mail client:
191
192     * $base_url<Message-ID>/t.mbox.gz
193
194     We use the mboxrd variant of the mbox format described
195     at:
196
197         $WIKI_URL/Mbox
198
199 contact
200 -------
201
202     This help text is maintained by public-inbox developers
203     reachable via plain-text email at: meta\@public-inbox.org
204
205 EOF
206         # TODO: support admin contact info in ~/.public-inbox/config
207         }
208         1;
209 }
210
211 1;