@@ -36,39 +36,32 @@ protected function is_valid_url( string $url ): bool {
3636 return false ;
3737 }
3838
39- // Must have a valid scheme and host, and scheme must be http or https .
39+ // Must have a valid scheme and host.
4040 if ( empty ( $ parsed_url ['scheme ' ] ) || empty ( $ parsed_url ['host ' ] ) ) {
4141 return false ;
4242 }
4343
44- if ( ! in_array ( $ parsed_url ['scheme ' ], array ( 'http ' , 'https ' ), true ) ) {
44+ // Validate host doesn't contain obviously invalid characters.
45+ // Allow alphanumeric, dots, hyphens, and underscores (for localhost, etc.).
46+ if ( preg_match ( '/[^a-z0-9.\-_]/i ' , $ parsed_url ['host ' ] ) ) {
4547 return false ;
4648 }
4749
48- // Check for duplicated protocol and invalid host characters.
49- return $ this ->validate_url_structure ( $ url , $ parsed_url );
50- }
51-
52- /**
53- * Validates URL structure for duplicated protocols and invalid host characters.
54- *
55- * @since 1.6.0
56- *
57- * @param string $url The full URL.
58- * @param array $parsed_url Parsed URL array.
59- * @return bool true if the URL structure is valid, otherwise false.
60- */
61- private function validate_url_structure ( string $ url , array $ parsed_url ): bool {
6250 // Detect duplicated protocol in the host/path portion (e.g., "https://http://example.com/").
6351 // Only check up to the query string to avoid false positives with URLs in query parameters.
64- $ url_without_query = strtok ( $ url , '? ' );
65- if ( false !== $ url_without_query && str_contains ( substr ( $ url_without_query , strlen ( $ parsed_url ['scheme ' ] ) + 3 ), ':// ' ) ) {
66- return false ;
52+ $ query_position = strpos ( $ url , '? ' );
53+
54+ if ( false !== $ query_position ) {
55+ $ url_without_query = substr ( $ url , 0 , $ query_position );
56+ } else {
57+ $ url_without_query = $ url ;
6758 }
6859
69- // Validate host doesn't contain obviously invalid characters.
70- // Allow alphanumeric, dots, hyphens, and underscores (for localhost, etc.).
71- if ( preg_match ( '/[^a-z0-9.\-_]/i ' , $ parsed_url ['host ' ] ) ) {
60+ // Check for duplicated protocol after the scheme:// portion.
61+ $ scheme_length = strlen ( $ parsed_url ['scheme ' ] );
62+ $ after_scheme = substr ( $ url_without_query , $ scheme_length + 3 );
63+
64+ if ( str_contains ( $ after_scheme , ':// ' ) ) {
7265 return false ;
7366 }
7467
0 commit comments