123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- /**
- * @license
- *
- * Grauw URI utilities
- *
- * See: http://hg.grauw.nl/grauw-lib/file/tip/src/uri.js
- *
- * @author Laurens Holst (http://www.grauw.nl/)
- *
- * Copyright 2012 Laurens Holst
- *
- * 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.
- *
- */
- /*global define*/
- define(function() {
- /**
- * Constructs a URI object.
- * @constructor
- * @class Implementation of URI parsing and base URI resolving algorithm in RFC 3986.
- * @param {string|URI} uri A string or URI object to create the object from.
- */
- function URI(uri) {
- if (uri instanceof URI) { // copy constructor
- this.scheme = uri.scheme;
- this.authority = uri.authority;
- this.path = uri.path;
- this.query = uri.query;
- this.fragment = uri.fragment;
- } else if (uri) { // uri is URI string or cast to string
- var c = parseRegex.exec(uri);
- this.scheme = c[1];
- this.authority = c[2];
- this.path = c[3];
- this.query = c[4];
- this.fragment = c[5];
- }
- };
- // Initial values on the prototype
- URI.prototype.scheme = null;
- URI.prototype.authority = null;
- URI.prototype.path = '';
- URI.prototype.query = null;
- URI.prototype.fragment = null;
- // Regular expression from RFC 3986 appendix B
- var parseRegex = new RegExp('^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\\?([^#]*))?(?:#(.*))?$');
- /**
- * Returns the scheme part of the URI.
- * In "http://example.com:80/a/b?x#y" this is "http".
- */
- URI.prototype.getScheme = function() {
- return this.scheme;
- };
- /**
- * Returns the authority part of the URI.
- * In "http://example.com:80/a/b?x#y" this is "example.com:80".
- */
- URI.prototype.getAuthority = function() {
- return this.authority;
- };
- /**
- * Returns the path part of the URI.
- * In "http://example.com:80/a/b?x#y" this is "/a/b".
- * In "mailto:mike@example.com" this is "mike@example.com".
- */
- URI.prototype.getPath = function() {
- return this.path;
- };
- /**
- * Returns the query part of the URI.
- * In "http://example.com:80/a/b?x#y" this is "x".
- */
- URI.prototype.getQuery = function() {
- return this.query;
- };
- /**
- * Returns the fragment part of the URI.
- * In "http://example.com:80/a/b?x#y" this is "y".
- */
- URI.prototype.getFragment = function() {
- return this.fragment;
- };
- /**
- * Tests whether the URI is an absolute URI.
- * See RFC 3986 section 4.3.
- */
- URI.prototype.isAbsolute = function() {
- return !!this.scheme && !this.fragment;
- };
- ///**
- //* Extensive validation of the URI against the ABNF in RFC 3986
- //*/
- //URI.prototype.validate
- /**
- * Tests whether the URI is a same-document reference.
- * See RFC 3986 section 4.4.
- *
- * To perform more thorough comparison, you can normalise the URI objects.
- */
- URI.prototype.isSameDocumentAs = function(uri) {
- return uri.scheme == this.scheme &&
- uri.authority == this.authority &&
- uri.path == this.path &&
- uri.query == this.query;
- };
- /**
- * Simple String Comparison of two URIs.
- * See RFC 3986 section 6.2.1.
- *
- * To perform more thorough comparison, you can normalise the URI objects.
- */
- URI.prototype.equals = function(uri) {
- return this.isSameDocumentAs(uri) && uri.fragment == this.fragment;
- };
- /**
- * Normalizes the URI using syntax-based normalization.
- * This includes case normalization, percent-encoding normalization and path segment normalization.
- * XXX: Percent-encoding normalization does not escape characters that need to be escaped.
- * (Although that would not be a valid URI in the first place. See validate().)
- * See RFC 3986 section 6.2.2.
- */
- URI.prototype.normalize = function() {
- this.removeDotSegments();
- if (this.scheme)
- this.scheme = this.scheme.toLowerCase();
- if (this.authority)
- this.authority = this.authority.replace(authorityRegex, replaceAuthority).
- replace(caseRegex, replaceCase);
- if (this.path)
- this.path = this.path.replace(caseRegex, replaceCase);
- if (this.query)
- this.query = this.query.replace(caseRegex, replaceCase);
- if (this.fragment)
- this.fragment = this.fragment.replace(caseRegex, replaceCase);
- };
- var caseRegex = /%[0-9a-z]{2}/gi;
- var percentRegex = /[a-zA-Z0-9\-\._~]/;
- var authorityRegex = /(.*@)?([^@:]*)(:.*)?/;
- function replaceCase(str) {
- var dec = unescape(str);
- return percentRegex.test(dec) ? dec : str.toUpperCase();
- }
- function replaceAuthority(str, p1, p2, p3) {
- return (p1 || '') + p2.toLowerCase() + (p3 || '');
- }
- /**
- * Resolve a relative URI (this) against a base URI.
- * The base URI must be an absolute URI.
- * See RFC 3986 section 5.2
- */
- URI.prototype.resolve = function(baseURI) {
- var uri = new URI();
- if (this.scheme) {
- uri.scheme = this.scheme;
- uri.authority = this.authority;
- uri.path = this.path;
- uri.query = this.query;
- } else {
- uri.scheme = baseURI.scheme;
- if (this.authority) {
- uri.authority = this.authority;
- uri.path = this.path;
- uri.query = this.query;
- } else {
- uri.authority = baseURI.authority;
- if (this.path == '') {
- uri.path = baseURI.path;
- uri.query = this.query || baseURI.query;
- } else {
- if (this.path.charAt(0) == '/') {
- uri.path = this.path;
- uri.removeDotSegments();
- } else {
- if (baseURI.authority && baseURI.path == '') {
- uri.path = '/' + this.path;
- } else {
- uri.path = baseURI.path.substring(0, baseURI.path.lastIndexOf('/') + 1) + this.path;
- }
- uri.removeDotSegments();
- }
- uri.query = this.query;
- }
- }
- }
- uri.fragment = this.fragment;
- return uri;
- };
- /**
- * Remove dot segments from path.
- * See RFC 3986 section 5.2.4
- * @private
- */
- URI.prototype.removeDotSegments = function() {
- var input = this.path.split('/'),
- output = [],
- segment,
- absPath = input[0] == '';
- if (absPath)
- input.shift();
- var sFirst = input[0] == '' ? input.shift() : null;
- while (input.length) {
- segment = input.shift();
- if (segment == '..') {
- output.pop();
- } else if (segment != '.') {
- output.push(segment);
- }
- }
- if (segment == '.' || segment == '..')
- output.push('');
- if (absPath)
- output.unshift('');
- this.path = output.join('/');
- };
- // We don't like this function because it builds up a cache that is never cleared.
- // /**
- // * Resolves a relative URI against an absolute base URI.
- // * Convenience method.
- // * @param {String} uri the relative URI to resolve
- // * @param {String} baseURI the base URI (must be absolute) to resolve against
- // */
- // URI.resolve = function(sURI, sBaseURI) {
- // var uri = cache[sURI] || (cache[sURI] = new URI(sURI));
- // var baseURI = cache[sBaseURI] || (cache[sBaseURI] = new URI(sBaseURI));
- // return uri.resolve(baseURI).toString();
- // };
- // var cache = {};
- /**
- * Serialises the URI to a string.
- */
- URI.prototype.toString = function() {
- var result = '';
- if (this.scheme)
- result += this.scheme + ':';
- if (this.authority)
- result += '//' + this.authority;
- result += this.path;
- if (this.query)
- result += '?' + this.query;
- if (this.fragment)
- result += '#' + this.fragment;
- return result;
- };
- return URI;
- });
|