/
home
/
infinitibizsol
/
testingcrm.infinitibizsol.com
/
node_modules
/
@hapi
/
statehood
/
lib
/
File Upload :
llllll
Current File: /home/infinitibizsol/testingcrm.infinitibizsol.com/node_modules/@hapi/statehood/lib/index.js
'use strict'; const Querystring = require('querystring'); const Boom = require('@hapi/boom'); const Bounce = require('@hapi/bounce'); const Bourne = require('@hapi/bourne'); const Cryptiles = require('@hapi/cryptiles'); const Hoek = require('@hapi/hoek'); const Iron = require('@hapi/iron'); const Validate = require('@hapi/validate'); const internals = { macPrefix: 'hapi.signed.cookie.1' }; internals.schema = Validate.object({ strictHeader: Validate.boolean(), ignoreErrors: Validate.boolean(), isSecure: Validate.boolean(), isHttpOnly: Validate.boolean(), isSameSite: Validate.valid('Strict', 'Lax', 'None', false), path: Validate.string().allow(null), domain: Validate.string().allow(null), ttl: Validate.number().allow(null), encoding: Validate.string().valid('base64json', 'base64', 'form', 'iron', 'none'), sign: Validate.object({ password: [Validate.string(), Validate.binary(), Validate.object()], integrity: Validate.object() }), iron: Validate.object(), password: [Validate.string(), Validate.binary(), Validate.object()], contextualize: Validate.function(), // Used by hapi clearInvalid: Validate.boolean(), autoValue: Validate.any(), passThrough: Validate.boolean() }); internals.defaults = { strictHeader: true, // Require an RFC 6265 compliant header format ignoreErrors: false, isSecure: true, isHttpOnly: true, isSameSite: 'Strict', path: null, domain: null, ttl: null, // MSecs, 0 means remove encoding: 'none' // options: 'base64json', 'base64', 'form', 'iron', 'none' }; // Header format internals.validateRx = { nameRx: { strict: /^[^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+$/, loose: /^[^=\s]*$/ }, valueRx: { strict: /^[^\x00-\x20\"\,\;\\\x7F]*$/, loose: /^(?:"([^\"]*)")|(?:[^\;]*)$/ }, domainRx: /^\.?[a-z\d]+(?:(?:[a-z\d]*)|(?:[a-z\d\-]*[a-z\d]))(?:\.[a-z\d]+(?:(?:[a-z\d]*)|(?:[a-z\d\-]*[a-z\d])))*$/, domainLabelLenRx: /^\.?[a-z\d\-]{1,63}(?:\.[a-z\d\-]{1,63})*$/, pathRx: /^\/[^\x00-\x1F\;]*$/ }; // 1: name 2: value internals.pairsRx = /\s*([^=\s]*)\s*=\s*([^\;]*)(?:(?:;\s*)|$)/g; exports.Definitions = class { constructor(options) { this.settings = Hoek.applyToDefaults(internals.defaults, options ?? {}); Validate.assert(this.settings, internals.schema, 'Invalid state definition defaults'); this.cookies = {}; this.names = []; } add(name, options) { Hoek.assert(name && typeof name === 'string', 'Invalid name'); Hoek.assert(!this.cookies[name], 'State already defined:', name); const settings = Hoek.applyToDefaults(this.settings, options ?? {}, { nullOverride: true }); Validate.assert(settings, internals.schema, 'Invalid state definition: ' + name); this.cookies[name] = settings; this.names.push(name); } async parse(cookies) { const state = {}; const names = []; const verify = internals.parsePairs(cookies, (name, value) => { if (name === '__proto__') { throw Boom.badRequest('Invalid cookie header'); } if (state[name]) { if (!Array.isArray(state[name])) { state[name] = [state[name]]; } state[name].push(value); } else { state[name] = value; names.push(name); } }); // Validate cookie header syntax const failed = []; // All errors if (verify !== null) { if (!this.settings.ignoreErrors) { throw Boom.badRequest('Invalid cookie header'); } failed.push({ settings: this.settings, reason: `Header contains unexpected syntax: ${verify}` }); } // Collect errors const errored = []; // Unignored errors const record = (reason, name, value, definition) => { const details = { name, value, settings: definition, reason: typeof reason === 'string' ? reason : reason.message }; failed.push(details); if (!definition.ignoreErrors) { errored.push(details); } }; // Parse cookies const parsed = {}; for (const name of names) { const value = state[name]; const definition = this.cookies[name] ?? this.settings; // Validate cookie if (definition.strictHeader) { const reason = internals.validate(name, state); if (reason) { record(reason, name, value, definition); continue; } } // Check cookie format if (definition.encoding === 'none') { parsed[name] = value; continue; } // Single value if (!Array.isArray(value)) { try { const unsigned = await internals.unsign(name, value, definition); const result = await internals.decode(unsigned, definition); parsed[name] = result; } catch (err) { Bounce.rethrow(err, 'system'); record(err, name, value, definition); } continue; } // Array const arrayResult = []; for (const arrayValue of value) { try { const unsigned = await internals.unsign(name, arrayValue, definition); const result = await internals.decode(unsigned, definition); arrayResult.push(result); } catch (err) { Bounce.rethrow(err, 'system'); record(err, name, value, definition); } } parsed[name] = arrayResult; } if (errored.length) { const error = Boom.badRequest('Invalid cookie value', errored); error.states = parsed; error.failed = failed; throw error; } return { states: parsed, failed }; } async format(cookies, context) { if (!cookies || Array.isArray(cookies) && !cookies.length) { return []; } if (!Array.isArray(cookies)) { cookies = [cookies]; } const header = []; for (let i = 0; i < cookies.length; ++i) { const cookie = cookies[i]; // Apply definition to local configuration const base = this.cookies[cookie.name] ?? this.settings; let definition = cookie.options ? Hoek.applyToDefaults(base, cookie.options, { nullOverride: true }) : base; // Contextualize definition if (definition.contextualize) { if (definition === base) { definition = Hoek.clone(definition); } await definition.contextualize(definition, context); } // Validate name const nameRx = definition.strictHeader ? internals.validateRx.nameRx.strict : internals.validateRx.nameRx.loose; if (!nameRx.test(cookie.name)) { throw Boom.badImplementation('Invalid cookie name: ' + cookie.name); } // Prepare value (encode, sign) const value = await exports.prepareValue(cookie.name, cookie.value, definition); // Validate prepared value const valueRx = definition.strictHeader ? internals.validateRx.valueRx.strict : internals.validateRx.valueRx.loose; if (value && (typeof value !== 'string' || !value.match(valueRx))) { throw Boom.badImplementation('Invalid cookie value: ' + cookie.value); } // Construct cookie let segment = cookie.name + '=' + (value || ''); if (definition.ttl !== null && definition.ttl !== undefined) { // Can be zero const expires = new Date(definition.ttl ? Date.now() + definition.ttl : 0); segment = segment + '; Max-Age=' + Math.floor(definition.ttl / 1000) + '; Expires=' + expires.toUTCString(); } if (definition.isSecure) { segment = segment + '; Secure'; } if (definition.isHttpOnly) { segment = segment + '; HttpOnly'; } if (definition.isSameSite) { segment = `${segment}; SameSite=${definition.isSameSite}`; } if (definition.domain) { const domain = definition.domain.toLowerCase(); if (!domain.match(internals.validateRx.domainLabelLenRx)) { throw Boom.badImplementation('Cookie domain too long: ' + definition.domain); } if (!domain.match(internals.validateRx.domainRx)) { throw Boom.badImplementation('Invalid cookie domain: ' + definition.domain); } segment = segment + '; Domain=' + domain; } if (definition.path) { if (!definition.path.match(internals.validateRx.pathRx)) { throw Boom.badImplementation('Invalid cookie path: ' + definition.path); } segment = segment + '; Path=' + definition.path; } header.push(segment); } return header; } passThrough(header, fallback) { if (!this.names.length) { return header; } const exclude = []; for (let i = 0; i < this.names.length; ++i) { const name = this.names[i]; const definition = this.cookies[name]; const passCookie = definition.passThrough !== undefined ? definition.passThrough : fallback; if (!passCookie) { exclude.push(name); } } return exports.exclude(header, exclude); } }; internals.parsePairs = function (cookies, eachPairFn) { let index = 0; while (index < cookies.length) { const eqIndex = cookies.indexOf('=', index); if (eqIndex === -1) { return cookies.slice(index); // E.g. 'a=1;xyz' -> 'xyz' } const semiIndex = cookies.indexOf(';', eqIndex); const endOfValueIndex = semiIndex !== -1 ? semiIndex : cookies.length; const name = cookies.slice(index, eqIndex).trim(); const value = cookies.slice(eqIndex + 1, endOfValueIndex).trim(); const unquotedValue = (value.startsWith('"') && value.endsWith('"') && value !== '"') ? value.slice(1, -1) : // E.g. '"abc"' -> 'abc' value; eachPairFn(name, unquotedValue); index = endOfValueIndex + 1; } return null; }; internals.validate = function (name, state) { if (!name.match(internals.validateRx.nameRx.strict)) { return 'Invalid cookie name'; } const values = [].concat(state[name]); for (let i = 0; i < values.length; ++i) { if (!values[i].match(internals.validateRx.valueRx.strict)) { return 'Invalid cookie value'; } } return null; }; internals.unsign = async function (name, value, definition) { if (!definition.sign) { return value; } const pos = value.lastIndexOf('.'); if (pos === -1) { throw Boom.badRequest('Missing signature separator'); } const unsigned = value.slice(0, pos); const sig = value.slice(pos + 1); if (!sig) { throw Boom.badRequest('Missing signature'); } const sigParts = sig.split('*'); if (sigParts.length !== 2) { throw Boom.badRequest('Invalid signature format'); } const hmacSalt = sigParts[0]; const hmac = sigParts[1]; const macOptions = Hoek.clone(definition.sign.integrity ?? Iron.defaults.integrity); macOptions.salt = hmacSalt; const mac = await Iron.hmacWithPassword(definition.sign.password, macOptions, [internals.macPrefix, name, unsigned].join('\n')); if (!Cryptiles.fixedTimeComparison(mac.digest, hmac)) { throw Boom.badRequest('Invalid hmac value'); } return unsigned; }; internals.decode = async function (value, definition) { if (!value && definition.encoding === 'form') { return {}; } Hoek.assert(typeof value === 'string', 'Invalid string'); // Encodings: 'base64json', 'base64', 'form', 'iron', 'none' if (definition.encoding === 'iron') { return await Iron.unseal(value, definition.password, definition.iron ?? Iron.defaults); } if (definition.encoding === 'base64json') { const decoded = Buffer.from(value, 'base64').toString('binary'); try { return Bourne.parse(decoded); } catch (err) { throw Boom.badRequest('Invalid JSON payload'); } } if (definition.encoding === 'base64') { return Buffer.from(value, 'base64').toString('binary'); } // encoding: 'form' return Querystring.parse(value); }; exports.prepareValue = async function (name, value, options) { Hoek.assert(options && typeof options === 'object', 'Missing or invalid options'); try { const encoded = await internals.encode(value, options); const signed = await internals.sign(name, encoded, options.sign); return signed; } catch (err) { throw Boom.badImplementation('Failed to encode cookie (' + name + ') value: ' + err.message); } }; internals.encode = function (value, options) { // Encodings: 'base64json', 'base64', 'form', 'iron', 'none' if (value === undefined || options.encoding === 'none') { return value; } if (options.encoding === 'iron') { return Iron.seal(value, options.password, options.iron ?? Iron.defaults); } if (options.encoding === 'base64') { return Buffer.from(value, 'binary').toString('base64'); } if (options.encoding === 'base64json') { const stringified = JSON.stringify(value); return Buffer.from(stringified, 'binary').toString('base64'); } // encoding: 'form' return Querystring.stringify(value); }; internals.sign = async function (name, value, options) { if (value === undefined || !options) { return value; } const mac = await Iron.hmacWithPassword(options.password, options.integrity ?? Iron.defaults.integrity, [internals.macPrefix, name, value].join('\n')); const signed = value + '.' + mac.salt + '*' + mac.digest; return signed; }; exports.exclude = function (cookies, excludes) { let result = ''; const verify = cookies.replace(internals.pairsRx, ($0, $1, $2) => { if (excludes.indexOf($1) === -1) { result = result + (result ? ';' : '') + $1 + '=' + $2; } return ''; }); return verify === '' ? result : Boom.badRequest('Invalid cookie header'); };
Copyright ©2k19 -
Hexid
|
Tex7ure