Django

Code

root/django/trunk/django/utils/_os.py

Revision 9411, 1.9 kB (checked in by kmtracey, 1 week ago)

Fixed #9579 -- Properly handle apps running with (and specifically, loading templates from) a current working directory path that contains non-ASCII characters. Thanks for the report to gonzalodelgado and for advice on how to fix it to Daniel Pope.

  • Property svn:eol-style set to native
Line 
1 import os
2 from os.path import join, normcase, normpath, abspath, isabs, sep
3 from django.utils.encoding import force_unicode
4
5 # Define our own abspath function that can handle joining
6 # unicode paths to a current working directory that has non-ASCII
7 # characters in it.  This isn't necessary on Windows since the
8 # Windows version of abspath handles this correctly.  The Windows
9 # abspath also handles drive letters differently than the pure
10 # Python implementation, so it's best not to replace it.
11 if os.name == 'nt':
12     abspathu = abspath
13 else:
14     def abspathu(path):
15         """
16         Version of os.path.abspath that uses the unicode representation
17         of the current working directory, thus avoiding a UnicodeDecodeError
18         in join when the cwd has non-ASCII characters.
19         """
20         if not isabs(path):
21             path = join(os.getcwdu(), path)
22         return normpath(path)
23
24 def safe_join(base, *paths):
25     """
26     Joins one or more path components to the base path component intelligently.
27     Returns a normalized, absolute version of the final path.
28
29     The final path must be located inside of the base path component (otherwise
30     a ValueError is raised).
31     """
32     # We need to use normcase to ensure we don't false-negative on case
33     # insensitive operating systems (like Windows).
34     base = force_unicode(base)
35     paths = [force_unicode(p) for p in paths]
36     final_path = normcase(abspathu(join(base, *paths)))
37     base_path = normcase(abspathu(base))
38     base_path_len = len(base_path)
39     # Ensure final_path starts with base_path and that the next character after
40     # the final path is os.sep (or nothing, in which case final_path must be
41     # equal to base_path).
42     if not final_path.startswith(base_path) \
43        or final_path[base_path_len:base_path_len+1] not in ('', sep):
44         raise ValueError('the joined path is located outside of the base path'
45                          ' component')
46     return final_path
Note: See TracBrowser for help on using the browser.