def mkdir(self, remote_path):

        try:
            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'],
                'HTTPHEADER': self.get_header('mkdir')
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def upload_from(self, buff, remote_path):

        try:
            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),
                'HTTPHEADER': self.get_header('upload_from'),
                'UPLOAD': 1,
                'READFUNCTION': buff.read,
            }

            request = self.Request(options=options)

            request.perform()
            code = request.getinfo(pycurl.HTTP_CODE)
            if code == "507":
                raise NotEnoughSpace()

            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def download_to(self, buff, remote_path):

        try:
            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),
                'WRITEFUNCTION': buff.write,
                'HTTPHEADER': self.get_header('download_to'),
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def check(self, remote_path=root):

        try:
            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'],
                'HTTPHEADER': self.get_header('check'),
                'WRITEDATA': response,
                'NOBODY': 1
            }

            request = self.Request(options=options)

            request.perform()
            code = request.getinfo(pycurl.HTTP_CODE)
            request.close()

            if int(code) == 200:
                return True

            return False

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
示例#5
0
    def upload_file(self, remote_path, local_path, progress=None):
        """Uploads file to remote path on WebDAV server. File should be 2Gb or less.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PUT

        :param remote_path: the path to uploading file on WebDAV server.
        :param local_path: the path to local file for uploading.
        :param progress: Progress function. Not supported now.
        """
        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:
            file_size = os.path.getsize(local_path)
            if file_size > self.large_size:
                raise ResourceTooBig(path=local_path,
                                     size=file_size,
                                     max_size=self.large_size)

            self.execute_request(action='upload',
                                 path=urn.quote(),
                                 data=local_file)
示例#6
0
    def clean(self, remote_path, matrix_params=None, query_params=None):

        try:
            urn = Urn(remote_path,
                      matrix_params=matrix_params,
                      query_params=query_params)

            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')
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
示例#7
0
    def download_file(self, remote_path, local_path, progress=None):
        """Downloads file from WebDAV server and save it locally.
        More information you can find by link http://webdav.org/specs/rfc4918.html#rfc.section.9.4

        :param remote_path: the path to remote file for downloading.
        :param local_path: the path to save file locally.
        :param progress: progress function. Not supported now.
        """
        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 os.path.sep in local_path:
            os.makedirs(local_path.rsplit(os.path.sep, 1)[0], exist_ok=True)

        if not self.check(urn.path()):
            raise RemoteResourceNotFound(urn.path())

        with open(local_path, 'wb') as local_file:
            response = self.execute_request('download', urn.quote())
            for block in response.iter_content(1024):
                local_file.write(block)
