mirror of
https://codeberg.org/keyoxide/doipjs.git
synced 2024-12-23 06:59:29 -07:00
1750 lines
44 KiB
JavaScript
1750 lines
44 KiB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.doip = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
|
'use strict'
|
|
/* global fetch, btoa, Headers */
|
|
const core = require('./core')
|
|
|
|
class StatusError extends Error {
|
|
constructor (res, ...params) {
|
|
super(...params)
|
|
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, StatusError)
|
|
}
|
|
|
|
this.name = 'StatusError'
|
|
this.message = res.statusMessage
|
|
this.statusCode = res.status
|
|
this.res = res
|
|
this.json = res.json.bind(res)
|
|
this.text = res.text.bind(res)
|
|
this.arrayBuffer = res.arrayBuffer.bind(res)
|
|
let buffer
|
|
const get = () => {
|
|
if (!buffer) buffer = this.arrayBuffer()
|
|
return buffer
|
|
}
|
|
Object.defineProperty(this, 'responseBody', { get })
|
|
// match Node.js headers object
|
|
this.headers = {}
|
|
for (const [key, value] of res.headers.entries()) {
|
|
this.headers[key.toLowerCase()] = value
|
|
}
|
|
}
|
|
}
|
|
|
|
const mkrequest = (statusCodes, method, encoding, headers, baseurl) => async (_url, body, _headers = {}) => {
|
|
_url = baseurl + (_url || '')
|
|
let parsed = new URL(_url)
|
|
|
|
if (!headers) headers = {}
|
|
if (parsed.username) {
|
|
headers.Authorization = 'Basic ' + btoa(parsed.username + ':' + parsed.password)
|
|
parsed = new URL(parsed.protocol + '//' + parsed.host + parsed.pathname + parsed.search)
|
|
}
|
|
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
|
|
throw new Error(`Unknown protocol, ${parsed.protocol}`)
|
|
}
|
|
|
|
if (body) {
|
|
if (body instanceof ArrayBuffer ||
|
|
ArrayBuffer.isView(body) ||
|
|
typeof body === 'string'
|
|
) {
|
|
// noop
|
|
} else if (typeof body === 'object') {
|
|
body = JSON.stringify(body)
|
|
headers['Content-Type'] = 'application/json'
|
|
} else {
|
|
throw new Error('Unknown body type.')
|
|
}
|
|
}
|
|
|
|
_headers = new Headers({ ...(headers || {}), ..._headers })
|
|
|
|
const resp = await fetch(parsed, { method, headers: _headers, body })
|
|
resp.statusCode = resp.status
|
|
|
|
if (!statusCodes.has(resp.status)) {
|
|
throw new StatusError(resp)
|
|
}
|
|
|
|
if (encoding === 'json') return resp.json()
|
|
else if (encoding === 'buffer') return resp.arrayBuffer()
|
|
else if (encoding === 'string') return resp.text()
|
|
else return resp
|
|
}
|
|
|
|
module.exports = core(mkrequest)
|
|
|
|
},{"./core":2}],2:[function(require,module,exports){
|
|
'use strict'
|
|
const encodings = new Set(['json', 'buffer', 'string'])
|
|
|
|
module.exports = mkrequest => (...args) => {
|
|
const statusCodes = new Set()
|
|
let method
|
|
let encoding
|
|
let headers
|
|
let baseurl = ''
|
|
|
|
args.forEach(arg => {
|
|
if (typeof arg === 'string') {
|
|
if (arg.toUpperCase() === arg) {
|
|
if (method) {
|
|
const msg = `Can't set method to ${arg}, already set to ${method}.`
|
|
throw new Error(msg)
|
|
} else {
|
|
method = arg
|
|
}
|
|
} else if (arg.startsWith('http:') || arg.startsWith('https:')) {
|
|
baseurl = arg
|
|
} else {
|
|
if (encodings.has(arg)) {
|
|
encoding = arg
|
|
} else {
|
|
throw new Error(`Unknown encoding, ${arg}`)
|
|
}
|
|
}
|
|
} else if (typeof arg === 'number') {
|
|
statusCodes.add(arg)
|
|
} else if (typeof arg === 'object') {
|
|
if (Array.isArray(arg) || arg instanceof Set) {
|
|
arg.forEach(code => statusCodes.add(code))
|
|
} else {
|
|
if (headers) {
|
|
throw new Error('Cannot set headers twice.')
|
|
}
|
|
headers = arg
|
|
}
|
|
} else {
|
|
throw new Error(`Unknown type: ${typeof arg}`)
|
|
}
|
|
})
|
|
|
|
if (!method) method = 'GET'
|
|
if (statusCodes.size === 0) {
|
|
statusCodes.add(200)
|
|
}
|
|
|
|
return mkrequest(statusCodes, method, encoding, headers, baseurl)
|
|
}
|
|
|
|
},{}],3:[function(require,module,exports){
|
|
|
|
},{}],4:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
module.exports = value => {
|
|
if (Object.prototype.toString.call(value) !== '[object Object]') {
|
|
return false;
|
|
}
|
|
|
|
const prototype = Object.getPrototypeOf(value);
|
|
return prototype === null || prototype === Object.prototype;
|
|
};
|
|
|
|
},{}],5:[function(require,module,exports){
|
|
'use strict';
|
|
const isOptionObject = require('is-plain-obj');
|
|
|
|
const {hasOwnProperty} = Object.prototype;
|
|
const {propertyIsEnumerable} = Object;
|
|
const defineProperty = (object, name, value) => Object.defineProperty(object, name, {
|
|
value,
|
|
writable: true,
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
|
|
const globalThis = this;
|
|
const defaultMergeOptions = {
|
|
concatArrays: false,
|
|
ignoreUndefined: false
|
|
};
|
|
|
|
const getEnumerableOwnPropertyKeys = value => {
|
|
const keys = [];
|
|
|
|
for (const key in value) {
|
|
if (hasOwnProperty.call(value, key)) {
|
|
keys.push(key);
|
|
}
|
|
}
|
|
|
|
/* istanbul ignore else */
|
|
if (Object.getOwnPropertySymbols) {
|
|
const symbols = Object.getOwnPropertySymbols(value);
|
|
|
|
for (const symbol of symbols) {
|
|
if (propertyIsEnumerable.call(value, symbol)) {
|
|
keys.push(symbol);
|
|
}
|
|
}
|
|
}
|
|
|
|
return keys;
|
|
};
|
|
|
|
function clone(value) {
|
|
if (Array.isArray(value)) {
|
|
return cloneArray(value);
|
|
}
|
|
|
|
if (isOptionObject(value)) {
|
|
return cloneOptionObject(value);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
function cloneArray(array) {
|
|
const result = array.slice(0, 0);
|
|
|
|
getEnumerableOwnPropertyKeys(array).forEach(key => {
|
|
defineProperty(result, key, clone(array[key]));
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
function cloneOptionObject(object) {
|
|
const result = Object.getPrototypeOf(object) === null ? Object.create(null) : {};
|
|
|
|
getEnumerableOwnPropertyKeys(object).forEach(key => {
|
|
defineProperty(result, key, clone(object[key]));
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @param {*} merged already cloned
|
|
* @param {*} source something to merge
|
|
* @param {string[]} keys keys to merge
|
|
* @param {Object} config Config Object
|
|
* @returns {*} cloned Object
|
|
*/
|
|
const mergeKeys = (merged, source, keys, config) => {
|
|
keys.forEach(key => {
|
|
if (typeof source[key] === 'undefined' && config.ignoreUndefined) {
|
|
return;
|
|
}
|
|
|
|
// Do not recurse into prototype chain of merged
|
|
if (key in merged && merged[key] !== Object.getPrototypeOf(merged)) {
|
|
defineProperty(merged, key, merge(merged[key], source[key], config));
|
|
} else {
|
|
defineProperty(merged, key, clone(source[key]));
|
|
}
|
|
});
|
|
|
|
return merged;
|
|
};
|
|
|
|
/**
|
|
* @param {*} merged already cloned
|
|
* @param {*} source something to merge
|
|
* @param {Object} config Config Object
|
|
* @returns {*} cloned Object
|
|
*
|
|
* see [Array.prototype.concat ( ...arguments )](http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat)
|
|
*/
|
|
const concatArrays = (merged, source, config) => {
|
|
let result = merged.slice(0, 0);
|
|
let resultIndex = 0;
|
|
|
|
[merged, source].forEach(array => {
|
|
const indices = [];
|
|
|
|
// `result.concat(array)` with cloning
|
|
for (let k = 0; k < array.length; k++) {
|
|
if (!hasOwnProperty.call(array, k)) {
|
|
continue;
|
|
}
|
|
|
|
indices.push(String(k));
|
|
|
|
if (array === merged) {
|
|
// Already cloned
|
|
defineProperty(result, resultIndex++, array[k]);
|
|
} else {
|
|
defineProperty(result, resultIndex++, clone(array[k]));
|
|
}
|
|
}
|
|
|
|
// Merge non-index keys
|
|
result = mergeKeys(result, array, getEnumerableOwnPropertyKeys(array).filter(key => !indices.includes(key)), config);
|
|
});
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* @param {*} merged already cloned
|
|
* @param {*} source something to merge
|
|
* @param {Object} config Config Object
|
|
* @returns {*} cloned Object
|
|
*/
|
|
function merge(merged, source, config) {
|
|
if (config.concatArrays && Array.isArray(merged) && Array.isArray(source)) {
|
|
return concatArrays(merged, source, config);
|
|
}
|
|
|
|
if (!isOptionObject(source) || !isOptionObject(merged)) {
|
|
return clone(source);
|
|
}
|
|
|
|
return mergeKeys(merged, source, getEnumerableOwnPropertyKeys(source), config);
|
|
}
|
|
|
|
module.exports = function (...options) {
|
|
const config = merge(clone(defaultMergeOptions), (this !== globalThis && this) || {}, defaultMergeOptions);
|
|
let merged = {_: {}};
|
|
|
|
for (const option of options) {
|
|
if (option === undefined) {
|
|
continue;
|
|
}
|
|
|
|
if (!isOptionObject(option)) {
|
|
throw new TypeError('`' + option + '` is not an Option Object');
|
|
}
|
|
|
|
merged = merge(merged, {_: option}, config);
|
|
}
|
|
|
|
return merged._;
|
|
};
|
|
|
|
},{"is-plain-obj":4}],6:[function(require,module,exports){
|
|
(function(module) {
|
|
'use strict';
|
|
|
|
module.exports.is_uri = is_iri;
|
|
module.exports.is_http_uri = is_http_iri;
|
|
module.exports.is_https_uri = is_https_iri;
|
|
module.exports.is_web_uri = is_web_iri;
|
|
// Create aliases
|
|
module.exports.isUri = is_iri;
|
|
module.exports.isHttpUri = is_http_iri;
|
|
module.exports.isHttpsUri = is_https_iri;
|
|
module.exports.isWebUri = is_web_iri;
|
|
|
|
|
|
// private function
|
|
// internal URI spitter method - direct from RFC 3986
|
|
var splitUri = function(uri) {
|
|
var splitted = uri.match(/(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/);
|
|
return splitted;
|
|
};
|
|
|
|
function is_iri(value) {
|
|
if (!value) {
|
|
return;
|
|
}
|
|
|
|
// check for illegal characters
|
|
if (/[^a-z0-9\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=\.\-\_\~\%]/i.test(value)) return;
|
|
|
|
// check for hex escapes that aren't complete
|
|
if (/%[^0-9a-f]/i.test(value)) return;
|
|
if (/%[0-9a-f](:?[^0-9a-f]|$)/i.test(value)) return;
|
|
|
|
var splitted = [];
|
|
var scheme = '';
|
|
var authority = '';
|
|
var path = '';
|
|
var query = '';
|
|
var fragment = '';
|
|
var out = '';
|
|
|
|
// from RFC 3986
|
|
splitted = splitUri(value);
|
|
scheme = splitted[1];
|
|
authority = splitted[2];
|
|
path = splitted[3];
|
|
query = splitted[4];
|
|
fragment = splitted[5];
|
|
|
|
// scheme and path are required, though the path can be empty
|
|
if (!(scheme && scheme.length && path.length >= 0)) return;
|
|
|
|
// if authority is present, the path must be empty or begin with a /
|
|
if (authority && authority.length) {
|
|
if (!(path.length === 0 || /^\//.test(path))) return;
|
|
} else {
|
|
// if authority is not present, the path must not start with //
|
|
if (/^\/\//.test(path)) return;
|
|
}
|
|
|
|
// scheme must begin with a letter, then consist of letters, digits, +, ., or -
|
|
if (!/^[a-z][a-z0-9\+\-\.]*$/.test(scheme.toLowerCase())) return;
|
|
|
|
// re-assemble the URL per section 5.3 in RFC 3986
|
|
out += scheme + ':';
|
|
if (authority && authority.length) {
|
|
out += '//' + authority;
|
|
}
|
|
|
|
out += path;
|
|
|
|
if (query && query.length) {
|
|
out += '?' + query;
|
|
}
|
|
|
|
if (fragment && fragment.length) {
|
|
out += '#' + fragment;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
function is_http_iri(value, allowHttps) {
|
|
if (!is_iri(value)) {
|
|
return;
|
|
}
|
|
|
|
var splitted = [];
|
|
var scheme = '';
|
|
var authority = '';
|
|
var path = '';
|
|
var port = '';
|
|
var query = '';
|
|
var fragment = '';
|
|
var out = '';
|
|
|
|
// from RFC 3986
|
|
splitted = splitUri(value);
|
|
scheme = splitted[1];
|
|
authority = splitted[2];
|
|
path = splitted[3];
|
|
query = splitted[4];
|
|
fragment = splitted[5];
|
|
|
|
if (!scheme) return;
|
|
|
|
if(allowHttps) {
|
|
if (scheme.toLowerCase() != 'https') return;
|
|
} else {
|
|
if (scheme.toLowerCase() != 'http') return;
|
|
}
|
|
|
|
// fully-qualified URIs must have an authority section that is
|
|
// a valid host
|
|
if (!authority) {
|
|
return;
|
|
}
|
|
|
|
// enable port component
|
|
if (/:(\d+)$/.test(authority)) {
|
|
port = authority.match(/:(\d+)$/)[0];
|
|
authority = authority.replace(/:\d+$/, '');
|
|
}
|
|
|
|
out += scheme + ':';
|
|
out += '//' + authority;
|
|
|
|
if (port) {
|
|
out += port;
|
|
}
|
|
|
|
out += path;
|
|
|
|
if(query && query.length){
|
|
out += '?' + query;
|
|
}
|
|
|
|
if(fragment && fragment.length){
|
|
out += '#' + fragment;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
function is_https_iri(value) {
|
|
return is_http_iri(value, true);
|
|
}
|
|
|
|
function is_web_iri(value) {
|
|
return (is_http_iri(value) || is_https_iri(value));
|
|
}
|
|
|
|
})(module);
|
|
|
|
},{}],7:[function(require,module,exports){
|
|
const utils = require('./utils')
|
|
|
|
const runOnJson = (res, proofData, checkPath, checkClaim, checkRelation) => {
|
|
let re
|
|
|
|
if (res.isVerified || !proofData) {
|
|
return res
|
|
}
|
|
|
|
if (Array.isArray(proofData)) {
|
|
proofData.forEach((item, i) => {
|
|
res = runOnJson(res, item, checkPath, checkClaim, checkRelation)
|
|
})
|
|
return res
|
|
}
|
|
|
|
if (checkPath.length == 0) {
|
|
switch (checkRelation) {
|
|
default:
|
|
case 'contains':
|
|
re = new RegExp(checkClaim.replace('[', '\\[').replace(']', '\\]'), "gi")
|
|
res.isVerified = re.test(proofData.replace(/\r?\n|\r/, ''))
|
|
break
|
|
case 'equals':
|
|
res.isVerified = proofData.replace(/\r?\n|\r/, '').toLowerCase() == checkClaim.toLowerCase()
|
|
break
|
|
case 'oneOf':
|
|
re = new RegExp(checkClaim, "gi")
|
|
res.isVerified = re.test(proofData.join("|"))
|
|
break
|
|
}
|
|
return res
|
|
}
|
|
|
|
try {
|
|
checkPath[0] in proofData
|
|
} catch(e) {
|
|
res.errors.push('err_data_structure_incorrect')
|
|
return res
|
|
}
|
|
|
|
res = runOnJson(res, proofData[checkPath[0]], checkPath.slice(1), checkClaim, checkRelation)
|
|
return res
|
|
}
|
|
|
|
const run = (proofData, spData) => {
|
|
let res = {
|
|
isVerified: false,
|
|
errors: []
|
|
}
|
|
|
|
switch (spData.proof.format) {
|
|
case 'json':
|
|
res = runOnJson(res, proofData, spData.claim.path, utils.generateClaim(spData.claim.fingerprint, spData.claim.format), spData.claim.relation)
|
|
break
|
|
case 'text':
|
|
re = new RegExp(utils.generateClaim(spData.claim.fingerprint, spData.claim.format), "gi")
|
|
res = re.test(proofData.replace(/\r?\n|\r/, ''))
|
|
break
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
exports.run = run
|
|
|
|
},{"./utils":24}],8:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 mergeOptions = require('merge-options')
|
|
const validUrl = require('valid-url')
|
|
const serviceproviders = require('./serviceproviders')
|
|
const claimVerification = require('./claimVerification')
|
|
const utils = require('./utils')
|
|
|
|
const verify = async (uri, fingerprint, opts) => {
|
|
if (!fingerprint) { fingerprint = null }
|
|
if (!opts) { opts = {} }
|
|
|
|
const defaultOpts = {
|
|
returnMatchesOnly: false,
|
|
proxyPolicy: 'adaptive',
|
|
doipProxyHostname: 'proxy.keyoxide.org'
|
|
}
|
|
opts = mergeOptions(defaultOpts, opts)
|
|
|
|
if (!validUrl.isUri(uri)) {
|
|
throw new Error('Not a valid URI')
|
|
}
|
|
|
|
const spMatches = serviceproviders.match(uri, opts)
|
|
|
|
if ('returnMatchesOnly' in opts && opts.returnMatchesOnly) {
|
|
return spMatches
|
|
}
|
|
let claimVerificationDone = false, claimVerificationResult, sp, iSp = 0, res, proofData, spData
|
|
while (!claimVerificationDone && iSp < spMatches.length) {
|
|
spData = spMatches[iSp]
|
|
spData.claim.fingerprint = fingerprint
|
|
|
|
res = null
|
|
|
|
if (spData.customRequestHandler instanceof Function) {
|
|
proofData = await spData.customRequestHandler(spData, opts)
|
|
} else if (!spData.proof.useProxy || 'proxyPolicy' in opts && !opts.useProxyWhenNeeded) {
|
|
proofData = await serviceproviders.directRequestHandler(spData, opts)
|
|
} else {
|
|
proofData = await serviceproviders.proxyRequestHandler(spData, opts)
|
|
}
|
|
|
|
if (proofData) {
|
|
claimVerificationResult = claimVerification.run(proofData, spData)
|
|
|
|
if (claimVerificationResult.errors.length == 0) {
|
|
claimVerificationDone = true
|
|
}
|
|
}
|
|
|
|
iSp++
|
|
}
|
|
|
|
if (!claimVerificationResult) {
|
|
claimVerificationResult = {
|
|
isVerified: false
|
|
}
|
|
}
|
|
|
|
return {
|
|
isVerified: claimVerificationResult.isVerified,
|
|
serviceproviderData: spData
|
|
}
|
|
}
|
|
|
|
exports.verify = verify
|
|
exports.serviceproviders = serviceproviders
|
|
exports.claimVerification = claimVerification
|
|
exports.utils = utils
|
|
|
|
},{"./claimVerification":7,"./serviceproviders":9,"./utils":24,"merge-options":5,"valid-url":6}],9:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 utils = require('./utils')
|
|
|
|
const list = [
|
|
'dns',
|
|
'xmpp',
|
|
'twitter',
|
|
'reddit',
|
|
'liberapay',
|
|
'hackernews',
|
|
'lobsters',
|
|
'devto',
|
|
'gitea',
|
|
'gitlab',
|
|
'github',
|
|
'mastodon',
|
|
'fediverse',
|
|
'discourse',
|
|
]
|
|
|
|
const data = {
|
|
dns: require('./serviceproviders/dns'),
|
|
xmpp: require('./serviceproviders/xmpp'),
|
|
twitter: require('./serviceproviders/twitter'),
|
|
reddit: require('./serviceproviders/reddit'),
|
|
liberapay: require('./serviceproviders/liberapay'),
|
|
hackernews: require('./serviceproviders/hackernews'),
|
|
lobsters: require('./serviceproviders/lobsters'),
|
|
devto: require('./serviceproviders/devto'),
|
|
gitea: require('./serviceproviders/gitea'),
|
|
gitlab: require('./serviceproviders/gitlab'),
|
|
github: require('./serviceproviders/github'),
|
|
mastodon: require('./serviceproviders/mastodon'),
|
|
fediverse: require('./serviceproviders/fediverse'),
|
|
discourse: require('./serviceproviders/discourse'),
|
|
}
|
|
|
|
const match = (uri, opts) => {
|
|
let matches = [], sp
|
|
|
|
list.forEach((spName, i) => {
|
|
sp = data[spName]
|
|
if (sp.reURI.test(uri)) {
|
|
matches.push(sp.processURI(uri, opts))
|
|
}
|
|
})
|
|
|
|
return matches
|
|
}
|
|
|
|
const directRequestHandler = async (spData, opts) => {
|
|
const res = await req(spData.proof.fetch ? spData.proof.fetch : spData.proof.uri, null, { Accept: 'application/json' })
|
|
|
|
switch (spData.proof.format) {
|
|
case 'json':
|
|
return await res.json()
|
|
break
|
|
case 'text':
|
|
return await res.text()
|
|
break
|
|
default:
|
|
throw new Error('No specified proof data format')
|
|
break
|
|
}
|
|
}
|
|
|
|
const proxyRequestHandler = async (spData, opts) => {
|
|
const url = spData.proof.fetch ? spData.proof.fetch : spData.proof.uri
|
|
const res = await req(utils.generateProxyURL(spData.proof.format, url, opts), null, { Accept: 'application/json' })
|
|
const json = await res.json()
|
|
return json.content
|
|
}
|
|
|
|
exports.list = list
|
|
exports.data = data
|
|
exports.match = match
|
|
exports.directRequestHandler = directRequestHandler
|
|
exports.proxyRequestHandler = proxyRequestHandler
|
|
|
|
},{"./serviceproviders/devto":10,"./serviceproviders/discourse":11,"./serviceproviders/dns":12,"./serviceproviders/fediverse":13,"./serviceproviders/gitea":14,"./serviceproviders/github":15,"./serviceproviders/gitlab":16,"./serviceproviders/hackernews":17,"./serviceproviders/liberapay":18,"./serviceproviders/lobsters":19,"./serviceproviders/mastodon":20,"./serviceproviders/reddit":21,"./serviceproviders/twitter":22,"./serviceproviders/xmpp":23,"./utils":24,"bent":1}],10:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/dev\.to\/(.*)\/(.*)\/?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'devto'
|
|
},
|
|
profile: {
|
|
display: match[1],
|
|
uri: `https://dev.to/${match[1]}`,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: uri,
|
|
fetch: `https://dev.to/api/articles/${match[1]}/${match[2]}`,
|
|
useProxy: false,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'message',
|
|
path: ['body_markdown'],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://dev.to/alice/post',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://dev.to/alice/post/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/alice/post',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],11:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/(.*)\/u\/(.*)\/?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'discourse'
|
|
},
|
|
profile: {
|
|
display: `${match[2]}@${match[1]}`,
|
|
uri: uri,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: uri,
|
|
fetch: `https://${match[1]}/u/${match[2]}.json`,
|
|
useProxy: true,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'message',
|
|
path: ['user', 'bio_raw'],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://domain.org/u/alice',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/u/alice/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/alice',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],12:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 dns = require('dns')
|
|
const bent = require('bent')
|
|
const req = bent('GET')
|
|
const utils = require('../utils')
|
|
const reURI = /^dns:([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/
|
|
|
|
const customRequestHandler = async (spData, opts) => {
|
|
if (('resolveTxt' in dns)) {
|
|
const prom = async () => {
|
|
return new Promise((resolve, reject) => {
|
|
dns.resolveTxt(spData.profile.display, (err, records) => {
|
|
if (err) reject(err)
|
|
resolve(records)
|
|
})
|
|
})
|
|
}
|
|
return {
|
|
hostname: spData.profile.display,
|
|
records: {
|
|
txt: await prom()
|
|
}
|
|
}
|
|
} else {
|
|
const res = await req(spData.proof.uri, null, { Accept: 'application/json' })
|
|
const json = await res.json()
|
|
return json
|
|
}
|
|
}
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'dns'
|
|
},
|
|
profile: {
|
|
display: match[1],
|
|
uri: `https://${match[1]}`,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: utils.generateProxyURL('dns', match[1]),
|
|
fetch: null,
|
|
useProxy: false,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'uri',
|
|
path: ['records', 'txt'],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: customRequestHandler
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'dns:domain.org',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'dns:domain.org?type=TXT',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{"../utils":24,"bent":1,"dns":3}],13:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/(.*)\/users\/(.*)\/?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'fediverse'
|
|
},
|
|
profile: {
|
|
display: `@${match[2]}@${match[1]}`,
|
|
uri: uri,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: uri,
|
|
fetch: null,
|
|
useProxy: false,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'fingerprint',
|
|
path: ['summary'],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://domain.org/users/alice',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/users/alice/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/alice',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],14:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/(.*)\/(.*)\/gitea_proof\/?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'gitea'
|
|
},
|
|
profile: {
|
|
display: `${match[2]}@${match[1]}`,
|
|
uri: `https://${match[1]}/${match[2]}`,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: uri,
|
|
fetch: `https://${match[1]}/api/v1/repos/${match[2]}/gitea_proof`,
|
|
useProxy: true,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'message',
|
|
path: ['description'],
|
|
relation: 'equals'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://domain.org/alice/gitea_proof',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/alice/gitea_proof/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/alice/other_proof',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],15:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/gist\.github\.com\/(.*)\/(.*)\/?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'github'
|
|
},
|
|
profile: {
|
|
display: match[1],
|
|
uri: `https://github.com/${match[1]}`,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: uri,
|
|
fetch: `https://api.github.com/gists/${match[2]}`,
|
|
useProxy: false,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'message',
|
|
path: ['files', 'openpgp.md', 'content'],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://gist.github.com/Alice/123456789',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://gist.github.com/Alice/123456789/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/Alice/123456789',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],16:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/(.*)\/(.*)\/gitlab_proof\/?/
|
|
|
|
const customRequestHandler = async (spData, opts) => {
|
|
const match = spData.proof.uri.match(reURI)
|
|
|
|
const urlUser = `https://${match[1]}/api/v4/users?username=${match[2]}`
|
|
const resUser = await req(urlUser, 'json', { Accept: 'application/json' })
|
|
const jsonUser = await resUser.json()
|
|
|
|
const user = jsonUser.find(user => user.username === match[2])
|
|
if (!user) {
|
|
throw new Error(`No user with username ${match[2]}`);
|
|
}
|
|
|
|
const urlProject = `https://${match[1]}/api/v4/users/${user.id}/projects`
|
|
const resProject = await req(urlProject, {}, { Accept: 'application/json' })
|
|
const jsonProject = await resProject.json()
|
|
|
|
const project = jsonProject.find(proj => proj.path === 'gitlab_proof')
|
|
if (!project) {
|
|
throw new Error(`No project at ${spData.proof.uri}`);
|
|
}
|
|
|
|
return project
|
|
}
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'gitlab'
|
|
},
|
|
profile: {
|
|
display: `${match[2]}@${match[1]}`,
|
|
uri: `https://${match[1]}/${match[2]}`,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: uri,
|
|
fetch: null,
|
|
useProxy: false,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'message',
|
|
path: ['description'],
|
|
relation: 'equals'
|
|
},
|
|
customRequestHandler: customRequestHandler
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://gitlab.domain.org/alice/gitlab_proof',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://gitlab.domain.org/alice/gitlab_proof/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/alice/other_proof',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{"bent":1}],17:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/news\.ycombinator\.com\/user\?id=(.*)\/?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'hackernews'
|
|
},
|
|
profile: {
|
|
display: match[1],
|
|
uri: uri,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: `https://hacker-news.firebaseio.com/v0/user/${match[1]}.json`,
|
|
fetch: null,
|
|
useProxy: true,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'uri',
|
|
path: ['about'],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://news.ycombinator.com/user?id=Alice',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://news.ycombinator.com/user?id=Alice/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/user?id=Alice',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],18:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/liberapay\.com\/(.*)\/?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'liberapay'
|
|
},
|
|
profile: {
|
|
display: match[1],
|
|
uri: uri,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: uri,
|
|
fetch: `https://liberapay.com/${match[1]}/public.json`,
|
|
useProxy: false,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'message',
|
|
path: ['statements', 'content'],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://liberapay.com/alice',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://liberapay.com/alice/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/alice',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],19:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/lobste\.rs\/u\/(.*)\/?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'lobsters'
|
|
},
|
|
profile: {
|
|
display: match[1],
|
|
uri: uri,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: `https://lobste.rs/u/${match[1]}.json`,
|
|
fetch: null,
|
|
useProxy: true,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'message',
|
|
path: ['about'],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://lobste.rs/u/Alice',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://lobste.rs/u/Alice/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/u/Alice',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],20:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/(.*)\/@(.*)\/?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'mastodon'
|
|
},
|
|
profile: {
|
|
display: `@${match[2]}@${match[1]}`,
|
|
uri: uri,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: uri,
|
|
fetch: null,
|
|
useProxy: false,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'fingerprint',
|
|
path: ['attachment', 'value'],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://domain.org/@alice',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/@alice/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/alice',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],21:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/(?:www\.)?reddit\.com\/user\/(.*)\/comments\/(.*)\/(.*)\/?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'reddit'
|
|
},
|
|
profile: {
|
|
display: match[1],
|
|
uri: `https://www.reddit.com/user/${match[1]}`,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: uri,
|
|
fetch: `https://www.reddit.com/user/${match[1]}/comments/${match[2]}.json`,
|
|
useProxy: true,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'message',
|
|
path: ['data', 'children', 'data', 'selftext'],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://www.reddit.com/user/Alice/comments/123456/post',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://www.reddit.com/user/Alice/comments/123456/post/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://reddit.com/user/Alice/comments/123456/post',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://reddit.com/user/Alice/comments/123456/post/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/user/Alice/comments/123456/post',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],22:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^https:\/\/twitter\.com\/(.*)\/status\/([0-9]*)(?:\?.*)?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'web',
|
|
name: 'twitter'
|
|
},
|
|
profile: {
|
|
display: `@${match[1]}`,
|
|
uri: `https://twitter.com/${match[1]}`,
|
|
qr: null
|
|
},
|
|
proof: {
|
|
uri: uri,
|
|
fetch: `https://mobile.twitter.com/${match[1]}/status/${match[2]}`,
|
|
useProxy: false,
|
|
format: 'text'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'message',
|
|
path: [],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'https://twitter.com/alice/status/1234567890123456789',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://twitter.com/alice/status/1234567890123456789/',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org/alice/status/1234567890123456789',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],23:[function(require,module,exports){
|
|
/*
|
|
Copyright 2020 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 reURI = /^xmpp:([a-zA-Z0-9\.\-\_]*)@([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/
|
|
|
|
const processURI = (uri, opts) => {
|
|
if (!opts) { opts = {} }
|
|
const match = uri.match(reURI)
|
|
|
|
return {
|
|
serviceprovider: {
|
|
type: 'communication',
|
|
name: 'xmpp'
|
|
},
|
|
profile: {
|
|
display: `${match[1]}@${match[2]}`,
|
|
uri: uri,
|
|
qr: uri
|
|
},
|
|
proof: {
|
|
uri: 'xmppVcardServerDomain' in opts
|
|
? `https://${opts.xmppVcardServerDomain}/api/vcard/${match[1]}@${match[2]}/DESC`
|
|
: null,
|
|
fetch: null,
|
|
useProxy: false,
|
|
format: 'json'
|
|
},
|
|
claim: {
|
|
fingerprint: null,
|
|
format: 'message',
|
|
path: [],
|
|
relation: 'contains'
|
|
},
|
|
customRequestHandler: null
|
|
}
|
|
}
|
|
|
|
const tests = [
|
|
{
|
|
uri: 'xmpp:alice@domain.org',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'xmpp:alice@domain.org?omemo-sid-123456789=A1B2C3D4E5F6G7H8I9',
|
|
shouldMatch: true
|
|
},
|
|
{
|
|
uri: 'https://domain.org',
|
|
shouldMatch: false
|
|
}
|
|
]
|
|
|
|
exports.reURI = reURI
|
|
exports.processURI = processURI
|
|
exports.tests = tests
|
|
|
|
},{}],24:[function(require,module,exports){
|
|
const generateProxyURL = (type, url, opts) => {
|
|
if (!opts || !opts.doipProxyHostname) { return null }
|
|
return `https://${opts.doipProxyHostname}/api/1/get/${type}/${encodeURIComponent(url)}`
|
|
}
|
|
|
|
const generateClaim = (fingerprint, format) => {
|
|
switch (format) {
|
|
case 'uri':
|
|
return `openpgp4fpr:${fingerprint}`
|
|
break;
|
|
case 'message':
|
|
return `[Verifying my OpenPGP key: openpgp4fpr:${fingerprint}]`
|
|
break;
|
|
case 'fingerprint':
|
|
return fingerprint
|
|
break;
|
|
default:
|
|
throw new Error('No valid claim format')
|
|
}
|
|
}
|
|
|
|
exports.generateProxyURL = generateProxyURL
|
|
exports.generateClaim = generateClaim
|
|
|
|
},{}]},{},[8])(8)
|
|
});
|