diff --git a/package-lock.json b/package-lock.json index 2de07a769..39329b9e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1173,6 +1173,54 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, + "archiver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz", + "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", + "requires": { + "archiver-utils": "^2.1.0", + "async": "^3.2.0", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "dependencies": { + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + } + }, "are-we-there-yet": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", @@ -2160,6 +2208,29 @@ "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", "dev": true }, + "compress-commons": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.0.tgz", + "integrity": "sha512-ofaaLqfraD1YRTkrRKPCrGJ1pFeDG/MVCkVVV2FNGeWquSlqw5wOrwOfPQ1xF2u+blpeWASie5EubHz+vsNIgA==", + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2269,6 +2340,36 @@ "buffer": "^5.1.0" } }, + "crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, + "crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "requires": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", @@ -3675,6 +3776,11 @@ "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" + }, "expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -5096,6 +5202,14 @@ "integrity": "sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q==", "dev": true }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "^2.0.5" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -5157,6 +5271,21 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -5168,6 +5297,16 @@ "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=" }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -6230,6 +6369,11 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==" + }, "process": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", @@ -6449,6 +6593,14 @@ "util-deprecate": "~1.0.1" } }, + "readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", + "requires": { + "minimatch": "^3.0.4" + } + }, "readdirp": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", @@ -8385,19 +8537,33 @@ "fd-slicer": "~1.1.0" } }, - "yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "requires": { - "buffer-crc32": "~0.2.3" - } - }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true + }, + "zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } } } } diff --git a/package.json b/package.json index 3033a8ab1..d92bb1cba 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "test-all": "npm run test && npm run test-es6" }, "dependencies": { + "archiver": "^5.3.0", "async-mutex": "0.3.1", "axios": "0.21.1", "better-sqlite3": "7.1.4", @@ -75,8 +76,7 @@ "turndown": "7.0.0", "unescape": "1.0.1", "ws": "7.4.5", - "yauzl": "2.10.0", - "yazl": "2.5.1" + "yauzl": "2.10.0" }, "devDependencies": { "cross-env": "7.0.3", diff --git a/src/services/export/zip.js b/src/services/export/zip.js index bc44ba7b0..8d98c5825 100644 --- a/src/services/export/zip.js +++ b/src/services/export/zip.js @@ -12,7 +12,7 @@ const protectedSessionService = require('../protected_session'); const sanitize = require("sanitize-filename"); const fs = require("fs"); const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR; -const yazl = require("yazl"); +const archiver = require('archiver'); /** * @param {TaskContext} taskContext @@ -20,7 +20,9 @@ const yazl = require("yazl"); * @param {string} format - 'html' or 'markdown' */ function exportToZip(taskContext, branch, format, res) { - const zipFile = new yazl.ZipFile(); + const archive = archiver('zip', { + zlib: { level: 9 } // Sets the compression level. + }); const noteIdToMeta = {}; @@ -268,7 +270,7 @@ ${content} content = prepareContent(noteMeta.title, content, noteMeta); - zipFile.addBuffer(content, filePathPrefix + noteMeta.dataFileName); + archive.append(content, { name: filePathPrefix + noteMeta.dataFileName }); return; } @@ -280,7 +282,7 @@ ${content} if (noteMeta.dataFileName) { const content = prepareContent(noteMeta.title, note.getContent(), noteMeta); - zipFile.addBuffer(content, filePathPrefix + noteMeta.dataFileName, {mtime: dateUtils.parseDateTime(note.utcDateModified)}); + archive.append(content, { name: filePathPrefix + noteMeta.dataFileName, date: dateUtils.parseDateTime(note.utcDateModified) }); } taskContext.increaseProgressCount(); @@ -288,7 +290,8 @@ ${content} if (noteMeta.children && noteMeta.children.length > 0) { const directoryPath = filePathPrefix + noteMeta.dirFileName; - zipFile.addEmptyDirectory(directoryPath, {mtime: dateUtils.parseDateTime(note.utcDateModified)}); + // create directory + archive.append('', { name: directoryPath + '/', date: dateUtils.parseDateTime(note.utcDateModified) }); for (const childMeta of noteMeta.children) { saveNote(childMeta, directoryPath + '/'); @@ -335,7 +338,7 @@ ${content} `; const prettyHtml = html.prettyPrint(fullHtml, {indent_size: 2}); - zipFile.addBuffer(prettyHtml, navigationMeta.dataFileName); + archive.append(prettyHtml, { name: navigationMeta.dataFileName }); } function saveIndex(rootMeta, indexMeta) { @@ -367,13 +370,13 @@ ${content} `; - zipFile.addBuffer(fullHtml, indexMeta.dataFileName); + archive.append(fullHtml, { name: indexMeta.dataFileName }); } function saveCss(rootMeta, cssMeta) { const cssContent = fs.readFileSync(RESOURCE_DIR + '/libraries/ckeditor/ckeditor-content.css'); - zipFile.addBuffer(cssContent, cssMeta.dataFileName); + archive.append(cssContent, { name: cssMeta.dataFileName }); } const existingFileNames = format === 'html' ? ['navigation', 'index'] : []; @@ -422,7 +425,7 @@ ${content} const metaFileJson = JSON.stringify(metaFile, null, '\t'); - zipFile.addBuffer(metaFileJson, "!!!meta.json"); + archive.append(metaFileJson, { name: "!!!meta.json" }); saveNote(rootMeta, ''); @@ -438,8 +441,8 @@ ${content} res.setHeader('Content-Disposition', utils.getContentDisposition(zipFileName)); res.setHeader('Content-Type', 'application/zip'); - zipFile.outputStream.pipe(res); - zipFile.end(); + archive.pipe(res); + archive.finalize(); taskContext.taskSucceeded(); }