82
82
# create new socket
83
83
sock = socket.create_connection((self.host, self.port),
89
89
# wrap the socket in ssl using verification
90
90
self.sock = ssl.wrap_socket(sock,
126
126
self.username = parsed_url.username
127
127
self.password = self.get_password()
128
self.directory = self._sanitize_path(parsed_url.path)
128
self.directory = self.sanitize_path(parsed_url.path)
130
130
log.Info("Using WebDAV protocol %s" % (globals.webdav_proto,))
131
131
log.Info("Using WebDAV host %s port %s" % (parsed_url.hostname, parsed_url.port))
136
def _sanitize_path(self,path):
136
def sanitize_path(self,path):
138
138
foldpath = re.compile('/+')
139
139
return foldpath.sub('/', path + '/' )
143
def _getText(self,nodelist):
143
def getText(self,nodelist):
145
145
for node in nodelist:
146
146
if node.nodeType == node.TEXT_NODE:
147
147
rc = rc + node.data
150
def _connect(self, forced=False):
150
def _retry_cleanup(self):
151
self.connect(forced=True)
153
def connect(self, forced=False):
152
155
Connect or re-connect to the server, updates self.conn
153
156
# reconnect on errors as a precaution, there are errors e.g.
154
157
# "[Errno 32] Broken pipe" or SSl errors that render the connection unusable
156
if self.retry_count<=1 and self.conn \
159
if not forced and self.conn \
157
160
and self.conn.host == self.parsed_url.hostname: return
159
log.Info("WebDAV create connection on '%s' (retry %s) " % (self.parsed_url.hostname,self.retry_count) )
162
log.Info("WebDAV create connection on '%s'" % (self.parsed_url.hostname))
160
163
if self.conn: self.conn.close()
161
164
# http schemes needed for redirect urls from servers
162
165
if self.parsed_url.scheme in ['webdav','http']:
198
201
if redirected > 10:
199
202
raise FatalBackendException("WebDAV redirected 10 times. Giving up.")
200
203
self.parsed_url = duplicity.backend.ParsedUrl(redirect_url)
201
self.directory = self._sanitize_path(self.parsed_url.path)
204
self.directory = self.sanitize_path(self.parsed_url.path)
202
205
return self.request(method,self.directory,data,redirected+1)
204
207
raise FatalBackendException("WebDAV missing location header in redirect response.")
304
307
for i in range(1,len(dirs)):
305
308
d="/".join(dirs[0:i+1])+"/"
307
self.close() # or we get previous request's data or exception
310
self._close() # or we get previous request's data or exception
308
311
self.headers['Depth'] = "1"
309
312
response = self.request("PROPFIND", d)
310
313
del self.headers['Depth']
314
317
if response.status == 404:
315
318
log.Info("Creating missing directory %s" % d)
316
self.close() # or we get previous request's data or exception
319
self._close() # or we get previous request's data or exception
318
321
res = self.request("MKCOL", d)
319
322
if res.status != 201:
320
323
raise BackendException("WebDAV MKCOL %s failed: %s %s" % (d,res.status,res.reason))
323
def __taste_href(self, href):
326
def taste_href(self, href):
325
328
Internal helper to taste the given href node and, if
326
329
it is a duplicity file, collect it as a result file.
328
331
@return: A matching filename, or None if the href did not match.
330
raw_filename = self._getText(href.childNodes).strip()
333
raw_filename = self.getText(href.childNodes).strip()
331
334
parsed_url = urlparse.urlparse(urllib.unquote(raw_filename))
332
335
filename = parsed_url.path
333
336
log.Debug("webdav path decoding and translation: "