Given a URL path, remove extra '/'s and '.' path elements and collapse any '..' references and returns a collapsed 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
(path)
| 970 | # Utilities for CGIHTTPRequestHandler |
| 971 | |
| 972 | def _url_collapse_path(path): |
| 973 | """ |
| 974 | Given a URL path, remove extra '/'s and '.' path elements and collapse |
| 975 | any '..' references and returns a collapsed path. |
| 976 | |
| 977 | Implements something akin to RFC-2396 5.2 step 6 to parse relative paths. |
| 978 | The utility of this function is limited to is_cgi method and helps |
| 979 | preventing some security attacks. |
| 980 | |
| 981 | Returns: The reconstituted URL, which will always start with a '/'. |
| 982 | |
| 983 | Raises: IndexError if too many '..' occur within the path. |
| 984 | |
| 985 | """ |
| 986 | # Query component should not be involved. |
| 987 | path, _, query = path.partition('?') |
| 988 | path = urllib.parse.unquote(path) |
| 989 | |
| 990 | # Similar to os.path.split(os.path.normpath(path)) but specific to URL |
| 991 | # path semantics rather than local operating system semantics. |
| 992 | path_parts = path.split('/') |
| 993 | head_parts = [] |
| 994 | for part in path_parts[:-1]: |
| 995 | if part == '..': |
| 996 | head_parts.pop() # IndexError if more '..' than prior parts |
| 997 | elif part and part != '.': |
| 998 | head_parts.append( part ) |
| 999 | if path_parts: |
| 1000 | tail_part = path_parts.pop() |
| 1001 | if tail_part: |
| 1002 | if tail_part == '..': |
| 1003 | head_parts.pop() |
| 1004 | tail_part = '' |
| 1005 | elif tail_part == '.': |
| 1006 | tail_part = '' |
| 1007 | else: |
| 1008 | tail_part = '' |
| 1009 | |
| 1010 | if query: |
| 1011 | tail_part = '?'.join((tail_part, query)) |
| 1012 | |
| 1013 | splitpath = ('/' + '/'.join(head_parts), tail_part) |
| 1014 | collapsed_path = "/".join(splitpath) |
| 1015 | |
| 1016 | return collapsed_path |
| 1017 | |
| 1018 | |
| 1019 |