diff --git a/js/init.js b/js/init.js index 9ba79bb9366..a1f2e2e71db 100644 --- a/js/init.js +++ b/js/init.js @@ -57,6 +57,7 @@ define([ var path = $.mobile.path, $pages = $( ":jqmData(role='page'), :jqmData(role='dialog')" ), hash = path.stripHash( path.stripQueryParams(path.parseLocation().hash) ), + theLocation = $.mobile.path.parseLocation(), hashPage = document.getElementById( hash ); // if no pages are found, create one with body's inner html @@ -70,7 +71,8 @@ define([ // unless the data url is already set set it to the pathname if ( !$this[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) ) { - $this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) || location.pathname + location.search ); + $this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) || + theLocation.pathname + theLocation.search ); } }); diff --git a/js/navigation/base.js b/js/navigation/base.js index 26ab6f755a6..7432ce9c726 100644 --- a/js/navigation/base.js +++ b/js/navigation/base.js @@ -46,13 +46,14 @@ define([ page.find( base.linkSelector ).each(function( i, link ) { var thisAttr = $( link ).is( "[href]" ) ? "href" : $( link ).is( "[src]" ) ? "src" : "action", + theLocation = $.mobile.path.parseLocation(), thisUrl = $( link ).attr( thisAttr ); // XXX_jblas: We need to fix this so that it removes the document // base URL, and then prepends with the new page URL. // if full path exists and is same, chop it - helps IE out - thisUrl = thisUrl.replace( location.protocol + "//" + - location.host + location.pathname, "" ); + thisUrl = thisUrl.replace( theLocation.protocol + theLocation.doubleSlash + + theLocation.host + theLocation.pathname, "" ); if ( !/^(\w+:|#|\/)/.test( thisUrl ) ) { $( link ).attr( thisAttr, newPath + thisUrl ); diff --git a/js/navigation/path.js b/js/navigation/path.js index 40d52bf0f3b..f2b28dc52c2 100644 --- a/js/navigation/path.js +++ b/js/navigation/path.js @@ -41,19 +41,34 @@ define([ urlParseRE: /^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/, // Abstraction to address xss (Issue #4787) by removing the authority in - // browsers that auto decode it. All references to location.href should be + // browsers that auto-decode it. All references to location.href should be // replaced with a call to this method so that it can be dealt with properly here getLocation: function( url ) { - var uri = url ? this.parseUrl( url ) : location, - hash = this.parseUrl( url || location.href ).hash; + var parsedUrl = this.parseUrl( url || location.href ), + uri = url ? parsedUrl : location, + + // Make sure to parse the url or the location object for the hash because using + // location.hash is autodecoded in firefox, the rest of the url should be from + // the object (location unless we're testing) to avoid the inclusion of the + // authority + hash = parsedUrl.hash; // mimic the browser with an empty string when the hash is empty hash = hash === "#" ? "" : hash; - // Make sure to parse the url or the location object for the hash because using location.hash - // is autodecoded in firefox, the rest of the url should be from the object (location unless - // we're testing) to avoid the inclusion of the authority - return uri.protocol + "//" + uri.host + uri.pathname + uri.search + hash; + return uri.protocol + + parsedUrl.doubleSlash + + uri.host + + + // The pathname must start with a slash if there's a protocol, because you + // can't have a protocol followed by a relative path. Also, it's impossible to + // calculate absolute URLs from relative ones if the absolute one doesn't have + // a leading "/". + ( ( uri.protocol !== "" && uri.pathname.substring( 0, 1 ) !== "/" ) ? + "/" : "" ) + + uri.pathname + + uri.search + + hash; }, //return the original document url @@ -323,7 +338,8 @@ define([ // reconstruct each of the pieces with the new search string and hash href = path.parseUrl( href ); - href = href.protocol + "//" + href.host + href.pathname + search + preservedHash; + href = href.protocol + href.doubleSlash + href.host + href.pathname + search + + preservedHash; } else { href += href.indexOf( "#" ) > -1 ? uiState : "#" + uiState; } diff --git a/tests/unit/path/path_core.js b/tests/unit/path/path_core.js index 357d6b644ef..4c2724b63ca 100644 --- a/tests/unit/path/path_core.js +++ b/tests/unit/path/path_core.js @@ -239,9 +239,11 @@ test( "path.getLocation works properly", function() { equal( $.mobile.path.getLocation("http://example.com/"), "http://example.com/" ); - equal( $.mobile.path.getLocation("http://foo@example.com"), "http://example.com" ); - equal( $.mobile.path.getLocation("http://foo:bar@example.com"), "http://example.com" ); - equal( $.mobile.path.getLocation("http://