1032
class ConnectedTransport(Transport):
1033
"""A transport connected to a remote server.
1035
Base class for transports that connect to a remote server
1036
with optional user and password. Cloning preserves existing
1037
connection and credentials.
1040
def __init__(self, base, from_transport=None):
1043
if from_transport is not None:
1044
# Copy the passowrd as it does not appear in base
1045
self._password = from_transport._password
1047
self._user, self._password,
1048
self._host, self._port,
1049
self._path) = self._split_url(base)
1050
# Rebuild base taken any special handling into account
1051
base = self._unsplit_url(self._scheme,
1052
self._user, self._password,
1053
self._host, self._port,
1054
self._urlencode_abspath(self._path))
1055
super(ConnectedTransport, self).__init__(base)
1056
if from_transport is not None:
1057
connection = from_transport.get_connection()
1060
self.set_connection(connection)
1062
def _split_url(self, url):
1063
if isinstance(url, unicode):
1064
import pdb; pdb.set_trace()
1065
raise errors.InvalidURL('should be ascii:\n%r' % url)
1066
url = url.encode('utf-8')
1067
(scheme, netloc, path, params,
1068
query, fragment) = urlparse.urlparse(url, allow_fragments=False)
1069
username = password = host = port = None
1071
username, host = netloc.split('@', 1)
1073
username, password = username.split(':', 1)
1074
password = urllib.unquote(password)
1075
username = urllib.unquote(username)
1080
host, port = host.rsplit(':', 1)
1084
raise errors.InvalidURL('invalid port number %s in url:\n%s' %
1086
host = urllib.unquote(host)
1087
path = self._urldecode_abspath(path)
1089
return (scheme, username, password, host, port, path)
1091
def _unsplit_url(self, scheme, user, password, host, port, path):
1092
netloc = urllib.quote(host)
1093
if user is not None:
1094
# Note that we don't put the password back even if we
1095
# have one so that it doesn't get accidentally
1097
netloc = '%s@%s' % (urllib.quote(user), netloc)
1098
if port is not None:
1099
netloc = '%s:%d' % (netloc, port)
1100
return urlparse.urlunparse((scheme, netloc, path, None, None, None))
1102
def _urlencode_abspath(self, abspath):
1103
return urllib.quote(abspath)
1105
def _urldecode_abspath(self, abspath):
1106
return urllib.unquote(abspath)
1108
def relpath(self, abspath):
1109
scheme, user, password, host, port, path = self._split_url(abspath)
1111
if (scheme != self._scheme):
1112
error.append('scheme mismatch')
1113
if (user != self._user):
1114
error.append('username mismatch')
1115
if (host != self._host):
1116
error.append('host mismatch')
1117
if (port != self._port):
1118
error.append('port mismatch')
1119
if not (path == self._path[:-1] or path.startswith(self._path)):
1120
error.append('path mismatch')
1122
extra = ', '.join(error)
1123
raise errors.PathNotChild(abspath, self.base, extra=extra)
1124
pl = len(self._path)
1125
return path[pl:].strip('/')
1127
def abspath(self, relpath):
1128
"""Return the full url to the given relative path.
1130
:param relpath: the relative path urlencoded
1132
path = self._remote_path(relpath)
1133
return self._unsplit_url(self._scheme, self._user, self._password,
1134
self._host, self._port,
1135
self._urlencode_abspath(path))
1137
def _remote_path(self, relpath):
1138
"""Return the absolute path part of the url to the given relative path.
1140
:param relpath: is a urlencoded string.
1142
relative = urlutils.unescape(relpath).encode('utf-8')
1143
remote_path = self._combine_paths(self._path, relative)
1146
def get_connection(self):
1147
"""Returns the transport specific connection object"""
1148
return self._connection
1150
def set_connection(self, connection):
1151
"""Set the transport specific connection object.
1153
Note: daughter classes should ensure that the connection
1154
is still shared if the connection is reset during the
1155
transport lifetime (using a list containing the single
1156
connection can help avoid aliasing bugs).
1158
self._connection = connection
1035
1161
# jam 20060426 For compatibility we copy the functions here
1036
1162
# TODO: The should be marked as deprecated
1037
1163
urlescape = urlutils.escape