Пример #1
0
    def _isValidZIPLink(self, link, subPath):
        '''
        Returns true if the file identified by subpath exists in
        the given link to a ZIP archive, false otherwise.

        @param link: list
            Link description in JSON format.
        @param subPath: string
            The path inside the linked directory (if needed)
        '''
        zipFilePath = normOSPath(link[1])
        inFilePath = normOSPath(link[2], True)
        zipFile = ZipFile(zipFilePath)
        inZipFile = normZipPath(join(inFilePath, subPath)) if subPath else normZipPath(inFilePath)
        return inZipFile in zipFile.NameToInfo
Пример #2
0
    def _isValidZIPLink(self, link, subPath):
        '''
        Returns true if the file identified by subpath exists in
        the given link to a ZIP archive, false otherwise.

        @param link: list
            Link description in JSON format.
        @param subPath: string
            The path inside the linked directory (if needed)
        '''
        zipFilePath = normOSPath(link[1])
        inFilePath = normOSPath(link[2], True)
        zipFile = ZipFile(zipFilePath)
        inZipFile = normZipPath(join(inFilePath, subPath)) if subPath else normZipPath(inFilePath)
        return inZipFile in zipFile.NameToInfo
Пример #3
0
    def _copyZipDir(self, zipFilePath, inDirPath, path):
        '''
        Copy a directory from a ZIP archive to a filesystem directory

        @param zipFilePath: string
            The path of the ZIP archive
        @param inDirPath: string
            The path to the file in the ZIP archive
        @param path: string
            Destination path where the ZIP directory is copied
        '''
        # make sure the ZIP file path is normalized and uses the OS separator
        zipFilePath = normOSPath(zipFilePath)
        # make sure the ZIP file path is normalized and uses the ZIP separator
        inDirPath = normZipPath(inDirPath)
        zipFile = ZipFile(zipFilePath)
        if isdir(path):
            if self._isSyncFile(zipFilePath, path):
                return
            rmtree(path)
        entries = [ent for ent in zipFile.namelist() if ent.startswith(inDirPath)]
        tmpDir = TemporaryDirectory()
        zipFile.extractall(tmpDir.name, entries)
        tmpDirPath = join(tmpDir.name, normOSPath(inDirPath))
        os.makedirs(path)
        for entry in os.listdir(tmpDirPath):
            move(join(tmpDirPath, entry), path)
Пример #4
0
    def _copyZipDir(self, zipFilePath, inDirPath, path):
        '''
        Copy a directory from a ZIP archive to a filesystem directory

        @param zipFilePath: string
            The path of the ZIP archive
        @param inDirPath: string
            The path to the file in the ZIP archive
        @param path: string
            Destination path where the ZIP directory is copied
        '''
        # make sure the ZIP file path is normalized and uses the OS separator
        zipFilePath = normOSPath(zipFilePath)
        # make sure the ZIP file path is normalized and uses the ZIP separator
        inDirPath = normZipPath(inDirPath)
        zipFile = ZipFile(zipFilePath)
        entries = [ent for ent in zipFile.namelist() if ent.startswith(inDirPath)]
        tmpDir = TemporaryDirectory()
        zipFile.extractall(tmpDir.name, entries)
        tmpDirPath = join(tmpDir.name, normOSPath(inDirPath))
        if not isdir(path): os.makedirs(path)
        for entry in os.listdir(tmpDirPath):
            dstPath = join(path, entry)
            if isfile(dstPath): os.remove(dstPath)
            elif isdir(dstPath): rmtree(dstPath)
            move(join(tmpDirPath, entry), path)
