added Linux arm64 SDK
This commit is contained in:
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
WI.Cookie = class Cookie
|
||||
{
|
||||
constructor(type, name, value, {header, expires, session, maxAge, path, domain, secure, httpOnly, sameSite} = {})
|
||||
{
|
||||
console.assert(Object.values(WI.Cookie.Type).includes(type));
|
||||
console.assert(typeof name === "string");
|
||||
console.assert(typeof value === "string");
|
||||
console.assert(!header || typeof header === "string");
|
||||
console.assert(!expires || expires instanceof Date);
|
||||
console.assert(!session || typeof session === "boolean");
|
||||
console.assert(!maxAge || typeof maxAge === "number");
|
||||
console.assert(!path || typeof path === "string");
|
||||
console.assert(!domain || typeof domain === "string");
|
||||
console.assert(!secure || typeof secure === "boolean");
|
||||
console.assert(!httpOnly || typeof httpOnly === "boolean");
|
||||
console.assert(!sameSite || Object.values(WI.Cookie.SameSiteType).includes(sameSite));
|
||||
|
||||
this._type = type;
|
||||
this._name = name;
|
||||
this._value = value;
|
||||
this._size = this._name.length + this._value.length;
|
||||
|
||||
if (this._type === WI.Cookie.Type.Response) {
|
||||
this._header = header || "";
|
||||
this._expires = (!session && expires) || null;
|
||||
this._session = session || false;
|
||||
this._maxAge = maxAge || null;
|
||||
this._path = path || null;
|
||||
this._domain = domain || null;
|
||||
this._secure = secure || false;
|
||||
this._httpOnly = httpOnly || false;
|
||||
this._sameSite = sameSite || WI.Cookie.SameSiteType.None;
|
||||
}
|
||||
}
|
||||
|
||||
// Static
|
||||
|
||||
static fromPayload(payload)
|
||||
{
|
||||
let {name, value, ...options} = payload;
|
||||
options.expires = options.expires ? new Date(options.expires.maxDecimals(-3)) : null;
|
||||
|
||||
return new WI.Cookie(WI.Cookie.Type.Response, name, value, options);
|
||||
}
|
||||
|
||||
// RFC 6265 defines the HTTP Cookie and Set-Cookie header fields:
|
||||
// https://www.ietf.org/rfc/rfc6265.txt
|
||||
|
||||
static parseCookieRequestHeader(header)
|
||||
{
|
||||
if (!header)
|
||||
return [];
|
||||
|
||||
header = header.trim();
|
||||
if (!header)
|
||||
return [];
|
||||
|
||||
let cookies = [];
|
||||
|
||||
// Cookie: <name> = <value> ( ";" SP <name> = <value> )*?
|
||||
// NOTE: Just name/value pairs.
|
||||
|
||||
let pairs = header.split(/; /);
|
||||
for (let pair of pairs) {
|
||||
let match = pair.match(/^(?<name>[^\s=]+)[ \t]*=[ \t]*(?<value>.*)$/);
|
||||
if (!match) {
|
||||
WI.reportInternalError("Failed to parse Cookie pair", {header, pair});
|
||||
continue;
|
||||
}
|
||||
|
||||
let {name, value} = match.groups;
|
||||
cookies.push(new WI.Cookie(WI.Cookie.Type.Request, name, value));
|
||||
}
|
||||
|
||||
return cookies;
|
||||
}
|
||||
|
||||
static displayNameForSameSiteType(sameSiteType)
|
||||
{
|
||||
switch (sameSiteType) {
|
||||
case WI.Cookie.SameSiteType.None:
|
||||
return WI.unlocalizedString("None");
|
||||
case WI.Cookie.SameSiteType.Lax:
|
||||
return WI.unlocalizedString("Lax");
|
||||
case WI.Cookie.SameSiteType.Strict:
|
||||
return WI.unlocalizedString("Strict");
|
||||
default:
|
||||
console.error("Invalid SameSite type", sameSiteType);
|
||||
return sameSiteType;
|
||||
}
|
||||
}
|
||||
|
||||
// <https://httpwg.org/http-extensions/rfc6265bis.html#the-samesite-attribute-1>
|
||||
static parseSameSiteAttributeValue(attributeValue)
|
||||
{
|
||||
if (!attributeValue)
|
||||
return WI.Cookie.SameSiteType.None;
|
||||
|
||||
switch (attributeValue.toLowerCase()) {
|
||||
case "lax":
|
||||
return WI.Cookie.SameSiteType.Lax;
|
||||
case "strict":
|
||||
return WI.Cookie.SameSiteType.Strict;
|
||||
}
|
||||
|
||||
return WI.Cookie.SameSiteType.None;
|
||||
}
|
||||
|
||||
static parseSetCookieResponseHeader(header)
|
||||
{
|
||||
if (!header)
|
||||
return null;
|
||||
|
||||
// Set-Cookie: <name> = <value> ( ";" SP <attr-maybe-pair> )*?
|
||||
// NOTE: Some attributes can have pairs (e.g. "Path=/"), some are only a
|
||||
// single word (e.g. "Secure").
|
||||
|
||||
// Parse name/value.
|
||||
let nameValueMatch = header.match(/^(?<name>[^\s=]+)[ \t]*=[ \t]*(?<value>[^;]*)/);
|
||||
if (!nameValueMatch) {
|
||||
WI.reportInternalError("Failed to parse Set-Cookie header", {header});
|
||||
return null;
|
||||
}
|
||||
|
||||
let {name, value} = nameValueMatch.groups;
|
||||
let expires = null;
|
||||
let session = false;
|
||||
let maxAge = null;
|
||||
let path = null;
|
||||
let domain = null;
|
||||
let secure = false;
|
||||
let httpOnly = false;
|
||||
let sameSite = WI.Cookie.SameSiteType.None;
|
||||
|
||||
// Parse Attributes
|
||||
let remaining = header.substr(nameValueMatch[0].length);
|
||||
let attributes = remaining.split(/; ?/);
|
||||
for (let attribute of attributes) {
|
||||
if (!attribute)
|
||||
continue;
|
||||
|
||||
let match = attribute.match(/^(?<name>[^\s=]+)(?:=(?<value>.*))?$/);
|
||||
if (!match) {
|
||||
console.error("Failed to parse Set-Cookie attribute:", attribute);
|
||||
continue;
|
||||
}
|
||||
|
||||
let attributeName = match.groups.name;
|
||||
let attributeValue = match.groups.value;
|
||||
switch (attributeName.toLowerCase()) {
|
||||
case "expires":
|
||||
console.assert(attributeValue);
|
||||
expires = new Date(attributeValue);
|
||||
if (isNaN(expires.getTime())) {
|
||||
console.warn("Invalid Expires date:", attributeValue);
|
||||
expires = null;
|
||||
}
|
||||
break;
|
||||
case "max-age":
|
||||
console.assert(attributeValue);
|
||||
maxAge = parseInt(attributeValue, 10);
|
||||
if (isNaN(maxAge) || !/^\d+$/.test(attributeValue)) {
|
||||
console.warn("Invalid MaxAge value:", attributeValue);
|
||||
maxAge = null;
|
||||
}
|
||||
break;
|
||||
case "path":
|
||||
console.assert(attributeValue);
|
||||
path = attributeValue;
|
||||
break;
|
||||
case "domain":
|
||||
console.assert(attributeValue);
|
||||
domain = attributeValue;
|
||||
break;
|
||||
case "secure":
|
||||
console.assert(!attributeValue);
|
||||
secure = true;
|
||||
break;
|
||||
case "httponly":
|
||||
console.assert(!attributeValue);
|
||||
httpOnly = true;
|
||||
break;
|
||||
case "samesite":
|
||||
sameSite = WI.Cookie.parseSameSiteAttributeValue(attributeValue);
|
||||
break;
|
||||
default:
|
||||
console.warn("Unknown Cookie attribute:", attribute);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!expires)
|
||||
session = true;
|
||||
|
||||
return new WI.Cookie(WI.Cookie.Type.Response, name, value, {header, expires, session, maxAge, path, domain, secure, httpOnly, sameSite});
|
||||
}
|
||||
|
||||
// Public
|
||||
|
||||
get type() { return this._type; }
|
||||
get name() { return this._name; }
|
||||
get value() { return this._value; }
|
||||
get header() { return this._header; }
|
||||
get expires() { return this._expires; }
|
||||
get session() { return this._session; }
|
||||
get maxAge() { return this._maxAge; }
|
||||
get path() { return this._path; }
|
||||
get domain() { return this._domain; }
|
||||
get secure() { return this._secure; }
|
||||
get httpOnly() { return this._httpOnly; }
|
||||
get sameSite() { return this._sameSite; }
|
||||
get size() { return this._size; }
|
||||
|
||||
get url()
|
||||
{
|
||||
let url = this._secure ? "https://" : "http://";
|
||||
url += this._domain || "";
|
||||
url += this._path || "";
|
||||
return url;
|
||||
}
|
||||
|
||||
expirationDate(requestSentDate)
|
||||
{
|
||||
if (this._session)
|
||||
return null;
|
||||
|
||||
if (this._maxAge) {
|
||||
let startDate = requestSentDate || new Date;
|
||||
return new Date(startDate.getTime() + (this._maxAge * 1000));
|
||||
}
|
||||
|
||||
return this._expires;
|
||||
}
|
||||
|
||||
equals(other)
|
||||
{
|
||||
return this._type === other.type
|
||||
&& this._name === other.name
|
||||
&& this._value === other.value
|
||||
&& this._header === other.header
|
||||
&& this._expires?.getTime() === other.expires?.getTime()
|
||||
&& this._session === other.session
|
||||
&& this._maxAge === other.maxAge
|
||||
&& this._path === other.path
|
||||
&& this._domain === other.domain
|
||||
&& this._secure === other.secure
|
||||
&& this._httpOnly === other.httpOnly
|
||||
&& this._sameSite === other.sameSite;
|
||||
}
|
||||
|
||||
toProtocol()
|
||||
{
|
||||
if (typeof this._name !== "string")
|
||||
return null;
|
||||
|
||||
if (typeof this._value !== "string")
|
||||
return null;
|
||||
|
||||
if (typeof this._domain !== "string")
|
||||
return null;
|
||||
|
||||
if (typeof this._path !== "string")
|
||||
return null;
|
||||
|
||||
if (!this._session && !this._expires)
|
||||
return null;
|
||||
|
||||
if (!Object.values(WI.Cookie.SameSiteType).includes(this._sameSite))
|
||||
return null;
|
||||
|
||||
let json = {
|
||||
name: this._name,
|
||||
value: this._value,
|
||||
domain: this._domain,
|
||||
path: this._path,
|
||||
expires: this._expires?.getTime(),
|
||||
session: this._session,
|
||||
httpOnly: !!this._httpOnly,
|
||||
secure: !!this._secure,
|
||||
sameSite: this._sameSite,
|
||||
};
|
||||
|
||||
return json;
|
||||
}
|
||||
};
|
||||
|
||||
WI.Cookie.Type = {
|
||||
Request: "request",
|
||||
Response: "response",
|
||||
};
|
||||
|
||||
// Keep these in sync with the "CookieSameSitePolicy" enum defined by the "Page" domain.
|
||||
WI.Cookie.SameSiteType = {
|
||||
None: "None",
|
||||
Lax: "Lax",
|
||||
Strict: "Strict",
|
||||
};
|
||||
Reference in New Issue
Block a user