X-Git-Url: https://git.ladys.computer/Gitweb/blobdiff_plain/0e8c2e1d97cde0d2549466c258a5b065b80fd03a68d75a5d176626fb725d3ff3..d1d7324283b1bcee78209f9e13495a75317797741008039523d5adaf66997dd0:/gitweb.perl diff --git a/gitweb.perl b/gitweb.perl index 3398de3..66d8628 100755 --- a/gitweb.perl +++ b/gitweb.perl @@ -1082,7 +1082,16 @@ sub evaluate_and_validate_params { if (length($searchtext) < 2) { die_error(403, "At least two characters are required for search parameter"); } - $search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext; + if ($search_use_regexp) { + $search_regexp = $searchtext; + if (!eval { qr/$search_regexp/; 1; }) { + (my $error = $@) =~ s/ at \S+ line \d+.*\n?//; + die_error(400, "Invalid search regexp '$search_regexp'", + esc_html($error)); + } + } else { + $search_regexp = quotemeta $searchtext; + } } } @@ -1743,20 +1752,61 @@ sub esc_html_hl_regions { return $out; } -# highlight match (if any), and escape HTML -sub esc_html_match_hl { +# return positions of beginning and end of each match +sub matchpos_list { my ($str, $regexp) = @_; - return esc_html($str) unless defined $regexp; + return unless (defined $str && defined $regexp); my @matches; while ($str =~ /$regexp/g) { push @matches, [$-[0], $+[0]]; } + return @matches; +} + +# highlight match (if any), and escape HTML +sub esc_html_match_hl { + my ($str, $regexp) = @_; + return esc_html($str) unless defined $regexp; + + my @matches = matchpos_list($str, $regexp); return esc_html($str) unless @matches; return esc_html_hl_regions($str, 'match', @matches); } + +# highlight match (if any) of shortened string, and escape HTML +sub esc_html_match_hl_chopped { + my ($str, $chopped, $regexp) = @_; + return esc_html_match_hl($str, $regexp) unless defined $chopped; + + my @matches = matchpos_list($str, $regexp); + return esc_html($chopped) unless @matches; + + # filter matches so that we mark chopped string + my $tail = "... "; # see chop_str + unless ($chopped =~ s/\Q$tail\E$//) { + $tail = ''; + } + my $chop_len = length($chopped); + my $tail_len = length($tail); + my @filtered; + + for my $m (@matches) { + if ($m->[0] > $chop_len) { + push @filtered, [ $chop_len, $chop_len + $tail_len ] if ($tail_len > 0); + last; + } elsif ($m->[1] > $chop_len) { + push @filtered, [ $m->[0], $chop_len + $tail_len ]; + last; + } + push @filtered, $m; + } + + return esc_html_hl_regions($chopped . $tail, 'match', @filtered); +} + ## ---------------------------------------------------------------------- ## functions returning short strings @@ -5207,7 +5257,7 @@ sub git_patchset_body { # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sub git_project_search_form { - my ($searchtext, $search_use_regexp); + my ($searchtext, $search_use_regexp) = @_; my $limit = ''; if ($project_filter) { @@ -5401,10 +5451,17 @@ sub git_project_list_rows { print "\n"; } print "