From d70e9cf41b96863b16f792343ca18cd4b927b341 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Thu, 29 Oct 2015 02:22:06 -0400 Subject: [PATCH] Add Zotero.File::zipDirectory() --- chrome/content/zotero/xpcom/file.js | 99 +++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/chrome/content/zotero/xpcom/file.js b/chrome/content/zotero/xpcom/file.js index 4d88f705f..b289dab54 100644 --- a/chrome/content/zotero/xpcom/file.js +++ b/chrome/content/zotero/xpcom/file.js @@ -653,6 +653,105 @@ Zotero.File = new function(){ }; + /** + * @param {String} dirPath - Directory containing files to add to ZIP + * @param {String} zipPath - ZIP file to create + * @param {nsIRequestObserver} [observer] + * @return {Promise} + */ + this.zipDirectory = Zotero.Promise.coroutine(function* (dirPath, zipPath, observer) { + var zw = Components.classes["@mozilla.org/zipwriter;1"] + .createInstance(Components.interfaces.nsIZipWriter); + zw.open(this.pathToFile(zipPath), 0x04 | 0x08 | 0x20); // open rw, create, truncate + var entries = yield _zipDirectory(dirPath, dirPath, zw); + if (entries.length == 0) { + Zotero.debug('No files to add -- removing ZIP file'); + zw.close(); + zipPath.remove(null); + return false; + } + + Zotero.debug(`Creating ${OS.Path.basename(zipPath)} with ${entries.length} file(s)`); + + var context = { + zipWriter: zw, + entries + }; + + var deferred = Zotero.Promise.defer(); + zw.processQueue( + { + onStartRequest: function (request, ctx) { + try { + if (observer && observer.onStartRequest) { + observer.onStartRequest(request, context); + } + } + catch (e) { + deferred.reject(e); + } + }, + onStopRequest: function (request, ctx, status) { + try { + if (observer && observer.onStopRequest) { + observer.onStopRequest(request, context, status); + } + } + catch (e) { + deferred.reject(e); + return; + } + finally { + zw.close(); + } + deferred.resolve(true); + } + }, + {} + ); + return deferred.promise; + }); + + + var _zipDirectory = Zotero.Promise.coroutine(function* (rootPath, path, zipWriter) { + var entries = []; + let iterator; + try { + iterator = new OS.File.DirectoryIterator(path); + yield iterator.forEach(Zotero.Promise.coroutine(function* (entry) { + if (entry.isSymLink) { + Zotero.debug("Skipping symlink " + entry.name); + return; + } + if (entry.isDir) { + entries.concat(yield _zipDirectory(rootPath, path, zipWriter)); + return; + } + if (entry.name.startsWith('.')) { + Zotero.debug('Skipping file ' + entry.name); + return; + } + + zipWriter.addEntryFile( + // Add relative path + entry.path.substr(rootPath.length + 1), + Components.interfaces.nsIZipWriter.COMPRESSION_DEFAULT, + Zotero.File.pathToFile(entry.path), + true + ); + entries.push({ + name: entry.name, + path: entry.path + }); + })); + } + finally { + iterator.close(); + } + return entries; + }); + + /** * Strip potentially invalid characters *