136
class SFTPTransport(Transport):
136
class SFTPUrlHandling(Transport):
137
"""Mix-in that does common handling of SSH/SFTP URLs."""
139
def __init__(self, base):
140
self._parse_url(base)
141
base = self._unparse_url(self._path)
144
super(SFTPUrlHandling, self).__init__(base)
146
def _parse_url(self, url):
148
self._username, self._password,
149
self._host, self._port, self._path) = self._split_url(url)
151
def _unparse_url(self, path):
152
"""Return a URL for a path relative to this transport.
154
path = urllib.quote(path)
155
# handle homedir paths
156
if not path.startswith('/'):
158
netloc = urllib.quote(self._host)
159
if self._username is not None:
160
netloc = '%s@%s' % (urllib.quote(self._username), netloc)
161
if self._port is not None:
162
netloc = '%s:%d' % (netloc, self._port)
163
return urlparse.urlunparse((self._scheme, netloc, path, '', '', ''))
165
def _split_url(self, url):
166
(scheme, username, password, host, port, path) = split_url(url)
167
## assert scheme == 'sftp'
169
# the initial slash should be removed from the path, and treated
170
# as a homedir relative path (the path begins with a double slash
171
# if it is absolute).
172
# see draft-ietf-secsh-scp-sftp-ssh-uri-03.txt
173
# RBC 20060118 we are not using this as its too user hostile. instead
174
# we are following lftp and using /~/foo to mean '~/foo'.
175
# handle homedir paths
176
if path.startswith('/~/'):
180
return (scheme, username, password, host, port, path)
182
def _remote_path(self, relpath):
183
"""Return the path to be passed along the sftp protocol for relpath.
185
:param relpath: is a urlencoded string.
187
return self._combine_paths(self._path, relpath)
190
class SFTPTransport(SFTPUrlHandling):
137
191
"""Transport implementation for SFTP access."""
139
193
_do_prefetch = _default_do_prefetch
230
279
def relpath(self, abspath):
231
username, password, host, port, path = self._split_url(abspath)
280
scheme, username, password, host, port, path = self._split_url(abspath)
233
282
if (username != self._username):
234
283
error.append('username mismatch')
692
741
# that we have taken the lock.
693
742
return SFTPLock(relpath, self)
695
def _unparse_url(self, path=None):
696
"""Gives a url for a relative reference."""
699
path = urllib.quote(path)
700
# handle homedir paths
701
if not path.startswith('/'):
703
netloc = urllib.quote(self._host)
704
if self._username is not None:
705
netloc = '%s@%s' % (urllib.quote(self._username), netloc)
706
if self._port is not None:
707
netloc = '%s:%d' % (netloc, self._port)
708
return urlparse.urlunparse(('sftp', netloc, path, '', '', ''))
710
def _split_url(self, url):
711
(scheme, username, password, host, port, path) = split_url(url)
712
assert scheme == 'sftp'
714
# the initial slash should be removed from the path, and treated
715
# as a homedir relative path (the path begins with a double slash
716
# if it is absolute).
717
# see draft-ietf-secsh-scp-sftp-ssh-uri-03.txt
718
# RBC 20060118 we are not using this as its too user hostile. instead
719
# we are following lftp and using /~/foo to mean '~/foo'.
720
# handle homedir paths
721
if path.startswith('/~/'):
725
return (username, password, host, port, path)
727
def _parse_url(self, url):
728
(self._username, self._password,
729
self._host, self._port, self._path) = self._split_url(url)
731
744
def _sftp_connect(self):
732
745
"""Connect to the remote sftp server.
733
746
After this, self._sftp should have a valid connection (or