def download_file(self, remote_path, local_path): urn = Urn(remote_path) if self.is_dir(urn.path()): raise OptionNotValid(name="remote_path", value=remote_path) if os.path.isdir(local_path): raise OptionNotValid(name="local_path", value=local_path) if not self.check(urn.path()): raise RemoteResourceNotFound(urn.path()) with open(local_path, 'wb') as local_file: url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'HTTPHEADER': self.get_header('download_file'), 'WRITEDATA': local_file, 'NOBODY': 0 } response = requests.request( "GET", options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('download_file')) for block in response.iter_content(1024): local_file.write(block)
def upload_from(self, buff, remote_path): urn = Urn(remote_path) if urn.is_dir(): raise OptionNotValid(name="remote_path", value=remote_path) if not self.check(urn.parent()): raise RemoteParentNotFound(urn.path()) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), } # import ipdb; ipdb.set_trace(); #FIXME if buff.tell() == 0: data = buff.read() else: data = buff response = requests.request('PUT', options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('upload_from'), data=data) if response.status_code == 507: raise NotEnoughSpace() log.debug("Response: %s", response)
def upload_file(self, remote_path, local_path, progress=None): if not os.path.exists(local_path): raise LocalResourceNotFound(local_path) urn = Urn(remote_path) if urn.is_dir(): raise OptionNotValid(name="remote_path", value=remote_path) if os.path.isdir(local_path): raise OptionNotValid(name="local_path", value=local_path) if not self.check(urn.parent()): raise RemoteParentNotFound(urn.path()) with open(local_path, "rb") as local_file: url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'HTTPHEADER': self.get_header('upload_file'), 'UPLOAD': 1, 'READFUNCTION': local_file.read, # 'NOPROGRESS': 0 if progress else 1 } # if progress: # options["PROGRESSFUNCTION"] = progress file_size = os.path.getsize(local_path) if file_size > self.large_size: options['INFILESIZE_LARGE'] = file_size else: options['INFILESIZE'] = file_size response = requests.request('PUT', options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('upload_file'), data=buff) if request.status_code == 507: raise NotEnoughSpace() if response.status_code == 409: raise Conflict()
def get_property(self, remote_path, option): def parse(response, option): response_str = response.content tree = etree.fromstring(response_str) xpath = "{xpath_prefix}{xpath_exp}".format( xpath_prefix=".//", xpath_exp=option['name']) return tree.findtext(xpath) def data(option): root = etree.Element("propfind", xmlns="DAV:") prop = etree.SubElement(root, "prop") etree.SubElement(prop, option.get('name', ""), xmlns=option.get('namespace', "")) tree = etree.ElementTree(root) buff = BytesIO() tree.write(buff) return buff.getvalue() urn = Urn(remote_path) if not self.check(urn.path()): raise RemoteResourceNotFound(urn.path()) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['get_metadata'], 'HTTPHEADER': self.get_header('get_metadata'), 'POSTFIELDS': data(option), 'NOBODY': 0 } response = requests.request(options["CUSTOMREQUEST"], options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('get_metadata'), data=data(option)) return parse(response, option)
def list(self, remote_path=root): def parse(response): try: response_str = response.content tree = etree.fromstring(response_str) hrees = [ unquote(hree.text) for hree in tree.findall(".//{DAV:}href") ] return [Urn(hree) for hree in hrees] except etree.XMLSyntaxError: return list() directory_urn = Urn(remote_path, directory=True) if directory_urn.path() != Client.root: if not self.check(directory_urn.path()): raise RemoteResourceNotFound(directory_urn.path()) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': directory_urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['list'], 'HTTPHEADER': self.get_header('list'), 'NOBODY': 0 } response = requests.request(options["CUSTOMREQUEST"], options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('list')) urns = parse(response) path = "{root}{path}".format(root=self.webdav.root, path=directory_urn.path()) return [ urn.filename() for urn in urns if urn.path() != path and urn.path() != path[:-1] ]
def set_property(self, remote_path, option): def data(option): root_node = etree.Element("propertyupdate", xmlns="DAV:") root_node.set('xmlns:u', option.get('namespace', "")) set_node = etree.SubElement(root_node, "set") prop_node = etree.SubElement(set_node, "prop") opt_node = etree.SubElement( prop_node, "{namespace}:{name}".format(namespace='u', name=option['name'])) opt_node.text = option.get('value', "") tree = etree.ElementTree(root_node) buff = BytesIO() tree.write(buff) return buff.getvalue() urn = Urn(remote_path) if not self.check(urn.path()): raise RemoteResourceNotFound(urn.path()) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['set_metadata'], 'HTTPHEADER': self.get_header('get_metadata'), 'POSTFIELDS': data(option) } response = requests.request(options["CUSTOMREQUEST"], options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('get_metadata'), data=data(option))
def clean(self, remote_path): urn = Urn(remote_path) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['clean'], 'HTTPHEADER': self.get_header('clean') } response = requests.request( options["CUSTOMREQUEST"], options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('clean'), )
def copy(self, remote_path_from, remote_path_to): def header(remote_path_to): path = Urn(remote_path_to).path() destination = "{root}{path}".format(root=self.webdav.root, path=path) header = self.get_header('copy') header["Destination"] = destination return header urn_from = Urn(remote_path_from) if not self.check(urn_from.path()): raise RemoteResourceNotFound(urn_from.path()) urn_to = Urn(remote_path_to) if not self.check(urn_to.parent()): raise RemoteParentNotFound(urn_to.path()) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn_from.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['copy'], 'HTTPHEADER': header(remote_path_to) } h = header(remote_path_to) response = requests.request( options["CUSTOMREQUEST"], options["URL"], auth=(self.webdav.login, self.webdav.password), headers=h, )
def mkdir(self, remote_path): directory_urn = Urn(remote_path, directory=True) if not self.check(directory_urn.parent()): raise RemoteParentNotFound(directory_urn.path()) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': directory_urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['mkdir'], } response = requests.request(options["CUSTOMREQUEST"], options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('mkdir'))
def check(self, remote_path=root): urn = Urn(remote_path) response = BytesIO() url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['check'], } response = requests.request(options["CUSTOMREQUEST"], options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('check')) if int(response.status_code) == 200: return True return False
def download_to(self, buff, remote_path): urn = Urn(remote_path) if self.is_dir(urn.path()): raise OptionNotValid(name="remote_path", value=remote_path) if not self.check(urn.path()): raise RemoteResourceNotFound(urn.path()) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), } response = requests.request("GET", options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('download_to')) buff.write(response.content)
def is_dir(self, remote_path): def parse(response, path): try: response_str = response.content tree = etree.fromstring(response_str) resps = tree.findall("{DAV:}response") for resp in resps: href = resp.findtext("{DAV:}href") urn = unquote(href) if path[-1] == Urn.separate: if not path == urn: continue else: path_with_sep = "{path}{sep}".format(path=path, sep=Urn.separate) if not path == urn and not path_with_sep == urn: continue type = resp.find(".//{DAV:}resourcetype") if type is None: raise MethodNotSupported(name="is_dir", server=self.webdav.hostname) dir_type = type.find("{DAV:}collection") return True if dir_type is not None else False raise RemoteResourceNotFound(path) except etree.XMLSyntaxError: raise MethodNotSupported(name="is_dir", server=self.webdav.hostname) urn = Urn(remote_path) parent_urn = Urn(urn.parent()) if not self.check(urn.path()) and not self.check( Urn(remote_path, directory=True).path()): raise RemoteResourceNotFound(remote_path) response = BytesIO() url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': parent_urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['info'], } response = requests.request(options["CUSTOMREQUEST"], options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('info')) path = "{root}{path}".format(root=self.webdav.root, path=urn.path()) return parse(response, path)
def info(self, remote_path): def parse(response, path): try: response_str = response.content tree = etree.fromstring(response_str) find_attributes = { 'created': ".//{DAV:}creationdate", 'name': ".//{DAV:}displayname", 'size': ".//{DAV:}getcontentlength", 'modified': ".//{DAV:}getlastmodified" } resps = tree.findall("{DAV:}response") for resp in resps: href = resp.findtext("{DAV:}href") urn = unquote(href) if path[-1] == Urn.separate: if not path == urn: continue else: path_with_sep = "{path}{sep}".format(path=path, sep=Urn.separate) if not path == urn and not path_with_sep == urn: continue info = dict() for (name, value) in find_attributes.items(): info[name] = resp.findtext(value) return info raise RemoteResourceNotFound(path) except etree.XMLSyntaxError: raise MethodNotSupported(name="info", server=self.webdav.hostname) urn = Urn(remote_path) # response = BytesIO() if not self.check(urn.path()) and not self.check( Urn(remote_path, directory=True).path()): raise RemoteResourceNotFound(remote_path) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['info'], } response = requests.request(options["CUSTOMREQUEST"], options["URL"], auth=(self.webdav.login, self.webdav.password), headers=self.get_header('info')) path = "{root}{path}".format(root=self.webdav.root, path=urn.path()) return parse(response, path)