aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Cross2013-11-13 12:56:54 -0800
committerJeff Cross2013-11-13 15:53:20 -0800
commit89f435de847635e3ec339726e6f83cf3f0ee9091 (patch)
tree109f8c7e8350faa1633ba07bdb18e902190e050e
parentbcc6e8d4f64a18039e0ed2eee0b54c17471b43e3 (diff)
downloadangular.js-89f435de847635e3ec339726e6f83cf3f0ee9091.tar.bz2
fix(urlUtils): made removal of windows drive from path safer
Prior to this fix, the urlResolve method would automatically strip the first segment of a path if the segment ends in a colon. This was to correct undesired behavior in the $location service using the file protocol on windows in multiple browsers (see #4680). However, there could be cases where users intentionally have first path segments that end in a colon (although this conflicts with section 3.3 of rfc3986). The solution to this problem is an extra check to make sure the first path segment of the input url does not end with a colon, to make sure we're only removing undesired path segments. Fixes #4939
-rw-r--r--src/ng/location.js16
-rw-r--r--src/ng/urlUtils.js32
-rw-r--r--test/ng/locationSpec.js9
3 files changed, 38 insertions, 19 deletions
diff --git a/src/ng/location.js b/src/ng/location.js
index 6ec7d337..f06a5f81 100644
--- a/src/ng/location.js
+++ b/src/ng/location.js
@@ -22,8 +22,8 @@ function encodePath(path) {
return segments.join('/');
}
-function parseAbsoluteUrl(absoluteUrl, locationObj) {
- var parsedUrl = urlResolve(absoluteUrl);
+function parseAbsoluteUrl(absoluteUrl, locationObj, appBase) {
+ var parsedUrl = urlResolve(absoluteUrl, appBase);
locationObj.$$protocol = parsedUrl.protocol;
locationObj.$$host = parsedUrl.hostname;
@@ -31,12 +31,12 @@ function parseAbsoluteUrl(absoluteUrl, locationObj) {
}
-function parseAppUrl(relativeUrl, locationObj) {
+function parseAppUrl(relativeUrl, locationObj, appBase) {
var prefixed = (relativeUrl.charAt(0) !== '/');
if (prefixed) {
relativeUrl = '/' + relativeUrl;
}
- var match = urlResolve(relativeUrl);
+ var match = urlResolve(relativeUrl, appBase);
locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
match.pathname.substring(1) : match.pathname);
locationObj.$$search = parseKeyValue(match.search);
@@ -91,7 +91,7 @@ function LocationHtml5Url(appBase, basePrefix) {
this.$$html5 = true;
basePrefix = basePrefix || '';
var appBaseNoFile = stripFile(appBase);
- parseAbsoluteUrl(appBase, this);
+ parseAbsoluteUrl(appBase, this, appBase);
/**
@@ -106,7 +106,7 @@ function LocationHtml5Url(appBase, basePrefix) {
appBaseNoFile);
}
- parseAppUrl(pathUrl, this);
+ parseAppUrl(pathUrl, this, appBase);
if (!this.$$path) {
this.$$path = '/';
@@ -158,7 +158,7 @@ function LocationHtml5Url(appBase, basePrefix) {
function LocationHashbangUrl(appBase, hashPrefix) {
var appBaseNoFile = stripFile(appBase);
- parseAbsoluteUrl(appBase, this);
+ parseAbsoluteUrl(appBase, this, appBase);
/**
@@ -178,7 +178,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
hashPrefix);
}
- parseAppUrl(withoutHashUrl, this);
+ parseAppUrl(withoutHashUrl, this, appBase);
this.$$compose();
};
diff --git a/src/ng/urlUtils.js b/src/ng/urlUtils.js
index 51d40f9e..cba8981c 100644
--- a/src/ng/urlUtils.js
+++ b/src/ng/urlUtils.js
@@ -67,7 +67,7 @@ var originUrl = urlResolve(window.location.href, true);
* | pathname | The pathname, beginning with "/"
*
*/
-function urlResolve(url) {
+function urlResolve(url, base) {
var href = url,
pathname;
@@ -92,10 +92,9 @@ function urlResolve(url) {
* do not include drive names for routing.
*/
- pathname = removeWindowsDriveName(urlParsingNode.pathname);
+ pathname = removeWindowsDriveName(urlParsingNode.pathname, url, base);
pathname = (pathname.charAt(0) === '/') ? pathname : '/' + pathname;
-
// urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
return {
href: urlParsingNode.href,
@@ -107,13 +106,6 @@ function urlResolve(url) {
port: urlParsingNode.port,
pathname: pathname
};
-
- function removeWindowsDriveName (path) {
- var firstPathSegmentMatch;
-
- firstPathSegmentMatch = windowsFilePathExp.exec(path);
- return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
- }
}
@@ -129,3 +121,23 @@ function urlIsSameOrigin(requestUrl) {
return (parsed.protocol === originUrl.protocol &&
parsed.host === originUrl.host);
}
+
+function removeWindowsDriveName (path, url, base) {
+ var firstPathSegmentMatch;
+
+ //Get the relative path from the input URL.
+ if (url.indexOf(base) === 0) {
+ url = url.replace(base, '');
+ }
+
+ /*
+ * The input URL intentionally contains a
+ * first path segment that ends with a colon.
+ */
+ if (windowsFilePathExp.exec(url)) {
+ return path;
+ }
+
+ firstPathSegmentMatch = windowsFilePathExp.exec(path);
+ return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
+} \ No newline at end of file
diff --git a/test/ng/locationSpec.js b/test/ng/locationSpec.js
index abd99585..ad565772 100644
--- a/test/ng/locationSpec.js
+++ b/test/ng/locationSpec.js
@@ -34,7 +34,6 @@ describe('$location', function() {
};
}));
-
afterEach(inject(function ($sniffer) {
if ($sniffer.msie) return;
//reset urlParsingNode
@@ -50,6 +49,14 @@ describe('$location', function() {
expect(url.path()).toBe('/foo');
});
+
+
+ it('should include the drive name if it was provided in the input url', function () {
+ url = new LocationHashbangUrl('file:///base', '#!');
+ url.$$parse('file:///base#!/C:/foo?a=b&c#hash');
+
+ expect(url.path()).toBe('/C:/foo');
+ });
});