示例#8
0
    def get_property(self,
                     remote_path,
                     option,
                     matrix_params=None,
                     query_params=None):
        def parse(response, option):

            response_str = response.getvalue()
            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()

        try:
            urn = Urn(remote_path,
                      matrix_params=matrix_params,
                      query_params=query_params)

            if not self.check(urn.path()):
                raise RemoteResourceNotFound(urn.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['get_metadata'],
                'HTTPHEADER': self.get_header('get_metadata'),
                'POSTFIELDS': data(option),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

            return parse(response, option)

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
示例#9
0
    def list(self, remote_path="/"):
        def parse(response):

            try:
                response_str = response.getvalue()
                print(response_str)
                tree = etree.fromstring(response_str)
                hrees = [
                    unquote(hree.text)
                    for hree in tree.findall(".//{DAV:}href")
                ]
                etags = [
                    unquote(etag.text)
                    for etag in tree.findall(".//{DAV:}getetag")
                ]
                i = 0
                ret = []
                for hree in hrees:
                    ret.append(MyUrn(hree, etags[i]))
                    i = i + 1
                return ret
            except etree.XMLSyntaxError:
                return list()

        try:
            directory_urn = Urn(remote_path, directory=True)

            if directory_urn.path() != wc.Client.root:
                if not self.client.check(directory_urn.path()):
                    raise RemoteResourceNotFound(directory_urn.path())

            response = BytesIO()

            url = {
                'hostname': self.client.webdav.hostname,
                'root': self.client.webdav.root,
                'path': directory_urn.quote()
            }
            options = {
                'URL': "{hostname}{root}{path}".format(**url),
                'CUSTOMREQUEST': wc.Client.requests['list'],
                'HTTPHEADER': self.client.get_header('list'),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.client.Request(options=options)

            request.perform()
            request.close()

            urns = parse(response)

            #path = "{root}{path}".format(root=self.client.webdav.root, path=directory_urn.path())
            #return [urn.filename() for urn in urns if urn.path() != path and urn.path() != path[:-1]]
            return urns

        except pycurl.error:
            raise NotConnection(self.client.webdav.hostname)
示例#10
0
    def clean(self, remote_path):
        """Cleans (Deletes) a remote resource on WebDAV server. The name of method is not changed for back compatibility
        with original library.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_DELETE

        :param remote_path: the remote resource whisch will be deleted.
        """
        urn = Urn(remote_path)
        self.execute_request(action='clean', path=urn.quote())
示例#11
0
    def check(self, remote_path=root):
        def parse(response, path):

            try:
                response_str = response.getvalue()
                tree = etree.fromstring(response_str)

                resps = tree.findall("{DAV:}response")

                for resp in resps:
                    href = resp.findtext("{DAV:}href")
                    urn = unquote(href)

                    if path.endswith(Urn.separate):
                        if path == urn or path[:-1] == urn:
                            return True
                    else:
                        if path == urn:
                            return True

                return False

            except etree.XMLSyntaxError:
                raise MethodNotSupported(name="check",
                                         server=self.webdav.hostname)

        try:
            urn = Urn(remote_path)
            parent_urn = Urn(urn.parent())
            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'],
                'HTTPHEADER': self.get_header('info'),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

            path = "{root}{path}".format(root=self.webdav.root,
                                         path=urn.path())

            return parse(response, path)

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
示例#12
0
    def upload_file(self, remote_path, local_path, progress=None):

        try:
            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 os.path.exists(local_path):
                raise LocalResourceNotFound(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

                request = self.Request(options=options)

                request.perform()
                code = request.getinfo(pycurl.HTTP_CODE)
                if code == "507":
                    raise NotEnoughSpace()

                request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
示例#13
0
    def list(self, remote_path=root, matrix_params=None, query_params=None):
        def parse(response):

            try:
                response_str = response.getvalue()
                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()

        try:
            directory_urn = Urn(remote_path,
                                directory=True,
                                matrix_params=matrix_params,
                                query_params=query_params)

            if directory_urn.path() != Client.root:
                if not self.check(directory_urn.path()):
                    raise RemoteResourceNotFound(directory_urn.path())

            response = BytesIO()

            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'),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

            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]
            ]

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
示例#14
0
    def set_property(self,
                     remote_path,
                     option,
                     matrix_params=None,
                     query_params=None):
        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()

        try:
            urn = Urn(remote_path,
                      matrix_params=matrix_params,
                      query_params=query_params)

            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)
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
示例#15
0
    def upload_to(self, buff, remote_path):
        """Uploads file from buffer to remote path on WebDAV server.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PUT

        :param buff: the buffer with content for file.
        :param remote_path: the path to save file remotely on WebDAV server.
        """
        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())

        self.execute_request(action='upload', path=urn.quote(), data=buff)
示例#16
0
    def download_from(self, buff, remote_path):
        """Downloads file from WebDAV and writes it in buffer.

        :param buff: buffer object for writing of downloaded file content.
        :param remote_path: path to file on WebDAV server.
        """
        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())

        response = self.execute_request(action='download', path=urn.quote())
        buff.write(response.content)
示例#17
0
    def is_dir(self, remote_path):
        """Checks is the remote resource directory.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND

        :param remote_path: the path to remote resource.
        :return: True in case the remote resource is directory and False otherwise.
        """
        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 = self.execute_request(action='info', path=parent_urn.quote())
        path = self.get_full_path(urn)
        return WebDavXmlUtils.parse_is_dir_response(
            content=response.content, path=path, hostname=self.webdav.hostname)
示例#18
0
    def download_file(self,
                      remote_path,
                      local_path,
                      progress=None,
                      matrix_params=None,
                      query_params=None):

        try:
            urn = Urn(remote_path,
                      matrix_params=matrix_params,
                      query_params=query_params)

            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,
                    'NOPROGRESS': 0 if progress else 1,
                    'NOBODY': 0
                }

                if progress:
                    options["PROGRESSFUNCTION"] = progress

                request = self.Request(options=options)

                request.perform()
                request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
