Support protocol-less URLs from the URL util.

This commit is contained in:
barryhughes 2022-03-31 17:04:03 -07:00
parent f7937593e9
commit bc11e57e14
2 changed files with 15 additions and 9 deletions

View File

@ -97,8 +97,12 @@ class URL {
$this->components['drive'] = $matches[2]; $this->components['drive'] = $matches[2];
} }
// If there is no scheme, assume and prepend "file://". /*
if ( ! preg_match( '#^[a-z]+://#i', $this->url ) ) { * If there is no scheme, assume and prepend "file://". An exception is made for cases where the URL simply
* starts with exactly two forward slashes, which indicates 'any scheme' (most commonly, that is used when
* there is freedom to switch between 'http' and 'https').
*/
if ( ! preg_match( '#^[a-z]+://#i', $this->url ) && ! preg_match( '#^//(?!/)#', $this->url ) ) {
$this->url = 'file://' . $this->url; $this->url = 'file://' . $this->url;
} }
@ -115,19 +119,19 @@ class URL {
); );
} }
$this->components = array_merge( $this->components, $parsed_components );
// File URLs cannot have a host. However, the initial path segment *or* the Windows drive letter // File URLs cannot have a host. However, the initial path segment *or* the Windows drive letter
// (if present) may be incorrectly be interpreted as the host name. // (if present) may be incorrectly be interpreted as the host name.
if ( 'file' === $parsed_components['scheme'] && ! empty( $parsed_components['host'] ) ) { if ( 'file' === $this->components['scheme'] && ! empty( $this->components['host'] ) ) {
// If we do not have a drive letter, then simply merge the host and the path together. // If we do not have a drive letter, then simply merge the host and the path together.
if ( null === $this->components['drive'] ) { if ( null === $this->components['drive'] ) {
$parsed_components['path'] = $parsed_components['host'] . ( $parsed_components['path'] ?? '' ); $this->components['path'] = $this->components['host'] . ( $this->components['path'] ?? '' );
} }
// Always unset the host in this situation. // Restore the host to null in this situation.
unset( $parsed_components['host'] ); $this->components['host'] = null;
} }
$this->components = array_merge( $this->components, $parsed_components );
} }
/** /**
@ -325,7 +329,7 @@ class URL {
public function get_url( array $component_overrides = array() ): string { public function get_url( array $component_overrides = array() ): string {
$components = array_merge( $this->components, $component_overrides ); $components = array_merge( $this->components, $component_overrides );
$scheme = null !== $components['scheme'] ? $components['scheme'] . '://' : ''; $scheme = null !== $components['scheme'] ? $components['scheme'] . '://' : '//';
$host = null !== $components['host'] ? $components['host'] : ''; $host = null !== $components['host'] ? $components['host'] : '';
$port = null !== $components['port'] ? ':' . $components['port'] : ''; $port = null !== $components['port'] ? ':' . $components['port'] : '';
$path = $this->get_path( $components['path'] ); $path = $this->get_path( $components['path'] );

View File

@ -88,6 +88,8 @@ class URLTest extends WC_Unit_Test_Case {
array( 'https://foo.bar/parent/%2E%2e/asset.txt', 'https://foo.bar/asset.txt' ), array( 'https://foo.bar/parent/%2E%2e/asset.txt', 'https://foo.bar/asset.txt' ),
array( 'https://foo.bar/parent/%2E.%2fasset.txt', 'https://foo.bar/parent/%2E.%2fasset.txt' ), array( 'https://foo.bar/parent/%2E.%2fasset.txt', 'https://foo.bar/parent/%2E.%2fasset.txt' ),
array( 'http://localhost?../../bar', 'http://localhost/?../../bar' ), array( 'http://localhost?../../bar', 'http://localhost/?../../bar' ),
array( '//http.or.https/', '//http.or.https/' ),
array( '//schemaless/with-path', '//schemaless/with-path' ),
); );
} }