Пример #5
0
    def process(self, errorProcessing, chain, request, response, responseCnt, **keyargs):
        '''
        @see: HandlerProcessor.process
        
        Provide the file content as a response.
        '''
        assert isinstance(errorProcessing, Processing), 'Invalid processing %s' % errorProcessing
        assert isinstance(chain, Chain), 'Invalid processors chain %s' % chain
        assert isinstance(request, Request), 'Invalid request %s' % request
        assert isinstance(response, Response), 'Invalid response %s' % response
        assert isinstance(responseCnt, ResponseContent), 'Invalid response content %s' % responseCnt

        if request.method != GET:
            response.allows = GET
            response.code, response.text = METHOD_NOT_AVAILABLE, 'Path only available for GET'
        else:
            chain.proceed()
            # Make sure the given path points inside the repository
            entryPath = normOSPath(join(self.repositoryPath, normZipPath(unquote(request.uri))))
            if not entryPath.startswith(self.repositoryPath):
                response.code, response.text = RESOURCE_NOT_FOUND, 'Out of repository path'
            else:
                # Initialize the read file handler with None value
                # This will be set upon successful file open
                rf = None
                if isfile(entryPath):
                    rf, size = open(entryPath, 'rb'), os.path.getsize(entryPath)
                else:
                    linkPath = entryPath
                    while len(linkPath) > len(self.repositoryPath):
                        if isfile(linkPath + self._linkExt):
                            with open(linkPath + self._linkExt) as f: links = json.load(f)
                            subPath = normOSPath(entryPath[len(linkPath):]).lstrip(sep)
                            for linkType, *data in links:
                                if linkType in self._linkTypes:
                                    # make sure the subpath is normalized and uses the OS separator
                                    if not self._isPathDeleted(join(linkPath, subPath)):
                                        entry = self._linkTypes[linkType](subPath, *data)
                                        if entry is not None:
                                            rf, size = entry
                                            break
                            break
                        subLinkPath = dirname(linkPath)
                        if subLinkPath == linkPath:
                            break
                        linkPath = subLinkPath
        
                if rf is None:
                    response.code, response.text = METHOD_NOT_AVAILABLE, 'Invalid content resource'
                else:
                    response.code, response.text = RESOURCE_FOUND, 'Resource found'
                    responseCnt.source = rf
                    responseCnt.length = size
                    responseCnt.type, _encoding = guess_type(entryPath)
                    if not responseCnt.type: responseCnt.type = self.defaultContentType
                    return
        
        chain.branch(errorProcessing)
Пример #6
0
    def process(self, request:Request, response:Response, responseCnt:ResponseContent, **keyargs):
        '''
        @see: HandlerProcessorProceed.process
        
        Provide the file content as a response.
        '''
        assert isinstance(request, Request), 'Invalid request %s' % request
        assert isinstance(response, Response), 'Invalid response %s' % response
        assert isinstance(responseCnt, ResponseContent), 'Invalid response content %s' % responseCnt

        if request.method != HTTP_GET:
            if response.allows is not None: response.allows.append(HTTP_GET)
            else: response.allows = [HTTP_GET]
            response.code, response.status, response.isSuccess = METHOD_NOT_AVAILABLE
        else:
            # Make sure the given path points inside the repository
            entryPath = normOSPath(join(self.repositoryPath, normZipPath(unquote(request.uri))))
            if not entryPath.startswith(self.repositoryPath):
                response.code, response.status, response.isSuccess = PATH_NOT_FOUND
            else:
                # Initialize the read file handler with None value
                # This will be set upon successful file open
                rf = None
                if isfile(entryPath):
                    rf, size = open(entryPath, 'rb'), os.path.getsize(entryPath)
                else:
                    linkPath = entryPath
                    while len(linkPath) > len(self.repositoryPath):
                        if isfile(linkPath + self._linkExt):
                            with open(linkPath + self._linkExt) as f: links = json.load(f)
                            subPath = normOSPath(entryPath[len(linkPath):]).lstrip(sep)
                            for linkType, *data in links:
                                if linkType in self._linkTypes:
                                    # make sure the subpath is normalized and uses the OS separator
                                    if not self._isPathDeleted(join(linkPath, subPath)):
                                        entry = self._linkTypes[linkType](subPath, *data)
                                        if entry is not None:
                                            rf, size = entry
                                            break
                            break
                        subLinkPath = dirname(linkPath)
                        if subLinkPath == linkPath:
                            break
                        linkPath = subLinkPath
        
                if rf is None:
                    response.code, response.status, response.isSuccess = PATH_NOT_FOUND
                else:
                    response.code, response.status, response.isSuccess = PATH_FOUND
                    responseCnt.source = rf
                    responseCnt.length = size
                    responseCnt.type, _encoding = guess_type(entryPath)
                    if not responseCnt.type: responseCnt.type = self.defaultContentType
                    responseCnt.type += '; charset=utf-8'
                    return
