From 53129e9cc7eb1c4f55b44a14adc91da23c7be85b Mon Sep 17 00:00:00 2001 From: Michał Gołębiowski-Owczarek Date: Wed, 26 Mar 2025 14:25:24 +0100 Subject: Tabs: Support URL-based credentials When credentials are provided directly in the URL, e.g.: https://username:password@www.example.com/ `location.href` strips out the auth part, but anchor links contain them, making our `isLocal` computation broken. This fixes it by only looking at `origin`, `pathname` & `search`. Fixes gh-2213 Closes gh-2345 --- tests/unit/tabs/core.js | 26 ++++++++++++++++++++++++++ ui/widgets/tabs.js | 33 +++++++++++++-------------------- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/tests/unit/tabs/core.js b/tests/unit/tabs/core.js index c2fd89048..f7515f585 100644 --- a/tests/unit/tabs/core.js +++ b/tests/unit/tabs/core.js @@ -747,4 +747,30 @@ QUnit.test( "extra listeners created when tabs are added/removed (trac-15136)", "No extra listeners after removing all the extra tabs" ); } ); +QUnit.test( "URL-based auth with local tabs (gh-2213)", function( assert ) { + assert.expect( 1 ); + + var origAjax = $.ajax, + element = $( "#tabs1" ), + anchor = element.find( "a[href='#fragment-3']" ), + url = new URL( anchor.prop( "href" ) ); + + try { + $.ajax = function() { + throw new Error( "Unexpected AJAX call; all tabs are local!" ); + }; + + anchor.attr( "href", url.protocol + "//username:password@" + url.host + + url.pathname + url.search + url.hash ); + + element.tabs(); + anchor.trigger( "click" ); + + assert.strictEqual( element.tabs( "option", "active" ), 2, + "should set the active option" ); + } finally { + $.ajax = origAjax; + } +} ); + } ); diff --git a/ui/widgets/tabs.js b/ui/widgets/tabs.js index 49468feb3..0a8efd3ca 100644 --- a/ui/widgets/tabs.js +++ b/ui/widgets/tabs.js @@ -61,26 +61,19 @@ $.widget( "ui.tabs", { load: null }, - _isLocal: ( function() { - var rhash = /#.*$/; - - return function( anchor ) { - var anchorUrl, locationUrl; - - anchorUrl = anchor.href.replace( rhash, "" ); - locationUrl = location.href.replace( rhash, "" ); - - // Decoding may throw an error if the URL isn't UTF-8 (#9518) - try { - anchorUrl = decodeURIComponent( anchorUrl ); - } catch ( _error ) {} - try { - locationUrl = decodeURIComponent( locationUrl ); - } catch ( _error ) {} - - return anchor.hash.length > 1 && anchorUrl === locationUrl; - }; - } )(), + _isLocal: function( anchor ) { + var anchorUrl = new URL( anchor.href ), + locationUrl = new URL( location.href ); + + return anchor.hash.length > 1 && + + // `href` may contain a hash but also username & password; + // we want to ignore them, so we check the three fields + // below instead. + anchorUrl.origin === locationUrl.origin && + anchorUrl.pathname === locationUrl.pathname && + anchorUrl.search === locationUrl.search; + }, _create: function() { var that = this, -- cgit v1.2.3