]> Lady’s Gitweb - Gitweb/blobdiff - gitweb.perl
gitweb: Fix handling of whitespace in generated links
[Gitweb] / gitweb.perl
index 83bfdb3d2698a45b0ecf9e97397675ed7db2235be58fd6193d4921d16f72ddd7..0d38bd1fd0596d620673048123e174a75c5be827795aced5035fc1c0351adb0a 100755 (executable)
@@ -612,6 +612,14 @@ sub filter_snapshot_fmts {
                !$known_snapshot_formats{$_}{'disabled'}} @fmts;
 }
 
                !$known_snapshot_formats{$_}{'disabled'}} @fmts;
 }
 
+# If it is set to code reference, it is code that it is to be run once per
+# request, allowing updating configurations that change with each request,
+# while running other code in config file only once.
+#
+# Otherwise, if it is false then gitweb would process config file only once;
+# if it is true then gitweb config would be run for each request.
+our $per_request_config = 1;
+
 our ($GITWEB_CONFIG, $GITWEB_CONFIG_SYSTEM);
 sub evaluate_gitweb_config {
        our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
 our ($GITWEB_CONFIG, $GITWEB_CONFIG_SYSTEM);
 sub evaluate_gitweb_config {
        our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
@@ -1082,12 +1090,22 @@ sub reset_timer {
        our $number_of_git_cmds = 0;
 }
 
        our $number_of_git_cmds = 0;
 }
 
+our $first_request = 1;
 sub run_request {
        reset_timer();
 
        evaluate_uri();
 sub run_request {
        reset_timer();
 
        evaluate_uri();
-       evaluate_gitweb_config();
-       evaluate_git_version();
+       if ($first_request) {
+               evaluate_gitweb_config();
+               evaluate_git_version();
+       }
+       if ($per_request_config) {
+               if (ref($per_request_config) eq 'CODE') {
+                       $per_request_config->();
+               } elsif (!$first_request) {
+                       evaluate_gitweb_config();
+               }
+       }
        check_loadavg();
 
        # $projectroot and $projects_list might be set in gitweb config file
        check_loadavg();
 
        # $projectroot and $projects_list might be set in gitweb config file
@@ -1141,6 +1159,7 @@ sub evaluate_argv {
 sub run {
        evaluate_argv();
 
 sub run {
        evaluate_argv();
 
+       $first_request = 1;
        $pre_listen_hook->()
                if $pre_listen_hook;
 
        $pre_listen_hook->()
                if $pre_listen_hook;
 
@@ -1153,6 +1172,7 @@ sub run {
 
                $post_dispatch_hook->()
                        if $post_dispatch_hook;
 
                $post_dispatch_hook->()
                        if $post_dispatch_hook;
+               $first_request = 0;
 
                last REQUEST if ($is_last_request->());
        }
 
                last REQUEST if ($is_last_request->());
        }
@@ -1211,7 +1231,7 @@ sub href {
                $href =~ s,/$,,;
 
                # Then add the project name, if present
                $href =~ s,/$,,;
 
                # Then add the project name, if present
-               $href .= "/".esc_url($params{'project'});
+               $href .= "/".esc_path_info($params{'project'});
                delete $params{'project'};
 
                # since we destructively absorb parameters, we keep this
                delete $params{'project'};
 
                # since we destructively absorb parameters, we keep this
@@ -1221,7 +1241,8 @@ sub href {
                # Summary just uses the project path URL, any other action is
                # added to the URL
                if (defined $params{'action'}) {
                # Summary just uses the project path URL, any other action is
                # added to the URL
                if (defined $params{'action'}) {
-                       $href .= "/".esc_url($params{'action'}) unless $params{'action'} eq 'summary';
+                       $href .= "/".esc_path_info($params{'action'})
+                               unless $params{'action'} eq 'summary';
                        delete $params{'action'};
                }
 
                        delete $params{'action'};
                }
 
@@ -1231,13 +1252,13 @@ sub href {
                        || $params{'hash_parent'} || $params{'hash'});
                if (defined $params{'hash_base'}) {
                        if (defined $params{'hash_parent_base'}) {
                        || $params{'hash_parent'} || $params{'hash'});
                if (defined $params{'hash_base'}) {
                        if (defined $params{'hash_parent_base'}) {
-                               $href .= esc_url($params{'hash_parent_base'});
+                               $href .= esc_path_info($params{'hash_parent_base'});
                                # skip the file_parent if it's the same as the file_name
                                if (defined $params{'file_parent'}) {
                                        if (defined $params{'file_name'} && $params{'file_parent'} eq $params{'file_name'}) {
                                                delete $params{'file_parent'};
                                        } elsif ($params{'file_parent'} !~ /\.\./) {
                                # skip the file_parent if it's the same as the file_name
                                if (defined $params{'file_parent'}) {
                                        if (defined $params{'file_name'} && $params{'file_parent'} eq $params{'file_name'}) {
                                                delete $params{'file_parent'};
                                        } elsif ($params{'file_parent'} !~ /\.\./) {
-                                               $href .= ":/".esc_url($params{'file_parent'});
+                                               $href .= ":/".esc_path_info($params{'file_parent'});
                                                delete $params{'file_parent'};
                                        }
                                }
                                                delete $params{'file_parent'};
                                        }
                                }
@@ -1245,19 +1266,19 @@ sub href {
                                delete $params{'hash_parent'};
                                delete $params{'hash_parent_base'};
                        } elsif (defined $params{'hash_parent'}) {
                                delete $params{'hash_parent'};
                                delete $params{'hash_parent_base'};
                        } elsif (defined $params{'hash_parent'}) {
-                               $href .= esc_url($params{'hash_parent'}). "..";
+                               $href .= esc_path_info($params{'hash_parent'}). "..";
                                delete $params{'hash_parent'};
                        }
 
                                delete $params{'hash_parent'};
                        }
 
-                       $href .= esc_url($params{'hash_base'});
+                       $href .= esc_path_info($params{'hash_base'});
                        if (defined $params{'file_name'} && $params{'file_name'} !~ /\.\./) {
                        if (defined $params{'file_name'} && $params{'file_name'} !~ /\.\./) {
-                               $href .= ":/".esc_url($params{'file_name'});
+                               $href .= ":/".esc_path_info($params{'file_name'});
                                delete $params{'file_name'};
                        }
                        delete $params{'hash'};
                        delete $params{'hash_base'};
                } elsif (defined $params{'hash'}) {
                                delete $params{'file_name'};
                        }
                        delete $params{'hash'};
                        delete $params{'hash_base'};
                } elsif (defined $params{'hash'}) {
-                       $href .= esc_url($params{'hash'});
+                       $href .= esc_path_info($params{'hash'});
                        delete $params{'hash'};
                }
 
                        delete $params{'hash'};
                }
 
@@ -1290,6 +1311,9 @@ sub href {
        }
        $href .= "?" . join(';', @result) if scalar @result;
 
        }
        $href .= "?" . join(';', @result) if scalar @result;
 
+       # final transformation: trailing spaces must be escaped (URI-encoded)
+       $href =~ s/(\s+)$/CGI::escape($1)/e;
+
        return $href;
 }
 
        return $href;
 }
 
@@ -1372,6 +1396,17 @@ sub esc_param {
        return $str;
 }
 
        return $str;
 }
 
+# the quoting rules for path_info fragment are slightly different
+sub esc_path_info {
+       my $str = shift;
+       return undef unless defined $str;
+
+       # path_info doesn't treat '+' as space (specially), but '?' must be escaped
+       $str =~ s/([^A-Za-z0-9\-_.~();\/;:@&= +]+)/CGI::escape($1)/eg;
+
+       return $str;
+}
+
 # quote unsafe chars in whole URL, so some characters cannot be quoted
 sub esc_url {
        my $str = shift;
 # quote unsafe chars in whole URL, so some characters cannot be quoted
 sub esc_url {
        my $str = shift;
This page took 0.269835 seconds and 4 git commands to generate.