diff --git a/.changeset/fair-rocks-promise.md b/.changeset/fair-rocks-promise.md new file mode 100644 index 000000000..d02d9de0a --- /dev/null +++ b/.changeset/fair-rocks-promise.md @@ -0,0 +1,5 @@ +--- +'@faustwp/wordpress-plugin': patch +--- + +Improve domain_match function to handle port checks and Add Comprehensive Test Cases diff --git a/plugins/faustwp/includes/rest/callbacks.php b/plugins/faustwp/includes/rest/callbacks.php index 6951d2acc..7574c025a 100644 --- a/plugins/faustwp/includes/rest/callbacks.php +++ b/plugins/faustwp/includes/rest/callbacks.php @@ -26,7 +26,7 @@ use function WPE\FaustWP\Settings\faustwp_get_setting; use function WPE\FaustWP\Settings\faustwp_update_setting; use function WPE\FaustWP\Settings\is_telemetry_enabled; -use function WPE\FaustWP\Utilities\domains_match; +use function WPE\FaustWP\Utilities\strict_domain_match; if ( ! defined( 'ABSPATH' ) ) { exit; @@ -560,7 +560,7 @@ function handle_rest_validate_public_wordpress_url_callback( \WP_REST_Request $r $public_wordpress_url = $parameters['public_wordpress_url']; // Check if the provided WordPress URL does not match the frontend URI. - if ( ! domains_match( $public_wordpress_url, $frontend_uri ) ) { + if ( ! strict_domain_match( $public_wordpress_url, $frontend_uri ) ) { // Return 200 OK if the URLs do not match. $response = new \WP_REST_Response( 'OK', 200 ); } else { diff --git a/plugins/faustwp/includes/utilities/functions.php b/plugins/faustwp/includes/utilities/functions.php index ac699e0cc..8ec33d36f 100644 --- a/plugins/faustwp/includes/utilities/functions.php +++ b/plugins/faustwp/includes/utilities/functions.php @@ -45,25 +45,33 @@ function plugin_version() { } /** - * Checks if two domain strings represent the same domain. + * Performs a strict domain comparison + * Also checks for matching ports (if present). * * @param string $domain1 The first domain string. * @param string $domain2 The second domain string. - * @return bool True if the domains match, false otherwise. + * @return bool True if the domains match (including localhost, loopback, and ports), false otherwise. */ -function domains_match( $domain1, $domain2 ) { - // Extract the domain part. - $extract_domain = function ( $url ) { - $parsed_url = wp_parse_url( $url, PHP_URL_HOST ); - return $parsed_url ? $parsed_url : null; - }; +function strict_domain_match( string $domain1, string $domain2 ): bool { + // Parse URLs. + $parsed_domain1 = wp_parse_url( $domain1 ); + $parsed_domain2 = wp_parse_url( $domain2 ); - $domain1 = $extract_domain( $domain1 ); - $domain2 = $extract_domain( $domain2 ); + // Extract components. + $host1 = isset( $parsed_domain1['host'] ) ? $parsed_domain1['host'] : null; + $host2 = isset( $parsed_domain2['host'] ) ? $parsed_domain2['host'] : null; + $scheme1 = isset( $parsed_domain1['scheme'] ) ? $parsed_domain1['scheme'] : 'http'; + $scheme2 = isset( $parsed_domain2['scheme'] ) ? $parsed_domain2['scheme'] : 'http'; + $port1 = isset( $parsed_domain1['port'] ) ? (int) $parsed_domain1['port'] : ( 'https' === $scheme1 ? 443 : 80 ); + $port2 = isset( $parsed_domain2['port'] ) ? (int) $parsed_domain2['port'] : ( 'https' === $scheme2 ? 443 : 80 ); - // Remove "www" prefix from domain if present. - $domain1 = preg_replace( '/^www\./i', '', $domain1 ); - $domain2 = preg_replace( '/^www\./i', '', $domain2 ); + if ( empty( $host1 ) || empty( $host2 ) ) { + return false; + } - return null !== $domain1 && null !== $domain2 && $domain1 === $domain2; + // Normalize the hosts by removing 'www.' if present. + $normalized_host1 = preg_replace( '/^www\./', '', $host1 ); + $normalized_host2 = preg_replace( '/^www\./', '', $host2 ); + + return ( $normalized_host1 === $normalized_host2 ) && ( $scheme1 === $scheme2 ) && ( $port1 === $port2 ); } diff --git a/plugins/faustwp/tests/unit/FunctionsTests.php b/plugins/faustwp/tests/unit/FunctionsTests.php index 66bd9ab45..ea09a550d 100644 --- a/plugins/faustwp/tests/unit/FunctionsTests.php +++ b/plugins/faustwp/tests/unit/FunctionsTests.php @@ -2,23 +2,35 @@ namespace WPE\FaustWP\Tests\Unit; -use function WPE\FaustWP\Utilities\{domains_match}; +use function WPE\FaustWP\Utilities\{strict_domain_match}; class FunctionsTests extends FaustUnitTest { - public function test_domains_match() { - // Test case 1: Same domains with different protocols - $this->assertTrue(domains_match("http://example.com", "https://example.com")); + public function test_match_valid_domains_with_ports() { + $this->assertTrue( strict_domain_match( 'https://example.com:443', 'https://example.com:443' ) ); + $this->assertTrue( strict_domain_match( 'http://example.com:80', 'http://example.com:80' ) ); + $this->assertTrue( strict_domain_match( 'https://www.example.org:443', 'https://example.org:443' ) ); // Different subdomains but same domain and port + } - // Test case 2: Same domains with trailing slashes - $this->assertTrue(domains_match("http://example.com/", "http://example.com")); + public function test_match_without_ports() { + $this->assertTrue( strict_domain_match( 'https://example.com', 'https://example.com' ) ); + $this->assertTrue( strict_domain_match( 'http://www.example.org', 'http://example.org' ) ); // Different subdomains + $this->assertTrue( strict_domain_match( 'https://example.com', 'https://example.com' ) ); + $this->assertFalse( strict_domain_match( 'https://example.com', 'http://example.com' ) ); // Different schemes + } - // Test case 3: Same domains with www prefix - $this->assertTrue(domains_match("http://www.example.com", "http://example.com")); + public function test_match_different_ports() { + $this->assertFalse( strict_domain_match( 'https://example.com:443', 'https://example.com:80' ) ); + $this->assertFalse( strict_domain_match( 'http://example.com:8080', 'http://example.com:80' ) ); + $this->assertFalse( strict_domain_match( 'http://www.example.org:8080', 'http://example.org:80' ) ); // Different ports + } - // Test case 4: Different domains - $this->assertFalse(domains_match("http://example1.com", "http://example2.com")); + public function test_match_different_protocols() { + $this->assertFalse( strict_domain_match( 'https://example.com', 'http://example.com' ) ); + $this->assertFalse( strict_domain_match( 'http://www.example.org', 'https://example.org' ) ); + } - // Test case 5: Same domains with different subdomains - $this->assertFalse(domains_match("http://1.example.com", "http://2.example.com")); + public function test_scheme_mismatch_same_domain_port() { + $this->assertFalse( strict_domain_match( 'http://example.com:80', 'https://example.com:80' ) ); + $this->assertFalse( strict_domain_match( 'https://example.com:443', 'http://example.com:443' ) ); } -} +} \ No newline at end of file