fix location parser for archives with @ char, add test, fixes #1930

we must exclude colon and slash chars from the username, otherwise the term for the user part
will match everything up to a @ char in the archive name.

a slash can't be in a username as the home directory would contain a illegal slash (slash is path sep),

a colon likely also should not be in a username because chown user:group ... syntax.
This commit is contained in:
Thomas Waldmann 2016-12-09 03:37:13 +01:00
parent 4affad73d1
commit 335d599db4
2 changed files with 9 additions and 2 deletions

View File

@ -791,7 +791,7 @@ class Location:
# regexes for misc. kinds of supported location specifiers: # regexes for misc. kinds of supported location specifiers:
ssh_re = re.compile(r""" ssh_re = re.compile(r"""
(?P<proto>ssh):// # ssh:// (?P<proto>ssh):// # ssh://
(?:(?P<user>[^@]+)@)? # user@ (optional) (?:(?P<user>[^@:/]+)@)? # user@ (optional) - username must not contain : or /
(?P<host>[^:/]+)(?::(?P<port>\d+))? # host or host:port (?P<host>[^:/]+)(?::(?P<port>\d+))? # host or host:port
""" + path_re + optional_archive_re, re.VERBOSE) # path or path::archive """ + path_re + optional_archive_re, re.VERBOSE) # path or path::archive
@ -802,7 +802,7 @@ class Location:
# note: scp_re is also use for local pathes # note: scp_re is also use for local pathes
scp_re = re.compile(r""" scp_re = re.compile(r"""
( (
(?:(?P<user>[^@]+)@)? # user@ (optional) (?:(?P<user>[^@:/]+)@)? # user@ (optional) - username must not contain : or /
(?P<host>[^:/]+): # host: (don't match / in host to disambiguate from file:) (?P<host>[^:/]+): # host: (don't match / in host to disambiguate from file:)
)? # user@host: part is optional )? # user@host: part is optional
""" + path_re + optional_archive_re, re.VERBOSE) # path with optional archive """ + path_re + optional_archive_re, re.VERBOSE) # path with optional archive

View File

@ -94,6 +94,13 @@ class TestLocationWithoutEnv:
assert repr(Location('/abs/path:with:colons')) == \ assert repr(Location('/abs/path:with:colons')) == \
"Location(proto='file', user=None, host=None, port=None, path='/abs/path:with:colons', archive=None)" "Location(proto='file', user=None, host=None, port=None, path='/abs/path:with:colons', archive=None)"
def test_user_parsing(self):
# see issue #1930
assert repr(Location('host:path::2016-12-31@23:59:59')) == \
"Location(proto='ssh', user=None, host='host', port=None, path='path', archive='2016-12-31@23:59:59')"
assert repr(Location('ssh://host/path::2016-12-31@23:59:59')) == \
"Location(proto='ssh', user=None, host='host', port=None, path='/path', archive='2016-12-31@23:59:59')"
def test_underspecified(self, monkeypatch): def test_underspecified(self, monkeypatch):
monkeypatch.delenv('BORG_REPO', raising=False) monkeypatch.delenv('BORG_REPO', raising=False)
with pytest.raises(ValueError): with pytest.raises(ValueError):