]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/WWW.pm
treewide: kill problematic "$h->{k} //= do {" assignments
[public-inbox.git] / lib / PublicInbox / WWW.pm
index 6bae2190ac5f3f4d0e040fb787cc951e2402c87d..a282784a257fb523ca3ae6a59567628709ecd5a6 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2014-2020 all contributors <meta@public-inbox.org>
+# Copyright (C) 2014-2021 all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 #
 # Main web interface for mailing list archives
 # - Must not rely on static content
 # - UTF-8 is only for user-content, 7-bit US-ASCII for us
 package PublicInbox::WWW;
-use 5.010_001;
 use strict;
-use warnings;
-use bytes (); # only for bytes::length
+use v5.10.1;
 use PublicInbox::Config;
 use PublicInbox::Hval;
 use URI::Escape qw(uri_unescape);
@@ -32,9 +30,8 @@ our $ATTACH_RE = qr!([0-9][0-9\.]*)-($PublicInbox::Hval::FN)!;
 our $OID_RE = qr![a-f0-9]{7,}!;
 
 sub new {
-       my ($class, $pi_config) = @_;
-       $pi_config ||= PublicInbox::Config->new;
-       bless { pi_config => $pi_config }, $class;
+       my ($class, $pi_cfg) = @_;
+       bless { pi_cfg => $pi_cfg // PublicInbox::Config->new }, $class;
 }
 
 # backwards compatibility, do not use
@@ -51,10 +48,9 @@ sub call {
        %{$ctx->{qp}} = map {
                utf8::decode($_);
                tr/+/ /;
-               my ($k, $v) = split('=', $_, 2);
-               $v = uri_unescape($v // '');
+               my ($k, $v) = split(/=/, $_, 2);
                # none of the keys we care about will need escaping
-               $k => $v;
+               ($k // '', uri_unescape($v // ''))
        } split(/[&;]+/, $env->{QUERY_STRING});
 
        my $path_info = path_info_raw($env);
@@ -135,7 +131,8 @@ sub call {
        # convenience redirects order matters
        } elsif ($path_info =~ m!$INBOX_RE/([^/]{2,})\z!o) {
                r301($ctx, $1, $2);
-
+       } elsif ($path_info =~ m!\A/\+/([a-zA-Z0-9_\-\.]+)\.css\z!) {
+               get_css($ctx, undef, $1); # for WwwListing
        } else {
                legacy_redirects($ctx, $path_info);
        }
@@ -169,25 +166,17 @@ sub preload {
                eval "require PublicInbox::$_;";
        }
        if (ref($self)) {
-               my $pi_config = $self->{pi_config};
-               if (defined($pi_config->{'publicinbox.cgitrc'})) {
-                       $pi_config->limiter('-cgit');
+               my $pi_cfg = $self->{pi_cfg};
+               if (defined($pi_cfg->{'publicinbox.cgitrc'})) {
+                       $pi_cfg->limiter('-cgit');
                }
+               $pi_cfg->ALL and require PublicInbox::Isearch;
                $self->cgit;
                $self->stylesheets_prepare($_) for ('', '../', '../../');
                $self->news_www;
-               $pi_config->each_inbox(\&preload_inbox);
        }
 }
 
-sub preload_inbox {
-       my $ibx = shift;
-       $ibx->altid_map;
-       $ibx->cloneurl;
-       $ibx->description;
-       $ibx->base_url;
-}
-
 # private functions below
 
 sub r404 {
@@ -210,8 +199,8 @@ sub news_cgit_fallback ($) {
 # returns undef if valid, array ref response if invalid
 sub invalid_inbox ($$) {
        my ($ctx, $inbox) = @_;
-       my $ibx = $ctx->{www}->{pi_config}->lookup_name($inbox) //
-                       $ctx->{www}->{pi_config}->lookup_ei($inbox);
+       my $ibx = $ctx->{www}->{pi_cfg}->lookup_name($inbox) //
+                       $ctx->{www}->{pi_cfg}->lookup_ei($inbox);
        if (defined $ibx) {
                $ctx->{ibx} = $ibx;
                return;
@@ -273,7 +262,7 @@ sub get_index {
 sub get_mid_txt {
        my ($ctx) = @_;
        require PublicInbox::Mbox;
-       PublicInbox::Mbox::emit_raw($ctx) || r404($ctx);
+       PublicInbox::Mbox::emit_raw($ctx) || r(404);
 }
 
 # /$INBOX/$MESSAGE_ID/                   -> HTML content (short quotes)
@@ -310,7 +299,7 @@ sub get_text {
 sub get_vcs_object ($$$;$) {
        my ($ctx, $inbox, $oid, $filename) = @_;
        my $r404 = invalid_inbox($ctx, $inbox);
-       return $r404 if $r404;
+       return $r404 if $r404 || !$ctx->{www}->{pi_cfg}->repo_objs($ctx->{ibx});
        require PublicInbox::ViewVCS;
        PublicInbox::ViewVCS::show($ctx, $oid, $filename);
 }
@@ -479,20 +468,20 @@ sub serve_mbox_range {
 
 sub news_www {
        my ($self) = @_;
-       $self->{news_www} ||= do {
+       $self->{news_www} //= do {
                require PublicInbox::NewsWWW;
-               PublicInbox::NewsWWW->new($self->{pi_config});
+               PublicInbox::NewsWWW->new($self->{pi_cfg});
        }
 }
 
 sub cgit {
        my ($self) = @_;
-       $self->{cgit} ||= do {
-               my $pi_config = $self->{pi_config};
+       $self->{cgit} //= do {
+               my $pi_cfg = $self->{pi_cfg};
 
-               if (defined($pi_config->{'publicinbox.cgitrc'})) {
+               if (defined($pi_cfg->{'publicinbox.cgitrc'})) {
                        require PublicInbox::Cgit;
-                       PublicInbox::Cgit->new($pi_config);
+                       PublicInbox::Cgit->new($pi_cfg);
                } else {
                        require Plack::Util;
                        Plack::Util::inline_object(call => sub { r404() });
@@ -506,7 +495,7 @@ sub get_inbox_manifest ($$$) {
        my $r404 = invalid_inbox($ctx, $inbox);
        return $r404 if $r404;
        require PublicInbox::ManifestJsGz;
-       PublicInbox::ManifestJsGz->response($ctx);
+       PublicInbox::ManifestJsGz::per_inbox($ctx);
 }
 
 sub get_attach {
@@ -538,7 +527,7 @@ sub stylesheets_prepare ($$) {
        } || sub { $_[0] };
 
        my $css_map = {};
-       my $stylesheets = $self->{pi_config}->{css} || [];
+       my $stylesheets = $self->{pi_cfg}->{css} || [];
        my $links = [];
        my $inline_ok = 1;
 
@@ -629,24 +618,25 @@ sub style {
        };
 }
 
-# /$INBOX/$KEY.css endpoint
+# /$INBOX/$KEY.css and /+/$KEY.css endpoints
 # CSS is configured globally for all inboxes, but we access them on
 # a per-inbox basis.  This allows administrators to setup per-inbox
 # static routes to intercept the request before it hits PSGI
+# inbox == undef => top-level WwwListing
 sub get_css ($$$) {
        my ($ctx, $inbox, $key) = @_;
-       my $r404 = invalid_inbox($ctx, $inbox);
+       my $r404 = defined($inbox) ? invalid_inbox($ctx, $inbox) : undef;
        return $r404 if $r404;
        my $self = $ctx->{www};
-       my $css_map = $self->{-css_map} || stylesheets_prepare($self, '');
+       my $css_map = $self->{-css_map} ||
+               stylesheets_prepare($self, defined($inbox) ? '' : '+/');
        my $css = $css_map->{$key};
-       if (!defined($css) && $key eq 'userContent') {
+       if (!defined($css) && defined($inbox) && $key eq 'userContent') {
                my $env = $ctx->{env};
                $css = PublicInbox::UserContent::sample($ctx->{ibx}, $env);
        }
        defined $css or return r404();
-       my $h = [ 'Content-Length', bytes::length($css),
-               'Content-Type', 'text/css' ];
+       my $h = [ 'Content-Length', length($css), 'Content-Type', 'text/css' ];
        PublicInbox::GitHTTPBackend::cache_one_year($h);
        [ 200, $h, [ $css ] ];
 }
@@ -655,9 +645,19 @@ sub get_description {
        my ($ctx, $inbox) = @_;
        invalid_inbox($ctx, $inbox) || do {
                my $d = $ctx->{ibx}->description . "\n";
-               [ 200, [ 'Content-Length', bytes::length($d),
+               utf8::encode($d);
+               [ 200, [ 'Content-Length', length($d),
                        'Content-Type', 'text/plain' ], [ $d ] ];
        };
 }
 
+sub event_step { # called via requeue
+       my ($self) = @_;
+       # gzf = PublicInbox::GzipFilter == $ctx
+       my $gzf = shift(@{$self->{-low_prio_q}}) // return;
+       PublicInbox::DS::requeue($self) if scalar(@{$self->{-low_prio_q}});
+       my $http = $gzf->{env}->{'psgix.io'}; # PublicInbox::HTTP
+       $http->next_step($gzf->can('async_next'));
+}
+
 1;