Merge remote-tracking branch 'origin/master' into revert-11498-revert-11413-fix-xss

Conflicts:
	npm-shrinkwrap.json
This commit is contained in:
Fabian Jakobs 2016-01-26 11:48:26 +00:00
commit 833528f12c
39 changed files with 471 additions and 122 deletions

2
.gitignore vendored
View File

@ -84,4 +84,4 @@ foo.js
hello.js
plugins/c9.docker/containers/ci/files/github_c9_newclient
plugins/c9.docker/containers/shared/files/plugins/salesforce*
security-audit.log
security-audit.log

View File

@ -1,7 +1,7 @@
{
"app": {
"launch": {
"web_url": "http://c9.io/"
"web_url": "http://c9.io/#1page"
},
"urls": [
"https://c9.io/", "https://www.c9.io/", "https://ide.c9.io/",

View File

@ -321,7 +321,82 @@ module.exports = function(options) {
"plugins/c9.ide.language.javascript/javascript",
"plugins/c9.ide.language.javascript.immediate/immediate",
"plugins/c9.ide.language.javascript.infer/jsinfer",
"plugins/c9.ide.language.javascript.tern/tern",
{
packagePath: "plugins/c9.ide.language.javascript.tern/tern",
plugins: [
{
name: "angular",
path: "tern/plugin/angular",
enabled: true,
hidden: false,
},
{
name: "doc_comment",
path: "tern/plugin/doc_comment",
enabled: true,
hidden: true,
},
{
name: "es_modules",
path: "tern/plugin/es_modules",
enabled: true,
hidden: true,
},
{
name: "modules",
path: "tern/plugin/modules",
enabled: true,
hidden: true,
},
{
name: "node",
path: "tern/plugin/node",
enabled: true,
hidden: false,
},
{
name: "requirejs",
path: "tern/plugin/requirejs",
enabled: true,
hidden: false,
},
{
name: "architect_resolver",
path: "./architect_resolver_worker",
enabled: true,
hidden: true,
},
],
defs: [{
name: "ecma5",
enabled: true,
experimental: false,
firstClass: true,
path: "lib/tern/defs/ecma5.json"
}, {
name: "jQuery",
enabled: true,
experimental: false,
path: "lib/tern/defs/jquery.json"
}, {
name: "browser",
enabled: true,
experimental: false,
firstClass: true,
path: "lib/tern/defs/browser.json"
}, {
name: "underscore",
enabled: false,
experimental: false,
path: "lib/tern/defs/underscore.json"
}, {
name: "chai",
enabled: false,
experimental: false,
path: "lib/tern/defs/chai.json"
}]
},
"plugins/c9.ide.language.javascript.tern/ui",
"plugins/c9.ide.language.javascript.tern/architect_resolver",
"plugins/c9.ide.language.javascript.eslint/eslint",
{

View File

@ -172,7 +172,8 @@ function DefaultHandlers(mouseHandler) {
};
this.onMouseUp = function(ev) {
if (this.isMousePressed) return;
if (this.isMousePressed == 2) return; // wait until release capture
this.isMousePressed = false;
var pos = ev.getDocumentPosition();
var node = this.editor.provider.findItemAtOffset(pos.y);
if (node && this.$clickNode && this.$clickNode == node) {

View File

@ -87,7 +87,7 @@ var MouseHandler = function(editor) {
this.x = ev.x;
this.y = ev.y;
this.isMousePressed = true;
this.isMousePressed = 2;
// do not move textarea during selection
var renderer = this.editor.renderer;

View File

@ -1,7 +1,7 @@
if (define === undefined) {
var define = function(fn) {
fn(require, exports, module);
};
if (typeof define === "undefined") {
var define = function(fn) {
fn(require, exports, module);
};
}
define(function(require, exports, module) {
@ -11,7 +11,7 @@ define(function(require, exports, module) {
if (!user) return {}; // empty traits get ignored
var traits = {
uid: user.id || user.uid,
uid: user.id,
username: user.name || user.username,
email: user.email,
createdAt: user.date_add,

View File

@ -1,7 +1,7 @@
if (define === undefined) {
var define = function(fn) {
fn(require, exports, module);
};
if (typeof define === "undefined") {
var define = function(fn) {
fn(require, exports, module);
};
}
define(function(require, exports, module) {

View File

@ -1,7 +1,7 @@
if (define === undefined) {
var define = function(fn) {
fn(require, exports, module);
};
if (typeof define === "undefined") {
var define = function(fn) {
fn(require, exports, module);
};
}
define(function(require, exports, module) {
@ -10,12 +10,10 @@ define(function(require, exports, module) {
var internalTestNames = ["c9test", "c9 test"];
var regex = new RegExp("^(" + internalTestNames.join("|") + ")+");
function hasInternalTestName(user) {
if (!user.name && !user.username) return false;
function hasInternalTestName(name) {
if (!name) return false;
var testedName = user.name ? user.name : user.username;
return regex.test(testedName);
return regex.test(name);
}
module.exports = hasInternalTestName;

32
node_modules/c9/hostname.js generated vendored
View File

@ -1,14 +1,30 @@
var fs = require("fs");
exports.parse = function(hostname) {
var parts = hostname.split("-");
return {
type: parts[0],
provider: parts[1],
region: parts[2],
index: parts[3],
env: parts[4]
};
var m1 = hostname.match(/^([0-9a-z-]+?)-gce-([a-z]+)-([0-9]+)-([a-z0-9]+)$/);
var m2 = hostname.match(/^([0-9a-z-]+?)-gce-([a-z]+)-([a-z0-9]+)-([a-z0-9]{4})$/);
if (m1) {
return {
type: m1[1],
provider: "gce",
region: m1[2],
index: m1[3],
env: m1[4]
};
}
else if (m2) {
return {
type: m2[1],
provider: "gce",
region: m2[2],
env: m2[3],
index: m2[4]
};
} else {
return {};
}
};
exports.get = function() {

25
node_modules/c9/hostname_test.js generated vendored Normal file
View File

@ -0,0 +1,25 @@
/*global describe it before after beforeEach afterEach define*/
"use strict";
"use server";
"use mocha";
require("c9/inline-mocha")(module);
var assert = require("assert-diff");
var hostname = require("./hostname");
describe(__filename, function() {
function assertServerName(sn, type, region, index, env) {
assert.equal(sn.type, type);
assert.equal(sn.region, region);
assert.equal(sn.index, index);
assert.equal(sn.env, env);
}
it("parse hostname", function() {
assertServerName(hostname.parse("fabian-gce-eu-04-dev"), "fabian", "eu", "04", "dev");
assertServerName(hostname.parse("newclient-gce-eu-prod-d4fg"), "newclient", "eu", "d4fg", "prod");
assertServerName(hostname.parse("ide-old-gce-usw-02-prod"), "ide-old", "usw", "02", "prod");
});
});

6
node_modules/c9/scm_url_parse.js generated vendored
View File

@ -1,3 +1,9 @@
if (typeof define === "undefined") {
var define = function(fn) {
fn(require, exports, module);
};
}
define(function(require, exports, module) {
"use strict";

30
node_modules/c9/skip-analytics.js generated vendored
View File

@ -1,7 +1,7 @@
if (define === undefined) {
var define = function(fn) {
fn(require, exports, module);
};
if (typeof define === "undefined") {
var define = function(fn) {
fn(require, exports, module);
};
}
define(function(require, exports, module) {
@ -10,21 +10,21 @@ define(function(require, exports, module) {
var hasInternalDomain = require("c9/has-internal-domain");
var hasInternalTestName = require("c9/has-internal-test-name");
function skipAnalytics(user, allowUnauthorized) {
if (!user) return true;
function skipAnalytics(userId, name, email, allowUnauthorized) {
if (!allowUnauthorized && hasUnauthorizedId(user)) return true;
if (typeof userId == "object") {
var user = userId;
return skipAnalytics(user.id, user.name || user.username, user.email, name); // make it backwards compatible for the client
}
if (!userId) return true; // users without an id should never reach the Segment library
if (!allowUnauthorized && userId === -1) return true;
if (hasInternalTestName(user)) return true;
if (hasInternalDomain(user.email)) return true;
if (hasInternalTestName(name)) return true;
if (hasInternalDomain(email)) return true;
return false;
}
function hasUnauthorizedId(user) {
if (user.id === -1) return true;
if (!user.id && user.uid === -1) return true;
}
module.exports = skipAnalytics;
});

View File

@ -8,10 +8,10 @@ var skipAnalytics = require("c9/skip-analytics");
describe("skip-analytics", function() {
it("returns true when user undefined", function() {
it("returns true when user or user id undefined", function() {
var user;
assert.equal(true, skipAnalytics(user), "skipAnalytics should return true when user undefined");
assert.equal(true, skipAnalytics(null, user), "skipAnalytics should return true when user undefined");
});
it("returns true when user id is -1", function() {

3
node_modules/c9/urls.js generated vendored
View File

@ -94,9 +94,6 @@ function getBaseUrl(req, sourceBaseUrlPattern, targetBaseUrlPattern) {
targetHost = "c9.io";
}
if (/^(ide|vfs)./.test(targetHost))
console.trace("Warning: possibly incorrect baseUrl constructed, with 'ide.' in the hostname: " + targetHost);
return replaceDomain(targetBaseUrlPattern, targetHost)
.replace(/\/$/, "");
}

View File

@ -24,7 +24,7 @@ module.exports = function setup(mount, vfs, mountOptions) {
else if (err.code === "ENOTREADY") res.statusCode = 503;
else if (err.code === "EISDIR") res.statusCode = 503;
else res.statusCode = 500;
var message = (err.stack || err) + "\n";
var message = (err.message || err.toString()) + "\n";
res.setHeader("Content-Type", "text/plain");
res.setHeader("Content-Length", Buffer.byteLength(message));
res.end(message);

11
node_modules/vfs-local/localfs.js generated vendored
View File

@ -322,8 +322,8 @@ module.exports = function setup(fsOptions) {
var isError = true;
if (isError) {
var err = new Error("EACCESS: '" + path + "' not in '" + localRoot + "'");
err.code = "EACCESS";
var err = new Error("EACCES: '" + path + "' not in '" + localRoot + "'");
err.code = "EACCES";
return callback(err);
}
}
@ -1293,7 +1293,7 @@ module.exports = function setup(fsOptions) {
function done() {
// Ignore if files is tmp file
if (latest && latest.name.substr(-1) == "~"
if (latest && (latest.name.substr(-1) == "~" || latest.name[1] === "~")
&& latest.name.charAt(0) == ".")
return;
@ -2335,6 +2335,11 @@ module.exports = function setup(fsOptions) {
}
function extend(name, options, callback) {
if (!name) {
var err = new Error("EACCES: Invalid extension name");
err.code = "EACCES";
return callback(err);
}
var meta = {};
// Pull from cache if it's already loaded.

View File

@ -49,7 +49,7 @@ describe('vfs-local', function () {
});
it('should reject paths that resolve outside the root', function (done) {
vfs.resolve("/../test-local.js", {}, function (err, meta) {
expect(err).property("code").equals("EACCESS");
expect(err).property("code").equals("EACCES");
done();
});
});
@ -893,6 +893,12 @@ describe('vfs-local', function () {
});
});
});
it("should error with EACCES if the same extension name is empty", function (done) {
vfs.extend("", {file: __dirname + "/math.js"}, function (err, meta) {
expect(err).property("code").equal("EACCES");
done();
});
});
it("should allow a redefine if options.redefine is set", function (done) {
vfs.extend("test", {file: __dirname + "/math.js"}, function (err, meta) {
if (err) throw err;

View File

@ -1,7 +1,7 @@
{
"name": "c9",
"description": "New Cloud9 Client",
"version": "3.1.1032",
"version": "3.1.1188",
"author": "Ajax.org B.V. <info@ajax.org>",
"private": true,
"main": "bin/c9",
@ -34,8 +34,8 @@
"rusha": "~0.7.2",
"send": "~0.1.4",
"simple-mime": "~0.0.8",
"tern": "git://github.com/cloud9ide/tern.git#749e64a0f0fed91f883ff055df37b4bfc9f2d980",
"tern_from_ts": "git://github.com/cloud9ide/tern_from_ts.git#6a0107e602b0d044fe1753533cf31f52cf5fb95a",
"tern": "git://github.com/cloud9ide/tern.git#39015d544d4c00c7899fea4c95c2e5bc2720e68e",
"tern_from_ts": "git://github.com/cloud9ide/tern_from_ts.git#84d51dcb9b16b126a206789d4d4237cde2801fe4",
"through": "2.2.0",
"tmp": "~0.0.20",
"uglify-js": "2.4.16",
@ -56,23 +56,23 @@
"c9"
],
"c9plugins": {
"c9.ide.language": "#9d12de412d",
"c9.ide.language": "#76ce872cdc",
"c9.ide.language.css": "#be07d72209",
"c9.ide.language.generic": "#2b5cc6275e",
"c9.ide.language.generic": "#a4023db7f6",
"c9.ide.language.html": "#9be847c0ce",
"c9.ide.language.html.diff": "#24f3608d26",
"c9.ide.language.javascript": "#1a0b1584c2",
"c9.ide.language.javascript": "#c6d102471f",
"c9.ide.language.javascript.immediate": "#c8b1e5767a",
"c9.ide.language.javascript.eslint": "#d7b067e838",
"c9.ide.language.javascript.tern": "#f9ba3813d7",
"c9.ide.language.javascript.infer": "#9cf94f77be",
"c9.ide.language.jsonalyzer": "#88c957758e",
"c9.ide.collab": "#10c224f9b8",
"c9.ide.language.javascript.eslint": "#3127e1eba1",
"c9.ide.language.javascript.tern": "#45e5f5b0e5",
"c9.ide.language.javascript.infer": "#0561c69d67",
"c9.ide.language.jsonalyzer": "#243e11bd42",
"c9.ide.collab": "#e2411fc12b",
"c9.ide.local": "#a6e689e33b",
"c9.ide.find": "#e33fbaed2f",
"c9.ide.find.infiles": "#c3bf17286d",
"c9.ide.find.replace": "#8cbce45290",
"c9.ide.run.debug": "#8b77a8379d",
"c9.ide.run.debug": "#7dfe32f721",
"c9.automate": "#47e2c429c9",
"c9.ide.ace.emmet": "#6dc4585e02",
"c9.ide.ace.gotoline": "#a8ff07c8f4",
@ -81,9 +81,9 @@
"c9.ide.ace.split": "#0ae0151c78",
"c9.ide.ace.statusbar": "#3aab0b67e0",
"c9.ide.ace.stripws": "#cf0f42ac59",
"c9.ide.behaviors": "#5ae88f87e1",
"c9.ide.behaviors": "#db32109ebc",
"c9.ide.closeconfirmation": "#cee4674141",
"c9.ide.configuration": "#a9066299a2",
"c9.ide.configuration": "#e3c90dcd96",
"c9.ide.dialog.wizard": "#7667ec79a8",
"c9.ide.fontawesome": "#781602c5d8",
"c9.ide.format": "#5ec97fb083",
@ -91,12 +91,12 @@
"c9.ide.imgeditor": "#612e75ef4f",
"c9.ide.immediate": "#a962119bec",
"c9.ide.installer": "#0fde9f0067",
"c9.ide.language.python": "#03b2523dc7",
"c9.ide.language.go": "#267378d2f3",
"c9.ide.language.python": "#4fad6f5a80",
"c9.ide.language.go": "#8f6d0beae7",
"c9.ide.mount": "#915b3d20be",
"c9.ide.navigate": "#38ae100ea1",
"c9.ide.navigate": "#1fbb7cd53b",
"c9.ide.newresource": "#981a408a7b",
"c9.ide.openfiles": "#7fa4a97fed",
"c9.ide.openfiles": "#2ae85a9e33",
"c9.ide.preview": "#8f87ff2f6a",
"c9.ide.preview.browser": "#c5b9a129de",
"c9.ide.preview.markdown": "#bc846e1562",
@ -105,15 +105,15 @@
"c9.ide.recentfiles": "#7c099abf40",
"c9.ide.remote": "#301d2ab519",
"c9.ide.processlist": "#2b12cd1bdd",
"c9.ide.run": "#453aa5f604",
"c9.ide.run": "#f03e4b018e",
"c9.ide.run.build": "#0598fff697",
"c9.ide.run.debug.xdebug": "#5553240abe",
"c9.ide.save": "#9461acd953",
"c9.ide.scm": "#930a9e6f00",
"c9.ide.terminal.monitor": "#e26502f0df",
"c9.ide.test": "#8f21f662d3",
"c9.ide.run.debug.xdebug": "#a1b39e0ac4",
"c9.ide.save": "#1ab1840513",
"c9.ide.scm": "#ca3c94b84f",
"c9.ide.terminal.monitor": "#a0d1f02991",
"c9.ide.test": "#a282ec1619",
"c9.ide.test.mocha": "#fc053b23d2",
"c9.ide.theme.flat": "#92cda0fb40",
"c9.ide.theme.flat": "#81dadeee55",
"c9.ide.threewaymerge": "#229382aa0b",
"c9.ide.undo": "#b028bcb4d5",
"c9.ide.upload": "#0bd010d3dc",

View File

@ -12,12 +12,11 @@ function plugin(options, imports, register) {
register(null, {
"analytics": {
log: function() {},
track: function() {},
identify: function() {},
logClean: function() {},
trackClean: function() {},
identifyClean: function() {},
updateTraits: function() {},
alias: function() {},
logClean: function() {} // huh??
}
});
}

View File

@ -57,7 +57,8 @@ define(function(require, exports, module) {
"text/x-csharp": "page_white_csharp",
"text/x-java-source": "page_white_cup",
"text/x-markdown": "page_white_text",
"text/x-xquery": "page_white_code"
"text/x-xquery": "page_white_code",
"text/x-go": "page_white_code",
};
var contentTypes = {
@ -87,6 +88,7 @@ define(function(require, exports, module) {
"xhtml": "application/xhtml+xml",
"coffee": "text/x-script.coffeescript",
"py": "text/x-script.python",
"go": "text/x-go",
"java": "text/x-java-source",
"logic": "text/x-logiql",

View File

@ -122,7 +122,7 @@ function plugin(options, imports, register) {
var allowedErrorKeys = [
"message", "projectState", "premium", "retryIn", "progress",
"oldHost", "blocked", "className", "errors"
"oldHost", "blocked", "className", "errors", "subtype"
];
allowedErrorKeys.forEach(function(key) {

View File

@ -216,7 +216,7 @@ define(function(require, exports, module) {
: (linkInfo
? { link: true, linkStat: { fullPath: linkInfo } }
: {});
stat.mtime = Math.floor(Date.now() / 1000);
stat.mtime = Date.now();
node = createNode(e.path, stat);
emit("add", {path : e.path, node : node});
@ -464,15 +464,30 @@ define(function(require, exports, module) {
var parts = path.split("/");
var node = context || model.root;
if (!node) {
node = orphans[parts[0]]; //model.realRoot ||
node = orphans[parts[0]]; // model.realRoot ||
if (node) parts.shift();
}
if (path == "/") parts.shift();
var up = 0;
for (var i = parts.length; i--;) {
var p = parts[i];
if (!p && i || p === ".") {
parts.splice(i, 1);
}
else if (p === "..") {
parts.splice(i, 1);
up++;
}
else if (up) {
parts.splice(i, 1);
up--;
}
}
for (var i = 0; i < parts.length; i++) {
var p = parts[i];
if (!p && i) continue; // allow paths with trailing /
if (node)
node = node.map && node.map[p];
if (!node)
@ -579,6 +594,14 @@ define(function(require, exports, module) {
node.children = null;
if (typeof node.mtime !== "number" && node.mtime) {
// why Date ends up here?
reportError(new Error("Date in fs cache"), {
stat: stat,
mtime: node.mtime,
path: node.path
});
}
if (!updating) {
if (!modified.length)
modified.push(parent);
@ -629,14 +652,6 @@ define(function(require, exports, module) {
});
} else if (key === "children" || key === "isSelected") {
prop = null;
} else if (Object.prototype.toString.call(node[key]) == "[object Date]") {
// why Date ends up here?
reportError(new Error("Date in fs cache"), {
key: key,
value: node[key],
path: node.path,
hasParentProp: !!node.parent,
});
} else {
prop = lang.deepCopy(node[key]);
}

View File

@ -21,6 +21,7 @@ define(function(require, exports, module) {
var stream = require("./fs.streams")(vfs, options.base, options.baseProc, options.cli);
var xhr = options.cli ? stream : require("./fs.xhr")(vfs.rest);
var uCaseFirst = require("c9/string").uCaseFirst;
var normalize = require("path").normalize;
var api = {
readFile: xhr.readFile,
@ -65,6 +66,11 @@ define(function(require, exports, module) {
if (typeof args[args.length - 1] != "function")
throw new Error("Missing callback for " + name);
path = args[0] = normalize(path);
if (name == "rename" || name == "copy" || name == "symlink") {
args[1] = normalize(args[1]);
}
// // TODO disabled to not break local version on windows
// if (!/^[!~/]/.test(path)) {
// var e = new Error("Invalid path passed to fs " + name);

View File

@ -111,7 +111,7 @@ define(function(require, exports, module) {
hide();
});
}
error.className = "errorlabel "
error.className = "errorlabel c9error "
+ (message.className ? message.className : "");
if (!message.noError) {
@ -141,7 +141,7 @@ define(function(require, exports, module) {
// Start anim
lastClassname = message.className;
setTimeout(function() {
error.className = "errorlabel anim " + (offset > 0 ? "fade-in" : "")
error.className = "errorlabel c9error anim " + (offset > 0 ? "fade-in" : "")
+ " " + (message.className || "");
error.style.top = (offset + topPx) + "px";
error.style.opacity = 1;
@ -164,7 +164,7 @@ define(function(require, exports, module) {
if (!error || error.style.display === "none")
return callback && callback();
error.className = "errorlabel anim " + (offset > 0 ? "fade-in " : " ")
error.className = "errorlabel c9error anim " + (offset > 0 ? "fade-in " : " ")
+ (lastClassname ? lastClassname : "");
if (offset > 0)
error.style.opacity = 0;

View File

@ -21,13 +21,13 @@
</div>
<div class="c9Staff">
<p textselect="true">
Arron Bailiss, Bas de Wachter, Dana Ivan, Fabian Jakobs, Harutyun Amirjanyan,
Ivar Pruijn, Justin Dray, Lennart Kats, Luca Cipriani,
Alex Brausewetter, Arron Bailiss, Bas de Wachter, Dana Ivan,
Fabian Jakobs, Harutyun Amirjanyan, Ivar Pruijn, Justin Dray, Lennart Kats, Luca Cipriani,
Mostafa Eweda, Matthijs van Henten, Nikolai Onken, Suraj Biyani, Tim Robinson, Ruben Daniels
</p>
</div>
<div class="c9Copyright">
<p>&#169; 2010 — 2015 Cloud9 Inc. All rights reserved</p>
<p>&#169; 2010 — 2016 Cloud9 Inc. All rights reserved</p>
</div>
</div>
</a:window>

View File

@ -26,6 +26,7 @@ define(function(require, exports, module) {
var plugin = new Panel("Ajax.org", main.consumes, {
index: options.index || 300,
caption: "Commands",
buttonCSSClass: "commands",
minWidth: 150,
autohide: true,
where: options.where || "left"

View File

@ -798,7 +798,7 @@
@gutter-tooltip-dark-shadow: 1px 1px 6px darken(rgba(0, 0, 0, 0.8), @darken-chrome);
@gutter-tooltip-dark-background: darken(#FFF399, @darken-chrome);
@gutter-tooltip-dark-border: black;
@gutter-tooltip-dark-color: darken(#e0e3e8, @darken-chrome);
@gutter-tooltip-dark-color: darken(#333, @darken-chrome);
@gutter-tooltip-dark-font-smoothing: true;
// Splitter

View File

@ -55,8 +55,6 @@ define(function(require, exports, module) {
/***** Methods *****/
// =0 means the value should be set to 0 to disable otherwise it is enabled
// =1 means the value should be set to 1 to enable otherwise it is disabled
var found = {};
function addExperiment(name, defaultValue, caption){
var uniqueId = name.replace(/\//g, "-");
@ -105,6 +103,7 @@ define(function(require, exports, module) {
plugin.on("unload", function() {
loaded = false;
drawn = false;
hasAlerted = false;
intro = null;
});

View File

@ -34,7 +34,7 @@
"Stop cursing, start coding",
"GET /this/workspace#loaded",
"Use our Vim mode for extra addictive effect!",
"Not your grandfather's IDE",
"Not your grandmother's IDE",
"Now made with 20% more cloud!",
"Literally makes your laptop cooler",
];

View File

@ -46,6 +46,7 @@ define(function(require, exports, module) {
index: options.index || 100,
caption: "Workspace",
panelCSSClass: "workspace_files",
buttonCSSClass: "workspace",
minWidth: 130,
where: options.where || "left"
});
@ -1586,4 +1587,4 @@ define(function(require, exports, module) {
tree: plugin
});
}
});
});

View File

@ -212,7 +212,8 @@ define(function(require, exports, module) {
} else if (body.indexOf("ENOENT") !== -1 || statusCode == 404) {
next(new error.NotFound("File '" + path + "' could not be found!"));
} else {
delete req.session.ws[req.ws];
if (req.session.ws)
delete req.session.ws[req.ws];
var json;
try {

View File

@ -331,7 +331,7 @@ function plugin(options, imports, register) {
.end(function() {});
user.lastVfsAccess = Date.now();
user.save(function() {});
user.save && user.save(function() {});
}
}

View File

@ -34,7 +34,7 @@ module.exports = function(methods, vfsHome, vfsWorkspace) {
function wrap(name, excluded) {
if (excluded) {
return function(){
return function() {
vfsWorkspace[name].apply(vfsWorkspace, arguments);
};
}
@ -43,11 +43,12 @@ module.exports = function(methods, vfsHome, vfsWorkspace) {
var args = Array.prototype.slice.call(arguments);
PATH_OPTIONS.forEach(function(o) {
options[o] = options[o] && substituteTilde(options[o]);
if (options[o] && typeof options[o] == "string")
options[o] = substituteTilde(options[o]);
});
args[1] = options;
if (path.charAt(0) == "~") {
if (typeof path == "string" && path.charAt(0) == "~") {
args[0] = substituteTilde(path);
vfsHome[name].apply(vfsHome, args);

View File

@ -0,0 +1,142 @@
#!/usr/bin/env node
/*global describe it before after beforeEach afterEach */
"use strict";
"use server";
require("c9/inline-mocha")(module);
var assert = require("assert-diff");
var async = require("async");
var sinon = require("sinon");
var vfs = require("vfs-local");
var vfsProxy = require("./vfs_proxy");
describe(__filename, function(){
var proxy, home, workspace;
before(function() {
home = vfs({
root: __dirname,
testing: true,
checkSymlinks: true
});
home.root = __dirname;
workspace = vfs({
root: __dirname + "/views",
testing: true,
checkSymlinks: true
});
});
beforeEach(function() {
proxy = vfsProxy(Object.keys(home), home, workspace);
});
it("should use home for files starting with ~ ", function(done) {
home.readfile = sinon.stub().callsArgWith(2, null, "home");
workspace.readfile = sinon.stub().callsArgWith(2, null, "workspace");
proxy.readfile("~/foo.txt", {}, function(err, data) {
assert(!err, err);
assert.equal(data, "home");
done();
});
});
it("should use workspace for files not starting with ~ ", function(done) {
home.readfile = sinon.stub().callsArgWith(2, null, "home");
workspace.readfile = sinon.stub().callsArgWith(2, null, "workspace");
proxy.readfile("foo.txt", {}, function(err, data) {
assert(!err, err);
assert.equal(data, "workspace");
done();
});
});
it("should expand ~ to paths relative to 'home'", function(done) {
home.readfile = function(path, options, callback) {
assert.equal(path, "/foo.txt");
callback(null, "home");
};
proxy.readfile("~/foo.txt", {}, function(err, data) {
assert(!err, err);
assert.equal(data, "home");
done();
});
});
it("should expand ~ in options", function(done) {
home.readfile = function(path, options, callback) {
assert.equal(path, "/foo.txt");
assert.equal(options.target, "/bar");
assert.equal(options.to, "/juhu");
assert.equal(options.from, "/kinners");
assert.equal(options.stuff, "~/stuff");
callback(null, "home");
};
proxy.readfile("~/foo.txt", {
target: "~/bar",
to: "~/juhu",
from: "~/kinners",
stuff: "~/stuff"
}, function(err, data) {
assert(!err, err);
assert.equal(data, "home");
done();
});
});
it("should expand some commands to absolute paths", function(done) {
home.execFile = function(path, options, callback) {
assert.equal(path, __dirname + "/foo.txt");
callback(null, "home");
};
proxy.execFile("~/foo.txt", {}, function(err, data) {
assert(!err, err);
assert.equal(data, "home");
done();
});
});
it("should not wrap some commands", function(done) {
async.eachSeries([
"connect",
"on",
"off",
"emit",
"extend",
"unextend",
"use",
"killtree"
], function(cmd, next) {
workspace[cmd] = function(path, options, callback) {
assert.equal(path, "~/foo.txt");
callback(null, "workspace");
};
proxy[cmd]("~/foo.txt", {}, function(err, data) {
assert(!err, err);
assert.equal(data, "workspace");
next();
});
}, done);
});
it("bad execFile arguments should not break the server", function(done) {
workspace.execFile = sinon.stub().callsArgWith(2, null, "done");
proxy.execFile(['ls', '-a'], {encoding: "utf8"}, function(err, data) {
assert(!err, err);
assert.equal(data, "done");
done();
});
});
});

View File

@ -83,6 +83,9 @@ module.exports = function(vfs, options) {
if (!options.file)
return callback(new error.Forbidden("Option 'file' is missing"));
if (typeof options.file != "string")
return callback(new error.Forbidden("Invalid option 'file'"));
if (extendDirectory) {
var file = options.file = path.normalize(path.join(extendDirectory, options.file));

View File

@ -0,0 +1,38 @@
#!/usr/bin/env node
/*global describe it before after beforeEach afterEach */
"use strict";
"use server";
require("c9/inline-mocha")(module);
var assert = require("assert-diff");
var path = require("path");
var vfs = require("vfs-local");
var vfsWrapper = require("./vfs_wrapper");
describe(__filename, function(){
describe("#extend", function() {
var wrapper;
beforeEach(function() {
var home = vfs({
root: path.normalize(__dirname + "/.."),
testing: true,
});
wrapper = vfsWrapper(home, {
root: __dirname
});
});
it("should return an error if file is not passed", function(done) {
wrapper.extend('foo', { file: {} ,encoding: "utf8"}, function(err, data) {
assert(err);
assert.equal(err.message, "Invalid option 'file'");
done();
});
});
});
});

View File

@ -168,6 +168,8 @@ function plugin(options, imports, register) {
});
var path = resolve(__dirname + "/../../build/output/latest.tar.gz");
fs.readlink(path, function(err, target) {
if (err) return next(err);
res.end((target || "").split(".")[0]);
});
});
@ -176,9 +178,19 @@ function plugin(options, imports, register) {
var filename = req.params.path;
var path = resolve(__dirname + "/../../build/output/" + filename);
res.writeHead(200, {"Content-Type": "application/octet-stream"});
var stream = fs.createReadStream(path);
stream.pipe(res);
stream.on("error", function(err) {
next(err);
});
stream.on("data", function(data) {
if (!res.headersSent)
res.writeHead(200, {"Content-Type": "application/octet-stream"});
res.write(data);
});
stream.on("end", function(data) {
res.end();
});
});
api.get("/configs/require_config.js", function(req, res, next) {

View File

@ -110,8 +110,9 @@ updateCore() {
fi
# without this git merge fails on windows
mv ./scripts/install-sdk.sh ./scripts/.install-sdk-tmp.sh
cp ./scripts/.install-sdk-tmp.sh ./scripts/install-sdk.sh
mv ./scripts/install-sdk.sh './scripts/.#install-sdk-tmp.sh'
rm ./scripts/.install-sdk-tmp.sh
cp './scripts/.#install-sdk-tmp.sh' ./scripts/install-sdk.sh
git checkout -- ./scripts/install-sdk.sh
git remote add c9 https://github.com/c9/core 2> /dev/null || true

View File

@ -12,6 +12,7 @@ var optimist = require("optimist");
var async = require("async");
var os = require("os");
var urls = require("c9/urls");
var hostname = require("c9/hostname");
var child_process = require("child_process");
require("c9/setup_paths.js");
@ -45,7 +46,7 @@ shortcuts.localdev = shortcuts.onlinedev.concat([
shortcuts.odev = shortcuts.onlinedev; // For backwards compatibility, if you see this in 2016 remove this line
var delayLoadConfigs = [
// Services that are usually not immediately needed
"preview", "user-content", "api", "apps-proxy", "worker",
"preview", "user-content", "apps-proxy", "worker", "homepage",
// Services that are very slow to load, blocking others
"profile",
];
@ -56,9 +57,7 @@ if (!module.parent)
main(process.argv.slice(2));
function getDefaultSettings() {
var hostname = os.hostname();
var suffix = hostname.trim().split("-").pop() || "";
var suffix = hostname.parse(os.hostname()).env;
var modes = {
"workflowstaging": "workflow-staging",
"prod": "deploy",