diff --git a/package.json b/package.json index 1fb53006..72d46593 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "c9", "description": "New Cloud9 Client", - "version": "3.1.2672", + "version": "3.1.2708", "author": "Ajax.org B.V. ", "private": true, "main": "bin/c9", @@ -58,11 +58,11 @@ "c9" ], "c9plugins": { - "c9.ide.language": "#f62951109c", + "c9.ide.language": "#0e86345d39", "c9.ide.language.core": "#10a225e77d", "c9.ide.language.css": "#46ad561506", "c9.ide.language.generic": "#b47cbe58f9", - "c9.ide.language.html": "#8e990755bb", + "c9.ide.language.html": "#cdc3960225", "c9.ide.language.html.diff": "#7d6cecfb90", "c9.ide.language.javascript": "#b82f16e56a", "c9.ide.language.javascript.immediate": "#82c426dbca", @@ -71,7 +71,7 @@ "c9.ide.language.javascript.infer": "#b9c2e4bdb8", "c9.ide.language.jsonalyzer": "#a32369793c", "c9.ide.language.codeintel": "#4e0a272229", - "c9.ide.collab": "#24e28024d7", + "c9.ide.collab": "#e015881720", "c9.ide.local": "#9169fec157", "c9.ide.find": "#a2dfc3e306", "c9.ide.find.infiles": "#488db22ee1", diff --git a/plugins/c9.ide.download/download.js b/plugins/c9.ide.download/download.js index dd6a585f..ab8e5280 100644 --- a/plugins/c9.ide.download/download.js +++ b/plugins/c9.ide.download/download.js @@ -91,24 +91,30 @@ define(function(require, exports, module) { } function downloadProject() { - vfs.download("/", info.getWorkspace().name + getArchiveFileExtension()); + vfs.download("/", makeArchiveFilename(info.getWorkspace().name)); } function downloadPaths(paths) { - vfs.download(paths, info.getWorkspace().name + getArchiveFileExtension()); + var lastPart = paths[0].match(/([^\/]*)\/?$/)[1]; + var filename = lastPart ? (lastPart + "[+" + (paths.length - 1) + "]") : info.getWorkspace().name; + vfs.download(paths, makeArchiveFilename(filename)); } function downloadFolder(path) { var withTrailingSlash = path.replace(/\/*$/, "/"); var parts = withTrailingSlash.split("/"); - var lastPart = parts[parts.length - 2]; - vfs.download(withTrailingSlash, lastPart + getArchiveFileExtension()); + var folderName = parts[parts.length - 2]; + vfs.download(withTrailingSlash, makeArchiveFilename(folderName)); } function downloadFile(path) { vfs.download(path.replace(/\/*$/, ""), null, true); } + function makeArchiveFilename(filename) { + return filename + getArchiveFileExtension(); + } + function getArchiveFileExtension() { var downloadFilesAs = settings.get(SETTING_PATH); if (downloadFilesAs === 'auto' || !downloadFilesAs) { diff --git a/plugins/c9.vfs.client/vfs_client.js b/plugins/c9.vfs.client/vfs_client.js index 93557f30..9badea1b 100644 --- a/plugins/c9.vfs.client/vfs_client.js +++ b/plugins/c9.vfs.client/vfs_client.js @@ -198,7 +198,8 @@ define(function(require, exports, module) { } window.open(vfsUrl(path) + extraPaths + "?download" - + (filename ? "=" + escape(filename) : "") + // Escape '+', otherwise it gets interpreted as a space. + + (filename ? "=" + escape(filename) : "").replace(/\+/g, "%2B") + (isfile ? "&isfile=1" : "")); } diff --git a/plugins/c9.vfs.server/download.js b/plugins/c9.vfs.server/download.js index b1dbea6f..b259713e 100644 --- a/plugins/c9.vfs.server/download.js +++ b/plugins/c9.vfs.server/download.js @@ -44,11 +44,11 @@ define(function(require, exports, module) { filename += (paths.length > 1 ? "[+" + (paths.length - 1) + "]" : "") + ".tar.gz"; } } - var filenameHeader = "attachment; filename*=utf-8''" + encodeURIComponent(filename); + var filenameHeader = "attachment; filename*=utf-8''" + escape(filename); - var process; + var proc; req.on("close", function() { - if (process) process.kill(); + if (proc) proc.kill(); }); if (req.uri.query.isfile) { @@ -113,24 +113,26 @@ define(function(require, exports, module) { paths.forEach(function(path) { if (!path) return; path = Path.relative(cwd, path); - // tar misinterprets the Windows path separator as an escape sequence, so use forward slash. - if (Path.sep === '\\') { - path = path.replace(/\\/g, '/'); + if (process.platform == "win32") { + // Quote the path to escape unusual characters and spaces. + // NB: Double quotes are illegal within the actual path on Windows. + path = '"' + path.replace(/"/g, "") + '"'; } args.push(path); }); vfs.spawn(executable, { args: args, - cwd: cwd + cwd: cwd, + windowsVerbatimArguments: true // Prevents Node from escaping the double quotes added above. }, function (err, meta) { if (err) return next(err); - process = meta.process; + proc = meta.process; // once we receive data on stdout pipe it to the response - process.stdout.once("data", function (data) { + proc.stdout.once("data", function (data) { if (res.headerSent) return; @@ -139,15 +141,15 @@ define(function(require, exports, module) { "Content-Disposition": filenameHeader }); res.write(data); - process.stdout.pipe(res); + proc.stdout.pipe(res); }); var stderr = ""; - process.stderr.on("data", function (data) { + proc.stderr.on("data", function (data) { stderr += data; }); - process.on("exit", function(code, signal) { + proc.on("exit", function(code, signal) { if (res.headerSent) return;