MediaWiki master
Sanitizer.php
Go to the documentation of this file.
1<?php
13namespace MediaWiki\Parser;
14
15use InvalidArgumentException;
16use LogicException;
20use UnexpectedValueException;
21use Wikimedia\RemexHtml\HTMLData;
22use Wikimedia\RemexHtml\Serializer\Serializer as RemexSerializer;
23use Wikimedia\RemexHtml\Tokenizer\Tokenizer as RemexTokenizer;
24use Wikimedia\RemexHtml\TreeBuilder\Dispatcher as RemexDispatcher;
25use Wikimedia\RemexHtml\TreeBuilder\TreeBuilder as RemexTreeBuilder;
27
32class Sanitizer {
39 private const CHAR_REFS_REGEX =
40 '/&([A-Za-z0-9\x80-\xff]+;)
41 |&\#([0-9]+);
42 |&\#[xX]([0-9A-Fa-f]+);
43 |&/x';
44
49 private const ELEMENT_BITS_REGEX = '!^(/?)([A-Za-z][^\t\n\v />\0]*+)([^>]*?)(/?>)([^<]*)$!';
50
60 private const EVIL_URI_PATTERN = '!(^|\s|\*/\s*)(javascript|vbscript)([^\w]|$)!i';
61 private const XMLNS_ATTRIBUTE_PATTERN = "/^xmlns:[:A-Z_a-z-.0-9]+$/";
62
68 public const ID_PRIMARY = 0;
69
76 public const ID_FALLBACK = 1;
77
82 private const MW_ENTITY_ALIASES = [
83 'רלמ;' => 'rlm;',
84 'رلم;' => 'rlm;',
85 ];
86
90 private static ?string $attribsRegex = null;
91
97 private static function getAttribsRegex(): string {
98 if ( self::$attribsRegex === null ) {
99 $spaceChars = '\x09\x0a\x0c\x0d\x20';
100 $space = "[{$spaceChars}]";
101 $attrib = "[^{$spaceChars}\/>=]";
102 $attribFirst = "(?:{$attrib}|=)";
103 self::$attribsRegex =
104 "/({$attribFirst}{$attrib}*)
105 ($space*=$space*
106 (?:
107 # The attribute value: quoted or alone
108 \"([^\"]*)(?:\"|\$)
109 | '([^']*)(?:'|\$)
110 | (((?!$space|>).)*)
111 )
112 )?/sxu";
113 }
114 return self::$attribsRegex;
115 }
116
120 private static ?string $attribNameRegex = null;
121
125 private static function getAttribNameRegex(): string {
126 if ( self::$attribNameRegex === null ) {
127 $attribFirst = "[:_\p{L}\p{N}]";
128 $attrib = "[:_\.\-\p{L}\p{N}]";
129 self::$attribNameRegex = "/^({$attribFirst}{$attrib}*)$/sxu";
130 }
131 return self::$attribNameRegex;
132 }
133
141 public static function getRecognizedTagData( array $extratags = [], array $removetags = [] ): array {
142 static $commonCase, $staticInitialised = false;
143 $isCommonCase = ( $extratags === [] && $removetags === [] );
144 if ( $staticInitialised && $isCommonCase && $commonCase ) {
145 return $commonCase;
146 }
147
148 static $htmlpairsStatic, $htmlsingle, $htmlsingleonly, $htmlnest, $tabletags,
149 $htmllist, $listtags, $htmlsingleallowed, $htmlelementsStatic;
150
151 if ( !$staticInitialised ) {
152 $htmlpairsStatic = [ # Tags that must be closed
153 'b', 'bdi', 'del', 'i', 'ins', 'u', 'font', 'big', 'small', 'sub', 'sup', 'h1',
154 'h2', 'h3', 'h4', 'h5', 'h6', 'cite', 'code', 'em', 's',
155 'strike', 'strong', 'tt', 'var', 'div', 'center',
156 'blockquote', 'ol', 'ul', 'dl', 'table', 'caption', 'pre',
157 'ruby', 'rb', 'rp', 'rt', 'rtc', 'p', 'span', 'abbr', 'dfn',
158 'kbd', 'samp', 'data', 'time', 'mark'
159 ];
160 # These tags can be self-closed. For tags not also on
161 # $htmlsingleonly, a self-closed tag will be emitted as
162 # an empty element (open-tag/close-tag pair).
163 $htmlsingle = [
164 'br', 'wbr', 'hr', 'li', 'dt', 'dd', 'meta', 'link'
165 ];
166
167 # Elements that cannot have close tags. This is (not coincidentally)
168 # also the list of tags for which the HTML 5 parsing algorithm
169 # requires you to "acknowledge the token's self-closing flag", i.e.
170 # a self-closing tag like <br/> is not an HTML 5 parse error only
171 # for this list.
172 $htmlsingleonly = [
173 'br', 'wbr', 'hr', 'meta', 'link'
174 ];
175
176 $htmlnest = [ # Tags that can be nested--??
177 'table', 'tr', 'td', 'th', 'div', 'blockquote', 'ol', 'ul',
178 'li', 'dl', 'dt', 'dd', 'font', 'big', 'small', 'sub', 'sup', 'span',
179 'var', 'kbd', 'samp', 'em', 'strong', 'q', 'ruby', 'bdo'
180 ];
181 $tabletags = [ # Can only appear inside table, we will close them
182 'td', 'th', 'tr',
183 ];
184 $htmllist = [ # Tags used by list
185 'ul', 'ol',
186 ];
187 $listtags = [ # Tags that can appear in a list
188 'li',
189 ];
190
191 $htmlsingleallowed = array_unique( array_merge( $htmlsingle, $tabletags ) );
192 $htmlelementsStatic = array_unique( array_merge( $htmlsingle, $htmlpairsStatic, $htmlnest ) );
193
194 # Convert them all to hashtables for faster lookup
195 $vars = [ 'htmlpairsStatic', 'htmlsingle', 'htmlsingleonly', 'htmlnest', 'tabletags',
196 'htmllist', 'listtags', 'htmlsingleallowed', 'htmlelementsStatic' ];
197 foreach ( $vars as $var ) {
198 $$var = array_fill_keys( $$var, true );
199 }
200 $staticInitialised = true;
201 }
202
203 # Populate $htmlpairs and $htmlelements with the $extratags and $removetags arrays
204 $extratags = array_fill_keys( $extratags, true );
205 $removetags = array_fill_keys( $removetags, true );
206 $htmlpairs = array_merge( $extratags, $htmlpairsStatic );
207 $htmlelements = array_diff_key( array_merge( $extratags, $htmlelementsStatic ), $removetags );
208
209 $result = [
210 'htmlpairs' => $htmlpairs,
211 'htmlsingle' => $htmlsingle,
212 'htmlsingleonly' => $htmlsingleonly,
213 'htmlnest' => $htmlnest,
214 'tabletags' => $tabletags,
215 'htmllist' => $htmllist,
216 'listtags' => $listtags,
217 'htmlsingleallowed' => $htmlsingleallowed,
218 'htmlelements' => $htmlelements,
219 ];
220 if ( $isCommonCase ) {
221 $commonCase = $result;
222 }
223 return $result;
224 }
225
254 public static function internalRemoveHtmlTags( string $text, ?callable $processCallback = null,
255 $args = [], array $extratags = [], array $removetags = []
256 ): string {
257 $tagData = self::getRecognizedTagData( $extratags, $removetags );
258 $htmlsingle = $tagData['htmlsingle'];
259 $htmlsingleonly = $tagData['htmlsingleonly'];
260 $htmlelements = $tagData['htmlelements'];
261
262 # Remove HTML comments
263 $text = self::removeHTMLcomments( $text );
264 $bits = explode( '<', $text );
265 $text = str_replace( '>', '&gt;', array_shift( $bits ) );
266
267 # this might be possible using remex tidy itself
268 foreach ( $bits as $x ) {
269 if ( preg_match( self::ELEMENT_BITS_REGEX, $x, $regs ) ) {
270 [ /* $qbar */, $slash, $t, $params, $brace, $rest ] = $regs;
271
272 $badtag = false;
273 $t = strtolower( $t );
274 if ( isset( $htmlelements[$t] ) ) {
275 if ( is_callable( $processCallback ) ) {
276 $processCallback( $params, $args );
277 }
278
279 if ( $brace == '/>' && !( isset( $htmlsingle[$t] ) || isset( $htmlsingleonly[$t] ) ) ) {
280 // Remove the self-closing slash, to be consistent
281 // with HTML5 semantics. T134423
282 $brace = '>';
283 }
284 if ( !self::validateTag( $params, $t ) ) {
285 $badtag = true;
286 }
287
288 $newparams = self::fixTagAttributes( $params, $t );
289 if ( !$badtag ) {
290 if ( $brace === '/>' && !isset( $htmlsingleonly[$t] ) ) {
291 # Interpret self-closing tags as empty tags even when
292 # HTML 5 would interpret them as start tags. Such input
293 # is commonly seen on Wikimedia wikis with this intention.
294 $brace = "></$t>";
295 }
296
297 $rest = str_replace( '>', '&gt;', $rest );
298 $text .= "<$slash$t$newparams$brace$rest";
299 continue;
300 }
301 }
302 }
303 $text .= '&lt;' . str_replace( '>', '&gt;', $x );
304 }
305 return $text;
306 }
307
331 public static function removeSomeTags(
332 string $text, array $options = []
333 ): string {
334 $extraTags = $options['extraTags'] ?? [];
335 $removeTags = $options['removeTags'] ?? [];
336 // These options are @internal:
337 $attrCallback = $options['attrCallback'] ?? null;
338 $attrCallbackArgs = $options['attrCallbackArgs'] ?? [];
339
340 // This disallows HTML5-style "missing trailing semicolon" attributes
341 // In wikitext "clean&copy" does *not* contain an entity.
342 $text = self::normalizeCharReferences( $text );
343
344 $tagData = self::getRecognizedTagData( $extraTags, $removeTags );
345 // Use RemexHtml to tokenize $text and remove the barred tags
346 $formatter = new RemexCompatFormatter;
347 $serializer = new RemexSerializer( $formatter );
348 $treeBuilder = new RemexTreeBuilder( $serializer, [
349 'ignoreErrors' => true,
350 'ignoreNulls' => true,
351 ] );
352 $dispatcher = new RemexDispatcher( $treeBuilder );
353 $tokenHandler = $dispatcher;
354 $remover = new RemexRemoveTagHandler(
355 $tokenHandler, $text, $tagData,
356 $attrCallback, $attrCallbackArgs,
357 [ 'commentRegex' => $options['commentRegex'] ?? null ]
358 );
359 $tokenizer = new RemexTokenizer( $remover, $text, [
360 'ignoreErrors' => true,
361 // don't ignore char refs, we want them to be decoded
362 'ignoreNulls' => true,
363 'skipPreprocess' => true,
364 ] );
365 $tokenizer->execute( [
366 'fragmentNamespace' => HTMLData::NS_HTML,
367 'fragmentName' => 'body',
368 ] );
369 return $serializer->getResult();
370 }
371
378 public static function removeHTMLcomments( string $text ): string {
379 // phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
380 while ( ( $start = strpos( $text, '<!--' ) ) !== false ) {
381 $end = strpos( $text, '-->', $start + 4 );
382 if ( $end === false ) {
383 # Unterminated comment; bail out
384 break;
385 }
386
387 $end += 3;
388
389 # Trim space and newline if the comment is both
390 # preceded and followed by a newline
391 $spaceStart = max( $start - 1, 0 );
392 $spaceLen = $end - $spaceStart;
393 while ( substr( $text, $spaceStart, 1 ) === ' ' && $spaceStart > 0 ) {
394 $spaceStart--;
395 $spaceLen++;
396 }
397 while ( substr( $text, $spaceStart + $spaceLen, 1 ) === ' ' ) {
398 $spaceLen++;
399 }
400 if ( substr( $text, $spaceStart, 1 ) === "\n"
401 && substr( $text, $spaceStart + $spaceLen, 1 ) === "\n" ) {
402 # Remove the comment, leading and trailing
403 # spaces, and leave only one newline.
404 $text = substr_replace( $text, "\n", $spaceStart, $spaceLen + 1 );
405 } else {
406 # Remove just the comment.
407 $text = substr_replace( $text, '', $start, $end - $start );
408 }
409 }
410 return $text;
411 }
412
423 private static function validateTag( string $params, string $element ): bool {
424 $params = self::decodeTagAttributes( $params );
425
426 if ( $element == 'meta' || $element == 'link' ) {
427 if ( !isset( $params['itemprop'] ) ) {
428 // <meta> and <link> must have an itemprop="" otherwise they are not valid or safe in content
429 return false;
430 }
431 if ( $element == 'meta' && !isset( $params['content'] ) ) {
432 // <meta> must have a content="" for the itemprop
433 return false;
434 }
435 if ( $element == 'link' && !isset( $params['href'] ) ) {
436 // <link> must have an associated href=""
437 return false;
438 }
439 }
440
441 return true;
442 }
443
455 public static function validateTagAttributes( array $attribs, string $element ): array {
456 return self::validateAttributes( $attribs,
457 self::attributesAllowedInternal( $element ) );
458 }
459
478 public static function validateAttributes( array $attribs, array $allowed ): array {
479 if ( isset( $allowed[0] ) ) {
480 // Calling this function with a sequential array is
481 // deprecated. For now just convert it.
482 wfDeprecated( __METHOD__ . ' with sequential array', '1.35' );
483 $allowed = array_fill_keys( $allowed, true );
484 }
485 $validProtocols = MediaWikiServices::getInstance()->getUrlUtils()->validProtocols();
486 $hrefExp = '/^(' . $validProtocols . ')[^\s]+$/';
487
488 $out = [];
489 foreach ( $attribs as $attribute => $value ) {
490 # Allow XML namespace declaration to allow RDFa
491 if ( preg_match( self::XMLNS_ATTRIBUTE_PATTERN, $attribute ) ) {
492 if ( !preg_match( self::EVIL_URI_PATTERN, $value ) ) {
493 $out[$attribute] = $value;
494 }
495
496 continue;
497 }
498
499 # Allow any attribute beginning with "data-"
500 # However:
501 # * Disallow data attributes used by MediaWiki code
502 # * Ensure that the attribute is not namespaced by banning
503 # colons.
504 # * Ensure attribute name will be accepted by the HTML
505 # parser; see
506 # https://github.com/whatwg/dom/issues/849#issuecomment-1007541209
507 # * Underscore and double-wide underscore (U+FF3F) is disallowed
508 # here (but not in Parsoid): T407131
509 if ( (
510 !preg_match( '|^data-[^:= \t\r\n/>\0__]*$|i', $attribute ) &&
511 !array_key_exists( $attribute, $allowed )
512 ) || self::isReservedDataAttribute( $attribute ) ) {
513 continue;
514 }
515
516 # Strip javascript "expression" from stylesheets.
517 # https://msdn.microsoft.com/en-us/library/ms537634.aspx
518 if ( $attribute == 'style' ) {
519 $value = self::checkCss( $value );
520 }
521
522 # Escape HTML id attributes
523 if ( $attribute === 'id' ) {
524 $value = self::escapeIdForAttribute( $value, self::ID_PRIMARY );
525 if ( $value === false || $value === '' ) {
526 continue;
527 }
528 }
529
530 # Escape HTML id reference lists
531 if ( $attribute === 'aria-describedby'
532 || $attribute === 'aria-flowto'
533 || $attribute === 'aria-labelledby'
534 || $attribute === 'aria-owns'
535 ) {
536 $value = self::escapeIdReferenceListInternal( $value );
537 }
538
539 // RDFa and microdata properties allow URLs, URIs and/or CURIs.
540 if ( $attribute === 'rel' || $attribute === 'rev'
541 # RDFa
542 || $attribute === 'about' || $attribute === 'property'
543 || $attribute === 'resource' || $attribute === 'datatype'
544 || $attribute === 'typeof'
545 # HTML5 microdata
546 || $attribute === 'itemid' || $attribute === 'itemprop'
547 || $attribute === 'itemref' || $attribute === 'itemscope'
548 || $attribute === 'itemtype'
549 ) {
550 // Paranoia. Allow "simple" values but suppress javascript
551 if ( preg_match( self::EVIL_URI_PATTERN, $value ) ) {
552 continue;
553 }
554 }
555
556 # NOTE: even though elements using href/src are not allowed directly, supply
557 # validation code that can be used by tag hook handlers, etc
558 if ( $attribute === 'href' || $attribute === 'src' || $attribute === 'poster' ) {
559 if ( !preg_match( $hrefExp, $value ) ) {
560 continue; // drop any href or src attributes not using an allowed protocol.
561 // NOTE: this also drops all relative URLs
562 }
563 }
564
565 if ( $attribute === 'tabindex' && $value !== '0' ) {
566 // Only allow tabindex of 0, which is useful for accessibility.
567 continue;
568 }
569
570 // If this attribute was previously set, override it.
571 // Output should only have one attribute of each name.
572 $out[$attribute] = $value;
573 }
574
575 # itemtype, itemid, itemref don't make sense without itemscope
576 if ( !array_key_exists( 'itemscope', $out ) ) {
577 unset( $out['itemtype'] );
578 unset( $out['itemid'] );
579 unset( $out['itemref'] );
580 }
581 # TODO: Strip itemprop if we aren't descendants of an itemscope or pointed to by an itemref.
582
583 return $out;
584 }
585
593 public static function isReservedDataAttribute( string $attr ): bool {
594 // data-ooui is reserved for ooui.
595 // data-mw and data-parsoid are reserved for parsoid.
596 // data-mw-<name here> is reserved for extensions (or core) if
597 // they need to communicate some data to the client and want to be
598 // sure that it isn't coming from an untrusted user.
599 // We ignore the possibility of namespaces since user-generated HTML
600 // can't use them anymore.
601 return (bool)preg_match( '/^data-(ooui|mw|parsoid)/i', $attr );
602 }
603
613 public static function mergeAttributes( array $a, array $b ): array {
614 $out = array_merge( $a, $b );
615 if ( isset( $a['class'] ) && isset( $b['class'] )
616 && is_string( $a['class'] ) && is_string( $b['class'] )
617 && $a['class'] !== $b['class']
618 ) {
619 $classes = preg_split( '/\s+/', "{$a['class']} {$b['class']}",
620 -1, PREG_SPLIT_NO_EMPTY );
621 $out['class'] = implode( ' ', array_unique( $classes ) );
622 }
623 return $out;
624 }
625
634 public static function normalizeCss( string $value ): string {
635 // Decode character references like &#123;
636 $value = self::decodeCharReferences( $value );
637
638 // Decode escape sequences and line continuation
639 // See the grammar in the CSS 2 spec, appendix D.
640 // This has to be done AFTER decoding character references.
641 // This means it isn't possible for this function to return
642 // unsanitized escape sequences. It is possible to manufacture
643 // input that contains character references that decode to
644 // escape sequences that decode to character references, but
645 // it's OK for the return value to contain character references
646 // because the caller is supposed to escape those anyway.
647 static $decodeRegex;
648 if ( !$decodeRegex ) {
649 $space = '[\\x20\\t\\r\\n\\f]';
650 $nl = '(?:\\n|\\r\\n|\\r|\\f)';
651 $backslash = '\\\\';
652 $decodeRegex = "/ $backslash
653 (?:
654 ($nl) | # 1. Line continuation
655 ([0-9A-Fa-f]{1,6})$space? | # 2. character number
656 (.) | # 3. backslash cancelling special meaning
657 () | # 4. backslash at end of string
658 )/xu";
659 }
660 $value = preg_replace_callback( $decodeRegex,
661 self::cssDecodeCallback( ... ), $value );
662
663 // Let the value through if it's nothing but a single comment, to
664 // allow other functions which may reject it to pass some error
665 // message through.
666 if ( !preg_match( '! ^ \s* /\* [^*\\/]* \*/ \s* $ !x', $value ) ) {
667 // Remove any comments; IE gets token splitting wrong
668 // This must be done AFTER decoding character references and
669 // escape sequences, because those steps can introduce comments
670 // This step cannot introduce character references or escape
671 // sequences, because it replaces comments with spaces rather
672 // than removing them completely.
673 $value = StringUtils::delimiterReplace( '/*', '*/', ' ', $value );
674
675 // Remove anything after a comment-start token, to guard against
676 // incorrect client implementations.
677 $commentPos = strpos( $value, '/*' );
678 if ( $commentPos !== false ) {
679 $value = substr( $value, 0, $commentPos );
680 }
681 }
682
683 return $value;
684 }
685
706 public static function checkCss( $value ) {
707 $value = self::normalizeCss( $value );
708
709 // Reject problematic keywords and control characters
710 if ( preg_match( '/[\000-\010\013\016-\037\177]/', $value ) ||
711 str_contains( $value, \UtfNormal\Constants::UTF8_REPLACEMENT ) ) {
712 return '/* invalid control char */';
713 } elseif ( preg_match(
714 '! expression
715 | accelerator\s*:
716 | -o-link\s*:
717 | -o-link-source\s*:
718 | -o-replace\s*:
719 | url\s*\‍(
720 | src\s*\‍(
721 | image\s*\‍(
722 | image-set\s*\‍(
723 | attr\s*\‍([^)]+[\s,]+url
724 !ix', $value ) ) {
725 return '/* insecure input */';
726 }
727 return $value;
728 }
729
730 private static function cssDecodeCallback( array $matches ): string {
731 if ( $matches[1] !== '' ) {
732 // Line continuation
733 return '';
734 } elseif ( $matches[2] !== '' ) {
735 # hexdec could return a float if the match is too long, but the
736 # regexp in question limits the string length to 6.
737 $char = \UtfNormal\Utils::codepointToUtf8( hexdec( $matches[2] ) );
738 } elseif ( $matches[3] !== '' ) {
739 $char = $matches[3];
740 } else {
741 $char = '\\';
742 }
743 if ( $char == "\n" || $char == '"' || $char == "'" || $char == '\\' ) {
744 // These characters need to be escaped in strings
745 // Clean up the escape sequence to avoid parsing errors by clients
746 return '\\' . dechex( ord( $char ) ) . ' ';
747 } else {
748 // Decode unnecessary escape
749 return $char;
750 }
751 }
752
774 public static function fixTagAttributes( string $text, string $element, bool $sorted = false ): string {
775 if ( trim( $text ) == '' ) {
776 return '';
777 }
778
779 $decoded = self::decodeTagAttributes( $text );
780 $stripped = self::validateTagAttributes( $decoded, $element );
781
782 if ( $sorted ) {
783 ksort( $stripped );
784 }
785
786 return self::safeEncodeTagAttributes( $stripped );
787 }
788
796 public static function encodeAttribute( string $text ): string {
797 $encValue = htmlspecialchars( $text, ENT_QUOTES );
798
799 // Whitespace is normalized during attribute decoding,
800 // so if we've been passed non-spaces we must encode them
801 // ahead of time or they won't be preserved.
802 $encValue = strtr( $encValue, [
803 "\n" => '&#10;',
804 "\r" => '&#13;',
805 "\t" => '&#9;',
806 ] );
807
808 return $encValue;
809 }
810
819 public static function armorFrenchSpaces( string $text, string $space = '&#160;' ): string {
820 // Replace $ with \$ and \ with \\
821 $space = preg_replace( '#(?<!\\\\‍)(\\$|\\\\‍)#', '\\\\$1', $space );
822 $fixtags = [
823 # French spaces, last one Guillemet-left
824 # only if it isn't followed by a word character.
825 '/ (?=[?:;!%»›](?!\w))/u' => "$space",
826 # French spaces, Guillemet-right
827 '/([«‹]) /u' => "\\1$space",
828 ];
829 return preg_replace( array_keys( $fixtags ), array_values( $fixtags ), $text );
830 }
831
840 public static function safeEncodeAttribute( string $text ): string {
841 $encValue = self::encodeAttribute( $text );
842
843 # Templates and links may be expanded in later parsing,
844 # creating invalid or dangerous output. Suppress this.
845 $encValue = strtr( $encValue, [
846 // '<', '>', and '"' should never happen, as they indicate that we've received invalid input which should
847 // have been escaped.
848 '<' => '&lt;',
849 '>' => '&gt;',
850 '"' => '&quot;',
851 '{' => '&#123;',
852 '}' => '&#125;', // prevent unpaired language conversion syntax
853 '[' => '&#91;',
854 ']' => '&#93;',
855 "''" => '&#39;&#39;',
856 'ISBN' => '&#73;SBN',
857 'RFC' => '&#82;FC',
858 'PMID' => '&#80;MID',
859 '|' => '&#124;',
860 '_' => '&#95;',
861 '_' => '&#xFF3F;', // Japanese magic words
862 ] );
863
864 # Stupid hack
865 $validProtocols = MediaWikiServices::getInstance()->getUrlUtils()->validProtocols();
866 $encValue = preg_replace_callback(
867 '/((?i)' . $validProtocols . ')/',
868 static function ( $matches ) {
869 return str_replace( ':', '&#58;', $matches[1] );
870 },
871 $encValue );
872 return $encValue;
873 }
874
890 public static function escapeIdForAttribute( string $id, int $mode = self::ID_PRIMARY ) {
891 global $wgFragmentMode;
892
893 if ( !isset( $wgFragmentMode[$mode] ) ) {
894 if ( $mode === self::ID_PRIMARY ) {
895 throw new UnexpectedValueException( '$wgFragmentMode is configured with no primary mode' );
896 }
897 return false;
898 }
899
900 $internalMode = $wgFragmentMode[$mode];
901
902 return self::escapeIdInternal( $id, $internalMode );
903 }
904
917 public static function escapeIdForLink( string $id ): string {
918 global $wgFragmentMode;
919
920 if ( !isset( $wgFragmentMode[self::ID_PRIMARY] ) ) {
921 throw new UnexpectedValueException( '$wgFragmentMode is configured with no primary mode' );
922 }
923
924 $mode = $wgFragmentMode[self::ID_PRIMARY];
925
926 $id = self::escapeIdInternalUrl( $id, $mode );
927
928 return $id;
929 }
930
940 public static function escapeIdForExternalInterwiki( string $id ): string {
941 global $wgExternalInterwikiFragmentMode;
942
943 $id = self::escapeIdInternalUrl( $id, $wgExternalInterwikiFragmentMode );
944
945 return $id;
946 }
947
957 private static function escapeIdInternalUrl( string $id, string $mode ): string {
958 $id = self::escapeIdInternal( $id, $mode );
959 if ( $mode === 'html5' ) {
960 $id = preg_replace( '/%([a-fA-F0-9]{2})/', '%25$1', $id );
961 }
962 return $id;
963 }
964
972 private static function escapeIdInternal( string $id, string $mode ): string {
973 // Truncate overly-long IDs. This isn't an HTML limit, it's just
974 // griefer protection. [T251506]
975 $id = mb_substr( $id, 0, 1024 );
976
977 switch ( $mode ) {
978 case 'html5':
979 // html5 spec says ids must not have any of the following:
980 // U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020 SPACE
981 // In practice, in wikitext, only tab, LF, CR (and SPACE) are
982 // possible using either Lua or html entities.
983 $id = str_replace( [ "\t", "\n", "\f", "\r", " " ], '_', $id );
984 break;
985 case 'legacy':
986 // This corresponds to 'noninitial' mode of the former escapeId()
987 static $replace = [
988 '%3A' => ':',
989 '%' => '.'
990 ];
991
992 $id = urlencode( str_replace( ' ', '_', $id ) );
993 $id = strtr( $id, $replace );
994 break;
995 default:
996 throw new InvalidArgumentException( "Invalid mode '$mode' passed to '" . __METHOD__ );
997 }
998
999 return $id;
1000 }
1001
1009 private static function escapeIdReferenceListInternal( string $referenceString ): string {
1010 # Explode the space delimited list string into an array of tokens
1011 $references = preg_split( '/\s+/', "{$referenceString}", -1, PREG_SPLIT_NO_EMPTY );
1012
1013 # Escape each token as an id
1014 foreach ( $references as &$ref ) {
1015 $ref = self::escapeIdForAttribute( $ref );
1016 }
1017
1018 # Merge the array back to a space delimited list string
1019 # If the array is empty, the result will be an empty string ('')
1020 $referenceString = implode( ' ', $references );
1021
1022 return $referenceString;
1023 }
1024
1033 public static function escapeClass( string $class ): string {
1034 // Convert ugly stuff to underscores and kill underscores in ugly places
1035 return rtrim( preg_replace(
1036 [ '/(^[0-9\\-])|[\\x00-\\x20!"#$%&\'()*+,.\\/:;<=>?@[\\]^`{|}~]|\\xC2\\xA0/', '/_+/' ],
1037 '_',
1038 $class ), '_' );
1039 }
1040
1041 public static function escapeCombiningChar( string $html ): string {
1042 return strtr( $html, [
1043 "\u{0338}" => '&#x338;', # T387130
1044 ] );
1045 }
1046
1056 public static function escapeHtmlAllowEntities( string $html ): string {
1057 $html = self::decodeCharReferences( $html );
1058 # It seems wise to escape ' as well as ", as a matter of course. Can't
1059 # hurt. Use ENT_SUBSTITUTE so that incorrectly truncated multibyte characters
1060 # don't cause the entire string to disappear.
1061 $html = htmlspecialchars( $html, ENT_QUOTES | ENT_SUBSTITUTE );
1062 return self::escapeCombiningChar( $html );
1063 }
1064
1070 public static function decodeTagAttributes( string $text ): array {
1071 if ( trim( $text ) == '' ) {
1072 return [];
1073 }
1074
1075 $pairs = [];
1076 if ( !preg_match_all(
1077 self::getAttribsRegex(),
1078 $text,
1079 $pairs,
1080 PREG_SET_ORDER ) ) {
1081 return [];
1082 }
1083
1084 $attribs = [];
1085 foreach ( $pairs as $set ) {
1086 $attribute = strtolower( $set[1] );
1087
1088 // Filter attribute names with unacceptable characters
1089 if ( !preg_match( self::getAttribNameRegex(), $attribute ) ) {
1090 continue;
1091 }
1092
1093 $value = self::getTagAttributeCallback( $set );
1094
1095 // Normalize whitespace
1096 $value = preg_replace( '/[\t\r\n ]+/', ' ', $value );
1097 $value = trim( $value );
1098
1099 // Decode character references
1100 $attribs[$attribute] = self::decodeCharReferences( $value );
1101 }
1102 return $attribs;
1103 }
1104
1109 public static function safeEncodeTagAttributes( array $assoc_array ): string {
1110 $attribs = [];
1111 foreach ( $assoc_array as $attribute => $value ) {
1112 $encAttribute = htmlspecialchars( $attribute, ENT_COMPAT );
1113 $encValue = self::safeEncodeAttribute( $value );
1114
1115 $attribs[] = "$encAttribute=\"$encValue\"";
1116 }
1117 return count( $attribs ) ? ' ' . implode( ' ', $attribs ) : '';
1118 }
1119
1124 private static function getTagAttributeCallback( array $set ): string {
1125 if ( isset( $set[5] ) ) {
1126 # No quotes.
1127 return $set[5];
1128 } elseif ( isset( $set[4] ) ) {
1129 # Single-quoted
1130 return $set[4];
1131 } elseif ( isset( $set[3] ) ) {
1132 # Double-quoted
1133 return $set[3];
1134 } elseif ( !isset( $set[2] ) ) {
1135 # In XHTML, attributes must have a value so return an empty string.
1136 # See "Empty attribute syntax",
1137 # https://www.w3.org/TR/html5/syntax.html#syntax-attribute-name
1138 return "";
1139 } else {
1140 throw new LogicException( "Tag conditions not met. This should never happen and is a bug." );
1141 }
1142 }
1143
1144 private static function normalizeWhitespace( string $text ): string {
1145 $normalized = preg_replace( '/[ \r\n\t]+/', ' ', $text );
1146 if ( $normalized === null ) {
1147 wfLogWarning( __METHOD__ . ': Failed to normalize whitespace: ' . preg_last_error() );
1148 return '';
1149 }
1150 return trim( $normalized );
1151 }
1152
1158 public static function normalizeSectionNameWhitespace( string $section ): string {
1159 $normalized = preg_replace( '/[ _]+/', ' ', $section );
1160 if ( $normalized === null ) {
1161 wfLogWarning( __METHOD__ . ': Failed to normalize whitespace: ' . preg_last_error() );
1162 return '';
1163 }
1164 return trim( $normalized );
1165 }
1166
1180 public static function normalizeCharReferences( string $text ): string {
1181 return preg_replace_callback(
1182 self::CHAR_REFS_REGEX,
1183 self::normalizeCharReferencesCallback( ... ),
1184 $text, -1, $count, PREG_UNMATCHED_AS_NULL
1185 );
1186 }
1187
1188 private static function normalizeCharReferencesCallback( array $matches ): string {
1189 $ret = null;
1190 if ( isset( $matches[1] ) ) {
1191 $ret = self::normalizeEntity( $matches[1] );
1192 } elseif ( isset( $matches[2] ) ) {
1193 $ret = self::decCharReference( $matches[2] );
1194 } elseif ( isset( $matches[3] ) ) {
1195 $ret = self::hexCharReference( $matches[3] );
1196 }
1197 if ( $ret === null ) {
1198 return htmlspecialchars( $matches[0], ENT_COMPAT );
1199 } else {
1200 return $ret;
1201 }
1202 }
1203
1214 private static function normalizeEntity( string $name ): string {
1215 if ( isset( self::MW_ENTITY_ALIASES[$name] ) ) {
1216 // Non-standard MediaWiki-specific entities
1217 return '&' . self::MW_ENTITY_ALIASES[$name];
1218 } elseif ( in_array( $name, [ 'lt;', 'gt;', 'amp;', 'quot;' ], true ) ) {
1219 // Keep these in word form
1220 return "&$name";
1221 } elseif ( isset( HTMLData::NAMED_ENTITY_TRANSLATION[$name] ) ) {
1222 // Beware: some entities expand to more than 1 codepoint
1223 return preg_replace_callback( '/./Ssu', static function ( $m ) {
1224 return '&#' . \UtfNormal\Utils::utf8ToCodepoint( $m[0] ) . ';';
1225 }, HTMLData::NAMED_ENTITY_TRANSLATION[$name] );
1226 } else {
1227 return "&amp;$name";
1228 }
1229 }
1230
1231 private static function decCharReference( string $codepoint ): ?string {
1232 # intval() will (safely) saturate at the maximum signed integer
1233 # value if $codepoint is too many digits
1234 $point = intval( $codepoint );
1235 if ( self::validateCodepoint( $point ) ) {
1236 return "&#$point;";
1237 } else {
1238 return null;
1239 }
1240 }
1241
1242 private static function hexCharReference( string $codepoint ): ?string {
1243 $point = hexdec( $codepoint );
1244 // hexdec() might return a float if the string is too long
1245 if ( is_int( $point ) && self::validateCodepoint( $point ) ) {
1246 return sprintf( '&#x%x;', $point );
1247 } else {
1248 return null;
1249 }
1250 }
1251
1256 private static function validateCodepoint( int $codepoint ): bool {
1257 # U+000C is valid in HTML5 but not allowed in XML.
1258 # U+000D is valid in XML but not allowed in HTML5.
1259 # U+007F - U+009F are disallowed in HTML5 (control characters).
1260 return $codepoint == 0x09
1261 || $codepoint == 0x0a
1262 || ( $codepoint >= 0x20 && $codepoint <= 0x7e )
1263 || ( $codepoint >= 0xa0 && $codepoint <= 0xd7ff )
1264 || ( $codepoint >= 0xe000 && $codepoint <= 0xfffd )
1265 || ( $codepoint >= 0x10000 && $codepoint <= 0x10ffff );
1266 }
1267
1272 public static function decodeCharReferences( string $text ): string {
1273 return preg_replace_callback(
1274 self::CHAR_REFS_REGEX,
1275 self::decodeCharReferencesCallback( ... ),
1276 $text, -1, $count, PREG_UNMATCHED_AS_NULL
1277 );
1278 }
1279
1290 public static function decodeCharReferencesAndNormalize( string $text ): string {
1291 $text = preg_replace_callback(
1292 self::CHAR_REFS_REGEX,
1293 self::decodeCharReferencesCallback( ... ),
1294 $text, -1, $count, PREG_UNMATCHED_AS_NULL
1295 );
1296
1297 if ( $count ) {
1298 return MediaWikiServices::getInstance()->getContentLanguage()->normalize( $text );
1299 } else {
1300 return $text;
1301 }
1302 }
1303
1304 private static function decodeCharReferencesCallback( array $matches ): string {
1305 if ( isset( $matches[1] ) ) {
1306 return self::decodeEntity( $matches[1] );
1307 } elseif ( isset( $matches[2] ) ) {
1308 // Value is user provided string and may exceed native int bounds.
1309 // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
1310 return self::decodeChar( @intval( $matches[2] ) );
1311 } elseif ( isset( $matches[3] ) ) {
1312 $point = hexdec( $matches[3] );
1313 // hexdec() might return a float if the string is too long
1314 if ( !is_int( $point ) ) {
1315 // Invalid character reference.
1316 return \UtfNormal\Constants::UTF8_REPLACEMENT;
1317 }
1318 return self::decodeChar( $point );
1319 }
1320 # Last case should be an ampersand by itself
1321 return $matches[0];
1322 }
1323
1329 private static function decodeChar( int $codepoint ): string {
1330 if ( self::validateCodepoint( $codepoint ) ) {
1331 return \UtfNormal\Utils::codepointToUtf8( $codepoint );
1332 } else {
1333 return \UtfNormal\Constants::UTF8_REPLACEMENT;
1334 }
1335 }
1336
1345 private static function decodeEntity( string $name ): string {
1346 // These are MediaWiki-specific entities, not in the HTML standard
1347 if ( isset( self::MW_ENTITY_ALIASES[$name] ) ) {
1348 $name = self::MW_ENTITY_ALIASES[$name];
1349 }
1350 $trans = HTMLData::NAMED_ENTITY_TRANSLATION[$name] ?? null;
1351 return $trans ?? "&$name";
1352 }
1353
1361 private static function attributesAllowedInternal( string $element ): array {
1362 $list = self::setupAttributesAllowedInternal();
1363 return $list[$element] ?? [];
1364 }
1365
1373 private static function setupAttributesAllowedInternal(): array {
1374 static $allowed;
1375
1376 if ( $allowed !== null ) {
1377 return $allowed;
1378 }
1379
1380 // For lookup efficiency flip each attributes array so the keys are
1381 // the valid attributes.
1382 $merge = static function ( $a, $b, $c = [] ) {
1383 return array_merge(
1384 $a,
1385 array_fill_keys( $b, true ),
1386 array_fill_keys( $c, true ) );
1387 };
1388 $common = $merge( [], [
1389 # HTML
1390 'id',
1391 'class',
1392 'style',
1393 'lang',
1394 'dir',
1395 'title',
1396 'tabindex',
1397
1398 # WAI-ARIA
1399 'aria-describedby',
1400 'aria-flowto',
1401 'aria-hidden',
1402 'aria-label',
1403 'aria-labelledby',
1404 'aria-level',
1405 'aria-owns',
1406 'role',
1407
1408 # RDFa
1409 # These attributes are specified in section 9 of
1410 # https://www.w3.org/TR/2008/REC-rdfa-syntax-20081014
1411 'about',
1412 'property',
1413 'resource',
1414 'datatype',
1415 'typeof',
1416
1417 # Microdata. These are specified by
1418 # https://html.spec.whatwg.org/multipage/microdata.html#the-microdata-model
1419 'itemid',
1420 'itemprop',
1421 'itemref',
1422 'itemscope',
1423 'itemtype',
1424 ] );
1425
1426 $block = $merge( $common, [ 'align' ] );
1427
1428 $tablealign = [ 'align', 'valign' ];
1429 $tablecell = [
1430 'abbr',
1431 'axis',
1432 'headers',
1433 'scope',
1434 'rowspan',
1435 'colspan',
1436 'nowrap', # deprecated
1437 'width', # deprecated
1438 'height', # deprecated
1439 'bgcolor', # deprecated
1440 ];
1441
1442 # HTML 5 section numbers refer to sections in HTML 5 standard describing the element.
1443 # Current revision: 2024-03-13 commit a187fec
1444 # See: https://html.spec.whatwg.org/multipage/
1445 # See: https://github.com/whatwg/html/commits
1446 #
1447 # HTML 4.01 section numbers refer to sections in HTML 4.01 standard describing the element.
1448 # See: https://www.w3.org/TR/html4/
1449 $allowed = [
1450 # HTML 5 section 4.2 Document metadata
1451 # https://html.spec.whatwg.org/multipage/semantics.html#document-metadata
1452
1453 # HTML 5 section 4.2.5, 4.2.4
1454 # meta and link are only permitted by internalRemoveHtmlTags when Microdata
1455 # is enabled so we don't bother adding a conditional to hide these.
1456 # Also meta and link are only valid in wikitext as Microdata elements
1457 # (ie: validateTag rejects tags missing the attributes needed for Microdata)
1458 # So we don't bother including $common attributes that have no purpose.
1459 'meta' => $merge( [], [ 'itemprop', 'content' ] ),
1460 'link' => $merge( [], [ 'itemprop', 'href', 'title' ] ),
1461
1462 # HTML 5 section 4.3 Sections
1463 # https://html.spec.whatwg.org/multipage/sections.html
1464
1465 # HTML 5 section 4.3.2, 4.3.3, 4.3.4, 4.3.5
1466 # 'article' => $common,
1467 # 'section' => $common,
1468 # 'nav' => $common,
1469 'aside' => $common,
1470
1471 # HTML 5 section 4.3.6
1472 # HTML 4.01 section 7.5.5
1473 'h1' => $block,
1474 'h2' => $block,
1475 'h3' => $block,
1476 'h4' => $block,
1477 'h5' => $block,
1478 'h6' => $block,
1479
1480 # HTML 5 section 4.3.7
1481 # 'hgroup' => $common,
1482
1483 # HTML 5 section 4.3.8, 4.3.9
1484 # 'header' => $common,
1485 # 'footer' => $common,
1486
1487 # HTML 5 section 4.3.10
1488 # HTML 4.01 section 7.5.6
1489 # 'address' => $common,
1490
1491 # HTML 5 section 4.4 Grouping content
1492 # https://html.spec.whatwg.org/multipage/grouping-content.html
1493
1494 # HTML 5 section 4.4.1
1495 # HTML 4.01 section 9.3.1
1496 'p' => $block,
1497
1498 # HTML 5 section 4.4.2
1499 # HTML 4.01 section 15.3
1500 'hr' => $merge( $common, [ 'width' ] ),
1501
1502 # HTML 5 section 4.4.3
1503 # HTML 4.01 section 9.3.4
1504 'pre' => $merge( $common, [ 'width' ] ),
1505
1506 # HTML 5 section 4.4.4
1507 # HTML 4.01 section 9.2.2
1508 'blockquote' => $merge( $common, [ 'cite' ] ),
1509
1510 # HTML 5 section 4.4.5, 4.4.6
1511 # HTML 4.01 section 10.2
1512 'ol' => $merge( $common, [ 'type', 'start', 'reversed' ] ),
1513 'ul' => $merge( $common, [ 'type' ] ),
1514
1515 # HTML 5 section 4.4.7
1516 # 'menu' => $merge( $common, [ 'type' ] ),
1517
1518 # HTML 5 section 4.4.8
1519 # HTML 4.01 section 10.2
1520 'li' => $merge( $common, [ 'type', 'value' ] ),
1521
1522 # HTML 5 section 4.4.9, 4.4.10, 4.4.11
1523 # HTML 4.01 section 10.3
1524 'dl' => $common,
1525 'dt' => $common,
1526 'dd' => $common,
1527
1528 # HTML 5 section 4.4.12, 4.4.13 (was section 4.5)
1529 'figure' => $common,
1530 'figcaption' => $common,
1531
1532 # HTML 5 section 4.4.14
1533 # 'main' => $common,
1534
1535 # HTML 5 section 4.4.15
1536 # 'search'
1537
1538 # HTML 5 section 4.4.16
1539 # HTML 4.01 section 7.5.4
1540 'div' => $block,
1541
1542 # HTML 5 section 4.5 Text-level semantics
1543 # https://html.spec.whatwg.org/multipage/text-level-semantics.html
1544
1545 # HTML 5 section 4.5.1
1546 # HTML 4.01 section 12.2
1547 # NOTE: <a> is not allowed directly, but this list of allowed
1548 # attributes is used from the Parser object
1549 # See: HTML 5 section 4.6 Links
1550 # https://html.spec.whatwg.org/multipage/links.html
1551 'a' => $merge( $common, [ 'href', 'rel', 'rev' ] ), # rel/rev esp. for RDFa
1552
1553 # HTML 5 section 4.5.2, 4.5.3
1554 # HTML 4.01 section 9.2.1
1555 'em' => $common,
1556 'strong' => $common,
1557
1558 # HTML 5 section 4.5.4
1559 # HTML 4.01 section 15.2.1
1560 'small' => $common,
1561
1562 # HTML 5 section 4.5.5
1563 # HTML 4.01 section 15.2.1
1564 's' => $common,
1565
1566 # HTML 5 section 4.5.6
1567 # HTML 4.01 section 9.2.1
1568 'cite' => $common,
1569
1570 # HTML 5 section 4.5.7
1571 # HTML 4.01 section 9.2.2
1572 'q' => $merge( $common, [ 'cite' ] ),
1573
1574 # HTML 5 section 4.5.8, 4.5.9
1575 # HTML 4.01 section 9.2.1
1576 'dfn' => $common,
1577 'abbr' => $common,
1578
1579 # HTML 5 section 4.5.10, 4.5.11, 4.5.12
1580 # HTML Ruby annotation text module, simple ruby only.
1581 # https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-ruby-element
1582 'ruby' => $common,
1583 'rt' => $common, # $merge( $common, [ 'rbspan' ] ),
1584 'rp' => $common,
1585
1586 # HTML 5 section 4.5.13, 4.5.14
1587 'data' => $merge( $common, [ 'value' ] ),
1588 'time' => $merge( $common, [ 'datetime' ] ),
1589
1590 # HTML 5 section 4.5.15, 4.5.16, 4.5.17, 4.5.18
1591 # HTML 4.01 section 9.2.1
1592 'code' => $common,
1593 'var' => $common,
1594 'samp' => $common,
1595 'kbd' => $common,
1596
1597 # HTML 5 section 4.5.19
1598 # HTML 4.01 section 9.2.3
1599 'sub' => $common,
1600 'sup' => $common,
1601
1602 # HTML 5 section 4.5.20, 4.5.21, 4.5.22, 4.5.23
1603 # HTML 4.01 section 15.2.1
1604 'i' => $common,
1605 'b' => $common,
1606 'u' => $common,
1607 'mark' => $common,
1608
1609 # HTML 5 section 4.5.24 (was section 4.6)
1610 'bdi' => $common,
1611
1612 # HTML 5 section 4.5.25
1613 # HTML 4.01 section 8.2.4
1614 'bdo' => $common,
1615
1616 # HTML 5 section 4.5.26
1617 # HTML 4.01 section 7.5.4
1618 'span' => $common,
1619
1620 # HTML 5 section 4.5.27
1621 # HTML 4.01 section 9.3.2
1622 'br' => $merge( $common, [ 'clear' ] ),
1623
1624 # HTML 5 section 4.5.28
1625 'wbr' => $common,
1626
1627 # HTML 5 section 4.7 Edits
1628 # https://html.spec.whatwg.org/multipage/edits.html
1629
1630 # HTML 5 section 4.7.1, 4.7.2
1631 # HTML 4.01 section 9.4
1632 'ins' => $merge( $common, [ 'cite', 'datetime' ] ),
1633 'del' => $merge( $common, [ 'cite', 'datetime' ] ),
1634
1635 # HTML 5 section 4.8 Embedded content
1636 # https://html.spec.whatwg.org/multipage/embedded-content.html
1637
1638 # HTML 5 section 4.8.1
1639 # 'picture'
1640
1641 # HTML 5 section 4.8.2, 4.8.3, 4.8.8, 4.8.9, 4.8.10
1642 # HTML 4.01 section 13.2
1643 # Not usually allowed, but may be used for extension-style hooks
1644 # such as <math> when it is rasterized
1645 'source' => $merge( $common, [ 'type', 'src' ] ),
1646 'img' => $merge( $common, [ 'alt', 'src', 'width', 'height', 'srcset' ] ),
1647 # Attributes for A/V tags added in T163583 / T133673
1648 'video' => $merge( $common, [ 'poster', 'controls', 'preload', 'width', 'height' ] ),
1649 'audio' => $merge( $common, [ 'controls', 'preload', 'width', 'height' ] ),
1650 'track' => $merge( $common, [ 'type', 'src', 'srclang', 'kind', 'label' ] ),
1651
1652 # HTML 5 section 4.8.12, 4.8.13
1653 # 'map'
1654 # 'area'
1655
1656 # HTML 5 section 4.8.15
1657 # MathML root element, where used for extensions
1658 # 'title' may not be 100% valid here; it's XHTML
1659 # https://www.w3.org/TR/REC-MathML/
1660 'math' => $merge( [], [ 'class', 'style', 'id', 'title' ] ),
1661
1662 # HTML 5 section 4.8.16
1663 # 'svg'
1664
1665 # HTML 5 section 4.9 Tabular data
1666 # https://html.spec.whatwg.org/multipage/tables.html
1667
1668 # HTML 5 section 4.9.1
1669 # HTML 4.01 section 11.2.1
1670 'table' => $merge(
1671 $common,
1672 [
1673 'summary', 'width', 'border', 'frame',
1674 'rules', 'cellspacing', 'cellpadding',
1675 'align', 'bgcolor',
1676 ]
1677 ),
1678
1679 # HTML 5 section 4.9.2
1680 # HTML 4.01 section 11.2.2
1681 'caption' => $block,
1682
1683 # HTML 5 section 4.9.3, 4.9.4
1684 # HTML 4.01 section 11.2.4
1685 'colgroup' => $merge( $common, [ 'span' ] ),
1686 'col' => $merge( $common, [ 'span' ] ),
1687
1688 # HTML 5 section 4.9.5, 4.9.6, 4.9.7
1689 # HTML 4.01 section 11.2.3
1690 'tbody' => $common,
1691 'thead' => $common,
1692 'tfoot' => $common,
1693
1694 # HTML 5 section 4.9.8
1695 # HTML 4.01 section 11.2.5
1696 'tr' => $merge( $common, [ 'bgcolor' ], $tablealign ),
1697
1698 # HTML 5 section 4.9.9, 4.9.10
1699 # HTML 4.01 section 11.2.6
1700 'td' => $merge( $common, $tablecell, $tablealign ),
1701 'th' => $merge( $common, $tablecell, $tablealign ),
1702
1703 # HTML 5 section 4.10 Forms
1704 # https://html.spec.whatwg.org/multipage/forms.html
1705 # https://html.spec.whatwg.org/multipage/input.html
1706 # https://html.spec.whatwg.org/multipage/form-elements.html
1707 # https://html.spec.whatwg.org/multipage/form-control-infrastructure.html
1708
1709 # HTML 5 section 4.10.3, 4.10.4
1710 # 'form'
1711 # 'label'
1712
1713 # HTML 5 section 4.10.5
1714 # 'input'
1715
1716 # HTML 5 section 4.10.6, 4.10.7, 4.10.8, 4.10.9, 4.10.10, 4.10.11, 4.10.12
1717 # 'button'
1718 # 'select'
1719 # 'datalist'
1720 # 'optgroup'
1721 # 'option'
1722 # 'textarea'
1723 # 'output'
1724
1725 # HTML 5 section 4.10.13, 4.10.14
1726 # 'progress' => $merge( $common, [ 'value', 'max' ] ),
1727 # 'meter' => $merge( $common, [ 'value', 'min', 'max', 'low', 'high', 'optimum' ] ),
1728
1729 # HTML 5 section 4.10.15, 4.10.14
1730 # 'fieldset'
1731 # 'legend'
1732
1733 # HTML 5 section 4.11 Interactive elements
1734 # https://html.spec.whatwg.org/multipage/interactive-elements.html
1735 # 4.11.1, 4.11.2
1736 # 'details' => $merge( $common, [ 'name', 'open' ] ),
1737 # 'summary' => $common,
1738
1739 # HTML 5 section 16 Obsolete features
1740 # https://html.spec.whatwg.org/multipage/obsolete.html#rb
1741
1742 # HTML 5 section 16.2 Non-conforming features
1743 # Elements that are entirely obsolete, and must not be used by authors
1744
1745 # HTML 4.01 section 9.2.1
1746 # Use 'abbr' instead.
1747 # 'acronym'
1748
1749 # HTML Ruby annotation text module, simple ruby only.
1750 # https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-ruby-element
1751 # Providing the ruby base directly inside the ruby element or using nested ruby elements
1752 # is sufficient.
1753 # 'rbc'
1754 'rb' => $common,
1755 'rtc' => $common,
1756
1757 # HTML 4.01 section 15.2.1
1758 # Use del instead if the element is marking an edit, otherwise use s instead.
1759 'strike' => $common,
1760
1761 # HTML 4.01 section 15.2.2
1762 # basefont
1763
1764 # HTML 4.01 section 15.2.1
1765 'big' => $common,
1766
1767 # HTML 4.01 section 7.5.4
1768 'center' => $common, # deprecated
1769
1770 # HTML 4.01 section 15.2.2
1771 'font' => $merge( $common, [ 'size', 'color', 'face' ] ),
1772
1773 # HTML 4.01 section 15.2.1
1774 'tt' => $common,
1775 ];
1776
1777 return $allowed;
1778 }
1779
1791 public static function stripAllTags( string $html ): string {
1792 // Use RemexHtml to tokenize $html and extract the text
1793 $handler = new RemexStripTagHandler;
1794 $tokenizer = new RemexTokenizer( $handler, $html, [
1795 'ignoreErrors' => true,
1796 // don't ignore char refs, we want them to be decoded
1797 'ignoreNulls' => true,
1798 'skipPreprocess' => true,
1799 // We ignore all attributes, don't bother to parse them
1800 'lazyAttributes' => true,
1801 ] );
1802 $tokenizer->execute();
1803 return self::normalizeWhitespace( $handler->getResult() );
1804 }
1805
1816 public static function hackDocType(): string {
1817 $out = "<!DOCTYPE html [\n";
1818 foreach ( HTMLData::NAMED_ENTITY_TRANSLATION as $entity => $translation ) {
1819 if ( substr( $entity, -1 ) !== ';' ) {
1820 // Some HTML entities omit the trailing semicolon;
1821 // wikitext does not permit these.
1822 continue;
1823 }
1824 $name = substr( $entity, 0, -1 );
1825 $expansion = self::normalizeEntity( $entity );
1826 if ( $entity === $expansion ) {
1827 // Skip &lt; &gt; etc
1828 continue;
1829 }
1830 $out .= "<!ENTITY $name \"$expansion\">";
1831 }
1832 $out .= "]>\n";
1833 return $out;
1834 }
1835
1836 public static function cleanUrl( string $url ): string {
1837 # Normalize any HTML entities in input. They will be
1838 # re-escaped by makeExternalLink().
1839 $url = self::decodeCharReferences( $url );
1840
1841 # Escape any control characters introduced by the above step
1842 $url = preg_replace_callback( '/[\][<>"\\x00-\\x20\\x7F\|]+/',
1843 static fn ( $m ) => urlencode( $m[0] ), $url );
1844
1845 # Validate hostname portion
1846 $matches = [];
1847 if ( preg_match( '!^([^:]+:)(//[^/]+)?(.*)$!iD', $url, $matches ) ) {
1848 [ /* $whole */, $protocol, $host, $rest ] = $matches;
1849
1850 // Characters that will be ignored in IDNs.
1851 // https://datatracker.ietf.org/doc/html/rfc8264#section-9.13
1852 // https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
1853 // Strip them before further processing so deny lists and such work.
1854 $strip = "/
1855 \\s| # general whitespace
1856 \u{00AD}| # SOFT HYPHEN
1857 \u{034F}| # COMBINING GRAPHEME JOINER
1858 \u{061C}| # ARABIC LETTER MARK
1859 [\u{115F}-\u{1160}]| # HANGUL CHOSEONG FILLER..
1860 # HANGUL JUNGSEONG FILLER
1861 [\u{17B4}-\u{17B5}]| # KHMER VOWEL INHERENT AQ..
1862 # KHMER VOWEL INHERENT AA
1863 [\u{180B}-\u{180D}]| # MONGOLIAN FREE VARIATION SELECTOR ONE..
1864 # MONGOLIAN FREE VARIATION SELECTOR THREE
1865 \u{180E}| # MONGOLIAN VOWEL SEPARATOR
1866 [\u{200B}-\u{200F}]| # ZERO WIDTH SPACE..
1867 # RIGHT-TO-LEFT MARK
1868 [\u{202A}-\u{202E}]| # LEFT-TO-RIGHT EMBEDDING..
1869 # RIGHT-TO-LEFT OVERRIDE
1870 [\u{2060}-\u{2064}]| # WORD JOINER..
1871 # INVISIBLE PLUS
1872 \u{2065}| # <reserved-2065>
1873 [\u{2066}-\u{206F}]| # LEFT-TO-RIGHT ISOLATE..
1874 # NOMINAL DIGIT SHAPES
1875 \u{3164}| # HANGUL FILLER
1876 [\u{FE00}-\u{FE0F}]| # VARIATION SELECTOR-1..
1877 # VARIATION SELECTOR-16
1878 \u{FEFF}| # ZERO WIDTH NO-BREAK SPACE
1879 \u{FFA0}| # HALFWIDTH HANGUL FILLER
1880 [\u{FFF0}-\u{FFF8}]| # <reserved-FFF0>..
1881 # <reserved-FFF8>
1882 [\u{1BCA0}-\u{1BCA3}]| # SHORTHAND FORMAT LETTER OVERLAP..
1883 # SHORTHAND FORMAT UP STEP
1884 [\u{1D173}-\u{1D17A}]| # MUSICAL SYMBOL BEGIN BEAM..
1885 # MUSICAL SYMBOL END PHRASE
1886 \u{E0000}| # <reserved-E0000>
1887 \u{E0001}| # LANGUAGE TAG
1888 [\u{E0002}-\u{E001F}]| # <reserved-E0002>..
1889 # <reserved-E001F>
1890 [\u{E0020}-\u{E007F}]| # TAG SPACE..
1891 # CANCEL TAG
1892 [\u{E0080}-\u{E00FF}]| # <reserved-E0080>..
1893 # <reserved-E00FF>
1894 [\u{E0100}-\u{E01EF}]| # VARIATION SELECTOR-17..
1895 # VARIATION SELECTOR-256
1896 [\u{E01F0}-\u{E0FFF}]| # <reserved-E01F0>..
1897 # <reserved-E0FFF>
1898 /xuD";
1899
1900 $host = preg_replace( $strip, '', $host );
1901
1902 // IPv6 host names are bracketed with []. Url-decode these.
1903 if ( str_starts_with( $host, "//%5B" ) &&
1904 preg_match( '!^//%5B([0-9A-Fa-f:.]+)%5D((:\d+)?)$!', $host, $matches )
1905 ) {
1906 $host = '//[' . $matches[1] . ']' . $matches[2];
1907 }
1908
1909 // @todo FIXME: Validate hostnames here
1910
1911 return $protocol . $host . $rest;
1912 } else {
1913 return $url;
1914 }
1915 }
1916
1945 public static function validateEmail( string $addr ): bool {
1946 $result = null;
1947 // TODO This method should be non-static, and have a HookRunner injected
1948 $hookRunner = new HookRunner( MediaWikiServices::getInstance()->getHookContainer() );
1949 if ( !$hookRunner->onIsValidEmailAddr( $addr, $result ) ) {
1950 return $result;
1951 }
1952
1953 // Please note strings below are enclosed in brackets [], this make the
1954 // hyphen "-" a range indicator. Hence it is double backslashed below.
1955 // See T28948
1956 $rfc5322_atext = "a-z0-9!#$%&'*+\\-\/=?^_`{|}~";
1957 $rfc1034_ldh_str = "a-z0-9\\-";
1958
1959 $html5_email_regexp = "/
1960 ^ # start of string
1961 [$rfc5322_atext\\.]+ # user part which is liberal :p
1962 @ # 'apostrophe'
1963 [$rfc1034_ldh_str]+ # First domain part
1964 (\\.[$rfc1034_ldh_str]+)* # Following part prefixed with a dot
1965 $ # End of string
1966 /ix"; // case Insensitive, eXtended
1967
1968 return (bool)preg_match( $html5_email_regexp, $addr );
1969 }
1970}
1971
1973class_alias( Sanitizer::class, 'Sanitizer' );
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:69
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Service locator for MediaWiki core services.
Helper class for Sanitizer::removeSomeTags().
Helper class for Sanitizer::stripAllTags().
HTML sanitizer for MediaWiki.
Definition Sanitizer.php:32
static validateTagAttributes(array $attribs, string $element)
Take an array of attribute names and values and normalize or discard illegal values for the given ele...
static stripAllTags(string $html)
Take a fragment of (potentially invalid) HTML and return a version with any tags removed,...
const ID_FALLBACK
Tells escapeUrlForHtml() to encode the ID using the fallback encoding, or return false if no fallback...
Definition Sanitizer.php:76
static normalizeCss(string $value)
Normalize CSS into a format we can easily search for hostile input.
static validateAttributes(array $attribs, array $allowed)
Take an array of attribute names and values and normalize or discard illegal values.
static normalizeCharReferences(string $text)
Ensure that any entities and character references are legal for XML and XHTML specifically.
static mergeAttributes(array $a, array $b)
Merge two sets of HTML attributes.
static checkCss( $value)
Pick apart some CSS and check it for forbidden or unsafe structures.
static removeHTMLcomments(string $text)
Remove '', and everything between.
static getRecognizedTagData(array $extratags=[], array $removetags=[])
Return the various lists of recognized tags.
const ID_PRIMARY
Tells escapeUrlForHtml() to encode the ID using the wiki's primary encoding.
Definition Sanitizer.php:68
static escapeCombiningChar(string $html)
static hackDocType()
Hack up a private DOCTYPE with HTML's standard entity declarations.
static decodeCharReferencesAndNormalize(string $text)
Decode any character references, numeric or named entities, in the next and normalize the resulting s...
static cleanUrl(string $url)
static internalRemoveHtmlTags(string $text, ?callable $processCallback=null, $args=[], array $extratags=[], array $removetags=[])
Cleans up HTML, removes dangerous tags and attributes, and removes HTML comments; BEWARE there may be...
static fixTagAttributes(string $text, string $element, bool $sorted=false)
Take a tag soup fragment listing an HTML element's attributes and normalize it to well-formed XML,...
static normalizeSectionNameWhitespace(string $section)
Normalizes whitespace in a section name, such as might be returned by Parser::stripSectionName(),...
static armorFrenchSpaces(string $text, string $space='&#160;')
Armor French spaces with a replacement character.
static validateEmail(string $addr)
Does a string look like an e-mail address?
static isReservedDataAttribute(string $attr)
Given an attribute name, checks whether it is a reserved data attribute (such as data-mw-foo) which i...
static encodeAttribute(string $text)
Encode an attribute value for HTML output.
static removeSomeTags(string $text, array $options=[])
Cleans up HTML, removes dangerous tags and attributes, and removes HTML comments; the result will alw...
static decodeCharReferences(string $text)
Decode any character references, numeric or named entities, in the text and return a UTF-8 string.
static escapeHtmlAllowEntities(string $html)
Given HTML input, escape with htmlspecialchars but un-escape entities.
A collection of static methods to play with strings.
return[ 'config-schema-inverse'=>['default'=>['ConfigRegistry'=>['main'=> 'MediaWiki\\Config\\GlobalVarConfig::newInstance',], 'Sitename'=> 'MediaWiki', 'Server'=> false, 'CanonicalServer'=> false, 'ServerName'=> false, 'AssumeProxiesUseDefaultProtocolPorts'=> true, 'HttpsPort'=> 443, 'ForceHTTPS'=> false, 'ScriptPath'=> '/wiki', 'UsePathInfo'=> null, 'Script'=> false, 'LoadScript'=> false, 'RestPath'=> false, 'StylePath'=> false, 'LocalStylePath'=> false, 'ExtensionAssetsPath'=> false, 'ExtensionDirectory'=> null, 'StyleDirectory'=> null, 'ArticlePath'=> false, 'UploadPath'=> false, 'ImgAuthPath'=> false, 'ThumbPath'=> false, 'UploadDirectory'=> false, 'FileCacheDirectory'=> false, 'Logo'=> false, 'Logos'=> false, 'Favicon'=> '/favicon.ico', 'AppleTouchIcon'=> false, 'ReferrerPolicy'=> false, 'TmpDirectory'=> false, 'UploadBaseUrl'=> '', 'UploadStashScalerBaseUrl'=> false, 'ActionPaths'=>[], 'MainPageIsDomainRoot'=> false, 'EnableUploads'=> false, 'UploadStashMaxAge'=> 21600, 'EnableAsyncUploads'=> false, 'EnableAsyncUploadsByURL'=> false, 'UploadMaintenance'=> false, 'IllegalFileChars'=> ':\\/\\\\', 'DeletedDirectory'=> false, 'ImgAuthDetails'=> false, 'ImgAuthUrlPathMap'=>[], 'LocalFileRepo'=>['class'=> 'MediaWiki\\FileRepo\\LocalRepo', 'name'=> 'local', 'directory'=> null, 'scriptDirUrl'=> null, 'favicon'=> null, 'url'=> null, 'hashLevels'=> null, 'thumbScriptUrl'=> null, 'transformVia404'=> null, 'deletedDir'=> null, 'deletedHashLevels'=> null, 'updateCompatibleMetadata'=> null, 'reserializeMetadata'=> null,], 'ForeignFileRepos'=>[], 'UseInstantCommons'=> false, 'UseSharedUploads'=> false, 'SharedUploadDirectory'=> null, 'SharedUploadPath'=> null, 'HashedSharedUploadDirectory'=> true, 'RepositoryBaseUrl'=> 'https:'FetchCommonsDescriptions'=> false, 'SharedUploadDBname'=> false, 'SharedUploadDBprefix'=> '', 'CacheSharedUploads'=> true, 'ForeignUploadTargets'=>['local',], 'UploadDialog'=>['fields'=>['description'=> true, 'date'=> false, 'categories'=> false,], 'licensemessages'=>['local'=> 'generic-local', 'foreign'=> 'generic-foreign',], 'comment'=>['local'=> '', 'foreign'=> '',], 'format'=>['filepage'=> ' $DESCRIPTION', 'description'=> ' $TEXT', 'ownwork'=> '', 'license'=> '', 'uncategorized'=> '',],], 'FileBackends'=>[], 'LockManagers'=>[], 'ShowEXIF'=> null, 'UpdateCompatibleMetadata'=> false, 'AllowCopyUploads'=> false, 'CopyUploadsDomains'=>[], 'CopyUploadsFromSpecialUpload'=> false, 'CopyUploadProxy'=> false, 'CopyUploadTimeout'=> false, 'CopyUploadAllowOnWikiDomainConfig'=> false, 'MaxUploadSize'=> 104857600, 'MinUploadChunkSize'=> 1024, 'UploadNavigationUrl'=> false, 'UploadMissingFileUrl'=> false, 'ThumbnailScriptPath'=> false, 'SharedThumbnailScriptPath'=> false, 'HashedUploadDirectory'=> true, 'CSPUploadEntryPoint'=> true, 'FileExtensions'=>['png', 'gif', 'jpg', 'jpeg', 'webp',], 'ProhibitedFileExtensions'=>['html', 'htm', 'js', 'jsb', 'mhtml', 'mht', 'xhtml', 'xht', 'php', 'phtml', 'php3', 'php4', 'php5', 'phps', 'phar', 'shtml', 'jhtml', 'pl', 'py', 'cgi', 'exe', 'scr', 'dll', 'msi', 'vbs', 'bat', 'com', 'pif', 'cmd', 'vxd', 'cpl', 'xml',], 'MimeTypeExclusions'=>['text/html', 'application/javascript', 'text/javascript', 'text/x-javascript', 'application/x-shellscript', 'application/x-php', 'text/x-php', 'text/x-python', 'text/x-perl', 'text/x-bash', 'text/x-sh', 'text/x-csh', 'text/scriptlet', 'application/x-msdownload', 'application/x-msmetafile', 'application/java', 'application/xml', 'text/xml',], 'CheckFileExtensions'=> true, 'StrictFileExtensions'=> true, 'DisableUploadScriptChecks'=> false, 'UploadSizeWarning'=> false, 'TrustedMediaFormats'=>['BITMAP', 'AUDIO', 'VIDEO', 'image/svg+xml', 'application/pdf',], 'MediaHandlers'=>[], 'NativeImageLazyLoading'=> false, 'ParserTestMediaHandlers'=>['image/jpeg'=> 'MockBitmapHandler', 'image/png'=> 'MockBitmapHandler', 'image/gif'=> 'MockBitmapHandler', 'image/tiff'=> 'MockBitmapHandler', 'image/webp'=> 'MockBitmapHandler', 'image/x-ms-bmp'=> 'MockBitmapHandler', 'image/x-bmp'=> 'MockBitmapHandler', 'image/x-xcf'=> 'MockBitmapHandler', 'image/svg+xml'=> 'MockSvgHandler', 'image/vnd.djvu'=> 'MockDjVuHandler',], 'UseImageResize'=> true, 'UseImageMagick'=> false, 'ImageMagickConvertCommand'=> '/usr/bin/convert', 'MaxInterlacingAreas'=>[], 'SharpenParameter'=> '0x0.4', 'SharpenReductionThreshold'=> 0.85, 'ImageMagickTempDir'=> false, 'CustomConvertCommand'=> false, 'JpegTran'=> '/usr/bin/jpegtran', 'JpegPixelFormat'=> 'yuv420', 'JpegQuality'=> 80, 'Exiv2Command'=> '/usr/bin/exiv2', 'Exiftool'=> '/usr/bin/exiftool', 'SVGConverters'=>['ImageMagick'=> ' $path/convert -background "#ffffff00" -thumbnail $widthx$height\\! $input PNG:$output', 'inkscape'=> ' $path/inkscape -w $width -o $output $input', 'batik'=> 'java -Djava.awt.headless=true -jar $path/batik-rasterizer.jar -w $width -d $output $input', 'rsvg'=> ' $path/rsvg-convert -w $width -h $height -o $output $input', 'ImagickExt'=>['SvgHandler::rasterizeImagickExt',],], 'SVGConverter'=> 'ImageMagick', 'SVGConverterPath'=> '', 'SVGMaxSize'=> 5120, 'SVGMetadataCutoff'=> 5242880, 'SVGNativeRendering'=> true, 'SVGNativeRenderingSizeLimit'=> 51200, 'MediaInTargetLanguage'=> true, 'MaxImageArea'=> 12500000, 'MaxAnimatedGifArea'=> 12500000, 'TiffThumbnailType'=>[], 'ThumbnailEpoch'=> '20030516000000', 'AttemptFailureEpoch'=> 1, 'IgnoreImageErrors'=> false, 'GenerateThumbnailOnParse'=> true, 'ShowArchiveThumbnails'=> true, 'EnableAutoRotation'=> null, 'Antivirus'=> null, 'AntivirusSetup'=>['clamav'=>['command'=> 'clamscan --no-summary ', 'codemap'=>[0=> 0, 1=> 1, 52=> -1, ' *'=> false,], 'messagepattern'=> '/.*?:(.*)/sim',],], 'AntivirusRequired'=> true, 'VerifyMimeType'=> true, 'MimeTypeFile'=> 'internal', 'MimeInfoFile'=> 'internal', 'MimeDetectorCommand'=> null, 'TrivialMimeDetection'=> false, 'XMLMimeTypes'=>['http:'svg'=> 'image/svg+xml', 'http:'http:'html'=> 'text/html',], 'ImageLimits'=>[[320, 240,], [640, 480,], [800, 600,], [1024, 768,], [1280, 1024,], [2560, 2048,],], 'ThumbLimits'=>[120, 150, 180, 200, 220, 250, 300, 400,], 'ThumbnailNamespaces'=>[6,], 'ThumbnailSteps'=> null, 'ThumbnailStepsRatio'=> null, 'ThumbnailBuckets'=> null, 'ThumbnailMinimumBucketDistance'=> 50, 'UploadThumbnailRenderMap'=>[], 'UploadThumbnailRenderMethod'=> 'jobqueue', 'UploadThumbnailRenderHttpCustomHost'=> false, 'UploadThumbnailRenderHttpCustomDomain'=> false, 'UseTinyRGBForJPGThumbnails'=> false, 'GalleryOptions'=>[], 'ThumbUpright'=> 0.75, 'DirectoryMode'=> 511, 'ResponsiveImages'=> true, 'ImagePreconnect'=> false, 'TrackMediaRequestProvenance'=> false, 'DjvuUseBoxedCommand'=> false, 'DjvuDump'=> null, 'DjvuRenderer'=> null, 'DjvuTxt'=> null, 'DjvuPostProcessor'=> 'pnmtojpeg', 'DjvuOutputExtension'=> 'jpg', 'EmergencyContact'=> false, 'PasswordSender'=> false, 'NoReplyAddress'=> false, 'EnableEmail'=> true, 'EnableUserEmail'=> true, 'UserEmailUseReplyTo'=> true, 'PasswordReminderResendTime'=> 24, 'NewPasswordExpiry'=> 604800, 'UserEmailConfirmationTokenExpiry'=> 604800, 'UserEmailConfirmationUseHTML'=> false, 'PasswordExpirationDays'=> false, 'PasswordExpireGrace'=> 604800, 'SMTP'=> false, 'AdditionalMailParams'=> null, 'AllowHTMLEmail'=> false, 'EnotifFromEditor'=> false, 'EmailAuthentication'=> true, 'EnotifWatchlist'=> false, 'EnotifUserTalk'=> false, 'EnotifRevealEditorAddress'=> false, 'EnotifMinorEdits'=> true, 'EnotifUseRealName'=> false, 'UsersNotifiedOnAllChanges'=>[], 'DBname'=> 'my_wiki', 'DBmwschema'=> null, 'DBprefix'=> '', 'DBserver'=> 'localhost', 'DBport'=> 5432, 'DBuser'=> 'wikiuser', 'DBpassword'=> '', 'DBtype'=> 'mysql', 'DBssl'=> false, 'DBcompress'=> false, 'DBStrictWarnings'=> false, 'DBadminuser'=> null, 'DBadminpassword'=> null, 'SearchType'=> null, 'SearchTypeAlternatives'=> null, 'DBTableOptions'=> 'ENGINE=InnoDB, DEFAULT CHARSET=binary', 'SQLMode'=> '', 'SQLiteDataDir'=> '', 'SharedDB'=> null, 'SharedPrefix'=> false, 'SharedTables'=>['user', 'user_properties', 'user_autocreate_serial',], 'SharedSchema'=> false, 'DBservers'=> false, 'LBFactoryConf'=>['class'=> 'Wikimedia\\Rdbms\\LBFactorySimple',], 'DataCenterUpdateStickTTL'=> 10, 'DBerrorLog'=> false, 'DBerrorLogTZ'=> false, 'LocalDatabases'=>[], 'DatabaseReplicaLagWarning'=> 10, 'DatabaseReplicaLagCritical'=> 30, 'MaxExecutionTimeForExpensiveQueries'=> 0, 'VirtualDomainsMapping'=>[], 'FileSchemaMigrationStage'=> 3, 'ExternalLinksDomainGaps'=>[], 'ContentHandlers'=>['wikitext'=>['class'=> 'MediaWiki\\Content\\WikitextContentHandler', 'services'=>['TitleFactory', 'ParserFactory', 'GlobalIdGenerator', 'LanguageNameUtils', 'LinkRenderer', 'MagicWordFactory', 'ParsoidParserFactory',],], 'javascript'=>['class'=> 'MediaWiki\\Content\\JavaScriptContentHandler', 'services'=>['MainConfig', 'ParserFactory', 'UserOptionsLookup',],], 'json'=>['class'=> 'MediaWiki\\Content\\JsonContentHandler', 'services'=>['ParsoidParserFactory', 'TitleFactory',],], 'css'=>['class'=> 'MediaWiki\\Content\\CssContentHandler', 'services'=>['MainConfig', 'ParserFactory', 'UserOptionsLookup',],], 'vue'=>['class'=> 'MediaWiki\\Content\\VueContentHandler', 'services'=>['MainConfig', 'ParserFactory',],], 'text'=> 'MediaWiki\\Content\\TextContentHandler', 'unknown'=> 'MediaWiki\\Content\\FallbackContentHandler',], 'NamespaceContentModels'=>[], 'TextModelsToParse'=>['wikitext', 'javascript', 'css',], 'CompressRevisions'=> false, 'ExternalStores'=>[], 'ExternalServers'=>[], 'DefaultExternalStore'=> false, 'RevisionCacheExpiry'=> 604800, 'PageLanguageUseDB'=> false, 'DiffEngine'=> null, 'ExternalDiffEngine'=> false, 'Wikidiff2Options'=>[], 'RequestTimeLimit'=> null, 'TransactionalTimeLimit'=> 120, 'CriticalSectionTimeLimit'=> 180.0, 'MiserMode'=> false, 'DisableQueryPages'=> false, 'QueryCacheLimit'=> 1000, 'WantedPagesThreshold'=> 1, 'AllowSlowParserFunctions'=> false, 'AllowSchemaUpdates'=> true, 'MaxArticleSize'=> 2048, 'MemoryLimit'=> '50M', 'PoolCounterConf'=> null, 'PoolCountClientConf'=>['servers'=>['127.0.0.1',], 'timeout'=> 0.1,], 'MaxUserDBWriteDuration'=> false, 'MaxJobDBWriteDuration'=> false, 'LinkHolderBatchSize'=> 1000, 'MaximumMovedPages'=> 100, 'ForceDeferredUpdatesPreSend'=> false, 'MultiShardSiteStats'=> false, 'CacheDirectory'=> false, 'MainCacheType'=> 0, 'MessageCacheType'=> -1, 'ParserCacheType'=> -1, 'SessionCacheType'=> -1, 'AnonSessionCacheType'=> false, 'LanguageConverterCacheType'=> -1, 'ObjectCaches'=>[0=>['class'=> 'Wikimedia\\ObjectCache\\EmptyBagOStuff', 'reportDupes'=> false,], 1=>['class'=> 'MediaWiki\\ObjectCache\\SqlBagOStuff', 'loggroup'=> 'SQLBagOStuff',], 'memcached-php'=>['class'=> 'Wikimedia\\ObjectCache\\MemcachedPhpBagOStuff', 'loggroup'=> 'memcached',], 'memcached-pecl'=>['class'=> 'Wikimedia\\ObjectCache\\MemcachedPeclBagOStuff', 'loggroup'=> 'memcached',], 'hash'=>['class'=> 'Wikimedia\\ObjectCache\\HashBagOStuff', 'reportDupes'=> false,], 'apc'=>['class'=> 'Wikimedia\\ObjectCache\\APCUBagOStuff', 'reportDupes'=> false,], 'apcu'=>['class'=> 'Wikimedia\\ObjectCache\\APCUBagOStuff', 'reportDupes'=> false,],], 'WANObjectCache'=>[], 'MicroStashType'=> -1, 'MainStash'=> 1, 'ParsoidCacheConfig'=>['StashType'=> null, 'StashDuration'=> 86400, 'WarmParsoidParserCache'=> false,], 'ParsoidSelectiveUpdateSampleRate'=> 0, 'ParserCacheFilterConfig'=>['pcache'=>['default'=>['minCpuTime'=> 0,],], 'parsoid-pcache'=>['default'=>['minCpuTime'=> 0,],], 'postproc-pcache'=>['default'=>['minCpuTime'=> 9223372036854775807,],], 'postproc-parsoid-pcache'=>['default'=>['minCpuTime'=> 9223372036854775807,],],], 'ChronologyProtectorSecret'=> '', 'ParserCacheExpireTime'=> 86400, 'ParserCacheAsyncExpireTime'=> 60, 'ParserCacheAsyncRefreshJobs'=> true, 'OldRevisionParserCacheExpireTime'=> 3600, 'ObjectCacheSessionExpiry'=> 3600, 'PHPSessionHandling'=> 'warn', 'SuspiciousIpExpiry'=> false, 'SessionPbkdf2Iterations'=> 10001, 'UseSessionCookieJwt'=> false, 'UseSessionCookieForBotPasswords'=> false, 'JwtSessionCookieIssuer'=> null, 'MemCachedServers'=>['127.0.0.1:11211',], 'MemCachedPersistent'=> false, 'MemCachedTimeout'=> 500000, 'UseLocalMessageCache'=> false, 'AdaptiveMessageCache'=> false, 'LocalisationCacheConf'=>['class'=> 'MediaWiki\\Language\\LocalisationCache', 'store'=> 'detect', 'storeClass'=> false, 'storeDirectory'=> false, 'storeServer'=>[], 'forceRecache'=> false, 'manualRecache'=> false,], 'CachePages'=> true, 'CacheEpoch'=> '20030516000000', 'GitInfoCacheDirectory'=> false, 'UseFileCache'=> false, 'FileCacheDepth'=> 2, 'RenderHashAppend'=> '', 'EnableSidebarCache'=> false, 'SidebarCacheExpiry'=> 86400, 'UseGzip'=> false, 'InvalidateCacheOnLocalSettingsChange'=> true, 'ExtensionInfoMTime'=> false, 'EnableRemoteBagOStuffTests'=> false, 'UseCdn'=> false, 'VaryOnXFP'=> false, 'InternalServer'=> false, 'CdnMaxAge'=> 18000, 'CdnMaxageLagged'=> 30, 'CdnMaxageStale'=> 10, 'CdnReboundPurgeDelay'=> 0, 'CdnMaxageSubstitute'=> 60, 'ForcedRawSMaxage'=> 300, 'CdnServers'=>[], 'CdnServersNoPurge'=>[], 'HTCPRouting'=>[], 'HTCPMulticastTTL'=> 1, 'UsePrivateIPs'=> false, 'CdnMatchParameterOrder'=> true, 'LanguageCode'=> 'en', 'GrammarForms'=>[], 'InterwikiMagic'=> true, 'HideInterlanguageLinks'=> false, 'ExtraInterlanguageLinkPrefixes'=>[], 'InterlanguageLinkCodeMap'=>[], 'ExtraLanguageNames'=>[], 'ExtraLanguageCodes'=>['bh'=> 'bho', 'no'=> 'nb', 'simple'=> 'en',], 'DummyLanguageCodes'=>[], 'AllUnicodeFixes'=> false, 'LegacyEncoding'=> false, 'AmericanDates'=> false, 'TranslateNumerals'=> true, 'UseDatabaseMessages'=> true, 'MaxMsgCacheEntrySize'=> 10000, 'DisableLangConversion'=> false, 'DisableTitleConversion'=> false, 'DefaultLanguageVariant'=> false, 'UsePigLatinVariant'=> false, 'DisabledVariants'=>[], 'VariantArticlePath'=> false, 'UseXssLanguage'=> false, 'LoginLanguageSelector'=> false, 'ForceUIMsgAsContentMsg'=>[], 'RawHtmlMessages'=>[], 'Localtimezone'=> null, 'LocalTZoffset'=> null, 'OverrideUcfirstCharacters'=>[], 'MimeType'=> 'text/html', 'Html5Version'=> null, 'EditSubmitButtonLabelPublish'=> false, 'XhtmlNamespaces'=>[], 'SiteNotice'=> '', 'BrowserFormatDetection'=> 'telephone=no', 'SkinMetaTags'=>[], 'DefaultSkin'=> 'vector-2022', 'FallbackSkin'=> 'fallback', 'SkipSkins'=>[], 'DisableOutputCompression'=> false, 'FragmentMode'=>['html5', 'legacy',], 'ExternalInterwikiFragmentMode'=> 'legacy', 'FooterIcons'=>['copyright'=>['copyright'=>[],], 'poweredby'=>['mediawiki'=>['src'=> null, 'url'=> 'https:'alt'=> 'Powered by MediaWiki', 'lang'=> 'en',],],], 'UseCombinedLoginLink'=> false, 'Edititis'=> false, 'Send404Code'=> true, 'ShowRollbackEditCount'=> 10, 'EnableCanonicalServerLink'=> false, 'InterwikiLogoOverride'=>[], 'ResourceModules'=>[], 'ResourceModuleSkinStyles'=>[], 'ResourceLoaderSources'=>[], 'ResourceBasePath'=> null, 'ResourceLoaderMaxage'=>[], 'ResourceLoaderDebug'=> false, 'ResourceLoaderMaxQueryLength'=> false, 'ResourceLoaderValidateJS'=> true, 'ResourceLoaderEnableJSProfiler'=> false, 'ResourceLoaderStorageEnabled'=> true, 'ResourceLoaderStorageVersion'=> 1, 'ResourceLoaderEnableSourceMapLinks'=> true, 'AllowSiteCSSOnRestrictedPages'=> false, 'VueDevelopmentMode'=> false, 'CodexDevelopmentDir'=> null, 'MetaNamespace'=> false, 'MetaNamespaceTalk'=> false, 'CanonicalNamespaceNames'=>[-2=> 'Media', -1=> 'Special', 0=> '', 1=> 'Talk', 2=> 'User', 3=> 'User_talk', 4=> 'Project', 5=> 'Project_talk', 6=> 'File', 7=> 'File_talk', 8=> 'MediaWiki', 9=> 'MediaWiki_talk', 10=> 'Template', 11=> 'Template_talk', 12=> 'Help', 13=> 'Help_talk', 14=> 'Category', 15=> 'Category_talk',], 'ExtraNamespaces'=>[], 'ExtraGenderNamespaces'=>[], 'NamespaceAliases'=>[], 'LegalTitleChars'=> ' %!"$&\'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+', 'CapitalLinks' => true, 'CapitalLinkOverrides' => [ ], 'NamespacesWithSubpages' => [ 1 => true, 2 => true, 3 => true, 4 => true, 5 => true, 7 => true, 8 => true, 9 => true, 10 => true, 11 => true, 12 => true, 13 => true, 15 => true, ], 'ContentNamespaces' => [ 0, ], 'ShortPagesNamespaceExclusions' => [ ], 'ExtraSignatureNamespaces' => [ ], 'InvalidRedirectTargets' => [ 'Filepath', 'Mypage', 'Mytalk', 'Redirect', 'Mylog', ], 'DisableHardRedirects' => false, 'FixDoubleRedirects' => false, 'LocalInterwikis' => [ ], 'InterwikiExpiry' => 10800, 'InterwikiCache' => false, 'InterwikiScopes' => 3, 'InterwikiFallbackSite' => 'wiki', 'RedirectSources' => false, 'SiteTypes' => [ 'mediawiki' => 'MediaWiki\\Site\\MediaWikiSite', ], 'MaxTocLevel' => 999, 'MaxPPNodeCount' => 1000000, 'MaxTemplateDepth' => 100, 'MaxPPExpandDepth' => 100, 'UrlProtocols' => [ 'bitcoin:', 'ftp: 'ftps: 'geo:', 'git: 'gopher: 'http: 'https: 'irc: 'ircs: 'magnet:', 'mailto:', 'matrix:', 'mms: 'news:', 'nntp: 'redis: 'sftp: 'sip:', 'sips:', 'sms:', 'ssh: 'svn: 'tel:', 'telnet: 'urn:', 'wikipedia: 'worldwind: 'xmpp:', ' ], 'CleanSignatures' => true, 'AllowExternalImages' => false, 'AllowExternalImagesFrom' => '', 'EnableImageWhitelist' => false, 'TidyConfig' => [ ], 'ParsoidSettings' => [ 'useSelser' => true, ], 'ParsoidExperimentalParserFunctionOutput' => false, 'UseLegacyMediaStyles' => false, 'RawHtml' => false, 'ExternalLinkTarget' => false, 'NoFollowLinks' => true, 'NoFollowNsExceptions' => [ ], 'NoFollowDomainExceptions' => [ 'mediawiki.org', ], 'RegisterInternalExternals' => false, 'ExternalLinksIgnoreDomains' => [ ], 'AllowDisplayTitle' => true, 'RestrictDisplayTitle' => true, 'ExpensiveParserFunctionLimit' => 100, 'PreprocessorCacheThreshold' => 1000, 'EnableScaryTranscluding' => false, 'TranscludeCacheExpiry' => 3600, 'EnableMagicLinks' => [ 'ISBN' => false, 'PMID' => false, 'RFC' => false, ], 'ParserEnableUserLanguage' => false, 'ArticleCountMethod' => 'link', 'ActiveUserDays' => 30, 'LearnerEdits' => 10, 'LearnerMemberSince' => 4, 'ExperiencedUserEdits' => 500, 'ExperiencedUserMemberSince' => 30, 'ManualRevertSearchRadius' => 15, 'RevertedTagMaxDepth' => 15, 'CentralIdLookupProviders' => [ 'local' => [ 'class' => 'MediaWiki\\User\\CentralId\\LocalIdLookup', 'services' => [ 'MainConfig', 'DBLoadBalancerFactory', 'HideUserUtils', ], ], ], 'CentralIdLookupProvider' => 'local', 'UserRegistrationProviders' => [ 'local' => [ 'class' => 'MediaWiki\\User\\Registration\\LocalUserRegistrationProvider', 'services' => [ 'ConnectionProvider', ], ], ], 'PasswordPolicy' => [ 'policies' => [ 'bureaucrat' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'sysop' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'interface-admin' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'bot' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'default' => [ 'MinimalPasswordLength' => [ 'value' => 8, 'suggestChangeOnLogin' => true, ], 'PasswordCannotBeSubstringInUsername' => [ 'value' => true, 'suggestChangeOnLogin' => true, ], 'PasswordCannotMatchDefaults' => [ 'value' => true, 'suggestChangeOnLogin' => true, ], 'MaximalPasswordLength' => [ 'value' => 4096, 'suggestChangeOnLogin' => true, ], 'PasswordNotInCommonList' => [ 'value' => true, 'suggestChangeOnLogin' => true, ], ], ], 'checks' => [ 'MinimalPasswordLength' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkMinimalPasswordLength', ], 'MinimumPasswordLengthToLogin' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkMinimumPasswordLengthToLogin', ], 'PasswordCannotBeSubstringInUsername' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkPasswordCannotBeSubstringInUsername', ], 'PasswordCannotMatchDefaults' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkPasswordCannotMatchDefaults', ], 'MaximalPasswordLength' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkMaximalPasswordLength', ], 'PasswordNotInCommonList' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkPasswordNotInCommonList', ], ], ], 'AuthManagerConfig' => null, 'AuthManagerAutoConfig' => [ 'preauth' => [ 'MediaWiki\\Auth\\ThrottlePreAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\ThrottlePreAuthenticationProvider', 'sort' => 0, ], ], 'primaryauth' => [ 'MediaWiki\\Auth\\TemporaryPasswordPrimaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\TemporaryPasswordPrimaryAuthenticationProvider', 'services' => [ 'DBLoadBalancerFactory', 'UserOptionsLookup', ], 'args' => [ [ 'authoritative' => false, ], ], 'sort' => 0, ], 'MediaWiki\\Auth\\LocalPasswordPrimaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\LocalPasswordPrimaryAuthenticationProvider', 'services' => [ 'DBLoadBalancerFactory', ], 'args' => [ [ 'authoritative' => true, ], ], 'sort' => 100, ], ], 'secondaryauth' => [ 'MediaWiki\\Auth\\CheckBlocksSecondaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\CheckBlocksSecondaryAuthenticationProvider', 'sort' => 0, ], 'MediaWiki\\Auth\\ResetPasswordSecondaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\ResetPasswordSecondaryAuthenticationProvider', 'sort' => 100, ], 'MediaWiki\\Auth\\EmailNotificationSecondaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\EmailNotificationSecondaryAuthenticationProvider', 'services' => [ 'DBLoadBalancerFactory', ], 'sort' => 200, ], ], ], 'RememberMe' => 'choose', 'ReauthenticateTime' => [ 'default' => 3600, ], 'AllowSecuritySensitiveOperationIfCannotReauthenticate' => [ 'default' => true, ], 'ChangeCredentialsBlacklist' => [ 'MediaWiki\\Auth\\TemporaryPasswordAuthenticationRequest', ], 'RemoveCredentialsBlacklist' => [ 'MediaWiki\\Auth\\PasswordAuthenticationRequest', ], 'InvalidPasswordReset' => true, 'PasswordDefault' => 'pbkdf2', 'PasswordConfig' => [ 'A' => [ 'class' => 'MediaWiki\\Password\\MWOldPassword', ], 'B' => [ 'class' => 'MediaWiki\\Password\\MWSaltedPassword', ], 'pbkdf2-legacyA' => [ 'class' => 'MediaWiki\\Password\\LayeredParameterizedPassword', 'types' => [ 'A', 'pbkdf2', ], ], 'pbkdf2-legacyB' => [ 'class' => 'MediaWiki\\Password\\LayeredParameterizedPassword', 'types' => [ 'B', 'pbkdf2', ], ], 'bcrypt' => [ 'class' => 'MediaWiki\\Password\\BcryptPassword', 'cost' => 9, ], 'pbkdf2' => [ 'class' => 'MediaWiki\\Password\\Pbkdf2PasswordUsingOpenSSL', 'algo' => 'sha512', 'cost' => '30000', 'length' => '64', ], 'argon2' => [ 'class' => 'MediaWiki\\Password\\Argon2Password', 'algo' => 'auto', ], ], 'PasswordResetRoutes' => [ 'username' => true, 'email' => true, ], 'MaxSigChars' => 255, 'SignatureValidation' => 'warning', 'SignatureAllowedLintErrors' => [ 'obsolete-tag', ], 'MaxNameChars' => 255, 'ReservedUsernames' => [ 'MediaWiki default', 'Conversion script', 'Maintenance script', 'Template namespace initialisation script', 'ScriptImporter', 'Delete page script', 'Move page script', 'Command line script', 'Unknown user', 'msg:double-redirect-fixer', 'msg:usermessage-editor', 'msg:proxyblocker', 'msg:sorbs', 'msg:spambot_username', 'msg:autochange-username', ], 'DefaultUserOptions' => [ 'ccmeonemails' => 0, 'date' => 'default', 'diffonly' => 0, 'diff-type' => 'table', 'disablemail' => 0, 'editfont' => 'monospace', 'editondblclick' => 0, 'editrecovery' => 0, 'editsectiononrightclick' => 0, 'email-allow-new-users' => 1, 'enotifminoredits' => 0, 'enotifrevealaddr' => 0, 'enotifusertalkpages' => 1, 'enotifwatchlistpages' => 1, 'extendwatchlist' => 1, 'fancysig' => 0, 'forceeditsummary' => 0, 'forcesafemode' => 0, 'gender' => 'unknown', 'hidecategorization' => 1, 'hideminor' => 0, 'hidepatrolled' => 0, 'imagesize' => 2, 'minordefault' => 0, 'newpageshidepatrolled' => 0, 'nickname' => '', 'norollbackdiff' => 0, 'prefershttps' => 1, 'previewonfirst' => 0, 'previewontop' => 1, 'pst-cssjs' => 1, 'rcdays' => 7, 'rcenhancedfilters-disable' => 0, 'rclimit' => 50, 'requireemail' => 0, 'search-match-redirect' => true, 'search-special-page' => 'Search', 'search-thumbnail-extra-namespaces' => true, 'searchlimit' => 20, 'showhiddencats' => 0, 'shownumberswatching' => 1, 'showrollbackconfirmation' => 0, 'skin' => false, 'skin-responsive' => 1, 'thumbsize' => 5, 'underline' => 2, 'useeditwarning' => 1, 'uselivepreview' => 0, 'usenewrc' => 1, 'watchcreations' => 1, 'watchcreations-expiry' => 'infinite', 'watchdefault' => 1, 'watchdefault-expiry' => 'infinite', 'watchdeletion' => 0, 'watchlistdays' => 7, 'watchlisthideanons' => 0, 'watchlisthidebots' => 0, 'watchlisthidecategorization' => 1, 'watchlisthideliu' => 0, 'watchlisthideminor' => 0, 'watchlisthideown' => 0, 'watchlisthidepatrolled' => 0, 'watchlistreloadautomatically' => 0, 'watchlistunwatchlinks' => 0, 'watchmoves' => 0, 'watchrollback' => 0, 'watchuploads' => 1, 'watchrollback-expiry' => 'infinite', 'watchstar-expiry' => 'infinite', 'wlenhancedfilters-disable' => 0, 'wllimit' => 250, ], 'ConditionalUserOptions' => [ ], 'HiddenPrefs' => [ ], 'UserJsPrefLimit' => 100, 'InvalidUsernameCharacters' => '@:>=', 'UserrightsInterwikiDelimiter' => '@', 'SecureLogin' => false, 'AuthenticationTokenVersion' => null, 'SessionProviders' => [ 'MediaWiki\\Session\\CookieSessionProvider' => [ 'class' => 'MediaWiki\\Session\\CookieSessionProvider', 'args' => [ [ 'priority' => 30, ], ], 'services' => [ 'JwtCodec', 'UrlUtils', ], ], 'MediaWiki\\Session\\BotPasswordSessionProvider' => [ 'class' => 'MediaWiki\\Session\\BotPasswordSessionProvider', 'args' => [ [ 'priority' => 75, ], ], 'services' => [ 'GrantsInfo', ], ], ], 'AutoCreateTempUser' => [ 'known' => false, 'enabled' => false, 'actions' => [ 'edit', ], 'genPattern' => '~$1', 'matchPattern' => null, 'reservedPattern' => '~$1', 'serialProvider' => [ 'type' => 'local', 'useYear' => true, ], 'serialMapping' => [ 'type' => 'readable-numeric', ], 'expireAfterDays' => 90, 'notifyBeforeExpirationDays' => 10, ], 'AutoblockExemptions' => [ ], 'AutoblockExpiry' => 86400, 'BlockAllowsUTEdit' => true, 'BlockCIDRLimit' => [ 'IPv4' => 16, 'IPv6' => 19, ], 'BlockDisablesLogin' => false, 'EnableMultiBlocks' => false, 'WhitelistRead' => false, 'WhitelistReadRegexp' => false, 'EmailConfirmToEdit' => false, 'HideIdentifiableRedirects' => true, 'GroupPermissions' => [ '*' => [ 'createaccount' => true, 'read' => true, 'edit' => true, 'createpage' => true, 'createtalk' => true, 'viewmyprivateinfo' => true, 'editmyprivateinfo' => true, 'editmyoptions' => true, ], 'user' => [ 'move' => true, 'move-subpages' => true, 'move-rootuserpages' => true, 'move-categorypages' => true, 'movefile' => true, 'read' => true, 'edit' => true, 'createpage' => true, 'createtalk' => true, 'upload' => true, 'reupload' => true, 'reupload-shared' => true, 'minoredit' => true, 'editmyusercss' => true, 'editmyuserjson' => true, 'editmyuserjs' => true, 'editmyuserjsredirect' => true, 'sendemail' => true, 'applychangetags' => true, 'changetags' => true, 'viewmywatchlist' => true, 'editmywatchlist' => true, ], 'autoconfirmed' => [ 'autoconfirmed' => true, 'editsemiprotected' => true, ], 'bot' => [ 'bot' => true, 'autoconfirmed' => true, 'editsemiprotected' => true, 'nominornewtalk' => true, 'autopatrol' => true, 'suppressredirect' => true, 'apihighlimits' => true, ], 'sysop' => [ 'block' => true, 'createaccount' => true, 'delete' => true, 'bigdelete' => true, 'deletedhistory' => true, 'deletedtext' => true, 'undelete' => true, 'editcontentmodel' => true, 'editinterface' => true, 'editsitejson' => true, 'edituserjson' => true, 'import' => true, 'importupload' => true, 'move' => true, 'move-subpages' => true, 'move-rootuserpages' => true, 'move-categorypages' => true, 'patrol' => true, 'autopatrol' => true, 'protect' => true, 'editprotected' => true, 'rollback' => true, 'upload' => true, 'reupload' => true, 'reupload-shared' => true, 'unwatchedpages' => true, 'autoconfirmed' => true, 'editsemiprotected' => true, 'ipblock-exempt' => true, 'blockemail' => true, 'markbotedits' => true, 'apihighlimits' => true, 'browsearchive' => true, 'noratelimit' => true, 'movefile' => true, 'unblockself' => true, 'suppressredirect' => true, 'mergehistory' => true, 'managechangetags' => true, 'deletechangetags' => true, ], 'interface-admin' => [ 'editinterface' => true, 'editsitecss' => true, 'editsitejson' => true, 'editsitejs' => true, 'editusercss' => true, 'edituserjson' => true, 'edituserjs' => true, ], 'bureaucrat' => [ 'userrights' => true, 'noratelimit' => true, 'renameuser' => true, ], 'suppress' => [ 'hideuser' => true, 'suppressrevision' => true, 'viewsuppressed' => true, 'suppressionlog' => true, 'deleterevision' => true, 'deletelogentry' => true, ], ], 'PrivilegedGroups' => [ 'bureaucrat', 'interface-admin', 'suppress', 'sysop', ], 'RevokePermissions' => [ ], 'GroupInheritsPermissions' => [ ], 'ImplicitGroups' => [ '*', 'user', 'autoconfirmed', ], 'GroupsAddToSelf' => [ ], 'GroupsRemoveFromSelf' => [ ], 'RestrictedGroups' => [ ], 'UserRequirementsPrivateConditions' => [ ], 'RestrictionTypes' => [ 'create', 'edit', 'move', 'upload', ], 'RestrictionLevels' => [ '', 'autoconfirmed', 'sysop', ], 'CascadingRestrictionLevels' => [ 'sysop', ], 'SemiprotectedRestrictionLevels' => [ 'autoconfirmed', ], 'NamespaceProtection' => [ ], 'NonincludableNamespaces' => [ ], 'AutoConfirmAge' => 0, 'AutoConfirmCount' => 0, 'Autopromote' => [ 'autoconfirmed' => [ '&', [ 1, null, ], [ 2, null, ], ], ], 'AutopromoteOnce' => [ 'onEdit' => [ ], ], 'AutopromoteOnceLogInRC' => true, 'AutopromoteOnceRCExcludedGroups' => [ ], 'AddGroups' => [ ], 'RemoveGroups' => [ ], 'AvailableRights' => [ ], 'ImplicitRights' => [ ], 'DeleteRevisionsLimit' => 0, 'DeleteRevisionsBatchSize' => 1000, 'HideUserContribLimit' => 1000, 'AccountCreationThrottle' => [ [ 'count' => 0, 'seconds' => 86400, ], ], 'TempAccountCreationThrottle' => [ [ 'count' => 1, 'seconds' => 600, ], [ 'count' => 6, 'seconds' => 86400, ], ], 'TempAccountNameAcquisitionThrottle' => [ [ 'count' => 60, 'seconds' => 86400, ], ], 'SpamRegex' => [ ], 'SummarySpamRegex' => [ ], 'EnableDnsBlacklist' => false, 'DnsBlacklistUrls' => [ ], 'ProxyList' => [ ], 'ProxyWhitelist' => [ ], 'SoftBlockRanges' => [ ], 'ApplyIpBlocksToXff' => false, 'RateLimits' => [ 'edit' => [ 'ip' => [ 8, 60, ], 'newbie' => [ 8, 60, ], 'user' => [ 90, 60, ], ], 'move' => [ 'newbie' => [ 2, 120, ], 'user' => [ 8, 60, ], ], 'upload' => [ 'ip' => [ 8, 60, ], 'newbie' => [ 8, 60, ], ], 'rollback' => [ 'user' => [ 10, 60, ], 'newbie' => [ 5, 120, ], ], 'mailpassword' => [ 'ip' => [ 5, 3600, ], ], 'sendemail' => [ 'ip' => [ 5, 86400, ], 'newbie' => [ 5, 86400, ], 'user' => [ 20, 86400, ], ], 'changeemail' => [ 'ip-all' => [ 10, 3600, ], 'user' => [ 4, 86400, ], ], 'confirmemail' => [ 'ip-all' => [ 10, 3600, ], 'user' => [ 4, 86400, ], ], 'purge' => [ 'ip' => [ 30, 60, ], 'user' => [ 30, 60, ], ], 'linkpurge' => [ 'ip' => [ 30, 60, ], 'user' => [ 30, 60, ], ], 'renderfile' => [ 'ip' => [ 700, 30, ], 'user' => [ 700, 30, ], ], 'renderfile-nonstandard' => [ 'ip' => [ 70, 30, ], 'user' => [ 70, 30, ], ], 'stashedit' => [ 'ip' => [ 30, 60, ], 'newbie' => [ 30, 60, ], ], 'stashbasehtml' => [ 'ip' => [ 5, 60, ], 'newbie' => [ 5, 60, ], ], 'changetags' => [ 'ip' => [ 8, 60, ], 'newbie' => [ 8, 60, ], ], 'editcontentmodel' => [ 'newbie' => [ 2, 120, ], 'user' => [ 8, 60, ], ], ], 'RateLimitsExcludedIPs' => [ ], 'PutIPinRC' => true, 'QueryPageDefaultLimit' => 50, 'ExternalQuerySources' => [ ], 'PasswordAttemptThrottle' => [ [ 'count' => 5, 'seconds' => 300, ], [ 'count' => 150, 'seconds' => 172800, ], ], 'GrantPermissions' => [ 'basic' => [ 'autocreateaccount' => true, 'autoconfirmed' => true, 'autopatrol' => true, 'editsemiprotected' => true, 'ipblock-exempt' => true, 'nominornewtalk' => true, 'patrolmarks' => true, 'read' => true, 'unwatchedpages' => true, ], 'highvolume' => [ 'bot' => true, 'apihighlimits' => true, 'noratelimit' => true, 'markbotedits' => true, ], 'import' => [ 'import' => true, 'importupload' => true, ], 'editpage' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'pagelang' => true, ], 'editprotected' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'editprotected' => true, ], 'editmycssjs' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'editmyusercss' => true, 'editmyuserjson' => true, 'editmyuserjs' => true, ], 'editmyoptions' => [ 'editmyoptions' => true, 'editmyuserjson' => true, ], 'editinterface' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'editinterface' => true, 'edituserjson' => true, 'editsitejson' => true, ], 'editsiteconfig' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'editinterface' => true, 'edituserjson' => true, 'editsitejson' => true, 'editusercss' => true, 'edituserjs' => true, 'editsitecss' => true, 'editsitejs' => true, ], 'createeditmovepage' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createpage' => true, 'createtalk' => true, 'delete-redirect' => true, 'move' => true, 'move-rootuserpages' => true, 'move-subpages' => true, 'move-categorypages' => true, 'suppressredirect' => true, ], 'uploadfile' => [ 'upload' => true, 'reupload-own' => true, ], 'uploadeditmovefile' => [ 'upload' => true, 'reupload-own' => true, 'reupload' => true, 'reupload-shared' => true, 'upload_by_url' => true, 'movefile' => true, 'suppressredirect' => true, ], 'patrol' => [ 'patrol' => true, ], 'rollback' => [ 'rollback' => true, ], 'blockusers' => [ 'block' => true, 'blockemail' => true, ], 'viewdeleted' => [ 'browsearchive' => true, 'deletedhistory' => true, 'deletedtext' => true, ], 'viewrestrictedlogs' => [ 'suppressionlog' => true, ], 'delete' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'browsearchive' => true, 'deletedhistory' => true, 'deletedtext' => true, 'delete' => true, 'bigdelete' => true, 'deletelogentry' => true, 'deleterevision' => true, 'undelete' => true, ], 'oversight' => [ 'suppressrevision' => true, 'viewsuppressed' => true, ], 'protect' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'editprotected' => true, 'protect' => true, ], 'viewmywatchlist' => [ 'viewmywatchlist' => true, ], 'editmywatchlist' => [ 'editmywatchlist' => true, ], 'sendemail' => [ 'sendemail' => true, ], 'createaccount' => [ 'createaccount' => true, ], 'privateinfo' => [ 'viewmyprivateinfo' => true, ], 'mergehistory' => [ 'mergehistory' => true, ], ], 'GrantPermissionGroups' => [ 'basic' => 'hidden', 'editpage' => 'page-interaction', 'createeditmovepage' => 'page-interaction', 'editprotected' => 'page-interaction', 'patrol' => 'page-interaction', 'uploadfile' => 'file-interaction', 'uploadeditmovefile' => 'file-interaction', 'sendemail' => 'email', 'viewmywatchlist' => 'watchlist-interaction', 'editviewmywatchlist' => 'watchlist-interaction', 'editmycssjs' => 'customization', 'editmyoptions' => 'customization', 'editinterface' => 'administration', 'editsiteconfig' => 'administration', 'rollback' => 'administration', 'blockusers' => 'administration', 'delete' => 'administration', 'viewdeleted' => 'administration', 'viewrestrictedlogs' => 'administration', 'protect' => 'administration', 'oversight' => 'administration', 'createaccount' => 'administration', 'mergehistory' => 'administration', 'import' => 'administration', 'highvolume' => 'high-volume', 'privateinfo' => 'private-information', ], 'GrantRiskGroups' => [ 'basic' => 'low', 'editpage' => 'low', 'createeditmovepage' => 'low', 'editprotected' => 'vandalism', 'patrol' => 'low', 'uploadfile' => 'low', 'uploadeditmovefile' => 'low', 'sendemail' => 'security', 'viewmywatchlist' => 'low', 'editviewmywatchlist' => 'low', 'editmycssjs' => 'security', 'editmyoptions' => 'security', 'editinterface' => 'vandalism', 'editsiteconfig' => 'security', 'rollback' => 'low', 'blockusers' => 'vandalism', 'delete' => 'vandalism', 'viewdeleted' => 'vandalism', 'viewrestrictedlogs' => 'security', 'protect' => 'vandalism', 'oversight' => 'security', 'createaccount' => 'low', 'mergehistory' => 'vandalism', 'import' => 'security', 'highvolume' => 'low', 'privateinfo' => 'low', ], 'EnableBotPasswords' => true, 'BotPasswordsCluster' => false, 'BotPasswordsDatabase' => false, 'BotPasswordsLimit' => 100, 'SecretKey' => false, 'JwtPrivateKey' => false, 'JwtPublicKey' => false, 'AllowUserJs' => false, 'AllowUserCss' => false, 'AllowUserCssPrefs' => true, 'UseSiteJs' => true, 'UseSiteCss' => true, 'BreakFrames' => false, 'EditPageFrameOptions' => 'DENY', 'ApiFrameOptions' => 'DENY', 'CSPHeader' => false, 'CSPReportOnlyHeader' => false, 'CSPFalsePositiveUrls' => [ 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'chrome-extension' => true, ], 'AllowCrossOrigin' => false, 'RestAllowCrossOriginCookieAuth' => false, 'SessionSecret' => false, 'CookieExpiration' => 2592000, 'ExtendedLoginCookieExpiration' => 15552000, 'SessionCookieJwtExpiration' => 14400, 'CookieDomain' => '', 'CookiePath' => '/', 'CookieSecure' => 'detect', 'CookiePrefix' => false, 'CookieHttpOnly' => true, 'CookieSameSite' => null, 'CacheVaryCookies' => [ ], 'SessionName' => false, 'CookieSetOnAutoblock' => true, 'CookieSetOnIpBlock' => true, 'DebugLogFile' => '', 'DebugLogPrefix' => '', 'DebugRedirects' => false, 'DebugRawPage' => false, 'DebugComments' => false, 'DebugDumpSql' => false, 'TrxProfilerLimits' => [ 'GET' => [ 'masterConns' => 0, 'writes' => 0, 'readQueryTime' => 5, 'readQueryRows' => 10000, ], 'POST' => [ 'readQueryTime' => 5, 'writeQueryTime' => 1, 'readQueryRows' => 100000, 'maxAffected' => 1000, ], 'POST-nonwrite' => [ 'writes' => 0, 'readQueryTime' => 5, 'readQueryRows' => 10000, ], 'PostSend-GET' => [ 'readQueryTime' => 5, 'writeQueryTime' => 1, 'readQueryRows' => 10000, 'maxAffected' => 1000, 'masterConns' => 0, 'writes' => 0, ], 'PostSend-POST' => [ 'readQueryTime' => 5, 'writeQueryTime' => 1, 'readQueryRows' => 100000, 'maxAffected' => 1000, ], 'JobRunner' => [ 'readQueryTime' => 30, 'writeQueryTime' => 5, 'readQueryRows' => 100000, 'maxAffected' => 500, ], 'Maintenance' => [ 'writeQueryTime' => 5, 'maxAffected' => 1000, ], ], 'DebugLogGroups' => [ ], 'MWLoggerDefaultSpi' => [ 'class' => 'MediaWiki\\Logger\\LegacySpi', ], 'ShowDebug' => false, 'SpecialVersionShowHooks' => false, 'ShowExceptionDetails' => false, 'LogExceptionBacktrace' => true, 'PropagateErrors' => true, 'ShowHostnames' => false, 'OverrideHostname' => false, 'DevelopmentWarnings' => false, 'DeprecationReleaseLimit' => false, 'Profiler' => [ ], 'StatsdServer' => false, 'StatsdMetricPrefix' => 'MediaWiki', 'StatsTarget' => null, 'StatsFormat' => null, 'StatsPrefix' => 'mediawiki', 'OpenTelemetryConfig' => null, 'PageInfoTransclusionLimit' => 50, 'EnableJavaScriptTest' => false, 'CachePrefix' => false, 'DebugToolbar' => false, 'DisableTextSearch' => false, 'AdvancedSearchHighlighting' => false, 'SearchHighlightBoundaries' => '[\\p{Z}\\p{P}\\p{C}]', 'OpenSearchTemplates' => [ 'application/x-suggestions+json' => false, 'application/x-suggestions+xml' => false, ], 'OpenSearchDefaultLimit' => 10, 'OpenSearchDescriptionLength' => 100, 'SearchSuggestCacheExpiry' => 1200, 'DisableSearchUpdate' => false, 'NamespacesToBeSearchedDefault' => [ true, ], 'DisableInternalSearch' => false, 'SearchForwardUrl' => null, 'SitemapNamespaces' => false, 'SitemapNamespacesPriorities' => false, 'SitemapApiConfig' => [ ], 'SpecialSearchFormOptions' => [ ], 'SearchMatchRedirectPreference' => false, 'SearchRunSuggestedQuery' => true, 'Diff3' => '/usr/bin/diff3', 'Diff' => '/usr/bin/diff', 'PreviewOnOpenNamespaces' => [ 14 => true, ], 'UniversalEditButton' => true, 'UseAutomaticEditSummaries' => true, 'CommandLineDarkBg' => false, 'ReadOnly' => null, 'ReadOnlyWatchedItemStore' => false, 'ReadOnlyFile' => false, 'UpgradeKey' => false, 'GitBin' => '/usr/bin/git', 'GitRepositoryViewers' => [ 'https: 'ssh: ], 'InstallerInitialPages' => [ [ 'titlemsg' => 'mainpage', 'text' => '{{subst:int:mainpagetext}}{{subst:int:mainpagedocfooter}}', ], ], 'RCMaxAge' => 7776000, 'WatchersMaxAge' => 15552000, 'UnwatchedPageSecret' => 1, 'RCFilterByAge' => false, 'RCLinkLimits' => [ 50, 100, 250, 500, ], 'RCLinkDays' => [ 1, 3, 7, 14, 30, ], 'RCFeeds' => [ ], 'RCWatchCategoryMembership' => false, 'UseRCPatrol' => true, 'StructuredChangeFiltersLiveUpdatePollingRate' => 3, 'UseNPPatrol' => true, 'UseFilePatrol' => true, 'Feed' => true, 'FeedLimit' => 50, 'FeedCacheTimeout' => 60, 'FeedDiffCutoff' => 32768, 'OverrideSiteFeed' => [ ], 'FeedClasses' => [ 'rss' => 'MediaWiki\\Feed\\RSSFeed', 'atom' => 'MediaWiki\\Feed\\AtomFeed', ], 'AdvertisedFeedTypes' => [ 'atom', ], 'RCShowWatchingUsers' => false, 'RCShowChangedSize' => true, 'RCChangedSizeThreshold' => 500, 'ShowUpdatedMarker' => true, 'DisableAnonTalk' => false, 'UseTagFilter' => true, 'SoftwareTags' => [ 'mw-contentmodelchange' => true, 'mw-new-redirect' => true, 'mw-removed-redirect' => true, 'mw-changed-redirect-target' => true, 'mw-blank' => true, 'mw-replace' => true, 'mw-recreated' => true, 'mw-rollback' => true, 'mw-undo' => true, 'mw-manual-revert' => true, 'mw-reverted' => true, 'mw-server-side-upload' => true, 'mw-ipblock-appeal' => true, ], 'UnwatchedPageThreshold' => false, 'RecentChangesFlags' => [ 'newpage' => [ 'letter' => 'newpageletter', 'title' => 'recentchanges-label-newpage', 'legend' => 'recentchanges-legend-newpage', 'grouping' => 'any', ], 'minor' => [ 'letter' => 'minoreditletter', 'title' => 'recentchanges-label-minor', 'legend' => 'recentchanges-legend-minor', 'class' => 'minoredit', 'grouping' => 'all', ], 'bot' => [ 'letter' => 'boteditletter', 'title' => 'recentchanges-label-bot', 'legend' => 'recentchanges-legend-bot', 'class' => 'botedit', 'grouping' => 'all', ], 'unpatrolled' => [ 'letter' => 'unpatrolledletter', 'title' => 'recentchanges-label-unpatrolled', 'legend' => 'recentchanges-legend-unpatrolled', 'grouping' => 'any', ], ], 'WatchlistExpiry' => false, 'EnableWatchlistLabels' => false, 'WatchlistLabelsMaxPerUser' => 100, 'WatchlistPurgeRate' => 0.1, 'WatchlistExpiryMaxDuration' => '1 year', 'EnableChangesListQueryPartitioning' => false, 'RightsPage' => null, 'RightsUrl' => null, 'RightsText' => null, 'RightsIcon' => null, 'UseCopyrightUpload' => false, 'MaxCredits' => 0, 'ShowCreditsIfMax' => true, 'ImportSources' => [ ], 'ImportTargetNamespace' => null, 'ExportAllowHistory' => true, 'ExportMaxHistory' => 0, 'ExportAllowListContributors' => false, 'ExportMaxLinkDepth' => 0, 'ExportFromNamespaces' => false, 'ExportAllowAll' => false, 'ExportPagelistLimit' => 5000, 'XmlDumpSchemaVersion' => '0.11', 'WikiFarmSettingsDirectory' => null, 'WikiFarmSettingsExtension' => 'yaml', 'ExtensionFunctions' => [ ], 'ExtensionMessagesFiles' => [ ], 'MessagesDirs' => [ ], 'TranslationAliasesDirs' => [ ], 'ExtensionEntryPointListFiles' => [ ], 'EnableParserLimitReporting' => true, 'ValidSkinNames' => [ ], 'SpecialPages' => [ ], 'ExtensionCredits' => [ ], 'Hooks' => [ ], 'ServiceWiringFiles' => [ ], 'JobClasses' => [ 'deletePage' => 'MediaWiki\\Page\\DeletePageJob', 'refreshLinks' => 'MediaWiki\\JobQueue\\Jobs\\RefreshLinksJob', 'deleteLinks' => 'MediaWiki\\Page\\DeleteLinksJob', 'htmlCacheUpdate' => 'MediaWiki\\JobQueue\\Jobs\\HTMLCacheUpdateJob', 'sendMail' => [ 'class' => 'MediaWiki\\Mail\\EmaillingJob', 'services' => [ 'Emailer', ], ], 'enotifNotify' => [ 'class' => 'MediaWiki\\RecentChanges\\RecentChangeNotifyJob', 'services' => [ 'RecentChangeLookup', ], ], 'fixDoubleRedirect' => [ 'class' => 'MediaWiki\\JobQueue\\Jobs\\DoubleRedirectJob', 'services' => [ 'RevisionLookup', 'MagicWordFactory', 'WikiPageFactory', ], 'needsPage' => true, ], 'AssembleUploadChunks' => 'MediaWiki\\JobQueue\\Jobs\\AssembleUploadChunksJob', 'PublishStashedFile' => 'MediaWiki\\JobQueue\\Jobs\\PublishStashedFileJob', 'ThumbnailRender' => 'MediaWiki\\JobQueue\\Jobs\\ThumbnailRenderJob', 'UploadFromUrl' => 'MediaWiki\\JobQueue\\Jobs\\UploadFromUrlJob', 'recentChangesUpdate' => 'MediaWiki\\RecentChanges\\RecentChangesUpdateJob', 'refreshLinksPrioritized' => 'MediaWiki\\JobQueue\\Jobs\\RefreshLinksJob', 'refreshLinksDynamic' => 'MediaWiki\\JobQueue\\Jobs\\RefreshLinksJob', 'activityUpdateJob' => 'MediaWiki\\Watchlist\\ActivityUpdateJob', 'categoryMembershipChange' => [ 'class' => 'MediaWiki\\JobQueue\\Jobs\\CategoryMembershipChangeJob', 'services' => [ 'RecentChangeFactory', ], ], 'CategoryCountUpdateJob' => [ 'class' => 'MediaWiki\\JobQueue\\Jobs\\CategoryCountUpdateJob', 'services' => [ 'ConnectionProvider', 'NamespaceInfo', ], ], 'clearUserWatchlist' => 'MediaWiki\\Watchlist\\ClearUserWatchlistJob', 'watchlistExpiry' => 'MediaWiki\\Watchlist\\WatchlistExpiryJob', 'cdnPurge' => 'MediaWiki\\JobQueue\\Jobs\\CdnPurgeJob', 'userGroupExpiry' => 'MediaWiki\\User\\UserGroupExpiryJob', 'clearWatchlistNotifications' => 'MediaWiki\\Watchlist\\ClearWatchlistNotificationsJob', 'userOptionsUpdate' => 'MediaWiki\\User\\Options\\UserOptionsUpdateJob', 'revertedTagUpdate' => 'MediaWiki\\JobQueue\\Jobs\\RevertedTagUpdateJob', 'null' => 'MediaWiki\\JobQueue\\Jobs\\NullJob', 'userEditCountInit' => 'MediaWiki\\User\\UserEditCountInitJob', 'parsoidCachePrewarm' => [ 'class' => 'MediaWiki\\JobQueue\\Jobs\\ParsoidCachePrewarmJob', 'services' => [ 'ParserOutputAccess', 'PageStore', 'RevisionLookup', 'ParsoidSiteConfig', ], 'needsPage' => false, ], 'renameUserTable' => [ 'class' => 'MediaWiki\\RenameUser\\Job\\RenameUserTableJob', 'services' => [ 'MainConfig', 'DBLoadBalancerFactory', ], ], 'renameUserDerived' => [ 'class' => 'MediaWiki\\RenameUser\\Job\\RenameUserDerivedJob', 'services' => [ 'RenameUserFactory', 'UserFactory', ], ], 'renameUser' => [ 'class' => 'MediaWiki\\RenameUser\\Job\\RenameUserTableJob', 'services' => [ 'MainConfig', 'DBLoadBalancerFactory', ], ], ], 'JobTypesExcludedFromDefaultQueue' => [ 'AssembleUploadChunks', 'PublishStashedFile', 'UploadFromUrl', ], 'JobBackoffThrottling' => [ ], 'JobTypeConf' => [ 'default' => [ 'class' => 'MediaWiki\\JobQueue\\JobQueueDB', 'order' => 'random', 'claimTTL' => 3600, ], ], 'JobQueueIncludeInMaxLagFactor' => false, 'SpecialPageCacheUpdates' => [ 'Statistics' => [ 'MediaWiki\\Deferred\\SiteStatsUpdate', 'cacheUpdate', ], ], 'PagePropLinkInvalidations' => [ 'hiddencat' => 'categorylinks', ], 'CategoryMagicGallery' => true, 'CategoryPagingLimit' => 200, 'CategoryCollation' => 'uppercase', 'TempCategoryCollations' => [ ], 'SortedCategories' => false, 'TrackingCategories' => [ ], 'LogTypes' => [ '', 'block', 'protect', 'rights', 'delete', 'upload', 'move', 'import', 'interwiki', 'patrol', 'merge', 'suppress', 'tag', 'managetags', 'contentmodel', 'renameuser', ], 'LogRestrictions' => [ 'suppress' => 'suppressionlog', ], 'FilterLogTypes' => [ 'patrol' => true, 'tag' => true, 'newusers' => false, ], 'LogNames' => [ '' => 'all-logs-page', 'block' => 'blocklogpage', 'protect' => 'protectlogpage', 'rights' => 'rightslog', 'delete' => 'dellogpage', 'upload' => 'uploadlogpage', 'move' => 'movelogpage', 'import' => 'importlogpage', 'patrol' => 'patrol-log-page', 'merge' => 'mergelog', 'suppress' => 'suppressionlog', ], 'LogHeaders' => [ '' => 'alllogstext', 'block' => 'blocklogtext', 'delete' => 'dellogpagetext', 'import' => 'importlogpagetext', 'merge' => 'mergelogpagetext', 'move' => 'movelogpagetext', 'patrol' => 'patrol-log-header', 'protect' => 'protectlogtext', 'rights' => 'rightslogtext', 'suppress' => 'suppressionlogtext', 'upload' => 'uploadlogpagetext', ], 'LogActions' => [ ], 'LogActionsHandlers' => [ 'block/block' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'block/reblock' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'block/unblock' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'contentmodel/change' => 'MediaWiki\\Logging\\ContentModelLogFormatter', 'contentmodel/new' => 'MediaWiki\\Logging\\ContentModelLogFormatter', 'delete/delete' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/delete_redir' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/delete_redir2' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/event' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/restore' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/revision' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'import/interwiki' => 'MediaWiki\\Logging\\ImportLogFormatter', 'import/upload' => 'MediaWiki\\Logging\\ImportLogFormatter', 'interwiki/iw_add' => 'MediaWiki\\Logging\\InterwikiLogFormatter', 'interwiki/iw_delete' => 'MediaWiki\\Logging\\InterwikiLogFormatter', 'interwiki/iw_edit' => 'MediaWiki\\Logging\\InterwikiLogFormatter', 'managetags/activate' => 'MediaWiki\\Logging\\LogFormatter', 'managetags/create' => 'MediaWiki\\Logging\\LogFormatter', 'managetags/deactivate' => 'MediaWiki\\Logging\\LogFormatter', 'managetags/delete' => 'MediaWiki\\Logging\\LogFormatter', 'merge/merge' => [ 'class' => 'MediaWiki\\Logging\\MergeLogFormatter', 'services' => [ 'TitleParser', ], ], 'merge/merge-into' => [ 'class' => 'MediaWiki\\Logging\\MergeLogFormatter', 'services' => [ 'TitleParser', ], ], 'move/move' => [ 'class' => 'MediaWiki\\Logging\\MoveLogFormatter', 'services' => [ 'TitleParser', ], ], 'move/move_redir' => [ 'class' => 'MediaWiki\\Logging\\MoveLogFormatter', 'services' => [ 'TitleParser', ], ], 'patrol/patrol' => 'MediaWiki\\Logging\\PatrolLogFormatter', 'patrol/autopatrol' => 'MediaWiki\\Logging\\PatrolLogFormatter', 'protect/modify' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'protect/move_prot' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'protect/protect' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'protect/unprotect' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'renameuser/renameuser' => [ 'class' => 'MediaWiki\\Logging\\RenameuserLogFormatter', 'services' => [ 'TitleParser', ], ], 'rights/autopromote' => 'MediaWiki\\Logging\\RightsLogFormatter', 'rights/rights' => 'MediaWiki\\Logging\\RightsLogFormatter', 'suppress/block' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'suppress/delete' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'suppress/event' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'suppress/reblock' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'suppress/revision' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'tag/update' => 'MediaWiki\\Logging\\TagLogFormatter', 'upload/overwrite' => 'MediaWiki\\Logging\\UploadLogFormatter', 'upload/revert' => 'MediaWiki\\Logging\\UploadLogFormatter', 'upload/upload' => 'MediaWiki\\Logging\\UploadLogFormatter', ], 'ActionFilteredLogs' => [ 'block' => [ 'block' => [ 'block', ], 'reblock' => [ 'reblock', ], 'unblock' => [ 'unblock', ], ], 'contentmodel' => [ 'change' => [ 'change', ], 'new' => [ 'new', ], ], 'delete' => [ 'delete' => [ 'delete', ], 'delete_redir' => [ 'delete_redir', 'delete_redir2', ], 'restore' => [ 'restore', ], 'event' => [ 'event', ], 'revision' => [ 'revision', ], ], 'import' => [ 'interwiki' => [ 'interwiki', ], 'upload' => [ 'upload', ], ], 'managetags' => [ 'create' => [ 'create', ], 'delete' => [ 'delete', ], 'activate' => [ 'activate', ], 'deactivate' => [ 'deactivate', ], ], 'move' => [ 'move' => [ 'move', ], 'move_redir' => [ 'move_redir', ], ], 'newusers' => [ 'create' => [ 'create', 'newusers', ], 'create2' => [ 'create2', ], 'autocreate' => [ 'autocreate', ], 'byemail' => [ 'byemail', ], ], 'protect' => [ 'protect' => [ 'protect', ], 'modify' => [ 'modify', ], 'unprotect' => [ 'unprotect', ], 'move_prot' => [ 'move_prot', ], ], 'rights' => [ 'rights' => [ 'rights', ], 'autopromote' => [ 'autopromote', ], ], 'suppress' => [ 'event' => [ 'event', ], 'revision' => [ 'revision', ], 'delete' => [ 'delete', ], 'block' => [ 'block', ], 'reblock' => [ 'reblock', ], ], 'upload' => [ 'upload' => [ 'upload', ], 'overwrite' => [ 'overwrite', ], 'revert' => [ 'revert', ], ], ], 'NewUserLog' => true, 'PageCreationLog' => true, 'AllowSpecialInclusion' => true, 'DisableQueryPageUpdate' => false, 'CountCategorizedImagesAsUsed' => false, 'MaxRedirectLinksRetrieved' => 500, 'RangeContributionsCIDRLimit' => [ 'IPv4' => 16, 'IPv6' => 32, ], 'Actions' => [ ], 'DefaultRobotPolicy' => 'index,follow', 'NamespaceRobotPolicies' => [ ], 'ArticleRobotPolicies' => [ ], 'ExemptFromUserRobotsControl' => null, 'DebugAPI' => false, 'APIModules' => [ ], 'APIFormatModules' => [ ], 'APIMetaModules' => [ ], 'APIPropModules' => [ ], 'APIListModules' => [ ], 'APIMaxDBRows' => 5000, 'APIMaxResultSize' => 8388608, 'APIMaxUncachedDiffs' => 1, 'APIMaxLagThreshold' => 7, 'APICacheHelpTimeout' => 3600, 'APIUselessQueryPages' => [ 'MIMEsearch', 'LinkSearch', ], 'AjaxLicensePreview' => true, 'CrossSiteAJAXdomains' => [ ], 'CrossSiteAJAXdomainExceptions' => [ ], 'AllowedCorsHeaders' => [ 'Accept', 'Accept-Language', 'Content-Language', 'Content-Type', 'Accept-Encoding', 'DNT', 'Origin', 'User-Agent', 'Api-User-Agent', 'Access-Control-Max-Age', 'Authorization', ], 'RestAPIAdditionalRouteFiles' => [ ], 'RestSandboxSpecs' => [ ], 'MaxShellMemory' => 307200, 'MaxShellFileSize' => 102400, 'MaxShellTime' => 180, 'MaxShellWallClockTime' => 180, 'ShellCgroup' => false, 'PhpCli' => '/usr/bin/php', 'ShellRestrictionMethod' => 'autodetect', 'ShellboxUrls' => [ 'default' => null, ], 'ShellboxSecretKey' => null, 'ShellboxShell' => '/bin/sh', 'HTTPTimeout' => 25, 'HTTPConnectTimeout' => 5.0, 'HTTPMaxTimeout' => 0, 'HTTPMaxConnectTimeout' => 0, 'HTTPImportTimeout' => 25, 'AsyncHTTPTimeout' => 25, 'HTTPProxy' => '', 'LocalVirtualHosts' => [ ], 'LocalHTTPProxy' => false, 'AllowExternalReqID' => false, 'GenerateReqIDFormat' => 'rand24', 'JobRunRate' => 1, 'RunJobsAsync' => false, 'UpdateRowsPerJob' => 300, 'UpdateRowsPerQuery' => 100, 'RedirectOnLogin' => null, 'VirtualRestConfig' => [ 'paths' => [ ], 'modules' => [ ], 'global' => [ 'timeout' => 360, 'forwardCookies' => false, 'HTTPProxy' => null, ], ], 'EventRelayerConfig' => [ 'default' => [ 'class' => 'Wikimedia\\EventRelayer\\EventRelayerNull', ], ], 'Pingback' => false, 'OriginTrials' => [ ], 'ReportToExpiry' => 86400, 'ReportToEndpoints' => [ ], 'FeaturePolicyReportOnly' => [ ], 'SkinsPreferred' => [ 'vector-2022', 'vector', ], 'SpecialContributeSkinsEnabled' => [ ], 'SpecialContributeNewPageTarget' => null, 'EnableEditRecovery' => false, 'EditRecoveryExpiry' => 2592000, 'UseCodexSpecialBlock' => false, 'ShowLogoutConfirmation' => false, 'EnableProtectionIndicators' => true, 'OutputPipelineStages' => [ ], 'FeatureShutdown' => [ ], 'CloneArticleParserOutput' => true, 'UseLeximorph' => false, 'UsePostprocCache' => false, 'UsePostprocCacheLegacy' => false, 'UsePostprocCacheParsoid' => false, 'ParserOptionsLogUnsafeSampleRate' => 0, ], 'type' => [ 'ConfigRegistry' => 'object', 'AssumeProxiesUseDefaultProtocolPorts' => 'boolean', 'ForceHTTPS' => 'boolean', 'ExtensionDirectory' => [ 'string', 'null', ], 'StyleDirectory' => [ 'string', 'null', ], 'UploadDirectory' => [ 'string', 'boolean', 'null', ], 'Logos' => [ 'object', 'boolean', ], 'ReferrerPolicy' => [ 'array', 'string', 'boolean', ], 'ActionPaths' => 'object', 'MainPageIsDomainRoot' => 'boolean', 'ImgAuthUrlPathMap' => 'object', 'LocalFileRepo' => 'object', 'ForeignFileRepos' => 'array', 'UseSharedUploads' => 'boolean', 'SharedUploadDirectory' => [ 'string', 'null', ], 'SharedUploadPath' => [ 'string', 'null', ], 'HashedSharedUploadDirectory' => 'boolean', 'FetchCommonsDescriptions' => 'boolean', 'SharedUploadDBname' => [ 'boolean', 'string', ], 'SharedUploadDBprefix' => 'string', 'CacheSharedUploads' => 'boolean', 'ForeignUploadTargets' => 'array', 'UploadDialog' => 'object', 'FileBackends' => 'object', 'LockManagers' => 'array', 'CopyUploadsDomains' => 'array', 'CopyUploadTimeout' => [ 'boolean', 'integer', ], 'SharedThumbnailScriptPath' => [ 'string', 'boolean', ], 'HashedUploadDirectory' => 'boolean', 'CSPUploadEntryPoint' => 'boolean', 'FileExtensions' => 'array', 'ProhibitedFileExtensions' => 'array', 'MimeTypeExclusions' => 'array', 'TrustedMediaFormats' => 'array', 'MediaHandlers' => 'object', 'NativeImageLazyLoading' => 'boolean', 'ParserTestMediaHandlers' => 'object', 'MaxInterlacingAreas' => 'object', 'SVGConverters' => 'object', 'SVGNativeRendering' => [ 'string', 'boolean', ], 'MaxImageArea' => [ 'string', 'integer', 'boolean', ], 'TiffThumbnailType' => 'array', 'GenerateThumbnailOnParse' => 'boolean', 'EnableAutoRotation' => [ 'boolean', 'null', ], 'Antivirus' => [ 'string', 'null', ], 'AntivirusSetup' => 'object', 'MimeDetectorCommand' => [ 'string', 'null', ], 'XMLMimeTypes' => 'object', 'ImageLimits' => 'array', 'ThumbLimits' => 'array', 'ThumbnailNamespaces' => 'array', 'ThumbnailSteps' => [ 'array', 'null', ], 'ThumbnailStepsRatio' => [ 'number', 'null', ], 'ThumbnailBuckets' => [ 'array', 'null', ], 'UploadThumbnailRenderMap' => 'object', 'GalleryOptions' => 'object', 'DjvuDump' => [ 'string', 'null', ], 'DjvuRenderer' => [ 'string', 'null', ], 'DjvuTxt' => [ 'string', 'null', ], 'DjvuPostProcessor' => [ 'string', 'null', ], 'UserEmailConfirmationUseHTML' => 'boolean', 'SMTP' => [ 'boolean', 'object', ], 'EnotifFromEditor' => 'boolean', 'EnotifRevealEditorAddress' => 'boolean', 'UsersNotifiedOnAllChanges' => 'object', 'DBmwschema' => [ 'string', 'null', ], 'SharedTables' => 'array', 'DBservers' => [ 'boolean', 'array', ], 'LBFactoryConf' => 'object', 'LocalDatabases' => 'array', 'VirtualDomainsMapping' => 'object', 'FileSchemaMigrationStage' => 'integer', 'ExternalLinksDomainGaps' => 'object', 'ContentHandlers' => 'object', 'NamespaceContentModels' => 'object', 'TextModelsToParse' => 'array', 'ExternalStores' => 'array', 'ExternalServers' => 'object', 'DefaultExternalStore' => [ 'array', 'boolean', ], 'RevisionCacheExpiry' => 'integer', 'PageLanguageUseDB' => 'boolean', 'DiffEngine' => [ 'string', 'null', ], 'ExternalDiffEngine' => [ 'string', 'boolean', ], 'Wikidiff2Options' => 'object', 'RequestTimeLimit' => [ 'integer', 'null', ], 'CriticalSectionTimeLimit' => 'number', 'PoolCounterConf' => [ 'object', 'null', ], 'PoolCountClientConf' => 'object', 'MaxUserDBWriteDuration' => [ 'integer', 'boolean', ], 'MaxJobDBWriteDuration' => [ 'integer', 'boolean', ], 'MultiShardSiteStats' => 'boolean', 'ObjectCaches' => 'object', 'WANObjectCache' => 'object', 'MicroStashType' => [ 'string', 'integer', ], 'ParsoidCacheConfig' => 'object', 'ParsoidSelectiveUpdateSampleRate' => 'integer', 'ParserCacheFilterConfig' => 'object', 'ChronologyProtectorSecret' => 'string', 'PHPSessionHandling' => 'string', 'SuspiciousIpExpiry' => [ 'integer', 'boolean', ], 'MemCachedServers' => 'array', 'LocalisationCacheConf' => 'object', 'ExtensionInfoMTime' => [ 'integer', 'boolean', ], 'CdnServers' => 'object', 'CdnServersNoPurge' => 'object', 'HTCPRouting' => 'object', 'GrammarForms' => 'object', 'ExtraInterlanguageLinkPrefixes' => 'array', 'InterlanguageLinkCodeMap' => 'object', 'ExtraLanguageNames' => 'object', 'ExtraLanguageCodes' => 'object', 'DummyLanguageCodes' => 'object', 'DisabledVariants' => 'object', 'ForceUIMsgAsContentMsg' => 'object', 'RawHtmlMessages' => 'array', 'OverrideUcfirstCharacters' => 'object', 'XhtmlNamespaces' => 'object', 'BrowserFormatDetection' => 'string', 'SkinMetaTags' => 'object', 'SkipSkins' => 'object', 'FragmentMode' => 'array', 'FooterIcons' => 'object', 'InterwikiLogoOverride' => 'array', 'ResourceModules' => 'object', 'ResourceModuleSkinStyles' => 'object', 'ResourceLoaderSources' => 'object', 'ResourceLoaderMaxage' => 'object', 'ResourceLoaderMaxQueryLength' => [ 'integer', 'boolean', ], 'CanonicalNamespaceNames' => 'object', 'ExtraNamespaces' => 'object', 'ExtraGenderNamespaces' => 'object', 'NamespaceAliases' => 'object', 'CapitalLinkOverrides' => 'object', 'NamespacesWithSubpages' => 'object', 'ContentNamespaces' => 'array', 'ShortPagesNamespaceExclusions' => 'array', 'ExtraSignatureNamespaces' => 'array', 'InvalidRedirectTargets' => 'array', 'LocalInterwikis' => 'array', 'InterwikiCache' => [ 'boolean', 'object', ], 'SiteTypes' => 'object', 'UrlProtocols' => 'array', 'TidyConfig' => 'object', 'ParsoidSettings' => 'object', 'ParsoidExperimentalParserFunctionOutput' => 'boolean', 'NoFollowNsExceptions' => 'array', 'NoFollowDomainExceptions' => 'array', 'ExternalLinksIgnoreDomains' => 'array', 'EnableMagicLinks' => 'object', 'ManualRevertSearchRadius' => 'integer', 'RevertedTagMaxDepth' => 'integer', 'CentralIdLookupProviders' => 'object', 'CentralIdLookupProvider' => 'string', 'UserRegistrationProviders' => 'object', 'PasswordPolicy' => 'object', 'AuthManagerConfig' => [ 'object', 'null', ], 'AuthManagerAutoConfig' => 'object', 'RememberMe' => 'string', 'ReauthenticateTime' => 'object', 'AllowSecuritySensitiveOperationIfCannotReauthenticate' => 'object', 'ChangeCredentialsBlacklist' => 'array', 'RemoveCredentialsBlacklist' => 'array', 'PasswordConfig' => 'object', 'PasswordResetRoutes' => 'object', 'SignatureAllowedLintErrors' => 'array', 'ReservedUsernames' => 'array', 'DefaultUserOptions' => 'object', 'ConditionalUserOptions' => 'object', 'HiddenPrefs' => 'array', 'UserJsPrefLimit' => 'integer', 'AuthenticationTokenVersion' => [ 'string', 'null', ], 'SessionProviders' => 'object', 'AutoCreateTempUser' => 'object', 'AutoblockExemptions' => 'array', 'BlockCIDRLimit' => 'object', 'EnableMultiBlocks' => 'boolean', 'GroupPermissions' => 'object', 'PrivilegedGroups' => 'array', 'RevokePermissions' => 'object', 'GroupInheritsPermissions' => 'object', 'ImplicitGroups' => 'array', 'GroupsAddToSelf' => 'object', 'GroupsRemoveFromSelf' => 'object', 'RestrictedGroups' => 'object', 'UserRequirementsPrivateConditions' => 'array', 'RestrictionTypes' => 'array', 'RestrictionLevels' => 'array', 'CascadingRestrictionLevels' => 'array', 'SemiprotectedRestrictionLevels' => 'array', 'NamespaceProtection' => 'object', 'NonincludableNamespaces' => 'object', 'Autopromote' => 'object', 'AutopromoteOnce' => 'object', 'AutopromoteOnceRCExcludedGroups' => 'array', 'AddGroups' => 'object', 'RemoveGroups' => 'object', 'AvailableRights' => 'array', 'ImplicitRights' => 'array', 'AccountCreationThrottle' => [ 'integer', 'array', ], 'TempAccountCreationThrottle' => 'array', 'TempAccountNameAcquisitionThrottle' => 'array', 'SpamRegex' => 'array', 'SummarySpamRegex' => 'array', 'DnsBlacklistUrls' => 'array', 'ProxyList' => [ 'string', 'array', ], 'ProxyWhitelist' => 'array', 'SoftBlockRanges' => 'array', 'RateLimits' => 'object', 'RateLimitsExcludedIPs' => 'array', 'ExternalQuerySources' => 'object', 'PasswordAttemptThrottle' => 'array', 'GrantPermissions' => 'object', 'GrantPermissionGroups' => 'object', 'GrantRiskGroups' => 'object', 'EnableBotPasswords' => 'boolean', 'BotPasswordsCluster' => [ 'string', 'boolean', ], 'BotPasswordsDatabase' => [ 'string', 'boolean', ], 'BotPasswordsLimit' => 'integer', 'CSPHeader' => [ 'boolean', 'object', ], 'CSPReportOnlyHeader' => [ 'boolean', 'object', ], 'CSPFalsePositiveUrls' => 'object', 'AllowCrossOrigin' => 'boolean', 'RestAllowCrossOriginCookieAuth' => 'boolean', 'CookieSameSite' => [ 'string', 'null', ], 'CacheVaryCookies' => 'array', 'TrxProfilerLimits' => 'object', 'DebugLogGroups' => 'object', 'MWLoggerDefaultSpi' => 'object', 'Profiler' => 'object', 'StatsTarget' => [ 'string', 'null', ], 'StatsFormat' => [ 'string', 'null', ], 'StatsPrefix' => 'string', 'OpenTelemetryConfig' => [ 'object', 'null', ], 'OpenSearchTemplates' => 'object', 'NamespacesToBeSearchedDefault' => 'object', 'SitemapNamespaces' => [ 'boolean', 'array', ], 'SitemapNamespacesPriorities' => [ 'boolean', 'object', ], 'SitemapApiConfig' => 'object', 'SpecialSearchFormOptions' => 'object', 'SearchMatchRedirectPreference' => 'boolean', 'SearchRunSuggestedQuery' => 'boolean', 'PreviewOnOpenNamespaces' => 'object', 'ReadOnlyWatchedItemStore' => 'boolean', 'GitRepositoryViewers' => 'object', 'InstallerInitialPages' => 'array', 'RCLinkLimits' => 'array', 'RCLinkDays' => 'array', 'RCFeeds' => 'object', 'OverrideSiteFeed' => 'object', 'FeedClasses' => 'object', 'AdvertisedFeedTypes' => 'array', 'SoftwareTags' => 'object', 'RecentChangesFlags' => 'object', 'WatchlistExpiry' => 'boolean', 'EnableWatchlistLabels' => 'boolean', 'WatchlistLabelsMaxPerUser' => 'integer', 'WatchlistPurgeRate' => 'number', 'WatchlistExpiryMaxDuration' => [ 'string', 'null', ], 'EnableChangesListQueryPartitioning' => 'boolean', 'ImportSources' => 'object', 'ExtensionFunctions' => 'array', 'ExtensionMessagesFiles' => 'object', 'MessagesDirs' => 'object', 'TranslationAliasesDirs' => 'object', 'ExtensionEntryPointListFiles' => 'object', 'ValidSkinNames' => 'object', 'SpecialPages' => 'object', 'ExtensionCredits' => 'object', 'Hooks' => 'object', 'ServiceWiringFiles' => 'array', 'JobClasses' => 'object', 'JobTypesExcludedFromDefaultQueue' => 'array', 'JobBackoffThrottling' => 'object', 'JobTypeConf' => 'object', 'SpecialPageCacheUpdates' => 'object', 'PagePropLinkInvalidations' => 'object', 'TempCategoryCollations' => 'array', 'SortedCategories' => 'boolean', 'TrackingCategories' => 'array', 'LogTypes' => 'array', 'LogRestrictions' => 'object', 'FilterLogTypes' => 'object', 'LogNames' => 'object', 'LogHeaders' => 'object', 'LogActions' => 'object', 'LogActionsHandlers' => 'object', 'ActionFilteredLogs' => 'object', 'RangeContributionsCIDRLimit' => 'object', 'Actions' => 'object', 'NamespaceRobotPolicies' => 'object', 'ArticleRobotPolicies' => 'object', 'ExemptFromUserRobotsControl' => [ 'array', 'null', ], 'APIModules' => 'object', 'APIFormatModules' => 'object', 'APIMetaModules' => 'object', 'APIPropModules' => 'object', 'APIListModules' => 'object', 'APIUselessQueryPages' => 'array', 'CrossSiteAJAXdomains' => 'object', 'CrossSiteAJAXdomainExceptions' => 'object', 'AllowedCorsHeaders' => 'array', 'RestAPIAdditionalRouteFiles' => 'array', 'RestSandboxSpecs' => 'object', 'ShellRestrictionMethod' => [ 'string', 'boolean', ], 'ShellboxUrls' => 'object', 'ShellboxSecretKey' => [ 'string', 'null', ], 'ShellboxShell' => [ 'string', 'null', ], 'HTTPTimeout' => 'number', 'HTTPConnectTimeout' => 'number', 'HTTPMaxTimeout' => 'number', 'HTTPMaxConnectTimeout' => 'number', 'LocalVirtualHosts' => 'object', 'LocalHTTPProxy' => [ 'string', 'boolean', ], 'GenerateReqIDFormat' => 'string', 'VirtualRestConfig' => 'object', 'EventRelayerConfig' => 'object', 'Pingback' => 'boolean', 'OriginTrials' => 'array', 'ReportToExpiry' => 'integer', 'ReportToEndpoints' => 'array', 'FeaturePolicyReportOnly' => 'array', 'SkinsPreferred' => 'array', 'SpecialContributeSkinsEnabled' => 'array', 'SpecialContributeNewPageTarget' => [ 'string', 'null', ], 'EnableEditRecovery' => 'boolean', 'EditRecoveryExpiry' => 'integer', 'UseCodexSpecialBlock' => 'boolean', 'ShowLogoutConfirmation' => 'boolean', 'EnableProtectionIndicators' => 'boolean', 'OutputPipelineStages' => 'object', 'FeatureShutdown' => 'array', 'CloneArticleParserOutput' => 'boolean', 'UseLeximorph' => 'boolean', 'UsePostprocCache' => 'boolean', 'UsePostprocCacheLegacy' => 'boolean', 'UsePostprocCacheParsoid' => 'boolean', 'ParserOptionsLogUnsafeSampleRate' => 'integer', ], 'mergeStrategy' => [ 'TiffThumbnailType' => 'replace', 'LBFactoryConf' => 'replace', 'InterwikiCache' => 'replace', 'PasswordPolicy' => 'array_replace_recursive', 'AuthManagerAutoConfig' => 'array_plus_2d', 'GroupPermissions' => 'array_plus_2d', 'RevokePermissions' => 'array_plus_2d', 'AddGroups' => 'array_merge_recursive', 'RemoveGroups' => 'array_merge_recursive', 'RateLimits' => 'array_plus_2d', 'GrantPermissions' => 'array_plus_2d', 'MWLoggerDefaultSpi' => 'replace', 'Profiler' => 'replace', 'Hooks' => 'array_merge_recursive', 'VirtualRestConfig' => 'array_plus_2d', ], 'dynamicDefault' => [ 'UsePathInfo' => [ 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultUsePathInfo', ], ], 'Script' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultScript', ], ], 'LoadScript' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLoadScript', ], ], 'RestPath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultRestPath', ], ], 'StylePath' => [ 'use' => [ 'ResourceBasePath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultStylePath', ], ], 'LocalStylePath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLocalStylePath', ], ], 'ExtensionAssetsPath' => [ 'use' => [ 'ResourceBasePath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultExtensionAssetsPath', ], ], 'ArticlePath' => [ 'use' => [ 'Script', 'UsePathInfo', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultArticlePath', ], ], 'UploadPath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultUploadPath', ], ], 'FileCacheDirectory' => [ 'use' => [ 'UploadDirectory', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultFileCacheDirectory', ], ], 'Logo' => [ 'use' => [ 'ResourceBasePath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLogo', ], ], 'DeletedDirectory' => [ 'use' => [ 'UploadDirectory', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultDeletedDirectory', ], ], 'ShowEXIF' => [ 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultShowEXIF', ], ], 'SharedPrefix' => [ 'use' => [ 'DBprefix', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultSharedPrefix', ], ], 'SharedSchema' => [ 'use' => [ 'DBmwschema', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultSharedSchema', ], ], 'DBerrorLogTZ' => [ 'use' => [ 'Localtimezone', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultDBerrorLogTZ', ], ], 'Localtimezone' => [ 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLocaltimezone', ], ], 'LocalTZoffset' => [ 'use' => [ 'Localtimezone', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLocalTZoffset', ], ], 'ResourceBasePath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultResourceBasePath', ], ], 'MetaNamespace' => [ 'use' => [ 'Sitename', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultMetaNamespace', ], ], 'CookieSecure' => [ 'use' => [ 'ForceHTTPS', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultCookieSecure', ], ], 'CookiePrefix' => [ 'use' => [ 'SharedDB', 'SharedPrefix', 'SharedTables', 'DBname', 'DBprefix', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultCookiePrefix', ], ], 'ReadOnlyFile' => [ 'use' => [ 'UploadDirectory', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultReadOnlyFile', ], ], ], ], 'config-schema' => [ 'UploadStashScalerBaseUrl' => [ 'deprecated' => 'since 1.36 Use thumbProxyUrl in $wgLocalFileRepo', ], 'IllegalFileChars' => [ 'deprecated' => 'since 1.41; no longer customizable', ], 'ThumbnailNamespaces' => [ 'items' => [ 'type' => 'integer', ], ], 'LocalDatabases' => [ 'items' => [ 'type' => 'string', ], ], 'ParserCacheFilterConfig' => [ 'additionalProperties' => [ 'type' => 'object', 'description' => 'A map of namespace IDs to filter definitions.', 'additionalProperties' => [ 'type' => 'object', 'description' => 'A map of filter names to values.', 'properties' => [ 'minCpuTime' => [ 'type' => 'number', ], ], ], ], ], 'PHPSessionHandling' => [ 'deprecated' => 'since 1.45 Integration with PHP session handling will be removed in the future', ], 'RawHtmlMessages' => [ 'items' => [ 'type' => 'string', ], ], 'InterwikiLogoOverride' => [ 'items' => [ 'type' => 'string', ], ], 'LegalTitleChars' => [ 'deprecated' => 'since 1.41; use Extension:TitleBlacklist to customize', ], 'ReauthenticateTime' => [ 'additionalProperties' => [ 'type' => 'integer', ], ], 'AllowSecuritySensitiveOperationIfCannotReauthenticate' => [ 'additionalProperties' => [ 'type' => 'boolean', ], ], 'ChangeCredentialsBlacklist' => [ 'items' => [ 'type' => 'string', ], ], 'RemoveCredentialsBlacklist' => [ 'items' => [ 'type' => 'string', ], ], 'GroupPermissions' => [ 'additionalProperties' => [ 'type' => 'object', 'additionalProperties' => [ 'type' => 'boolean', ], ], ], 'GroupInheritsPermissions' => [ 'additionalProperties' => [ 'type' => 'string', ], ], 'AvailableRights' => [ 'items' => [ 'type' => 'string', ], ], 'ImplicitRights' => [ 'items' => [ 'type' => 'string', ], ], 'SoftBlockRanges' => [ 'items' => [ 'type' => 'string', ], ], 'ExternalQuerySources' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'enabled' => [ 'type' => 'boolean', 'default' => false, ], 'url' => [ 'type' => 'string', 'format' => 'uri', ], 'timeout' => [ 'type' => 'integer', 'default' => 10, ], ], 'required' => [ 'enabled', 'url', ], 'additionalProperties' => false, ], ], 'GrantPermissions' => [ 'additionalProperties' => [ 'type' => 'object', 'additionalProperties' => [ 'type' => 'boolean', ], ], ], 'GrantPermissionGroups' => [ 'additionalProperties' => [ 'type' => 'string', ], ], 'SitemapNamespacesPriorities' => [ 'deprecated' => 'since 1.45 and ignored', ], 'SitemapApiConfig' => [ 'additionalProperties' => [ 'enabled' => [ 'type' => 'bool', ], 'sitemapsPerIndex' => [ 'type' => 'int', ], 'pagesPerSitemap' => [ 'type' => 'int', ], 'expiry' => [ 'type' => 'int', ], ], ], 'SoftwareTags' => [ 'additionalProperties' => [ 'type' => 'boolean', ], ], 'JobBackoffThrottling' => [ 'additionalProperties' => [ 'type' => 'number', ], ], 'JobTypeConf' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'class' => [ 'type' => 'string', ], 'order' => [ 'type' => 'string', ], 'claimTTL' => [ 'type' => 'integer', ], ], ], ], 'TrackingCategories' => [ 'deprecated' => 'since 1.25 Extensions should now register tracking categories using the new extension registration system.', ], 'RangeContributionsCIDRLimit' => [ 'additionalProperties' => [ 'type' => 'integer', ], ], 'RestSandboxSpecs' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'url' => [ 'type' => 'string', 'format' => 'url', ], 'name' => [ 'type' => 'string', ], 'file' => [ 'type' => 'string', ], 'msg' => [ 'type' => 'string', 'description' => 'a message key', ], ], ], ], 'ShellboxUrls' => [ 'additionalProperties' => [ 'type' => [ 'string', 'boolean', 'null', ], ], ], ], 'obsolete-config' => [ 'MangleFlashPolicy' => 'Since 1.39; no longer has any effect.', 'EnableOpenSearchSuggest' => 'Since 1.35, no longer used', 'AutoloadAttemptLowercase' => 'Since 1.40; no longer has any effect.', ],]
$wgFragmentMode
Config variable stub for the FragmentMode setting, for use by phpdoc and IDEs.