Skip to content

Commit 57d8172

Browse files
committed
query-string unescape moved to js land
1 parent 2219c64 commit 57d8172

File tree

2 files changed

+71
-82
lines changed

2 files changed

+71
-82
lines changed

lib/querystring.js

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,78 @@
33
var QueryString = exports;
44
var urlDecode = process.binding("http_parser").urlDecode;
55

6+
7+
function charCode (c) {
8+
return c.charCodeAt(0);
9+
}
10+
11+
612
// a safe fast alternative to decodeURIComponent
7-
QueryString.unescape = urlDecode;
13+
QueryString.unescape = function (s, decodeSpaces) {
14+
var out = new Buffer(s.length);
15+
var state = "CHAR"; // states: CHAR, HEX0, HEX1
16+
var n, m, hexchar;
17+
18+
for (var inIndex = 0, outIndex = 0; inIndex <= s.length; inIndex++) {
19+
var c = s.charCodeAt(inIndex);
20+
switch (state) {
21+
case 'CHAR':
22+
switch (c) {
23+
case charCode('%'):
24+
n = 0;
25+
m = 0;
26+
state = 'HEX0';
27+
break;
28+
case charCode('+'):
29+
if (decodeSpaces) c = charCode(' ');
30+
// pass thru
31+
default:
32+
out[outIndex++] = c;
33+
break;
34+
}
35+
break;
36+
37+
case 'HEX0':
38+
state = 'HEX1';
39+
hexchar = c;
40+
if (charCode('0') <= c && c <= charCode('9')) {
41+
n = c - charCode('0');
42+
} else if (charCode('a') <= c && c <= charCode('f')) {
43+
n = c - charCode('a') + 10;
44+
} else if (charCode('A') <= c && c <= charCode('F')) {
45+
n = c - charCode('A') + 10;
46+
} else {
47+
out[outIndex++] = charCode('%');
48+
out[outIndex++] = c;
49+
state = 'CHAR';
50+
break;
51+
}
52+
break;
53+
54+
case 'HEX1':
55+
state = 'CHAR';
56+
if (charCode('0') <= c && c <= charCode('9')) {
57+
m = c - charCode('0');
58+
} else if (charCode('a') <= c && c <= charCode('f')) {
59+
m = c - charCode('a') + 10;
60+
} else if (charCode('A') <= c && c <= charCode('F')) {
61+
m = c - charCode('A') + 10;
62+
} else {
63+
out[outIndex++] = charCode('%');
64+
out[outIndex++] = hexchar;
65+
out[outIndex++] = c;
66+
break;
67+
}
68+
out[outIndex++] = 16*n + m;
69+
break;
70+
}
71+
}
72+
73+
// TODO support returning arbitrary buffers.
74+
75+
return out.toString('utf8', 0, outIndex-1);
76+
};
77+
878

979
QueryString.escape = function (str) {
1080
return encodeURIComponent(str);

src/node_http_parser.cc

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -338,86 +338,6 @@ class Parser : public ObjectWrap {
338338
};
339339

340340

341-
static Handle<Value> UrlDecode (const Arguments& args) {
342-
HandleScope scope;
343-
344-
if (!args[0]->IsString()) {
345-
return ThrowException(Exception::TypeError(
346-
String::New("First arg must be a string")));
347-
}
348-
349-
bool decode_spaces = args[1]->IsTrue();
350-
351-
String::Utf8Value in_v(args[0]->ToString());
352-
size_t l = in_v.length();
353-
char* out = strdup(*in_v);
354-
355-
enum { CHAR, HEX0, HEX1 } state = CHAR;
356-
357-
int n, m, hexchar;
358-
size_t in_index = 0, out_index = 0;
359-
char c;
360-
for (; in_index <= l; in_index++) {
361-
c = out[in_index];
362-
switch (state) {
363-
case CHAR:
364-
switch (c) {
365-
case '%':
366-
n = 0;
367-
m = 0;
368-
state = HEX0;
369-
break;
370-
case '+':
371-
if (decode_spaces) c = ' ';
372-
// pass thru
373-
default:
374-
out[out_index++] = c;
375-
break;
376-
}
377-
break;
378-
379-
case HEX0:
380-
state = HEX1;
381-
hexchar = c;
382-
if ('0' <= c && c <= '9') {
383-
n = c - '0';
384-
} else if ('a' <= c && c <= 'f') {
385-
n = c - 'a' + 10;
386-
} else if ('A' <= c && c <= 'F') {
387-
n = c - 'A' + 10;
388-
} else {
389-
out[out_index++] = '%';
390-
out[out_index++] = c;
391-
state = CHAR;
392-
break;
393-
}
394-
break;
395-
396-
case HEX1:
397-
state = CHAR;
398-
if ('0' <= c && c <= '9') {
399-
m = c - '0';
400-
} else if ('a' <= c && c <= 'f') {
401-
m = c - 'a' + 10;
402-
} else if ('A' <= c && c <= 'F') {
403-
m = c - 'A' + 10;
404-
} else {
405-
out[out_index++] = '%';
406-
out[out_index++] = hexchar;
407-
out[out_index++] = c;
408-
break;
409-
}
410-
out[out_index++] = 16*n + m;
411-
break;
412-
}
413-
}
414-
415-
Local<String> out_v = String::New(out, out_index-1);
416-
free(out);
417-
return scope.Close(out_v);
418-
}
419-
420-
421341
void InitHttpParser(Handle<Object> target) {
422342
HandleScope scope;
423343

@@ -430,7 +350,6 @@ void InitHttpParser(Handle<Object> target) {
430350
NODE_SET_PROTOTYPE_METHOD(t, "reinitialize", Parser::Reinitialize);
431351

432352
target->Set(String::NewSymbol("HTTPParser"), t->GetFunction());
433-
NODE_SET_METHOD(target, "urlDecode", UrlDecode);
434353

435354
on_message_begin_sym = NODE_PSYMBOL("onMessageBegin");
436355
on_path_sym = NODE_PSYMBOL("onPath");

0 commit comments

Comments
 (0)