""" Connection Module
"""
import httplib2
import xml.dom.minidom
class Connection(object):
""" Connection object
"""
def __init__(self, settings):
""" Set up the object
"""
# Get network settings
self.username = settings['username']
self.password = settings['password']
self.realm = settings['realm']
self.host = settings['host']
self.path = settings['path']
self.port = settings['port']
# Make an http object for this connection
self.httpcon = httplib2.Http()
self.httpcon.add_credentials(self.username, self.password)
def _send_request(self, request_method, path, body='', headers=None):
""" Send a request over http to the webdav server
"""
if not headers:
headers = {}
uri = httplib2.urlparse.urljoin(self.host, path)
try:
resp, content = self.httpcon.request(uri, request_method,
body=body, headers=headers)
except httplib2.ServerNotFoundError:
raise
return resp, content
def send_delete(self, path):
""" Send a DELETE request
"""
try:
resp, content = self._send_request('DELETE', path)
return resp, content
except httplib2.ServerNotFoundError:
raise
def send_get(self, path):
""" Send a GET request
"""
try:
resp, content = self._send_request('GET', path)
return resp, content
except httplib2.ServerNotFoundError:
raise
def send_put(self, path, body):
""" This PUT request will put data files onto a webdav server.
However, please note that due to the way in which httplib2 sends
files, it is not currently possible to break a file up into chunks
and read it in. In other words, the whole file has to be read into
memory for sending. This could be problematic for large files.
"""
try:
resp, content = self._send_request('PUT', path, body=body)
return resp, content
except httplib2.ServerNotFoundError:
raise
def send_propfind(self, path):
""" Send a PROPFIND request
"""
try:
headers = {'Depth':'1'}
resp, content = self._send_request('PROPFIND', path,
headers=headers)
return resp, content
except httplib2.ServerNotFoundError:
raise
def send_lock(self, path):
""" Send a LOCK request
"""
try:
body = '<?xml version="1.0" encoding="utf-8" ?>'
body += '<D:lockinfo xmlns:D="DAV:"><D:lockscope><D:exclusive/>'
body += '</D:lockscope><D:locktype><D:write/></D:locktype><D:owner>'
body += '<D:href>MyWebDAV/test_file1.txt</D:href>'
body += '</D:owner></D:lockinfo>'
resp, content = self._send_request('LOCK', path, body=body)
lock_token = LockToken(resp['lock-token'])
return resp, content, lock_token
except httplib2.ServerNotFoundError:
raise
def send_unlock(self, path, lock_token):
""" Send an UNLOCK request
"""
try:
headers = {'Lock-Token': lock_token.token}
body = '<?xml version="1.0" encoding="utf-8" ?>'
body += '<D:lockinfo xmlns:D="DAV:"><D:lockscope><D:exclusive/>'
body += '</D:lockscope><D:locktype><D:write/></D:locktype><D:owner>'
body += '<D:href>MyWebDAV/test_file1.txt</D:href>'
body += '</D:owner></D:lockinfo>'
resp, content = self._send_request('UNLOCK', path, headers=headers,
body=body)
return resp, content
except httplib2.ServerNotFoundError:
raise
def send_mkcol(self, path):
""" Send a MKCOL request
"""
try:
resp, content = self._send_request('MKCOL', path)
return resp, content
except httplib2.ServerNotFoundError, err:
print "Oops, server not found!", err
raise
def send_rmcol(self, path):
""" Send an RMCOL request
"""
try:
resp, content = self._send_request('DELETE', path)
return resp, content
except httplib2.ServerNotFoundError:
raise
def send_copy(self, path, destination):
""" Send a COPY request
"""
try:
full_destination = httplib2.urlparse.urljoin(self.host, destination)
headers = {'Destination': full_destination}
resp, content = self._send_request('COPY', path, headers=headers)
return resp, content
except httplib2.ServerNotFoundError:
raise
class LockToken(object):
""" LockToken object
"""
def __init__(self, lock_token):
""" Make a lock token
"""
self.token = lock_token
class Property(object):
""" Property object for storing information about WebDAV properties
"""
def set_property(self, property_name, property_value=None):
""" Set property names
"""
self.__dict__[property_name] = property_value
class Client(object):
""" This class is a mid-level class for accessing webdav things
"""
def __init__(self):
""" Init with minidom
"""
self.dom = xml.dom.minidom
self.all_nodes = None
self.resource_nodes = None
def get_properties(self, url):
""" Get a list of property objects
@url - the path of the resource / collection minus the host section
"""
def parse_xml_prop(self, xml):
""" Parse the property XML
"""
self.all_nodes = []
#child_nodes = []
self.resource_nodes = []
xml_dom = self.dom.parseString(xml)
#child_nodes = xml_dom.childNodes[0].childNodes
self.get_nodes(xml_dom.childNodes)
resources_all = self.make_resources(self.resource_nodes)
return resources_all
def get_nodes(self, nodes):
""" Get any DAV nodes
"""
for child in nodes:
for cur_node in child.childNodes:
try:
#print cur_node.
if cur_node.namespaceURI == u'DAV:' and cur_node.tagName \
== u'D:response':
self.resource_nodes.append(cur_node)
except AttributeError:
pass
self.get_nodes(child.childNodes)
self.all_nodes.append(child)
def make_resources(self, element_list):
""" Make any resources
"""
prop_list = []
for element in element_list:
for node in element.childNodes:
try:
if node.localName == u'href':
href = node.childNodes[0].data
elif node.localName == u'propstat':
for item in node.childNodes:
if item.localName == u'prop':
this_property = Property()
this_property.set_property(u'href', href)
for cn1 in item.childNodes:
if cn1.localName != None:
try:
# Try and get the data from the
# element
this_property.set_property(
cn1.localName,
cn1.childNodes[0].data)
except AttributeError:
# No data, so see if there are any
# child nodes
if cn1.childNodes:
this_property.set_property(
cn1.localName,
cn1.childNodes[0].localName)
else:
this_property.set_property(
cn1.localName,
cn1.localName)
except IndexError:
# Add in some handling for locks
print "Index Error!"
continue
prop_list.append(this_property)
except AttributeError:
pass
return prop_list