Changeset 123:446c42e017fd
- Timestamp:
- 2007-08-02 19:17:43 (1 year ago)
- Files:
-
- urlpath.py (modified) (3 diffs)
- websourcebrowser.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
urlpath.py
r109 r123 24 24 import urllib 25 25 import os 26 import re 26 27 27 28 29 # separator in URLs 28 30 sep = "/" 29 31 30 32 class NotUnderRoot(Exception): 31 33 pass 34 35 def _normalize_path(path): 36 """ 37 Return the `path` in "normalized" form: 38 - change each sequence of path separators to a single path separator 39 - change path by evaluating "." and ".." occurences 40 - make path absolute 41 """ 42 if os.sep == "\\": 43 replacement = "\\\\" 44 else: 45 replacement = os.sep 46 path = re.sub("(?:%s)+" % re.escape(os.sep), replacement, path) 47 path = os.path.normcase(os.path.normpath(path)) 48 return os.path.abspath(path) 49 50 def _is_file_system_root(path): 51 r""" 52 Return `True` if `path` is a file system root directory, else 53 `False`. 54 55 Under Posix, the file system root directory is "/", under 56 Windows, it's r"x:\", where x is any drive letter. 57 """ 58 path = _normalize_path(path) 59 drive, rest = os.path.splitdrive(path) 60 return rest == os.sep 61 62 def is_safe_path(root, path): 63 """ 64 Return `True` if the `path` is a subdirectory of or a file 65 under the document root directory `root`, else return `False`. 66 67 >>> import urlpath 68 >>> urlpath.is_safe_path("/the/root", "/the/root/some_file") 69 True 70 >>> urlpath.is_safe_path("/the/root", "/somewhere/else/some_file") 71 False 72 """ 73 root = _normalize_path(root) 74 path = _normalize_path(path) 75 if root == path: 76 return True 77 if _is_file_system_root(root): 78 return path.startswith(root) 79 else: 80 return path.startswith(root + os.sep) 32 81 33 82 def to_url(root, path): … … 43 92 >>> urlpath.to_url("/the/root", "/the/root/some dir/some file") 44 93 '/some%20dir/some%20file' 45 46 It also works on Windows:47 48 >>> import os49 >>> oldsep = os.sep; os.sep = "\\"50 >>> urlpath.to_url(r"C:\the\root", r"C:\the\root\somedir\somefile")51 '/somedir/somefile'52 >>> os.sep = oldsep53 94 54 95 Trailing path separators on the `root` or `path` don't matter: … … 92 133 '/the/root/some dir/some file' 93 134 94 It also works on Windows:95 96 >>> import os97 >>> oldsep = os.sep; os.sep = "\\"98 >>> urlpath.to_file_system(r"C:\the\root", "/somedir/somefile")99 'C:\\the\\root\\somedir\\somefile'100 >>> os.sep = oldsep101 102 135 Trailing path separators on the `root` or `url` don't matter: 103 136 websourcebrowser.py
r120 r123 67 67 return css_path 68 68 69 def is_safe_path(absolute_path):70 """71 Return `True` if the `absolute_path` is a subdirectory of or a72 file in the document root directory, else return `False`.73 """74 if absolute_path.count(os.sep) == 1:75 # file system root directory76 # Attention: On Posix, we could now just return `True`, but on77 # Windows, we have a file system root directory _per drive letter_78 return absolute_path.startswith(config.root)79 else:80 return absolute_path.startswith(config.root + os.sep)81 82 69 83 70 class SourceBrowserHandler(BaseHTTPServer.BaseHTTPRequestHandler): … … 182 169 source_path = urllib.unquote(source_path) 183 170 source_path = os.path.join(config.root, source_path[1:]) 184 if is_safe_path(source_path):171 if urlpath.is_safe_path(config.root, source_path): 185 172 content_type = mimetypes.guess_type(source_path)[0] 186 173 if content_type is None: … … 192 179 return 193 180 path = urlpath.to_file_system(config.root, self.path) 194 if not is_safe_path(path):181 if not urlpath.is_safe_path(config.root, path): 195 182 # don't show items "above" the current directory; thereby 196 183 # avoiding information disclosure (double dot attack)