From 57d817290649a53472664cd266d5f756e8e59e95 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Thu, 18 Nov 2010 15:12:21 -0800 Subject: [PATCH] query-string unescape moved to js land --- lib/querystring.js | 72 +++++++++++++++++++++++++++++++++++- src/node_http_parser.cc | 81 ----------------------------------------- 2 files changed, 71 insertions(+), 82 deletions(-) diff --git a/lib/querystring.js b/lib/querystring.js index f60ab1dc57..d7c642f101 100644 --- a/lib/querystring.js +++ b/lib/querystring.js @@ -3,8 +3,78 @@ var QueryString = exports; var urlDecode = process.binding("http_parser").urlDecode; + +function charCode (c) { + return c.charCodeAt(0); +} + + // a safe fast alternative to decodeURIComponent -QueryString.unescape = urlDecode; +QueryString.unescape = function (s, decodeSpaces) { + var out = new Buffer(s.length); + var state = "CHAR"; // states: CHAR, HEX0, HEX1 + var n, m, hexchar; + + for (var inIndex = 0, outIndex = 0; inIndex <= s.length; inIndex++) { + var c = s.charCodeAt(inIndex); + switch (state) { + case 'CHAR': + switch (c) { + case charCode('%'): + n = 0; + m = 0; + state = 'HEX0'; + break; + case charCode('+'): + if (decodeSpaces) c = charCode(' '); + // pass thru + default: + out[outIndex++] = c; + break; + } + break; + + case 'HEX0': + state = 'HEX1'; + hexchar = c; + if (charCode('0') <= c && c <= charCode('9')) { + n = c - charCode('0'); + } else if (charCode('a') <= c && c <= charCode('f')) { + n = c - charCode('a') + 10; + } else if (charCode('A') <= c && c <= charCode('F')) { + n = c - charCode('A') + 10; + } else { + out[outIndex++] = charCode('%'); + out[outIndex++] = c; + state = 'CHAR'; + break; + } + break; + + case 'HEX1': + state = 'CHAR'; + if (charCode('0') <= c && c <= charCode('9')) { + m = c - charCode('0'); + } else if (charCode('a') <= c && c <= charCode('f')) { + m = c - charCode('a') + 10; + } else if (charCode('A') <= c && c <= charCode('F')) { + m = c - charCode('A') + 10; + } else { + out[outIndex++] = charCode('%'); + out[outIndex++] = hexchar; + out[outIndex++] = c; + break; + } + out[outIndex++] = 16*n + m; + break; + } + } + + // TODO support returning arbitrary buffers. + + return out.toString('utf8', 0, outIndex-1); +}; + QueryString.escape = function (str) { return encodeURIComponent(str); diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index 1524f4abd3..5c7758b367 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -338,86 +338,6 @@ class Parser : public ObjectWrap { }; -static Handle UrlDecode (const Arguments& args) { - HandleScope scope; - - if (!args[0]->IsString()) { - return ThrowException(Exception::TypeError( - String::New("First arg must be a string"))); - } - - bool decode_spaces = args[1]->IsTrue(); - - String::Utf8Value in_v(args[0]->ToString()); - size_t l = in_v.length(); - char* out = strdup(*in_v); - - enum { CHAR, HEX0, HEX1 } state = CHAR; - - int n, m, hexchar; - size_t in_index = 0, out_index = 0; - char c; - for (; in_index <= l; in_index++) { - c = out[in_index]; - switch (state) { - case CHAR: - switch (c) { - case '%': - n = 0; - m = 0; - state = HEX0; - break; - case '+': - if (decode_spaces) c = ' '; - // pass thru - default: - out[out_index++] = c; - break; - } - break; - - case HEX0: - state = HEX1; - hexchar = c; - if ('0' <= c && c <= '9') { - n = c - '0'; - } else if ('a' <= c && c <= 'f') { - n = c - 'a' + 10; - } else if ('A' <= c && c <= 'F') { - n = c - 'A' + 10; - } else { - out[out_index++] = '%'; - out[out_index++] = c; - state = CHAR; - break; - } - break; - - case HEX1: - state = CHAR; - if ('0' <= c && c <= '9') { - m = c - '0'; - } else if ('a' <= c && c <= 'f') { - m = c - 'a' + 10; - } else if ('A' <= c && c <= 'F') { - m = c - 'A' + 10; - } else { - out[out_index++] = '%'; - out[out_index++] = hexchar; - out[out_index++] = c; - break; - } - out[out_index++] = 16*n + m; - break; - } - } - - Local out_v = String::New(out, out_index-1); - free(out); - return scope.Close(out_v); -} - - void InitHttpParser(Handle target) { HandleScope scope; @@ -430,7 +350,6 @@ void InitHttpParser(Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "reinitialize", Parser::Reinitialize); target->Set(String::NewSymbol("HTTPParser"), t->GetFunction()); - NODE_SET_METHOD(target, "urlDecode", UrlDecode); on_message_begin_sym = NODE_PSYMBOL("onMessageBegin"); on_path_sym = NODE_PSYMBOL("onPath");