summaryrefslogtreecommitdiff
path: root/deps/npm/node_modules/request/node_modules/tough-cookie/lib/cookie.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/node_modules/request/node_modules/tough-cookie/lib/cookie.js')
-rw-r--r--deps/npm/node_modules/request/node_modules/tough-cookie/lib/cookie.js321
1 files changed, 271 insertions, 50 deletions
diff --git a/deps/npm/node_modules/request/node_modules/tough-cookie/lib/cookie.js b/deps/npm/node_modules/request/node_modules/tough-cookie/lib/cookie.js
index bec7f90b1..4f677c387 100644
--- a/deps/npm/node_modules/request/node_modules/tough-cookie/lib/cookie.js
+++ b/deps/npm/node_modules/request/node_modules/tough-cookie/lib/cookie.js
@@ -35,6 +35,7 @@ var pubsuffix = require('./pubsuffix');
var Store = require('./store').Store;
var MemoryCookieStore = require('./memstore').MemoryCookieStore;
var pathMatch = require('./pathMatch').pathMatch;
+var VERSION = require('../package.json').version;
var punycode;
try {
@@ -84,8 +85,6 @@ var YEAR = /^(\d{2}|\d{4})$/; // 2 to 4 digits
var MAX_TIME = 2147483647000; // 31-bit max
var MIN_TIME = 0; // 31-bit min
-var cookiesCreated = 0; // Number of cookies created in runtime
-
// RFC6265 S5.1.1 date parser:
function parseDate(str) {
@@ -458,47 +457,60 @@ function parse(str) {
}
}
- // ensure a default date for sorting:
- c.creation = new Date();
- //NOTE: add runtime index for the cookieCompare() to resolve the situation when Date's precision is not enough .
- //Store initial UTC time as well, so we will be able to determine if we need to fallback to the Date object.
- c._creationRuntimeIdx = ++cookiesCreated;
- c._initialCreationTime = c.creation.getTime();
return c;
}
+// avoid the V8 deoptimization monster!
+function jsonParse(str) {
+ var obj;
+ try {
+ obj = JSON.parse(str);
+ } catch (e) {
+ return e;
+ }
+ return obj;
+}
+
function fromJSON(str) {
if (!str) {
return null;
}
var obj;
- try {
- obj = JSON.parse(str);
- } catch (e) {
- return null;
+ if (typeof str === 'string') {
+ obj = jsonParse(str);
+ if (obj instanceof Error) {
+ return null;
+ }
+ } else {
+ // assume it's an Object
+ obj = str;
}
var c = new Cookie();
- for (var i=0; i<numCookieProperties; i++) {
- var prop = cookieProperties[i];
- if (obj[prop] == null) {
- continue;
+ for (var i=0; i<Cookie.serializableProperties.length; i++) {
+ var prop = Cookie.serializableProperties[i];
+ if (obj[prop] === undefined ||
+ obj[prop] === Cookie.prototype[prop])
+ {
+ continue; // leave as prototype default
}
+
if (prop === 'expires' ||
prop === 'creation' ||
prop === 'lastAccessed')
{
- c[prop] = obj[prop] == "Infinity" ? "Infinity" : new Date(obj[prop]);
+ if (obj[prop] === null) {
+ c[prop] = null;
+ } else {
+ c[prop] = obj[prop] == "Infinity" ?
+ "Infinity" : new Date(obj[prop]);
+ }
} else {
c[prop] = obj[prop];
}
}
-
- // ensure a default date for sorting:
- c.creation = c.creation || new Date();
-
return c;
}
@@ -512,23 +524,28 @@ function fromJSON(str) {
*/
function cookieCompare(a,b) {
+ var cmp = 0;
+
// descending for length: b CMP a
- var deltaLen = (b.path ? b.path.length : 0) - (a.path ? a.path.length : 0);
- if (deltaLen !== 0) {
- return deltaLen;
+ var aPathLen = a.path ? a.path.length : 0;
+ var bPathLen = b.path ? b.path.length : 0;
+ cmp = bPathLen - aPathLen;
+ if (cmp !== 0) {
+ return cmp;
}
+ // ascending for time: a CMP b
var aTime = a.creation ? a.creation.getTime() : MAX_TIME;
var bTime = b.creation ? b.creation.getTime() : MAX_TIME;
-
- // NOTE: if creation dates are equal and they were not modified from the outside,
- // then use _creationRuntimeIdx for the comparison.
- if(aTime === bTime && aTime === a._initialCreationTime && bTime === b._initialCreationTime) {
- return a._creationRuntimeIdx - b._creationRuntimeIdx;
+ cmp = aTime - bTime;
+ if (cmp !== 0) {
+ return cmp;
}
- // ascending for time: a CMP b
- return aTime - bTime;
+ // break ties for the same millisecond (precision of JavaScript's clock)
+ cmp = a.creationIndex - b.creationIndex;
+
+ return cmp;
}
// Gives the permutation of all possible pathMatch()es of a given path. The
@@ -569,17 +586,31 @@ function getCookieContext(url) {
return urlParse(url);
}
-function Cookie (opts) {
- if (typeof opts !== "object") {
- return;
- }
- Object.keys(opts).forEach(function (key) {
- if (Cookie.prototype.hasOwnProperty(key)) {
- this[key] = opts[key] || Cookie.prototype[key];
+function Cookie(opts) {
+ opts = opts || {};
+
+ Object.keys(opts).forEach(function(prop) {
+ if (Cookie.prototype.hasOwnProperty(prop) &&
+ Cookie.prototype[prop] !== opts[prop] &&
+ prop.substr(0,1) !== '_')
+ {
+ this[prop] = opts[prop];
}
- }.bind(this));
+ }, this);
+
+ this.creation = this.creation || new Date();
+
+ // used to break creation ties in cookieCompare():
+ Object.defineProperty(this, 'creationIndex', {
+ configurable: false,
+ enumerable: false, // important for assert.deepEqual checks
+ writable: true,
+ value: ++Cookie.cookiesCreated
+ });
}
+Cookie.cookiesCreated = 0; // incremented each time a cookie is created
+
Cookie.parse = parse;
Cookie.fromJSON = fromJSON;
@@ -599,17 +630,22 @@ Cookie.prototype.extensions = null;
Cookie.prototype.hostOnly = null; // boolean when set
Cookie.prototype.pathIsDefault = null; // boolean when set
Cookie.prototype.creation = null; // Date when set; defaulted by Cookie.parse
-Cookie.prototype._initialCreationTime = null; // Used to determine if cookie.creation was modified
-Cookie.prototype._creationRuntimeIdx = null; // Runtime index of the created cookie, used in cookieCompare()
Cookie.prototype.lastAccessed = null; // Date when set
+Object.defineProperty(Cookie.prototype, 'creationIndex', {
+ configurable: true,
+ enumerable: false,
+ writable: true,
+ value: 0
+});
-var cookieProperties = Object.freeze(Object.keys(Cookie.prototype).map(function(p) {
- if (p instanceof Function) {
- return;
- }
- return p;
-}));
-var numCookieProperties = cookieProperties.length;
+Cookie.serializableProperties = Object.keys(Cookie.prototype)
+ .filter(function(prop) {
+ return !(
+ Cookie.prototype[prop] instanceof Function ||
+ prop === 'creationIndex' ||
+ prop.substr(0,1) === '_'
+ );
+ });
Cookie.prototype.inspect = function inspect() {
var now = Date.now();
@@ -620,6 +656,46 @@ Cookie.prototype.inspect = function inspect() {
'"';
};
+Cookie.prototype.toJSON = function() {
+ var obj = {};
+
+ var props = Cookie.serializableProperties;
+ for (var i=0; i<props.length; i++) {
+ var prop = props[i];
+ if (this[prop] === Cookie.prototype[prop]) {
+ continue; // leave as prototype default
+ }
+
+ if (prop === 'expires' ||
+ prop === 'creation' ||
+ prop === 'lastAccessed')
+ {
+ if (this[prop] === null) {
+ obj[prop] = null;
+ } else {
+ obj[prop] = this[prop] == "Infinity" ? // intentionally not ===
+ "Infinity" : this[prop].toISOString();
+ }
+ } else if (prop === 'maxAge') {
+ if (this[prop] !== null) {
+ // again, intentionally not ===
+ obj[prop] = (this[prop] == Infinity || this[prop] == -Infinity) ?
+ this[prop].toString() : this[prop];
+ }
+ } else {
+ if (this[prop] !== Cookie.prototype[prop]) {
+ obj[prop] = this[prop];
+ }
+ }
+ }
+
+ return obj;
+};
+
+Cookie.prototype.clone = function() {
+ return fromJSON(this.toJSON());
+};
+
Cookie.prototype.validate = function validate() {
if (!COOKIE_OCTETS.test(this.value)) {
return false;
@@ -744,7 +820,7 @@ Cookie.prototype.TTL = function TTL(now) {
// elsewhere)
Cookie.prototype.expiryTime = function expiryTime(now) {
if (this.maxAge != null) {
- var relativeTo = this.creation || now || new Date();
+ var relativeTo = now || this.creation || new Date();
var age = (this.maxAge <= 0) ? -Infinity : this.maxAge*1000;
return relativeTo.getTime() + age;
}
@@ -782,7 +858,6 @@ Cookie.prototype.canonicalizedDomain = function canonicalizedDomain() {
return canonicalDomain(this.domain);
};
-
function CookieJar(store, rejectPublicSuffixes) {
if (rejectPublicSuffixes != null) {
this.rejectPublicSuffixes = rejectPublicSuffixes;
@@ -895,6 +970,7 @@ CookieJar.prototype.setCookie = function(cookie, url, options, cb) {
return cb(options.ignoreError ? null : err);
}
cookie.creation = oldCookie.creation; // step 11.3
+ cookie.creationIndex = oldCookie.creationIndex; // preserve tie-breaker
cookie.lastAccessed = now;
// Step 11.4 (delete cookie) is implied by just setting the new one:
store.updateCookie(oldCookie, cookie, next); // step 12
@@ -1041,6 +1117,151 @@ CookieJar.prototype.getSetCookieStrings = function(/*..., cb*/) {
this.getCookies.apply(this,args);
};
+CAN_BE_SYNC.push('serialize');
+CookieJar.prototype.serialize = function(cb) {
+ var type = this.store.constructor.name;
+ if (type === 'Object') {
+ type = null;
+ }
+
+ // update README.md "Serialization Format" if you change this, please!
+ var serialized = {
+ // The version of tough-cookie that serialized this jar. Generally a good
+ // practice since future versions can make data import decisions based on
+ // known past behavior. When/if this matters, use `semver`.
+ version: 'tough-cookie@'+VERSION,
+
+ // add the store type, to make humans happy:
+ storeType: type,
+
+ // CookieJar configuration:
+ rejectPublicSuffixes: !!this.rejectPublicSuffixes,
+
+ // this gets filled from getAllCookies:
+ cookies: []
+ };
+
+ if (!(this.store.getAllCookies &&
+ typeof this.store.getAllCookies === 'function'))
+ {
+ return cb(new Error('store does not support getAllCookies and cannot be serialized'));
+ }
+
+ this.store.getAllCookies(function(err,cookies) {
+ if (err) {
+ return cb(err);
+ }
+
+ serialized.cookies = cookies.map(function(cookie) {
+ // convert to serialized 'raw' cookies
+ cookie = (cookie instanceof Cookie) ? cookie.toJSON() : cookie;
+
+ // Remove the index so new ones get assigned during deserialization
+ delete cookie.creationIndex;
+
+ return cookie;
+ });
+
+ return cb(null, serialized);
+ });
+};
+
+// well-known name that JSON.stringify calls
+CookieJar.prototype.toJSON = function() {
+ return this.serializeSync();
+};
+
+// use the class method CookieJar.deserialize instead of calling this directly
+CAN_BE_SYNC.push('_importCookies');
+CookieJar.prototype._importCookies = function(serialized, cb) {
+ var jar = this;
+ var cookies = serialized.cookies;
+ if (!cookies || !Array.isArray(cookies)) {
+ return cb(new Error('serialized jar has no cookies array'));
+ }
+
+ function putNext(err) {
+ if (err) {
+ return cb(err);
+ }
+
+ if (!cookies.length) {
+ return cb(err, jar);
+ }
+
+ var cookie;
+ try {
+ cookie = fromJSON(cookies.shift());
+ } catch (e) {
+ return cb(e);
+ }
+
+ if (cookie === null) {
+ return putNext(null); // skip this cookie
+ }
+
+ jar.store.putCookie(cookie, putNext);
+ }
+
+ putNext();
+};
+
+CookieJar.deserialize = function(strOrObj, store, cb) {
+ if (arguments.length !== 3) {
+ // store is optional
+ cb = store;
+ store = null;
+ }
+
+ var serialized;
+ if (typeof strOrObj === 'string') {
+ serialized = jsonParse(strOrObj);
+ if (serialized instanceof Error) {
+ return cb(serialized);
+ }
+ } else {
+ serialized = strOrObj;
+ }
+
+ var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+ jar._importCookies(serialized, function(err) {
+ if (err) {
+ return cb(err);
+ }
+ cb(null, jar);
+ });
+};
+
+CookieJar.fromJSON = CookieJar.deserializeSync;
+CookieJar.deserializeSync = function(strOrObj, store) {
+ var serialized = typeof strOrObj === 'string' ?
+ JSON.parse(strOrObj) : strOrObj;
+ var jar = new CookieJar(store, serialized.rejectPublicSuffixes);
+
+ // catch this mistake early:
+ if (!jar.store.synchronous) {
+ throw new Error('CookieJar store is not synchronous; use async API instead.');
+ }
+
+ jar._importCookiesSync(serialized);
+ return jar;
+};
+
+CAN_BE_SYNC.push('clone');
+CookieJar.prototype.clone = function(newStore, cb) {
+ if (arguments.length === 1) {
+ cb = newStore;
+ newStore = null;
+ }
+
+ this.serialize(function(err,serialized) {
+ if (err) {
+ return cb(err);
+ }
+ CookieJar.deserialize(newStore, serialized, cb);
+ });
+};
+
// Use a closure to provide a true imperative API for synchronous stores.
function syncWrap(method) {
return function() {