示例#19
0
    def check(self, remote_path=root):
        """Checks an existence of remote resource on WebDAV server by remote path.
        More information you can find by link http://webdav.org/specs/rfc4918.html#rfc.section.9.4

        :param remote_path: (optional) path to resource on WebDAV server. Defaults is root directory of WebDAV.
        :return: True if resource is exist or False otherwise
        """
        urn = Urn(remote_path)
        try:
            response = self.execute_request(action='check', path=urn.quote())
        except ResponseErrorCode:
            return False

        if int(response.status_code) == 200:
            return True

        return False
示例#20
0
    def set_property_batch(self, remote_path, option):
        """Sets batch metadata properties of remote resource on WebDAV server in batch.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPPATCH

        :param remote_path: the path to remote resource.
        :param option: the property attributes as list of dictionaries with following keys:
                       `namespace`: (optional) the namespace for XML property which will be set,
                       `name`: the name of property which will be set,
                       `value`: (optional) the value of property which will be set. Defaults is empty string.
        """
        urn = Urn(remote_path)
        if not self.check(urn.path()):
            raise RemoteResourceNotFound(urn.path())

        data = WebDavXmlUtils.create_set_property_batch_request_content(option)
        self.execute_request(action='set_property',
                             path=urn.quote(),
                             data=data)
示例#21
0
    def copy(self, remote_path_from, remote_path_to):
        """Copies resource from one place to another on WebDAV server.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_COPY

        :param remote_path_from: the path to resource which will be copied,
        :param remote_path_to: the path where resource will be copied.
        """
        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())

        header_destination = f'Destination: {self.get_full_path(urn_to)}'
        self.execute_request(action='copy',
                             path=urn_from.quote(),
                             headers_ext=[header_destination])
    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_item = "Destination: {destination}".format(
                destination=destination)

            header = self.get_header('copy')
            header.append(header_item)

            return header

        try:
            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)
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
示例#23
0
    def mkdir(self, remote_path):
        """Makes new directory on WebDAV server.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_MKCOL

        :param remote_path: path to directory
        :return: True if request executed with code 200 or 201 and False otherwise.

        """
        directory_urn = Urn(remote_path, directory=True)

        try:
            response = self.execute_request(action='mkdir',
                                            path=directory_urn.quote())

            return response.status_code in (200, 201)
        except ResponseErrorCode as e:
            if e.code == 405:
                return True

            raise
示例#24
0
    def info(self, remote_path):
        """Gets information about resource on WebDAV.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND

        :param remote_path: the path to remote resource.
        :return: a dictionary of information attributes and them values with following keys:
                 `created`: date of resource creation,
                 `name`: name of resource,
                 `size`: size of resource,
                 `modified`: date of resource modification.
        """
        urn = Urn(remote_path)
        if not self.check(urn.path()) and not self.check(
                Urn(remote_path, directory=True).path()):
            raise RemoteResourceNotFound(remote_path)

        response = self.execute_request(action='info', path=urn.quote())
        path = self.get_full_path(urn)
        return WebDavXmlUtils.parse_info_response(
            content=response.content, path=path, hostname=self.webdav.hostname)
示例#25
0
    def get_property(self, remote_path, option):
        """Gets metadata property of remote resource on WebDAV server.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND

        :param remote_path: the path to remote resource.
        :param option: the property attribute as dictionary with following keys:
                       `namespace`: (optional) the namespace for XML property which will be set,
                       `name`: the name of property which will be set.
        :return: the value of property or None if property is not found.
        """
        urn = Urn(remote_path)
        if not self.check(urn.path()):
            raise RemoteResourceNotFound(urn.path())

        data = WebDavXmlUtils.create_get_property_request_content(option)
        response = self.execute_request(action='get_property',
                                        path=urn.quote(),
                                        data=data)
        return WebDavXmlUtils.parse_get_property_response(
            response.content, option['name'])
