]> Sergey Matveev's repositories - public-inbox.git/commitdiff
searchview: retry queries if uri_unescape-able
authorEric Wong <e@80x24.org>
Tue, 23 May 2017 23:07:24 +0000 (23:07 +0000)
committerEric Wong <e@80x24.org>
Tue, 23 May 2017 23:09:51 +0000 (23:09 +0000)
It is possible to have double-escaped queries when copy and
pasting into browsers, so try to help users work around this
common error by automatically retrying after unescaping once.

Of course, we must inform the user when doing this results in
success, in case they really meant to search for a
double-escaped term which resulted in nothing.

Reported-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
  https://public-inbox.org/meta/CACBZZX5Gnow08r=0A1J_kt3a=zpGyMfvsqu8nAN7kacNnDm+dg@mail.gmail.com/

lib/PublicInbox/SearchView.pm

index 42bc648260f01f7b9259a8b16ca786660480db0e..f92790f4a957472f6c79ede6bd0e8add9bb4178f 100644 (file)
@@ -5,11 +5,12 @@
 package PublicInbox::SearchView;
 use strict;
 use warnings;
 package PublicInbox::SearchView;
 use strict;
 use warnings;
+use URI::Escape qw(uri_unescape uri_escape);
 use PublicInbox::SearchMsg;
 use PublicInbox::Hval qw/ascii_html/;
 use PublicInbox::View;
 use PublicInbox::WwwAtomStream;
 use PublicInbox::SearchMsg;
 use PublicInbox::Hval qw/ascii_html/;
 use PublicInbox::View;
 use PublicInbox::WwwAtomStream;
-use PublicInbox::MID qw(mid2path mid_mime mid_clean mid_escape);
+use PublicInbox::MID qw(mid2path mid_mime mid_clean mid_escape MID_ESC);
 use PublicInbox::MIME;
 require PublicInbox::Git;
 require PublicInbox::SearchThread;
 use PublicInbox::MIME;
 require PublicInbox::Git;
 require PublicInbox::SearchThread;
@@ -29,19 +30,27 @@ sub sres_top_html {
                mset => 1,
                relevance => $q->{r},
        };
                mset => 1,
                relevance => $q->{r},
        };
-       my ($mset, $total);
+       my ($mset, $total, $err, $cb);
+retry:
        eval {
                $mset = $ctx->{srch}->query($q->{'q'}, $opts);
                $total = $mset->get_matches_estimated;
        };
        eval {
                $mset = $ctx->{srch}->query($q->{'q'}, $opts);
                $total = $mset->get_matches_estimated;
        };
-       my $err = $@;
+       $err = $@;
        ctx_prepare($q, $ctx);
        ctx_prepare($q, $ctx);
-       my $cb;
        if ($err) {
                $code = 400;
                $ctx->{-html_tip} = '<pre>'.err_txt($ctx, $err).'</pre><hr>';
                $cb = *noop;
        } elsif ($total == 0) {
        if ($err) {
                $code = 400;
                $ctx->{-html_tip} = '<pre>'.err_txt($ctx, $err).'</pre><hr>';
                $cb = *noop;
        } elsif ($total == 0) {
+               if (defined($ctx->{-uxs_retried})) {
+                       # undo retry damage:
+                       $q->{'q'} = $ctx->{-uxs_retried};
+               } elsif (index($q->{'q'}, '%') >= 0) {
+                       $ctx->{-uxs_retried} = $q->{'q'};
+                       $q->{'q'} = uri_unescape($q->{'q'});
+                       goto retry;
+               }
                $code = 404;
                $ctx->{-html_tip} = "<pre>\n[No results found]</pre><hr>";
                $cb = *noop;
                $code = 404;
                $ctx->{-html_tip} = "<pre>\n[No results found]</pre><hr>";
                $cb = *noop;
@@ -49,7 +58,7 @@ sub sres_top_html {
                my $x = $q->{x};
                return adump($_[0], $mset, $q, $ctx) if $x eq 'A';
 
                my $x = $q->{x};
                return adump($_[0], $mset, $q, $ctx) if $x eq 'A';
 
-               $ctx->{-html_tip} = search_nav_top($mset, $q) . "\n\n";
+               $ctx->{-html_tip} = search_nav_top($mset, $q, $ctx) . "\n\n";
                if ($x eq 't') {
                        $cb = mset_thread($ctx, $mset, $q);
                } else {
                if ($x eq 't') {
                        $cb = mset_thread($ctx, $mset, $q);
                } else {
@@ -113,9 +122,22 @@ sub err_txt {
 }
 
 sub search_nav_top {
 }
 
 sub search_nav_top {
-       my ($mset, $q) = @_;
+       my ($mset, $q, $ctx) = @_;
+
+       my $rv = '<pre>';
+       my $initial_q = $ctx->{-uxs_retried};
+       if (defined $initial_q) {
+               my $rewritten = $q->{'q'};
+               utf8::decode($initial_q);
+               utf8::decode($rewritten);
+               $initial_q = ascii_html($initial_q);
+               $rewritten = ascii_html($rewritten);
+               $rv .= " Warning: Initial query:\n <b>$initial_q</b>\n";
+               $rv .= " returned no results, used:\n";
+               $rv .= " <b>$rewritten</b>\n instead\n\n";
+       }
 
 
-       my $rv = "<pre>Search results ordered by [";
+       $rv .= 'Search results ordered by [';
        if ($q->{r}) {
                my $d = $q->qs_html(r => 0);
                $rv .= qq{<a\nhref="?$d">date</a>|<b>relevance</b>};
        if ($q->{r}) {
                my $d = $q->qs_html(r => 0);
                $rv .= qq{<a\nhref="?$d">date</a>|<b>relevance</b>};