Пример #7
0
    def _createLinkToZipFile(self, path, zipFilePath, inFilePath):
        repFilePath = self._getItemPath(path) + self._linkExt
        if isfile(repFilePath):
            with open(repFilePath, 'r') as f: links = json.load(f)
        else: links = []
        inFilePath = normZipPath(inFilePath)
        for k, entry in enumerate(links):
            if entry and entry[0] == self._zipHeader:
                if entry[1] == zipFilePath and entry[2] == inFilePath:
                    if k > 0: links.insert(0, links.pop(k))
                    break
        else: links.insert(0, (self._zipHeader, zipFilePath, inFilePath))

        with open(repFilePath, 'w') as f: json.dump(links, f)
Пример #8
0
 def _processZiplink(self, subPath, zipFilePath, inFilePath):
     '''
     Reads a link description file and returns a file handler to
     the linked file inside the ZIP archive.
     '''
     # make sure the ZIP file path uses the OS separator
     zipFilePath = normOSPath(zipFilePath)
     # convert the internal ZIP path to OS format in order to use standard path functions
     inFilePath = normOSPath(inFilePath)
     zipFile = ZipFile(zipFilePath)
     # resource internal ZIP path should be in ZIP format
     resPath = normZipPath(join(inFilePath, subPath))
     if resPath in zipFile.NameToInfo:
         return zipFile.open(resPath, 'r'), zipFile.getinfo(resPath).file_size
Пример #9
0
    def _createLinkToZipFile(self, path, zipFilePath, inFilePath):
        repFilePath = self._getItemPath(path) + self._linkExt
        if isfile(repFilePath):
            with open(repFilePath, 'r') as f: links = json.load(f)
        else: links = []
        inFilePath = normZipPath(inFilePath)
        for k, entry in enumerate(links):
            if entry and entry[0] == self._zipHeader:
                if entry[1] == zipFilePath and entry[2] == inFilePath:
                    if k > 0: links.insert(0, links.pop(k))
                    break
        else: links.insert(0, (self._zipHeader, zipFilePath, inFilePath))

        with open(repFilePath, 'w') as f: json.dump(links, f)
Пример #10
0
 def _processZiplink(self, subPath, zipFilePath, inFilePath):
     '''
     Reads a link description file and returns a file handler to
     the linked file inside the ZIP archive.
     '''
     # make sure the ZIP file path uses the OS separator
     zipFilePath = normOSPath(zipFilePath)
     # convert the internal ZIP path to OS format in order to use standard path functions
     inFilePath = normOSPath(inFilePath)
     zipFile = ZipFile(zipFilePath)
     # resource internal ZIP path should be in ZIP format
     resPath = normZipPath(join(inFilePath, subPath))
     if resPath in zipFile.NameToInfo:
         return zipFile.open(resPath,
                             'r'), zipFile.getinfo(resPath).file_size
