From 4bbd05bd5508f2fff6844af02c788006341fc9eb Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 26 May 2020 15:08:47 +0200 Subject: [PATCH] MOBILE-3411 h5p: Fix extracting H5P in browser --- src/core/emulator/providers/file.ts | 87 +++++++++++++++++++---------- src/providers/file.ts | 76 +++++++------------------ 2 files changed, 77 insertions(+), 86 deletions(-) diff --git a/src/core/emulator/providers/file.ts b/src/core/emulator/providers/file.ts index d219d1d68..4fa59267e 100644 --- a/src/core/emulator/providers/file.ts +++ b/src/core/emulator/providers/file.ts @@ -98,13 +98,7 @@ export class FileMock extends File { * @return Returns a Promise that resolves to the new Entry object or rejects with an error. */ copyDir(path: string, dirName: string, newPath: string, newDirName: string): Promise { - return this.resolveDirectoryUrl(path).then((fse) => { - return this.getDirectory(fse, dirName, { create: false }); - }).then((srcde) => { - return this.resolveDirectoryUrl(newPath).then((deste) => { - return this.copyMock(srcde, deste, newDirName); - }); - }); + return this.copyFileOrDir(path, dirName, newPath, newDirName); } /** @@ -117,15 +111,26 @@ export class FileMock extends File { * @return Returns a Promise that resolves to an Entry or rejects with an error. */ copyFile(path: string, fileName: string, newPath: string, newFileName: string): Promise { - newFileName = newFileName || fileName; + return this.copyFileOrDir(path, fileName, newPath, newFileName || fileName); + } - return this.resolveDirectoryUrl(path).then((fse) => { - return this.getFile(fse, fileName, { create: false }); - }).then((srcfe) => { - return this.resolveDirectoryUrl(newPath).then((deste) => { - return this.copyMock(srcfe, deste, newFileName); - }); - }); + /** + * Copy a file or dir to a given path. + * + * @param sourcePath Path of the file/dir to copy. + * @param sourceName Name of file/dir to copy + * @param destPath Path where to copy. + * @param destName New name of file/dir. + * @return Returns a Promise that resolves to the new Entry or rejects with an error. + */ + async copyFileOrDir(sourcePath: string, sourceName: string, destPath: string, destName: string): Promise { + const destFixed = this.fixPathAndName(destPath, destName); + + const source = await this.resolveLocalFilesystemUrl(this.textUtils.concatenatePaths(sourcePath, sourceName)); + + const destParentDir = await this.resolveDirectoryUrl(destFixed.path); + + return this.copyMock(source, destParentDir, destFixed.name); } /** @@ -431,13 +436,7 @@ export class FileMock extends File { * an error. */ moveDir(path: string, dirName: string, newPath: string, newDirName: string): Promise { - return this.resolveDirectoryUrl(path).then((fse) => { - return this.getDirectory(fse, dirName, { create: false }); - }).then((srcde) => { - return this.resolveDirectoryUrl(newPath).then((deste) => { - return this.moveMock(srcde, deste, newDirName); - }); - }); + return this.moveFileOrDir(path, dirName, newPath, newDirName); } /** @@ -450,15 +449,43 @@ export class FileMock extends File { * @return Returns a Promise that resolves to the new Entry or rejects with an error. */ moveFile(path: string, fileName: string, newPath: string, newFileName: string): Promise { - newFileName = newFileName || fileName; + return this.moveFileOrDir(path, fileName, newPath, newFileName || fileName); + } - return this.resolveDirectoryUrl(path).then((fse) => { - return this.getFile(fse, fileName, { create: false }); - }).then((srcfe) => { - return this.resolveDirectoryUrl(newPath).then((deste) => { - return this.moveMock(srcfe, deste, newFileName); - }); - }); + /** + * Move a file or dir to a given path. + * + * @param sourcePath Path of the file/dir to copy. + * @param sourceName Name of file/dir to copy + * @param destPath Path where to copy. + * @param destName New name of file/dir. + * @return Returns a Promise that resolves to the new Entry or rejects with an error. + */ + async moveFileOrDir(sourcePath: string, sourceName: string, destPath: string, destName: string): Promise { + const destFixed = this.fixPathAndName(destPath, destName); + + const source = await this.resolveLocalFilesystemUrl(this.textUtils.concatenatePaths(sourcePath, sourceName)); + + const destParentDir = await this.resolveDirectoryUrl(destFixed.path); + + return this.moveMock(source, destParentDir, destFixed.name); + } + + /** + * Fix a path and name, making sure the name doesn't contain any folder. If it does, the folder will be moved to the path. + * + * @param path Path to fix. + * @param name Name to fix. + * @return Fixed values. + */ + protected fixPathAndName(path: string, name: string): {path: string, name: string} { + + const fullPath = this.textUtils.concatenatePaths(path, name); + + return { + path: fullPath.substring(0, fullPath.lastIndexOf('/')), + name: fullPath.substr(fullPath.lastIndexOf('/') + 1), + }; } /** diff --git a/src/providers/file.ts b/src/providers/file.ts index e856da932..ea33e7313 100644 --- a/src/providers/file.ts +++ b/src/providers/file.ts @@ -812,42 +812,17 @@ export class CoreFileProvider { } }).then(() => { - if (this.isHTMLAPI) { - // In Cordova API we need to calculate the longest matching path to make it work. - // The function this.file.moveFile('a/', 'b/c.ext', 'a/', 'b/d.ext') doesn't work. - // The function this.file.moveFile('a/b/', 'c.ext', 'a/b/', 'd.ext') works. - const dirsA = originalPath.split('/'), - dirsB = newPath.split('/'); - let commonPath = this.basePath; + return moveFn(this.basePath, originalPath, this.basePath, newPath).catch((error) => { + // The move can fail if the path has encoded characters. Try again if that's the case. + const decodedOriginal = decodeURI(originalPath), + decodedNew = decodeURI(newPath); - for (let i = 0; i < dirsA.length; i++) { - let dir = dirsA[i]; - if (dirsB[i] === dir) { - // Found a common folder, add it to common path and remove it from each specific path. - dir = dir + '/'; - commonPath = this.textUtils.concatenatePaths(commonPath, dir); - originalPath = originalPath.replace(dir, ''); - newPath = newPath.replace(dir, ''); - } else { - // Folder doesn't match, stop searching. - break; - } + if (decodedOriginal != originalPath || decodedNew != newPath) { + return moveFn(this.basePath, decodedOriginal, this.basePath, decodedNew); + } else { + return Promise.reject(error); } - - return moveFn(commonPath, originalPath, commonPath, newPath); - } else { - return moveFn(this.basePath, originalPath, this.basePath, newPath).catch((error) => { - // The move can fail if the path has encoded characters. Try again if that's the case. - const decodedOriginal = decodeURI(originalPath), - decodedNew = decodeURI(newPath); - - if (decodedOriginal != originalPath || decodedNew != newPath) { - return moveFn(this.basePath, decodedOriginal, this.basePath, decodedNew); - } else { - return Promise.reject(error); - } - }); - } + }); }); } @@ -888,8 +863,6 @@ export class CoreFileProvider { * @return Promise resolved when the entry is copied. */ protected copyFileOrDir(from: string, to: string, isDir?: boolean, destDirExists?: boolean): Promise { - let fromFileAndDir, - toFileAndDir; const copyFn = isDir ? this.file.copyDir.bind(this.file) : this.file.copyFile.bind(this.file); return this.init().then(() => { @@ -897,33 +870,24 @@ export class CoreFileProvider { from = this.removeStartingSlash(from.replace(this.basePath, '')); to = this.removeStartingSlash(to.replace(this.basePath, '')); - fromFileAndDir = this.getFileAndDirectoryFromPath(from); - toFileAndDir = this.getFileAndDirectoryFromPath(to); + const toFileAndDir = this.getFileAndDirectoryFromPath(to); if (toFileAndDir.directory && !destDirExists) { // Create the target directory if it doesn't exist. return this.createDir(toFileAndDir.directory); } }).then(() => { - if (this.isHTMLAPI) { - // In HTML API, the file name cannot include a directory, otherwise it fails. - const fromDir = this.textUtils.concatenatePaths(this.basePath, fromFileAndDir.directory), - toDir = this.textUtils.concatenatePaths(this.basePath, toFileAndDir.directory); + return copyFn(this.basePath, from, this.basePath, to).catch((error) => { + // The copy can fail if the path has encoded characters. Try again if that's the case. + const decodedFrom = decodeURI(from), + decodedTo = decodeURI(to); - return copyFn(fromDir, fromFileAndDir.name, toDir, toFileAndDir.name); - } else { - return copyFn(this.basePath, from, this.basePath, to).catch((error) => { - // The copy can fail if the path has encoded characters. Try again if that's the case. - const decodedFrom = decodeURI(from), - decodedTo = decodeURI(to); - - if (from != decodedFrom || to != decodedTo) { - return copyFn(this.basePath, decodedFrom, this.basePath, decodedTo); - } else { - return Promise.reject(error); - } - }); - } + if (from != decodedFrom || to != decodedTo) { + return copyFn(this.basePath, decodedFrom, this.basePath, decodedTo); + } else { + return Promise.reject(error); + } + }); }); }