Skip to content
Permalink
Tree: bf699433ff
Find file Copy path
Find file Copy path
187 contributors

Users who have contributed to this file

@reedy @atdt @jdforrester @demon @MaxSem @legoktm @Krinkle @AaronSchulz @catrope @hashar @filbertkm @dereckson @Krenair @tgr @kaldari @tstarling @lavagetto @nyurik @matthiasmullie @Nikerabbit @ebernhardson @addshore @jdlrobson @bd808 @MatmaRex @mariushoch
4027 lines (3414 sloc) 124 KB
<?php
# WARNING: This file is publicly viewable on the web. Do not put private data here.
# CommonSettings.php is the main configuration file of the WMF cluster.
# This file contains settings common to all (or many) WMF wikis.
# For per-wiki configuration, see InitialiseSettings.php.
#
# This for PRODUCTION.
#
# Effective load order:
# - multiversion
# - mediawiki/DefaultSettings.php
# - wmf-config/InitialiseSettings.php
# - wmf-config/CommonSettings.php [THIS FILE]
#
# Full load tree:
# - multiversion
# - mediawiki/index.php (or other entry point)
# - mediawiki/WebStart.php
# - mediawiki/Setup.php
# - mediawiki/DefaultSettings.php
# - mediawiki/LocalSettings.php
# `-- wmf-config/CommonSettings.php [THIS FILE]
# |-- wmf-config/*Services.php
# |-- wmf-config/etcd.php
# |-- wmf-config/wgConf.php
# |-- wmf-config/InitialiseSettings.php
# |-- private/PrivateSettings.php
# |-- wmf-config/logging.php
# |-- wmf-config/redis.php
# |-- wmf-config/filebackend.php
# |-- wmf-config/db-*.php
# |-- wmf-config/mc.php
# |
# `-- (main stuff in CommonSettings.php)
#
use MediaWiki\Auth\AuthenticationResponse;
use MediaWiki\Logger\LoggerFactory;
use Wikimedia\MWConfig\ServiceConfig;
use Wikimedia\MWConfig\XWikimediaDebug;
# Godforsaken hack to work around problems with the reverse proxy caching changes...
#
# To minimize damage on fatal PHP errors, output a default no-cache header
# It will be overridden in cases where we actually specify caching behavior.
#
# More modern PHP versions will send a 500 result code on fatal error,
# at least sometimes, but what we're running will send a 200.
if ( PHP_SAPI !== 'cli' ) {
header( "Cache-control: no-cache" );
} else {
# Override for sanity's sake. Log errors to stderr.
ini_set( 'display_errors', 'stderr' );
}
// Clobber any value in $_SERVER['SERVER_SOFTWARE'] other than Apache, so that
// IEUrlExtension::haveUndecodedRequestUri() always thinks we're running Apache.
// Otherwise, the absence of 'Apache' from $_SERVER['SERVER_SOFTWARE'] causes it
// to distrust REQUEST_URI, which leads to incorrect behavior.
if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
$_SERVER['SERVER_SOFTWARE'] = 'Apache';
}
if ( isset( $_SERVER['SERVER_ADDR'] ) ) {
ini_set( 'error_append_string', ' (' . $_SERVER['SERVER_ADDR'] . ')' );
}
# ----------------------------------------------------------------------
# Initialisation
# Load classes required by configuration files
require_once __DIR__ . '/../src/XWikimediaDebug.php';
require_once __DIR__ . '/../src/ServiceConfig.php';
# Get the version object for this Wiki (must be set by now, along with $IP)
if ( !class_exists( 'MWMultiVersion' ) ) {
print "No MWMultiVersion instance initialized! MWScript.php wrapper not used?\n";
exit( 1 );
}
$multiVersion = MWMultiVersion::getInstance();
$includePaths = [ $IP, '/usr/local/lib/php', '/usr/share/php' ];
if ( is_readable( "$IP/vendor/composer/include_paths.php" ) ) {
$includePaths = array_merge(
require "$IP/vendor/composer/include_paths.php",
$includePaths
);
}
set_include_path( implode( PATH_SEPARATOR, $includePaths ) );
### List of some service hostnames
# 'meta' : meta wiki for user editable content
# 'upload' : hostname where files are hosted
# 'wikidata': hostname for the data repository
# Whenever all realms/datacenters should use the same host, do not use
# $wmfHostnames but use the hardcoded hostname instead. A good example are the
# spam blacklists hosted on meta.wikimedia.org which you will surely want to
# reuse.
$wmfHostnames = [];
switch ( $wmfRealm ) {
case 'labs':
$wmfHostnames['meta'] = 'meta.wikimedia.beta.wmflabs.org';
$wmfHostnames['test'] = 'test.wikimedia.beta.wmflabs.org';
$wmfHostnames['upload'] = 'upload.beta.wmflabs.org';
$wmfHostnames['wikidata'] = 'wikidata.beta.wmflabs.org';
break;
case 'production':
default:
$wmfHostnames['meta'] = 'meta.wikimedia.org';
$wmfHostnames['test'] = 'test.wikipedia.org';
$wmfHostnames['upload'] = 'upload.wikimedia.org';
$wmfHostnames['wikidata'] = 'www.wikidata.org';
break;
}
# This must be set *after* the DefaultSettings.php inclusion
$wgDBname = $multiVersion->getDatabase();
# Better have the proper username (T46251)
$wgDBuser = 'wikiuser';
# wmf-config directory (in common/)
$wmfConfigDir = "$IP/../wmf-config";
# Get all the service definitions
$wmfAllServices = ServiceConfig::getInstance()->getAllServices();
# Shorthand when we have no master-slave situation to keep into account
$wmfLocalServices = $wmfAllServices[$wmfDatacenter];
# Configuration from etcd (sets $wmfMasterDatacenter, $wgReadOnly and wmfEtcdLastModifiedIndex)
require "$wmfConfigDir/etcd.php";
wmfEtcdConfig();
$wmfMasterServices = $wmfAllServices[$wmfMasterDatacenter];
# Must be set before InitialiseSettings.php:
$wmfUdp2logDest = $wmfLocalServices['udp2log'];
# Initialise wgConf
require "$wmfConfigDir/wgConf.php";
/**
* @param $conf
*/
function wmfLoadInitialiseSettings( $conf ) {
global $wmfConfigDir;
require "$wmfConfigDir/InitialiseSettings.php";
}
// Do not add wikimedia.org, because of other sites under that domain (such as codereview-proxy.wikimedia.org)
$wgLocalVirtualHosts = [
'wikipedia.org',
'wiktionary.org',
'wikiquote.org',
'wikibooks.org',
'wikiquote.org',
'wikinews.org',
'wikisource.org',
'wikiversity.org',
'wikivoyage.org',
'www.wikidata.org',
'meta.wikimedia.org', // Presumably needed to load meta spam list. Any others?
'commons.wikimedia.org',
'www.mediawiki.org',
];
# Is this database listed in dblist?
# Note: $wgLocalDatabases set in wgConf.php.
# Note: must be done before calling $multiVersion functions other than getDatabase().
if ( array_search( $wgDBname, $wgLocalDatabases ) === false ) {
# No? Load missing.php
if ( $wgCommandLineMode ) {
print "Database name $wgDBname is not listed in dblist\n";
} else {
require "$wmfConfigDir/missing.php";
}
exit;
}
# Determine domain and language and the directories for this instance
list( $site, $lang ) = $wgConf->siteFromDB( $wgDBname );
$wmgVersionNumber = $multiVersion->getVersionNumber();
# Try configuration cache
$filename = "/tmp/mw-cache-$wmgVersionNumber/conf-$wgDBname";
if ( defined( 'HHVM_VERSION' ) ) {
$filename .= '-hhvm';
}
$globals = false;
if ( @filemtime( $filename ) >= filemtime( "$wmfConfigDir/InitialiseSettings.php" ) ) {
$cacheRecord = @file_get_contents( $filename );
if ( $cacheRecord !== false ) {
$globals = unserialize( $cacheRecord );
}
}
if ( !$globals ) {
# Get configuration from SiteConfiguration object
require "$wmfConfigDir/InitialiseSettings.php";
# Collect all the dblist tags associated with this wiki
$wikiTags = [];
# When updating list please run ./docroot/noc/createTxtFileSymlinks.sh
# Expand computed dblists with ./multiversion/bin/expanddblist
foreach ( [
'private',
'fishbowl',
'special',
'closed',
'flow',
'flaggedrevs',
'small',
'medium',
'large',
'wikimania',
'wikidata',
'wikibaserepo',
'wikidataclient',
'wikidataclient-test',
'visualeditor-nondefault',
'commonsuploads',
'nonbetafeatures',
'group0',
'group1',
'group2',
'wikipedia',
'nonglobal',
'wikitech',
'nonecho',
'mobilemainpagelegacy',
'wikipedia-cyrillic',
'wikipedia-e-acute',
'wikipedia-devanagari',
'wikipedia-english',
'nowikidatadescriptiontaglines',
'related-articles-footer-blacklisted-skins',
'top6-wikipedia',
'rtl',
'pp_stage0',
'pp_stage1',
'cirrussearch-big-indices',
] as $tag ) {
$dblist = MWWikiversions::readDbListFile( $tag );
if ( in_array( $wgDBname, $dblist ) ) {
$wikiTags[] = $tag;
}
}
$dbSuffix = ( $site === 'wikipedia' ) ? 'wiki' : $site;
$confParams = [
'lang' => $lang,
'docRoot' => $_SERVER['DOCUMENT_ROOT'],
'site' => $site,
];
// Add a per-language tag as well
$wikiTags[] = $wgConf->get( 'wgLanguageCode', $wgDBname, $dbSuffix, $confParams, $wikiTags );
$globals = $wgConf->getAll( $wgDBname, $dbSuffix, $confParams, $wikiTags );
# Save cache
@mkdir( '/tmp/mw-cache-' . $wmgVersionNumber );
$tmpFile = tempnam( '/tmp/', "conf-$wmgVersionNumber-$wgDBname" );
if ( $tmpFile && file_put_contents( $tmpFile, serialize( $globals ) ) ) {
if ( !rename( $tmpFile, $filename ) ) {
// T136258: Rename failed, cleanup temp file
unlink( $tmpFile );
};
}
}
extract( $globals );
# -------------------------------------------------------------------------
# Settings common to all wikis
# Private settings such as passwords, that shouldn't be published
# Needs to be before db.php
require "$wmfConfigDir/../private/PrivateSettings.php";
$wgMemCachedServers = [];
require "$wmfConfigDir/logging.php";
require "$wmfConfigDir/redis.php";
require "$wmfConfigDir/filebackend.php";
# Override certain settings in command-line mode
# This must be after InitialiseSettings.php is processed (T197475)
if ( PHP_SAPI === 'cli' ) {
$wgShowExceptionDetails = true;
$wgShowDBErrorBacktrace = true;
# APC not available in CLI mode
$wgLanguageConverterCacheType = CACHE_NONE;
}
if ( XWikimediaDebug::getInstance()->hasOption( 'readonly' ) ) {
$wgReadOnly = 'X-Wikimedia-Debug';
}
if ( $wmfRealm === 'labs' ) {
require "$wmfConfigDir/db-labs.php";
require "$wmfConfigDir/mc-labs.php";
} else {
require "$wmfConfigDir/mc.php";
require "$wmfConfigDir/db-{$wmfDatacenter}.php";
}
// Set $wgProfiler to the value provided by PhpAutoPrepend.php
if ( isset( $wmgProfiler ) ) {
$wgProfiler = $wmgProfiler;
}
# Disallow web request DB transactions slower than this
$wgMaxUserDBWriteDuration = 3;
# Activate read-only mode for bots when lag is getting high.
# This should be lower than 'max lag' in the LBFactory conf.
$wgAPIMaxLagThreshold = 3;
ini_set( 'memory_limit', $wmgMemoryLimit );
# Change calls to wfShellWikiCmd() to use MWScript.php wrapper
$wgHooks['wfShellWikiCmd'][] = 'MWMultiVersion::onWfShellMaintenanceCmd';
setlocale( LC_ALL, 'en_US.UTF-8' );
# ######################################################################
# Revision backend settings
# ######################################################################
$wgCompressRevisions = true;
$wgExternalStores = [ 'DB' ];
$wgContentHandlerUseDB = true;
# ######################################################################
# Performance settings and restrictions
# ######################################################################
// Replicas aren't fast enough to generate all special pages all the time.
$wgMiserMode = true;
$wgQueryCacheLimit = 5000;
// ParserCache expire time set to 30 days
$wgParserCacheExpireTime = 86400 * 30;
# ######################################################################
# Account- and notifications-related settings
# ######################################################################
$wgSecureLogin = true;
$wgMaxNameChars = 85;
// Turn this on so UserMailer::send() will be able to send both text and html email
$wgAllowHTMLEmail = true;
$wgEnotifUserTalk = true;
$wgEnotifWatchlist = true;
// Keep this true; it's just whether the feature is available at all, not the default
// setting. T142727
$wgEnotifMinorEdits = true;
# ######################################################################
# Anti-abuse settings
# ######################################################################
$wgCookieSetOnAutoblock = true;
$wgCookieSetOnIpBlock = true;
$wgEnableUserEmailBlacklist = true;
# ######################################################################
# Legal matters
# ######################################################################
$wgRightsIcon = '//creativecommons.org/images/public/somerights20.png';
# ######################################################################
# ResourceLoader settings
# ######################################################################
unset( $wgStylePath );
$wgInternalServer = $wgCanonicalServer;
$wgArticlePath = '/wiki/$1';
$wgScriptPath = '/w';
$wgScript = "{$wgScriptPath}/index.php";
$wgRedirectScript = "{$wgScriptPath}/redirect.php";
$wgLoadScript = "{$wgScriptPath}/load.php";
// Don't include a hostname in $wgResourceBasePath and friends
// - Goes wrong otherwise on mobile web (T106966, T112646)
// - Improves performance by leveraging HTTP/2
// - $wgLocalStylePath MUST be relative
// Apache rewrites /w/resources, /w/extensions, and /w/skins to /w/static.php (T99096)
$wgResourceBasePath = '/w';
$wgExtensionAssetsPath = "{$wgResourceBasePath}/extensions";
$wgStylePath = "{$wgResourceBasePath}/skins";
$wgLocalStylePath = $wgStylePath;
// Cache ResourceLoader modules in localStorage
$wgResourceLoaderStorageEnabled = true;
// Deprecated
$wgIncludeLegacyJavaScript = true;
$wgResourceLoaderMaxQueryLength = 5000;
if ( $wmgReduceStartupExpiry ) {
$wgResourceLoaderMaxage['unversioned'] = [ 'server' => 30, 'client' => 30 ];
}
// Cache version key for ResourceLoader client-side module store
// - Bumped to fix breakage due to old /static/$branchName/ urls still
// being cached after the switch to /w/static.php (T134368).
// - Bumped to fix broken SVG embedding being cached (T176884)
$wgResourceLoaderStorageVersion .= '-3';
$wgCacheDirectory = '/tmp/mw-cache-' . $wmgVersionNumber;
$wgGitInfoCacheDirectory = "$IP/cache/gitinfo";
// @var string|bool: E-mail address to send notifications to, or false to disable notifications.
$wmgAddWikiNotify = "newprojects@lists.wikimedia.org";
$wgLocalisationCacheConf['storeClass'] = LCStoreCDB::class;
$wgLocalisationCacheConf['storeDirectory'] = "$IP/cache/l10n";
$wgLocalisationCacheConf['manualRecache'] = true;
// T29320: skip MessageBlobStore::clear(); handle via refreshMessageBlobs.php instead
$wgHooks['LocalisationCacheRecache'][] = function ( $cache, $code, &$allData, &$purgeBlobs = true ) {
$purgeBlobs = false;
return true;
};
// Add some useful config data to query=siteinfo
$wgHooks['APIQuerySiteInfoGeneralInfo'][] = function ( $module, &$data ) {
global $wmfMasterDatacenter;
global $wmfEtcdLastModifiedIndex;
global $wmgCirrusSearchDefaultCluster;
global $wgCirrusSearchDefaultCluster;
$data['wmf-config'] = [
'wmfMasterDatacenter' => $wmfMasterDatacenter,
'wmfEtcdLastModifiedIndex' => $wmfEtcdLastModifiedIndex,
'wmgCirrusSearchDefaultCluster' => $wmgCirrusSearchDefaultCluster,
'wgCirrusSearchDefaultCluster' => $wgCirrusSearchDefaultCluster,
];
};
$wgEmergencyContact = 'noc@wikipedia.org';
$wgShowIPinHeader = false;
$wgRCMaxAge = 30 * 86400;
$wgTmpDirectory = '/tmp';
$wgSQLMode = null;
# Object cache and session settings
$wgSessionName = $wgDBname . 'Session';
$pcTemplate = [ 'type' => 'mysql',
'dbname' => 'parsercache',
'user' => $wgDBuser,
'password' => $wgDBpassword,
'flags' => 0,
];
$pcServers = [];
foreach ( $wmgParserCacheDBs as $tag => $host ) {
$pcServers[$tag] = [ 'host' => $host ] + $pcTemplate;
}
$wgObjectCaches['mysql-multiwrite'] = [
'class' => 'MultiWriteBagOStuff',
'caches' => [
0 => [
'factory' => [ 'ObjectCache', 'getInstance' ],
'args' => [ 'mcrouter' ]
],
1 => [
'class' => 'SqlBagOStuff',
'servers' => $pcServers,
'purgePeriod' => 0,
'tableName' => 'pc',
'shards' => 256,
'reportDupes' => false
],
],
'replication' => 'async',
'reportDupes' => false
];
// T203888: Purge Wikidata Lexeme parser cache for senses deployment - Addshore
if ( $wgDBname === 'wikidatawiki' ) {
/** @var WikiPage $wikiPage */
$wgHooks['RejectParserCacheValue'][] = function ( $value, $wikiPage, $popts ) {
if (
$wikiPage->getTitle()->getNamespace() === 146 &&
$value->expired( '20181018105500' )
) {
return false;
}
return true;
};
}
session_name( $lang . 'wikiSession' );
// Use PBKDF2 for password hashing (T70766)
$wgPasswordDefault = 'pbkdf2';
// This needs to be increased as allowable by server performance
$wgPasswordConfig['pbkdf2'] = [
'class' => 'Pbkdf2Password',
'algo' => 'sha512',
'cost' => '128000',
'length' => '64',
];
// Temporary for T57420
$wgPasswordConfig['null'] = [ 'class' => InvalidPassword::class ];
// Password policies; see https://meta.wikimedia.org/wiki/Password_policy
$wmgPrivilegedPolicy = [
'MinimalPasswordLength' => [ 'value' => 10, 'suggestChangeOnLogin' => true ],
'MinimumPasswordLengthToLogin' => [ 'value' => 1, 'suggestChangeOnLogin' => true ],
'PasswordNotInLargeBlacklist' => [ 'value' => true, 'suggestChangeOnLogin' => true ],
];
if ( $wgDBname === 'labswiki' || $wgDBname === 'labtestwiki' ) {
$wgPasswordPolicy['policies']['default']['MinimalPasswordLength'] = [
'value' => 10,
'suggestChangeOnLogin' => true,
];
} else {
foreach ( $wmgPrivilegedGroups as $group ) {
// On non-SUL wikis this is the effective password policy. On SUL wikis, it will be overridden
// in the PasswordPoliciesForUser hook, but still needed for Special:PasswordPolicies
if ( $group === 'user' ) {
$group = 'default'; // For e.g. private and fishbowl wikis; covers 'user' in password policies
}
$wgPasswordPolicy['policies'][$group] = array_merge( $wgPasswordPolicy['policies'][$group] ?? [],
$wmgPrivilegedPolicy );
}
}
$wgPasswordPolicy['policies']['default']['MinimalPasswordLength'] = [
'value' => 8,
'suggestChangeOnLogin' => false,
];
$wgPasswordPolicy['policies']['default']['PasswordCannotBePopular'] = [
'value' => 100,
'suggestChangeOnLogin' => true,
];
// Enforce password policy when users login on other wikis; also for sensitive global groups
// FIXME does this just duplicate the the global policy checks down in the main $wmgUseCentralAuth block?
if ( $wmgUseCentralAuth ) {
$wgHooks['PasswordPoliciesForUser'][] = function ( User $user, array &$effectivePolicy ) use ( $wmgPrivilegedPolicy ) {
$privilegedGroups = wmfGetPrivilegedGroups( $user->getName(), $user );
if ( $privilegedGroups ) {
$effectivePolicy = UserPasswordPolicy::maxOfPolicies( $effectivePolicy, $wmgPrivilegedPolicy );
// hack; PasswordNotInLargeBlacklist obsoletes PasswordCannotBePopular but maxOfPolicies can't handle that
if ( $effectivePolicy['PasswordNotInLargeBlacklist'] ?? false ) {
$effectivePolicy['PasswordCannotBePopular'] = 0;
}
if ( in_array( 'staff', $privilegedGroups, true ) ) {
$effectivePolicy['MinimumPasswordLengthToLogin'] = [
'value' => 10,
'suggestChangeOnLogin' => true,
];
}
}
return true;
};
}
// For global policies, see $wgCentralAuthGlobalPasswordPolicies below
$wgEnableBotPasswords = $wmgEnableBotPasswords;
$wgBotPasswordsCluster = $wmgBotPasswordsCluster;
$wgBotPasswordsDatabase = $wmgBotPasswordsDatabase;
# ######################################################################
# Server security settings
# ######################################################################
$wgRestrictionMethod = 'firejail';
$wgUseImageMagick = true;
$wgImageMagickConvertCommand = '/usr/local/bin/mediawiki-firejail-convert';
$wgSharpenParameter = '0x0.8'; # for IM>6.5, T26857
if ( $wmgUsePagedTiffHandler ) {
wfLoadExtension( 'PagedTiffHandler' );
}
$wgTiffMaxMetaSize = 1048576;
$wgMaxImageArea = 10e7; // 100MP
$wgMaxAnimatedGifArea = 10e7; // 100MP
$wgFileExtensions = array_merge( $wgFileExtensions, $wmgFileExtensions );
$wgFileBlacklist = array_merge( $wgFileBlacklist, $wmgFileBlacklist );
if ( isset( $wmgUploadStashMaxAge ) ) {
$wgUploadStashMaxAge = $wmgUploadStashMaxAge;
}
if ( $wmgPrivateWikiUploads ) {
# mav forced me to --midom
$wgFileExtensions[] = 'ppt';
# mav forced me as well!!! -- Tim
$wgFileExtensions[] = 'doc';
# adding since removed elsewhere now -- 2007-08-21 -- brion
$wgFileExtensions[] = 'xls';
# delphine made me do it!!!!! --brion
$wgFileExtensions[] = 'eps';
$wgFileExtensions[] = 'zip';
# OpenOffice, hell if we're going to allow doc we may as well have these too -- Tim
$wgFileExtensions[] = 'odf';
$wgFileExtensions[] = 'odp';
$wgFileExtensions[] = 'ods';
$wgFileExtensions[] = 'odt';
$wgFileExtensions[] = 'odg'; // OpenOffice Graphics
$wgFileExtensions[] = 'ott'; // Templates
# Temporary for office work :P
$wgFileExtensions[] = 'wmv';
$wgFileExtensions[] = 'dv';
$wgFileExtensions[] = 'avi';
$wgFileExtensions[] = 'mov';
$wgFileExtensions[] = 'aif'; // "
$wgFileExtensions[] = 'aiff'; // "
# Because I hate having to find print drivers -- tomasz
$wgFileExtensions[] = 'ppd';
# InDesign & PhotoShop, Illustrator wanted for Chapters logo work
$wgFileExtensions[] = 'indd';
$wgFileExtensions[] = 'inx';
$wgFileExtensions[] = 'psd';
$wgFileExtensions[] = 'ai';
# Pete made me --Roan
$wgFileExtensions[] = 'omniplan';
# Dia Diagrams files --fred.
$wgFileExtensions[] = 'dia';
# Font files (so we can upload Montserrat to donatewiki) --Roan
$wgFileExtensions[] = 'woff';
$wgFileExtensions[] = 'woff2';
// To allow OpenOffice doc formats we need to not blacklist zip files
$wgMimeTypeBlacklist = array_diff(
$wgMimeTypeBlacklist,
[ 'application/zip' ] );
}
# ######################################################################
# SVG renderer settings
# ######################################################################
$wgSVGConverter = 'rsvg-secure';
$wgSVGConverterPath = '/usr/bin';
$wgSVGMaxSize = 4096; // 1024's a bit low?
# Hack for rsvg broken by security patch
$wgSVGConverters['rsvg-broken'] = '$path/rsvg-convert -w $width -h $height -o $output < $input';
if ( defined( 'HHVM_VERSION' ) ) {
# Newer librsvg supports a sane security model by default and doesn't need our security patch
$wgSVGConverters['rsvg-secure'] = '$path/rsvg-convert -u -w $width -h $height -o $output $input';
} else {
# This converter will only work when rsvg has a suitable security patch
$wgSVGConverters['rsvg-secure'] = '$path/rsvg-convert --no-external-files -w $width -h $height -o $output $input';
}
# ######################################################################
# DJVU renderer settings
# ######################################################################
$wgDjvuDump = '/usr/bin/djvudump';
$wgDjvuRenderer = '/usr/bin/ddjvu';
$wgDjvuTxt = '/usr/bin/djvutxt';
# ######################################################################
# Reverse proxy Configuration
# ######################################################################
$wgStatsdServer = $wmfLocalServices['statsd'];
$wgUseCdn = true;
if ( $wmfRealm === 'production' ) {
require "$wmfConfigDir/reverse-proxy.php";
} elseif ( $wmfRealm === 'labs' ) {
$wgStatsdMetricPrefix = 'BetaMediaWiki';
require "$wmfConfigDir/reverse-proxy-staging.php";
}
// CORS (cross-domain AJAX, T22814)
// This lists the domains that are accepted as *origins* of CORS requests
// DO NOT add domains here that aren't WMF wikis unless you really know what you're doing
if ( $wmgUseCORS ) {
$wgCrossSiteAJAXdomains = [
'*.wikipedia.org',
'*.wikinews.org',
'*.wiktionary.org',
'*.wikibooks.org',
'*.wikiversity.org',
'*.wikisource.org',
'wikisource.org',
'*.wikiquote.org',
'www.wikidata.org',
'm.wikidata.org',
'test.wikidata.org',
'test.m.wikidata.org',
'*.wikivoyage.org',
'www.mediawiki.org',
'm.mediawiki.org',
'advisory.wikimedia.org',
'advisory.m.wikimedia.org',
'affcom.wikimedia.org',
'auditcom.wikimedia.org',
'boardgovcom.wikimedia.org',
'board.wikimedia.org',
'chair.wikimedia.org',
'checkuser.wikimedia.org',
'checkuser.m.wikimedia.org',
'collab.wikimedia.org',
'commons.wikimedia.org',
'commons.m.wikimedia.org',
'test-commons.wikimedia.org',
'test-commons.m.wikimedia.org',
'donate.wikimedia.org',
'exec.wikimedia.org',
'grants.wikimedia.org',
'incubator.wikimedia.org',
'incubator.m.wikimedia.org',
'internal.wikimedia.org',
'login.wikimedia.org',
'meta.wikimedia.org',
'meta.m.wikimedia.org',
'movementroles.wikimedia.org',
'office.wikimedia.org',
'office.m.wikimedia.org',
'otrs-wiki.wikimedia.org',
'otrs-wiki.m.wikimedia.org',
'outreach.wikimedia.org',
'outreach.m.wikimedia.org',
'quality.wikimedia.org',
'quality.m.wikimedia.org',
'searchcom.wikimedia.org',
'spcom.wikimedia.org',
'species.wikimedia.org',
'species.m.wikimedia.org',
'steward.wikimedia.org',
'steward.m.wikimedia.org',
'strategy.wikimedia.org',
'strategy.m.wikimedia.org',
'usability.wikimedia.org',
'usability.m.wikimedia.org',
'wikimania.wikimedia.org',
'wikimania.m.wikimedia.org',
'wikimania????.wikimedia.org',
'wikimania????.m.wikimedia.org',
'wikimaniateam.wikimedia.org',
'wikimaniateam.m.wikimedia.org',
'am.wikimedia.org',
'am.m.wikimedia.org',
'ar.wikimedia.org',
'ar.m.wikimedia.org',
'bd.wikimedia.org',
'bd.m.wikimedia.org',
'be.wikimedia.org',
'be.m.wikimedia.org',
'br.wikimedia.org',
'br.m.wikimedia.org',
'ca.wikimedia.org',
'ca.m.wikimedia.org',
'cn.wikimedia.org',
'cn.m.wikimedia.org',
'co.wikimedia.org',
'co.m.wikimedia.org',
'dk.wikimedia.org',
'dk.m.wikimedia.org',
'ec.wikimedia.org',
'ec.m.wikimedia.org',
'et.wikimedia.org',
'et.m.wikimedia.org',
'fi.wikimedia.org',
'fi.m.wikimedia.org',
'hi.wikimedia.org',
'hi.m.wikimedia.org',
'id.wikimedia.org',
'id.m.wikimedia.org',
'il.wikimedia.org',
'il.m.wikimedia.org',
'mai.wikimedia.org',
'mai.m.wikimedia.org',
'mk.wikimedia.org',
'mk.m.wikimedia.org',
'mx.wikimedia.org',
'mx.m.wikimedia.org',
'nl.wikimedia.org',
'nl.m.wikimedia.org',
'noboard-chapters.wikimedia.org',
'no.wikimedia.org',
'no.m.wikimedia.org',
'nyc.wikimedia.org',
'nyc.m.wikimedia.org',
'nz.wikimedia.org',
'nz.m.wikimedia.org',
'pa-us.wikimedia.org',
'pa-us.m.wikimedia.org',
'pl.wikimedia.org',
'pl.m.wikimedia.org',
'pt.wikimedia.org',
'pt.m.wikimedia.org',
'romd.wikimedia.org',
'romd.m.wikimedia.org',
'rs.wikimedia.org',
'rs.m.wikimedia.org',
'ru.wikimedia.org',
'ru.m.wikimedia.org',
'se.wikimedia.org',
'se.m.wikimedia.org',
'tr.wikimedia.org',
'tr.m.wikimedia.org',
'ua.wikimedia.org',
'ua.m.wikimedia.org',
'wb.wikimedia.org',
'wb.m.wikimedia.org',
];
}
wfLoadSkins( [ 'Vector', 'MonoBook', 'Modern', 'CologneBlue', 'Timeless' ] );
// The Print logo for Vector should use the same wordmark as Minerva
// This avoids duplicate config entries (T169732)
if (
isset( $wgMinervaCustomLogos['copyright'] ) &&
isset( $wgMinervaCustomLogos['copyright-height'] ) &&
isset( $wgMinervaCustomLogos['copyright-width'] )
) {
$wgVectorPrintLogo = [
'width' => $wgMinervaCustomLogos['copyright-width'],
'height' => $wgMinervaCustomLogos['copyright-height'],
'url' => $wgMinervaCustomLogos['copyright'],
];
}
// Grants and rights
// Note these have to be visible on all wikis, not just the ones the
// extension is enabled on, for proper display in OAuth pages and such.
// Adding Flaggedrevs rights so that they are available for globalgroups/staff rights - JRA 2013-07-22
$wgAvailableRights[] = 'autoreviewrestore';
$wgAvailableRights[] = 'stablesettings';
$wgAvailableRights[] = 'review';
$wgAvailableRights[] = 'unreviewedpages';
$wgAvailableRights[] = 'movestable';
$wgAvailableRights[] = 'validate';
$wgGrantPermissions['editprotected']['movestable'] = true;
// So that protection rights can be assigned to global groups
$wgAvailableRights[] = 'templateeditor';
$wgAvailableRights[] = 'editeditorprotected';
$wgAvailableRights[] = 'editextendedsemiprotected';
$wgAvailableRights[] = 'extendedconfirmed';
$wgAvailableRights[] = 'autoreviewprotected';
$wgGrantPermissions['editprotected']['templateeditor'] = true;
$wgGrantPermissions['editprotected']['editeditorprotected'] = true;
$wgGrantPermissions['editprotected']['editextendedsemiprotected'] = true;
$wgGrantPermissions['editprotected']['extendedconfirmed'] = true;
$wgGrantPermissions['editprotected']['autoreviewprotected'] = true;
// Allow tboverride with editprotected, and tboverride-account with createaccount
$wgGrantPermissions['editprotected']['tboverride'] = true;
$wgGrantPermissions['createaccount']['tboverride-account'] = true;
// Adding Flow's rights so that they are available for global groups/staff rights
$wgAvailableRights[] = 'flow-create-board';
$wgAvailableRights[] = 'flow-edit-post';
$wgAvailableRights[] = 'flow-suppress';
$wgAvailableRights[] = 'flow-hide';
$wgAvailableRights[] = 'flow-delete';
// Checkuser
$wgGrantPermissions['checkuser']['checkuser'] = true;
$wgGrantPermissions['checkuser']['checkuser-log'] = true;
// Categorize additional groups defined above.
// Corresponding messages are mwoauth-grant-* in WikimediaMessages.
$wgGrantPermissionGroups['checkuser'] = 'administration';
// Rights needed to interact with wikibase
$wgGrantPermissions['createeditmovepage']['property-create'] = true;
$wgGrantPermissions['editpage']['item-term'] = true;
$wgGrantPermissions['editpage']['item-merge'] = true;
$wgGrantPermissions['editpage']['property-term'] = true;
$wgGrantPermissions['editpage']['item-redirect'] = true;
// Extension:Newsletter, so that they are available for global groups --MA 2017.09.09
$wgAvailableRights[] = 'newsletter-create';
$wgAvailableRights[] = 'newsletter-delete';
$wgAvailableRights[] = 'newsletter-manage';
$wgAvailableRights[] = 'newsletter-restore';
// Enable a "viewdeletedfile" userright for [[m:Global deleted image review]] (T16801)
$wgAvailableRights[] = 'viewdeletedfile';
$wgHooks['TitleQuickPermissions'][] = function ( Title $title, User $user, $action, &$errors, $doExpensiveQueries, $short ) {
return ( !in_array( $action, [ 'deletedhistory', 'deletedtext' ] ) || !$title->inNamespaces( NS_FILE, NS_FILE_TALK ) || !$user->isAllowed( 'viewdeletedfile' ) );
};
if ( $wmgUseTimeline ) {
include "$wmfConfigDir/timeline.php";
}
# Most probably only used by EasyTimeline which is conditionally included above
# but it is hard know whether there other use cases.
putenv( "GDFONTPATH=/srv/mediawiki/fonts" );
if ( $wmgUseWikiHiero ) {
wfLoadExtension( 'wikihiero' );
}
wfLoadExtension( 'SiteMatrix' );
// Config for sitematrix
$wgSiteMatrixFile = ( $wmfRealm === 'labs' ) ? "$IP/../langlist-labs" : "$IP/../langlist";
$wgSiteMatrixSites = [
'wiki' => [
'name' => 'Wikipedia',
'host' => 'www.wikipedia.org',
'prefix' => 'w',
],
'wiktionary' => [
'name' => 'Wiktionary',
'host' => 'www.wiktionary.org',
'prefix' => 'wikt',
],
'wikibooks' => [
'name' => 'Wikibooks',
'host' => 'www.wikibooks.org',
'prefix' => 'b',
],
'wikinews' => [
'name' => 'Wikinews',
'host' => 'www.wikinews.org',
'prefix' => 'n',
],
'wikiquote' => [
'name' => 'Wikiquote',
'host' => 'www.wikiquote.org',
'prefix' => 'q',
],
'wikisource' => [
'name' => 'Wikisource',
'host' => 'www.wikisource.org',
'prefix' => 's',
],
'wikiversity' => [
'name' => 'Wikiversity',
'host' => 'www.wikiversity.org',
'prefix' => 'v',
],
'wikivoyage' => [
'name' => 'Wikivoyage',
'host' => 'www.wikivoyage.org',
'prefix' => 'voy',
],
];
$wgSiteMatrixClosedSites = MWWikiversions::readDbListFile( 'closed' );
$wgSiteMatrixPrivateSites = MWWikiversions::readDbListFile( 'private' );
$wgSiteMatrixFishbowlSites = MWWikiversions::readDbListFile( 'fishbowl' );
$wgSiteMatrixNonGlobalSites = MWWikiversions::readDbListFile( 'nonglobal' );
if ( $wmgUseCharInsert ) {
wfLoadExtension( 'CharInsert' );
}
if ( $wmgUseParserFunctions ) {
wfLoadExtension( 'ParserFunctions' );
}
$wgExpensiveParserFunctionLimit = 500;
if ( $wmgUseCite ) {
wfLoadExtension( 'Cite' );
}
if ( $wmgUseCiteThisPage ) {
wfLoadExtension( 'CiteThisPage' );
}
if ( $wmgUseInputBox ) {
wfLoadExtension( 'InputBox' );
}
if ( $wmgUseImageMap ) {
wfLoadExtension( 'ImageMap' );
}
if ( $wmgUseGeSHi ) {
wfLoadExtension( 'SyntaxHighlight_GeSHi' );
}
if ( $wmgUseDoubleWiki ) {
wfLoadExtension( 'DoubleWiki' );
}
if ( $wmgUsePoem ) {
wfLoadExtension( 'Poem' );
}
// Per-wiki config for Flagged Revisions
if ( $wmgUseFlaggedRevs ) {
// Include load of extension, and its config.
include "$wmfConfigDir/flaggedrevs.php";
}
if ( $wmgUseCategoryTree ) {
wfLoadExtension( 'CategoryTree' );
}
if ( $wmgUseProofreadPage ) {
wfLoadExtension( 'ProofreadPage' );
if ( $wgDBname === 'dewikisource' ) {
$wgGroupPermissions['*']['pagequality'] = true; # 27516
}
if ( $wmgProofreadPageShowHeaders ) {
$wgDefaultUserOptions['proofreadpage-showheaders'] = 1;
}
}
if ( $wmgUseLabeledSectionTransclusion ) {
wfLoadExtension( 'LabeledSectionTransclusion' );
}
if ( $wmgUseSpamBlacklist ) {
wfLoadExtension( 'SpamBlacklist' );
$wgBlacklistSettings = [
'email' => [
'files' => [
'https://meta.wikimedia.org/w/index.php?title=Email_blacklist&action=raw&sb_ver=1'
],
],
'spam' => [
'files' => [
'https://meta.wikimedia.org/w/index.php?title=Spam_blacklist&action=raw&sb_ver=1'
],
],
];
$wgLogSpamBlacklistHits = true;
}
wfLoadExtension( 'TitleBlacklist' );
$wgTitleBlacklistBlockAutoAccountCreation = false;
if ( $wmgUseGlobalTitleBlacklist ) {
$wgTitleBlacklistSources = [
'meta' => [
'type' => 'url',
'src' => "https://meta.wikimedia.org/w/index.php?title=Title_blacklist&action=raw&tb_ver=1",
],
];
}
if ( $wmgUseQuiz ) {
wfLoadExtension( 'Quiz' );
}
if ( $wmgUseGadgets ) {
wfLoadExtension( 'Gadgets' );
}
if ( $wmgUseTimedMediaHandler ) {
wfLoadExtension( 'TimedMediaHandler' );
$wgTimedTextForeignNamespaces = [ 'commonswiki' => 102 ];
if ( $wgDBname === 'commonswiki' ) {
$wgTimedTextNS = 102;
}
// overwrite enabling of local TimedText namespace
$wgEnableLocalTimedText = $wmgEnableLocalTimedText;
// enable transcoding on all wikis that allow uploads
$wgEnableTranscode = $wgEnableUploads;
$wgEnabledTranscodeSet = [
// Keep the old WebM VP8 flat-file transcodes enabled
// while we transition, or playback of un-upgraded files
// will revert to original high-res sources.
// Disable them again once T200747 batch process complete.
'160p.webm' => true,
'240p.webm' => true,
'360p.webm' => true,
'480p.webm' => true,
'720p.webm' => true,
'1080p.webm' => true,
// Enable the WebM VP9 flat-file transcodes
'120p.vp9.webm' => true,
'180p.vp9.webm' => true,
'240p.vp9.webm' => true,
'360p.vp9.webm' => true,
'480p.vp9.webm' => true,
'720p.vp9.webm' => true,
'1080p.vp9.webm' => true,
'1440p.vp9.webm' => true,
'2160p.vp9.webm' => true,
];
$wgOggThumbLocation = false; // use ffmpeg for performance
// tmh1/2 have 12 cores and need lots of shared memory
// for ffmpeg, which mmaps large input files
$wgTranscodeBackgroundMemoryLimit = 4 * 1024 * 1024; // 4GB
// This allows using 2x the threads for VP9 encoding, but will
// fail if running a too-old ffmpeg version.
$wgFFmpegVP9RowMT = true;
// VP9 encoding benefits from more threads; up to 4 for HD or
// 8 when using row-based multithreading.
//
// Note compression of second pass is "spiky", alternating between
// single-threaded and multithreaded portions, so you can somewhat
// overcommit process threads per CPU thread.
$wgFFmpegThreads = 8;
// HD transcodes of full-length films/docs/conference vids can
// take several hours, and sometimes over 12. Bump up from default
// 8 hour limit to 16 to avoid wasting the time we've already spent
// when breaking these off.
// Then double that for VP9, which is more intense on the CPU.
$wgTranscodeBackgroundTimeLimit = 32 * 3600;
// ffmpeg tends to use about 175% CPU when dual-threaded, so hits
// say an 8-hour ulimit in 4-6 hours. This tends to cut
// off very large files at very high resolution just before
// they finish, wasting a lot of time.
// Pad it back out so we don't waste that CPU time with a fail!
$wgTranscodeBackgroundTimeLimit *= $wgFFmpegThreads;
// Minimum size for an embed video player
$wgMinimumVideoPlayerSize = $wmgMinimumVideoPlayerSize;
// use new ffmpeg build w/ VP9 & Opus support
$wgFFmpegLocation = '/usr/bin/ffmpeg';
// For MIDI to Ogg/MP3 conversion:
// add Debian paths for fluidsynth and the sound font to use
$wgTmhFluidsynthLocation = '/usr/bin/fluidsynth';
$wgTmhSoundfontLocation = '/usr/share/sounds/sf2/FluidR3_GM.sf2';
// The type of HTML5 player to use
$wgTmhWebPlayer = $wmgTmhWebPlayer;
// Enable the Beta Feature for trying out the new video player (see also the BF whitelist)
$wgTmhUseBetaFeatures = true;
}
if ( $wmgUseUploadsLink ) {
wfLoadExtension( 'UploadsLink' );
}
if ( $wmgUseUrlShortener ) {
wfLoadExtension( 'UrlShortener' );
$wgUrlShortenerTemplate = '/$1';
$wgUrlShortenerServer = 'https://w.wiki';
$wgUrlShortenerDBCluster = 'extension1';
$wgUrlShortenerDBName = 'wikishared';
$wgUrlShortenerDomainsWhitelist = [
'(.*\.)?wikipedia\.org',
'(.*\.)?wiktionary\.org',
'(.*\.)?wikibooks\.org',
'(.*\.)?wikinews\.org',
'(.*\.)?wikiquote\.org',
'(.*\.)?wikisource\.org',
'(.*\.)?wikiversity\.org',
'(.*\.)?wikivoyage\.org',
'(.*\.)?wikimedia\.org',
'(.*\.)?wikidata\.org',
'(.*\.)?mediawiki\.org',
];
$wgUrlShortenerApprovedDomains = [
'*.wikipedia.org',
'*.wiktionary.org',
'*.wikibooks.org',
'*.wikinews.org',
'*.wikiquote.org',
'*.wikisource.org',
'*.wikiversity.org',
'*.wikivoyage.org',
'*.wikimedia.org',
'*.wikidata.org',
'*.mediawiki.org',
];
$wgUrlShortenerEnableSidebar = false;
$wgGroupPermissions['sysop']['urlshortener-manage-url'] = false;
// Never ever change this config
// Changing it would change target of all short urls
$wgUrlShortenerIdSet = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz$';
}
if ( $wmgPFEnableStringFunctions ) {
$wgPFEnableStringFunctions = true;
}
if ( $wgDBname === 'mediawikiwiki' ) {
wfLoadExtension( 'ExtensionDistributor' );
$wgExtDistListFile = 'https://gerrit.wikimedia.org/mediawiki-extensions.txt';
$wgExtDistAPIConfig = [
'class' => 'GerritExtDistProvider',
'apiUrl' => 'https://gerrit.wikimedia.org/r/projects/mediawiki%2F$TYPE%2F$EXT/branches',
'tarballUrl' => 'https://extdist.wmflabs.org/dist/$TYPE/$EXT-$REF-$SHA.tar.gz',
'tarballName' => '$EXT-$REF-$SHA.tar.gz',
'repoListUrl' => 'https://gerrit.wikimedia.org/r/projects/?b=master&p=mediawiki/$TYPE/',
'sourceUrl' => 'https://gerrit.wikimedia.org/r/mediawiki/$TYPE/$EXT.git',
];
// Current stable release
$wgExtDistDefaultSnapshot = 'REL1_32';
// Current development snapshot
$wgExtDistCandidateSnapshot = 'REL1_33';
// Available snapshots
$wgExtDistSnapshotRefs = [
'master',
'REL1_33',
'REL1_32',
'REL1_31',
];
// Use Graphite for popular list
$wgExtDistGraphiteRenderApi = 'https://graphite.wikimedia.org/render';
}
if ( $wmgUseGlobalBlocking ) {
wfLoadExtension( 'GlobalBlocking' );
$wgGlobalBlockingDatabase = 'centralauth';
$wgApplyGlobalBlocks = $wmgApplyGlobalBlocks;
$wgGlobalBlockingBlockXFF = true; // Apply blocks to IPs in XFF (T25343)
}
wfLoadExtension( 'TrustedXFF' );
$wgTrustedXffFile = "$wmfConfigDir/trusted-xff.php";
if ( $wmgUseContactPage ) {
wfLoadExtension( 'ContactPage' );
$wgContactConfig = [];
$wgContactConfig['default'] = [
'RecipientUser' => null,
'SenderEmail' => null,
'SenderName' => 'Contact Form on ' . $wgSitename,
'RequireDetails' => false,
'IncludeIP' => false,
'MustBeLoggedIn' => false,
'RLModules' => [],
'RLStyleModules' => [],
'AdditionalFields' => [
'Text' => [
'label-message' => 'emailmessage',
'type' => 'textarea',
'rows' => 20,
'required' => true,
],
],
];
$wgContactConfig['default'] = array_merge( $wgContactConfig['default'], $wmgContactPageConf );
if ( $wgDBname === 'metawiki' ) {
include "$wmfConfigDir/MetaContactPages.php";
$wgContactConfig['stewards'] = [ // T98625
'RecipientUser' => 'Wikimedia Stewards',
'SenderEmail' => $wmgNotificationSender,
'RequireDetails' => true,
'IncludeIP' => true,
'AdditionalFields' => [
'Text' => [
'label-message' => 'emailmessage',
'type' => 'textarea',
'rows' => 20,
'required' => true
],
'Disclaimer' => [
'label-message' => 'contactpage-stewards-disclaimer-label',
'type' => 'info'
]
]
];
}
}
if ( $wmgUseSecurePoll ) {
wfLoadExtension( 'SecurePoll' );
$wgSecurePollUseNamespace = $wmgSecurePollUseNamespace;
$wgSecurePollScript = 'auth-api.php';
$wgHooks['SecurePoll_JumpUrl'][] = function ( $page, &$url ) {
global $site, $lang;
$url = wfAppendQuery( $url, [ 'site' => $site, 'lang' => $lang ] );
return true;
};
$wgSecurePollCreateWikiGroups = [
'securepollglobal' => 'securepoll-dblist-securepollglobal'
];
// T173393 - This is number of days after the election ends, not
// number of days after the vote was cast. Lower to 60 days so that
// overall time retained is not > 90 days.
$wgSecurePollKeepPrivateInfoDays = 60;
// T209802 - gpg2 is untested and evidently broken
$wgSecurePollGPGCommand = 'gpg1';
}
// PoolCounter
if ( $wmgUsePoolCounter ) {
include "$wmfConfigDir/PoolCounterSettings.php";
}
if ( $wmgUseScore ) {
wfLoadExtension( 'Score' );
$wgScoreSafeMode = false;
$wgScoreFileBackend = $wmgScoreFileBackend;
$wgScorePath = $wmgScorePath;
}
$wgHiddenPrefs[] = 'realname';
# Default address gets rejected by some mail hosts
$wgPasswordSender = 'wiki@wikimedia.org';
# e-mailing password based on e-mail address (T36386)
$wgPasswordResetRoutes['email'] = true;
if ( $wgDBname === 'labswiki' || $wgDBname === 'labtestwiki' ) {
$wgUseInstantCommons = true;
}
if ( $wmgUseClusterJobqueue ) {
$wgJobTypeConf['default'] = [ 'class' => 'JobQueueEventBus', 'readOnlyReason' => false ];
}
if ( $wgDBname === 'nostalgiawiki' ) {
# Link back to current version from the archive funhouse
if ( ( isset( $_REQUEST['title'] ) && ( $title = $_REQUEST['title'] ) )
|| ( isset( $_SERVER['PATH_INFO'] ) && ( $title = substr( $_SERVER['PATH_INFO'], 1 ) ) ) ) {
if ( preg_match( '/^(.*)\\/Talk$/', $title, $matches ) ) {
$title = 'Talk:' . $matches[1];
}
$wgSiteNotice = "[//en.wikipedia.org/wiki/" .
htmlspecialchars( urlencode( $title ) ) .
' See the current version of this page on Wikipedia]';
} else {
$wgSiteNotice = "[//en.wikipedia.org/ See current Wikipedia]";
}
// Nostalgia skin
wfLoadSkin( 'Nostalgia' );
}
$wgFooterIcons['copyright']['copyright'] = '<a href="https://wikimediafoundation.org/">' .
'<img src="/static/images/wikimedia-button.png" ' .
'srcset="' .
'/static/images/wikimedia-button-1.5x.png 1.5x, ' .
'/static/images/wikimedia-button-2x.png 2x' .
'" ' .
'width="88" height="31" alt="Wikimedia Foundation"/></a>';
# :SEARCH:
# All wikis are special and get Cirrus :)
# Must come *AFTER* PoolCounterSettings.php
wfLoadExtension( 'Elastica' );
wfLoadExtension( 'CirrusSearch' );
include "$wmfConfigDir/CirrusSearch-common.php";
// Various DB contention settings
if ( in_array( $wgDBname, [ 'testwiki', 'test2wiki', 'mediawikiwiki', 'commonswiki' ] ) ) {
$wgSiteStatsAsyncFactor = 1;
}
$wgInvalidateCacheOnLocalSettingsChange = false;
$wgEnableUserEmail = true;
$wgNoFollowLinks = true; // In case the MediaWiki default changed, T44594
# XFF log for vandal tracking
$wgExtensionFunctions[] = function () {
global $wmfUdp2logDest, $wgRequest;
if (
isset( $_SERVER['REQUEST_METHOD'] )
&& $_SERVER['REQUEST_METHOD'] === 'POST'
&& $wgRequest->getIP() !== '127.0.0.1' # T129982
) {
$uri = ( ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] ) ? 'https://' : 'http://' ) .
$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$xff = isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : '';
$logger = LoggerFactory::getInstance( 'xff' );
// TODO: it would be nice to log this as actual structured data
// instead of this ad-hoc tab delimited format
$logger->info(
gmdate( 'r' ) . "\t" .
"$uri\t" .
"$xff, {$_SERVER['REMOTE_ADDR']}\t" .
( ( isset( $_REQUEST['wpSave'] ) && $_REQUEST['wpSave'] ) ? 'save' : '' )
);
}
};
// T26313, turn off minordefault on enwiki
if ( $wgDBname === 'enwiki' ) {
$wgHiddenPrefs[] = 'minordefault';
}
if ( $wmgUseFooterContactLink ) {
$wgHooks['SkinTemplateOutputPageBeforeExec'][] = function ( $sk, &$tpl ) {
$contactLink = Html::element( 'a', [ 'href' => $sk->msg( 'contact-url' )->escaped() ],
$sk->msg( 'contact' )->text() );
$tpl->set( 'contact', $contactLink );
$tpl->data['footerlinks']['places'][] = 'contact';
return true;
};
}
if ( $wmgUseFooterCodeOfConductLink ) {
$wgHooks['SkinTemplateOutputPageBeforeExec'][] = function ( $sk, &$tpl ) {
$contactLink = Html::element( 'a', [ 'href' => $sk->msg( 'wm-codeofconduct-url' )->escaped() ],
$sk->msg( 'wm-codeofconduct' )->text() );
$tpl->set( 'wm-codeofconduct', $contactLink );
$tpl->data['footerlinks']['places'][] = 'wm-codeofconduct';
return true;
};
}
// T35186: turn off incomplete feature action=imagerotate
$wgAPIModules['imagerotate'] = 'ApiDisabled';
if ( $wmgUseDPL ) {
wfLoadExtension( 'intersection' );
}
wfLoadExtension( 'Renameuser' );
$wgGroupPermissions['bureaucrat']['renameuser'] = $wmgAllowLocalRenameuser;
if ( $wmgUseSpecialNuke ) {
wfLoadExtension( 'Nuke' );
}
if ( $wmgUseTorBlock ) {
wfLoadExtension( 'TorBlock' );
$wgTorLoadNodes = false;
$wgTorIPs = [ '91.198.174.232', '208.80.152.2', '208.80.152.134' ];
$wgTorAutoConfirmAge = 90 * 86400;
$wgTorAutoConfirmCount = 100;
$wgTorDisableAdminBlocks = false;
$wgTorTagChanges = false;
$wgGroupPermissions['user']['torunblocked'] = false;
$wgTorBlockProxy = $wgCopyUploadProxy;
}
if ( $wmgUseRSSExtension ) {
wfLoadExtension( 'RSS' );
$wgRSSProxy = $wgCopyUploadProxy;
$wgRSSUrlWhitelist = $wmgRSSUrlWhitelist;
}
if ( $wgMaxCredits === 0 ) {
$wgActions['credits'] = false;
}
# Process group overrides
$wgGroupPermissions['steward' ]['userrights'] = true;
$wgGroupPermissions['bureaucrat']['userrights'] = false;
$wgGroupPermissions['sysop']['bigdelete'] = false; // quick hack
foreach ( $groupOverrides2 as $group => $permissions ) {
if ( !array_key_exists( $group, $wgGroupPermissions ) ) {
$wgGroupPermissions[$group] = [];
}
$wgGroupPermissions[$group] = $permissions + $wgGroupPermissions[$group];
}
foreach ( $groupOverrides as $group => $permissions ) {
if ( !array_key_exists( $group, $wgGroupPermissions ) ) {
$wgGroupPermissions[$group] = [];
}
$wgGroupPermissions[$group] = $permissions + $wgGroupPermissions[$group];
}
if ( $wgDBname === 'loginwiki' ) {
$wgGroupPermissions['*'] = [
'read' => true,
'autocreateaccount' => true,
'editmyoptions' => true, // T158871
];
$wgGroupPermissions['user'] = [
'read' => true,
];
$wgGroupPermissions['autoconfirmed'] = [
'read' => true,
];
unset( $wgGroupPermissions['import'] );
unset( $wgGroupPermissions['transwiki'] );
$wgGroupPermissions['sysop'] = array_merge(
$wgGroupPermissions['sysop'],
[
'editinterface' => false,
]
);
}
$wgAutopromote = [
'autoconfirmed' => [ '&',
[ APCOND_EDITCOUNT, $wgAutoConfirmCount ],
[ APCOND_AGE, $wgAutoConfirmAge ],
],
];
if ( is_array( $wmgAutopromoteExtraGroups ) ) {
$wgAutopromote += $wmgAutopromoteExtraGroups;
}
$wgAutopromoteOnce = [
'onEdit' => $wmgAutopromoteOnceonEdit,
];
if ( is_array( $wmgExtraImplicitGroups ) ) {
$wgImplicitGroups = array_merge( $wgImplicitGroups, $wmgExtraImplicitGroups );
}
if ( $wmfRealm == 'labs' ) {
$wgHTTPTimeout = 10;
}
$wgHiddenPrefs[] = 'prefershttps'; // T91352, T102245
if ( isset( $_REQUEST['captchabypass'] ) && $_REQUEST['captchabypass'] == $wmgCaptchaPassword ) {
$wmgEnableCaptcha = false;
}
if ( $wmgEnableCaptcha ) {
wfLoadExtension( 'ConfirmEdit' );
wfLoadExtension( 'ConfirmEdit/FancyCaptcha' );
$wgGroupPermissions['autoconfirmed']['skipcaptcha'] = true;
$wgCaptchaFileBackend = 'global-multiwrite';
$wgCaptchaSecret = $wmgCaptchaSecret;
$wgCaptchaDirectoryLevels = 3;
$wgCaptchaStorageClass = 'CaptchaCacheStore';
$wgCaptchaClass = 'FancyCaptcha';
$wgCaptchaWhitelist =
'#^(https?:)?//([.a-z0-9-]+\\.)?((wikimedia|wikipedia|wiktionary|wikiquote|wikibooks|wikisource|wikispecies|mediawiki|wikinews|wikiversity|wikivoyage|wikidata|wmflabs)\.org'
. '|dnsstuff\.com|completewhois\.com|wikimedia\.de)([?/\#]|$)#i';
// 'XRumer' spambot
// adds non-real links
// http://meta.wikimedia.org/wiki/User:Cometstyles/XRumer
// http://meta.wikimedia.org/wiki/User:Jorunn/tracks
// (added 2008-05-08 -- brion)
$wgCaptchaRegexes[] = '/<a +href/i';
// For emergencies
if ( $wmgEmergencyCaptcha ) {
$wgCaptchaTriggers['edit'] = true;
$wgCaptchaTriggers['create'] = true;
}
if ( $wgDBname === 'labswiki' || $wgDBname === 'labtestwiki' ) {
$wgCaptchaTriggers['addurl'] = false;
}
# akosiaris 20180306. contact pages in metawiki are being abused by bots
if ( $wgDBname === 'metawiki' ) {
$wgCaptchaTriggers['contactpage'] = true;
}
}
if ( extension_loaded( 'wikidiff2' ) ) {
$wgDiff = false;
}
if ( $wmfRealm === 'labs' ) {
$wgInterwikiCache = require "$wmfConfigDir/interwiki-labs.php";
} else {
$wgInterwikiCache = require "$wmfConfigDir/interwiki.php";
}
// Username spoofing / mixed-script / similarity check detection
wfLoadExtension( 'AntiSpoof' );
// For transwiki import
ini_set( 'user_agent', 'Wikimedia internal server fetcher (noc@wikimedia.org' );
$wgHTTPImportTimeout = 50; // T155209
// CentralAuth
if ( $wmgUseCentralAuth ) {
wfLoadExtension( 'CentralAuth' );
$wgCentralAuthDryRun = false;
$wgCentralAuthCookies = true;
$wgCentralAuthUseEventLogging = true;
$wgCentralAuthPreventUnattached = true;
if ( $wmfRealm == 'production' ) {
$wgCentralAuthRC[] = [
'formatter' => 'IRCColourfulCARCFeedFormatter',
'uri' => "udp://$wmgRC2UDPAddress:$wmgRC2UDPPort/#central\t",
];
}
switch ( $wmfRealm ) {
case 'production':
// Production cluster
$wmgSecondLevelDomainRegex = '/^\w+\.\w+\./';
$wgCentralAuthAutoLoginWikis = $wmgCentralAuthAutoLoginWikis;
$wgCentralAuthLoginWiki = 'loginwiki';
break;
case 'labs':
// wmflabs beta cluster
$wmgSecondLevelDomainRegex = '/^\w+\.\w+\.\w+\.\w+\./';
$wgCentralAuthAutoLoginWikis = [
'.wikipedia.beta.wmflabs.org' => 'enwiki',
'.wikisource.beta.wmflabs.org' => 'enwikisource',
'.wikibooks.beta.wmflabs.org' => 'enwikibooks',
'.wikiversity.beta.wmflabs.org' => 'enwikiversity',
'.wikiquote.beta.wmflabs.org' => 'enwikiquote',
'.wikinews.beta.wmflabs.org' => 'enwikinews',
'.wikivoyage.beta.wmflabs.org' => 'enwikivoyage',
'.wiktionary.beta.wmflabs.org' => 'enwiktionary',
'meta.wikimedia.beta.wmflabs.org' => 'metawiki',
'deployment.wikimedia.beta.wmflabs.org' => 'deploymentwiki',
'test.wikimedia.beta.wmflabs.org' => 'testwiki',
'commons.wikimedia.beta.wmflabs.org' => 'commonswiki',
$wmfHostnames['wikidata'] => 'wikidatawiki',
];
$wgCentralAuthLoginWiki = 'loginwiki';
break;
}
if ( preg_match( $wmgSecondLevelDomainRegex, strrev( $wgServer ), $m ) ) {
$wmgSecondLevelDomain = strrev( $m[0] );
} else {
$wmgSecondLevelDomain = false;
}
unset( $wmgSecondLevelDomainRegex );
# Don't autologin to self
if ( isset( $wgCentralAuthAutoLoginWikis[$wmgSecondLevelDomain] ) ) {
unset( $wgCentralAuthAutoLoginWikis[$wmgSecondLevelDomain] );
$wgCentralAuthCookieDomain = $wmgSecondLevelDomain;
} elseif ( $wgDBname === 'commonswiki' && isset( $wgCentralAuthAutoLoginWikis["commons$wmgSecondLevelDomain"] ) ) {
unset( $wgCentralAuthAutoLoginWikis["commons$wmgSecondLevelDomain"] );
$wgCentralAuthCookieDomain = "commons$wmgSecondLevelDomain";
} elseif ( $wgDBname === 'metawiki' ) {
unset( $wgCentralAuthAutoLoginWikis["meta$wmgSecondLevelDomain"] );
$wgCentralAuthCookieDomain = "meta$wmgSecondLevelDomain";
} else {
# Don't set 2nd-level cookies for *.wikimedia.org, insecure
$wgCentralAuthCookieDomain = '';
}
$wgCentralAuthLoginIcon = $wmgCentralAuthLoginIcon;
$wgCentralAuthAutoNew = true;
/**
* This function is used for both the CentralAuthWikiList and
* GlobalUserPageWikis hooks.
*
* @param array &$list
* @return bool
*/
function wmfCentralAuthWikiList( &$list ) {
global $wgLocalDatabases, $IP, $wgSiteMatrixPrivateSites,
$wgSiteMatrixFishbowlSites, $wgSiteMatrixClosedSites,
$wgSiteMatrixNonGlobalSites;
$list = array_diff(
$wgLocalDatabases,
$wgSiteMatrixPrivateSites,
$wgSiteMatrixFishbowlSites,
$wgSiteMatrixClosedSites,
$wgSiteMatrixNonGlobalSites
);
return false;
}
$wgHooks['CentralAuthWikiList'][] = 'wmfCentralAuthWikiList';
// Let's give it another try
$wgCentralAuthCreateOnView = true;
// Attempt to attach unattached accounts by password on login
$wgCentralAuthAutoMigrate = true;
// Try to create global accounts if one doesn't exist and it's safe
$wgCentralAuthAutoMigrateNonGlobalAccounts = true;
// Enables Special:GlobalRenameRequest
$wgCentralAuthEnableGlobalRenameRequest = true;
// Only allow users with global accounts to login
$wgCentralAuthStrict = true;
// Create some local accounts as soon as the global registration happens
$wgCentralAuthAutoCreateWikis = [ 'loginwiki', 'metawiki' ];
// Link global block blockers to user pages on Meta
$wgCentralAuthGlobalBlockInterwikiPrefix = 'meta';
// See T104371 and [[m:Requests_for_comment/Password_policy_for_users_with_certain_advanced_permissions]]
foreach ( $wmgPrivilegedGlobalGroups as $group ) {
$wgCentralAuthGlobalPasswordPolicies[$group] = $wmgPrivilegedPolicy;
if ( $group === 'staff' ) {
// Require 10 byte password for staff.
$wgCentralAuthGlobalPasswordPolicies[$group]['MinimumPasswordLengthToLogin'] = 10;
}
}
$wgCentralAuthUseSlaves = true;
// Check global rename log on meta for new accounts
$wgCentralAuthOldNameAntiSpoofWiki = 'metawiki';
}
// Config for GlobalCssJs
// Only enable on CentralAuth wikis
if ( $wmgUseGlobalCssJs && $wmgUseCentralAuth ) {
wfLoadExtension( 'GlobalCssJs' );
// Disable site-wide global css/js
$wgUseGlobalSiteCssJs = false;
// Setup metawiki as central wiki
$wgResourceLoaderSources['metawiki'] = [
'apiScript' => '//meta.wikimedia.org/w/api.php',
'loadScript' => '//meta.wikimedia.org/w/load.php',
];
$wgGlobalCssJsConfig = [
'wiki' => 'metawiki', // database name
'source' => 'metawiki', // ResourceLoader source name
];
}
if ( $wmgUseGlobalUserPage && $wmgUseCentralAuth ) {
wfLoadExtension( 'GlobalUserPage' );
$wgGlobalUserPageAPIUrl = 'https://meta.wikimedia.org/w/api.php';
$wgGlobalUserPageDBname = 'metawiki';
$wgHooks['GlobalUserPageWikis'][] = 'wmfCentralAuthWikiList';
}
if ( $wmgLocalAuthLoginOnly && $wmgUseCentralAuth ) {
// T57420: prevent creation of local password records for SUL users
if ( isset( $wgAuthManagerAutoConfig['primaryauth'][\MediaWiki\Auth\LocalPasswordPrimaryAuthenticationProvider::class] ) ) {
$wgAuthManagerAutoConfig['primaryauth'][\MediaWiki\Auth\LocalPasswordPrimaryAuthenticationProvider::class]['args'][0]['loginOnly'] = true;
}
}
if ( $wmgUseApiFeatureUsage ) {
wfLoadExtension( 'ApiFeatureUsage' );
$wgApiFeatureUsageQueryEngineConf = [
'class' => 'ApiFeatureUsageQueryEngineElastica',
'serverList' => $wmfLocalServices['search-chi'],
];
}
// taking it live 2006-12-15 brion
wfLoadExtension( 'DismissableSiteNotice' );
$wgDismissableSiteNoticeForAnons = true; // T59732
$wgMajorSiteNoticeID = '2';
/**
* Get an array of groups (in $wmgPrivilegedGroups) that $username is part of
*
* @param string $username
* @param User $user
* @return array Any elevated/privileged groups the user is a member of
*/
function wmfGetPrivilegedGroups( $username, $user ) {
global $wmgUseCentralAuth, $wmgPrivilegedGroups, $wmgPrivilegedGlobalGroups;
if ( $wmgUseCentralAuth && CentralAuthUser::getInstanceByName( $username )->exists() ) {
$centralUser = CentralAuthUser::getInstanceByName( $username );
try {
$groups = array_intersect(
array_merge( $wmgPrivilegedGroups, $wmgPrivilegedGlobalGroups ),
array_merge( $centralUser->getGlobalGroups(), $centralUser->getLocalGroups() )
);
} catch ( Exception $e ) {
// Don't block login if we can't query attached (T119736)
MWExceptionHandler::logException( $e );
$groups = array_merge( $user->getGroups(), $centralUser->getGlobalGroups() );
}
} else {
// use effective groups, as we set 'user' as privileged for private/fishbowl wikis
$groups = array_intersect( $wmgPrivilegedGroups, $user->getEffectiveGroups() );
}
return $groups;
}
// log suspicious or sensitive login attempts
$wgHooks['AuthManagerLoginAuthenticateAudit'][] = function ( $response, $user, $username ) {
$guessed = false;
if ( !$user && $username ) {
$user = User::newFromName( $username );
$guessed = true;
}
if ( !$user || !in_array( $response->status,
[ AuthenticationResponse::PASS, AuthenticationResponse::FAIL ], true )
) {
return;
}
global $wgRequest;
$headers = function_exists( 'apache_request_headers' ) ? apache_request_headers() : [];
$successful = $response->status === AuthenticationResponse::PASS;
$privGroups = wmfGetPrivilegedGroups( $username, $user );
$channel = $successful ? 'goodpass' : 'badpass';
if ( $privGroups ) {
$channel .= '-priv';
}
$logger = LoggerFactory::getInstance( $channel );
$verb = $successful ? 'succeeded' : 'failed';
$logger->info( "Login $verb for {priv} {name} from {ip} - {xff} - {ua} - {geocookie}: {messagestr}", [
'successful' => $successful,
'groups' => implode( ', ', $privGroups ),
'priv' => ( $privGroups ? 'elevated' : 'normal' ),
'name' => $user->getName(),
'ip' => $wgRequest->getIP(),
'xff' => @$headers['X-Forwarded-For'],
'ua' => @$headers['User-Agent'],
'guessed' => $guessed,
'msgname' => $response->message ? $response->message->getKey() : '-',
'messagestr' => $response->message ? $response->message->inLanguage( 'en' )->text() : '',
'geocookie' => $wgRequest->getCookie( 'GeoIP', '' ),
] );
};
// log sysop password changes
$wgHooks['ChangeAuthenticationDataAudit'][] = function ( $req, $status ) {
$user = User::newFromName( $req->username );
$status = Status::wrap( $status );
if ( $req instanceof \MediaWiki\Auth\PasswordAuthenticationRequest
&& wmfGetPrivilegedGroups( $req->username, $user )
) {
global $wgRequest;
$headers = function_exists( 'apache_request_headers' ) ? apache_request_headers() : [];
$privGroups = wmfGetPrivilegedGroups( $req->username, $user );
$logger = LoggerFactory::getInstance( 'badpass' );
$logger->info( 'Password change in prefs for {priv} {name}: {status} - {ip} - {xff} - {ua} - {geocookie}', [
'name' => $user->getName(),
'groups' => implode( ', ', $privGroups ),
'priv' => ( $privGroups ? 'elevated' : 'normal' ),
'status' => $status->isGood() ? 'ok' : $status->getWikiText( null, null, 'en' ),
'ip' => $wgRequest->getIP(),
'xff' => @$headers['X-Forwarded-For'],
'ua' => @$headers['User-Agent'],
'geocookie' => $wgRequest->getCookie( 'GeoIP', '' ),
] );
}
};
// Passed to ulimit
$wgMaxShellFileSize = 512 * 1024; // Kilobytes
$wgMaxShellMemory = 1024 * 1024; // Kilobytes
$wgMaxShellTime = 50; // seconds
// Use a cgroup for shell execution.
// This will cause shell execution to fail if the cgroup is not installed.
// If some misc server doesn't have the cgroup installed, you can create it
// with: mkdir -p -m777 /sys/fs/cgroup/memory/mediawiki/job
$wgShellCgroup = '/sys/fs/cgroup/memory/mediawiki/job';
switch ( $wmfRealm ) {
case 'production' :
$wgImageMagickTempDir = '/tmp/magick-tmp';
break;
case 'labs':
$wgImageMagickTempDir = '/tmp/a/magick-tmp';
break;
}
// Banner notice system
if ( $wmgUseCentralNotice ) {
wfLoadExtension( 'CentralNotice' );
// for DNS prefetching
$wgCentralHost = "//{$wmfHostnames['meta']}";
// for banner loading
if ( $wmfRealm === 'production' && $wgDBname === 'testwiki' ) {
$wgCentralSelectedBannerDispatcher = "//test.wikipedia.org/w/index.php?title=Special:BannerLoader";
// No caching for banners on testwiki, so we can develop them there a bit faster - NeilK 2012-01-16
// Never set this to zero on a highly trafficked wiki, there are server-melting consequences
$wgNoticeBannerMaxAge = 0;
} else {
$wgCentralSelectedBannerDispatcher = "//{$wmfHostnames['meta']}/w/index.php?title=Special:BannerLoader";
}
// Relative URL which is hardcoded to HTTP 204 in Varnish config.
$wgCentralBannerRecorder = "{$wgServer}/beacon/impression";
// Allow only these domains to access CentralNotice data through the reporter
$wgNoticeReporterDomains = 'https://donate.wikimedia.org';
$wgCentralDBname = 'metawiki';
$wgNoticeInfrastructure = false;
$wgCentralNoticeAdminGroup = false;
if ( $wmfRealm == 'production' && $wgDBname === 'testwiki' ) {
// test.wikipedia.org has its own central database:
$wgCentralDBname = 'testwiki';
$wgNoticeInfrastructure = true;
} elseif ( $wgDBname === 'metawiki' ) {
$wgNoticeInfrastructure = true;
}
if ( $wgNoticeInfrastructure ) {
$wgCentralNoticeMessageProtectRight = 'banner-protect';
}
// Set fundraising banners to use HTTPS on foundation wiki
$wgNoticeFundraisingUrl = 'https://donate.wikimedia.org/wiki/Special:LandingCheck';
// Enable the CentralNotice/Translate integration
$wgNoticeUseTranslateExtension = true;
// T51905
$wgNoticeUseLanguageConversion = true;
// *** Hide Cookies ***
// A little bit of historical breadcrumbs:
// In 2012 we expired cookies on 2012-12-26, then everyone had
// a two week expiration until 2013-01-22 whereupon we introduced
// a year long expiration. For the 2013 fundraiser starting
// 2013-12-02 we're now using a 10 month expiration.
// For the 2014 fundraiser it's 250 days, though we can change it
// retroactively as the cookie value now has a create date and reason.
// 'close' duration is used for the banner X button
// 'donate' duration is used for cookie set on Thank You page
$wgNoticeCookieDurations = [
'close' => 604800, // 1 week
'donate' => 21600000, // 250 days
];
// T18821
// Updates made here also need to be reflected in
// foundation.wikimedia.org/wiki/Template:HideBanners
$wgNoticeHideUrls = [
'//en.wikipedia.org/w/index.php?title=Special:HideBanners',
'//meta.wikimedia.org/w/index.php?title=Special:HideBanners',
'//commons.wikimedia.org/w/index.php?title=Special:HideBanners',
'//species.wikimedia.org/w/index.php?title=Special:HideBanners',
'//en.wikibooks.org/w/index.php?title=Special:HideBanners',
'//en.wikiquote.org/w/index.php?title=Special:HideBanners',
'//en.wikisource.org/w/index.php?title=Special:HideBanners',
'//en.wikinews.org/w/index.php?title=Special:HideBanners',
'//en.wikiversity.org/w/index.php?title=Special:HideBanners',
'//www.mediawiki.org/w/index.php?title=Special:HideBanners',
];
// Emit CSP headers on banner previews. This can go away when full CSP
// support (T135963) is deployed.
$wgCentralNoticeContentSecurityPolicy = "default-src *.wikimedia.org *.wikipedia.org *.wiktionary.org *.wikisource.org *.wikibooks.org *.wikiversity.org *.wikiquote.org *.wikinews.org www.mediawiki.org www.wikidata.org *.wikivoyage.org data: blob: 'self'; script-src *.wikimedia.org 'unsafe-inline' 'unsafe-eval' 'self'; style-src *.wikimedia.org data: 'unsafe-inline' 'self';";
// Turn on EventLogging data globally at a low level
$wgCentralNoticeImpressionEventSampleRate = 0.01;
}
// Load our site-specific l10n extension
wfLoadExtension( 'WikimediaMessages' );
if ( $wgDBname === 'enwiki' ) {
// Please don't interfere with our hundreds of wikis ability to manage themselves.
// Only use this shitty hack for enwiki. Thanks.
// -- brion 2008-04-10
$wgHooks['getUserPermissionsErrorsExpensive'][] = function ( &$title, &$user, $action, &$result ) {
if ( $action !== 'delete' && $action !== 'move' ) {
return true;
}
$main = Title::newMainPage();
$mainText = $main->getPrefixedDBkey();
if ( $mainText === $title->getPrefixedDBkey() ) {
$result = [ 'cant-delete-main-page' ];
return false;
}
return true;
};
}
if ( $wgDBname === 'enwiki' || $wgDBname === 'fawiki' ) {
// T59569, T105118
//
// If it's an anonymous user creating a page in the English and Persian Wikipedia
// Draft namespace, tell TitleQuickPermissions to abort the normal
// checkQuickPermissions checks. This lets anonymous users create a page in this
// namespace, even though they don't have the general 'createpage' right.
//
// It does not affect other checks from getUserPermissionsErrorsInternal
// (e.g. protection and blocking).
//
// Returning true tells it to proceed as normal in other cases.
$wgHooks['TitleQuickPermissions'][] = function ( Title $title, User $user, $action, &$errors, $doExpensiveQueries, $short ) {
return ( $action !== 'create' || $title->getNamespace() !== 118 || !$user->isAnon() );
};
}
if ( $wmgUseCollection ) {
// PediaPress / PDF generation
include "$IP/extensions/Collection/Collection.php";
// Use pediapress server for POD function (T73675)
$wgCollectionCommandToServeURL = [
'zip_post' => "{$wmfLocalServices['urldownloader']}|https://pediapress.com/wmfup/",
];
$wgCollectionPODPartners = [
'pediapress' => [
'name' => 'PediaPress',
'url' => 'https://pediapress.com/',
'posturl' => 'https://pediapress.com/api/collections/',
'infopagetitle' => 'coll-order_info_article',
],
];
// MediaWiki namespace is not a good default
$wgCommunityCollectionNamespace = NS_PROJECT;
// Allow collecting Help pages
$wgCollectionArticleNamespaces[] = NS_HELP;
$wgCollectionFormats = [
'rdf2latex' => 'PDF',
'rdf2text' => 'TXT',
];
if ( !$wmgUseElectronPdfService ) {
$wgCollectionShowRenderNotes[] = 'coll-rendering_finished_note_article_rdf2latex';
}
$wgCollectionPortletForLoggedInUsersOnly = $wmgCollectionPortletForLoggedInUsersOnly;
$wgCollectionArticleNamespaces = $wmgCollectionArticleNamespaces;
$wgCollectionPortletFormats = $wmgCollectionPortletFormats;
}
if ( $wmgUseElectronPdfService ) {
wfLoadExtension( 'ElectronPdfService' );
}
wfLoadExtension( 'AdvancedSearch' );
# Various system to allow/prevent flooding
# (including exemptions for scheduled outreach events)
require "$wmfConfigDir/throttle.php";
require "$wmfConfigDir/throttle-analyze.php";
if ( $wmgUseNewUserMessage ) {
wfLoadExtension( 'NewUserMessage' );
$wgNewUserSuppressRC = true;
$wgNewUserMinorEdit = $wmgNewUserMinorEdit;
$wgNewUserMessageOnAutoCreate = $wmgNewUserMessageOnAutoCreate;
}
if ( $wmgUseCodeReview ) {
wfLoadExtension( 'CodeReview' );
$wgGroupPermissions['user']['codereview-add-tag'] = false;
$wgGroupPermissions['user']['codereview-remove-tag'] = false;
$wgGroupPermissions['user']['codereview-post-comment'] = false;
$wgGroupPermissions['user']['codereview-set-status'] = false;
$wgGroupPermissions['user']['codereview-link-user'] = false;
$wgGroupPermissions['user']['codereview-signoff'] = false;
$wgGroupPermissions['user']['codereview-associate'] = false;
$wgCodeReviewRepoStatsCacheTime = 24 * 60 * 60;
$wgCodeReviewMaxDiffPaths = 100;
// Delist the deprecated special page.
$wgCodeReviewListSpecialPage = false;
}
# AbuseFilter
wfLoadExtension( 'AbuseFilter' );
include "$wmfConfigDir/abusefilter.php";
if ( $wmgUseGlobalAbuseFilters ) {
$wgAbuseFilterCentralDB = $wmgAbuseFilterCentralDB;
$wgAbuseFilterIsCentral = ( $wgDBname === $wgAbuseFilterCentralDB );
}
# PdfHandler
if ( $wmgUsePdfHandler ) {
wfLoadExtension( 'PdfHandler' );
$wgPdfProcessor = '/usr/local/bin/mediawiki-firejail-ghostscript';
$wgPdfPostProcessor = '/usr/local/bin/mediawiki-firejail-convert';
}
# WikiEditor
wfLoadExtension( 'WikiEditor' );
$wgDefaultUserOptions['usebetatoolbar'] = 1;
# LocalisationUpdate
wfLoadExtension( 'LocalisationUpdate' );
$wgLocalisationUpdateDirectory = "/var/lib/l10nupdate/caches/cache-$wmgVersionNumber";
$wgLocalisationUpdateRepository = 'local';
$wgLocalisationUpdateRepositories['local'] = [
'mediawiki' => '/var/lib/l10nupdate/mediawiki/core/%PATH%',
'extension' => '/var/lib/l10nupdate/mediawiki/extensions/%NAME%/%PATH%',
'skin' => '/var/lib/l10nupdate/mediawiki/skins/%NAME%/%PATH%',
];
if ( $wmgEnableLandingCheck ) {
wfLoadExtension( 'LandingCheck' );
$wgPriorityCountries = [
// === Fundraising Chapers
'DE', 'CH',
// === Blacklisted countries
'BY', 'CD', 'CI', 'CU', 'IQ', 'IR', 'KP', 'LB', 'LY', 'MM', 'SD', 'SO', 'SY', 'YE', 'ZW',
];
$wgLandingCheckPriorityURLBase = "//foundation.wikimedia.org/wiki/Special:LandingCheck";
$wgLandingCheckNormalURLBase = "//donate.wikimedia.org/wiki/Special:LandingCheck";
}
if ( $wmgEnableFundraiserLandingPage ) {
wfLoadExtension( 'FundraiserLandingPage' );
}
if ( $wmgUseLiquidThreads || $wmgLiquidThreadsFrozen ) {
require_once "$wmfConfigDir/liquidthreads.php";
}
if ( $wmgUseGlobalUsage ) {
wfLoadExtension( 'GlobalUsage' );
$wgGlobalUsageDatabase = 'commonswiki';
$wgGlobalUsageSharedRepoWiki = 'commonswiki';
$wgGlobalUsagePurgeBacklinks = true;
}
if ( $wmgUseLivePreview ) {
$wgDefaultUserOptions['uselivepreview'] = 1;
}
if ( $wmgUseSentry ) {
wfLoadExtension( 'Sentry' );
$wgSentryLogPhpErrors = false;
}
wfLoadExtension( 'TemplateStyles' );
// allow protocol-relative URLs per T188760
$wgTemplateStylesAllowedUrls = [
'audio' => [
'<^(?:https:)?//upload\\.wikimedia\\.org/wikipedia/commons/>',
],
'image' => [
'<^(?:https:)?//upload\\.wikimedia\\.org/wikipedia/commons/>',
],
'svg' => [
'<^(?:https:)?//upload\\.wikimedia\\.org/wikipedia/commons/[^?#]*\\.svg(?:[?#]|$)>',
],
'font' => [],
'namespace' => [ '<.>' ],
'css' => [],
];
wfLoadExtension( 'CodeMirror' );
// Must be loaded BEFORE VisualEditor, or things will break
if ( $wmgUseArticleCreationWorkflow ) {
wfLoadExtension( 'ArticleCreationWorkflow' );
}
$wgDefaultUserOptions['thumbsize'] = $wmgThumbsizeIndex;
$wgDefaultUserOptions['showhiddencats'] = $wmgShowHiddenCats;
$wgDefaultUserOptions['watchcreations'] = true;
// Temporary override: WMF is not hardcore enough to enable this.
// See T37785, T38316, T47022 about it.
if ( $wmgWatchlistDefault ) {
$wgDefaultUserOptions['watchdefault'] = 1;
} else {
$wgDefaultUserOptions['watchdefault'] = 0;
}
if ( $wmgWatchMoves ) {
$wgDefaultUserOptions['watchmoves'] = 1;
} else {
$wgDefaultUserOptions['watchmoves'] = 0;
}
if ( $wmgWatchRollback ) {
$wgDefaultUserOptions['watchrollback'] = 1;
} else {
$wgDefaultUserOptions['watchrollback'] = 0;
}
$wgDefaultUserOptions['enotifminoredits'] = $wmgEnotifMinorEditsUserDefault;
$wgDefaultUserOptions['enotifwatchlistpages'] = 0;
if ( $wmgEnhancedRecentChanges ) {
$wgDefaultUserOptions['usenewrc'] = 1;
} else {
$wgDefaultUserOptions['usenewrc'] = 0;
}
if ( $wmgEnhancedWatchlist ) {
$wgDefaultUserOptions['extendwatchlist'] = 1;
} else {
$wgDefaultUserOptions['extendwatchlist'] = 0;
}
if ( $wmgForceEditSummary ) {
$wgDefaultUserOptions['forceeditsummary'] = 1;
} else {
$wgDefaultUserOptions['forceeditsummary'] = 0;
}
if ( $wmgShowWikidataInWatchlist ) {
$wgDefaultUserOptions['wlshowwikibase'] = 1;
} else {
$wgDefaultUserOptions['wlshowwikibase'] = 0;
}
// ContributionTracking for handling PayPal redirects
if ( $wgUseContributionTracking ) {
wfLoadExtension( 'ContributionTracking' );
// the following variables will disable all donation forms and send users to a maintenance page
$wgContributionTrackingFundraiserMaintenance = false;
$wgContributionTrackingFundraiserMaintenanceUnsched = false;
}
if ( $wmgUseMassMessage ) {
wfLoadExtension( 'MassMessage' );
}
if ( $wmgUseSandboxLink ) {
wfLoadExtension( 'SandboxLink' );
}
if ( $wmgUseUploadWizard ) {
wfLoadExtension( 'UploadWizard' );
$wgUploadStashScalerBaseUrl = "//{$wmfHostnames['upload']}/$site/$lang/thumb/temp";
$wgUploadWizardConfig = [
# 'debug' => true,
// Normally we don't include API keys in CommonSettings, but this key
// isn't private since it's used on the client-side, i.e. anyone can see
// it in the outgoing AJAX requests to Flickr.
'flickrApiKey' => 'e9d8174a79c782745289969a45d350e8',
// Slowwwwwwww
'campaignExpensiveStatsEnabled' => false,
'licensing' => [
'thirdParty' => [
'licenseGroups' => [
[
// This should be a list of all CC licenses we can reasonably expect to find around the web
'head' => 'mwe-upwiz-license-cc-head',
'subhead' => 'mwe-upwiz-license-cc-subhead',
'licenses' => [
'cc-by-sa-4.0',
'cc-by-sa-3.0',
'cc-by-sa-2.5',
'cc-by-4.0',
'cc-by-3.0',
'cc-by-2.5',
'cc-zero'
]
],
[
// n.b. as of April 2011, Flickr still uses CC 2.0 licenses.
// The White House also has an account there, hence the Public Domain US Government license
'head' => 'mwe-upwiz-license-flickr-head',
'subhead' => 'mwe-upwiz-license-flickr-subhead',
'prependTemplates' => [ 'flickrreview' ],
'licenses' => [
'cc-by-sa-2.0',
'cc-by-2.0',
'pd-usgov',
]
],
[
'head' => 'mwe-upwiz-license-public-domain-usa-head',
'subhead' => 'mwe-upwiz-license-public-domain-usa-subhead',
'licenses' => [
'pd-us',
'pd-old-70-1923',
'pd-art',
]
],
[
'head' => 'mwe-upwiz-license-usgov-head',
'licenses' => [
'pd-usgov',
'pd-usgov-nasa'
]
],
[
'head' => 'mwe-upwiz-license-custom-head',
'special' => 'custom',
'licenses' => [ 'custom' ],
],
[
'head' => 'mwe-upwiz-license-none-head',
'licenses' => [ 'none' ]
],
],
],
],
'licenses' => [
'pd-old-70-1923' => [
'msg' => 'mwe-upwiz-license-pd-old-70-1923',
'templates' => [ 'PD-old-70-1923' ],
],
],
];
$wgUploadWizardConfig['enableChunked'] = 'opt-in';
$wgUploadWizardConfig['altUploadForm'] = $wmgAltUploadForm; // T35513
if ( $wgDBname === 'testwiki' ) {
$wgUploadWizardConfig['feedbackPage'] = 'Prototype_upload_wizard_feedback';
$wgUploadWizardConfig["missingCategoriesWikiText"] = '<p><span class="errorbox"><b>Hey, no categories?</b></span></p>';
unset( $wgUploadWizardConfig['fallbackToAltUploadForm'] );
} elseif ( $wgDBname === 'commonswiki' ) {
$wgUploadWizardConfig['feedbackPage'] = 'Commons:Upload_Wizard_feedback'; # Set by neilk, 2011-11-01, per erik
$wgUploadWizardConfig["missingCategoriesWikiText"] = "{{subst:unc}}";
$wgUploadWizardConfig['flickrBlacklistPage'] = 'User:FlickreviewR/bad-authors';
$wgUploadWizardConfig['customLicenseTemplate'] = 'Template:License_template_tag';
}
// Enable Structured Data captions on upload
if ( $wmgUseWikibaseMediaInfo ) {
$wgUploadWizardConfig['wikibase']['enabled'] = true;
$wgUploadWizardConfig['wikibase']['statements'] = $wmgMediaInfoEnableUploadWizardStatements;
}
}
if ( $wmgCustomUploadDialog ) {
$wgUploadDialog = [
'fields' => [
'description' => true,
'date' => true,
'categories' => true,
],
'licensemessages' => [
// Messages defined in WikimediaMessages: upload-form-label-own-work-message-commons,
// upload-form-label-not-own-work-message-commons, upload-form-label-not-own-work-local-commons
'local' => $wgDBname === 'commonswiki' ? 'commons' : 'generic-local',
'foreign' => $wgDBname === 'commonswiki' ? 'commons' : 'generic-foreign',
],
'comment' => 'Cross-wiki upload from $HOST',
'format' => [
'filepage' => '== {{int:filedesc}} ==
{{Information
|description=$DESCRIPTION
|date=$DATE
|source=$SOURCE
|author=$AUTHOR
}}
== {{int:license-header}} ==
$LICENSE
$CATEGORIES
',
'description' => '{{$LANGUAGE|1=$TEXT}}',
'ownwork' => '{{own}}',
'license' => '{{self|cc-by-sa-4.0}}',
'uncategorized' => '{{subst:unc}}',
],
];
}
if ( $wmgUseBetaFeatures ) {
wfLoadExtension( 'BetaFeatures' );
}
if ( $wmgUseCommonsMetadata ) {
wfLoadExtension( 'CommonsMetadata' );
$wgCommonsMetadataSetTrackingCategories = true;
$wgCommonsMetadataForceRecalculate = $wmgCommonsMetadataForceRecalculate;
// T222954: evict defective cache entries made while I2a316a758d7 was live
// TODO: remove this after 2019-06-15
$wgHooks['ValidateExtendedMetadataCache'] = function ( $timestamp, File $file ) {
$timestamp = wfTimestamp( TS_UNIX, $timestamp );
return $timestamp < /* 2019-05-05 */1557014400 || $timestamp > /* 2019-06-14 */1557792000;
};
}
if ( $wmgUseGWToolset ) {
wfLoadExtension( 'GWToolset' );
$wgGWTFileBackend = 'local-multiwrite';
// extra throttling until the image scalers are more robust
$wgGWToolsetConfigOverrides['mediafile_job_throttle_default'] = 5; // 5 files per batch
$wgJobBackoffThrottling['gwtoolsetUploadMetadataJob'] = 5 / 3600; // 5 batches per hour
}
if ( $wmgUseMultimediaViewer ) {
wfLoadExtension( 'MultimediaViewer' );
}
if ( $wmgUsePopups ) {
wfLoadExtension( 'Popups' );
}
if ( $wmgUseLinter ) {
wfLoadExtension( 'Linter' );
}
if ( !isset( $wgVirtualRestConfig ) && ( $wmgUseRestbaseVRS || $wmgUseParsoid || $wmgUseCollection ) ) {
$wgVirtualRestConfig = [
'modules' => [],
'global' => [
'domain' => $wgCanonicalServer,
'timeout' => 360,
'forwardCookies' => false,
'HTTPProxy' => null,
]
];
}
if ( $wmgUseRestbaseVRS ) {
$wgVirtualRestConfig['modules']['restbase'] = [
'url' => $wmfLocalServices['restbase'],
'domain' => $wgCanonicalServer,
'forwardCookies' => false,
'parsoidCompat' => false
];
}
if ( $wmgUseParsoid ) {
$wmgParsoidURL = $wmfLocalServices['parsoid'];
$wgVirtualRestConfig['modules']['parsoid'] = [
'url' => $wmgParsoidURL,
'prefix' => $wgDBname, // The wiki prefix to use; deprecated
'domain' => $wgCanonicalServer,
'forwardCookies' => $wmgParsoidForwardCookies,
'restbaseCompat' => false
];
}
if ( $wmgUseCollection ) {
$wgVirtualRestConfig['modules']['electron'] = [
'url' => $wmfLocalServices['electron'],
'options' => [
'accessKey' => $wmgElectronSecret, // set in private repo
],
];
}
if ( $wmgUseVisualEditor ) {
wfLoadExtension( 'VisualEditor' );
// RESTBase connection configuration is done by $wmfUseRestbaseVRS above.
// Parsoid connection configuration is done by $wmgUseParsoid above.
// At least one of these should be set if you want to use Visual Editor.
// RESTbase connection configuration
if ( $wmgVisualEditorAccessRESTbaseDirectly ) {
$wgVisualEditorRestbaseURL = "/api/rest_v1/page/html/";
$wgVisualEditorFullRestbaseURL = "/api/rest_";
// There should be no lossy switching in RESTBase mode, but just in case
$wgVisualEditorAllowLossySwitching = false;
} else {
// Prefer lossy switching (dirty diffs) to not being able to switch editors
$wgVisualEditorAllowLossySwitching = true;
}
// Tab configuration
if ( $wmgVisualEditorUseSingleEditTab ) {
$wgVisualEditorUseSingleEditTab = true;
$wgVisualEditorSingleEditTabSwitchTime = $wmgVisualEditorSingleEditTabSwitchTime;
}
if ( $wmgVisualEditorIsSecondaryEditor ) {
if ( !$wmgVisualEditorUseSingleEditTab ) {
$wgVisualEditorTabPosition = 'after';
}
$wgDefaultUserOptions['visualeditor-editor'] = 'wikitext';
} else {
$wgDefaultUserOptions['visualeditor-editor'] = 'visualeditor';
}
if ( $wmgVisualEditorEnableWikitext ) {
$wgVisualEditorEnableWikitext = true;
$wgDefaultUserOptions['visualeditor-newwikitext'] = true;
}
if ( $wmgVisualEditorEnableVisualSectionEditing ) {
$wgVisualEditorEnableVisualSectionEditing = $wmgVisualEditorEnableVisualSectionEditing;
}
if ( $wmgVisualEditorEnableNewMobileContext ) {
$wgVisualEditorEnableNewMobileContext = $wmgVisualEditorEnableNewMobileContext;
}
// Namespace configuration
$wgVisualEditorAvailableNamespaces = $wmgVisualEditorAvailableNamespaces;
if ( !isset( $wgVisualEditorAvailableNamespaces ) ) {
$wgVisualEditorAvailableNamespaces = []; // Set null to be an empty array to avoid fatals
}
// User access configuration
if ( $wmgVisualEditorDefault ) {
$wgDefaultUserOptions['visualeditor-enable'] = 1;
$wgHiddenPrefs[] = 'visualeditor-enable'; // T50666
} else {
// Only show the beta-disable preference if the wiki is in 'beta'.
$wgHiddenPrefs[] = 'visualeditor-betatempdisable';
}
if ( $wmgVisualEditorTransitionDefault ) {
$wgVisualEditorTransitionDefault = true;
}
// T52000 - to remove once roll-out is complete.
if ( $wmgVisualEditorDisableForAnons ) {
$wgVisualEditorDisableForAnons = true;
}
// Feedback configuration
if ( $wmgVisualEditorConsolidateFeedback ) {
$wgVisualEditorFeedbackAPIURL = 'https://www.mediawiki.org/w/api.php';
$wgVisualEditorFeedbackTitle = 'VisualEditor/Feedback';
$wgVisualEditorSourceFeedbackTitle = '2017 wikitext editor/Feedback';
}
// Enable for auto-created accounts
if ( $wmgVisualEditorAutoAccountEnable ) {
$wgVisualEditorAutoAccountEnable = true;
}
// Enable for a proportion of new accounts
if ( $wmgVisualEditorNewAccountEnableProportion ) {
$wgVisualEditorNewAccountEnableProportion = $wmgVisualEditorNewAccountEnableProportion;
}
// Citoid
wfLoadExtension( 'Citoid' );
// Move the citation button from the primary toolbar into the "other" group
if ( $wmgCiteVisualEditorOtherGroup ) {
$wgCiteVisualEditorOtherGroup = true;
}
// Enable the wikitext mode Beta Feature for opt-in
$wgVisualEditorEnableWikitextBetaFeature = true;
// Enable the diff page visual diff Beta Feature for opt-in
$wgVisualEditorEnableDiffPageBetaFeature = true;
}
if ( $wmgUseTemplateData ) { // T61702 - 2015-07-20
// TemplateData enabled for all wikis - 2014-09-29
wfLoadExtension( 'TemplateData' );
// TemplateData GUI enabled for all wikis - 2014-11-06
$wgTemplateDataUseGUI = true;
// TemplateWizard enabled for all TemplateData wikis – T202545
wfLoadExtension( 'TemplateWizard' );
}
if ( $wmgUseGoogleNewsSitemap ) {
wfLoadExtension( 'GoogleNewsSitemap' );
$wgGNSMfallbackCategory = $wmgGNSMfallbackCategory;
$wgGNSMcommentNamespace = $wmgGNSMcommentNamespace;
}
if ( $wmgUseCLDR ) {
wfLoadExtension( 'cldr' );
}
if ( $wmgUseIncubator ) {
wfLoadExtension( 'WikimediaIncubator' );
$wmincClosedWikis = $wgSiteMatrixClosedSites;
}
if ( $wmgUseWikiLove ) {
wfLoadExtension( 'WikiLove' );
$wgWikiLoveLogging = true;
$wgDefaultUserOptions['wikilove-enabled'] = 1;
}
if ( $wmgUseGuidedTour || $wmgUseGettingStarted ) {
wfLoadExtension( 'GuidedTour' );
}
if ( $wmgUseMobileApp ) {
wfLoadExtension( 'MobileApp' );
}
# Mobile related configuration
require "{$wmfConfigDir}/mobile.php";
# MUST be after MobileFrontend initialization
if ( $wmgEnableTextExtracts ) {
wfLoadExtension( 'TextExtracts' );
}
if ( $wmgUseSubPageList3 ) {
wfLoadExtension( 'SubPageList3' );
}
// Serve 'Powered by MediaWiki' badge from /static/images instead of
// $wgResourceBasePath so we can set far-future expires.
$wgFooterIcons['poweredby']['mediawiki']['src'] =
'/static/images/poweredby_mediawiki_88x31.png';
$wgFooterIcons['poweredby']['mediawiki']['srcset'] =
'/static/images/poweredby_mediawiki_132x47.png 1.5x, ' .
'/static/images/poweredby_mediawiki_176x62.png 2x';
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) {
$wgCookieSecure = true;
$_SERVER['HTTPS'] = 'on'; // Fake this so MW goes into HTTPS mode
}
$wgVaryOnXFP = true;
$wgCookieExpiration = 30 * 86400;
$wgExtendedLoginCookieExpiration = 365 * 86400;
if ( $wmgUseMath ) {
wfLoadExtension( 'Math' );
$wgTexvc = '/usr/bin/texvc';
$wgMathTexvcCheckExecutable = '/usr/bin/texvccheck';
$wgMathCheckFiles = false;
if ( $wmgUseMathML && $wmgUseRestbaseVRS ) {
$wgDefaultUserOptions['math'] = 'mathml';
}
// This variable points to non-WMF servers by default.
// Prevent accidental use.
$wgMathLaTeXMLUrl = null;
$wgMathMathMLUrl = $wmfLocalServices['mathoid'];
// Increase the number of concurrent connections made to RESTBase
$wgMathConcurrentReqs = 150;
// Set up $wgMathFullRestbaseURL - similar to VE RESTBase config above
// HACK: $wgServerName is not available yet at this point, it's set by Setup.php
// so use a hook
$wgExtensionFunctions[] = function () {
global $wgServerName, $wgMathFullRestbaseURL, $wmfRealm;
$wgMathFullRestbaseURL = $wmfRealm === 'production'
? 'https://wikimedia.org/api/rest_' // T136205
: "//$wgServerName/api/rest_";
};
}
if ( $wmgUseBabel ) {
wfLoadExtension( 'Babel' );
$wgBabelCategoryNames = $wmgBabelCategoryNames;
$wgBabelMainCategory = $wmgBabelMainCategory;
$wgBabelDefaultLevel = $wmgBabelDefaultLevel;
$wgBabelUseUserLanguage = $wmgBabelUseUserLanguage;
$wgBabelUseDatabase = true;
if ( $wmgUseCentralAuth ) {
$wgBabelCentralDb = 'metawiki';
$wgBabelCentralApi = 'https://meta.wikimedia.org/w/api.php';
}
}
if ( $wmgUseBounceHandler ) {
wfLoadExtension( 'BounceHandler' );
// $wmgVERPsecret is set in PrivateSettings.php
$wgVERPsecret = $wmgVERPsecret;
$wgVERPdomainPart = 'wikimedia.org';
$wgBounceHandlerUnconfirmUsers = true;
$wgBounceRecordLimit = 5;
$wgBounceHandlerCluster = 'extension1';
$wgBounceHandlerSharedDB = 'wikishared';
$wgBounceHandlerInternalIPs = [
'208.80.154.76', # mx1001
'2620:0:861:3:208:80:154:76', # mx1001
'208.80.153.45', # mx2001
'2620:0:860:2:208:80:153:45', # mx2001
];
}
if ( $wmgUseTranslate ) {
require_once "$IP/extensions/Translate/Translate.php";
$wgGroupPermissions['*']['translate'] = true;
$wgGroupPermissions['translationadmin']['pagetranslation'] = true;
$wgGroupPermissions['translationadmin']['translate-manage'] = true;
$wgGroupPermissions['translationadmin']['translate-import'] = true; // T42341
$wgGroupPermissions['translationadmin']['pagelang'] = true; // T153209
$wgGroupPermissions['user']['translate-messagereview'] = true;
$wgGroupPermissions['user']['translate-groupreview'] = true;
$wgGroupPermissions['sysop']['pagelang'] = true; // T153209
$wgAddGroups['bureaucrat'][] = 'translationadmin'; // T178793
$wgRemoveGroups['bureaucrat'][] = 'translationadmin'; // T178793
$wgGroupsAddToSelf['sysop'][] = 'translationadmin'; // T178793
$wgGroupsRemoveFromSelf['sysop'][] = 'translationadmin'; // T178793
$wgTranslateDocumentationLanguageCode = 'qqq';
$wgExtraLanguageNames['qqq'] = 'Message documentation'; # No linguistic content. Used for documenting messages
$wgPageLanguageUseDB = true; // T153209
$wgTranslateTranslationServices = [];
if ( $wmgUseTranslationMemory ) {
// Switch to 'eqiad' or 'codfw' if you plan to bring down
// the elastic cluster equals to $wmfDatacenter
$wgTranslateTranslationDefaultService = $wmfDatacenter;
// If the downtime is long (> 10mins) consider disabling
// mirroring in this var to avoid logspam about ttm updates
// then plan to refresh this index via ttmserver-export when
// it's back up.
// NOTE: these settings are also used for the labs cluster
// where codfw may not be available
$wgTranslateClustersAndMirrors = [
'eqiad' => isset( $wmfAllServices['codfw']['search-chi'] ) ? [ 'codfw' ] : [],
'codfw' => isset( $wmfAllServices['eqiad']['search-chi'] ) ? [ 'eqiad' ] : [],
];
foreach ( $wgTranslateClustersAndMirrors as $cluster => $mirrors ) {
if ( !isset( $wmfAllServices[$cluster]['search-chi'] ) ) {
continue;
}
$wgTranslateTranslationServices[$cluster] = [
'type' => 'ttmserver',
'class' => 'ElasticSearchTTMServer',
'shards' => 1,
'replicas' => 1,
'index' => $wmgTranslateESIndex,
'cutoff' => 0.65,
'use_wikimedia_extra' => true,
'config' => [
'servers' => array_map( function ( $hostConfig ) {
if ( is_array( $hostConfig ) ) {
return $hostConfig;
}
return [
'host' => $hostConfig,
'port' => 9243,
'transport' => 'Https',
];
}, $wmfAllServices[$cluster]['search-chi'] ),
],
'mirrors' => $mirrors,
];
}
unset( $wgTranslateClustersAndMirrors );
} else {
$wgTranslateTranslationDefaultService = false;
}
$wgTranslateWorkflowStates = $wmgTranslateWorkflowStates;
$wgTranslateRcFilterDefault = $wmgTranslateRcFilterDefault;
$wgTranslateUsePreSaveTransform = true; // T39304
$wgEnablePageTranslation = true;
$wgTranslateDelayedMessageIndexRebuild = true;
// Deprecated language codes
$wgTranslateBlacklist = [
'*' => [
'gan-hans' => 'Translate in gan please.',
'gan-hant' => 'Translate in gan please.',
'ike-cans' => 'Translate in iu please.',
'ike-latn' => 'Translate in iu please.',
'kk-cyrl' => 'Translate in kk please.',
'kk-latn' => 'Translate in kk please.',
'kk-arab' => 'Translate in kk please.',
'kk-kz' => 'Translate in kk please.',
'kk-tr' => 'Translate in kk please.',
'kk-cn' => 'Translate in kk please.',
'ku-latn' => 'Translate in ku please.',
'ku-arab' => 'Translate in ku please.',
'shi-tfng' => 'Translate in shi please.',
'shi-latn' => 'Translate in shi please.',
'sr-ec' => 'Translate in sr please.',
'sr-el' => 'Translate in sr please.',
'tg-latn' => 'Translate in tg please.',
'zh-hans' => 'Translate in zh please.',
'zh-hant' => 'Translate in zh please.',
'zh-cn' => 'Translate in zh please.',
'zh-hk' => 'Translate in zh please.',
'zh-mo' => 'Translate in zh please.',
'zh-my' => 'Translate in zh please.',
'zh-sg' => 'Translate in zh please.',
'zh-tw' => 'Translate in zh please.',
],
];
if ( $wgDBname === 'commonswiki' ) {
$wgHooks['TranslatePostInitGroups'][] = function ( &$cc ) {
$id = 'wiki-translatable';
$mg = new WikiMessageGroup( $id, 'translatable-messages' );
$mg->setLabel( 'Interface' );
$mg->setDescription( 'Messages used in the custom interface of this wiki' );
$cc[$id] = $mg;
return true;
};
};
$wgSpecialPages['ManageMessageGroups'] = DisabledSpecialPage::getCallback( 'ManageMessageGroups' );
$wgSpecialPages['TranslationStats'] = DisabledSpecialPage::getCallback( 'TranslationStats' );
$wgTranslateTranslationServices['Apertium'] = [
'type' => 'cxserver',
'host' => $wmfLocalServices['cxserver'],
'timeout' => 3,
];
}
if ( $wmgUseTranslationNotifications ) {
wfLoadExtension( 'TranslationNotifications' );
$wgNotificationUsername = 'Translation Notification Bot@Translation_Notification_Bot';
$wgNotificationUserPassword = $wmgTranslationNotificationUserPassword;
$wgTranslationNotificationsContactMethods['talkpage-elsewhere'] = true;
}
if ( $wmgUseFundraisingTranslateWorkflow ) {
wfLoadExtension( 'FundraisingTranslateWorkflow' );
}
if ( $wmgUseVips ) {
wfLoadExtension( 'VipsScaler' );
$wgVipsOptions = [
[
'conditions' => [
'mimeType' => 'image/png',
'minArea' => 2e7,
],
],
[
'conditions' => [
'mimeType' => 'image/tiff',
'minShrinkFactor' => 1.2,
'minArea' => 5e7,
],
'sharpen' => [ 'sigma' => 0.8 ],
],
];
}
if ( $wmgUseShortUrl ) {
wfLoadExtension( 'ShortUrl' );
$wgShortUrlTemplate = "/s/$1";
}
if ( $wmgUseFeaturedFeeds ) {
wfLoadExtension( 'FeaturedFeeds' );
require_once "$wmfConfigDir/FeaturedFeedsWMF.php";
}
$wgDisplayFeedsInSidebar = $wmgDisplayFeedsInSidebar;
if ( $wmgEnablePageTriage ) {
wfLoadExtension( 'PageTriage' );
$wgAddGroups['bureaucrat'][] = 'copyviobot'; // T206731
$wgRemoveGroups['bureaucrat'][] = 'copyviobot'; // T206731
}
if ( $wmgEnableInterwiki ) {
wfLoadExtension( 'Interwiki' );
$wgInterwikiViewOnly = true;
}
# Avoid excessive CPU due to cache misses from rapid invalidations
$wgJobBackoffThrottling['htmlCacheUpdate'] = 50; // pages/sec per runner
# Job types to exclude from the default queue processing. Aka the very long
# one. That will exclude the types from any queries such as nextJobDB.php
# We have to set this for any project cause we usually run PHP script against
# the 'aawiki' database, but might as well run it against another name.
# Timed Media Handler:
$wgJobTypesExcludedFromDefaultQueue[] = 'webVideoTranscode';
$wgJobTypesExcludedFromDefaultQueue[] = 'webVideoTranscodePrioritized';
# GWToolset
$wgJobTypesExcludedFromDefaultQueue[] = 'gwtoolsetUploadMetadataJob';
$wgJobTypesExcludedFromDefaultQueue[] = 'gwtoolsetUploadMediafileJob';
$wgJobTypesExcludedFromDefaultQueue[] = 'gwtoolsetGWTFileBackendCleanupJob';
if ( $wmgUseEducationProgram ) {
$wgExtraNamespaces[446] = 'Education_Program';