示例#26
0
    def list(self, remote_path=root):
        """Returns list of nested files and directories for remote WebDAV directory by path.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND

        :param remote_path: path to remote directory.
        :return: list of nested file or directory names.
        """
        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())

        response = self.execute_request(action='list',
                                        path=directory_urn.quote())
        urns = WebDavXmlUtils.parse_get_list_response(response.content)

        path = Urn.normalize_path(self.get_full_path(directory_urn))
        return [
            urn.filename() for urn in urns
            if Urn.compare_path(path, urn.path()) is False
        ]
    def unpublish(self, remote_path):
        def data(for_server):

            root = etree.Element("propertyupdate", xmlns="DAV:")
            remove = etree.SubElement(root, "remove")
            prop = etree.SubElement(remove, "prop")
            xmlns = Client.meta_xmlns.get(for_server, "")
            etree.SubElement(prop, "public_url", xmlns=xmlns)
            tree = etree.ElementTree(root)

            buff = BytesIO()
            tree.write(buff)

            return buff.getvalue()

        try:
            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['unpublish'],
                'HTTPHEADER': self.get_header('unpublish'),
                'POSTFIELDS': data(for_server=self.webdav.hostname)
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
示例#28
0
    def move(self, remote_path_from, remote_path_to, overwrite=False):
        """Moves resource from one place to another on WebDAV server.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_MOVE

        :param remote_path_from: the path to resource which will be moved,
        :param remote_path_to: the path where resource will be moved.
        :param overwrite: (optional) the flag, overwrite file if it exists. Defaults is False
        """
        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())

        header_destination = f'Destination: {self.get_full_path(urn_to)}'
        header_overwrite = f'Overwrite: {"T" if overwrite else "F"}'
        self.execute_request(
            action='move',
            path=urn_from.quote(),
            headers_ext=[header_destination, header_overwrite])
    def list(self, remote_path=root):

        def parse(response):

            try:
                response_str = response.getvalue()
                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()

        try:
            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())

            response = BytesIO()

            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'),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

            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]]

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def check(self, remote_path=root):

        def parse(response, path):

            try:
                response_str = response.getvalue()
                tree = etree.fromstring(response_str)

                resps = tree.findall("{DAV:}response")

                for resp in resps:
                    href = resp.findtext("{DAV:}href")
                    urn = unquote(href)

                    if path.endswith(Urn.separate):
                        if path == urn or path[:-1] == urn:
                            return True
                    else:
                        if path == urn:
                            return True

                return False

            except etree.XMLSyntaxError:
                raise MethodNotSupported(name="check", server=self.webdav.hostname)

        try:
            urn = Urn(remote_path)
            parent_urn = Urn(urn.parent())
            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'],
                'HTTPHEADER': self.get_header('info'),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

            path = "{root}{path}".format(root=self.webdav.root, path=urn.path())

            return parse(response, path)

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def mkdir(self, remote_path):

        try:
            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'],
                'HTTPHEADER': self.get_header('mkdir')
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def download_to(self, buff, remote_path):

        try:
            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),
                'WRITEFUNCTION': buff.write,
                'HTTPHEADER': self.get_header('download_to'),
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def download_file(self, remote_path, local_path, progress=None):

        try:
            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,
                    'NOPROGRESS': 0 if progress else 1,
                    'NOBODY': 0
                }

                if progress:
                   options["PROGRESSFUNCTION"] = progress

                request = self.Request(options=options)

                request.perform()
                request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def upload_from(self, buff, remote_path):

        try:
            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),
                'HTTPHEADER': self.get_header('upload_from'),
                'UPLOAD': 1,
                'READFUNCTION': buff.read,
            }

            request = self.Request(options=options)

            request.perform()
            code = request.getinfo(pycurl.HTTP_CODE)
            if code == "507":
                raise NotEnoughSpace()

            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def is_dir(self, remote_path):

        def parse(response, path):

            try:
                response_str = response.getvalue()
                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)

        try:
            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'],
                'HTTPHEADER': self.get_header('info'),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

            path = "{root}{path}".format(root=self.webdav.root, path=urn.path())

            return parse(response, path)

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
示例#36
0
    def check(self, remote_path=root):

        try:
            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'],
                'HTTPHEADER': self.get_header('check'),
                'WRITEDATA': response,
                'NOBODY': 1
            }

            request = self.Request(options=options)

            request.perform()
            code = request.getinfo(pycurl.HTTP_CODE)
            request.close()

            if int(code) == 200:
                return True
        
            return False

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def clean(self, remote_path):

        try:
            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')
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def publish(self, remote_path):

        def parse(response):

            try:
                response_str = response.getvalue()
                tree = etree.fromstring(response_str)
                result = tree.xpath("//*[local-name() = 'public_url']")
                public_url = result[0]
                return public_url.text
            except IndexError:
                raise MethodNotSupported(name="publish", server=self.webdav.hostname)
            except etree.XMLSyntaxError:
                return ""

        def data(for_server):

            root_node = etree.Element("propertyupdate", xmlns="DAV:")
            set_node = etree.SubElement(root_node, "set")
            prop_node = etree.SubElement(set_node, "prop")
            xmlns = Client.meta_xmlns.get(for_server, "")
            public_url = etree.SubElement(prop_node, "public_url", xmlns=xmlns)
            public_url.text = "true"
            tree = etree.ElementTree(root_node)

            buff = BytesIO()
            tree.write(buff)

            return buff.getvalue()

        try:
            urn = Urn(remote_path)

            if not self.check(urn.path()):
                raise RemoteResourceNotFound(urn.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['publish'],
                'HTTPHEADER': self.get_header('publish'),
                'POSTFIELDS': data(for_server=self.webdav.hostname),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

            return parse(response)

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def unpublish(self, remote_path):

        def data(for_server):

            root = etree.Element("propertyupdate", xmlns="DAV:")
            remove = etree.SubElement(root, "remove")
            prop = etree.SubElement(remove, "prop")
            xmlns = Client.meta_xmlns.get(for_server, "")
            etree.SubElement(prop, "public_url", xmlns=xmlns)
            tree = etree.ElementTree(root)

            buff = BytesIO()
            tree.write(buff)

            return buff.getvalue()

        try:
            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['unpublish'],
                'HTTPHEADER': self.get_header('unpublish'),
                'POSTFIELDS': data(for_server=self.webdav.hostname)
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    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()

        try:
            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)
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def get_property(self, remote_path, option):

        def parse(response, option):

            response_str = response.getvalue()
            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()

        try:
            urn = Urn(remote_path)

            if not self.check(urn.path()):
                raise RemoteResourceNotFound(urn.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['get_metadata'],
                'HTTPHEADER': self.get_header('get_metadata'),
                'POSTFIELDS': data(option),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

            return parse(response, option)

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def info(self, remote_path):
        def parse(response, path):

            try:
                response_str = response.getvalue()
                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)

        try:
            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'],
                'HTTPHEADER': self.get_header('info'),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

            path = "{root}{path}".format(root=self.webdav.root,
                                         path=urn.path())

            return parse(response, path)

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def upload_file(self, remote_path, local_path, progress=None):

        try:
            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 os.path.exists(local_path):
                raise LocalResourceNotFound(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

                request = self.Request(options=options)

                request.perform()
                code = request.getinfo(pycurl.HTTP_CODE)
                if code == "507":
                    raise NotEnoughSpace()

                request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def info(self, remote_path):

        def parse(response, path):

            try:
                response_str = response.getvalue()
                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)

        try:
            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'],
                'HTTPHEADER': self.get_header('info'),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

            path = "{root}{path}".format(root=self.webdav.root, path=urn.path())

            return parse(response, path)

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def is_dir(self, remote_path):
        def parse(response, path):

            try:
                response_str = response.getvalue()
                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)

        try:
            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'],
                'HTTPHEADER': self.get_header('info'),
                'WRITEDATA': response,
                'NOBODY': 0
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

            path = "{root}{path}".format(root=self.webdav.root,
                                         path=urn.path())

            return parse(response, path)

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)
    def move(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_item = "Destination: {destination}".format(destination=destination)
            header = self.get_header('move')
            header.append(header_item)
            return header

        try:
            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['move'],
                'HTTPHEADER': header(remote_path_to)
            }

            request = self.Request(options=options)

            request.perform()
            request.close()

        except pycurl.error:
            raise NotConnection(self.webdav.hostname)