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)
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)
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)
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
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
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
def __init__(self): assert isinstance(self.serverURI, str), 'Invalid server URI value %s' % self.serverURI assert isinstance(self.repositoryPath, str), 'Invalid repository directory value %s' % self.repositoryPath self.repositoryPath = normOSPath(self.repositoryPath) if not os.path.exists(self.repositoryPath): os.makedirs(self.repositoryPath) assert isdir(self.repositoryPath) and os.access(self.repositoryPath, os.W_OK), \ 'Unable to access the repository directory %s' % self.repositoryPath
def publishFromDir(self, path, dirPath): ''' @see ICDM.publishFromDir ''' assert isinstance( path, str) and len(path) > 0, 'Invalid content path %s' % path assert isinstance(dirPath, str), 'Invalid directory path value %s' % dirPath path, fullPath = self._validatePath(path) if not isdir(dirPath): # not a directory, see if it's a entry in a zip file zipFilePath, inDirPath = getZipFilePath( dirPath, self.delivery.getRepositoryPath()) if not inDirPath.endswith(ZIPSEP): inDirPath = inDirPath + ZIPSEP self._copyZipDir(zipFilePath, inDirPath, fullPath) assert log.debug('Success publishing ZIP dir %s (%s) to path %s', inDirPath, zipFilePath, path) or True return dirPath = normpath(dirPath) assert os.access( dirPath, os.R_OK), 'Unable to read the directory path %s' % dirPath for root, _dirs, files in os.walk(dirPath): relPath = relpath(root, dirPath) for file in files: publishPath = join(normOSPath(path), relPath.lstrip(os.sep), file) filePath = join(root, file) self.publishFromFile(publishPath, filePath) assert log.debug('Success publishing directory %s to path %s', dirPath, path) or True
def __init__(self): assert isinstance(self.dumpRequestsSize, int), 'Invalid dump size %s' % self.dumpRequestsSize assert isinstance(self.dumpRequestsPath, str), 'Invalid dump path %s' % self.dumpRequestsPath self.dumpRequestsPath = normOSPath(self.dumpRequestsPath) if not os.path.exists(self.dumpRequestsPath): os.makedirs(self.dumpRequestsPath) assert isdir(self.dumpRequestsPath) and os.access(self.dumpRequestsPath, os.W_OK), \ 'Unable to access the dump directory %s' % self.dumpRequestsPath super().__init__() self._count = 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)
def synchronizeURIToDir(path, dirPath): ''' Publishes the entire contents from the URI path to the provided directory path. @param path: string The path to a resource: a file system path, a ZIP path @param dirPath: string The directory path to synchronize with. ''' assert isinstance(path, str) and path, 'Invalid content path %s' % path assert isinstance(dirPath, str), 'Invalid directory path value %s' % dirPath if not isdir(path): # not a directory, see if it's a entry in a zip file zipFilePath, inDirPath = getZipFilePath(path) zipFile = ZipFile(zipFilePath) if not inDirPath.endswith(ZIPSEP): inDirPath = inDirPath + ZIPSEP tmpDir = TemporaryDirectory() lenPath, zipTime = len(inDirPath), datetime.fromtimestamp(stat(zipFilePath).st_mtime) for zipInfo in zipFile.filelist: assert isinstance(zipInfo, ZipInfo), 'Invalid zip info %s' % zipInfo if zipInfo.filename.startswith(inDirPath): if zipInfo.filename[0] == '/': dest = zipInfo.filename[1:] else: dest = zipInfo.filename dest = normpath(join(dirPath, dest[lenPath:])) if exists(dest) and zipTime <= datetime.fromtimestamp(stat(dest).st_mtime): continue destDir = dirname(dest) if not exists(destDir): makedirs(destDir) zipFile.extract(zipInfo.filename, tmpDir.name) move(join(tmpDir.name, normOSPath(zipInfo.filename)), dest) if zipInfo.filename.endswith('.exe'): os.chmod(dest, stat(dest).st_mode | S_IEXEC) return path = normpath(path) assert os.access(path, os.R_OK), 'Unable to read the directory path %s' % path lenPath = len(path) + 1 for root, _dirs, files in os.walk(path): for file in files: src, dest = join(root, file), join(dirPath, root[lenPath:], file) if exists(dest) and \ datetime.fromtimestamp(stat(src).st_mtime) <= datetime.fromtimestamp(stat(dest).st_mtime): continue destDir = dirname(dest) if not exists(destDir): makedirs(destDir) copy(src, dest) if file.endswith('.exe'): os.chmod(dest, stat(dest).st_mode | S_IEXEC)
def timestampURI(path): ''' Returns the last modified time stamp for the given path. @param path: string The path to a resource: a file system path, a ZIP path @return: datetime The last modified time stamp. ''' path = normOSPath(path) if isfile(path): return datetime.fromtimestamp(stat(path).st_mtime) zipFilePath, _inZipPath = getZipFilePath(path) return datetime.fromtimestamp(stat(zipFilePath).st_mtime)
def _processLink(self, subPath, linkedFilePath): ''' Reads a link description file and returns a file handler to the linked file. ''' # make sure the file path uses the OS separator linkedFilePath = normOSPath(linkedFilePath) if isdir(linkedFilePath): resPath = join(linkedFilePath, subPath) elif not subPath: resPath = linkedFilePath else: return None if isfile(resPath): return open(resPath, 'rb'), os.path.getsize(resPath)
def openURI(path): """ Returns a read file object for the given path. @param path: string The path to a resource: a file system path, a ZIP path @return: byte file A file like object that delivers bytes. """ path = normOSPath(path) if isfile(path): return open(path, "rb") zipFilePath, inZipPath = getZipFilePath(path) zipFile = ZipFile(zipFilePath) if inZipPath in zipFile.NameToInfo and not inZipPath.endswith(ZIPSEP) and inZipPath != "": return zipFile.open(inZipPath) raise IOError("Invalid file path %s" % path)
def openURI(path, byteMode=True): ''' Returns a read file object for the given path. @param path: string The path to a resource: a file system path, a ZIP path @return: byte file A file like object that delivers bytes. ''' path = normOSPath(path) mode = 'rb' if byteMode else 'rt' if isfile(path): return open(path, mode) zipFilePath, inZipPath = getZipFilePath(path) zipFile = ZipFile(zipFilePath) if inZipPath in zipFile.NameToInfo and not inZipPath.endswith(ZIPSEP) and inZipPath != '': f = zipFile.open(inZipPath) if byteMode: return f else: return StringIO(f.read().decode()) raise IOError('Invalid file path %s' % path)
def openURI(path, byteMode=True): ''' Returns a read file object for the given path. @param path: string The path to a resource: a file system path, a ZIP path @return: byte file A file like object that delivers bytes. ''' path = normOSPath(path) mode = 'rb' if byteMode else 'rt' if isfile(path): return open(path, mode) zipFilePath, inZipPath = getZipFilePath(path) zipFile = ZipFile(zipFilePath) if inZipPath in zipFile.NameToInfo and not inZipPath.endswith( ZIPSEP) and inZipPath != '': f = zipFile.open(inZipPath) if byteMode: return f else: return StringIO(f.read().decode()) raise IOError('Invalid file path %s' % path)
def publishFromDir(self, path, dirPath): ''' @see ICDM.publishFromDir ''' assert isinstance(path, str) and len(path) > 0, 'Invalid content path %s' % path assert isinstance(dirPath, str), 'Invalid directory path value %s' % dirPath path, fullPath = self._validatePath(path) if not isdir(dirPath): # not a directory, see if it's a entry in a zip file zipFilePath, inDirPath = getZipFilePath(dirPath, self.delivery.getRepositoryPath()) if not inDirPath.endswith(ZIPSEP): inDirPath = inDirPath + ZIPSEP self._copyZipDir(zipFilePath, inDirPath, fullPath) assert log.debug('Success publishing ZIP dir %s (%s) to path %s', inDirPath, zipFilePath, path) or True return dirPath = normpath(dirPath) assert os.access(dirPath, os.R_OK), 'Unable to read the directory path %s' % dirPath for root, _dirs, files in os.walk(dirPath): relPath = relpath(root, dirPath) for file in files: publishPath = join(normOSPath(path), relPath.lstrip(os.sep), file) filePath = join(root, file) self.publishFromFile(publishPath, filePath) assert log.debug('Success publishing directory %s to path %s', dirPath, path) or True
def testLocalFileSystemLinkCDM(self): d = HTTPDelivery() rootDir = TemporaryDirectory() d.serverURI = 'http://localhost/content/' d.repositoryPath = rootDir.name d.repositoryPath = '/var/www/repository' # ioc.Initializer.initialize(d) cdm = LocalFileSystemLinkCDM() cdm.delivery = d try: exceptionRaised = False cdm.publishFromFile('a/../../b', 'somefile.txt') except PathNotFound: exceptionRaised = True self.assertTrue(exceptionRaised, 'No exception was raised on out of repository path') # test publish from a file from the file system try: srcTmpFile = NamedTemporaryFile() dstFile = join('testdir7', 'tempfile.txt') cdm.publishFromFile(dstFile, srcTmpFile.name) dstLinkPath = join(d.getRepositoryPath(), dstFile + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertIsInstance(links, list) self.assertEqual(links[0][0], 'FS') self.assertEqual(srcTmpFile.name, links[0][1]) self.assertEqual(stat(srcTmpFile.name).st_mtime, cdm.getTimestamp('testdir7/tempfile.txt')) finally: rmtree(dirname(dstLinkPath)) # test publish from a file from a zip archive try: dstFile = join('testdir8', 'tempfile2.txt') inFileName = join('dir1', 'subdir2', 'file1.txt') srcFilePath = join(dirname(__file__), 'test.zip', inFileName) cdm.publishFromFile(dstFile, srcFilePath) dstLinkPath = join(d.getRepositoryPath(), dstFile + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertEqual(links[0][0], 'ZIP') zipPath = links[0][1] inPath = normOSPath(links[0][2], True) linkPath = join(zipPath, inPath) self.assertEqual(normpath(linkPath), normpath(srcFilePath)) self.assertEqual(stat(join(dirname(__file__), 'test.zip')).st_mtime, cdm.getTimestamp('testdir8/tempfile2.txt')) finally: rmtree(dirname(dstLinkPath)) # test publish from a directory from the file system srcTmpDir = TemporaryDirectory() dirs = (join(srcTmpDir.name, 'test1/subdir1'), join(srcTmpDir.name, 'test2/subdir1')) for dir in dirs: makedirs(dir) with open(join(dir, 'text.html'), 'w+') as _f: pass try: cdm.publishFromDir('testlink1', srcTmpDir.name) dstLinkPath = join(d.getRepositoryPath(), 'testlink1' + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertEqual(links[0][0], 'FS') self.assertEqual(srcTmpDir.name, links[0][1]) self.assertEqual(stat(join(srcTmpDir.name, 'test1/subdir1/text.html')).st_mtime, cdm.getTimestamp('testlink1/test1/subdir1/text.html')) # test path remove delPath1 = 'testlink1/test1/subdir1/text.html' cdm.removePath(delPath1) self.assertTrue(isfile(join(d.getRepositoryPath(), delPath1 + '.deleted'))) delPath2 = 'testlink1/test1' cdm.removePath(delPath2) self.assertTrue(isfile(join(d.getRepositoryPath(), delPath2 + '.deleted'))) finally: rmtree(join(d.getRepositoryPath(), 'testlink1')) remove(dstLinkPath) # test publish from a file from a zip archive try: srcFilePath = join(dirname(__file__), 'test.zip', 'dir1') + sep cdm.publishFromFile('testlink2', srcFilePath) dstLinkPath = join(d.getRepositoryPath(), 'testlink2' + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertEqual(links[0][0], 'ZIP') zipPath = links[0][1] inPath = normOSPath(links[0][2], True) link = join(zipPath, inPath) self.assertEqual(link, srcFilePath) self.assertEqual(stat(join(dirname(__file__), 'test.zip')).st_mtime, cdm.getTimestamp('testlink2/subdir1/file1.txt')) # test path remove delPath1 = 'testlink2/subdir1/file1.txt' cdm.removePath(delPath1) self.assertTrue(isfile(join(d.getRepositoryPath(), delPath1 + '.deleted'))) delPath2 = 'testlink2/subdir1/' self.assertTrue(isdir(join(d.getRepositoryPath(), delPath2))) cdm.removePath(delPath2) self.assertTrue(isfile(join(d.getRepositoryPath(), delPath2.rstrip('/') + '.deleted'))) self.assertFalse(isdir(join(d.getRepositoryPath(), delPath2))) self.assertFalse(isfile(join(d.getRepositoryPath(), delPath1 + '.deleted'))) finally: rmtree(join(d.getRepositoryPath(), 'testlink2')) remove(dstLinkPath)
def _validatePath(self, path): path = normOSPath(path, True) fullPath = normOSPath(self._getItemPath(path), True) if not fullPath.startswith(self.delivery.getRepositoryPath()): raise PathNotFound('Path is outside the repository: %s' % path) return (path, fullPath)
def _getItemPath(self, path): return join(self.delivery.getRepositoryPath(), normOSPath(path.lstrip(os.sep), True))
def synchronizeURIToDir(path, dirPath): ''' Publishes the entire contents from the URI path to the provided directory path. @param path: string The path to a resource: a file system path, a ZIP path @param dirPath: string The directory path to synchronize with. ''' assert isinstance(path, str) and path, 'Invalid content path %s' % path assert isinstance(dirPath, str), 'Invalid directory path value %s' % dirPath if not isdir(path): # not a directory, see if it's a entry in a zip file zipFilePath, inDirPath = getZipFilePath(path) zipFile = ZipFile(zipFilePath) if not inDirPath.endswith(ZIPSEP): inDirPath = inDirPath + ZIPSEP tmpDir = TemporaryDirectory() lenPath, zipTime = len(inDirPath), datetime.fromtimestamp( stat(zipFilePath).st_mtime) for zipInfo in zipFile.filelist: assert isinstance(zipInfo, ZipInfo), 'Invalid zip info %s' % zipInfo if zipInfo.filename.startswith(inDirPath): if zipInfo.filename[0] == '/': dest = zipInfo.filename[1:] else: dest = zipInfo.filename dest = normpath(join(dirPath, dest[lenPath:])) if exists(dest) and zipTime <= datetime.fromtimestamp( stat(dest).st_mtime): continue destDir = dirname(dest) if not exists(destDir): makedirs(destDir) zipFile.extract(zipInfo.filename, tmpDir.name) move(join(tmpDir.name, normOSPath(zipInfo.filename)), dest) if zipInfo.filename.endswith('.exe'): os.chmod(dest, stat(dest).st_mode | S_IEXEC) return path = normpath(path) assert os.access(path, os.R_OK), 'Unable to read the directory path %s' % path lenPath = len(path) + 1 for root, _dirs, files in os.walk(path): for file in files: src, dest = join(root, file), join(dirPath, root[lenPath:], file) if exists(dest) and \ datetime.fromtimestamp(stat(src).st_mtime) <= datetime.fromtimestamp(stat(dest).st_mtime): continue destDir = dirname(dest) if not exists(destDir): makedirs(destDir) copy(src, dest) if file.endswith('.exe'): os.chmod(dest, stat(dest).st_mode | S_IEXEC)
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
def testLocalFilesystemCDM(self): d = HTTPDelivery() rootDir = TemporaryDirectory() d.serverURI = 'http://localhost/content/' d.repositoryPath = rootDir.name # d.repositoryPath = '/var/www/repository' # ioc.Initializer.initialize(d) cdm = LocalFileSystemCDM() cdm.delivery = d # test publish from a file from the file system try: srcTmpFile = NamedTemporaryFile(delete=False) srcTmpFile.close() dstPath = 'testdir1/tempfile.txt' cdm.publishFromFile(dstPath, srcTmpFile.name) dstFilePath = join(d.getRepositoryPath(), normOSPath(dstPath)) self.assertTrue(isfile(dstFilePath)) self.assertEqual(datetime.fromtimestamp(stat(dstFilePath).st_mtime), cdm.getTimestamp(dstPath)) finally: rmtree(dirname(dstFilePath)) remove(srcTmpFile.name) # test publish from a file from a zip archive try: inFileName = join('dir1', 'subdir2', 'file1.txt') dstPath = join('testdir2', 'tempfile2.txt') cdm.publishFromFile(dstPath, join(dirname(__file__), 'test.zip', inFileName)) dstFilePath = join(d.getRepositoryPath(), normOSPath(dstPath)) self.assertTrue(isfile(dstFilePath)) finally: rmtree(dirname(dstFilePath)) # test publish from a directory from the file system srcTmpDir = TemporaryDirectory() dirs = ('test1/subdir1', 'test2/subdir1') for dir in dirs: fullPath = join(srcTmpDir.name, dir) makedirs(fullPath) with open(join(fullPath, 'text.html'), 'w') as _f: pass try: cdm.publishFromDir('testdir3', srcTmpDir.name) dstDirPath = join(d.getRepositoryPath(), 'testdir3') for dir in dirs: dstFilePath = join(dstDirPath, dir, 'text.html') self.assertTrue(isfile(dstFilePath)) self.assertEqual(datetime.fromtimestamp(stat(dstFilePath).st_mtime), cdm.getTimestamp(join('testdir3', dir, 'text.html'))) # test remove path filePath = 'testdir3/test1/subdir1/text.html' self.assertTrue(isfile(join(d.getRepositoryPath(), filePath))) cdm.republish(filePath, filePath + '.new') self.assertTrue(isfile(join(d.getRepositoryPath(), filePath + '.new'))) cdm.republish(filePath + '.new', filePath) cdm.remove(filePath) self.assertFalse(isfile(join(d.getRepositoryPath(), filePath))) dirPath = 'testdir3/test2' self.assertTrue(isdir(join(d.getRepositoryPath(), dirPath))) cdm.remove(dirPath) self.assertFalse(isdir(join(d.getRepositoryPath(), dirPath))) finally: rmtree(dstDirPath) # test publish from a directory from a zip file try: cdm.publishFromDir('testdir4', join(dirname(__file__), 'test.zip', 'dir1')) dstDirPath = join(d.getRepositoryPath(), 'testdir4') dstFilePath = join(dstDirPath, 'subdir1', 'file1.txt') self.assertTrue(isfile(dstFilePath)) dstFilePath = join(dstDirPath, 'subdir2', 'file2.txt') self.assertTrue(isfile(dstFilePath)) # Test whether republishing the same directory checks the last modified date # The file created manually in the repository should not be deleted because # the zip archive was not modified from the last publish dstFilePath = join(dstDirPath, 'sometestfile.txt') with open(dstFilePath, 'w') as _f: pass cdm.publishFromDir('testdir4', join(dirname(__file__), 'test.zip', 'dir1')) self.assertTrue(isfile(dstFilePath)) finally: rmtree(dstDirPath) # test publish from a string try: path = join('testdir5', 'somecontent.txt') cdm.publishContent(path, BytesIO(b'test')) dstFilePath = join(d.getRepositoryPath(), path) self.assertTrue(isfile(dstFilePath)) finally: rmtree(join(d.getRepositoryPath(), dirname(path))) # test publish from a file object try: path = join('testdir6', 'somecontent2.txt') cdm.publishFromFile(path, BytesIO(b'test 2')) dstFilePath = join(d.getRepositoryPath(), path) self.assertTrue(isfile(dstFilePath)) finally: rmtree(join(d.getRepositoryPath(), dirname(path)))
def testLocalFileSystemLinkCDM(self): d = HTTPDelivery() rootDir = TemporaryDirectory() d.serverURI = 'http://localhost/content/' d.repositoryPath = rootDir.name # d.repositoryPath = '/var/www/repository' # ioc.Initializer.initialize(d) cdm = LocalFileSystemLinkCDM() cdm.delivery = d try: exceptionRaised = False cdm.publishFromFile('a/../../b', 'somefile.txt') except PathNotFound: exceptionRaised = True self.assertTrue(exceptionRaised, 'No exception was raised on out of repository path') # test publish from a file from the file system try: srcTmpFile = NamedTemporaryFile() dstFile = join('testdir7', 'tempfile.txt') cdm.publishFromFile(dstFile, srcTmpFile.name) dstLinkPath = join(d.getRepositoryPath(), dstFile + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertIsInstance(links, list) self.assertEqual(links[0][0], 'FS') self.assertEqual(srcTmpFile.name, links[0][1]) self.assertEqual( datetime.fromtimestamp(stat(srcTmpFile.name).st_mtime), cdm.getTimestamp('testdir7/tempfile.txt')) finally: rmtree(dirname(dstLinkPath)) # test publish from a file from a zip archive try: dstFile = join('testdir8', 'tempfile2.txt') inFileName = join('dir1', 'subdir2', 'file1.txt') srcFilePath = join(dirname(__file__), 'test.zip', inFileName) cdm.publishFromFile(dstFile, srcFilePath) dstLinkPath = join(d.getRepositoryPath(), dstFile + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertEqual(links[0][0], 'ZIP') zipPath = links[0][1] inPath = normOSPath(links[0][2], True) linkPath = join(zipPath, inPath) self.assertEqual(normpath(linkPath), normpath(srcFilePath)) self.assertEqual( datetime.fromtimestamp( stat(join(dirname(__file__), 'test.zip')).st_mtime), cdm.getTimestamp('testdir8/tempfile2.txt')) finally: rmtree(dirname(dstLinkPath)) # test publish from a directory from the file system srcTmpDir = TemporaryDirectory() dirs = (join(srcTmpDir.name, 'test1/subdir1'), join(srcTmpDir.name, 'test2/subdir1')) for dir in dirs: makedirs(dir) with open(join(dir, 'text.html'), 'w+') as _f: pass try: cdm.publishFromDir('testlink1', srcTmpDir.name) dstLinkPath = join(d.getRepositoryPath(), 'testlink1' + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertEqual(links[0][0], 'FS') self.assertEqual(srcTmpDir.name, links[0][1]) self.assertEqual( datetime.fromtimestamp( stat(join(srcTmpDir.name, 'test1/subdir1/text.html')).st_mtime), cdm.getTimestamp('testlink1/test1/subdir1/text.html')) # test path remove delPath1 = 'testlink1/test1/subdir1/text.html' cdm.remove(delPath1) self.assertTrue( isfile(join(d.getRepositoryPath(), delPath1 + '.deleted'))) delPath2 = 'testlink1/test1' cdm.remove(delPath2) self.assertTrue( isfile(join(d.getRepositoryPath(), delPath2 + '.deleted'))) finally: rmtree(join(d.getRepositoryPath(), 'testlink1')) remove(dstLinkPath) # test publish from a file from a zip archive try: srcFilePath = join(dirname(__file__), 'test.zip', 'dir1') + sep cdm.publishFromFile('testlink2', srcFilePath) dstLinkPath = join(d.getRepositoryPath(), 'testlink2' + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertEqual(links[0][0], 'ZIP') zipPath = links[0][1] inPath = normOSPath(links[0][2], True) link = join(zipPath, inPath) self.assertEqual(link, srcFilePath) self.assertEqual( datetime.fromtimestamp( stat(join(dirname(__file__), 'test.zip')).st_mtime), cdm.getTimestamp('testlink2/subdir1/file1.txt')) # test path remove delPath1 = 'testlink2/subdir1/file1.txt' cdm.remove(delPath1) self.assertTrue( isfile(join(d.getRepositoryPath(), delPath1 + '.deleted'))) delPath2 = 'testlink2/subdir1/' self.assertTrue(isdir(join(d.getRepositoryPath(), delPath2))) cdm.remove(delPath2) self.assertTrue( isfile( join(d.getRepositoryPath(), delPath2.rstrip('/') + '.deleted'))) self.assertFalse(isdir(join(d.getRepositoryPath(), delPath2))) self.assertFalse( isfile(join(d.getRepositoryPath(), delPath1 + '.deleted'))) finally: rmtree(join(d.getRepositoryPath(), 'testlink2')) remove(dstLinkPath)
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)
def testLocalFilesystemCDM(self): d = HTTPDelivery() rootDir = TemporaryDirectory() d.serverURI = 'http://localhost/content/' d.repositoryPath = rootDir.name # d.repositoryPath = '/var/www/repository' # ioc.Initializer.initialize(d) cdm = LocalFileSystemCDM() cdm.delivery = d # test publish from a file from the file system try: srcTmpFile = NamedTemporaryFile(delete=False) srcTmpFile.close() dstPath = 'testdir1/tempfile.txt' cdm.publishFromFile(dstPath, srcTmpFile.name) dstFilePath = join(d.getRepositoryPath(), normOSPath(dstPath)) self.assertTrue(isfile(dstFilePath)) self.assertEqual( datetime.fromtimestamp(stat(dstFilePath).st_mtime), cdm.getTimestamp(dstPath)) finally: rmtree(dirname(dstFilePath)) remove(srcTmpFile.name) # test publish from a file from a zip archive try: inFileName = join('dir1', 'subdir2', 'file1.txt') dstPath = join('testdir2', 'tempfile2.txt') cdm.publishFromFile( dstPath, join(dirname(__file__), 'test.zip', inFileName)) dstFilePath = join(d.getRepositoryPath(), normOSPath(dstPath)) self.assertTrue(isfile(dstFilePath)) finally: rmtree(dirname(dstFilePath)) # test publish from a directory from the file system srcTmpDir = TemporaryDirectory() dirs = ('test1/subdir1', 'test2/subdir1') for dir in dirs: fullPath = join(srcTmpDir.name, dir) makedirs(fullPath) with open(join(fullPath, 'text.html'), 'w') as _f: pass try: cdm.publishFromDir('testdir3', srcTmpDir.name) dstDirPath = join(d.getRepositoryPath(), 'testdir3') for dir in dirs: dstFilePath = join(dstDirPath, dir, 'text.html') self.assertTrue(isfile(dstFilePath)) self.assertEqual( datetime.fromtimestamp(stat(dstFilePath).st_mtime), cdm.getTimestamp(join('testdir3', dir, 'text.html'))) # test remove path filePath = 'testdir3/test1/subdir1/text.html' self.assertTrue(isfile(join(d.getRepositoryPath(), filePath))) cdm.republish(filePath, filePath + '.new') self.assertTrue( isfile(join(d.getRepositoryPath(), filePath + '.new'))) cdm.republish(filePath + '.new', filePath) cdm.remove(filePath) self.assertFalse(isfile(join(d.getRepositoryPath(), filePath))) dirPath = 'testdir3/test2' self.assertTrue(isdir(join(d.getRepositoryPath(), dirPath))) cdm.remove(dirPath) self.assertFalse(isdir(join(d.getRepositoryPath(), dirPath))) finally: rmtree(dstDirPath) # test publish from a directory from a zip file try: cdm.publishFromDir('testdir4', join(dirname(__file__), 'test.zip', 'dir1')) dstDirPath = join(d.getRepositoryPath(), 'testdir4') dstFilePath = join(dstDirPath, 'subdir1', 'file1.txt') self.assertTrue(isfile(dstFilePath)) dstFilePath = join(dstDirPath, 'subdir2', 'file2.txt') self.assertTrue(isfile(dstFilePath)) # Test whether republishing the same directory checks the last modified date # The file created manually in the repository should not be deleted because # the zip archive was not modified from the last publish dstFilePath = join(dstDirPath, 'sometestfile.txt') with open(dstFilePath, 'w') as _f: pass cdm.publishFromDir('testdir4', join(dirname(__file__), 'test.zip', 'dir1')) self.assertTrue(isfile(dstFilePath)) finally: rmtree(dstDirPath) # test publish from a string try: path = join('testdir5', 'somecontent.txt') cdm.publishContent(path, BytesIO(b'test')) dstFilePath = join(d.getRepositoryPath(), path) self.assertTrue(isfile(dstFilePath)) finally: rmtree(join(d.getRepositoryPath(), dirname(path))) # test publish from a file object try: path = join('testdir6', 'somecontent2.txt') cdm.publishFromFile(path, BytesIO(b'test 2')) dstFilePath = join(d.getRepositoryPath(), path) self.assertTrue(isfile(dstFilePath)) finally: rmtree(join(d.getRepositoryPath(), dirname(path)))
def testLocalFileSystemLinkCDM(self): d = HTTPDelivery() rootDir = TemporaryDirectory() d.serverURI = "http://localhost/content/" d.repositoryPath = rootDir.name # d.repositoryPath = '/var/www/repository' # ioc.Initializer.initialize(d) cdm = LocalFileSystemLinkCDM() cdm.delivery = d try: exceptionRaised = False cdm.publishFromFile("a/../../b", "somefile.txt") except PathNotFound: exceptionRaised = True self.assertTrue(exceptionRaised, "No exception was raised on out of repository path") # test publish from a file from the file system try: srcTmpFile = NamedTemporaryFile() dstFile = join("testdir7", "tempfile.txt") cdm.publishFromFile(dstFile, srcTmpFile.name) dstLinkPath = join(d.getRepositoryPath(), dstFile + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertIsInstance(links, list) self.assertEqual(links[0][0], "FS") self.assertEqual(srcTmpFile.name, links[0][1]) self.assertEqual( datetime.fromtimestamp(stat(srcTmpFile.name).st_mtime), cdm.getTimestamp("testdir7/tempfile.txt") ) finally: rmtree(dirname(dstLinkPath)) # test publish from a file from a zip archive try: dstFile = join("testdir8", "tempfile2.txt") inFileName = join("dir1", "subdir2", "file1.txt") srcFilePath = join(dirname(__file__), "test.zip", inFileName) cdm.publishFromFile(dstFile, srcFilePath) dstLinkPath = join(d.getRepositoryPath(), dstFile + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertEqual(links[0][0], "ZIP") zipPath = links[0][1] inPath = normOSPath(links[0][2], True) linkPath = join(zipPath, inPath) self.assertEqual(normpath(linkPath), normpath(srcFilePath)) self.assertEqual( datetime.fromtimestamp(stat(join(dirname(__file__), "test.zip")).st_mtime), cdm.getTimestamp("testdir8/tempfile2.txt"), ) finally: rmtree(dirname(dstLinkPath)) # test publish from a directory from the file system srcTmpDir = TemporaryDirectory() dirs = (join(srcTmpDir.name, "test1/subdir1"), join(srcTmpDir.name, "test2/subdir1")) for dir in dirs: makedirs(dir) with open(join(dir, "text.html"), "w+") as _f: pass try: cdm.publishFromDir("testlink1", srcTmpDir.name) dstLinkPath = join(d.getRepositoryPath(), "testlink1" + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertEqual(links[0][0], "FS") self.assertEqual(srcTmpDir.name, links[0][1]) self.assertEqual( datetime.fromtimestamp(stat(join(srcTmpDir.name, "test1/subdir1/text.html")).st_mtime), cdm.getTimestamp("testlink1/test1/subdir1/text.html"), ) # test path remove delPath1 = "testlink1/test1/subdir1/text.html" cdm.remove(delPath1) self.assertTrue(isfile(join(d.getRepositoryPath(), delPath1 + ".deleted"))) delPath2 = "testlink1/test1" cdm.remove(delPath2) self.assertTrue(isfile(join(d.getRepositoryPath(), delPath2 + ".deleted"))) finally: rmtree(join(d.getRepositoryPath(), "testlink1")) remove(dstLinkPath) # test publish from a file from a zip archive try: srcFilePath = join(dirname(__file__), "test.zip", "dir1") + sep cdm.publishFromFile("testlink2", srcFilePath) dstLinkPath = join(d.getRepositoryPath(), "testlink2" + cdm._linkExt) self.assertTrue(isfile(dstLinkPath)) with open(dstLinkPath) as f: links = json.load(f) self.assertEqual(links[0][0], "ZIP") zipPath = links[0][1] inPath = normOSPath(links[0][2], True) link = join(zipPath, inPath) self.assertEqual(link, srcFilePath) self.assertEqual( datetime.fromtimestamp(stat(join(dirname(__file__), "test.zip")).st_mtime), cdm.getTimestamp("testlink2/subdir1/file1.txt"), ) # test path remove delPath1 = "testlink2/subdir1/file1.txt" cdm.remove(delPath1) self.assertTrue(isfile(join(d.getRepositoryPath(), delPath1 + ".deleted"))) delPath2 = "testlink2/subdir1/" self.assertTrue(isdir(join(d.getRepositoryPath(), delPath2))) cdm.remove(delPath2) self.assertTrue(isfile(join(d.getRepositoryPath(), delPath2.rstrip("/") + ".deleted"))) self.assertFalse(isdir(join(d.getRepositoryPath(), delPath2))) self.assertFalse(isfile(join(d.getRepositoryPath(), delPath1 + ".deleted"))) finally: rmtree(join(d.getRepositoryPath(), "testlink2")) remove(dstLinkPath)