@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
JavaScript
(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