summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbtimby <btimby@67cdc799-7952-0410-af00-57a81ceafa0f>2012-04-20 19:17:32 +0000
committerbtimby <btimby@67cdc799-7952-0410-af00-57a81ceafa0f>2012-04-20 19:17:32 +0000
commit083d6f32ca749a68541e54c86d95582a3ed46377 (patch)
tree47a414710dbdf1a07144f4f025a5b234acb574fb
parentd04d263597a8f2c19e3ab7dcc7374704ed1d2ac4 (diff)
downloadpyfilesystem-083d6f32ca749a68541e54c86d95582a3ed46377.tar.gz
Use explicit exception to detect invalid path (BackReferenceError), see comments on r773
git-svn-id: http://pyfilesystem.googlecode.com/svn/trunk@775 67cdc799-7952-0410-af00-57a81ceafa0f
-rw-r--r--fs/errors.py5
-rw-r--r--fs/expose/sftp.py6
-rw-r--r--fs/path.py20
3 files changed, 19 insertions, 12 deletions
diff --git a/fs/errors.py b/fs/errors.py
index 38cb4b7..93f8905 100644
--- a/fs/errors.py
+++ b/fs/errors.py
@@ -188,6 +188,11 @@ class NoMMapError(ResourceError):
default_message = "Can't get mmap for %(path)s"
+class BackReferenceError(FSError, ValueError):
+ """Exception raised when too many backrefs exist in a path (ex: '/..', '/docs/../..')."""
+ default_message = "Too many backrefs in '%(path)s'"
+
+
def convert_fs_errors(func):
"""Function wrapper to convert FSError instances into OSError."""
@wraps(func)
diff --git a/fs/expose/sftp.py b/fs/expose/sftp.py
index a5bf9f9..7abd359 100644
--- a/fs/expose/sftp.py
+++ b/fs/expose/sftp.py
@@ -185,12 +185,10 @@ class SFTPServerInterface(paramiko.SFTPServerInterface):
def canonicalize(self, path):
try:
return abspath(normpath(path)).encode(self.encoding)
- except ValueError, e:
+ except BackReferenceError:
# If the client tries to use backrefs to escape root, gently
# nudge them back to /.
- if 'too many backrefs' in e.args[0]:
- return '/'
- raise
+ return '/'
@report_sftp_errors
def chattr(self, path, attr):
diff --git a/fs/path.py b/fs/path.py
index 0f55aa4..ebb7fcc 100644
--- a/fs/path.py
+++ b/fs/path.py
@@ -33,31 +33,34 @@ def normpath(path):
>>> normpath("foo/../../bar")
Traceback (most recent call last)
...
- ValueError: too many backrefs in path 'foo/../../bar'
+ BackReferenceError: Too many backrefs in 'foo/../../bar'
"""
-
+
if path in ('', '/'):
return path
-
+
path = path.replace('\\', '/')
-
+
# An early out if there is no need to normalize this path
if not _requires_normalization(path):
return path.rstrip('/')
-
+
components = []
append = components.append
special = ('..', '.', '').__contains__
try:
for component in path.split('/'):
if special(component):
- if component == '..':
+ if component == '..':
components.pop()
else:
append(component)
except IndexError:
- raise ValueError("too many backrefs in path '%s'" % path)
+ # Imported here because errors imports this module (path),
+ # causing a circular import.
+ from fs.errors import BackReferenceError
+ BackReferenceError(details={ 'path': path })
if path[0] == '/':
return '/%s' % '/'.join(components)
return '/'.join(components)
@@ -77,7 +80,8 @@ def iteratepath(path, numsplits=None):
return path.split('/')
else:
return path.split('/', numsplits)
-
+
+
def recursepath(path, reverse=False):
"""Returns intermediate paths from the root to the given path