qs 0.6.5 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.jshintignore ADDED
@@ -0,0 +1 @@
1
+ node_modules
package/.jshintrc ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "node": true,
3
+
4
+ "curly": true,
5
+ "latedef": true,
6
+ "quotmark": true,
7
+ "undef": true,
8
+ "unused": true,
9
+ "trailing": true
10
+ }
package/.npmignore CHANGED
@@ -1,7 +1,18 @@
1
- test
2
- .travis.yml
3
- benchmark.js
4
- component.json
5
- examples.js
6
- History.md
7
- Makefile
1
+ .idea
2
+ *.iml
3
+ npm-debug.log
4
+ dump.rdb
5
+ node_modules
6
+ results.tap
7
+ results.xml
8
+ npm-shrinkwrap.json
9
+ config.json
10
+ .DS_Store
11
+ */.DS_Store
12
+ */*/.DS_Store
13
+ ._*
14
+ */._*
15
+ */*/._*
16
+ coverage.*
17
+ lib-cov
18
+ complexity.md
package/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: node_js
2
+
3
+ node_js:
4
+ - 0.10
package/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ Copyright (c) 2014 Nathan LaFreniere and other contributors.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+ * Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ * Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+ * The names of any contributors may not be used to endorse or promote
12
+ products derived from this software without specific prior written
13
+ permission.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ * * *
27
+
28
+ The complete list of contributors can be found at: https://github.com/hapijs/qs/graphs/contributors
package/Makefile ADDED
@@ -0,0 +1,8 @@
1
+ test:
2
+ @node node_modules/lab/bin/lab
3
+ test-cov:
4
+ @node node_modules/lab/bin/lab -t 100
5
+ test-cov-html:
6
+ @node node_modules/lab/bin/lab -r html -o coverage.html
7
+
8
+ .PHONY: test test-cov test-cov-html
package/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # qs
2
+
3
+ A querystring parsing and stringifying library with some added security.
4
+
5
+ [![Build Status](https://secure.travis-ci.org/hapijs/qs.svg)](http://travis-ci.org/hapijs/qs)
6
+
7
+ Lead Maintainer: [Nathan LaFreniere](https://github.com/nlf)
8
+
9
+ The **qs** module was original created and maintained by [TJ Holowaychuk](https://github.com/visionmedia/node-querystring).
10
+
11
+ ## Usage
12
+
13
+ ```javascript
14
+ var Qs = require('qs');
15
+
16
+ var obj = Qs.parse('a=c'); // { a: 'c' }
17
+ var str = Qs.stringify(obj); // 'a=c'
18
+ ```
19
+
20
+ ### Objects
21
+
22
+ **qs** allows you to create nested objects within your query strings, by surrounding the name of sub-keys with square brackets `[]`.
23
+ For example, the string `'foo[bar]=baz'` converts to:
24
+
25
+ ```javascript
26
+ {
27
+ foo: {
28
+ bar: 'baz'
29
+ }
30
+ }
31
+ ```
32
+
33
+ You can also nest your objects, like `'foo[bar][baz]=foobarbaz'`:
34
+
35
+ ```javascript
36
+ {
37
+ foo: {
38
+ bar: {
39
+ baz: 'foobarbaz'
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ By default, when nesting objects **qs** will only parse up to 5 children deep. This means if you attempt to parse a string like
46
+ `'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be:
47
+
48
+ ```javascript
49
+ {
50
+ a: {
51
+ b: {
52
+ c: {
53
+ d: {
54
+ e: {
55
+ f: {
56
+ '[g][h][i]': 'j'
57
+ }
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
64
+ ```
65
+
66
+ This depth can be overridden by passing a `depth` option to `Qs.parse(string, depth)`:
67
+
68
+ ```javascript
69
+ Qs.parse('a[b][c][d][e][f][g][h][i]=j', 1);
70
+ // { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } }
71
+ ```
72
+
73
+ The depth limit mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number.
74
+
75
+ ### Arrays
76
+
77
+ **qs** can also parse arrays using a similar `[]` notation:
78
+
79
+ ```javascript
80
+ Qs.parse('a[]=b&a[]=c');
81
+ // { a: ['b', 'c'] }
82
+ ```
83
+
84
+ You may specify an index as well:
85
+
86
+ ```javascript
87
+ Qs.parse('a[1]=c&a[0]=b');
88
+ // { a: ['b', 'c'] }
89
+ ```
90
+
91
+ Note that the only difference between an index in an array and a key in an object is that the value between the brackets must be a number
92
+ to create an array. When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving
93
+ their order:
94
+
95
+ ```javascript
96
+ Qs.parse('a[1]=b&a[15]=c');
97
+ // { a: ['b', 'c'] }
98
+ ```
99
+
100
+ **qs** will also limit specifying indices in an array to a maximum index of `20`. Any array members with an index of greater than `20` will
101
+ instead be converted to an object with the index as the key:
102
+
103
+ ```javascript
104
+ Qs.parse('a[100]=b');
105
+ // { a: { '100': 'b' } }
106
+ ```
107
+
108
+ If you mix notations, **qs** will merge the two items into an object:
109
+
110
+ ```javascript
111
+ Qs.parse('a[0]=b&a[b]=c');
112
+ // { a: { '0': 'b', b: 'c' } }
113
+ ```
114
+
115
+ You can also create arrays of objects:
116
+
117
+ ```javascript
118
+ Qs.parse('a[][b]=c');
119
+ // { a: [{ b: 'c' }] }
120
+ ```
package/index.js CHANGED
@@ -1,387 +1 @@
1
- /**
2
- * Object#toString() ref for stringify().
3
- */
4
-
5
- var toString = Object.prototype.toString;
6
-
7
- /**
8
- * Object#hasOwnProperty ref
9
- */
10
-
11
- var hasOwnProperty = Object.prototype.hasOwnProperty;
12
-
13
- /**
14
- * Array#indexOf shim.
15
- */
16
-
17
- var indexOf = typeof Array.prototype.indexOf === 'function'
18
- ? function(arr, el) { return arr.indexOf(el); }
19
- : function(arr, el) {
20
- for (var i = 0; i < arr.length; i++) {
21
- if (arr[i] === el) return i;
22
- }
23
- return -1;
24
- };
25
-
26
- /**
27
- * Array.isArray shim.
28
- */
29
-
30
- var isArray = Array.isArray || function(arr) {
31
- return toString.call(arr) == '[object Array]';
32
- };
33
-
34
- /**
35
- * Object.keys shim.
36
- */
37
-
38
- var objectKeys = Object.keys || function(obj) {
39
- var ret = [];
40
- for (var key in obj) ret.push(key);
41
- return ret;
42
- };
43
-
44
- /**
45
- * Array#forEach shim.
46
- */
47
-
48
- var forEach = typeof Array.prototype.forEach === 'function'
49
- ? function(arr, fn) { return arr.forEach(fn); }
50
- : function(arr, fn) {
51
- for (var i = 0; i < arr.length; i++) fn(arr[i]);
52
- };
53
-
54
- /**
55
- * Array#reduce shim.
56
- */
57
-
58
- var reduce = function(arr, fn, initial) {
59
- if (typeof arr.reduce === 'function') return arr.reduce(fn, initial);
60
- var res = initial;
61
- for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]);
62
- return res;
63
- };
64
-
65
- /**
66
- * Create a nullary object if possible
67
- */
68
-
69
- function createObject() {
70
- return Object.create
71
- ? Object.create(null)
72
- : {};
73
- }
74
-
75
- /**
76
- * Cache non-integer test regexp.
77
- */
78
-
79
- var isint = /^[0-9]+$/;
80
-
81
- function promote(parent, key) {
82
- if (parent[key].length == 0) return parent[key] = createObject();
83
- var t = createObject();
84
- for (var i in parent[key]) {
85
- if (hasOwnProperty.call(parent[key], i)) {
86
- t[i] = parent[key][i];
87
- }
88
- }
89
- parent[key] = t;
90
- return t;
91
- }
92
-
93
- function parse(parts, parent, key, val) {
94
- var part = parts.shift();
95
- // end
96
- if (!part) {
97
- if (isArray(parent[key])) {
98
- parent[key].push(val);
99
- } else if ('object' == typeof parent[key]) {
100
- parent[key] = val;
101
- } else if ('undefined' == typeof parent[key]) {
102
- parent[key] = val;
103
- } else {
104
- parent[key] = [parent[key], val];
105
- }
106
- // array
107
- } else {
108
- var obj = parent[key] = parent[key] || [];
109
- if (']' == part) {
110
- if (isArray(obj)) {
111
- if ('' != val) obj.push(val);
112
- } else if ('object' == typeof obj) {
113
- obj[objectKeys(obj).length] = val;
114
- } else {
115
- obj = parent[key] = [parent[key], val];
116
- }
117
- // prop
118
- } else if (~indexOf(part, ']')) {
119
- part = part.substr(0, part.length - 1);
120
- if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
121
- parse(parts, obj, part, val);
122
- // key
123
- } else {
124
- if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
125
- parse(parts, obj, part, val);
126
- }
127
- }
128
- }
129
-
130
- /**
131
- * Merge parent key/val pair.
132
- */
133
-
134
- function merge(parent, key, val){
135
- if (~indexOf(key, ']')) {
136
- var parts = key.split('[')
137
- , len = parts.length
138
- , last = len - 1;
139
- parse(parts, parent, 'base', val);
140
- // optimize
141
- } else {
142
- if (!isint.test(key) && isArray(parent.base)) {
143
- var t = createObject();
144
- for (var k in parent.base) t[k] = parent.base[k];
145
- parent.base = t;
146
- }
147
- set(parent.base, key, val);
148
- }
149
-
150
- return parent;
151
- }
152
-
153
- /**
154
- * Compact sparse arrays.
155
- */
156
-
157
- function compact(obj) {
158
- if ('object' != typeof obj) return obj;
159
-
160
- if (isArray(obj)) {
161
- var ret = [];
162
-
163
- for (var i in obj) {
164
- if (hasOwnProperty.call(obj, i)) {
165
- ret.push(obj[i]);
166
- }
167
- }
168
-
169
- return ret;
170
- }
171
-
172
- for (var key in obj) {
173
- obj[key] = compact(obj[key]);
174
- }
175
-
176
- return obj;
177
- }
178
-
179
- /**
180
- * Restore Object.prototype.
181
- * see pull-request #58
182
- */
183
-
184
- function restoreProto(obj) {
185
- if (!Object.create) return obj;
186
- if (isArray(obj)) return obj;
187
- if (obj && 'object' != typeof obj) return obj;
188
-
189
- for (var key in obj) {
190
- if (hasOwnProperty.call(obj, key)) {
191
- obj[key] = restoreProto(obj[key]);
192
- }
193
- }
194
-
195
- obj.__proto__ = Object.prototype;
196
- return obj;
197
- }
198
-
199
- /**
200
- * Parse the given obj.
201
- */
202
-
203
- function parseObject(obj){
204
- var ret = { base: {} };
205
-
206
- forEach(objectKeys(obj), function(name){
207
- merge(ret, name, obj[name]);
208
- });
209
-
210
- return compact(ret.base);
211
- }
212
-
213
- /**
214
- * Parse the given str.
215
- */
216
-
217
- function parseString(str){
218
- var ret = reduce(String(str).split('&'), function(ret, pair){
219
- var eql = indexOf(pair, '=')
220
- , brace = lastBraceInKey(pair)
221
- , key = pair.substr(0, brace || eql)
222
- , val = pair.substr(brace || eql, pair.length)
223
- , val = val.substr(indexOf(val, '=') + 1, val.length);
224
-
225
- // ?foo
226
- if ('' == key) key = pair, val = '';
227
- if ('' == key) return ret;
228
-
229
- return merge(ret, decode(key), decode(val));
230
- }, { base: createObject() }).base;
231
-
232
- return restoreProto(compact(ret));
233
- }
234
-
235
- /**
236
- * Parse the given query `str` or `obj`, returning an object.
237
- *
238
- * @param {String} str | {Object} obj
239
- * @return {Object}
240
- * @api public
241
- */
242
-
243
- exports.parse = function(str){
244
- if (null == str || '' == str) return {};
245
- return 'object' == typeof str
246
- ? parseObject(str)
247
- : parseString(str);
248
- };
249
-
250
- /**
251
- * Turn the given `obj` into a query string
252
- *
253
- * @param {Object} obj
254
- * @return {String}
255
- * @api public
256
- */
257
-
258
- var stringify = exports.stringify = function(obj, prefix) {
259
- if (isArray(obj)) {
260
- return stringifyArray(obj, prefix);
261
- } else if ('[object Object]' == toString.call(obj)) {
262
- return stringifyObject(obj, prefix);
263
- } else if ('string' == typeof obj) {
264
- return stringifyString(obj, prefix);
265
- } else {
266
- return prefix + '=' + encodeURIComponent(String(obj));
267
- }
268
- };
269
-
270
- /**
271
- * Stringify the given `str`.
272
- *
273
- * @param {String} str
274
- * @param {String} prefix
275
- * @return {String}
276
- * @api private
277
- */
278
-
279
- function stringifyString(str, prefix) {
280
- if (!prefix) throw new TypeError('stringify expects an object');
281
- return prefix + '=' + encodeURIComponent(str);
282
- }
283
-
284
- /**
285
- * Stringify the given `arr`.
286
- *
287
- * @param {Array} arr
288
- * @param {String} prefix
289
- * @return {String}
290
- * @api private
291
- */
292
-
293
- function stringifyArray(arr, prefix) {
294
- var ret = [];
295
- if (!prefix) throw new TypeError('stringify expects an object');
296
- for (var i = 0; i < arr.length; i++) {
297
- ret.push(stringify(arr[i], prefix + '[' + i + ']'));
298
- }
299
- return ret.join('&');
300
- }
301
-
302
- /**
303
- * Stringify the given `obj`.
304
- *
305
- * @param {Object} obj
306
- * @param {String} prefix
307
- * @return {String}
308
- * @api private
309
- */
310
-
311
- function stringifyObject(obj, prefix) {
312
- var ret = []
313
- , keys = objectKeys(obj)
314
- , key;
315
-
316
- for (var i = 0, len = keys.length; i < len; ++i) {
317
- key = keys[i];
318
- if ('' == key) continue;
319
- if (null == obj[key]) {
320
- ret.push(encodeURIComponent(key) + '=');
321
- } else {
322
- ret.push(stringify(obj[key], prefix
323
- ? prefix + '[' + encodeURIComponent(key) + ']'
324
- : encodeURIComponent(key)));
325
- }
326
- }
327
-
328
- return ret.join('&');
329
- }
330
-
331
- /**
332
- * Set `obj`'s `key` to `val` respecting
333
- * the weird and wonderful syntax of a qs,
334
- * where "foo=bar&foo=baz" becomes an array.
335
- *
336
- * @param {Object} obj
337
- * @param {String} key
338
- * @param {String} val
339
- * @api private
340
- */
341
-
342
- function set(obj, key, val) {
343
- var v = obj[key];
344
- if (undefined === v) {
345
- obj[key] = val;
346
- } else if (isArray(v)) {
347
- v.push(val);
348
- } else {
349
- obj[key] = [v, val];
350
- }
351
- }
352
-
353
- /**
354
- * Locate last brace in `str` within the key.
355
- *
356
- * @param {String} str
357
- * @return {Number}
358
- * @api private
359
- */
360
-
361
- function lastBraceInKey(str) {
362
- var len = str.length
363
- , brace
364
- , c;
365
- for (var i = 0; i < len; ++i) {
366
- c = str[i];
367
- if (']' == c) brace = false;
368
- if ('[' == c) brace = true;
369
- if ('=' == c && !brace) return i;
370
- }
371
- }
372
-
373
- /**
374
- * Decode `str`.
375
- *
376
- * @param {String} str
377
- * @return {String}
378
- * @api private
379
- */
380
-
381
- function decode(str) {
382
- try {
383
- return decodeURIComponent(str.replace(/\+/g, ' '));
384
- } catch (err) {
385
- return str;
386
- }
387
- }
1
+ module.exports = require('./lib');
package/lib/index.js ADDED
@@ -0,0 +1,15 @@
1
+ // Load modules
2
+
3
+ var Stringify = require('./stringify');
4
+ var Parse = require('./parse');
5
+
6
+
7
+ // Declare internals
8
+
9
+ var internals = {};
10
+
11
+
12
+ module.exports = {
13
+ stringify: Stringify,
14
+ parse: Parse
15
+ };