summaryrefslogtreecommitdiffstats
path: root/Lib/CGIHTTPServer.py
diff options
context:
space:
mode:
authorSenthil Kumaran <senthil@uthcode.com>2012-04-11 18:23:23 (GMT)
committerSenthil Kumaran <senthil@uthcode.com>2012-04-11 18:23:23 (GMT)
commit5f7e7345cf4f583c127160aa43ee5c3fea7ba06f (patch)
tree6ce93dfa3afc325fe585a53564d9c37a468a71ad /Lib/CGIHTTPServer.py
parentdc0b324a0f73692e90fe999260f1d0f3c8371147 (diff)
downloadcpython-5f7e7345cf4f583c127160aa43ee5c3fea7ba06f.zip
cpython-5f7e7345cf4f583c127160aa43ee5c3fea7ba06f.tar.gz
cpython-5f7e7345cf4f583c127160aa43ee5c3fea7ba06f.tar.bz2
Issue 10484 - Incorporate improvements to CGI module - Suggested by Glenn Linderman. Refactor code and tests
Diffstat (limited to 'Lib/CGIHTTPServer.py')
-rw-r--r--Lib/CGIHTTPServer.py51
1 files changed, 26 insertions, 25 deletions
diff --git a/Lib/CGIHTTPServer.py b/Lib/CGIHTTPServer.py
index 61f34f8..47a994c 100644
--- a/Lib/CGIHTTPServer.py
+++ b/Lib/CGIHTTPServer.py
@@ -84,10 +84,9 @@ class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
path begins with one of the strings in self.cgi_directories
(and the next character is a '/' or the end of the string).
"""
- splitpath = _url_collapse_path_split(self.path)
- joined_path = '/'.join(splitpath)
- dir_sep = joined_path.find('/', 1)
- head, tail = joined_path[:dir_sep], joined_path[dir_sep+1:]
+ collapsed_path = _url_collapse_path(self.path)
+ dir_sep = collapsed_path.find('/', 1)
+ head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:]
if head in self.cgi_directories:
self.cgi_info = head, tail
return True
@@ -301,44 +300,46 @@ class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
self.log_message("CGI script exited OK")
-# TODO(gregory.p.smith): Move this into an appropriate library.
-def _url_collapse_path_split(path):
+def _url_collapse_path(path):
"""
Given a URL path, remove extra '/'s and '.' path elements and collapse
- any '..' references.
+ any '..' references and returns a colllapsed path.
Implements something akin to RFC-2396 5.2 step 6 to parse relative paths.
+ The utility of this function is limited to is_cgi method and helps
+ preventing some security attacks.
Returns: A tuple of (head, tail) where tail is everything after the final /
and head is everything before it. Head will always start with a '/' and,
if it contains anything else, never have a trailing '/'.
Raises: IndexError if too many '..' occur within the path.
+
"""
# Similar to os.path.split(os.path.normpath(path)) but specific to URL
# path semantics rather than local operating system semantics.
- path_parts = []
- for part in path.split('/'):
- if part == '.':
- path_parts.append('')
- else:
- path_parts.append(part)
- # Filter out blank non trailing parts before consuming the '..'.
- path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:]
+ path_parts = path.split('/')
+ head_parts = []
+ for part in path_parts[:-1]:
+ if part == '..':
+ head_parts.pop() # IndexError if more '..' than prior parts
+ elif part and part != '.':
+ head_parts.append( part )
if path_parts:
tail_part = path_parts.pop()
+ if tail_part:
+ if tail_part == '..':
+ head_parts.pop()
+ tail_part = ''
+ elif tail_part == '.':
+ tail_part = ''
else:
tail_part = ''
- head_parts = []
- for part in path_parts:
- if part == '..':
- head_parts.pop()
- else:
- head_parts.append(part)
- if tail_part and tail_part == '..':
- head_parts.pop()
- tail_part = ''
- return ('/' + '/'.join(head_parts), tail_part)
+
+ splitpath = ('/' + '/'.join(head_parts), tail_part)
+ collapsed_path = "/".join(splitpath)
+
+ return collapsed_path
nobody = None