Пример #11
0
    def _removeZiplink(self, link, path, entryPath, subPath):
        '''
        Removes a link to a file or directory in a ZIP archive.

        @param link: list
            Link description in JSON format.
        @param path: string
            The repository path to remove.
        @param entryPath: string
            The full path for which to create the deletion mark.
        @param subPath: string
            The path inside the linked ZIP archive.
        '''
        zipFilePath = normOSPath(link[1])
        inFilePath = normOSPath(link[2], True)
        zipFile = ZipFile(zipFilePath)
        inZipFile = normZipPath(join(inFilePath, subPath))
        if not inZipFile in zipFile.NameToInfo:
            raise PathNotFound(path)
        self._createDelMark(entryPath)
Пример #12
0
    def _removeZiplink(self, link, path, entryPath, subPath):
        '''
        Removes a link to a file or directory in a ZIP archive.

        @param link: list
            Link description in JSON format.
        @param path: string
            The repository path to remove.
        @param entryPath: string
            The full path for which to create the deletion mark.
        @param subPath: string
            The path inside the linked ZIP archive.
        '''
        zipFilePath = normOSPath(link[1])
        inFilePath = normOSPath(link[2], True)
        zipFile = ZipFile(zipFilePath)
        inZipFile = normZipPath(join(inFilePath, subPath))
        if not inZipFile in zipFile.NameToInfo:
            raise PathNotFound(path)
        self._createDelMark(entryPath)
Пример #13
0
    def process(self, request: Request, response: Response,
                responseCnt: ResponseContent, **keyargs):
        '''
        @see: HandlerProcessorProceed.process
        
        Provide the file content as a response.
        '''
        assert isinstance(request, Request), 'Invalid request %s' % request
        assert isinstance(response, Response), 'Invalid response %s' % response
        assert isinstance(
            responseCnt,
            ResponseContent), 'Invalid response content %s' % responseCnt

        if request.method != HTTP_GET:
            if response.allows is not None: response.allows.append(HTTP_GET)
            else: response.allows = [HTTP_GET]
            response.code, response.status, response.isSuccess = METHOD_NOT_AVAILABLE
        else:
            # Make sure the given path points inside the repository
            entryPath = normOSPath(
                join(self.repositoryPath, normZipPath(unquote(request.uri))))
            if not entryPath.startswith(self.repositoryPath):
                response.code, response.status, response.isSuccess = PATH_NOT_FOUND
            else:
                # Initialize the read file handler with None value
                # This will be set upon successful file open
                rf = None
                if isfile(entryPath):
                    rf, size = open(entryPath,
                                    'rb'), os.path.getsize(entryPath)
                else:
                    linkPath = entryPath
                    while len(linkPath) > len(self.repositoryPath):
                        if isfile(linkPath + self._linkExt):
                            with open(linkPath + self._linkExt) as f:
                                links = json.load(f)
                            subPath = normOSPath(
                                entryPath[len(linkPath):]).lstrip(sep)
                            for linkType, *data in links:
                                if linkType in self._linkTypes:
                                    # make sure the subpath is normalized and uses the OS separator
                                    if not self._isPathDeleted(
                                            join(linkPath, subPath)):
                                        entry = self._linkTypes[linkType](
                                            subPath, *data)
                                        if entry is not None:
                                            rf, size = entry
                                            break
                            break
                        subLinkPath = dirname(linkPath)
                        if subLinkPath == linkPath:
                            break
                        linkPath = subLinkPath

                if rf is None:
                    response.code, response.status, response.isSuccess = PATH_NOT_FOUND
                else:
                    response.code, response.status, response.isSuccess = PATH_FOUND
                    responseCnt.source = rf
                    responseCnt.length = size
                    responseCnt.type, _encoding = guess_type(entryPath)
                    if not responseCnt.type:
                        responseCnt.type = self.defaultContentType
                    responseCnt.type += '; charset=utf-8'
                    return
Пример #14
0
 def _validatePath(self, path):
     path = normZipPath(path)
     fullPath = normOSPath(self._getItemPath(path), True)
     if not fullPath.startswith(self.delivery.getRepositoryPath()):
         raise PathNotFound(path)
     return (path, fullPath)