Replace Ant build with primitive Maven build.
6 * See: http://hg.grauw.nl/grauw-lib/file/tip/src/uri.js
8 * @author Laurens Holst (http://www.grauw.nl/)
10 * Copyright 2010 Laurens Holst
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
16 * http://www.apache.org/licenses/LICENSE-2.0
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
25 gl.module('gl.uri', [], function() {
28 * Constructs a URI object.
30 * @class Implementation of URI parsing and base URI resolving algorithm in RFC 3986.
31 * @param {string|URI} uri A string or URI object to create the object from.
33 var URI = function(vURI) {
34 if (vURI instanceof URI) { // copy constructor
35 this.scheme = vURI.scheme;
36 this.authority = vURI.authority;
37 this.path = vURI.path;
38 this.query = vURI.query;
39 this.fragment = vURI.fragment;
40 } else if (vURI) { // vURI is URI string or cast to string
41 var c = oParseRegex.exec(vURI);
43 this.authority = c[2];
50 // Initial values on the prototype
51 URI.prototype.scheme = null;
52 URI.prototype.authority = null;
53 URI.prototype.path = '';
54 URI.prototype.query = null;
55 URI.prototype.fragment = null;
57 // Regular expression from RFC 3986 appendix B
58 var oParseRegex = new RegExp('^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\\?([^#]*))?(?:#(.*))?$');
61 * Returns the scheme part of the URI.
62 * In "http://example.com:80/a/b?x#y" this is "http".
65 URI.prototype.getScheme = function() {
70 * Returns the authority part of the URI.
71 * In "http://example.com:80/a/b?x#y" this is "example.com:80".
74 URI.prototype.getAuthority = function() {
75 return this.authority;
79 * Returns the path part of the URI.
80 * In "http://example.com:80/a/b?x#y" this is "/a/b".
81 * In "mailto:mike@example.com" this is "mike@example.com".
84 URI.prototype.getPath = function() {
89 * Returns the query part of the URI.
90 * In "http://example.com:80/a/b?x#y" this is "x".
93 URI.prototype.getQuery = function() {
98 * Returns the fragment part of the URI.
99 * In "http://example.com:80/a/b?x#y" this is "y".
102 URI.prototype.getFragment = function() {
103 return this.fragment;
107 * Tests whether the URI is an absolute URI.
108 * See RFC 3986 section 4.3.
110 URI.prototype.isAbsolute = function() {
111 return this.scheme && !this.fragment;
115 //* Extensive validation of the URI against the ABNF in RFC 3986
117 //URI.prototype.validate
120 * Tests whether the URI is a same-document reference.
121 * See RFC 3986 section 4.4.
123 * To perform more thorough comparison, you can normalise the URI objects.
125 URI.prototype.isSameDocumentAs = function(oURI) {
126 return oURI.scheme == this.scheme &&
127 oURI.authority == this.authority &&
128 oURI.path == this.path &&
129 oURI.query == this.query;
133 * Simple String Comparison of two URIs.
134 * See RFC 3986 section 6.2.1.
136 * To perform more thorough comparison, you can normalise the URI objects.
138 URI.prototype.equals = function(oURI) {
139 return this.isSameDocumentAs(oURI) && oURI.fragment == this.fragment;
143 * Normalizes the URI using syntax-based normalization.
144 * This includes case normalization, percent-encoding normalization and path segment normalization.
145 * XXX: Percent-encoding normalization does not escape characters that need to be escaped.
146 * (Although that would not be a valid URI in the first place. See validate().)
147 * See RFC 3986 section 6.2.2.
149 URI.prototype.normalize = function() {
150 this.removeDotSegments();
152 this.scheme = this.scheme.toLowerCase();
154 this.authority = this.authority.replace(oAuthorityRegex, fAuthority).
155 replace(oCaseRegex, fCase);
157 this.path = this.path.replace(oCaseRegex, fCase);
159 this.query = this.query.replace(oCaseRegex, fCase);
161 this.fragment = this.fragment.replace(oCaseRegex, fCase);
164 var oCaseRegex = /%[0-9a-z]{2}/gi;
165 var oPercentRegex = /[a-zA-Z0-9\-\._~]/;
166 var oAuthorityRegex = /(.*@)?([^@:]*)(:.*)?/;
168 function fCase(sStr) {
169 var sDec = unescape(sStr);
170 return oPercentRegex.test(sDec) ? sDec : sStr.toUpperCase();
173 function fAuthority(sStr, p1, p2, p3) {
174 return (p1 || '') + p2.toLowerCase() + (p3 || '');
178 * Resolve a relative URI (this) against a base URI.
179 * The base URI must be an absolute URI.
180 * See RFC 3986 section 5.2
182 URI.prototype.resolve = function(oBaseURI) {
183 var oURI = new URI();
185 oURI.scheme = this.scheme;
186 oURI.authority = this.authority;
187 oURI.path = this.path;
188 oURI.query = this.query;
190 oURI.scheme = oBaseURI.scheme;
191 if (this.authority) {
192 oURI.authority = this.authority;
193 oURI.path = this.path;
194 oURI.query = this.query;
196 oURI.authority = oBaseURI.authority;
197 if (this.path == '') {
198 oURI.path = oBaseURI.path;
199 oURI.query = this.query || oBaseURI.query;
201 if (this.path.charAt(0) == '/') {
202 oURI.path = this.path;
203 oURI.removeDotSegments();
205 if (oBaseURI.authority && oBaseURI.path == '') {
206 oURI.path = '/' + this.path;
208 oURI.path = oBaseURI.path.substring(0, oBaseURI.path.lastIndexOf('/') + 1) + this.path;
210 oURI.removeDotSegments();
212 oURI.query = this.query;
216 oURI.fragment = this.fragment;
221 * Remove dot segments from path.
222 * See RFC 3986 section 5.2.4
225 URI.prototype.removeDotSegments = function() {
226 var aInput = this.path.split('/'),
229 bAbsPath = aInput[0] == '';
232 var sFirst = aInput[0] == '' ? aInput.shift() : null;
233 while (aInput.length) {
234 sSegment = aInput.shift();
235 if (sSegment == '..') {
237 } else if (sSegment != '.') {
238 aOutput.push(sSegment);
241 if (sSegment == '.' || sSegment == '..')
245 this.path = aOutput.join('/');
249 * Resolves a relative URI against an absolute base URI.
250 * Convenience method.
251 * @param {String} uri the relative URI to resolve
252 * @param {String} baseURI the base URI (must be absolute) to resolve against
254 URI.resolve = function(sURI, sBaseURI) {
255 var oURI = hCache[sURI] || (hCache[sURI] = new URI(sURI));
256 var oBaseURI = hCache[sBaseURI] || (hCache[sBaseURI] = new URI(sBaseURI));
257 return oURI.resolve(oBaseURI).toString();
263 * Serialises the URI to a string.
265 URI.prototype.toString = function() {
268 sResult += this.scheme + ':';
270 sResult += '//' + this.authority;
271 sResult += this.path;
273 sResult += '?' + this.query;
275 sResult += '#' + this.fragment;