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