diff --git a/babel/localedata.py b/babel/localedata.py index 9308b5e..688af79 100644 --- a/babel/localedata.py +++ b/babel/localedata.py @@ -18,6 +18,9 @@ """ import os +import re +import sys + import pickle try: import threading @@ -31,7 +34,23 @@ __docformat__ = 'restructuredtext en' _cache = {} _cache_lock = threading.RLock() _dirname = os.path.join(os.path.dirname(__file__), 'localedata') +_windows_reserved_name_re = re.compile("^(con|prn|aux|nul|com[0-9]|lpt[0-9])$", re.I) + + +def resolve_locale_filename(name): + """ + Resolve a locale identifier to a `.dat` path on disk. + """ + + # Clean up any possible relative paths. + name = os.path.basename(name) + + # Ensure we're not left with one of the Windows reserved names. + if sys.platform == "win32" and _windows_reserved_name_re.match(os.path.splitext(name)[0]): + raise ValueError("Name %s is invalid on Windows" % name) + # Build the path. + return os.path.join(_dirname, '%s.dat' % name) def exists(name): """Check whether locale data is available for the given locale. @@ -42,7 +61,7 @@ def exists(name): """ if name in _cache: return True - return os.path.exists(os.path.join(_dirname, '%s.dat' % name)) + return os.path.exists(resolve_locale_filename(name)) def list(): @@ -85,6 +104,7 @@ def load(name, merge_inherited=True): :raise `IOError`: if no locale data file is found for the given locale identifer, or one of the locales it inherits from """ + name = os.path.basename(name) _cache_lock.acquire() try: data = _cache.get(name) @@ -99,7 +119,7 @@ def load(name, merge_inherited=True): else: parent = '_'.join(parts[:-1]) data = load(parent).copy() - filename = os.path.join(_dirname, '%s.dat' % name) + filename = resolve_locale_filename(name) fileobj = open(filename, 'rb') try: if name != 'root' and merge_inherited: