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