UNPKG

@stellar/stellar-sdk

Version:

A library for working with the Stellar network, including communication with the Horizon and Soroban RPC servers.

1,544 lines (1,372 loc) 1.36 MB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define("StellarSdk", [], factory); else if(typeof exports === 'object') exports["StellarSdk"] = factory(); else root["StellarSdk"] = factory(); })(self, () => { return /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ 76: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ j: () => (/* binding */ Api) /* harmony export */ }); var Api; (function (_Api) { var GetTransactionStatus = function (GetTransactionStatus) { GetTransactionStatus["SUCCESS"] = "SUCCESS"; GetTransactionStatus["NOT_FOUND"] = "NOT_FOUND"; GetTransactionStatus["FAILED"] = "FAILED"; return GetTransactionStatus; }({}); _Api.GetTransactionStatus = GetTransactionStatus; function isSimulationError(sim) { return "error" in sim; } _Api.isSimulationError = isSimulationError; function isSimulationSuccess(sim) { return "transactionData" in sim; } _Api.isSimulationSuccess = isSimulationSuccess; function isSimulationRestore(sim) { return isSimulationSuccess(sim) && "restorePreamble" in sim && !!sim.restorePreamble.transactionData; } _Api.isSimulationRestore = isSimulationRestore; function isSimulationRaw(sim) { return !sim._parsed; } _Api.isSimulationRaw = isSimulationRaw; })(Api || (Api = {})); /***/ }), /***/ 121: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: () => (/* binding */ Utils) /* harmony export */ }); function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } var Utils = function () { function Utils() { _classCallCheck(this, Utils); } return _createClass(Utils, null, [{ key: "validateTimebounds", value: function validateTimebounds(transaction) { var gracePeriod = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; if (!transaction.timeBounds) { return false; } var now = Math.floor(Date.now() / 1000); var _transaction$timeBoun = transaction.timeBounds, minTime = _transaction$timeBoun.minTime, maxTime = _transaction$timeBoun.maxTime; return now >= Number.parseInt(minTime, 10) - gracePeriod && now <= Number.parseInt(maxTime, 10) + gracePeriod; } }, { key: "sleep", value: function sleep(ms) { return new Promise(function (resolve) { return setTimeout(resolve, ms); }); } }]); }(); /***/ }), /***/ 127: /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! * URI.js - Mutating URLs * URI Template Support - http://tools.ietf.org/html/rfc6570 * * Version: 1.19.11 * * Author: Rodney Rehm * Web: http://medialize.github.io/URI.js/ * * Licensed under * MIT License http://www.opensource.org/licenses/mit-license * */ (function (root, factory) { 'use strict'; // https://github.com/umdjs/umd/blob/master/returnExports.js if ( true && module.exports) { // Node module.exports = factory(__webpack_require__(193)); } else if (true) { // AMD. Register as an anonymous module. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(193)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } else // removed by dead control flow {} }(this, function (URI, root) { 'use strict'; // FIXME: v2.0.0 renamce non-camelCase properties to uppercase /*jshint camelcase: false */ // save current URITemplate variable, if any var _URITemplate = root && root.URITemplate; var hasOwn = Object.prototype.hasOwnProperty; function URITemplate(expression) { // serve from cache where possible if (URITemplate._cache[expression]) { return URITemplate._cache[expression]; } // Allow instantiation without the 'new' keyword if (!(this instanceof URITemplate)) { return new URITemplate(expression); } this.expression = expression; URITemplate._cache[expression] = this; return this; } function Data(data) { this.data = data; this.cache = {}; } var p = URITemplate.prototype; // list of operators and their defined options var operators = { // Simple string expansion '' : { prefix: '', separator: ',', named: false, empty_name_separator: false, encode : 'encode' }, // Reserved character strings '+' : { prefix: '', separator: ',', named: false, empty_name_separator: false, encode : 'encodeReserved' }, // Fragment identifiers prefixed by '#' '#' : { prefix: '#', separator: ',', named: false, empty_name_separator: false, encode : 'encodeReserved' }, // Name labels or extensions prefixed by '.' '.' : { prefix: '.', separator: '.', named: false, empty_name_separator: false, encode : 'encode' }, // Path segments prefixed by '/' '/' : { prefix: '/', separator: '/', named: false, empty_name_separator: false, encode : 'encode' }, // Path parameter name or name=value pairs prefixed by ';' ';' : { prefix: ';', separator: ';', named: true, empty_name_separator: false, encode : 'encode' }, // Query component beginning with '?' and consisting // of name=value pairs separated by '&'; an '?' : { prefix: '?', separator: '&', named: true, empty_name_separator: true, encode : 'encode' }, // Continuation of query-style &name=value pairs // within a literal query component. '&' : { prefix: '&', separator: '&', named: true, empty_name_separator: true, encode : 'encode' } // The operator characters equals ("="), comma (","), exclamation ("!"), // at sign ("@"), and pipe ("|") are reserved for future extensions. }; // storage for already parsed templates URITemplate._cache = {}; // pattern to identify expressions [operator, variable-list] in template URITemplate.EXPRESSION_PATTERN = /\{([^a-zA-Z0-9%_]?)([^\}]+)(\}|$)/g; // pattern to identify variables [name, explode, maxlength] in variable-list URITemplate.VARIABLE_PATTERN = /^([^*:.](?:\.?[^*:.])*)((\*)|:(\d+))?$/; // pattern to verify variable name integrity URITemplate.VARIABLE_NAME_PATTERN = /[^a-zA-Z0-9%_.]/; // pattern to verify literal integrity URITemplate.LITERAL_PATTERN = /[<>{}"`^| \\]/; // expand parsed expression (expression, not template!) URITemplate.expand = function(expression, data, opts) { // container for defined options for the given operator var options = operators[expression.operator]; // expansion type (include keys or not) var type = options.named ? 'Named' : 'Unnamed'; // list of variables within the expression var variables = expression.variables; // result buffer for evaluating the expression var buffer = []; var d, variable, i; for (i = 0; (variable = variables[i]); i++) { // fetch simplified data source d = data.get(variable.name); if (d.type === 0 && opts && opts.strict) { throw new Error('Missing expansion value for variable "' + variable.name + '"'); } if (!d.val.length) { if (d.type) { // empty variables (empty string) // still lead to a separator being appended! buffer.push(''); } // no data, no action continue; } if (d.type > 1 && variable.maxlength) { // composite variable cannot specify maxlength throw new Error('Invalid expression: Prefix modifier not applicable to variable "' + variable.name + '"'); } // expand the given variable buffer.push(URITemplate['expand' + type]( d, options, variable.explode, variable.explode && options.separator || ',', variable.maxlength, variable.name )); } if (buffer.length) { return options.prefix + buffer.join(options.separator); } else { // prefix is not prepended for empty expressions return ''; } }; // expand a named variable URITemplate.expandNamed = function(d, options, explode, separator, length, name) { // variable result buffer var result = ''; // peformance crap var encode = options.encode; var empty_name_separator = options.empty_name_separator; // flag noting if values are already encoded var _encode = !d[encode].length; // key for named expansion var _name = d.type === 2 ? '': URI[encode](name); var _value, i, l; // for each found value for (i = 0, l = d.val.length; i < l; i++) { if (length) { // maxlength must be determined before encoding can happen _value = URI[encode](d.val[i][1].substring(0, length)); if (d.type === 2) { // apply maxlength to keys of objects as well _name = URI[encode](d.val[i][0].substring(0, length)); } } else if (_encode) { // encode value _value = URI[encode](d.val[i][1]); if (d.type === 2) { // encode name and cache encoded value _name = URI[encode](d.val[i][0]); d[encode].push([_name, _value]); } else { // cache encoded value d[encode].push([undefined, _value]); } } else { // values are already encoded and can be pulled from cache _value = d[encode][i][1]; if (d.type === 2) { _name = d[encode][i][0]; } } if (result) { // unless we're the first value, prepend the separator result += separator; } if (!explode) { if (!i) { // first element, so prepend variable name result += URI[encode](name) + (empty_name_separator || _value ? '=' : ''); } if (d.type === 2) { // without explode-modifier, keys of objects are returned comma-separated result += _name + ','; } result += _value; } else { // only add the = if it is either default (?&) or there actually is a value (;) result += _name + (empty_name_separator || _value ? '=' : '') + _value; } } return result; }; // expand an unnamed variable URITemplate.expandUnnamed = function(d, options, explode, separator, length) { // variable result buffer var result = ''; // performance crap var encode = options.encode; var empty_name_separator = options.empty_name_separator; // flag noting if values are already encoded var _encode = !d[encode].length; var _name, _value, i, l; // for each found value for (i = 0, l = d.val.length; i < l; i++) { if (length) { // maxlength must be determined before encoding can happen _value = URI[encode](d.val[i][1].substring(0, length)); } else if (_encode) { // encode and cache value _value = URI[encode](d.val[i][1]); d[encode].push([ d.type === 2 ? URI[encode](d.val[i][0]) : undefined, _value ]); } else { // value already encoded, pull from cache _value = d[encode][i][1]; } if (result) { // unless we're the first value, prepend the separator result += separator; } if (d.type === 2) { if (length) { // maxlength also applies to keys of objects _name = URI[encode](d.val[i][0].substring(0, length)); } else { // at this point the name must already be encoded _name = d[encode][i][0]; } result += _name; if (explode) { // explode-modifier separates name and value by "=" result += (empty_name_separator || _value ? '=' : ''); } else { // no explode-modifier separates name and value by "," result += ','; } } result += _value; } return result; }; URITemplate.noConflict = function() { if (root.URITemplate === URITemplate) { root.URITemplate = _URITemplate; } return URITemplate; }; // expand template through given data map p.expand = function(data, opts) { var result = ''; if (!this.parts || !this.parts.length) { // lazilyy parse the template this.parse(); } if (!(data instanceof Data)) { // make given data available through the // optimized data handling thingie data = new Data(data); } for (var i = 0, l = this.parts.length; i < l; i++) { /*jshint laxbreak: true */ result += typeof this.parts[i] === 'string' // literal string ? this.parts[i] // expression : URITemplate.expand(this.parts[i], data, opts); /*jshint laxbreak: false */ } return result; }; // parse template into action tokens p.parse = function() { // performance crap var expression = this.expression; var ePattern = URITemplate.EXPRESSION_PATTERN; var vPattern = URITemplate.VARIABLE_PATTERN; var nPattern = URITemplate.VARIABLE_NAME_PATTERN; var lPattern = URITemplate.LITERAL_PATTERN; // token result buffer var parts = []; // position within source template var pos = 0; var variables, eMatch, vMatch; var checkLiteral = function(literal) { if (literal.match(lPattern)) { throw new Error('Invalid Literal "' + literal + '"'); } return literal; }; // RegExp is shared accross all templates, // which requires a manual reset ePattern.lastIndex = 0; // I don't like while(foo = bar()) loops, // to make things simpler I go while(true) and break when required while (true) { eMatch = ePattern.exec(expression); if (eMatch === null) { // push trailing literal parts.push(checkLiteral(expression.substring(pos))); break; } else { // push leading literal parts.push(checkLiteral(expression.substring(pos, eMatch.index))); pos = eMatch.index + eMatch[0].length; } if (!operators[eMatch[1]]) { throw new Error('Unknown Operator "' + eMatch[1] + '" in "' + eMatch[0] + '"'); } else if (!eMatch[3]) { throw new Error('Unclosed Expression "' + eMatch[0] + '"'); } // parse variable-list variables = eMatch[2].split(','); for (var i = 0, l = variables.length; i < l; i++) { vMatch = variables[i].match(vPattern); if (vMatch === null) { throw new Error('Invalid Variable "' + variables[i] + '" in "' + eMatch[0] + '"'); } else if (vMatch[1].match(nPattern)) { throw new Error('Invalid Variable Name "' + vMatch[1] + '" in "' + eMatch[0] + '"'); } variables[i] = { name: vMatch[1], explode: !!vMatch[3], maxlength: vMatch[4] && parseInt(vMatch[4], 10) }; } if (!variables.length) { throw new Error('Expression Missing Variable(s) "' + eMatch[0] + '"'); } parts.push({ expression: eMatch[0], operator: eMatch[1], variables: variables }); } if (!parts.length) { // template doesn't contain any expressions // so it is a simple literal string // this probably should fire a warning or something? parts.push(checkLiteral(expression)); } this.parts = parts; return this; }; // simplify data structures Data.prototype.get = function(key) { // performance crap var data = this.data; // cache for processed data-point var d = { // type of data 0: undefined/null, 1: string, 2: object, 3: array type: 0, // original values (except undefined/null) val: [], // cache for encoded values (only for non-maxlength expansion) encode: [], encodeReserved: [] }; var i, l, value; if (this.cache[key] !== undefined) { // we've already processed this key return this.cache[key]; } this.cache[key] = d; if (String(Object.prototype.toString.call(data)) === '[object Function]') { // data itself is a callback (global callback) value = data(key); } else if (String(Object.prototype.toString.call(data[key])) === '[object Function]') { // data is a map of callbacks (local callback) value = data[key](key); } else { // data is a map of data value = data[key]; } // generalize input into [ [name1, value1], [name2, value2], … ] // so expansion has to deal with a single data structure only if (value === undefined || value === null) { // undefined and null values are to be ignored completely return d; } else if (String(Object.prototype.toString.call(value)) === '[object Array]') { for (i = 0, l = value.length; i < l; i++) { if (value[i] !== undefined && value[i] !== null) { // arrays don't have names d.val.push([undefined, String(value[i])]); } } if (d.val.length) { // only treat non-empty arrays as arrays d.type = 3; // array } } else if (String(Object.prototype.toString.call(value)) === '[object Object]') { for (i in value) { if (hasOwn.call(value, i) && value[i] !== undefined && value[i] !== null) { // objects have keys, remember them for named expansion d.val.push([i, String(value[i])]); } } if (d.val.length) { // only treat non-empty objects as objects d.type = 2; // object } } else { d.type = 1; // primitive string (could've been string, number, boolean and objects with a toString()) // arrays don't have names d.val.push([undefined, String(value)]); } return d; }; // hook into URI for fluid access URI.expand = function(expression, data) { var template = new URITemplate(expression); var expansion = template.expand(data); return new URI(expansion); }; return URITemplate; })); /***/ }), /***/ 138: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ c: () => (/* binding */ DEFAULT_TIMEOUT), /* harmony export */ u: () => (/* binding */ NULL_ACCOUNT) /* harmony export */ }); /* harmony import */ var _stellar_stellar_base__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(950); /* harmony import */ var _stellar_stellar_base__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_stellar_stellar_base__WEBPACK_IMPORTED_MODULE_0__); var DEFAULT_TIMEOUT = 5 * 60; var NULL_ACCOUNT = "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF"; /***/ }), /***/ 193: /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! * URI.js - Mutating URLs * * Version: 1.19.11 * * Author: Rodney Rehm * Web: http://medialize.github.io/URI.js/ * * Licensed under * MIT License http://www.opensource.org/licenses/mit-license * */ (function (root, factory) { 'use strict'; // https://github.com/umdjs/umd/blob/master/returnExports.js if ( true && module.exports) { // Node module.exports = factory(__webpack_require__(340), __webpack_require__(430), __webpack_require__(704)); } else if (true) { // AMD. Register as an anonymous module. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(340), __webpack_require__(430), __webpack_require__(704)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } else // removed by dead control flow {} }(this, function (punycode, IPv6, SLD, root) { 'use strict'; /*global location, escape, unescape */ // FIXME: v2.0.0 renamce non-camelCase properties to uppercase /*jshint camelcase: false */ // save current URI variable, if any var _URI = root && root.URI; function URI(url, base) { var _urlSupplied = arguments.length >= 1; var _baseSupplied = arguments.length >= 2; // Allow instantiation without the 'new' keyword if (!(this instanceof URI)) { if (_urlSupplied) { if (_baseSupplied) { return new URI(url, base); } return new URI(url); } return new URI(); } if (url === undefined) { if (_urlSupplied) { throw new TypeError('undefined is not a valid argument for URI'); } if (typeof location !== 'undefined') { url = location.href + ''; } else { url = ''; } } if (url === null) { if (_urlSupplied) { throw new TypeError('null is not a valid argument for URI'); } } this.href(url); // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor if (base !== undefined) { return this.absoluteTo(base); } return this; } function isInteger(value) { return /^[0-9]+$/.test(value); } URI.version = '1.19.11'; var p = URI.prototype; var hasOwn = Object.prototype.hasOwnProperty; function escapeRegEx(string) { // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963 return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); } function getType(value) { // IE8 doesn't return [Object Undefined] but [Object Object] for undefined value if (value === undefined) { return 'Undefined'; } return String(Object.prototype.toString.call(value)).slice(8, -1); } function isArray(obj) { return getType(obj) === 'Array'; } function filterArrayValues(data, value) { var lookup = {}; var i, length; if (getType(value) === 'RegExp') { lookup = null; } else if (isArray(value)) { for (i = 0, length = value.length; i < length; i++) { lookup[value[i]] = true; } } else { lookup[value] = true; } for (i = 0, length = data.length; i < length; i++) { /*jshint laxbreak: true */ var _match = lookup && lookup[data[i]] !== undefined || !lookup && value.test(data[i]); /*jshint laxbreak: false */ if (_match) { data.splice(i, 1); length--; i--; } } return data; } function arrayContains(list, value) { var i, length; // value may be string, number, array, regexp if (isArray(value)) { // Note: this can be optimized to O(n) (instead of current O(m * n)) for (i = 0, length = value.length; i < length; i++) { if (!arrayContains(list, value[i])) { return false; } } return true; } var _type = getType(value); for (i = 0, length = list.length; i < length; i++) { if (_type === 'RegExp') { if (typeof list[i] === 'string' && list[i].match(value)) { return true; } } else if (list[i] === value) { return true; } } return false; } function arraysEqual(one, two) { if (!isArray(one) || !isArray(two)) { return false; } // arrays can't be equal if they have different amount of content if (one.length !== two.length) { return false; } one.sort(); two.sort(); for (var i = 0, l = one.length; i < l; i++) { if (one[i] !== two[i]) { return false; } } return true; } function trimSlashes(text) { var trim_expression = /^\/+|\/+$/g; return text.replace(trim_expression, ''); } URI._parts = function() { return { protocol: null, username: null, password: null, hostname: null, urn: null, port: null, path: null, query: null, fragment: null, // state preventInvalidHostname: URI.preventInvalidHostname, duplicateQueryParameters: URI.duplicateQueryParameters, escapeQuerySpace: URI.escapeQuerySpace }; }; // state: throw on invalid hostname // see https://github.com/medialize/URI.js/pull/345 // and https://github.com/medialize/URI.js/issues/354 URI.preventInvalidHostname = false; // state: allow duplicate query parameters (a=1&a=1) URI.duplicateQueryParameters = false; // state: replaces + with %20 (space in query strings) URI.escapeQuerySpace = true; // static properties URI.protocol_expression = /^[a-z][a-z0-9.+-]*$/i; URI.idn_expression = /[^a-z0-9\._-]/i; URI.punycode_expression = /(xn--)/i; // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care? URI.ip4_expression = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; // credits to Rich Brown // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096 // specification: http://www.ietf.org/rfc/rfc4291.txt URI.ip6_expression = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/; // expression used is "gruber revised" (@gruber v2) determined to be the // best solution in a regex-golf we did a couple of ages ago at // * http://mathiasbynens.be/demo/url-regex // * http://rodneyrehm.de/t/url-regex.html URI.find_uri_expression = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/ig; URI.findUri = { // valid "scheme://" or "www." start: /\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi, // everything up to the next whitespace end: /[\s\r\n]|$/, // trim trailing punctuation captured by end RegExp trim: /[`!()\[\]{};:'".,<>?«»“”„‘’]+$/, // balanced parens inclusion (), [], {}, <> parens: /(\([^\)]*\)|\[[^\]]*\]|\{[^}]*\}|<[^>]*>)/g, }; URI.leading_whitespace_expression = /^[\x00-\x20\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/ // https://infra.spec.whatwg.org/#ascii-tab-or-newline URI.ascii_tab_whitespace = /[\u0009\u000A\u000D]+/g // http://www.iana.org/assignments/uri-schemes.html // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports URI.defaultPorts = { http: '80', https: '443', ftp: '21', gopher: '70', ws: '80', wss: '443' }; // list of protocols which always require a hostname URI.hostProtocols = [ 'http', 'https' ]; // allowed hostname characters according to RFC 3986 // ALPHA DIGIT "-" "." "_" "~" "!" "$" "&" "'" "(" ")" "*" "+" "," ";" "=" %encoded // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . - _ URI.invalid_hostname_characters = /[^a-zA-Z0-9\.\-:_]/; // map DOM Elements to their URI attribute URI.domAttributes = { 'a': 'href', 'blockquote': 'cite', 'link': 'href', 'base': 'href', 'script': 'src', 'form': 'action', 'img': 'src', 'area': 'href', 'iframe': 'src', 'embed': 'src', 'source': 'src', 'track': 'src', 'input': 'src', // but only if type="image" 'audio': 'src', 'video': 'src' }; URI.getDomAttribute = function(node) { if (!node || !node.nodeName) { return undefined; } var nodeName = node.nodeName.toLowerCase(); // <input> should only expose src for type="image" if (nodeName === 'input' && node.type !== 'image') { return undefined; } return URI.domAttributes[nodeName]; }; function escapeForDumbFirefox36(value) { // https://github.com/medialize/URI.js/issues/91 return escape(value); } // encoding / decoding according to RFC3986 function strictEncodeURIComponent(string) { // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent return encodeURIComponent(string) .replace(/[!'()*]/g, escapeForDumbFirefox36) .replace(/\*/g, '%2A'); } URI.encode = strictEncodeURIComponent; URI.decode = decodeURIComponent; URI.iso8859 = function() { URI.encode = escape; URI.decode = unescape; }; URI.unicode = function() { URI.encode = strictEncodeURIComponent; URI.decode = decodeURIComponent; }; URI.characters = { pathname: { encode: { // RFC3986 2.1: For consistency, URI producers and normalizers should // use uppercase hexadecimal digits for all percent-encodings. expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig, map: { // -._~!'()* '%24': '$', '%26': '&', '%2B': '+', '%2C': ',', '%3B': ';', '%3D': '=', '%3A': ':', '%40': '@' } }, decode: { expression: /[\/\?#]/g, map: { '/': '%2F', '?': '%3F', '#': '%23' } } }, reserved: { encode: { // RFC3986 2.1: For consistency, URI producers and normalizers should // use uppercase hexadecimal digits for all percent-encodings. expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig, map: { // gen-delims '%3A': ':', '%2F': '/', '%3F': '?', '%23': '#', '%5B': '[', '%5D': ']', '%40': '@', // sub-delims '%21': '!', '%24': '$', '%26': '&', '%27': '\'', '%28': '(', '%29': ')', '%2A': '*', '%2B': '+', '%2C': ',', '%3B': ';', '%3D': '=' } } }, urnpath: { // The characters under `encode` are the characters called out by RFC 2141 as being acceptable // for usage in a URN. RFC2141 also calls out "-", ".", and "_" as acceptable characters, but // these aren't encoded by encodeURIComponent, so we don't have to call them out here. Also // note that the colon character is not featured in the encoding map; this is because URI.js // gives the colons in URNs semantic meaning as the delimiters of path segements, and so it // should not appear unencoded in a segment itself. // See also the note above about RFC3986 and capitalalized hex digits. encode: { expression: /%(21|24|27|28|29|2A|2B|2C|3B|3D|40)/ig, map: { '%21': '!', '%24': '$', '%27': '\'', '%28': '(', '%29': ')', '%2A': '*', '%2B': '+', '%2C': ',', '%3B': ';', '%3D': '=', '%40': '@' } }, // These characters are the characters called out by RFC2141 as "reserved" characters that // should never appear in a URN, plus the colon character (see note above). decode: { expression: /[\/\?#:]/g, map: { '/': '%2F', '?': '%3F', '#': '%23', ':': '%3A' } } } }; URI.encodeQuery = function(string, escapeQuerySpace) { var escaped = URI.encode(string + ''); if (escapeQuerySpace === undefined) { escapeQuerySpace = URI.escapeQuerySpace; } return escapeQuerySpace ? escaped.replace(/%20/g, '+') : escaped; }; URI.decodeQuery = function(string, escapeQuerySpace) { string += ''; if (escapeQuerySpace === undefined) { escapeQuerySpace = URI.escapeQuerySpace; } try { return URI.decode(escapeQuerySpace ? string.replace(/\+/g, '%20') : string); } catch(e) { // we're not going to mess with weird encodings, // give up and return the undecoded original string // see https://github.com/medialize/URI.js/issues/87 // see https://github.com/medialize/URI.js/issues/92 return string; } }; // generate encode/decode path functions var _parts = {'encode':'encode', 'decode':'decode'}; var _part; var generateAccessor = function(_group, _part) { return function(string) { try { return URI[_part](string + '').replace(URI.characters[_group][_part].expression, function(c) { return URI.characters[_group][_part].map[c]; }); } catch (e) { // we're not going to mess with weird encodings, // give up and return the undecoded original string // see https://github.com/medialize/URI.js/issues/87 // see https://github.com/medialize/URI.js/issues/92 return string; } }; }; for (_part in _parts) { URI[_part + 'PathSegment'] = generateAccessor('pathname', _parts[_part]); URI[_part + 'UrnPathSegment'] = generateAccessor('urnpath', _parts[_part]); } var generateSegmentedPathFunction = function(_sep, _codingFuncName, _innerCodingFuncName) { return function(string) { // Why pass in names of functions, rather than the function objects themselves? The // definitions of some functions (but in particular, URI.decode) will occasionally change due // to URI.js having ISO8859 and Unicode modes. Passing in the name and getting it will ensure // that the functions we use here are "fresh". var actualCodingFunc; if (!_innerCodingFuncName) { actualCodingFunc = URI[_codingFuncName]; } else { actualCodingFunc = function(string) { return URI[_codingFuncName](URI[_innerCodingFuncName](string)); }; } var segments = (string + '').split(_sep); for (var i = 0, length = segments.length; i < length; i++) { segments[i] = actualCodingFunc(segments[i]); } return segments.join(_sep); }; }; // This takes place outside the above loop because we don't want, e.g., encodeUrnPath functions. URI.decodePath = generateSegmentedPathFunction('/', 'decodePathSegment'); URI.decodeUrnPath = generateSegmentedPathFunction(':', 'decodeUrnPathSegment'); URI.recodePath = generateSegmentedPathFunction('/', 'encodePathSegment', 'decode'); URI.recodeUrnPath = generateSegmentedPathFunction(':', 'encodeUrnPathSegment', 'decode'); URI.encodeReserved = generateAccessor('reserved', 'encode'); URI.parse = function(string, parts) { var pos; if (!parts) { parts = { preventInvalidHostname: URI.preventInvalidHostname }; } string = string.replace(URI.leading_whitespace_expression, '') // https://infra.spec.whatwg.org/#ascii-tab-or-newline string = string.replace(URI.ascii_tab_whitespace, '') // [protocol"://"[username[":"password]"@"]hostname[":"port]"/"?][path]["?"querystring]["#"fragment] // extract fragment pos = string.indexOf('#'); if (pos > -1) { // escaping? parts.fragment = string.substring(pos + 1) || null; string = string.substring(0, pos); } // extract query pos = string.indexOf('?'); if (pos > -1) { // escaping? parts.query = string.substring(pos + 1) || null; string = string.substring(0, pos); } // slashes and backslashes have lost all meaning for the web protocols (https, http, wss, ws) string = string.replace(/^(https?|ftp|wss?)?:+[/\\]*/i, '$1://'); // slashes and backslashes have lost all meaning for scheme relative URLs string = string.replace(/^[/\\]{2,}/i, '//'); // extract protocol if (string.substring(0, 2) === '//') { // relative-scheme parts.protocol = null; string = string.substring(2); // extract "user:pass@host:port" string = URI.parseAuthority(string, parts); } else { pos = string.indexOf(':'); if (pos > -1) { parts.protocol = string.substring(0, pos) || null; if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) { // : may be within the path parts.protocol = undefined; } else if (string.substring(pos + 1, pos + 3).replace(/\\/g, '/') === '//') { string = string.substring(pos + 3); // extract "user:pass@host:port" string = URI.parseAuthority(string, parts); } else { string = string.substring(pos + 1); parts.urn = true; } } } // what's left must be the path parts.path = string; // and we're done return parts; }; URI.parseHost = function(string, parts) { if (!string) { string = ''; } // Copy chrome, IE, opera backslash-handling behavior. // Back slashes before the query string get converted to forward slashes // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124 // See: https://code.google.com/p/chromium/issues/detail?id=25916 // https://github.com/medialize/URI.js/pull/233 string = string.replace(/\\/g, '/'); // extract host:port var pos = string.indexOf('/'); var bracketPos; var t; if (pos === -1) { pos = string.length; } if (string.charAt(0) === '[') { // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6 // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts // IPv6+port in the format [2001:db8::1]:80 (for the time being) bracketPos = string.indexOf(']'); parts.hostname = string.substring(1, bracketPos) || null; parts.port = string.substring(bracketPos + 2, pos) || null; if (parts.port === '/') { parts.port = null; } } else { var firstColon = string.indexOf(':'); var firstSlash = string.indexOf('/'); var nextColon = string.indexOf(':', firstColon + 1); if (nextColon !== -1 && (firstSlash === -1 || nextColon < firstSlash)) { // IPv6 host contains multiple colons - but no port // this notation is actually not allowed by RFC 3986, but we're a liberal parser parts.hostname = string.substring(0, pos) || null; parts.port = null; } else { t = string.substring(0, pos).split(':'); parts.hostname = t[0] || null; parts.port = t[1] || null; } } if (parts.hostname && string.substring(pos).charAt(0) !== '/') { pos++; string = '/' + string; } if (parts.preventInvalidHostname) { URI.ensureValidHostname(parts.hostname, parts.protocol); } if (parts.port) { URI.ensureValidPort(parts.port); } return string.substring(pos) || '/'; }; URI.parseAuthority = function(string, parts) { string = URI.parseUserinfo(string, parts); return URI.parseHost(string, parts); }; URI.parseUserinfo = function(string, parts) { // extract username:password var _string = string var firstBackSlash = string.indexOf('\\'); if (firstBackSlash !== -1) { string = string.replace(/\\/g, '/') } var firstSlash = string.indexOf('/'); var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1); var t; // authority@ must come before /path or \path if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) { t = string.substring(0, pos).split(':'); parts.username = t[0] ? URI.decode(t[0]) : null; t.shift(); parts.password = t[0] ? URI.decode(t.join(':')) : null; string = _string.substring(pos + 1); } else { parts.username = null; parts.password = null; } return string; }; URI.parseQuery = function(string, escapeQuerySpace) { if (!string) { return {}; } // throw out the funky business - "?"[name"="value"&"]+ string = string.replace(/&+/g, '&').replace(/^\?*&*|&+$/g, ''); if (!string) { return {}; } var items = {}; var splits = string.split('&'); var length = splits.length; var v, name, value; for (var i = 0; i < length; i++) { v = splits[i].split('='); name = URI.decodeQuery(v.shift(), escapeQuerySpace); // no "=" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null; if (name === '__proto__') { // ignore attempt at exploiting JavaScript internals continue; } else if (hasOwn.call(items, name)) { if (typeof items[name] === 'string' || items[name] === null) { items[name] = [items[name]]; } items[name].push(value); } else { items[name] = value; } } return items; }; URI.build = function(parts) { var t = ''; var requireAbsolutePath = false if (parts.protocol) { t += parts.protocol + ':'; } if (!parts.urn && (t || parts.hostname)) { t += '//'; requireAbsolutePath = true } t += (URI.buildAuthority(parts) || ''); if (typeof parts.path === 'string') { if (parts.path.charAt(0) !== '/' && requireAbsolutePath) { t += '/'; } t += parts.path; } if (typeof parts.query === 'string' && parts.query) { t += '?' + parts.query; } if (typeof parts.fragment === 'string' && parts.fragment) { t += '#' + parts.fragment; } return t; }; URI.buildHost = function(parts) { var t = ''; if (!parts.hostname) { return ''; } else if (URI.ip6_expression.test(parts.hostname)) { t += '[' + parts.hostname + ']'; } else { t += parts.hostname; } if (parts.port) { t += ':' + parts.port; } return t; }; URI.buildAuthority = function(parts) { return URI.buildUserinfo(parts) + URI.buildHost(parts); }; URI.buildUserinfo = function(parts) { var t = ''; if (parts.username) { t += URI.encode(parts.username); } if (parts.password) { t += ':' + URI.encode(parts.password); } if (t) { t += '@'; } return t; }; URI.buildQuery = function(data, duplicateQueryParameters, escapeQuerySpace) { // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax! // URI.js treats the query string as being application/x-www-form-urlencoded // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type var t = ''; var unique, key, i, length; for (key in data) { if (key === '__proto__') { // ignore attempt at exploiting JavaScript internals continue; } else if (hasOwn.call(data, key)) { if (isArray(data[key])) { unique = {}; for (i = 0, length = data[key].length; i < length; i++) { if (data[key][i] !== undefined && unique[data[key][i] + ''] === undefined) { t += '&' + URI.buildQueryParameter(key, data[key][i], escapeQuerySpace); if (duplicateQueryParameters !== true) { unique[data[key][i] + ''] = true; } } } } else if (data[key] !== undefined) { t += '&' + URI.buildQueryParameter(key, data[key], escapeQuerySpace); } } } return t.substring(1); }; URI.buildQueryParameter = function(name, value, escapeQuerySpace) { // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded // don't append "=" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization return URI.encodeQuery(name, escapeQuerySpace) + (value !== null ? '=' + URI.encodeQuery(value, escapeQuerySpace) : ''); }; URI.addQuery = function(data, name, value) { if (typeof name === 'object') { for (var key in name) { if (hasOwn.call(name, key)) { URI.addQuery(data, key, name[key]); } } } else if (typeof name === 'string') { if (data[name] === undefined) { data[name] = value; return; } else if (typeof data[name] === 'string') { data[name] = [data[name]]; } if (!isArray(value)) { value = [value]; } data[name] = (data[name] || []).concat(value); } else { throw new TypeError('URI.addQuery() accepts an object, string as the name parameter'); } }; URI.setQuery = function(data, name, value) { if (typeof name === 'object') { for (var key in name) { if (hasOwn.call(name, key)) { URI.setQuery(data, key, name[key]); } } } else if (typeof name === 'string') { data[name] = value === undefined ? null : value; } else { throw new TypeError('URI.setQuery() accepts an object, string as the name parameter'); } }; URI.removeQuery = function(data, name, value) { var i, length, key; if (isArray(name)) { for (i = 0, length = name.length; i < length; i++) { data[name[i]] = undefined; } } else if (getType(name) === 'RegExp') { for (key in data) { if (name.test(key)) { data[key] = undefined; } } } else if (typeof name === 'object') { for (key in name) { if (hasOwn.call(name, key)) { URI.removeQuery(data, key, name[key]); } } } else if (typeof name === 'string') { if (value !== undefined) { if (getType(value) === 'RegExp') { if (!isArray(data[name]) && value.test(data[name])) { data[name] = undefined; } else { data[name] = filterArrayValues(data[name], value); } } else if (data[name] === String(value) && (!isArray(value) || value.length === 1)) { data[name] = undefined; } else if (isArray(data[name])) { data[name] = filterArrayValues(data[name], value); } } else { data[name] = undefined; } } else { throw new TypeError('URI.removeQuery() accepts an object, string, RegExp as the first parameter'); } }; URI.hasQuery = function(data, name, value, withinArray) { switch (getType(name)) { case 'String': // Nothing to do here break; case 'RegExp': for (var key in data) { if (hasOwn.call(data, key)) { if (name.test(key) && (value === undefined || URI.hasQuery(data, key, value))) { return true; } } } return false; case 'Object': for (var _key in name) { if (hasOwn.call(name, _key)) { if (!URI.hasQuery(data, _key, name[_key])) { return false; } } } return true; default: throw new TypeError('URI.hasQuery() accepts a string, regular expression or object as the name parameter'); } switch (getType(value)) { case 'Undefine