119 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| var has = Object.prototype.hasOwnProperty
 | |
|   , undef;
 | |
| 
 | |
| /**
 | |
|  * Decode a URI encoded string.
 | |
|  *
 | |
|  * @param {String} input The URI encoded string.
 | |
|  * @returns {String|Null} The decoded string.
 | |
|  * @api private
 | |
|  */
 | |
| function decode(input) {
 | |
|   try {
 | |
|     return decodeURIComponent(input.replace(/\+/g, ' '));
 | |
|   } catch (e) {
 | |
|     return null;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Attempts to encode a given input.
 | |
|  *
 | |
|  * @param {String} input The string that needs to be encoded.
 | |
|  * @returns {String|Null} The encoded string.
 | |
|  * @api private
 | |
|  */
 | |
| function encode(input) {
 | |
|   try {
 | |
|     return encodeURIComponent(input);
 | |
|   } catch (e) {
 | |
|     return null;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Simple query string parser.
 | |
|  *
 | |
|  * @param {String} query The query string that needs to be parsed.
 | |
|  * @returns {Object}
 | |
|  * @api public
 | |
|  */
 | |
| function querystring(query) {
 | |
|   var parser = /([^=?#&]+)=?([^&]*)/g
 | |
|     , result = {}
 | |
|     , part;
 | |
| 
 | |
|   while (part = parser.exec(query)) {
 | |
|     var key = decode(part[1])
 | |
|       , value = decode(part[2]);
 | |
| 
 | |
|     //
 | |
|     // Prevent overriding of existing properties. This ensures that build-in
 | |
|     // methods like `toString` or __proto__ are not overriden by malicious
 | |
|     // querystrings.
 | |
|     //
 | |
|     // In the case if failed decoding, we want to omit the key/value pairs
 | |
|     // from the result.
 | |
|     //
 | |
|     if (key === null || value === null || key in result) continue;
 | |
|     result[key] = value;
 | |
|   }
 | |
| 
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Transform a query string to an object.
 | |
|  *
 | |
|  * @param {Object} obj Object that should be transformed.
 | |
|  * @param {String} prefix Optional prefix.
 | |
|  * @returns {String}
 | |
|  * @api public
 | |
|  */
 | |
| function querystringify(obj, prefix) {
 | |
|   prefix = prefix || '';
 | |
| 
 | |
|   var pairs = []
 | |
|     , value
 | |
|     , key;
 | |
| 
 | |
|   //
 | |
|   // Optionally prefix with a '?' if needed
 | |
|   //
 | |
|   if ('string' !== typeof prefix) prefix = '?';
 | |
| 
 | |
|   for (key in obj) {
 | |
|     if (has.call(obj, key)) {
 | |
|       value = obj[key];
 | |
| 
 | |
|       //
 | |
|       // Edge cases where we actually want to encode the value to an empty
 | |
|       // string instead of the stringified value.
 | |
|       //
 | |
|       if (!value && (value === null || value === undef || isNaN(value))) {
 | |
|         value = '';
 | |
|       }
 | |
| 
 | |
|       key = encode(key);
 | |
|       value = encode(value);
 | |
| 
 | |
|       //
 | |
|       // If we failed to encode the strings, we should bail out as we don't
 | |
|       // want to add invalid strings to the query.
 | |
|       //
 | |
|       if (key === null || value === null) continue;
 | |
|       pairs.push(key +'='+ value);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return pairs.length ? prefix + pairs.join('&') : '';
 | |
| }
 | |
| 
 | |
| //
 | |
| // Expose the module.
 | |
| //
 | |
| exports.stringify = querystringify;
 | |
| exports.parse = querystring;
 |