Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
95.00% |
19 / 20 |
|
66.67% |
2 / 3 |
CRAP | |
0.00% |
0 / 1 |
WMFBaseDomainExtractor | |
95.00% |
19 / 20 |
|
66.67% |
2 / 3 |
8 | |
0.00% |
0 / 1 |
getCookieDomain | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
3 | |||
matchBaseHostname | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
4.07 | |||
extractSubdomain | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace MobileFrontend; |
4 | |
5 | use MediaWiki\MediaWikiServices; |
6 | |
7 | /** |
8 | * Utility class to find base domain for given host. |
9 | * |
10 | * This class contains a hardcoded list of all WMF hosts and WMF specific domain logic. As we never |
11 | * experienced any bug requests from users and we do not change domains too often there is no need |
12 | * to put that hosts list into settings. |
13 | * |
14 | * @see T148975 |
15 | */ |
16 | class WMFBaseDomainExtractor implements BaseDomainExtractorInterface { |
17 | /** |
18 | * @var string[] |
19 | */ |
20 | private $wmfWikiHosts = [ |
21 | 'wikipedia.org', |
22 | 'wikibooks.org', |
23 | 'wikiversity.org', |
24 | 'wikinews.org', |
25 | 'wiktionary.org', |
26 | 'wikisource.org', |
27 | 'wikiquote.org', |
28 | 'wikivoyage.org', |
29 | 'wikidata.org', |
30 | 'mediawiki.org', |
31 | // local vagrant instances |
32 | 'local.wmftest.net' |
33 | ]; |
34 | /** |
35 | * @var string[] |
36 | */ |
37 | private $wmfMultiDomainWikiHosts = [ |
38 | // commons, office, meta, outreach, wikimania, incubator, etc... |
39 | '.wikimedia.org', |
40 | // beta cluster |
41 | '.beta.wmflabs.org', |
42 | // all other labs |
43 | '.wmflabs.org' |
44 | ]; |
45 | |
46 | /** |
47 | * Although some browsers will accept cookies without the initial . in domain |
48 | * RFC 2109 requires it to be included. |
49 | * |
50 | * $server must be a valid URL (i.e. with the scheme included, http or https |
51 | * or protocol-relative e.g. //en.m.wikipedia.org'). NULL and empty strings |
52 | * can also be taken but will return NULL or empty string respectively. |
53 | * |
54 | * @inheritDoc |
55 | */ |
56 | public function getCookieDomain( $server ) { |
57 | // Per http://php.net/manual/en/function.parse-url.php, |
58 | // If the requested component doesn't exist within the given |
59 | // URL, NULL will be returned. So UrlUtils::parse() will return |
60 | // null as it calls parse_url() if a valid server URL is not |
61 | // given except it's an empty string. |
62 | $services = MediaWikiServices::getInstance(); |
63 | $urlUtils = $services->getUrlUtils(); |
64 | $host = $urlUtils->parse( (string)$server )['host'] ?? ''; |
65 | |
66 | $wikiHost = $this->matchBaseHostname( $host, $this->wmfWikiHosts ); |
67 | if ( $wikiHost !== false ) { |
68 | return '.' . $wikiHost; |
69 | } |
70 | |
71 | $multiWikiHost = $this->matchBaseHostname( $host, $this->wmfMultiDomainWikiHosts ); |
72 | if ( $multiWikiHost !== false ) { |
73 | return '.' . $this->extractSubdomain( $host, $multiWikiHost ); |
74 | } |
75 | return $host; |
76 | } |
77 | |
78 | /** |
79 | * Find out whether $hostname matches or is subdomain of any host from $hosts array |
80 | * |
81 | * @param string|null $hostname Visited host |
82 | * @param string[] $hosts Array of all wikimedia hosts |
83 | * @return bool|string Returns wikimedia host base domain, false when not found |
84 | */ |
85 | private function matchBaseHostname( $hostname, array $hosts ) { |
86 | if ( $hostname === null ) { |
87 | return false; |
88 | } |
89 | foreach ( $hosts as $wmfHost ) { |
90 | if ( str_ends_with( $hostname, $wmfHost ) ) { |
91 | return $wmfHost; |
92 | } |
93 | } |
94 | return false; |
95 | } |
96 | |
97 | /** |
98 | * Parse $host and return $baseDomain with first subdomain |
99 | * ex: extractSubdomain('en.commons.wikimedia.org', '.wikimedia.org') => 'commons.wikimedia.org' |
100 | * |
101 | * This function assumes that $fullHostname is a subdomain of $baseDomain. Please |
102 | * do the str_ends_with() check first before calling this function |
103 | * |
104 | * @param string $fullHostname |
105 | * @param string $baseDomain |
106 | * @return string |
107 | */ |
108 | private function extractSubdomain( $fullHostname, $baseDomain ) { |
109 | $length = strlen( $baseDomain ); |
110 | |
111 | $subdomains = explode( '.', substr( $fullHostname, 0, -$length ) ); |
112 | $subdomain = array_pop( $subdomains ); |
113 | return $subdomain . $baseDomain; |
114 | } |
115 | |
116 | } |