|
|
/**
|
|
|
*
|
|
|
*/
|
|
|
define(["dojo/_base/declare", "dojo/_base/lang", "implab/safe"], function (declare, lang, safe) {
|
|
|
|
|
|
|
|
|
var formats = {
|
|
|
"base64+json": {
|
|
|
encode: function (data) {
|
|
|
return new Buffer(JSON.stringify(data)).toString('base64');
|
|
|
},
|
|
|
decode: function (data) {
|
|
|
try {
|
|
|
return JSON.parse(new Buffer(data, 'base64').toString());
|
|
|
} catch (err) {
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
"base64": {
|
|
|
encode: function (data) {
|
|
|
if (!safe.isPrimitive(data))
|
|
|
throw new Error("Can'n serialize a complex data");
|
|
|
return new Buffer(data).toString('base64');
|
|
|
},
|
|
|
decode: function (data) {
|
|
|
return new Buffer(data, 'base64').toString();
|
|
|
},
|
|
|
},
|
|
|
"simple": {
|
|
|
encode: function (data) {
|
|
|
if (!safe.isPrimitive(data))
|
|
|
throw new Error("Can'n serialize a complex data");
|
|
|
return safe.isNull(data) ? "" : data.toString();
|
|
|
},
|
|
|
decode: function (data) {
|
|
|
return data;
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
|
|
|
let args = {
|
|
|
secure: false,
|
|
|
httpOnly: false,
|
|
|
path: null,
|
|
|
domain: null,
|
|
|
maxAge: null,
|
|
|
expires: null,
|
|
|
extension: null,
|
|
|
format: null
|
|
|
};
|
|
|
|
|
|
let Cookie = declare(null, {
|
|
|
secure: false,
|
|
|
httpOnly: false,
|
|
|
path: null,
|
|
|
name: null,
|
|
|
domain: null,
|
|
|
maxAge: null,
|
|
|
expires: null,
|
|
|
extension: null,
|
|
|
value: null,
|
|
|
format: "base64+json",
|
|
|
_createTime: null,
|
|
|
|
|
|
constructor: function (name, value, opts) {
|
|
|
safe.argumentNotEmptyString(name, "name");
|
|
|
|
|
|
if (opts) {
|
|
|
for (let i in opts)
|
|
|
if (i in args)
|
|
|
this[i] = opts[i];
|
|
|
}
|
|
|
|
|
|
this.name = name;
|
|
|
this.value = value;
|
|
|
this._createTime = new Date();
|
|
|
},
|
|
|
|
|
|
isExpired: function () {
|
|
|
let expires;
|
|
|
if (this.maxAge) {
|
|
|
let dt = this.getNormalMaxAge();
|
|
|
expires = new Date(this._createTime.getTime() + dt * 1000);
|
|
|
} else if (this.expires) {
|
|
|
expires = new Date(this.expires);
|
|
|
}
|
|
|
|
|
|
return (expires && new Date() > expires);
|
|
|
},
|
|
|
|
|
|
getNormalMaxAge: function () {
|
|
|
if (safe.isNull(this.maxAge))
|
|
|
return null;
|
|
|
if (safe.isNumber(this.maxAge))
|
|
|
return Math.round(this.maxAge);
|
|
|
|
|
|
let norm = Number(this.maxAge);
|
|
|
|
|
|
if (norm == this.maxAge)
|
|
|
return Math.round(norm);
|
|
|
|
|
|
let parts = this.maxAge.toString().match("^(?:(\\d+)d)?(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$");
|
|
|
if (parts) {
|
|
|
let factor = [0, 86400, 3600, 60, 1];
|
|
|
norm = 0;
|
|
|
for (let i = 1; i < parts.length; i++) {
|
|
|
norm += factor[i] * (Number(parts[i]) || 0);
|
|
|
}
|
|
|
} else {
|
|
|
norm = null;
|
|
|
}
|
|
|
|
|
|
return norm;
|
|
|
},
|
|
|
|
|
|
toString: function () {
|
|
|
let data = [];
|
|
|
|
|
|
let pair = function (name, value, enc) {
|
|
|
if (!safe.isNullOrEmptyString(value))
|
|
|
data.push([name, enc ? enc(value) : value].join('='));
|
|
|
};
|
|
|
|
|
|
let flag = function (name, isSet) {
|
|
|
if (isSet)
|
|
|
data.push(name);
|
|
|
};
|
|
|
|
|
|
pair(this.name, this.value, this.format ? Cookie.formats[this.format].encode : null);
|
|
|
pair("Expires", this.expires, function (d) {
|
|
|
return new Date(d).toUTCString();
|
|
|
});
|
|
|
pair("Max-Age", this.getNormalMaxAge());
|
|
|
pair("Domain", this.domain);
|
|
|
pair("Path", this.path);
|
|
|
flag("Secure", this.secure);
|
|
|
flag("HttpOnly", this.httpOnly);
|
|
|
flag(this.extension, this.extension);
|
|
|
|
|
|
return data.join('; ');
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
/**
|
|
|
* Парсит строку с печеньками из HTTP заголока Cookies
|
|
|
*
|
|
|
* @return возвращает коллекцию печенек в виде { "cookie-name" : {
|
|
|
* value='raw%20data', decode : function(format) {} } }
|
|
|
*
|
|
|
*/
|
|
|
Cookie.parseHeaderValue = function (str) {
|
|
|
safe.argumentNotEmptyString(str, "str");
|
|
|
|
|
|
let pairs = str.split(/;\s*/);
|
|
|
let cookies = {};
|
|
|
|
|
|
for (let i in pairs) {
|
|
|
let pair = pairs[i];
|
|
|
let idx = pair.indexOf('=');
|
|
|
if (idx >= 0) {
|
|
|
cookies[pair.substring(0, idx)] = {
|
|
|
value: pair.substring(idx + 1),
|
|
|
decode: function (format) {
|
|
|
if (!format)
|
|
|
format = "simple";
|
|
|
|
|
|
if (!formats[format])
|
|
|
throw new Error("The specified format '" + format + "' is unsupported");
|
|
|
let decode = formats[format].decode;
|
|
|
|
|
|
return decode(this.value);
|
|
|
}
|
|
|
};
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return cookies;
|
|
|
|
|
|
};
|
|
|
|
|
|
Cookie.formats = formats;
|
|
|
|
|
|
Cookie.parse = function (str, format) {
|
|
|
safe.argumentNotEmptyString(str, "str");
|
|
|
if (!format)
|
|
|
format = "simple";
|
|
|
|
|
|
if (!formats[format])
|
|
|
throw new Error("The specified format '" + format + "' is unsupported");
|
|
|
|
|
|
let pairs = str.split(/;\s*/);
|
|
|
let options = {
|
|
|
format: format
|
|
|
};
|
|
|
|
|
|
let cookieName, cookieValue, first = true;
|
|
|
|
|
|
let map = {
|
|
|
"Expires": "expires",
|
|
|
"Max-Age": "maxAge",
|
|
|
"Domain": "domain",
|
|
|
"Path": "path",
|
|
|
"Secure": "secure",
|
|
|
"HttpOnly": "httpOnly"
|
|
|
};
|
|
|
|
|
|
for (let i in pairs) {
|
|
|
let pair = pairs[i];
|
|
|
let idx = pair.indexOf('=');
|
|
|
|
|
|
if (idx >= 0) {
|
|
|
|
|
|
let name = pair.substring(0, idx);
|
|
|
let value = pair.substring(idx + 1);
|
|
|
|
|
|
if (first) {
|
|
|
cookieName = name;
|
|
|
cookieValue = value;
|
|
|
first = false;
|
|
|
} else {
|
|
|
if (name in map)
|
|
|
options[map[name]] = value;
|
|
|
}
|
|
|
} else {
|
|
|
if (pair in map)
|
|
|
options[map[pair]] = true;
|
|
|
else
|
|
|
options.extension = pair;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return new Cookie(cookieName, cookieValue, options);
|
|
|
};
|
|
|
|
|
|
return Cookie;
|
|
|
});
|