Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

replace decodeURIComponent with a simple buffer-based deal

Fix caught by aheckmann
  • Loading branch information...
commit c5337780cb3518fe875c2465384ba7a9dddbbb4c 1 parent 55c5485
@isaacs authored
Showing with 71 additions and 20 deletions.
  1. +71 −20 lib/querystring.js
View
91 lib/querystring.js
@@ -1,10 +1,71 @@
// Query String Utilities
-var QueryString = exports;
+var QueryString = exports
+ , Buffer = require("buffer").Buffer
+// a safe fast alternative to decodeURIComponent
QueryString.unescape = function (str, decodeSpaces) {
- return decodeURIComponent(decodeSpaces ? str.replace(/\+/g, " ") : str);
-};
+ return "" + QueryString.unescapeToBuffer(str, decodeSpaces)
+}
+QueryString.unescapeToBuffer = function (str, decodeSpaces) {
+ var hex = ""
+ , l = str.length
+ , b = 0
+ // create the buffer on the assumption of maximum size.
+ // bytes are cheap.
+ , buffer = new Buffer(l)
+ , i
+ , c
+ , state = "CHAR"
+ , PCT = "%".charCodeAt(0)
+ for (i = 0; c = str.charAt(i); i ++) {
+ switch (state) {
+ case "CHAR":
+ switch (c) {
+ case "%": state = "HEX0"; break
+ default :
+ if (c === "+" && decodeSpaces) c = " "
+ buffer[b++] = c.charCodeAt(0)
+ break
+ }
+ continue;
+ case "HEX0":
+ switch (c) {
+ case "0": case "1": case "2": case "3": case "4": case "5":
+ case "6": case "7": case "8": case "9": case "a": case "b":
+ case "c": case "d": case "e": case "f": case "A": case "B":
+ case "C": case "D": case "E": case "F":
+ hex = c
+ state = "HEX1"
+ break
+ default:
+ buffer[b++] = PCT
+ buffer[b++] = c.charCodeAt(0)
+ state = "CHAR"
+ break
+ }
+ continue;
+ case "HEX1":
+ switch (c) {
+ case "0": case "1": case "2": case "3": case "4": case "5":
+ case "6": case "7": case "8": case "9": case "a": case "b":
+ case "c": case "d": case "e": case "f": case "A": case "B":
+ case "C": case "D": case "E": case "F":
+ hex += c
+ buffer[b++] = parseInt(hex, 16)
+ break;
+ default:
+ buffer[b++] = PCT
+ buffer[b++] = hex.charCodeAt(0)
+ buffer[b++] = c.charCodeAt(0)
+ break
+ }
+ state = "CHAR"
+ continue
+ }
+ }
+ return buffer.slice(0, b)
+}
QueryString.escape = function (str) {
return encodeURIComponent(str);
@@ -25,17 +86,17 @@ var stack = [];
* @param name {String} (optional) Name of the current key, for handling children recursively.
* @static
*/
-QueryString.stringify = function (obj, sep, eq, munge, name) {
+QueryString.stringify = QueryString.encode = function (obj, sep, eq, munge, name) {
munge = typeof(munge) == "undefined" ? true : munge;
sep = sep || "&";
eq = eq || "=";
if (isA(obj, null) || isA(obj, undefined) || typeof(obj) === 'function') {
- return name ? encodeURIComponent(name) + eq : '';
+ return name ? QueryString.escape(name) + eq : '';
}
if (isBool(obj)) obj = +obj;
if (isNumber(obj) || isString(obj)) {
- return encodeURIComponent(name) + eq + encodeURIComponent(obj);
+ return QueryString.escape(name) + eq + QueryString.escape(obj);
}
if (isA(obj, [])) {
var s = [];
@@ -71,11 +132,11 @@ QueryString.stringify = function (obj, sep, eq, munge, name) {
return s;
};
-QueryString.parseQuery = QueryString.parse = function (qs, sep, eq) {
+QueryString.parse = QueryString.decode = function (qs, sep, eq) {
return (qs || '')
.split(sep||"&")
.map(pieceParser(eq||"="))
- .reduce(mergeParams);
+ .reduce(mergeParams)
};
// Parse a key=val string.
@@ -87,8 +148,7 @@ QueryString.parseQuery = QueryString.parse = function (qs, sep, eq) {
// return parse(foo[bar], [{bla:"baz"}])
// return parse(foo, {bar:[{bla:"baz"}]})
// return {foo:{bar:[{bla:"baz"}]}}
-var trimmerPattern = /^\s+|\s+$/g,
- slicerPattern = /(.*)\[([^\]]*)\]$/;
+var slicerPattern = /(.*)\[([^\]]*)\]$/;
var pieceParser = function (eq) {
return function parsePiece (key, val) {
if (arguments.length !== 2) {
@@ -96,18 +156,9 @@ var pieceParser = function (eq) {
key = key.split(eq);
return parsePiece(
QueryString.unescape(key.shift(), true),
- QueryString.unescape(key.join(eq), true)
+ ''+QueryString.unescape(key.join(eq), true)
);
}
- key = key.replace(trimmerPattern, '');
- if (isString(val)) {
- val = val.replace(trimmerPattern, '');
- // convert numerals to numbers
- if (!isNaN(val)) {
- var numVal = +val;
- if (val === numVal.toString(10)) val = numVal;
- }
- }
var sliced = slicerPattern.exec(key);
if (!sliced) {
var ret = {};
Please sign in to comment.
Something went wrong with that request. Please try again.