Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
72.73% covered (warning)
72.73%
16 / 22
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialGoToInterwiki
76.19% covered (warning)
76.19%
16 / 21
25.00% covered (danger)
25.00%
1 / 4
11.35
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 execute
83.33% covered (warning)
83.33%
15 / 18
0.00% covered (danger)
0.00%
0 / 1
7.23
 requiresWrite
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace MediaWiki\Specials;
8
9use MediaWiki\SpecialPage\UnlistedSpecialPage;
10use MediaWiki\Title\Title;
11
12/**
13 * Landing page for non-local interwiki links.
14 *
15 * This exists for security and privacy reasons.
16 *
17 * The landing page warns people and obtains consent before leaving
18 * the site and visiting a third-party website. This can reduce
19 * impact of phishing tricks as well.
20 *
21 * This is meant to be used as the replacement URL when resolving
22 * an interwiki link things in a context where it would be
23 * navigated to without clear consent. For example, when doing
24 * a simple search (not "advanced") in which we would normally
25 * redirect to the first result if there is an exact match
26 * (e.g. Special:Search/google:foo).
27 *
28 * This is not needed for external interwiki links in content,
29 * e.g. [[google:foo]] in parser output may link directly.
30 *
31 * Further context at https://phabricator.wikimedia.org/T122209.
32 *
33 * @ingroup SpecialPage
34 */
35class SpecialGoToInterwiki extends UnlistedSpecialPage {
36    public function __construct() {
37        parent::__construct( 'GoToInterwiki' );
38    }
39
40    /** @inheritDoc */
41    public function execute( $par ) {
42        $par ??= '';
43
44        // Allow forcing an interstitial for local interwikis. This is used
45        // when a redirect page is reached via a special page which resolves
46        // to a user-dependent value (as defined by
47        // RedirectSpecialPage::personallyIdentifiableTarget). See the hack
48        // for avoiding T109724 in MediaWiki::performRequest (which also
49        // explains why we can't use a query parameter instead).
50        $force = str_starts_with( $par, 'force/' );
51        if ( $force ) {
52            $par = substr( $par, 6 );
53        }
54
55        $this->setHeaders();
56        $target = Title::newFromText( $par );
57        // Disallow special pages as a precaution against
58        // possible redirect loops.
59        if ( !$target || $target->isSpecialPage() ) {
60            $this->getOutput()->setStatusCode( 404 );
61            $this->getOutput()->addWikiMsg( 'gotointerwiki-invalid' );
62            return;
63        }
64
65        $url = $target->getFullURL();
66        if ( !$target->isExternal() || ( $target->isLocal() && !$force ) ) {
67            // Either a normal page, or a local interwiki.
68            // Just redirect.
69            $this->getOutput()->redirect( $url, '301' );
70        } else {
71            $this->getOutput()->addWikiMsg(
72                'gotointerwiki-external',
73                $url,
74                $target->getFullText()
75            );
76        }
77    }
78
79    /**
80     * @return bool
81     */
82    public function requiresWrite() {
83        return false;
84    }
85
86    /**
87     * @return string
88     */
89    protected function getGroupName() {
90        return 'redirects';
91    }
92}
93
94/** @deprecated class alias since 1.41 */
95class_alias( SpecialGoToInterwiki::class, 'SpecialGoToInterwiki' );