From: Tomas Doran Date: Mon, 30 Nov 2009 18:26:34 +0000 (+0000) Subject: Commit miyagawa's fix for PATH_INFO decoding. I think that this also implies changes... X-Git-Tag: 5.80014_02~8 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=commitdiff_plain;h=8bf285ed9abb4b2cb4acc7958512488bc6bbce64;hp=255f7ab3eb8d3840ff7115519ab4311f85e2eed7 Commit miyagawa's fix for PATH_INFO decoding. I think that this also implies changes / fixes in the fcgi _fix_env stuff --- diff --git a/Changes b/Changes index adc4932..9d84a71 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,10 @@ produce the same output either way, but bytes::length returns too big values for upgraded strings containing characters >127 - Fix t/live_fork.t with bleadperl (RT#52100) + - Set $ENV{PATH_INFO} from $ENV{REQUEST_URI} combined with + $ENV{SCRIPT_NAME} if possible. This is many web servers always fully + decode PATH_INFO including URI reserved characters. This allows us to + tell foo%2cbar from foo%252cbar.. RT#50082 Refactoring / cleanups: - NoTabs and Pod tests moved to t/author so that they're not run diff --git a/lib/Catalyst/Engine/CGI.pm b/lib/Catalyst/Engine/CGI.pm index 4c20c62..8fa1fca 100644 --- a/lib/Catalyst/Engine/CGI.pm +++ b/lib/Catalyst/Engine/CGI.pm @@ -115,13 +115,16 @@ sub prepare_path { my $scheme = $c->request->secure ? 'https' : 'http'; my $host = $ENV{HTTP_HOST} || $ENV{SERVER_NAME}; my $port = $ENV{SERVER_PORT} || 80; + my $script_name = $ENV{SCRIPT_NAME}; + $script_name =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go if $script_name; + my $base_path; if ( exists $ENV{REDIRECT_URL} ) { $base_path = $ENV{REDIRECT_URL}; $base_path =~ s/$ENV{PATH_INFO}$//; } else { - $base_path = $ENV{SCRIPT_NAME} || '/'; + $base_path = $script_name || '/'; } # If we are running as a backend proxy, get the true hostname @@ -143,8 +146,22 @@ sub prepare_path { } } + # RFC 3875: "Unlike a URI path, the PATH_INFO is not URL-encoded, + # and cannot contain path-segment parameters." This means PATH_INFO + # is always decoded, and the script can't distinguish / vs %2F. + # See https://issues.apache.org/bugzilla/show_bug.cgi?id=35256 + # Here we try to resurrect the original encoded URI from REQUEST_URI. + my $path_info = $ENV{PATH_INFO}; + if (my $req_uri = $ENV{REQUEST_URI}) { + if (defined $script_name) { + $req_uri =~ s/^\Q$script_name\E//; + } + $req_uri =~ s/\?.*$//; + $path_info = $req_uri if $req_uri; + } + # set the request URI - my $path = $base_path . ( $ENV{PATH_INFO} || '' ); + my $path = $base_path . ( $path_info || '' ); $path =~ s{^/+}{}; # Using URI directly is way too slow, so we construct the URLs manually