aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcash <cash.costello@gmail.com>2011-11-10 21:24:47 -0500
committercash <cash.costello@gmail.com>2011-11-16 19:53:03 -0500
commit6b6cb8e8f70b254d100ba494ea913d99be95fa7d (patch)
tree50150d855cd28478b584d45535e2edf7b063c837
parent45f007ed495b8f79f0b867fec72226d3c11c5eab (diff)
downloadelgg-6b6cb8e8f70b254d100ba494ea913d99be95fa7d.tar.gz
elgg-6b6cb8e8f70b254d100ba494ea913d99be95fa7d.tar.bz2
Fixes #4010 not sending naked query strings into add ajax tokens and also fixed a few related bugs in JavaScript
-rw-r--r--js/lib/ajax.js6
-rw-r--r--js/lib/elgglib.js68
-rw-r--r--js/lib/security.js18
-rw-r--r--js/tests/ElggLibTest.js22
-rw-r--r--js/tests/ElggSecurityTest.js40
5 files changed, 82 insertions, 72 deletions
diff --git a/js/lib/ajax.js b/js/lib/ajax.js
index 6f6ae052f..b3f39cc42 100644
--- a/js/lib/ajax.js
+++ b/js/lib/ajax.js
@@ -187,7 +187,11 @@ elgg.action = function(action, options) {
options = elgg.ajax.handleOptions(action, options);
- options.data = elgg.security.addToken(options.data);
+ // This is a misuse of elgg.security.addToken() because it is not always a
+ // full query string with a ?. As such we need a special check for the tokens.
+ if (!elgg.isString(options.data) || options.data.indexOf('__elgg_ts') == -1) {
+ options.data = elgg.security.addToken(options.data);
+ }
options.dataType = 'json';
//Always display system messages after actions
diff --git a/js/lib/elgglib.js b/js/lib/elgglib.js
index ca7914e7c..81209ebd0 100644
--- a/js/lib/elgglib.js
+++ b/js/lib/elgglib.js
@@ -410,16 +410,6 @@ elgg.parse_url = function(url, component, expand) {
// fragment
+ '(?:#(.*))?)',
keys = {
- 'mailto': {
- 4: "scheme",
- 5: "user",
- 6: "host",
- 9: "path",
- 12: "query",
- 13: "fragment"
- },
-
- 'standard': {
1: "scheme",
4: "user",
5: "pass",
@@ -428,58 +418,28 @@ elgg.parse_url = function(url, component, expand) {
9: "path",
12: "query",
13: "fragment"
- }
},
- results = {},
- match_keys,
- is_mailto = false;
+ results = {};
- var re = new RegExp(re_str);
- var matches = re.exec(url);
-
- // if the scheme field is undefined it means we're using a protocol
- // without :// and an @. Feel free to fix this in the re if you can >:O
- if (matches[1] == undefined) {
- match_keys = keys['mailto'];
- is_mailto = true;
- } else {
- match_keys = keys['standard'];
+ if (url.indexOf('mailto:') === 0) {
+ results['scheme'] = 'mailto';
+ results['path'] = url.replace('mailto:', '');
+ return results;
}
- for (var i in match_keys) {
- if (matches[i]) {
- results[match_keys[i]] = matches[i];
- }
+ if (url.indexOf('javascript:') === 0) {
+ results['scheme'] = 'javascript';
+ results['path'] = url.replace('javascript:', '');
+ return results;
}
- // merge everything to path if not standard
- if (is_mailto) {
- var path = '',
- new_results = {};
-
- if (typeof(results['user']) != 'undefined' && typeof(results['host']) != 'undefined') {
- path = results['user'] + '@' + results['host'];
- delete results['user'];
- delete results['host'];
- } else if (typeof(results['user'])) {
- path = results['user'];
- delete results['user'];
- } else if (typeof(results['host'])) {
- path = results['host'];
- delete results['host'];
- }
-
- if (typeof(results['path']) != 'undefined') {
- results['path'] = path + results['path'];
- } else {
- results['path'] = path;
- }
+ var re = new RegExp(re_str);
+ var matches = re.exec(url);
- for (var prop in results) {
- new_results[prop] = results[prop];
+ for (var i in keys) {
+ if (matches[i]) {
+ results[keys[i]] = matches[i];
}
-
- results = new_results;
}
if (expand && typeof(results['query']) != 'undefined') {
diff --git a/js/lib/security.js b/js/lib/security.js
index 726c6b767..61aa1cfcd 100644
--- a/js/lib/security.js
+++ b/js/lib/security.js
@@ -60,7 +60,7 @@ elgg.security.refreshToken = function() {
/**
- * Add elgg action tokens to an object, URL, or query string.
+ * Add elgg action tokens to an object, URL, or query string (with a ?).
*
* @param {Object|string} data
* @return {Object} The new data object including action tokens
@@ -75,17 +75,17 @@ elgg.security.addToken = function(data) {
args = {},
base = '';
- if (parts['host'] == data) {
- if (data.indexOf('=') > -1) {
+ if (parts['host'] == undefined) {
+ if (data.indexOf('?') === 0) {
// query string
- args = elgg.parse_str(data);
- } else {
- // relative URL
- base = data + '?';
+ base = '?';
+ args = elgg.parse_str(parts['query']);
}
} else {
- // a URL
- if (typeof parts['query'] != 'undefined') {
+ // full or relative URL
+
+ if (parts['query'] != undefined) {
+ // with query string
args = elgg.parse_str(parts['query']);
}
var split = data.split('?');
diff --git a/js/tests/ElggLibTest.js b/js/tests/ElggLibTest.js
index c53c6331d..a29ebf743 100644
--- a/js/tests/ElggLibTest.js
+++ b/js/tests/ElggLibTest.js
@@ -105,3 +105,25 @@ ElggLibTest.prototype.testNormalizeUrl = function() {
assertEquals(args[1], elgg.normalize_url(args[0]));
});
};
+
+ElggLibTest.prototype.testParseUrl = function() {
+
+ [
+ ["http://www.elgg.org/test/", {'scheme': 'http', 'host': 'www.elgg.org', 'path': '/test/'}],
+ ["https://www.elgg.org/test/", {'scheme': 'https', 'host': 'www.elgg.org', 'path': '/test/'}],
+ ["ftp://www.elgg.org/test/", {'scheme': 'ftp', 'host': 'www.elgg.org', 'path': '/test/'}],
+ ["http://elgg.org/test?val1=one&val2=two", {'scheme': 'http', 'host': 'elgg.org', 'path': '/test', 'query': 'val1=one&val2=two'}],
+ ["http://elgg.org:8080/", {'scheme': 'http', 'host': 'elgg.org', 'port': 8080, 'path': '/'}],
+ ["http://elgg.org/test#there", {'scheme': 'http', 'host': 'elgg.org', 'path': '/test', 'fragment': 'there'}],
+
+ ["test?val=one", {'host': 'test', 'query': 'val=one'}],
+ ["?val=one", {'query': 'val=one'}],
+
+ ["mailto:joe@elgg.org", {'scheme': 'mailto', 'path': 'joe@elgg.org'}],
+ ["javascript:load()", {'scheme': 'javascript', 'path': 'load()'}]
+
+ ].forEach(function(args) {
+ assertEquals(args[1], elgg.parse_url(args[0]));
+ });
+};
+
diff --git a/js/tests/ElggSecurityTest.js b/js/tests/ElggSecurityTest.js
index c7309d55f..107c0adbd 100644
--- a/js/tests/ElggSecurityTest.js
+++ b/js/tests/ElggSecurityTest.js
@@ -26,16 +26,42 @@ ElggSecurityTest.prototype.testAddTokenAcceptsObject = function() {
assertEquals(expected, elgg.security.addToken(input));
};
-ElggSecurityTest.prototype.testAddTokenAcceptsString = function() {
+ElggSecurityTest.prototype.testAddTokenAcceptsRelativeUrl = function() {
var input,
str = "__elgg_ts=" + this.ts + "&__elgg_token=" + this.token;
-
- input = "";
- assertEquals('?' + str, elgg.security.addToken(input));
-
+
+ input = "test";
+ assertEquals(input + '?' + str, elgg.security.addToken(input));
+};
+
+ElggSecurityTest.prototype.testAddTokenAcceptsFullUrl = function() {
+ var input,
+ str = "__elgg_ts=" + this.ts + "&__elgg_token=" + this.token;
+
+ input = "http://elgg.org/";
+ assertEquals(input + '?' + str, elgg.security.addToken(input));
+};
+
+ElggSecurityTest.prototype.testAddTokenAcceptsQueryString = function() {
+ var input,
+ str = "__elgg_ts=" + this.ts + "&__elgg_token=" + this.token;
+
input = "?data=sofar";
assertEquals(input + '&' + str, elgg.security.addToken(input));
-
+
+ input = "test?data=sofar";
+ assertEquals(input + '&' + str, elgg.security.addToken(input));
+
+ input = "http://elgg.org/?data=sofar";
+ assertEquals(input + '&' + str, elgg.security.addToken(input));
+};
+
+ElggSecurityTest.prototype.testAddTokenAlreadyAdded = function() {
+ var input,
+ str = "__elgg_ts=" + this.ts + "&__elgg_token=" + this.token;
+
+ input = "http://elgg.org/?" + str + "&data=sofar";
+ assertEquals(input, elgg.security.addToken(input));
};
ElggSecurityTest.prototype.testSetTokenSetsElggSecurityToken = function() {
@@ -47,5 +73,3 @@ ElggSecurityTest.prototype.testSetTokenSetsElggSecurityToken = function() {
elgg.security.setToken(json);
assertEquals(json, elgg.security.token);
};
-
-