From 75c8ce36266b6e2ea91317b126a364a9193635fb Mon Sep 17 00:00:00 2001 From: Yarmo Mackenbach Date: Fri, 5 Mar 2021 17:13:08 +0100 Subject: [PATCH] Release 0.11.0 --- CHANGELOG.md | 2 + dist/doip.js | 781 +++++++++++++++++++++++++++++++++++++++++-- dist/doip.min.js | 2 +- docs/_coverpage.md | 2 +- docs/changelog.md | 10 + docs/installation.md | 2 +- package.json | 2 +- 7 files changed, 766 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 832ba3f..6032919 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [0.11.0] - 2021-03-05 ## Added - IRC service provider - Matrix service provider diff --git a/dist/doip.js b/dist/doip.js index cee399f..82f88fc 100644 --- a/dist/doip.js +++ b/dist/doip.js @@ -133,6 +133,121 @@ module.exports = mkrequest => (...args) => { },{}],4:[function(require,module,exports){ 'use strict'; +var token = '%[a-f0-9]{2}'; +var singleMatcher = new RegExp(token, 'gi'); +var multiMatcher = new RegExp('(' + token + ')+', 'gi'); + +function decodeComponents(components, split) { + try { + // Try to decode the entire string first + return decodeURIComponent(components.join('')); + } catch (err) { + // Do nothing + } + + if (components.length === 1) { + return components; + } + + split = split || 1; + + // Split the array in 2 parts + var left = components.slice(0, split); + var right = components.slice(split); + + return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right)); +} + +function decode(input) { + try { + return decodeURIComponent(input); + } catch (err) { + var tokens = input.match(singleMatcher); + + for (var i = 1; i < tokens.length; i++) { + input = decodeComponents(tokens, i).join(''); + + tokens = input.match(singleMatcher); + } + + return input; + } +} + +function customDecodeURIComponent(input) { + // Keep track of all the replacements and prefill the map with the `BOM` + var replaceMap = { + '%FE%FF': '\uFFFD\uFFFD', + '%FF%FE': '\uFFFD\uFFFD' + }; + + var match = multiMatcher.exec(input); + while (match) { + try { + // Decode as big chunks as possible + replaceMap[match[0]] = decodeURIComponent(match[0]); + } catch (err) { + var result = decode(match[0]); + + if (result !== match[0]) { + replaceMap[match[0]] = result; + } + } + + match = multiMatcher.exec(input); + } + + // Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else + replaceMap['%C2'] = '\uFFFD'; + + var entries = Object.keys(replaceMap); + + for (var i = 0; i < entries.length; i++) { + // Replace all decoded components + var key = entries[i]; + input = input.replace(new RegExp(key, 'g'), replaceMap[key]); + } + + return input; +} + +module.exports = function (encodedURI) { + if (typeof encodedURI !== 'string') { + throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`'); + } + + try { + encodedURI = encodedURI.replace(/\+/g, ' '); + + // Try the built in decoder first + return decodeURIComponent(encodedURI); + } catch (err) { + // Fallback to a more advanced decoder + return customDecodeURIComponent(encodedURI); + } +}; + +},{}],5:[function(require,module,exports){ +'use strict'; +module.exports = function (obj, predicate) { + var ret = {}; + var keys = Object.keys(obj); + var isArr = Array.isArray(predicate); + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var val = obj[key]; + + if (isArr ? predicate.indexOf(key) !== -1 : predicate(key, val, obj)) { + ret[key] = val; + } + } + + return ret; +}; + +},{}],6:[function(require,module,exports){ +'use strict'; module.exports = value => { if (Object.prototype.toString.call(value) !== '[object Object]') { @@ -143,7 +258,7 @@ module.exports = value => { return prototype === null || prototype === Object.prototype; }; -},{}],5:[function(require,module,exports){ +},{}],7:[function(require,module,exports){ 'use strict'; const isOptionObject = require('is-plain-obj'); @@ -316,7 +431,7 @@ module.exports = function (...options) { return merged._; }; -},{"is-plain-obj":4}],6:[function(require,module,exports){ +},{"is-plain-obj":6}],8:[function(require,module,exports){ (function (process){(function (){ // 'path' module extracted from Node.js v8.11.1 (only the posix part) // transplited with Babel @@ -849,7 +964,7 @@ posix.posix = posix; module.exports = posix; }).call(this)}).call(this,require('_process')) -},{"_process":7}],7:[function(require,module,exports){ +},{"_process":9}],9:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -1035,7 +1150,441 @@ process.chdir = function (dir) { }; process.umask = function() { return 0; }; -},{}],8:[function(require,module,exports){ +},{}],10:[function(require,module,exports){ +'use strict'; +const strictUriEncode = require('strict-uri-encode'); +const decodeComponent = require('decode-uri-component'); +const splitOnFirst = require('split-on-first'); +const filterObject = require('filter-obj'); + +const isNullOrUndefined = value => value === null || value === undefined; + +function encoderForArrayFormat(options) { + switch (options.arrayFormat) { + case 'index': + return key => (result, value) => { + const index = result.length; + + if ( + value === undefined || + (options.skipNull && value === null) || + (options.skipEmptyString && value === '') + ) { + return result; + } + + if (value === null) { + return [...result, [encode(key, options), '[', index, ']'].join('')]; + } + + return [ + ...result, + [encode(key, options), '[', encode(index, options), ']=', encode(value, options)].join('') + ]; + }; + + case 'bracket': + return key => (result, value) => { + if ( + value === undefined || + (options.skipNull && value === null) || + (options.skipEmptyString && value === '') + ) { + return result; + } + + if (value === null) { + return [...result, [encode(key, options), '[]'].join('')]; + } + + return [...result, [encode(key, options), '[]=', encode(value, options)].join('')]; + }; + + case 'comma': + case 'separator': + return key => (result, value) => { + if (value === null || value === undefined || value.length === 0) { + return result; + } + + if (result.length === 0) { + return [[encode(key, options), '=', encode(value, options)].join('')]; + } + + return [[result, encode(value, options)].join(options.arrayFormatSeparator)]; + }; + + default: + return key => (result, value) => { + if ( + value === undefined || + (options.skipNull && value === null) || + (options.skipEmptyString && value === '') + ) { + return result; + } + + if (value === null) { + return [...result, encode(key, options)]; + } + + return [...result, [encode(key, options), '=', encode(value, options)].join('')]; + }; + } +} + +function parserForArrayFormat(options) { + let result; + + switch (options.arrayFormat) { + case 'index': + return (key, value, accumulator) => { + result = /\[(\d*)\]$/.exec(key); + + key = key.replace(/\[\d*\]$/, ''); + + if (!result) { + accumulator[key] = value; + return; + } + + if (accumulator[key] === undefined) { + accumulator[key] = {}; + } + + accumulator[key][result[1]] = value; + }; + + case 'bracket': + return (key, value, accumulator) => { + result = /(\[\])$/.exec(key); + key = key.replace(/\[\]$/, ''); + + if (!result) { + accumulator[key] = value; + return; + } + + if (accumulator[key] === undefined) { + accumulator[key] = [value]; + return; + } + + accumulator[key] = [].concat(accumulator[key], value); + }; + + case 'comma': + case 'separator': + return (key, value, accumulator) => { + const isArray = typeof value === 'string' && value.includes(options.arrayFormatSeparator); + const isEncodedArray = (typeof value === 'string' && !isArray && decode(value, options).includes(options.arrayFormatSeparator)); + value = isEncodedArray ? decode(value, options) : value; + const newValue = isArray || isEncodedArray ? value.split(options.arrayFormatSeparator).map(item => decode(item, options)) : value === null ? value : decode(value, options); + accumulator[key] = newValue; + }; + + default: + return (key, value, accumulator) => { + if (accumulator[key] === undefined) { + accumulator[key] = value; + return; + } + + accumulator[key] = [].concat(accumulator[key], value); + }; + } +} + +function validateArrayFormatSeparator(value) { + if (typeof value !== 'string' || value.length !== 1) { + throw new TypeError('arrayFormatSeparator must be single character string'); + } +} + +function encode(value, options) { + if (options.encode) { + return options.strict ? strictUriEncode(value) : encodeURIComponent(value); + } + + return value; +} + +function decode(value, options) { + if (options.decode) { + return decodeComponent(value); + } + + return value; +} + +function keysSorter(input) { + if (Array.isArray(input)) { + return input.sort(); + } + + if (typeof input === 'object') { + return keysSorter(Object.keys(input)) + .sort((a, b) => Number(a) - Number(b)) + .map(key => input[key]); + } + + return input; +} + +function removeHash(input) { + const hashStart = input.indexOf('#'); + if (hashStart !== -1) { + input = input.slice(0, hashStart); + } + + return input; +} + +function getHash(url) { + let hash = ''; + const hashStart = url.indexOf('#'); + if (hashStart !== -1) { + hash = url.slice(hashStart); + } + + return hash; +} + +function extract(input) { + input = removeHash(input); + const queryStart = input.indexOf('?'); + if (queryStart === -1) { + return ''; + } + + return input.slice(queryStart + 1); +} + +function parseValue(value, options) { + if (options.parseNumbers && !Number.isNaN(Number(value)) && (typeof value === 'string' && value.trim() !== '')) { + value = Number(value); + } else if (options.parseBooleans && value !== null && (value.toLowerCase() === 'true' || value.toLowerCase() === 'false')) { + value = value.toLowerCase() === 'true'; + } + + return value; +} + +function parse(query, options) { + options = Object.assign({ + decode: true, + sort: true, + arrayFormat: 'none', + arrayFormatSeparator: ',', + parseNumbers: false, + parseBooleans: false + }, options); + + validateArrayFormatSeparator(options.arrayFormatSeparator); + + const formatter = parserForArrayFormat(options); + + // Create an object with no prototype + const ret = Object.create(null); + + if (typeof query !== 'string') { + return ret; + } + + query = query.trim().replace(/^[?#&]/, ''); + + if (!query) { + return ret; + } + + for (const param of query.split('&')) { + if (param === '') { + continue; + } + + let [key, value] = splitOnFirst(options.decode ? param.replace(/\+/g, ' ') : param, '='); + + // Missing `=` should be `null`: + // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters + value = value === undefined ? null : ['comma', 'separator'].includes(options.arrayFormat) ? value : decode(value, options); + formatter(decode(key, options), value, ret); + } + + for (const key of Object.keys(ret)) { + const value = ret[key]; + if (typeof value === 'object' && value !== null) { + for (const k of Object.keys(value)) { + value[k] = parseValue(value[k], options); + } + } else { + ret[key] = parseValue(value, options); + } + } + + if (options.sort === false) { + return ret; + } + + return (options.sort === true ? Object.keys(ret).sort() : Object.keys(ret).sort(options.sort)).reduce((result, key) => { + const value = ret[key]; + if (Boolean(value) && typeof value === 'object' && !Array.isArray(value)) { + // Sort object keys, not values + result[key] = keysSorter(value); + } else { + result[key] = value; + } + + return result; + }, Object.create(null)); +} + +exports.extract = extract; +exports.parse = parse; + +exports.stringify = (object, options) => { + if (!object) { + return ''; + } + + options = Object.assign({ + encode: true, + strict: true, + arrayFormat: 'none', + arrayFormatSeparator: ',' + }, options); + + validateArrayFormatSeparator(options.arrayFormatSeparator); + + const shouldFilter = key => ( + (options.skipNull && isNullOrUndefined(object[key])) || + (options.skipEmptyString && object[key] === '') + ); + + const formatter = encoderForArrayFormat(options); + + const objectCopy = {}; + + for (const key of Object.keys(object)) { + if (!shouldFilter(key)) { + objectCopy[key] = object[key]; + } + } + + const keys = Object.keys(objectCopy); + + if (options.sort !== false) { + keys.sort(options.sort); + } + + return keys.map(key => { + const value = object[key]; + + if (value === undefined) { + return ''; + } + + if (value === null) { + return encode(key, options); + } + + if (Array.isArray(value)) { + return value + .reduce(formatter(key), []) + .join('&'); + } + + return encode(key, options) + '=' + encode(value, options); + }).filter(x => x.length > 0).join('&'); +}; + +exports.parseUrl = (url, options) => { + options = Object.assign({ + decode: true + }, options); + + const [url_, hash] = splitOnFirst(url, '#'); + + return Object.assign( + { + url: url_.split('?')[0] || '', + query: parse(extract(url), options) + }, + options && options.parseFragmentIdentifier && hash ? {fragmentIdentifier: decode(hash, options)} : {} + ); +}; + +exports.stringifyUrl = (object, options) => { + options = Object.assign({ + encode: true, + strict: true + }, options); + + const url = removeHash(object.url).split('?')[0] || ''; + const queryFromUrl = exports.extract(object.url); + const parsedQueryFromUrl = exports.parse(queryFromUrl, {sort: false}); + + const query = Object.assign(parsedQueryFromUrl, object.query); + let queryString = exports.stringify(query, options); + if (queryString) { + queryString = `?${queryString}`; + } + + let hash = getHash(object.url); + if (object.fragmentIdentifier) { + hash = `#${encode(object.fragmentIdentifier, options)}`; + } + + return `${url}${queryString}${hash}`; +}; + +exports.pick = (input, filter, options) => { + options = Object.assign({ + parseFragmentIdentifier: true + }, options); + + const {url, query, fragmentIdentifier} = exports.parseUrl(input, options); + return exports.stringifyUrl({ + url, + query: filterObject(query, filter), + fragmentIdentifier + }, options); +}; + +exports.exclude = (input, filter, options) => { + const exclusionFilter = Array.isArray(filter) ? key => !filter.includes(key) : (key, value) => !filter(key, value); + + return exports.pick(input, exclusionFilter, options); +}; + +},{"decode-uri-component":4,"filter-obj":5,"split-on-first":11,"strict-uri-encode":12}],11:[function(require,module,exports){ +'use strict'; + +module.exports = (string, separator) => { + if (!(typeof string === 'string' && typeof separator === 'string')) { + throw new TypeError('Expected the arguments to be of type `string`'); + } + + if (separator === '') { + return [string]; + } + + const separatorIndex = string.indexOf(separator); + + if (separatorIndex === -1) { + return [string]; + } + + return [ + string.slice(0, separatorIndex), + string.slice(separatorIndex + separator.length) + ]; +}; + +},{}],12:[function(require,module,exports){ +'use strict'; +module.exports = str => encodeURIComponent(str).replace(/[!'()*]/g, x => `%${x.charCodeAt(0).toString(16).toUpperCase()}`); + +},{}],13:[function(require,module,exports){ (function(module) { 'use strict'; @@ -1190,10 +1739,10 @@ process.umask = function() { return 0; }; })(module); -},{}],9:[function(require,module,exports){ +},{}],14:[function(require,module,exports){ module.exports={ "name": "doipjs", - "version": "0.10.5", + "version": "0.11.0", "description": "Decentralized OpenPGP Identity Proofs library in Node.js", "main": "src/index.js", "dependencies": { @@ -1202,6 +1751,7 @@ module.exports={ "merge-options": "^3.0.3", "openpgp": "^4.10.9", "prettier": "^2.1.2", + "query-string": "^6.14.1", "valid-url": "^1.0.9" }, "devDependencies": { @@ -1249,7 +1799,7 @@ module.exports={ } } -},{}],10:[function(require,module,exports){ +},{}],15:[function(require,module,exports){ (function (global){(function (){ /* Copyright 2021 Yarmo Mackenbach @@ -1579,7 +2129,7 @@ const verify = async (input, fingerprint, opts) => { setTimeout(() => { resolve(objResult) return - }, 3000) + }, 10000) }) return await Promise.race([promiseClaim, promiseTimeout]) @@ -1588,7 +2138,7 @@ const verify = async (input, fingerprint, opts) => { exports.verify = verify }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./keys":12,"./serviceproviders":13,"./utils":30,"merge-options":5,"path":6,"valid-url":8}],11:[function(require,module,exports){ +},{"./keys":17,"./serviceproviders":18,"./utils":37,"merge-options":7,"path":8,"valid-url":13}],16:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -1616,7 +2166,7 @@ exports.signatures = signatures exports.serviceproviders = serviceproviders exports.utils = utils -},{"./claims":10,"./keys":12,"./serviceproviders":13,"./signatures":29,"./utils":30}],12:[function(require,module,exports){ +},{"./claims":15,"./keys":17,"./serviceproviders":18,"./signatures":36,"./utils":37}],17:[function(require,module,exports){ (function (global){(function (){ /* Copyright 2021 Yarmo Mackenbach @@ -1857,7 +2407,7 @@ exports.getUserData = getUserData exports.getFingerprint = getFingerprint }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"bent":1,"merge-options":5,"path":6,"valid-url":8}],13:[function(require,module,exports){ +},{"bent":1,"merge-options":7,"path":8,"valid-url":13}],18:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -1879,7 +2429,9 @@ const utils = require('./utils') const list = [ 'dns', + 'irc', 'xmpp', + 'matrix', 'twitter', 'reddit', 'liberapay', @@ -1897,7 +2449,9 @@ const list = [ const data = { dns: require('./serviceproviders/dns'), + irc: require('./serviceproviders/irc'), xmpp: require('./serviceproviders/xmpp'), + matrix: require('./serviceproviders/matrix'), twitter: require('./serviceproviders/twitter'), reddit: require('./serviceproviders/reddit'), liberapay: require('./serviceproviders/liberapay'), @@ -1930,6 +2484,10 @@ const match = (uri, opts) => { const directRequestHandler = (spData, opts) => { return new Promise(async (resolve, reject) => { const url = spData.proof.fetch ? spData.proof.fetch : spData.proof.uri + if (!url) { + reject('No valid URI provided') + return + } let res switch (spData.proof.format) { @@ -1991,7 +2549,7 @@ exports.match = match exports.directRequestHandler = directRequestHandler exports.proxyRequestHandler = proxyRequestHandler -},{"../package.json":9,"./serviceproviders/devto":14,"./serviceproviders/discourse":15,"./serviceproviders/dns":16,"./serviceproviders/fediverse":17,"./serviceproviders/gitea":18,"./serviceproviders/github":19,"./serviceproviders/gitlab":20,"./serviceproviders/hackernews":21,"./serviceproviders/liberapay":22,"./serviceproviders/lobsters":23,"./serviceproviders/mastodon":24,"./serviceproviders/owncast":25,"./serviceproviders/reddit":26,"./serviceproviders/twitter":27,"./serviceproviders/xmpp":28,"./utils":30,"bent":1}],14:[function(require,module,exports){ +},{"../package.json":14,"./serviceproviders/devto":19,"./serviceproviders/discourse":20,"./serviceproviders/dns":21,"./serviceproviders/fediverse":22,"./serviceproviders/gitea":23,"./serviceproviders/github":24,"./serviceproviders/gitlab":25,"./serviceproviders/hackernews":26,"./serviceproviders/irc":27,"./serviceproviders/liberapay":28,"./serviceproviders/lobsters":29,"./serviceproviders/mastodon":30,"./serviceproviders/matrix":31,"./serviceproviders/owncast":32,"./serviceproviders/reddit":33,"./serviceproviders/twitter":34,"./serviceproviders/xmpp":35,"./utils":37,"bent":1}],19:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2060,7 +2618,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],15:[function(require,module,exports){ +},{}],20:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2129,7 +2687,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],16:[function(require,module,exports){ +},{}],21:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2227,7 +2785,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{"../utils":30,"bent":1,"dns":3}],17:[function(require,module,exports){ +},{"../utils":37,"bent":1,"dns":3}],22:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2296,7 +2854,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],18:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2365,7 +2923,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],19:[function(require,module,exports){ +},{}],24:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2434,7 +2992,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],20:[function(require,module,exports){ +},{}],25:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2546,7 +3104,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{"bent":1}],21:[function(require,module,exports){ +},{"bent":1}],26:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2615,7 +3173,77 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],22:[function(require,module,exports){ +},{}],27:[function(require,module,exports){ +/* +Copyright 2021 Yarmo Mackenbach + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const utils = require('../utils') +const reURI = /^irc\:\/\/(.*)\/([a-zA-Z0-9]*)/ + +const processURI = (uri, opts) => { + if (!opts) { + opts = {} + } + const match = uri.match(reURI) + + return { + serviceprovider: { + type: 'communication', + name: 'irc', + }, + profile: { + display: `irc://${match[1]}/${match[2]}`, + uri: uri, + qr: null, + }, + proof: { + uri: utils.generateProxyURL('irc', [match[1], match[2]], opts), + fetch: null, + useProxy: false, + format: 'json', + }, + claim: { + fingerprint: null, + format: 'uri', + path: ['data'], + relation: 'contains', + }, + customRequestHandler: null, + } +} + +const tests = [ + { + uri: 'irc://chat.ircserver.org/Alice1', + shouldMatch: true, + }, + { + uri: 'irc://chat.ircserver.org/alice?param=123', + shouldMatch: true, + }, + { + uri: 'https://chat.ircserver.org/alice', + shouldMatch: false, + }, +] + +exports.reURI = reURI +exports.processURI = processURI +exports.tests = tests + +},{"../utils":37}],28:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2684,7 +3312,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],23:[function(require,module,exports){ +},{}],29:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2753,7 +3381,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],24:[function(require,module,exports){ +},{}],30:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2822,7 +3450,91 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],25:[function(require,module,exports){ +},{}],31:[function(require,module,exports){ +/* +Copyright 2021 Yarmo Mackenbach + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const bent = require('bent') +const req = bent('GET') +const queryString = require('query-string') +const utils = require('../utils') +const reURI = /^matrix\:u\/(\@[^:]*\:[^?]*)(\?.*)?/ + +const processURI = (uri, opts) => { + if (!opts) { + opts = {} + } + const match = uri.match(reURI) + let proofUrl = null + if (match[2]) { + const params = queryString.parse(match[2]) + if ('org.keyoxide.e' in params && 'org.keyoxide.r' in params) { + proofUrl = utils.generateProxyURL('matrix', [params['org.keyoxide.r'], params['org.keyoxide.e']], opts) + } + } + + return { + serviceprovider: { + type: 'communication', + name: 'matrix', + }, + profile: { + display: match[1], + uri: uri, + qr: null, + }, + proof: { + uri: proofUrl, + fetch: null, + useProxy: false, + format: 'json', + }, + claim: { + fingerprint: null, + format: 'message', + path: ['data', 'content', 'body'], + relation: 'contains', + }, + customRequestHandler: null, + } +} + +const tests = [ + { + uri: 'matrix:u/@alice:matrix.domain.org', + shouldMatch: true, + }, + { + uri: 'matrix:u/@alice:matrix.domain.org?org.keyoxide.r=!123:domain.org&org.keyoxide.e=$123', + shouldMatch: true, + }, + { + uri: 'xmpp:alice@domain.org', + shouldMatch: false, + }, + { + uri: 'https://domain.org/@alice', + shouldMatch: false, + }, +] + +exports.reURI = reURI +exports.processURI = processURI +exports.tests = tests + +},{"../utils":37,"bent":1,"query-string":10}],32:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2898,7 +3610,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{"bent":1}],26:[function(require,module,exports){ +},{"bent":1}],33:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -2975,7 +3687,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{}],27:[function(require,module,exports){ +},{}],34:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -3087,7 +3799,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{"../serviceproviders":13,"../utils":30,"bent":1}],28:[function(require,module,exports){ +},{"../serviceproviders":18,"../utils":37,"bent":1}],35:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -3157,7 +3869,7 @@ exports.reURI = reURI exports.processURI = processURI exports.tests = tests -},{"../utils":30}],29:[function(require,module,exports){ +},{"../utils":37}],36:[function(require,module,exports){ (function (global){(function (){ /* Copyright 2021 Yarmo Mackenbach @@ -3284,7 +3996,7 @@ const verify = (signature, opts) => { exports.verify = verify }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./claims":10,"./keys":12,"merge-options":5}],30:[function(require,module,exports){ +},{"./claims":15,"./keys":17,"merge-options":7}],37:[function(require,module,exports){ /* Copyright 2021 Yarmo Mackenbach @@ -3300,7 +4012,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -const generateProxyURL = (type, url, opts) => { +const generateProxyURL = (type, urlElements, opts) => { if (!opts || !opts.doipProxyHostname) { return null } @@ -3308,9 +4020,16 @@ const generateProxyURL = (type, url, opts) => { if (type == 'xmpp') { addParam += '/DESC' } + + if (!Array.isArray(urlElements)) { + urlElements = [urlElements] + } + + urlElements.map((x) => { encodeURIComponent(x) }) + return `https://${ opts.doipProxyHostname - }/api/1/get/${type}/${encodeURIComponent(url)}${addParam}` + }/api/1/get/${type}/${urlElements.join('/')}${addParam}` } const generateClaim = (fingerprint, format) => { @@ -3332,5 +4051,5 @@ const generateClaim = (fingerprint, format) => { exports.generateProxyURL = generateProxyURL exports.generateClaim = generateClaim -},{}]},{},[11])(11) +},{}]},{},[16])(16) }); diff --git a/dist/doip.min.js b/dist/doip.min.js index 5289732..ba9ffc9 100644 --- a/dist/doip.min.js +++ b/dist/doip.min.js @@ -1 +1 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).doip=e()}}((function(){return function e(t,r,i){function o(n,a){if(!r[n]){if(!t[n]){var c="function"==typeof require&&require;if(!a&&c)return c(n,!0);if(s)return s(n,!0);var l=new Error("Cannot find module '"+n+"'");throw l.code="MODULE_NOT_FOUND",l}var u=r[n]={exports:{}};t[n][0].call(u.exports,(function(e){return o(t[n][1][e]||e)}),u,u.exports,e,t,r,i)}return r[n].exports}for(var s="function"==typeof require&&require,n=0;n(r||(r=this.arrayBuffer()),r)}),this.headers={};for(const[t,r]of e.headers.entries())this.headers[t.toLowerCase()]=r}}t.exports=i(((e,t,r,i,s)=>async(n,a,c={})=>{n=s+(n||"");let l=new URL(n);if(i||(i={}),l.username&&(i.Authorization="Basic "+btoa(l.username+":"+l.password),l=new URL(l.protocol+"//"+l.host+l.pathname+l.search)),"https:"!==l.protocol&&"http:"!==l.protocol)throw new Error("Unknown protocol, "+l.protocol);if(a)if(a instanceof ArrayBuffer||ArrayBuffer.isView(a)||"string"==typeof a);else{if("object"!=typeof a)throw new Error("Unknown body type.");a=JSON.stringify(a),i["Content-Type"]="application/json"}c=new Headers({...i||{},...c});const u=await fetch(l,{method:t,headers:c,body:a});if(u.statusCode=u.status,!e.has(u.status))throw new o(u);return"json"===r?u.json():"buffer"===r?u.arrayBuffer():"string"===r?u.text():u}))},{"./core":2}],2:[function(e,t,r){"use strict";const i=new Set(["json","buffer","string"]);t.exports=e=>(...t)=>{const r=new Set;let o,s,n,a="";return t.forEach((e=>{if("string"==typeof e)if(e.toUpperCase()===e){if(o){throw new Error(`Can't set method to ${e}, already set to ${o}.`)}o=e}else if(e.startsWith("http:")||e.startsWith("https:"))a=e;else{if(!i.has(e))throw new Error("Unknown encoding, "+e);s=e}else if("number"==typeof e)r.add(e);else{if("object"!=typeof e)throw new Error("Unknown type: "+typeof e);if(Array.isArray(e)||e instanceof Set)e.forEach((e=>r.add(e)));else{if(n)throw new Error("Cannot set headers twice.");n=e}}})),o||(o="GET"),0===r.size&&r.add(200),e(r,o,s,n,a)}},{}],3:[function(e,t,r){},{}],4:[function(e,t,r){"use strict";t.exports=e=>{if("[object Object]"!==Object.prototype.toString.call(e))return!1;const t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}},{}],5:[function(e,t,r){"use strict";const i=e("is-plain-obj"),{hasOwnProperty:o}=Object.prototype,{propertyIsEnumerable:s}=Object,n=(e,t,r)=>Object.defineProperty(e,t,{value:r,writable:!0,enumerable:!0,configurable:!0}),a=this,c={concatArrays:!1,ignoreUndefined:!1},l=e=>{const t=[];for(const r in e)o.call(e,r)&&t.push(r);if(Object.getOwnPropertySymbols){const r=Object.getOwnPropertySymbols(e);for(const i of r)s.call(e,i)&&t.push(i)}return t};function u(e){return Array.isArray(e)?function(e){const t=e.slice(0,0);return l(e).forEach((r=>{n(t,r,u(e[r]))})),t}(e):i(e)?function(e){const t=null===Object.getPrototypeOf(e)?Object.create(null):{};return l(e).forEach((r=>{n(t,r,u(e[r]))})),t}(e):e}const p=(e,t,r,i)=>(r.forEach((r=>{void 0===t[r]&&i.ignoreUndefined||(r in e&&e[r]!==Object.getPrototypeOf(e)?n(e,r,d(e[r],t[r],i)):n(e,r,u(t[r])))})),e);function d(e,t,r){return r.concatArrays&&Array.isArray(e)&&Array.isArray(t)?((e,t,r)=>{let i=e.slice(0,0),s=0;return[e,t].forEach((t=>{const a=[];for(let r=0;r!a.includes(e))),r)})),i})(e,t,r):i(t)&&i(e)?p(e,t,l(t),r):u(t)}t.exports=function(...e){const t=d(u(c),this!==a&&this||{},c);let r={_:{}};for(const o of e)if(void 0!==o){if(!i(o))throw new TypeError("`"+o+"` is not an Option Object");r=d(r,{_:o},t)}return r._}},{"is-plain-obj":4}],6:[function(e,t,r){(function(e){(function(){"use strict";function r(e){if("string"!=typeof e)throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}function i(e,t){for(var r,i="",o=0,s=-1,n=0,a=0;a<=e.length;++a){if(a2){var c=i.lastIndexOf("/");if(c!==i.length-1){-1===c?(i="",o=0):o=(i=i.slice(0,c)).length-1-i.lastIndexOf("/"),s=a,n=0;continue}}else if(2===i.length||1===i.length){i="",o=0,s=a,n=0;continue}t&&(i.length>0?i+="/..":i="..",o=2)}else i.length>0?i+="/"+e.slice(s+1,a):i=e.slice(s+1,a),o=a-s-1;s=a,n=0}else 46===r&&-1!==n?++n:n=-1}return i}var o={resolve:function(){for(var t,o="",s=!1,n=arguments.length-1;n>=-1&&!s;n--){var a;n>=0?a=arguments[n]:(void 0===t&&(t=e.cwd()),a=t),r(a),0!==a.length&&(o=a+"/"+o,s=47===a.charCodeAt(0))}return o=i(o,!s),s?o.length>0?"/"+o:"/":o.length>0?o:"."},normalize:function(e){if(r(e),0===e.length)return".";var t=47===e.charCodeAt(0),o=47===e.charCodeAt(e.length-1);return 0!==(e=i(e,!t)).length||t||(e="."),e.length>0&&o&&(e+="/"),t?"/"+e:e},isAbsolute:function(e){return r(e),e.length>0&&47===e.charCodeAt(0)},join:function(){if(0===arguments.length)return".";for(var e,t=0;t0&&(void 0===e?e=i:e+="/"+i)}return void 0===e?".":o.normalize(e)},relative:function(e,t){if(r(e),r(t),e===t)return"";if((e=o.resolve(e))===(t=o.resolve(t)))return"";for(var i=1;il){if(47===t.charCodeAt(a+p))return t.slice(a+p+1);if(0===p)return t.slice(a+p)}else n>l&&(47===e.charCodeAt(i+p)?u=p:0===p&&(u=0));break}var d=e.charCodeAt(i+p);if(d!==t.charCodeAt(a+p))break;47===d&&(u=p)}var h="";for(p=i+u+1;p<=s;++p)p!==s&&47!==e.charCodeAt(p)||(0===h.length?h+="..":h+="/..");return h.length>0?h+t.slice(a+u):(a+=u,47===t.charCodeAt(a)&&++a,t.slice(a))},_makeLong:function(e){return e},dirname:function(e){if(r(e),0===e.length)return".";for(var t=e.charCodeAt(0),i=47===t,o=-1,s=!0,n=e.length-1;n>=1;--n)if(47===(t=e.charCodeAt(n))){if(!s){o=n;break}}else s=!1;return-1===o?i?"/":".":i&&1===o?"//":e.slice(0,o)},basename:function(e,t){if(void 0!==t&&"string"!=typeof t)throw new TypeError('"ext" argument must be a string');r(e);var i,o=0,s=-1,n=!0;if(void 0!==t&&t.length>0&&t.length<=e.length){if(t.length===e.length&&t===e)return"";var a=t.length-1,c=-1;for(i=e.length-1;i>=0;--i){var l=e.charCodeAt(i);if(47===l){if(!n){o=i+1;break}}else-1===c&&(n=!1,c=i+1),a>=0&&(l===t.charCodeAt(a)?-1==--a&&(s=i):(a=-1,s=c))}return o===s?s=c:-1===s&&(s=e.length),e.slice(o,s)}for(i=e.length-1;i>=0;--i)if(47===e.charCodeAt(i)){if(!n){o=i+1;break}}else-1===s&&(n=!1,s=i+1);return-1===s?"":e.slice(o,s)},extname:function(e){r(e);for(var t=-1,i=0,o=-1,s=!0,n=0,a=e.length-1;a>=0;--a){var c=e.charCodeAt(a);if(47!==c)-1===o&&(s=!1,o=a+1),46===c?-1===t?t=a:1!==n&&(n=1):-1!==t&&(n=-1);else if(!s){i=a+1;break}}return-1===t||-1===o||0===n||1===n&&t===o-1&&t===i+1?"":e.slice(t,o)},format:function(e){if(null===e||"object"!=typeof e)throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof e);return function(e,t){var r=t.dir||t.root,i=t.base||(t.name||"")+(t.ext||"");return r?r===t.root?r+i:r+e+i:i}("/",e)},parse:function(e){r(e);var t={root:"",dir:"",base:"",ext:"",name:""};if(0===e.length)return t;var i,o=e.charCodeAt(0),s=47===o;s?(t.root="/",i=1):i=0;for(var n=-1,a=0,c=-1,l=!0,u=e.length-1,p=0;u>=i;--u)if(47!==(o=e.charCodeAt(u)))-1===c&&(l=!1,c=u+1),46===o?-1===n?n=u:1!==p&&(p=1):-1!==n&&(p=-1);else if(!l){a=u+1;break}return-1===n||-1===c||0===p||1===p&&n===c-1&&n===a+1?-1!==c&&(t.base=t.name=0===a&&s?e.slice(1,c):e.slice(a,c)):(0===a&&s?(t.name=e.slice(1,n),t.base=e.slice(1,c)):(t.name=e.slice(a,n),t.base=e.slice(a,c)),t.ext=e.slice(n,c)),a>0?t.dir=e.slice(0,a-1):s&&(t.dir="/"),t},sep:"/",delimiter:":",win32:null,posix:null};o.posix=o,t.exports=o}).call(this)}).call(this,e("_process"))},{_process:7}],7:[function(e,t,r){var i,o,s=t.exports={};function n(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function c(e){if(i===setTimeout)return setTimeout(e,0);if((i===n||!i)&&setTimeout)return i=setTimeout,setTimeout(e,0);try{return i(e,0)}catch(t){try{return i.call(null,e,0)}catch(t){return i.call(this,e,0)}}}!function(){try{i="function"==typeof setTimeout?setTimeout:n}catch(e){i=n}try{o="function"==typeof clearTimeout?clearTimeout:a}catch(e){o=a}}();var l,u=[],p=!1,d=-1;function h(){p&&l&&(p=!1,l.length?u=l.concat(u):d=-1,u.length&&f())}function f(){if(!p){var e=c(h);p=!0;for(var t=u.length;t;){for(l=u,u=[];++d1)for(var r=1;r=0){if(i&&i.length){if(0!==o.length&&!/^\//.test(o))return}else if(/^\/\//.test(o))return;if(/^[a-z][a-z0-9\+\-\.]*$/.test(a.toLowerCase()))return c+=a+":",i&&i.length&&(c+="//"+i),c+=o,s&&s.length&&(c+="?"+s),n&&n.length&&(c+="#"+n),c}}}function i(e,i){if(r(e)){var o,s,n,a,c="",l="",u="",p="";if(c=(o=t(e))[1],l=o[2],s=o[3],n=o[4],a=o[5],c){if(i){if("https"!=c.toLowerCase())return}else if("http"!=c.toLowerCase())return;if(l)return/:(\d+)$/.test(l)&&(u=l.match(/:(\d+)$/)[0],l=l.replace(/:\d+$/,"")),p+=c+":",p+="//"+l,u&&(p+=u),p+=s,n&&n.length&&(p+="?"+n),a&&a.length&&(p+="#"+a),p}}}function o(e){return i(e,!0)}function s(e){return i(e)||o(e)}}(t)},{}],9:[function(e,t,r){t.exports={name:"doipjs",version:"0.10.5",description:"Decentralized OpenPGP Identity Proofs library in Node.js",main:"src/index.js",dependencies:{bent:"^7.3.12",browserify:"^17.0.0","merge-options":"^3.0.3",openpgp:"^4.10.9",prettier:"^2.1.2","valid-url":"^1.0.9"},devDependencies:{"browserify-shim":"^3.8.14",chai:"^4.2.0","chai-as-promised":"^7.1.1","chai-match-pattern":"^1.2.0","license-check-and-add":"^3.0.4",minify:"^6.0.1",mocha:"^8.2.0"},scripts:{"release:bundle":"./node_modules/browserify/bin/cmd.js ./src/index.js --standalone doip -x openpgp -o ./dist/doip.js","release:minify":"./node_modules/minify/bin/minify.js ./dist/doip.js > ./dist/doip.min.js","prettier:check":"./node_modules/prettier/bin-prettier.js --check .","prettier:write":"./node_modules/prettier/bin-prettier.js --write .","license:check":"./node_modules/license-check-and-add/dist/src/cli.js check","license:add":"./node_modules/license-check-and-add/dist/src/cli.js add","license:remove":"./node_modules/license-check-and-add/dist/src/cli.js remove",docs:"docsify serve ./docs",test:"./node_modules/mocha/bin/mocha"},repository:{type:"git",url:"https://codeberg.org/keyoxide/doipjs"},homepage:"https://js.doip.rocks",keywords:["pgp","gpg","openpgp","encryption","decentralized","identity"],author:"Yarmo Mackenbach (https://yarmo.eu)",license:"Apache-2.0",browserify:{transform:["browserify-shim"]},"browserify-shim":{openpgp:"global:openpgp"}}},{}],10:[function(e,t,r){(function(t){(function(){e("path");const i=e("merge-options"),o=e("valid-url"),s="undefined"!=typeof window?window.openpgp:void 0!==t?t.openpgp:null,n=e("./serviceproviders"),a=e("./keys"),c=e("./utils");Promise.allSettled=Promise.allSettled||(e=>Promise.all(e.map((e=>e.then((e=>({status:"fulfilled",value:e}))).catch((e=>({status:"rejected",reason:e})))))));const l=(e,t,r,i,o)=>{let s;if(e.isVerified||!t)return e;if(Array.isArray(t))return t.forEach(((t,s)=>{e=l(e,t,r,i,o)})),e;if(0==r.length){switch(o){default:case"contains":s=new RegExp(i,"gi"),e.isVerified=s.test(t.replace(/\r?\n|\r|\\/g,""));break;case"equals":e.isVerified=t.replace(/\r?\n|\r|\\/g,"").toLowerCase()==i.toLowerCase();break;case"oneOf":s=new RegExp(i,"gi"),e.isVerified=s.test(t.join("|"))}return e}try{r[0]}catch(t){return e.errors.push("err_data_structure_incorrect"),e}return e=l(e,t[r[0]],r.slice(1),i,o)},u=(e,t)=>{let r={isVerified:!1,errors:[]};switch(t.proof.format){case"json":r=l(r,e,t.claim.path,c.generateClaim(t.claim.fingerprint,t.claim.format),t.claim.relation);break;case"text":re=new RegExp(c.generateClaim(t.claim.fingerprint,t.claim.format),"gi"),r.isVerified=re.test(e.replace(/\r?\n|\r/,""))}return r},p=async(e,t,r)=>{if(e instanceof s.key.Key){const t=await a.getFingerprint(e),i=(await a.getUserData(e)).map((async(e,i)=>new Promise((async(i,o)=>{try{i(await p(e.notations,t,r))}catch(e){o(e)}}))));return Promise.allSettled(i).then((e=>e.map(((e,t)=>"fulfilled"==e.status?e.value:e.reason))))}if(e instanceof Array){const i=e.map((async(e,i)=>new Promise((async(i,o)=>{try{i(await p(e,t,r))}catch(e){o(e)}}))));return Promise.allSettled(i).then((e=>e.map(((e,t)=>"fulfilled"==e.status?e.value:e.reason))))}const c=new Promise((async(s,a)=>{let c={isVerified:!1,errors:[],serviceproviderData:void 0};const l=e.replace(/^\s+|\s+$/g,"");t||(t=null);if(r=i({returnMatchesOnly:!1,proxyPolicy:"adaptive",doipProxyHostname:"proxy.keyoxide.org",twitterBearerToken:null,nitterInstance:null},r||{}),!o.isUri(l))return c.errors.push("invalid_uri"),void a(c);const p=n.match(l,r);if("returnMatchesOnly"in r&&r.returnMatchesOnly)return void s(p);let d,h,f,m,y=!1,g=0;for(;!y&&g{const t={isVerified:!1,errors:["verification_timed_out"],serviceproviderData:void 0};setTimeout((()=>{e(t)}),3e3)}));return await Promise.race([c,l])};r.verify=p}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./keys":12,"./serviceproviders":13,"./utils":30,"merge-options":5,path:6,"valid-url":8}],11:[function(e,t,r){const i=e("./claims"),o=e("./keys"),s=e("./signatures"),n=e("./serviceproviders"),a=e("./utils");r.claims=i,r.keys=o,r.signatures=s,r.serviceproviders=n,r.utils=a},{"./claims":10,"./keys":12,"./serviceproviders":13,"./signatures":29,"./utils":30}],12:[function(e,t,r){(function(t){(function(){e("path");const i=e("bent")("GET"),o=e("valid-url"),s="undefined"!=typeof window?window.openpgp:void 0!==t?t.openpgp:null,n=(e("merge-options"),(e,t)=>new Promise((async(r,i)=>{t=t?"https://"+t:"https://keys.openpgp.org";const o=new s.HKP(t),n={query:e};let a=await o.lookup(n).catch((e=>{i("Key does not exist or could not be fetched")}));a=await s.key.readArmored(a).then((e=>e.keys[0])).catch((e=>null)),a?r(a):i("Key does not exist or could not be fetched")}))),a=e=>new Promise((async(t,r)=>{const i=new s.WKD,o={email:e},n=await i.lookup(o).then((e=>e.keys[0])).catch((e=>null));n?t(n):r("Key does not exist or could not be fetched")})),c=(e,t)=>new Promise((async(e,t)=>{try{await i(opts.keyLink).then((e=>{if(200===e.status)return e})).then((e=>e.text()))}catch(e){t("Error fetching Keybase key: "+e.message)}const r=await s.key.readArmored(rawKeyContent).then((e=>e.keys[0])).catch((e=>null));r?e(r):t("Key does not exist or could not be fetched")})),l=e=>new Promise((async(t,r)=>{e||r("Invalid public key");const i=await e.primaryKey.getFingerprint(),o=await e.getPrimaryUser(),n=e.users;let a=[];n.forEach(((e,t)=>{if(a[t]={userData:{id:e.userId?e.userId.userid:null,name:e.userId?e.userId.name:null,email:e.userId?e.userId.email:null,comment:e.userId?e.userId.comment:null,isPrimary:o.index===t}},"selfCertifications"in e&&e.selfCertifications.length>0){const r=e.selfCertifications[0].rawNotations;a[t].notations=r.map((({name:e,value:t,humanReadable:r})=>{if(r&&"proof@metacode.biz"===e)return s.util.decode_utf8(t)}))}else a[t].notations=[]})),t({fingerprint:i,users:a,primaryUserIndex:o.index})}));r.fetch={uri:e=>new Promise((async(t,r)=>{o.isUri(e)||r("Invalid URI");const i=e.match(/([a-zA-Z0-9]*):([a-zA-Z0-9@._=+\-]*)(?:\:([a-zA-Z0-9@._=+\-]*))?/);switch(i[1]||r("Invalid URI"),i[1]){case"hkp":t(n(i[3]?i[3]:i[2],i[3]?i[2]:null));break;case"wkd":t(a(i[2]));break;case"kb":t(c(i[2],i.length>=4&&i[3]));break;default:r("Invalid URI protocol")}})),hkp:n,wkd:a,keybase:c,plaintext:e=>new Promise((async(t,r)=>{t((await s.key.readArmored(e)).keys[0])})),signature:(e,t)=>new Promise((async(r,i)=>{let o=await s.signature.readArmored(e);if("compressed"in o.packets[0]){o=o.packets[0];await s.stream.readToEnd(await o.packets[1].getText())}const a=o.packets[0].signersUserId,c=await o.packets[0].issuerKeyId.toHex();r(n(a||c,t))}))},r.process=l,r.getUserData=e=>new Promise((async(t,r)=>{t((await l(e)).users)})),r.getFingerprint=e=>new Promise((async(t,r)=>{t((await l(e)).fingerprint)}))}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{bent:1,"merge-options":5,path:6,"valid-url":8}],13:[function(e,t,r){const i=e("bent")("GET"),o=e("./utils"),s=["dns","xmpp","twitter","reddit","liberapay","hackernews","lobsters","devto","gitea","gitlab","github","mastodon","fediverse","discourse","owncast"],n={dns:e("./serviceproviders/dns"),xmpp:e("./serviceproviders/xmpp"),twitter:e("./serviceproviders/twitter"),reddit:e("./serviceproviders/reddit"),liberapay:e("./serviceproviders/liberapay"),hackernews:e("./serviceproviders/hackernews"),lobsters:e("./serviceproviders/lobsters"),devto:e("./serviceproviders/devto"),gitea:e("./serviceproviders/gitea"),gitlab:e("./serviceproviders/gitlab"),github:e("./serviceproviders/github"),mastodon:e("./serviceproviders/mastodon"),fediverse:e("./serviceproviders/fediverse"),discourse:e("./serviceproviders/discourse"),owncast:e("./serviceproviders/owncast")};r.list=s,r.data=n,r.match=(e,t)=>{let r,i=[];return s.forEach(((o,s)=>{r=n[o],r.reURI.test(e)&&i.push(r.processURI(e,t))})),i},r.directRequestHandler=(t,r)=>new Promise((async(r,o)=>{const s=t.proof.fetch?t.proof.fetch:t.proof.uri;switch(t.proof.format){case"json":i(s,null,{Accept:"application/json","User-Agent":"doipjs/"+e("../package.json").version}).then((async e=>await e.json())).then((e=>{r(e)})).catch((e=>{o(e)}));break;case"text":i(s).then((async e=>await e.text())).then((e=>{r(e)})).catch((e=>{o(e)}));break;default:o("No specified proof data format")}})),r.proxyRequestHandler=(e,t)=>new Promise((async(r,s)=>{const n=e.proof.fetch?e.proof.fetch:e.proof.uri;i(o.generateProxyURL(e.proof.format,n,t),null,{Accept:"application/json"}).then((async e=>await e.json())).then((e=>{r(e.content)})).catch((e=>{s(e)}))}))},{"../package.json":9,"./serviceproviders/devto":14,"./serviceproviders/discourse":15,"./serviceproviders/dns":16,"./serviceproviders/fediverse":17,"./serviceproviders/gitea":18,"./serviceproviders/github":19,"./serviceproviders/gitlab":20,"./serviceproviders/hackernews":21,"./serviceproviders/liberapay":22,"./serviceproviders/lobsters":23,"./serviceproviders/mastodon":24,"./serviceproviders/owncast":25,"./serviceproviders/reddit":26,"./serviceproviders/twitter":27,"./serviceproviders/xmpp":28,"./utils":30,bent:1}],14:[function(e,t,r){const i=/^https:\/\/dev\.to\/(.*)\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"devto"},profile:{display:r[1],uri:"https://dev.to/"+r[1],qr:null},proof:{uri:e,fetch:`https://dev.to/api/articles/${r[1]}/${r[2]}`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["body_markdown"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://dev.to/alice/post",shouldMatch:!0},{uri:"https://dev.to/alice/post/",shouldMatch:!0},{uri:"https://domain.org/alice/post",shouldMatch:!1}]},{}],15:[function(e,t,r){const i=/^https:\/\/(.*)\/u\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"discourse"},profile:{display:`${r[2]}@${r[1]}`,uri:e,qr:null},proof:{uri:e,fetch:`https://${r[1]}/u/${r[2]}.json`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["user","bio_raw"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/u/alice",shouldMatch:!0},{uri:"https://domain.org/u/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],16:[function(e,t,r){const i=e("dns"),o=e("bent")("GET"),s=e("../utils"),n=/^dns:([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/,a=async(e,t)=>{if("resolveTxt"in i){const t=async()=>new Promise(((t,r)=>{i.resolveTxt(e.profile.display,((e,i)=>{e&&r(e),t(i)}))}));return{hostname:e.profile.display,records:{txt:await t()}}}{const t=await o(e.proof.uri,null,{Accept:"application/json"});return await t.json()}};r.reURI=n,r.processURI=(e,t)=>{t||(t={});const r=e.match(n);return{serviceprovider:{type:"web",name:"dns"},profile:{display:r[1],uri:"https://"+r[1],qr:null},proof:{uri:s.generateProxyURL("dns",r[1],t),fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"uri",path:["records","txt"],relation:"contains"},customRequestHandler:a}},r.tests=[{uri:"dns:domain.org",shouldMatch:!0},{uri:"dns:domain.org?type=TXT",shouldMatch:!0},{uri:"https://domain.org",shouldMatch:!1}]},{"../utils":30,bent:1,dns:3}],17:[function(e,t,r){const i=/^https:\/\/(.*)\/users\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"fediverse"},profile:{display:`@${r[2]}@${r[1]}`,uri:e,qr:null},proof:{uri:e,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"fingerprint",path:["summary"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/users/alice",shouldMatch:!0},{uri:"https://domain.org/users/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],18:[function(e,t,r){const i=/^https:\/\/(.*)\/(.*)\/gitea_proof\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"gitea"},profile:{display:`${r[2]}@${r[1]}`,uri:`https://${r[1]}/${r[2]}`,qr:null},proof:{uri:e,fetch:`https://${r[1]}/api/v1/repos/${r[2]}/gitea_proof`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["description"],relation:"equals"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/alice/gitea_proof",shouldMatch:!0},{uri:"https://domain.org/alice/gitea_proof/",shouldMatch:!0},{uri:"https://domain.org/alice/other_proof",shouldMatch:!1}]},{}],19:[function(e,t,r){const i=/^https:\/\/gist\.github\.com\/(.*)\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"github"},profile:{display:r[1],uri:"https://github.com/"+r[1],qr:null},proof:{uri:e,fetch:"https://api.github.com/gists/"+r[2],useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["files","openpgp.md","content"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://gist.github.com/Alice/123456789",shouldMatch:!0},{uri:"https://gist.github.com/Alice/123456789/",shouldMatch:!0},{uri:"https://domain.org/Alice/123456789",shouldMatch:!1}]},{}],20:[function(e,t,r){const i=e("bent")("GET"),o=/^https:\/\/(.*)\/(.*)\/gitlab_proof\/?/,s=async(e,t)=>{const r=e.proof.uri.match(o),s=`https://${r[1]}/api/v4/users?username=${r[2]}`;let n;try{n=await i(s,null,{Accept:"application/json"})}catch(e){n=await i(utils.generateProxyURL("web",s,t),null,{Accept:"application/json"})}const a=(await n.json()).find((e=>e.username===r[2]));if(!a)throw new Error("No user with username "+r[2]);const c=`https://${r[1]}/api/v4/users/${a.id}/projects`;let l;try{l=await i(c,null,{Accept:"application/json"})}catch(e){l=await i(utils.generateProxyURL("web",c,t),null,{Accept:"application/json"})}const u=(await l.json()).find((e=>"gitlab_proof"===e.path));if(!u)throw new Error("No project at "+e.proof.uri);return u};r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"gitlab"},profile:{display:`${r[2]}@${r[1]}`,uri:`https://${r[1]}/${r[2]}`,qr:null},proof:{uri:e,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["description"],relation:"equals"},customRequestHandler:s}},r.tests=[{uri:"https://gitlab.domain.org/alice/gitlab_proof",shouldMatch:!0},{uri:"https://gitlab.domain.org/alice/gitlab_proof/",shouldMatch:!0},{uri:"https://domain.org/alice/other_proof",shouldMatch:!1}]},{bent:1}],21:[function(e,t,r){const i=/^https:\/\/news\.ycombinator\.com\/user\?id=(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"hackernews"},profile:{display:r[1],uri:e,qr:null},proof:{uri:`https://hacker-news.firebaseio.com/v0/user/${r[1]}.json`,fetch:null,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"uri",path:["about"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://news.ycombinator.com/user?id=Alice",shouldMatch:!0},{uri:"https://news.ycombinator.com/user?id=Alice/",shouldMatch:!0},{uri:"https://domain.org/user?id=Alice",shouldMatch:!1}]},{}],22:[function(e,t,r){const i=/^https:\/\/liberapay\.com\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"liberapay"},profile:{display:r[1],uri:e,qr:null},proof:{uri:e,fetch:`https://liberapay.com/${r[1]}/public.json`,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["statements","content"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://liberapay.com/alice",shouldMatch:!0},{uri:"https://liberapay.com/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],23:[function(e,t,r){const i=/^https:\/\/lobste\.rs\/u\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"lobsters"},profile:{display:r[1],uri:e,qr:null},proof:{uri:`https://lobste.rs/u/${r[1]}.json`,fetch:null,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["about"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://lobste.rs/u/Alice",shouldMatch:!0},{uri:"https://lobste.rs/u/Alice/",shouldMatch:!0},{uri:"https://domain.org/u/Alice",shouldMatch:!1}]},{}],24:[function(e,t,r){const i=/^https:\/\/(.*)\/@(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"mastodon"},profile:{display:`@${r[2]}@${r[1]}`,uri:e,qr:null},proof:{uri:e,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"fingerprint",path:["attachment","value"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/@alice",shouldMatch:!0},{uri:"https://domain.org/@alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],25:[function(e,t,r){e("bent")("GET");const i=/^https:\/\/(.*)/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});return{serviceprovider:{type:"web",name:"owncast"},profile:{display:e.match(i)[1],uri:e,qr:null},proof:{uri:e+"/api/config",fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"fingerprint",path:["socialHandles","url"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://live.domain.org",shouldMatch:!0},{uri:"https://live.domain.org/",shouldMatch:!0},{uri:"https://domain.org/live",shouldMatch:!0},{uri:"https://domain.org/live/",shouldMatch:!0}]},{bent:1}],26:[function(e,t,r){const i=/^https:\/\/(?:www\.)?reddit\.com\/user\/(.*)\/comments\/(.*)\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"reddit"},profile:{display:r[1],uri:"https://www.reddit.com/user/"+r[1],qr:null},proof:{uri:e,fetch:`https://www.reddit.com/user/${r[1]}/comments/${r[2]}.json`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["data","children","data","selftext"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://www.reddit.com/user/Alice/comments/123456/post",shouldMatch:!0},{uri:"https://www.reddit.com/user/Alice/comments/123456/post/",shouldMatch:!0},{uri:"https://reddit.com/user/Alice/comments/123456/post",shouldMatch:!0},{uri:"https://reddit.com/user/Alice/comments/123456/post/",shouldMatch:!0},{uri:"https://domain.org/user/Alice/comments/123456/post",shouldMatch:!1}]},{}],27:[function(e,t,r){const i=e("bent")("GET"),o=e("../serviceproviders"),s=e("../utils"),n=/^https:\/\/twitter\.com\/(.*)\/status\/([0-9]*)(?:\?.*)?/,a=async(e,t)=>{const r=e.proof.uri.match(n);if("always"!==t.proxyPolicy){if("twitterBearerToken"in t&&t.twitterBearerToken){const e=await i("https://api.twitter.com/1.1/statuses/show.json?id="+r[2],null,{Accept:"application/json",Authorization:"Bearer "+t.twitterBearerToken});return(await e.json()).text}if("nitterInstance"in t&&t.nitterInstance){e.proof.fetch=`https://${t.nitterInstance}/${r[1]}/status/${r[2]}`;return await o.proxyRequestHandler(e,t)}}return"never"!==t.proxyPolicy&&e.proof.fetch?i(s.generateProxyURL("twitter",r[2],t),null,{Accept:"application/json"}).then((async e=>await e.json())).then((e=>e.data.text)).catch((e=>{reject(e)})):null};r.reURI=n,r.processURI=(e,t)=>{t||(t={});const r=e.match(n);return{serviceprovider:{type:"web",name:"twitter"},profile:{display:"@"+r[1],uri:"https://twitter.com/"+r[1],qr:null},proof:{uri:e,fetch:s.generateProxyURL("twitter",r[2],t),useProxy:!1,format:"text"},claim:{fingerprint:null,format:"message",path:[],relation:"contains"},customRequestHandler:a}},r.tests=[{uri:"https://twitter.com/alice/status/1234567890123456789",shouldMatch:!0},{uri:"https://twitter.com/alice/status/1234567890123456789/",shouldMatch:!0},{uri:"https://domain.org/alice/status/1234567890123456789",shouldMatch:!1}]},{"../serviceproviders":13,"../utils":30,bent:1}],28:[function(e,t,r){const i=e("../utils"),o=/^xmpp:([a-zA-Z0-9\.\-\_]*)@([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"communication",name:"xmpp"},profile:{display:`${r[1]}@${r[2]}`,uri:e,qr:e},proof:{uri:i.generateProxyURL("xmpp",`${r[1]}@${r[2]}`,t),fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:[],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"xmpp:alice@domain.org",shouldMatch:!0},{uri:"xmpp:alice@domain.org?omemo-sid-123456789=A1B2C3D4E5F6G7H8I9",shouldMatch:!0},{uri:"https://domain.org",shouldMatch:!1}]},{"../utils":30}],29:[function(e,t,r){(function(t){(function(){const i="undefined"!=typeof window?window.openpgp:void 0!==t?t.openpgp:null,o=(e("merge-options"),e("./claims")),s=e("./keys");r.verify=(e,t)=>new Promise((async(r,n)=>{let a,c=[];try{a=await i.cleartext.readArmored(e)}catch(e){return c.push("invalid_signature"),void n({errors:c})}const l=a.signature.packets[0].issuerKeyId.toHex(),u=a.signature.packets[0].signersUserId,p=a.signature.packets[0].preferredKeyServer||"https://keys.openpgp.org/",d=a.getText();let h,f,m=[],y=[];if(d.split("\n").forEach(((e,t)=>{const r=e.match(/^([a-zA-Z0-9]*)\=(.*)$/i);if(r)switch(r[1].toLowerCase()){case"key":m.push(r[2]);break;case"proof":y.push(r[2])}})),m.length>0)try{f=m[0],h=await s.fetch.uri(f)}catch(e){}if(!h&&u)try{f="wkd:"+u,h=await s.fetch.uri(f)}catch(e){}if(!h)try{f=`hkp:${p.match(/^(.*\:\/\/)?([^/]*)(?:\/)?$/i)[2]}:${l||u}`,h=await s.fetch.uri(f)}catch(e){return c.push("key_not_found"),void n({errors:c})}const g=h.keyPacket.getFingerprint();try{const e=await a.verify([h]);await e[0].verified}catch(e){return c.push("invalid_signature_verification"),void n({errors:c})}const w=await o.verify(y,g,t);r({errors:c,signature:{data:a.signature,issuerKeyId:l,signersUserId:u,preferredKeyServer:p},publicKey:{data:h,uri:f,fingerprint:g},text:d,claims:w})}))}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./claims":10,"./keys":12,"merge-options":5}],30:[function(e,t,r){r.generateProxyURL=(e,t,r)=>{if(!r||!r.doipProxyHostname)return null;let i="";return"xmpp"==e&&(i+="/DESC"),`https://${r.doipProxyHostname}/api/1/get/${e}/${encodeURIComponent(t)}${i}`},r.generateClaim=(e,t)=>{switch(t){case"uri":return"openpgp4fpr:"+e;case"message":return`[Verifying my OpenPGP key: openpgp4fpr:${e}]`;case"fingerprint":return e;default:throw new Error("No valid claim format")}}},{}]},{},[11])(11)})); +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).doip=e()}}((function(){return function e(t,r,i){function o(s,a){if(!r[s]){if(!t[s]){var c="function"==typeof require&&require;if(!a&&c)return c(s,!0);if(n)return n(s,!0);var l=new Error("Cannot find module '"+s+"'");throw l.code="MODULE_NOT_FOUND",l}var u=r[s]={exports:{}};t[s][0].call(u.exports,(function(e){return o(t[s][1][e]||e)}),u,u.exports,e,t,r,i)}return r[s].exports}for(var n="function"==typeof require&&require,s=0;s(r||(r=this.arrayBuffer()),r)}),this.headers={};for(const[t,r]of e.headers.entries())this.headers[t.toLowerCase()]=r}}t.exports=i(((e,t,r,i,n)=>async(s,a,c={})=>{s=n+(s||"");let l=new URL(s);if(i||(i={}),l.username&&(i.Authorization="Basic "+btoa(l.username+":"+l.password),l=new URL(l.protocol+"//"+l.host+l.pathname+l.search)),"https:"!==l.protocol&&"http:"!==l.protocol)throw new Error("Unknown protocol, "+l.protocol);if(a)if(a instanceof ArrayBuffer||ArrayBuffer.isView(a)||"string"==typeof a);else{if("object"!=typeof a)throw new Error("Unknown body type.");a=JSON.stringify(a),i["Content-Type"]="application/json"}c=new Headers({...i||{},...c});const u=await fetch(l,{method:t,headers:c,body:a});if(u.statusCode=u.status,!e.has(u.status))throw new o(u);return"json"===r?u.json():"buffer"===r?u.arrayBuffer():"string"===r?u.text():u}))},{"./core":2}],2:[function(e,t,r){"use strict";const i=new Set(["json","buffer","string"]);t.exports=e=>(...t)=>{const r=new Set;let o,n,s,a="";return t.forEach((e=>{if("string"==typeof e)if(e.toUpperCase()===e){if(o){throw new Error(`Can't set method to ${e}, already set to ${o}.`)}o=e}else if(e.startsWith("http:")||e.startsWith("https:"))a=e;else{if(!i.has(e))throw new Error("Unknown encoding, "+e);n=e}else if("number"==typeof e)r.add(e);else{if("object"!=typeof e)throw new Error("Unknown type: "+typeof e);if(Array.isArray(e)||e instanceof Set)e.forEach((e=>r.add(e)));else{if(s)throw new Error("Cannot set headers twice.");s=e}}})),o||(o="GET"),0===r.size&&r.add(200),e(r,o,n,s,a)}},{}],3:[function(e,t,r){},{}],4:[function(e,t,r){"use strict";var i="%[a-f0-9]{2}",o=new RegExp(i,"gi"),n=new RegExp("("+i+")+","gi");function s(e,t){try{return decodeURIComponent(e.join(""))}catch(e){}if(1===e.length)return e;t=t||1;var r=e.slice(0,t),i=e.slice(t);return Array.prototype.concat.call([],s(r),s(i))}function a(e){try{return decodeURIComponent(e)}catch(i){for(var t=e.match(o),r=1;r{if("[object Object]"!==Object.prototype.toString.call(e))return!1;const t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}},{}],7:[function(e,t,r){"use strict";const i=e("is-plain-obj"),{hasOwnProperty:o}=Object.prototype,{propertyIsEnumerable:n}=Object,s=(e,t,r)=>Object.defineProperty(e,t,{value:r,writable:!0,enumerable:!0,configurable:!0}),a=this,c={concatArrays:!1,ignoreUndefined:!1},l=e=>{const t=[];for(const r in e)o.call(e,r)&&t.push(r);if(Object.getOwnPropertySymbols){const r=Object.getOwnPropertySymbols(e);for(const i of r)n.call(e,i)&&t.push(i)}return t};function u(e){return Array.isArray(e)?function(e){const t=e.slice(0,0);return l(e).forEach((r=>{s(t,r,u(e[r]))})),t}(e):i(e)?function(e){const t=null===Object.getPrototypeOf(e)?Object.create(null):{};return l(e).forEach((r=>{s(t,r,u(e[r]))})),t}(e):e}const p=(e,t,r,i)=>(r.forEach((r=>{void 0===t[r]&&i.ignoreUndefined||(r in e&&e[r]!==Object.getPrototypeOf(e)?s(e,r,d(e[r],t[r],i)):s(e,r,u(t[r])))})),e);function d(e,t,r){return r.concatArrays&&Array.isArray(e)&&Array.isArray(t)?((e,t,r)=>{let i=e.slice(0,0),n=0;return[e,t].forEach((t=>{const a=[];for(let r=0;r!a.includes(e))),r)})),i})(e,t,r):i(t)&&i(e)?p(e,t,l(t),r):u(t)}t.exports=function(...e){const t=d(u(c),this!==a&&this||{},c);let r={_:{}};for(const o of e)if(void 0!==o){if(!i(o))throw new TypeError("`"+o+"` is not an Option Object");r=d(r,{_:o},t)}return r._}},{"is-plain-obj":6}],8:[function(e,t,r){(function(e){(function(){"use strict";function r(e){if("string"!=typeof e)throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}function i(e,t){for(var r,i="",o=0,n=-1,s=0,a=0;a<=e.length;++a){if(a2){var c=i.lastIndexOf("/");if(c!==i.length-1){-1===c?(i="",o=0):o=(i=i.slice(0,c)).length-1-i.lastIndexOf("/"),n=a,s=0;continue}}else if(2===i.length||1===i.length){i="",o=0,n=a,s=0;continue}t&&(i.length>0?i+="/..":i="..",o=2)}else i.length>0?i+="/"+e.slice(n+1,a):i=e.slice(n+1,a),o=a-n-1;n=a,s=0}else 46===r&&-1!==s?++s:s=-1}return i}var o={resolve:function(){for(var t,o="",n=!1,s=arguments.length-1;s>=-1&&!n;s--){var a;s>=0?a=arguments[s]:(void 0===t&&(t=e.cwd()),a=t),r(a),0!==a.length&&(o=a+"/"+o,n=47===a.charCodeAt(0))}return o=i(o,!n),n?o.length>0?"/"+o:"/":o.length>0?o:"."},normalize:function(e){if(r(e),0===e.length)return".";var t=47===e.charCodeAt(0),o=47===e.charCodeAt(e.length-1);return 0!==(e=i(e,!t)).length||t||(e="."),e.length>0&&o&&(e+="/"),t?"/"+e:e},isAbsolute:function(e){return r(e),e.length>0&&47===e.charCodeAt(0)},join:function(){if(0===arguments.length)return".";for(var e,t=0;t0&&(void 0===e?e=i:e+="/"+i)}return void 0===e?".":o.normalize(e)},relative:function(e,t){if(r(e),r(t),e===t)return"";if((e=o.resolve(e))===(t=o.resolve(t)))return"";for(var i=1;il){if(47===t.charCodeAt(a+p))return t.slice(a+p+1);if(0===p)return t.slice(a+p)}else s>l&&(47===e.charCodeAt(i+p)?u=p:0===p&&(u=0));break}var d=e.charCodeAt(i+p);if(d!==t.charCodeAt(a+p))break;47===d&&(u=p)}var f="";for(p=i+u+1;p<=n;++p)p!==n&&47!==e.charCodeAt(p)||(0===f.length?f+="..":f+="/..");return f.length>0?f+t.slice(a+u):(a+=u,47===t.charCodeAt(a)&&++a,t.slice(a))},_makeLong:function(e){return e},dirname:function(e){if(r(e),0===e.length)return".";for(var t=e.charCodeAt(0),i=47===t,o=-1,n=!0,s=e.length-1;s>=1;--s)if(47===(t=e.charCodeAt(s))){if(!n){o=s;break}}else n=!1;return-1===o?i?"/":".":i&&1===o?"//":e.slice(0,o)},basename:function(e,t){if(void 0!==t&&"string"!=typeof t)throw new TypeError('"ext" argument must be a string');r(e);var i,o=0,n=-1,s=!0;if(void 0!==t&&t.length>0&&t.length<=e.length){if(t.length===e.length&&t===e)return"";var a=t.length-1,c=-1;for(i=e.length-1;i>=0;--i){var l=e.charCodeAt(i);if(47===l){if(!s){o=i+1;break}}else-1===c&&(s=!1,c=i+1),a>=0&&(l===t.charCodeAt(a)?-1==--a&&(n=i):(a=-1,n=c))}return o===n?n=c:-1===n&&(n=e.length),e.slice(o,n)}for(i=e.length-1;i>=0;--i)if(47===e.charCodeAt(i)){if(!s){o=i+1;break}}else-1===n&&(s=!1,n=i+1);return-1===n?"":e.slice(o,n)},extname:function(e){r(e);for(var t=-1,i=0,o=-1,n=!0,s=0,a=e.length-1;a>=0;--a){var c=e.charCodeAt(a);if(47!==c)-1===o&&(n=!1,o=a+1),46===c?-1===t?t=a:1!==s&&(s=1):-1!==t&&(s=-1);else if(!n){i=a+1;break}}return-1===t||-1===o||0===s||1===s&&t===o-1&&t===i+1?"":e.slice(t,o)},format:function(e){if(null===e||"object"!=typeof e)throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof e);return function(e,t){var r=t.dir||t.root,i=t.base||(t.name||"")+(t.ext||"");return r?r===t.root?r+i:r+e+i:i}("/",e)},parse:function(e){r(e);var t={root:"",dir:"",base:"",ext:"",name:""};if(0===e.length)return t;var i,o=e.charCodeAt(0),n=47===o;n?(t.root="/",i=1):i=0;for(var s=-1,a=0,c=-1,l=!0,u=e.length-1,p=0;u>=i;--u)if(47!==(o=e.charCodeAt(u)))-1===c&&(l=!1,c=u+1),46===o?-1===s?s=u:1!==p&&(p=1):-1!==s&&(p=-1);else if(!l){a=u+1;break}return-1===s||-1===c||0===p||1===p&&s===c-1&&s===a+1?-1!==c&&(t.base=t.name=0===a&&n?e.slice(1,c):e.slice(a,c)):(0===a&&n?(t.name=e.slice(1,s),t.base=e.slice(1,c)):(t.name=e.slice(a,s),t.base=e.slice(a,c)),t.ext=e.slice(s,c)),a>0?t.dir=e.slice(0,a-1):n&&(t.dir="/"),t},sep:"/",delimiter:":",win32:null,posix:null};o.posix=o,t.exports=o}).call(this)}).call(this,e("_process"))},{_process:9}],9:[function(e,t,r){var i,o,n=t.exports={};function s(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function c(e){if(i===setTimeout)return setTimeout(e,0);if((i===s||!i)&&setTimeout)return i=setTimeout,setTimeout(e,0);try{return i(e,0)}catch(t){try{return i.call(null,e,0)}catch(t){return i.call(this,e,0)}}}!function(){try{i="function"==typeof setTimeout?setTimeout:s}catch(e){i=s}try{o="function"==typeof clearTimeout?clearTimeout:a}catch(e){o=a}}();var l,u=[],p=!1,d=-1;function f(){p&&l&&(p=!1,l.length?u=l.concat(u):d=-1,u.length&&h())}function h(){if(!p){var e=c(f);p=!0;for(var t=u.length;t;){for(l=u,u=[];++d1)for(var r=1;rNumber(e)-Number(t))).map((t=>e[t])):e}function p(e){const t=e.indexOf("#");return-1!==t&&(e=e.slice(0,t)),e}function d(e){const t=(e=p(e)).indexOf("?");return-1===t?"":e.slice(t+1)}function f(e,t){return t.parseNumbers&&!Number.isNaN(Number(e))&&"string"==typeof e&&""!==e.trim()?e=Number(e):!t.parseBooleans||null===e||"true"!==e.toLowerCase()&&"false"!==e.toLowerCase()||(e="true"===e.toLowerCase()),e}function h(e,t){a((t=Object.assign({decode:!0,sort:!0,arrayFormat:"none",arrayFormatSeparator:",",parseNumbers:!1,parseBooleans:!1},t)).arrayFormatSeparator);const r=function(e){let t;switch(e.arrayFormat){case"index":return(e,r,i)=>{t=/\[(\d*)\]$/.exec(e),e=e.replace(/\[\d*\]$/,""),t?(void 0===i[e]&&(i[e]={}),i[e][t[1]]=r):i[e]=r};case"bracket":return(e,r,i)=>{t=/(\[\])$/.exec(e),e=e.replace(/\[\]$/,""),t?void 0!==i[e]?i[e]=[].concat(i[e],r):i[e]=[r]:i[e]=r};case"comma":case"separator":return(t,r,i)=>{const o="string"==typeof r&&r.includes(e.arrayFormatSeparator),n="string"==typeof r&&!o&&l(r,e).includes(e.arrayFormatSeparator);r=n?l(r,e):r;const s=o||n?r.split(e.arrayFormatSeparator).map((t=>l(t,e))):null===r?r:l(r,e);i[t]=s};default:return(e,t,r)=>{void 0!==r[e]?r[e]=[].concat(r[e],t):r[e]=t}}}(t),i=Object.create(null);if("string"!=typeof e)return i;if(!(e=e.trim().replace(/^[?#&]/,"")))return i;for(const o of e.split("&")){if(""===o)continue;let[e,s]=n(t.decode?o.replace(/\+/g," "):o,"=");s=void 0===s?null:["comma","separator"].includes(t.arrayFormat)?s:l(s,t),r(l(e,t),s,i)}for(const e of Object.keys(i)){const r=i[e];if("object"==typeof r&&null!==r)for(const e of Object.keys(r))r[e]=f(r[e],t);else i[e]=f(r,t)}return!1===t.sort?i:(!0===t.sort?Object.keys(i).sort():Object.keys(i).sort(t.sort)).reduce(((e,t)=>{const r=i[t];return Boolean(r)&&"object"==typeof r&&!Array.isArray(r)?e[t]=u(r):e[t]=r,e}),Object.create(null))}r.extract=d,r.parse=h,r.stringify=(e,t)=>{if(!e)return"";a((t=Object.assign({encode:!0,strict:!0,arrayFormat:"none",arrayFormatSeparator:","},t)).arrayFormatSeparator);const r=r=>t.skipNull&&null==e[r]||t.skipEmptyString&&""===e[r],i=function(e){switch(e.arrayFormat){case"index":return t=>(r,i)=>{const o=r.length;return void 0===i||e.skipNull&&null===i||e.skipEmptyString&&""===i?r:null===i?[...r,[c(t,e),"[",o,"]"].join("")]:[...r,[c(t,e),"[",c(o,e),"]=",c(i,e)].join("")]};case"bracket":return t=>(r,i)=>void 0===i||e.skipNull&&null===i||e.skipEmptyString&&""===i?r:null===i?[...r,[c(t,e),"[]"].join("")]:[...r,[c(t,e),"[]=",c(i,e)].join("")];case"comma":case"separator":return t=>(r,i)=>null==i||0===i.length?r:0===r.length?[[c(t,e),"=",c(i,e)].join("")]:[[r,c(i,e)].join(e.arrayFormatSeparator)];default:return t=>(r,i)=>void 0===i||e.skipNull&&null===i||e.skipEmptyString&&""===i?r:null===i?[...r,c(t,e)]:[...r,[c(t,e),"=",c(i,e)].join("")]}}(t),o={};for(const t of Object.keys(e))r(t)||(o[t]=e[t]);const n=Object.keys(o);return!1!==t.sort&&n.sort(t.sort),n.map((r=>{const o=e[r];return void 0===o?"":null===o?c(r,t):Array.isArray(o)?o.reduce(i(r),[]).join("&"):c(r,t)+"="+c(o,t)})).filter((e=>e.length>0)).join("&")},r.parseUrl=(e,t)=>{t=Object.assign({decode:!0},t);const[r,i]=n(e,"#");return Object.assign({url:r.split("?")[0]||"",query:h(d(e),t)},t&&t.parseFragmentIdentifier&&i?{fragmentIdentifier:l(i,t)}:{})},r.stringifyUrl=(e,t)=>{t=Object.assign({encode:!0,strict:!0},t);const i=p(e.url).split("?")[0]||"",o=r.extract(e.url),n=r.parse(o,{sort:!1}),s=Object.assign(n,e.query);let a=r.stringify(s,t);a&&(a="?"+a);let l=function(e){let t="";const r=e.indexOf("#");return-1!==r&&(t=e.slice(r)),t}(e.url);return e.fragmentIdentifier&&(l="#"+c(e.fragmentIdentifier,t)),`${i}${a}${l}`},r.pick=(e,t,i)=>{i=Object.assign({parseFragmentIdentifier:!0},i);const{url:o,query:n,fragmentIdentifier:a}=r.parseUrl(e,i);return r.stringifyUrl({url:o,query:s(n,t),fragmentIdentifier:a},i)},r.exclude=(e,t,i)=>{const o=Array.isArray(t)?e=>!t.includes(e):(e,r)=>!t(e,r);return r.pick(e,o,i)}},{"decode-uri-component":4,"filter-obj":5,"split-on-first":11,"strict-uri-encode":12}],11:[function(e,t,r){"use strict";t.exports=(e,t)=>{if("string"!=typeof e||"string"!=typeof t)throw new TypeError("Expected the arguments to be of type `string`");if(""===t)return[e];const r=e.indexOf(t);return-1===r?[e]:[e.slice(0,r),e.slice(r+t.length)]}},{}],12:[function(e,t,r){"use strict";t.exports=e=>encodeURIComponent(e).replace(/[!'()*]/g,(e=>"%"+e.charCodeAt(0).toString(16).toUpperCase()))},{}],13:[function(e,t,r){!function(e){"use strict";e.exports.is_uri=r,e.exports.is_http_uri=i,e.exports.is_https_uri=o,e.exports.is_web_uri=n,e.exports.isUri=r,e.exports.isHttpUri=i,e.exports.isHttpsUri=o,e.exports.isWebUri=n;var t=function(e){return e.match(/(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/)};function r(e){if(e&&!/[^a-z0-9\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=\.\-\_\~\%]/i.test(e)&&!/%[^0-9a-f]/i.test(e)&&!/%[0-9a-f](:?[^0-9a-f]|$)/i.test(e)){var r,i,o,n,s,a="",c="";if(a=(r=t(e))[1],i=r[2],o=r[3],n=r[4],s=r[5],a&&a.length&&o.length>=0){if(i&&i.length){if(0!==o.length&&!/^\//.test(o))return}else if(/^\/\//.test(o))return;if(/^[a-z][a-z0-9\+\-\.]*$/.test(a.toLowerCase()))return c+=a+":",i&&i.length&&(c+="//"+i),c+=o,n&&n.length&&(c+="?"+n),s&&s.length&&(c+="#"+s),c}}}function i(e,i){if(r(e)){var o,n,s,a,c="",l="",u="",p="";if(c=(o=t(e))[1],l=o[2],n=o[3],s=o[4],a=o[5],c){if(i){if("https"!=c.toLowerCase())return}else if("http"!=c.toLowerCase())return;if(l)return/:(\d+)$/.test(l)&&(u=l.match(/:(\d+)$/)[0],l=l.replace(/:\d+$/,"")),p+=c+":",p+="//"+l,u&&(p+=u),p+=n,s&&s.length&&(p+="?"+s),a&&a.length&&(p+="#"+a),p}}}function o(e){return i(e,!0)}function n(e){return i(e)||o(e)}}(t)},{}],14:[function(e,t,r){t.exports={name:"doipjs",version:"0.11.0",description:"Decentralized OpenPGP Identity Proofs library in Node.js",main:"src/index.js",dependencies:{bent:"^7.3.12",browserify:"^17.0.0","merge-options":"^3.0.3",openpgp:"^4.10.9",prettier:"^2.1.2","query-string":"^6.14.1","valid-url":"^1.0.9"},devDependencies:{"browserify-shim":"^3.8.14",chai:"^4.2.0","chai-as-promised":"^7.1.1","chai-match-pattern":"^1.2.0","license-check-and-add":"^3.0.4",minify:"^6.0.1",mocha:"^8.2.0"},scripts:{"release:bundle":"./node_modules/browserify/bin/cmd.js ./src/index.js --standalone doip -x openpgp -o ./dist/doip.js","release:minify":"./node_modules/minify/bin/minify.js ./dist/doip.js > ./dist/doip.min.js","prettier:check":"./node_modules/prettier/bin-prettier.js --check .","prettier:write":"./node_modules/prettier/bin-prettier.js --write .","license:check":"./node_modules/license-check-and-add/dist/src/cli.js check","license:add":"./node_modules/license-check-and-add/dist/src/cli.js add","license:remove":"./node_modules/license-check-and-add/dist/src/cli.js remove",docs:"docsify serve ./docs",test:"./node_modules/mocha/bin/mocha"},repository:{type:"git",url:"https://codeberg.org/keyoxide/doipjs"},homepage:"https://js.doip.rocks",keywords:["pgp","gpg","openpgp","encryption","decentralized","identity"],author:"Yarmo Mackenbach (https://yarmo.eu)",license:"Apache-2.0",browserify:{transform:["browserify-shim"]},"browserify-shim":{openpgp:"global:openpgp"}}},{}],15:[function(e,t,r){(function(t){(function(){e("path");const i=e("merge-options"),o=e("valid-url"),n="undefined"!=typeof window?window.openpgp:void 0!==t?t.openpgp:null,s=e("./serviceproviders"),a=e("./keys"),c=e("./utils");Promise.allSettled=Promise.allSettled||(e=>Promise.all(e.map((e=>e.then((e=>({status:"fulfilled",value:e}))).catch((e=>({status:"rejected",reason:e})))))));const l=(e,t,r,i,o)=>{let n;if(e.isVerified||!t)return e;if(Array.isArray(t))return t.forEach(((t,n)=>{e=l(e,t,r,i,o)})),e;if(0==r.length){switch(o){default:case"contains":n=new RegExp(i,"gi"),e.isVerified=n.test(t.replace(/\r?\n|\r|\\/g,""));break;case"equals":e.isVerified=t.replace(/\r?\n|\r|\\/g,"").toLowerCase()==i.toLowerCase();break;case"oneOf":n=new RegExp(i,"gi"),e.isVerified=n.test(t.join("|"))}return e}try{r[0]}catch(t){return e.errors.push("err_data_structure_incorrect"),e}return e=l(e,t[r[0]],r.slice(1),i,o)},u=(e,t)=>{let r={isVerified:!1,errors:[]};switch(t.proof.format){case"json":r=l(r,e,t.claim.path,c.generateClaim(t.claim.fingerprint,t.claim.format),t.claim.relation);break;case"text":re=new RegExp(c.generateClaim(t.claim.fingerprint,t.claim.format),"gi"),r.isVerified=re.test(e.replace(/\r?\n|\r/,""))}return r},p=async(e,t,r)=>{if(e instanceof n.key.Key){const t=await a.getFingerprint(e),i=(await a.getUserData(e)).map((async(e,i)=>new Promise((async(i,o)=>{try{i(await p(e.notations,t,r))}catch(e){o(e)}}))));return Promise.allSettled(i).then((e=>e.map(((e,t)=>"fulfilled"==e.status?e.value:e.reason))))}if(e instanceof Array){const i=e.map((async(e,i)=>new Promise((async(i,o)=>{try{i(await p(e,t,r))}catch(e){o(e)}}))));return Promise.allSettled(i).then((e=>e.map(((e,t)=>"fulfilled"==e.status?e.value:e.reason))))}const c=new Promise((async(n,a)=>{let c={isVerified:!1,errors:[],serviceproviderData:void 0};const l=e.replace(/^\s+|\s+$/g,"");t||(t=null);if(r=i({returnMatchesOnly:!1,proxyPolicy:"adaptive",doipProxyHostname:"proxy.keyoxide.org",twitterBearerToken:null,nitterInstance:null},r||{}),!o.isUri(l))return c.errors.push("invalid_uri"),void a(c);const p=s.match(l,r);if("returnMatchesOnly"in r&&r.returnMatchesOnly)return void n(p);let d,f,h,m,y=!1,g=0;for(;!y&&g{const t={isVerified:!1,errors:["verification_timed_out"],serviceproviderData:void 0};setTimeout((()=>{e(t)}),1e4)}));return await Promise.race([c,l])};r.verify=p}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./keys":17,"./serviceproviders":18,"./utils":37,"merge-options":7,path:8,"valid-url":13}],16:[function(e,t,r){const i=e("./claims"),o=e("./keys"),n=e("./signatures"),s=e("./serviceproviders"),a=e("./utils");r.claims=i,r.keys=o,r.signatures=n,r.serviceproviders=s,r.utils=a},{"./claims":15,"./keys":17,"./serviceproviders":18,"./signatures":36,"./utils":37}],17:[function(e,t,r){(function(t){(function(){e("path");const i=e("bent")("GET"),o=e("valid-url"),n="undefined"!=typeof window?window.openpgp:void 0!==t?t.openpgp:null,s=(e("merge-options"),(e,t)=>new Promise((async(r,i)=>{t=t?"https://"+t:"https://keys.openpgp.org";const o=new n.HKP(t),s={query:e};let a=await o.lookup(s).catch((e=>{i("Key does not exist or could not be fetched")}));a=await n.key.readArmored(a).then((e=>e.keys[0])).catch((e=>null)),a?r(a):i("Key does not exist or could not be fetched")}))),a=e=>new Promise((async(t,r)=>{const i=new n.WKD,o={email:e},s=await i.lookup(o).then((e=>e.keys[0])).catch((e=>null));s?t(s):r("Key does not exist or could not be fetched")})),c=(e,t)=>new Promise((async(e,t)=>{try{await i(opts.keyLink).then((e=>{if(200===e.status)return e})).then((e=>e.text()))}catch(e){t("Error fetching Keybase key: "+e.message)}const r=await n.key.readArmored(rawKeyContent).then((e=>e.keys[0])).catch((e=>null));r?e(r):t("Key does not exist or could not be fetched")})),l=e=>new Promise((async(t,r)=>{e||r("Invalid public key");const i=await e.primaryKey.getFingerprint(),o=await e.getPrimaryUser(),s=e.users;let a=[];s.forEach(((e,t)=>{if(a[t]={userData:{id:e.userId?e.userId.userid:null,name:e.userId?e.userId.name:null,email:e.userId?e.userId.email:null,comment:e.userId?e.userId.comment:null,isPrimary:o.index===t}},"selfCertifications"in e&&e.selfCertifications.length>0){const r=e.selfCertifications[0].rawNotations;a[t].notations=r.map((({name:e,value:t,humanReadable:r})=>{if(r&&"proof@metacode.biz"===e)return n.util.decode_utf8(t)}))}else a[t].notations=[]})),t({fingerprint:i,users:a,primaryUserIndex:o.index})}));r.fetch={uri:e=>new Promise((async(t,r)=>{o.isUri(e)||r("Invalid URI");const i=e.match(/([a-zA-Z0-9]*):([a-zA-Z0-9@._=+\-]*)(?:\:([a-zA-Z0-9@._=+\-]*))?/);switch(i[1]||r("Invalid URI"),i[1]){case"hkp":t(s(i[3]?i[3]:i[2],i[3]?i[2]:null));break;case"wkd":t(a(i[2]));break;case"kb":t(c(i[2],i.length>=4&&i[3]));break;default:r("Invalid URI protocol")}})),hkp:s,wkd:a,keybase:c,plaintext:e=>new Promise((async(t,r)=>{t((await n.key.readArmored(e)).keys[0])})),signature:(e,t)=>new Promise((async(r,i)=>{let o=await n.signature.readArmored(e);if("compressed"in o.packets[0]){o=o.packets[0];await n.stream.readToEnd(await o.packets[1].getText())}const a=o.packets[0].signersUserId,c=await o.packets[0].issuerKeyId.toHex();r(s(a||c,t))}))},r.process=l,r.getUserData=e=>new Promise((async(t,r)=>{t((await l(e)).users)})),r.getFingerprint=e=>new Promise((async(t,r)=>{t((await l(e)).fingerprint)}))}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{bent:1,"merge-options":7,path:8,"valid-url":13}],18:[function(e,t,r){const i=e("bent")("GET"),o=e("./utils"),n=["dns","irc","xmpp","matrix","twitter","reddit","liberapay","hackernews","lobsters","devto","gitea","gitlab","github","mastodon","fediverse","discourse","owncast"],s={dns:e("./serviceproviders/dns"),irc:e("./serviceproviders/irc"),xmpp:e("./serviceproviders/xmpp"),matrix:e("./serviceproviders/matrix"),twitter:e("./serviceproviders/twitter"),reddit:e("./serviceproviders/reddit"),liberapay:e("./serviceproviders/liberapay"),hackernews:e("./serviceproviders/hackernews"),lobsters:e("./serviceproviders/lobsters"),devto:e("./serviceproviders/devto"),gitea:e("./serviceproviders/gitea"),gitlab:e("./serviceproviders/gitlab"),github:e("./serviceproviders/github"),mastodon:e("./serviceproviders/mastodon"),fediverse:e("./serviceproviders/fediverse"),discourse:e("./serviceproviders/discourse"),owncast:e("./serviceproviders/owncast")};r.list=n,r.data=s,r.match=(e,t)=>{let r,i=[];return n.forEach(((o,n)=>{r=s[o],r.reURI.test(e)&&i.push(r.processURI(e,t))})),i},r.directRequestHandler=(t,r)=>new Promise((async(r,o)=>{const n=t.proof.fetch?t.proof.fetch:t.proof.uri;if(!n)return void o("No valid URI provided");switch(t.proof.format){case"json":i(n,null,{Accept:"application/json","User-Agent":"doipjs/"+e("../package.json").version}).then((async e=>await e.json())).then((e=>{r(e)})).catch((e=>{o(e)}));break;case"text":i(n).then((async e=>await e.text())).then((e=>{r(e)})).catch((e=>{o(e)}));break;default:o("No specified proof data format")}})),r.proxyRequestHandler=(e,t)=>new Promise((async(r,n)=>{const s=e.proof.fetch?e.proof.fetch:e.proof.uri;i(o.generateProxyURL(e.proof.format,s,t),null,{Accept:"application/json"}).then((async e=>await e.json())).then((e=>{r(e.content)})).catch((e=>{n(e)}))}))},{"../package.json":14,"./serviceproviders/devto":19,"./serviceproviders/discourse":20,"./serviceproviders/dns":21,"./serviceproviders/fediverse":22,"./serviceproviders/gitea":23,"./serviceproviders/github":24,"./serviceproviders/gitlab":25,"./serviceproviders/hackernews":26,"./serviceproviders/irc":27,"./serviceproviders/liberapay":28,"./serviceproviders/lobsters":29,"./serviceproviders/mastodon":30,"./serviceproviders/matrix":31,"./serviceproviders/owncast":32,"./serviceproviders/reddit":33,"./serviceproviders/twitter":34,"./serviceproviders/xmpp":35,"./utils":37,bent:1}],19:[function(e,t,r){const i=/^https:\/\/dev\.to\/(.*)\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"devto"},profile:{display:r[1],uri:"https://dev.to/"+r[1],qr:null},proof:{uri:e,fetch:`https://dev.to/api/articles/${r[1]}/${r[2]}`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["body_markdown"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://dev.to/alice/post",shouldMatch:!0},{uri:"https://dev.to/alice/post/",shouldMatch:!0},{uri:"https://domain.org/alice/post",shouldMatch:!1}]},{}],20:[function(e,t,r){const i=/^https:\/\/(.*)\/u\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"discourse"},profile:{display:`${r[2]}@${r[1]}`,uri:e,qr:null},proof:{uri:e,fetch:`https://${r[1]}/u/${r[2]}.json`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["user","bio_raw"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/u/alice",shouldMatch:!0},{uri:"https://domain.org/u/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],21:[function(e,t,r){const i=e("dns"),o=e("bent")("GET"),n=e("../utils"),s=/^dns:([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/,a=async(e,t)=>{if("resolveTxt"in i){const t=async()=>new Promise(((t,r)=>{i.resolveTxt(e.profile.display,((e,i)=>{e&&r(e),t(i)}))}));return{hostname:e.profile.display,records:{txt:await t()}}}{const t=await o(e.proof.uri,null,{Accept:"application/json"});return await t.json()}};r.reURI=s,r.processURI=(e,t)=>{t||(t={});const r=e.match(s);return{serviceprovider:{type:"web",name:"dns"},profile:{display:r[1],uri:"https://"+r[1],qr:null},proof:{uri:n.generateProxyURL("dns",r[1],t),fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"uri",path:["records","txt"],relation:"contains"},customRequestHandler:a}},r.tests=[{uri:"dns:domain.org",shouldMatch:!0},{uri:"dns:domain.org?type=TXT",shouldMatch:!0},{uri:"https://domain.org",shouldMatch:!1}]},{"../utils":37,bent:1,dns:3}],22:[function(e,t,r){const i=/^https:\/\/(.*)\/users\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"fediverse"},profile:{display:`@${r[2]}@${r[1]}`,uri:e,qr:null},proof:{uri:e,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"fingerprint",path:["summary"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/users/alice",shouldMatch:!0},{uri:"https://domain.org/users/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],23:[function(e,t,r){const i=/^https:\/\/(.*)\/(.*)\/gitea_proof\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"gitea"},profile:{display:`${r[2]}@${r[1]}`,uri:`https://${r[1]}/${r[2]}`,qr:null},proof:{uri:e,fetch:`https://${r[1]}/api/v1/repos/${r[2]}/gitea_proof`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["description"],relation:"equals"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/alice/gitea_proof",shouldMatch:!0},{uri:"https://domain.org/alice/gitea_proof/",shouldMatch:!0},{uri:"https://domain.org/alice/other_proof",shouldMatch:!1}]},{}],24:[function(e,t,r){const i=/^https:\/\/gist\.github\.com\/(.*)\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"github"},profile:{display:r[1],uri:"https://github.com/"+r[1],qr:null},proof:{uri:e,fetch:"https://api.github.com/gists/"+r[2],useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["files","openpgp.md","content"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://gist.github.com/Alice/123456789",shouldMatch:!0},{uri:"https://gist.github.com/Alice/123456789/",shouldMatch:!0},{uri:"https://domain.org/Alice/123456789",shouldMatch:!1}]},{}],25:[function(e,t,r){const i=e("bent")("GET"),o=/^https:\/\/(.*)\/(.*)\/gitlab_proof\/?/,n=async(e,t)=>{const r=e.proof.uri.match(o),n=`https://${r[1]}/api/v4/users?username=${r[2]}`;let s;try{s=await i(n,null,{Accept:"application/json"})}catch(e){s=await i(utils.generateProxyURL("web",n,t),null,{Accept:"application/json"})}const a=(await s.json()).find((e=>e.username===r[2]));if(!a)throw new Error("No user with username "+r[2]);const c=`https://${r[1]}/api/v4/users/${a.id}/projects`;let l;try{l=await i(c,null,{Accept:"application/json"})}catch(e){l=await i(utils.generateProxyURL("web",c,t),null,{Accept:"application/json"})}const u=(await l.json()).find((e=>"gitlab_proof"===e.path));if(!u)throw new Error("No project at "+e.proof.uri);return u};r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"web",name:"gitlab"},profile:{display:`${r[2]}@${r[1]}`,uri:`https://${r[1]}/${r[2]}`,qr:null},proof:{uri:e,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["description"],relation:"equals"},customRequestHandler:n}},r.tests=[{uri:"https://gitlab.domain.org/alice/gitlab_proof",shouldMatch:!0},{uri:"https://gitlab.domain.org/alice/gitlab_proof/",shouldMatch:!0},{uri:"https://domain.org/alice/other_proof",shouldMatch:!1}]},{bent:1}],26:[function(e,t,r){const i=/^https:\/\/news\.ycombinator\.com\/user\?id=(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"hackernews"},profile:{display:r[1],uri:e,qr:null},proof:{uri:`https://hacker-news.firebaseio.com/v0/user/${r[1]}.json`,fetch:null,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"uri",path:["about"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://news.ycombinator.com/user?id=Alice",shouldMatch:!0},{uri:"https://news.ycombinator.com/user?id=Alice/",shouldMatch:!0},{uri:"https://domain.org/user?id=Alice",shouldMatch:!1}]},{}],27:[function(e,t,r){const i=e("../utils"),o=/^irc\:\/\/(.*)\/([a-zA-Z0-9]*)/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"communication",name:"irc"},profile:{display:`irc://${r[1]}/${r[2]}`,uri:e,qr:null},proof:{uri:i.generateProxyURL("irc",[r[1],r[2]],t),fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"uri",path:["data"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"irc://chat.ircserver.org/Alice1",shouldMatch:!0},{uri:"irc://chat.ircserver.org/alice?param=123",shouldMatch:!0},{uri:"https://chat.ircserver.org/alice",shouldMatch:!1}]},{"../utils":37}],28:[function(e,t,r){const i=/^https:\/\/liberapay\.com\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"liberapay"},profile:{display:r[1],uri:e,qr:null},proof:{uri:e,fetch:`https://liberapay.com/${r[1]}/public.json`,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["statements","content"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://liberapay.com/alice",shouldMatch:!0},{uri:"https://liberapay.com/alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],29:[function(e,t,r){const i=/^https:\/\/lobste\.rs\/u\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"lobsters"},profile:{display:r[1],uri:e,qr:null},proof:{uri:`https://lobste.rs/u/${r[1]}.json`,fetch:null,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["about"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://lobste.rs/u/Alice",shouldMatch:!0},{uri:"https://lobste.rs/u/Alice/",shouldMatch:!0},{uri:"https://domain.org/u/Alice",shouldMatch:!1}]},{}],30:[function(e,t,r){const i=/^https:\/\/(.*)\/@(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"mastodon"},profile:{display:`@${r[2]}@${r[1]}`,uri:e,qr:null},proof:{uri:e,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"fingerprint",path:["attachment","value"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://domain.org/@alice",shouldMatch:!0},{uri:"https://domain.org/@alice/",shouldMatch:!0},{uri:"https://domain.org/alice",shouldMatch:!1}]},{}],31:[function(e,t,r){e("bent")("GET");const i=e("query-string"),o=e("../utils"),n=/^matrix\:u\/(\@[^:]*\:[^?]*)(\?.*)?/;r.reURI=n,r.processURI=(e,t)=>{t||(t={});const r=e.match(n);let s=null;if(r[2]){const e=i.parse(r[2]);"org.keyoxide.e"in e&&"org.keyoxide.r"in e&&(s=o.generateProxyURL("matrix",[e["org.keyoxide.r"],e["org.keyoxide.e"]],t))}return{serviceprovider:{type:"communication",name:"matrix"},profile:{display:r[1],uri:e,qr:null},proof:{uri:s,fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:["data","content","body"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"matrix:u/@alice:matrix.domain.org",shouldMatch:!0},{uri:"matrix:u/@alice:matrix.domain.org?org.keyoxide.r=!123:domain.org&org.keyoxide.e=$123",shouldMatch:!0},{uri:"xmpp:alice@domain.org",shouldMatch:!1},{uri:"https://domain.org/@alice",shouldMatch:!1}]},{"../utils":37,bent:1,"query-string":10}],32:[function(e,t,r){e("bent")("GET");const i=/^https:\/\/(.*)/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});return{serviceprovider:{type:"web",name:"owncast"},profile:{display:e.match(i)[1],uri:e,qr:null},proof:{uri:e+"/api/config",fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"fingerprint",path:["socialHandles","url"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://live.domain.org",shouldMatch:!0},{uri:"https://live.domain.org/",shouldMatch:!0},{uri:"https://domain.org/live",shouldMatch:!0},{uri:"https://domain.org/live/",shouldMatch:!0}]},{bent:1}],33:[function(e,t,r){const i=/^https:\/\/(?:www\.)?reddit\.com\/user\/(.*)\/comments\/(.*)\/(.*)\/?/;r.reURI=i,r.processURI=(e,t)=>{t||(t={});const r=e.match(i);return{serviceprovider:{type:"web",name:"reddit"},profile:{display:r[1],uri:"https://www.reddit.com/user/"+r[1],qr:null},proof:{uri:e,fetch:`https://www.reddit.com/user/${r[1]}/comments/${r[2]}.json`,useProxy:!0,format:"json"},claim:{fingerprint:null,format:"message",path:["data","children","data","selftext"],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"https://www.reddit.com/user/Alice/comments/123456/post",shouldMatch:!0},{uri:"https://www.reddit.com/user/Alice/comments/123456/post/",shouldMatch:!0},{uri:"https://reddit.com/user/Alice/comments/123456/post",shouldMatch:!0},{uri:"https://reddit.com/user/Alice/comments/123456/post/",shouldMatch:!0},{uri:"https://domain.org/user/Alice/comments/123456/post",shouldMatch:!1}]},{}],34:[function(e,t,r){const i=e("bent")("GET"),o=e("../serviceproviders"),n=e("../utils"),s=/^https:\/\/twitter\.com\/(.*)\/status\/([0-9]*)(?:\?.*)?/,a=async(e,t)=>{const r=e.proof.uri.match(s);if("always"!==t.proxyPolicy){if("twitterBearerToken"in t&&t.twitterBearerToken){const e=await i("https://api.twitter.com/1.1/statuses/show.json?id="+r[2],null,{Accept:"application/json",Authorization:"Bearer "+t.twitterBearerToken});return(await e.json()).text}if("nitterInstance"in t&&t.nitterInstance){e.proof.fetch=`https://${t.nitterInstance}/${r[1]}/status/${r[2]}`;return await o.proxyRequestHandler(e,t)}}return"never"!==t.proxyPolicy&&e.proof.fetch?i(n.generateProxyURL("twitter",r[2],t),null,{Accept:"application/json"}).then((async e=>await e.json())).then((e=>e.data.text)).catch((e=>{reject(e)})):null};r.reURI=s,r.processURI=(e,t)=>{t||(t={});const r=e.match(s);return{serviceprovider:{type:"web",name:"twitter"},profile:{display:"@"+r[1],uri:"https://twitter.com/"+r[1],qr:null},proof:{uri:e,fetch:n.generateProxyURL("twitter",r[2],t),useProxy:!1,format:"text"},claim:{fingerprint:null,format:"message",path:[],relation:"contains"},customRequestHandler:a}},r.tests=[{uri:"https://twitter.com/alice/status/1234567890123456789",shouldMatch:!0},{uri:"https://twitter.com/alice/status/1234567890123456789/",shouldMatch:!0},{uri:"https://domain.org/alice/status/1234567890123456789",shouldMatch:!1}]},{"../serviceproviders":18,"../utils":37,bent:1}],35:[function(e,t,r){const i=e("../utils"),o=/^xmpp:([a-zA-Z0-9\.\-\_]*)@([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/;r.reURI=o,r.processURI=(e,t)=>{t||(t={});const r=e.match(o);return{serviceprovider:{type:"communication",name:"xmpp"},profile:{display:`${r[1]}@${r[2]}`,uri:e,qr:e},proof:{uri:i.generateProxyURL("xmpp",`${r[1]}@${r[2]}`,t),fetch:null,useProxy:!1,format:"json"},claim:{fingerprint:null,format:"message",path:[],relation:"contains"},customRequestHandler:null}},r.tests=[{uri:"xmpp:alice@domain.org",shouldMatch:!0},{uri:"xmpp:alice@domain.org?omemo-sid-123456789=A1B2C3D4E5F6G7H8I9",shouldMatch:!0},{uri:"https://domain.org",shouldMatch:!1}]},{"../utils":37}],36:[function(e,t,r){(function(t){(function(){const i="undefined"!=typeof window?window.openpgp:void 0!==t?t.openpgp:null,o=(e("merge-options"),e("./claims")),n=e("./keys");r.verify=(e,t)=>new Promise((async(r,s)=>{let a,c=[];try{a=await i.cleartext.readArmored(e)}catch(e){return c.push("invalid_signature"),void s({errors:c})}const l=a.signature.packets[0].issuerKeyId.toHex(),u=a.signature.packets[0].signersUserId,p=a.signature.packets[0].preferredKeyServer||"https://keys.openpgp.org/",d=a.getText();let f,h,m=[],y=[];if(d.split("\n").forEach(((e,t)=>{const r=e.match(/^([a-zA-Z0-9]*)\=(.*)$/i);if(r)switch(r[1].toLowerCase()){case"key":m.push(r[2]);break;case"proof":y.push(r[2])}})),m.length>0)try{h=m[0],f=await n.fetch.uri(h)}catch(e){}if(!f&&u)try{h="wkd:"+u,f=await n.fetch.uri(h)}catch(e){}if(!f)try{h=`hkp:${p.match(/^(.*\:\/\/)?([^/]*)(?:\/)?$/i)[2]}:${l||u}`,f=await n.fetch.uri(h)}catch(e){return c.push("key_not_found"),void s({errors:c})}const g=f.keyPacket.getFingerprint();try{const e=await a.verify([f]);await e[0].verified}catch(e){return c.push("invalid_signature_verification"),void s({errors:c})}const v=await o.verify(y,g,t);r({errors:c,signature:{data:a.signature,issuerKeyId:l,signersUserId:u,preferredKeyServer:p},publicKey:{data:f,uri:h,fingerprint:g},text:d,claims:v})}))}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./claims":15,"./keys":17,"merge-options":7}],37:[function(e,t,r){r.generateProxyURL=(e,t,r)=>{if(!r||!r.doipProxyHostname)return null;let i="";return"xmpp"==e&&(i+="/DESC"),Array.isArray(t)||(t=[t]),t.map((e=>{encodeURIComponent(e)})),`https://${r.doipProxyHostname}/api/1/get/${e}/${t.join("/")}${i}`},r.generateClaim=(e,t)=>{switch(t){case"uri":return"openpgp4fpr:"+e;case"message":return`[Verifying my OpenPGP key: openpgp4fpr:${e}]`;case"fingerprint":return e;default:throw new Error("No valid claim format")}}},{}]},{},[16])(16)})); diff --git a/docs/_coverpage.md b/docs/_coverpage.md index 5b9ad08..fd02b2f 100644 --- a/docs/_coverpage.md +++ b/docs/_coverpage.md @@ -1,4 +1,4 @@ -# doip.js 0.10.5 +# doip.js 0.11.0 diff --git a/docs/changelog.md b/docs/changelog.md index 48942e9..c73e49c 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,15 @@ # Changelog +## [0.11.0] + +[2021-03-05](https://codeberg.org/keyoxide/doipjs/releases/tag/0.11.0) + +## Added +- IRC service provider +- Matrix service provider +## Fixed +- Handling of requests without URI + ## [0.10.5] [2021-03-02](https://codeberg.org/keyoxide/doipjs/releases/tag/0.10.5) diff --git a/docs/installation.md b/docs/installation.md index fc27419..c8aeff9 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -15,7 +15,7 @@ npm install --save doipjs Install on website by including the following HTML snippet: ```html - + ``` Next step: [quick start (Node.js)](quickstart-nodejs.md) and [quick start (browser)](quickstart-browser.md) diff --git a/package.json b/package.json index e3f7a65..fee7959 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "doipjs", - "version": "0.10.5", + "version": "0.11.0", "description": "Decentralized OpenPGP Identity Proofs library in Node.js", "main": "src/index.js", "dependencies": {