Skip to content

Commit 0cbc505

Browse files
fix($location): do not decode forward slashes in the path in HTML5 mode
Closes angular#16312
1 parent 667db46 commit 0cbc505

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

src/ng/location.js

+23-7
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,23 @@ function encodePath(path) {
1616
i = segments.length;
1717

1818
while (i--) {
19-
segments[i] = encodeUriSegment(segments[i]);
19+
// decode forward slashes to prevent them from being double encoded
20+
segments[i] = encodeUriSegment(segments[i].replace(/%2F/g, '/'));
21+
}
22+
23+
return segments.join('/');
24+
}
25+
26+
function decodePath(path, html5Mode) {
27+
var segments = path.split('/'),
28+
i = segments.length;
29+
30+
while (i--) {
31+
segments[i] = decodeURIComponent(segments[i]);
32+
if (html5Mode) {
33+
// encode forward slashes to prevent them from being mistaken for path separators
34+
segments[i] = segments[i].replace(/\//g, '%2F');
35+
}
2036
}
2137

2238
return segments.join('/');
@@ -31,7 +47,7 @@ function parseAbsoluteUrl(absoluteUrl, locationObj) {
3147
}
3248

3349
var DOUBLE_SLASH_REGEX = /^\s*[\\/]{2,}/;
34-
function parseAppUrl(url, locationObj) {
50+
function parseAppUrl(url, locationObj, html5Mode) {
3551

3652
if (DOUBLE_SLASH_REGEX.test(url)) {
3753
throw $locationMinErr('badpath', 'Invalid url "{0}".', url);
@@ -42,8 +58,8 @@ function parseAppUrl(url, locationObj) {
4258
url = '/' + url;
4359
}
4460
var match = urlResolve(url);
45-
locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
46-
match.pathname.substring(1) : match.pathname);
61+
var path = prefixed && match.pathname.charAt(0) === '/' ? match.pathname.substring(1) : match.pathname;
62+
locationObj.$$path = decodePath(path, html5Mode);
4763
locationObj.$$search = parseKeyValue(match.search);
4864
locationObj.$$hash = decodeURIComponent(match.hash);
4965

@@ -118,7 +134,7 @@ function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) {
118134
appBaseNoFile);
119135
}
120136

121-
parseAppUrl(pathUrl, this);
137+
parseAppUrl(pathUrl, this, true);
122138

123139
if (!this.$$path) {
124140
this.$$path = '/';
@@ -221,7 +237,7 @@ function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) {
221237
}
222238
}
223239

224-
parseAppUrl(withoutHashUrl, this);
240+
parseAppUrl(withoutHashUrl, this, false);
225241

226242
this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
227243

@@ -406,7 +422,7 @@ var locationPrototype = {
406422
}
407423

408424
var match = PATH_MATCH.exec(url);
409-
if (match[1] || url === '') this.path(decodeURIComponent(match[1]));
425+
if (match[1] || url === '') this.path(decodeURI(match[1]));
410426
if (match[2] || match[1] || url === '') this.search(match[3] || '');
411427
this.hash(match[5] || '');
412428

test/ng/locationSpec.js

+11
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,17 @@ describe('$location', function() {
477477
expect(locationUrl.hash()).toBe('x <>#');
478478
});
479479

480+
481+
it('should not decode encoded forward slashes in the path', function() {
482+
var locationUrl = new LocationHtml5Url('http://host.com/base/', 'http://host.com/base/');
483+
locationUrl.$$parse('http://host.com/base/a/ng2;path=%2Fsome%2Fpath');
484+
expect(locationUrl.path()).toBe('/a/ng2;path=%2Fsome%2Fpath');
485+
expect(locationUrl.search()).toEqual({});
486+
expect(locationUrl.hash()).toBe('');
487+
expect(locationUrl.url()).toBe('/a/ng2;path=%2Fsome%2Fpath');
488+
expect(locationUrl.absUrl()).toBe('http://host.com/base/a/ng2;path=%2Fsome%2Fpath');
489+
});
490+
480491
it('should decode pluses as spaces in urls', function() {
481492
var locationUrl = new LocationHtml5Url('http://host.com/', 'http://host.com/');
482493
locationUrl.$$parse('http://host.com/?a+b=c+d');

0 commit comments

Comments
 (0)