addon-sdk/source/lib/sdk/querystring.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 'use strict';
michael@0 6
michael@0 7 module.metadata = {
michael@0 8 "stability": "unstable"
michael@0 9 };
michael@0 10
michael@0 11 let unescape = decodeURIComponent;
michael@0 12 exports.unescape = unescape;
michael@0 13
michael@0 14 // encodes a string safely for application/x-www-form-urlencoded
michael@0 15 // adheres to RFC 3986
michael@0 16 // see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURIComponent
michael@0 17 function escape(query) {
michael@0 18 return encodeURIComponent(query).
michael@0 19 replace(/%20/g, '+').
michael@0 20 replace(/!/g, '%21').
michael@0 21 replace(/'/g, '%27').
michael@0 22 replace(/\(/g, '%28').
michael@0 23 replace(/\)/g, '%29').
michael@0 24 replace(/\*/g, '%2A');
michael@0 25 }
michael@0 26 exports.escape = escape;
michael@0 27
michael@0 28 // Converts an object of unordered key-vals to a string that can be passed
michael@0 29 // as part of a request
michael@0 30 function stringify(options, separator, assigner) {
michael@0 31 separator = separator || '&';
michael@0 32 assigner = assigner || '=';
michael@0 33 // Explicitly return null if we have null, and empty string, or empty object.
michael@0 34 if (!options)
michael@0 35 return '';
michael@0 36
michael@0 37 // If content is already a string, just return it as is.
michael@0 38 if (typeof(options) == 'string')
michael@0 39 return options;
michael@0 40
michael@0 41 // At this point we have a k:v object. Iterate over it and encode each value.
michael@0 42 // Arrays and nested objects will get encoded as needed. For example...
michael@0 43 //
michael@0 44 // { foo: [1, 2, { omg: 'bbq', 'all your base!': 'are belong to us' }], bar: 'baz' }
michael@0 45 //
michael@0 46 // will be encoded as
michael@0 47 //
michael@0 48 // foo[0]=1&foo[1]=2&foo[2][omg]=bbq&foo[2][all+your+base!]=are+belong+to+us&bar=baz
michael@0 49 //
michael@0 50 // Keys (including '[' and ']') and values will be encoded with
michael@0 51 // `escape` before returning.
michael@0 52 //
michael@0 53 // Execution was inspired by jQuery, but some details have changed and numeric
michael@0 54 // array keys are included (whereas they are not in jQuery).
michael@0 55
michael@0 56 let encodedContent = [];
michael@0 57 function add(key, val) {
michael@0 58 encodedContent.push(escape(key) + assigner + escape(val));
michael@0 59 }
michael@0 60
michael@0 61 function make(key, value) {
michael@0 62 if (value && typeof(value) === 'object')
michael@0 63 Object.keys(value).forEach(function(name) {
michael@0 64 make(key + '[' + name + ']', value[name]);
michael@0 65 });
michael@0 66 else
michael@0 67 add(key, value);
michael@0 68 }
michael@0 69
michael@0 70 Object.keys(options).forEach(function(name) { make(name, options[name]); });
michael@0 71 return encodedContent.join(separator);
michael@0 72
michael@0 73 //XXXzpao In theory, we can just use a FormData object on 1.9.3, but I had
michael@0 74 // trouble getting that working. It would also be nice to stay
michael@0 75 // backwards-compat as long as possible. Keeping this in for now...
michael@0 76 // let formData = Cc['@mozilla.org/files/formdata;1'].
michael@0 77 // createInstance(Ci.nsIDOMFormData);
michael@0 78 // for ([k, v] in Iterator(content)) {
michael@0 79 // formData.append(k, v);
michael@0 80 // }
michael@0 81 // return formData;
michael@0 82 }
michael@0 83 exports.stringify = stringify;
michael@0 84
michael@0 85 // Exporting aliases that nodejs implements just for the sake of
michael@0 86 // interoperability.
michael@0 87 exports.encode = stringify;
michael@0 88 exports.serialize = stringify;
michael@0 89
michael@0 90 // Note: That `stringify` and `parse` aren't bijective as we use `stringify`
michael@0 91 // as it was implement in request module, but implement `parse` to match nodejs
michael@0 92 // behavior.
michael@0 93 // TODO: Make `stringify` implement API as in nodejs and figure out backwards
michael@0 94 // compatibility.
michael@0 95 function parse(query, separator, assigner) {
michael@0 96 separator = separator || '&';
michael@0 97 assigner = assigner || '=';
michael@0 98 let result = {};
michael@0 99
michael@0 100 if (typeof query !== 'string' || query.length === 0)
michael@0 101 return result;
michael@0 102
michael@0 103 query.split(separator).forEach(function(chunk) {
michael@0 104 let pair = chunk.split(assigner);
michael@0 105 let key = unescape(pair[0]);
michael@0 106 let value = unescape(pair.slice(1).join(assigner));
michael@0 107
michael@0 108 if (!(key in result))
michael@0 109 result[key] = value;
michael@0 110 else if (Array.isArray(result[key]))
michael@0 111 result[key].push(value);
michael@0 112 else
michael@0 113 result[key] = [result[key], value];
michael@0 114 });
michael@0 115
michael@0 116 return result;
michael@0 117 };
michael@0 118 exports.parse = parse;
michael@0 119 // Exporting aliases that nodejs implements just for the sake of
michael@0 120 // interoperability.
michael@0 121 exports.decode = parse;

mercurial