wiki.techinc.nl/tests/phpunit/unit/includes/utils/UrlUtilsTest.php
Petr Pchelko 5ad8ee4d92 Follow RFC 3986 on what is path in mailto URLs
This hack was originally added to wfParseUrl
as a fix for T10324 specifically for LinkFilter,
however according to the RFC 3986 this is wrong.

RFC defines that in URLs the authority component
must start with //, so in urls without //, e.g. news:
or mailto: there is no authority component, and thus
no host component, everything after : is actually a path,
so default PHP parse_url is correct.

RFC even has an example:
> For example, the URI <mailto:fred@example.com>
has a path of "fred@example.com".

It's fairly ugly to just copy-paste the hack
into LinkFilter, but I didn't find an easy and
elegant way to rewrite it without making any
changes to the link indexes values stored in the DB.

See https://datatracker.ietf.org/doc/html/rfc3986

Co-Authored-by: 沈澄心 <dringsim@qq.com>
Change-Id: I3dd04495db9c7a66f62c3914c0eff06754b7d560
2023-09-04 05:48:23 +00:00

147 lines
4.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
use MediaWiki\Utils\UrlUtils;
/**
* @coversDefaultClass \MediaWiki\Utils\UrlUtils
* @covers ::__construct
*/
class UrlUtilsTest extends MediaWikiUnitTestCase {
public function testConstructError(): void {
$this->expectException( InvalidArgumentException::class );
$this->expectExceptionMessage( 'Unrecognized option "unrecognized"' );
new UrlUtils( [ 'unrecognized' => true ] );
}
/**
* @covers ::expand
* @dataProvider UrlUtilsProviders::provideExpandException
* @param array $options
* @param string|int|null $defaultProto
* @param string $expectedClass Expected class of exception
* @param string $expectedMsg Expected exception message
*/
public function testExpandException(
array $options, $defaultProto, string $expectedClass, string $expectedMsg
): void {
$this->expectException( $expectedClass );
$this->expectExceptionMessage( $expectedMsg );
$urlUtils = new UrlUtils( $options );
$urlUtils->expand( '/', $defaultProto );
}
/**
* @covers ::expand
* @dataProvider UrlUtilsProviders::provideExpand
* @param string $input
* @param array $options
* @param string|int|null $defaultProto
* @param ?string $expected
*/
public function testExpand(
string $input, array $options, $defaultProto, ?string $expected
): void {
$urlUtils = new UrlUtils( $options );
$this->assertSame( $expected, $urlUtils->expand( $input, $defaultProto ) );
}
/**
* @covers ::getServer
* @dataProvider UrlUtilsProviders::provideGetServer
* @param array $options
* @param string|int|null $defaultProto
* @param string $expected
*/
public function testGetServer( array $options, $defaultProto, string $expected ): void {
$urlUtils = new UrlUtils( $options );
$this->assertSame( $expected, $urlUtils->getServer( $defaultProto ) );
}
/**
* @covers ::assemble
* @dataProvider UrlUtilsProviders::provideAssemble
* @param array $bits
* @param string $expected
*/
public function testAssemble( array $bits, string $expected ): void {
$this->assertSame( $expected, UrlUtils::assemble( $bits ) );
}
/**
* @covers ::removeDotSegments
* @dataProvider UrlUtilsProviders::provideRemoveDotSegments
* @param string $input
* @param string $expected
*/
public function testRemoveDotSegments( string $input, string $expected ): void {
$this->assertSame( $expected, UrlUtils::removeDotSegments( $input ) );
}
/**
* @covers ::validProtocols
* @covers ::validAbsoluteProtocols
* @covers ::validProtocolsInternal
* @dataProvider UrlUtilsProviders::provideValidProtocols
* @param string $method 'validProtocols' or 'validAbsoluteProtocols'
* @param array|string $validProtocols Value of option passed to UrlUtils
* @param string $expected
*/
public function testValidProtocols( string $method, $validProtocols, string $expected ): void {
if ( !is_array( $validProtocols ) ) {
$this->expectDeprecationAndContinue(
'/Use of \$wgUrlProtocols that is not an array was deprecated in MediaWiki 1\.39/' );
}
$urlUtils = new UrlUtils( [ UrlUtils::VALID_PROTOCOLS => $validProtocols ] );
$this->assertSame( $expected, $urlUtils->$method() );
}
/**
* @covers ::parse
* @dataProvider UrlUtilsProviders::provideParse
* @param string $url
* @param ?array $expected
*/
public function testParse( string $url, ?array $expected ): void {
$urlUtils = new UrlUtils( [ UrlUtils::VALID_PROTOCOLS => [
'//',
'http://',
'https://',
'file://',
'mailto:',
'news:',
] ] );
$actual = $urlUtils->parse( $url );
if ( $expected ) {
ksort( $expected );
}
if ( $actual ) {
ksort( $actual );
}
$this->assertSame( $expected, $actual );
}
/**
* @covers ::expandIRI
*/
public function testExpandIRI(): void {
$this->assertSame( "https://te.wikibooks.org/wiki/ఉబుటు_వాడుకరి_మార్గదర్శని",
( new UrlUtils )->expandIRI( "https://te.wikibooks.org/wiki/"
. "%E0%B0%89%E0%B0%AC%E0%B1%81%E0%B0%82%E0%B0%9F%E0%B1%81_"
. "%E0%B0%B5%E0%B0%BE%E0%B0%A1%E0%B1%81%E0%B0%95%E0%B0%B0%E0%B0%BF_"
. "%E0%B0%AE%E0%B0%BE%E0%B0%B0%E0%B1%8D%E0%B0%97%E0%B0%A6%E0%B0%B0"
. "%E0%B1%8D%E0%B0%B6%E0%B0%A8%E0%B0%BF" ) );
}
/**
* @covers ::matchesDomainList
* @dataProvider UrlUtilsProviders::provideMatchesDomainList
* @param string $url
* @param array $domains
* @param bool $expected
*/
public function testMatchesDomainList( string $url, array $domains, bool $expected ): void {
$this->assertSame( $expected, ( new UrlUtils )->matchesDomainList( $url, $domains ) );
}
}