123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- /**!
- * urlencode - lib/urlencode.js
- *
- * MIT Licensed
- *
- * Authors:
- * fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
- */
- "use strict";
- /**
- * Module dependencies.
- */
- var iconv = require('iconv-lite');
- function isUTF8(charset) {
- if (!charset) {
- return true;
- }
- charset = charset.toLowerCase();
- return charset === 'utf8' || charset === 'utf-8';
- }
- function encode(str, charset) {
- if (isUTF8(charset)) {
- return encodeURIComponent(str);
- }
- var buf = iconv.encode(str, charset);
- var encodeStr = '';
- var ch = '';
- for (var i = 0; i < buf.length; i++) {
- ch = buf[i].toString('16');
- if (ch.length === 1) {
- ch = '0' + ch;
- }
- encodeStr += '%' + ch;
- }
- encodeStr = encodeStr.toUpperCase();
- return encodeStr;
- }
- function decode(str, charset) {
- if (isUTF8(charset)) {
- return decodeURIComponent(str);
- }
- var bytes = [];
- for (var i = 0; i < str.length; ) {
- if (str[i] === '%') {
- i++;
- bytes.push(parseInt(str.substring(i, i + 2), 16));
- i += 2;
- } else {
- bytes.push(str.charCodeAt(i));
- i++;
- }
- }
- var buf = new Buffer(bytes);
- return iconv.decode(buf, charset);
- }
- function parse(qs, sep, eq, options) {
- if (typeof sep === 'object') {
- // parse(qs, options)
- options = sep;
- sep = null;
- }
- sep = sep || '&';
- eq = eq || '=';
- var obj = {};
- if (typeof qs !== 'string' || qs.length === 0) {
- return obj;
- }
- var regexp = /\+/g;
- qs = qs.split(sep);
- var maxKeys = 1000;
- var charset = null;
- if (options) {
- if (typeof options.maxKeys === 'number') {
- maxKeys = options.maxKeys;
- }
- if (typeof options.charset === 'string') {
- charset = options.charset;
- }
- }
- var len = qs.length;
- // maxKeys <= 0 means that we should not limit keys count
- if (maxKeys > 0 && len > maxKeys) {
- len = maxKeys;
- }
- for (var i = 0; i < len; ++i) {
- var x = qs[i].replace(regexp, '%20');
- var idx = x.indexOf(eq);
- var kstr, vstr, k, v;
- if (idx >= 0) {
- kstr = x.substr(0, idx);
- vstr = x.substr(idx + 1);
- } else {
- kstr = x;
- vstr = '';
- }
- if (kstr && kstr.indexOf('%') >= 0) {
- try {
- k = decode(kstr, charset);
- } catch (e) {
- k = kstr;
- }
- } else {
- k = kstr;
- }
- if (vstr && vstr.indexOf('%') >= 0) {
- try {
- v = decode(vstr, charset);
- } catch (e) {
- v = vstr;
- }
- } else {
- v = vstr;
- }
- if (!has(obj, k)) {
- obj[k] = v;
- } else if (Array.isArray(obj[k])) {
- obj[k].push(v);
- } else {
- obj[k] = [obj[k], v];
- }
- }
- return obj;
- }
- function has(obj, prop) {
- return Object.prototype.hasOwnProperty.call(obj, prop);
- }
- function isASCII(str) {
- return (/^[\x00-\x7F]*$/).test(str);
- }
- function encodeComponent(item, charset) {
- item = String(item);
- if (isASCII(item)) {
- item = encodeURIComponent(item);
- } else {
- item = encode(item, charset);
- }
- return item;
- }
- var stringify = function(obj, prefix, options) {
- if (typeof prefix !== 'string') {
- options = prefix || {};
- prefix = null;
- }
- var charset = options.charset || 'utf-8';
- if (Array.isArray(obj)) {
- return stringifyArray(obj, prefix, options);
- } else if ('[object Object]' === {}.toString.call(obj)) {
- return stringifyObject(obj, prefix, options);
- } else if ('string' === typeof obj) {
- return stringifyString(obj, prefix, options);
- } else {
- return prefix + '=' + encodeComponent(String(obj), charset);
- }
- };
- function stringifyString(str, prefix, options) {
- if (!prefix) {
- throw new TypeError('stringify expects an object');
- }
- var charset = options.charset;
- return prefix + '=' + encodeComponent(str, charset);
- }
- function stringifyArray(arr, prefix, options) {
- var ret = [];
- if (!prefix) {
- throw new TypeError('stringify expects an object');
- }
- for (var i = 0; i < arr.length; i++) {
- ret.push(stringify(arr[i], prefix + '[' + i + ']', options));
- }
- return ret.join('&');
- }
- function stringifyObject(obj, prefix, options) {
- var ret = [];
- var keys = Object.keys(obj);
- var key;
- var charset = options.charset;
- for (var i = 0, len = keys.length; i < len; ++i) {
- key = keys[i];
- if ('' === key) {
- continue;
- }
- if (null === obj[key]) {
- ret.push(encode(key, charset) + '=');
- } else {
- ret.push(stringify(
- obj[key],
- prefix ? prefix + '[' + encodeComponent(key, charset) + ']': encodeComponent(key, charset),
- options));
- }
- }
- return ret.join('&');
- }
- module.exports = encode;
- module.exports.encode = encode;
- module.exports.decode = decode;
- module.exports.parse = parse;
- module.exports.stringify = stringify;
|