diff options
Diffstat (limited to 'lib/PublicInbox/WWW.pm')
-rw-r--r-- | lib/PublicInbox/WWW.pm | 91 |
1 files changed, 66 insertions, 25 deletions
diff --git a/lib/PublicInbox/WWW.pm b/lib/PublicInbox/WWW.pm index 1df5572d..289599b8 100644 --- a/lib/PublicInbox/WWW.pm +++ b/lib/PublicInbox/WWW.pm @@ -14,6 +14,7 @@ package PublicInbox::WWW; use strict; use v5.10.1; use PublicInbox::Config; +use PublicInbox::Git; use PublicInbox::Hval; use URI::Escape qw(uri_unescape); use PublicInbox::MID qw(mid_escape); @@ -25,7 +26,7 @@ use PublicInbox::Eml; # TODO: consider a routing tree now that we have more endpoints: our $INBOX_RE = qr!\A/([\w\-][\w\.\-\+]*)!; our $MID_RE = qr!([^/]+)!; -our $END_RE = qr!(T/|t/|t\.mbox(?:\.gz)?|t\.atom|raw|)!; +our $END_RE = qr!(T/|t/|d/|t\.mbox(?:\.gz)?|t\.atom|raw|)!; our $ATTACH_RE = qr!([0-9][0-9\.]*)-($PublicInbox::Hval::FN)!; our $OID_RE = qr![a-f0-9]{7,}!; @@ -45,14 +46,21 @@ sub call { my $ctx = { env => $env, www => $self }; # we don't care about multi-value - %{$ctx->{qp}} = map { - utf8::decode($_); - tr/+/ /; - my ($k, $v) = split(/=/, $_, 2); - # none of the keys we care about will need escaping - ($k // '', uri_unescape($v // '')) - } split(/[&;]+/, $env->{QUERY_STRING}); - + # '0' isn't a QUERY_STRING we care about + if (my $qs = $env->{QUERY_STRING}) { + utf8::decode($qs); + $qs =~ tr/+/ /; + %{$ctx->{qp}} = map { + # we only use single-char query param keys + if (s/\A([A-Za-z])=//) { + $1 => uri_unescape($_) + } elsif (/\A[a-z]\z/) { # some boolean options + $_ => '' + } else { + () # ignored + } + } split(/[&;]+/, $qs); + } my $path_info = path_info_raw($env); my $method = $env->{REQUEST_METHOD}; @@ -68,7 +76,9 @@ sub call { my ($idx, $fn) = ($3, $4); return invalid_inbox_mid($ctx, $1, $2) || get_attach($ctx, $idx, $fn); - } elsif ($path_info =~ m!$INBOX_RE/!o) { + } elsif ($path_info =~ m!$INBOX_RE/$MID_RE/\z!o) { + return invalid_inbox_mid($ctx, $1, $2) || mbox_results($ctx); + } elsif ($path_info =~ m!$INBOX_RE/\z!o) { return invalid_inbox($ctx, $1) || mbox_results($ctx); } } @@ -91,6 +101,9 @@ sub call { invalid_inbox($ctx, $1) || get_atom($ctx); } elsif ($path_info =~ m!$INBOX_RE/new\.html\z!o) { invalid_inbox($ctx, $1) || get_new($ctx); + } elsif ($path_info =~ + m!$INBOX_RE/topics_(new|active)\.(atom|html)\z!o) { + get_topics($ctx, $1, $2, $3); } elsif ($path_info =~ m!$INBOX_RE/description\z!o) { get_description($ctx, $1); } elsif ($path_info =~ m!$INBOX_RE/(?:(?:git/)?([0-9]+)(?:\.git)?/)? @@ -176,6 +189,7 @@ sub preload { } $pi_cfg->ALL and require PublicInbox::Isearch; $self->cgit; + $self->coderepo; $self->stylesheets_prepare($_) for ('', '../', '../../'); $self->news_www; } @@ -194,10 +208,20 @@ sub r404 { sub news_cgit_fallback ($) { my ($ctx) = @_; - my $www = $ctx->{www}; - my $env = $ctx->{env}; - my $res = $www->news_www->call($env); - $res->[0] == 404 ? $www->cgit->call($env) : $res; + my $res = $ctx->{www}->news_www->call($ctx->{env}); + + $res->[0] == 404 and ($ctx->{www}->{cgit_fallback} //= do { + my $c = $ctx->{www}->{pi_cfg}->{'publicinbox.cgit'} // 'first'; + $c ne 'first' # `fallback' and `rewrite' => true + } // 0) and $res = $ctx->{www}->coderepo->srv($ctx); + + ref($res) eq 'ARRAY' && $res->[0] == 404 and + $res = $ctx->{www}->cgit->call($ctx->{env}, $ctx); + + ref($res) eq 'ARRAY' && $res->[0] == 404 && + !$ctx->{www}->{cgit_fallback} and + $res = $ctx->{www}->coderepo->srv($ctx); + $res; } # returns undef if valid, array ref response if invalid @@ -250,6 +274,13 @@ sub get_new { PublicInbox::Feed::new_html($ctx); } +# /$INBOX/topics_(new|active).(html|atom) +sub get_topics { + my ($ctx, $ibx_name, $category, $type) = @_; + require PublicInbox::WwwTopics; + PublicInbox::WwwTopics::response($ctx, $ibx_name, $category, $type); +} + # /$INBOX/?r=$GIT_COMMIT -> HTML only sub get_index { my ($ctx) = @_; @@ -318,11 +349,12 @@ sub get_altid_dump { } sub need { - my ($ctx, $extra) = @_; + my ($ctx, $extra, $upref) = @_; require PublicInbox::WwwStream; + $upref //= '../'; PublicInbox::WwwStream::html_oneshot($ctx, 501, <<EOF); <pre>$extra is not available for this public-inbox -<a\nhref="../">Return to index</a></pre> +<a\nhref="$upref">Return to index</a></pre> EOF } @@ -442,6 +474,10 @@ sub msg_page { # legacy, but no redirect for compatibility: 'f/' eq $e and return get_mid_html($ctx); + if ($e eq 'd/') { + require PublicInbox::View; + return PublicInbox::View::diff_msg($ctx); + } r404($ctx); } @@ -481,16 +517,21 @@ sub news_www { sub cgit { my ($self) = @_; - $self->{cgit} //= do { - my $pi_cfg = $self->{pi_cfg}; - - if (defined($pi_cfg->{'publicinbox.cgitrc'})) { + $self->{cgit} //= + (defined($self->{pi_cfg}->{'publicinbox.cgitrc'}) ? do { require PublicInbox::Cgit; - PublicInbox::Cgit->new($pi_cfg); - } else { + PublicInbox::Cgit->new($self->{pi_cfg}); + } : undef) // do { require Plack::Util; Plack::Util::inline_object(call => sub { r404() }); - } + }; +} + +sub coderepo { + my ($self) = @_; + $self->{coderepo} //= do { + require PublicInbox::WwwCoderepo; + PublicInbox::WwwCoderepo->new($self->{pi_cfg}); } } @@ -559,9 +600,9 @@ sub stylesheets_prepare ($$) { next; }; my $ctime = 0; - my $local = do { local $/; <$fh> }; + my $local = PublicInbox::IO::read_all $fh; # sets _ if ($local =~ /\S/) { - $ctime = sprintf('%x',(stat($fh))[10]); + $ctime = sprintf('%x',(stat(_))[10]); $local = $mini->($local); } |