X-Git-Url: http://git.cyclocoop.org/%7B%24admin_url%7Dcompta/comptes/journal.php?a=blobdiff_plain;f=includes%2FMessage.php;h=7d05f41e86cda77ce6203dec1b447e042ec92620;hb=719387f2e27ddc87205ac151c8337d97b63ae8fd;hp=d119940adf60b80fbc32b8e4cdab153f09b55fe3;hpb=ee12202b4c217252f8e392e50eddd4428af78d2a;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Message.php b/includes/Message.php index d119940adf..7d05f41e86 100644 --- a/includes/Message.php +++ b/includes/Message.php @@ -732,6 +732,8 @@ class Message implements MessageSpecifier, Serializable { if ( !$this->language instanceof Language || $this->language->getCode() != $lang ) { $this->language = Language::factory( $lang ); } + } elseif ( $lang instanceof StubUserLang ) { + $this->language = false; } else { $type = gettype( $lang ); throw new MWException( __METHOD__ . " must be " @@ -1103,7 +1105,7 @@ class Message implements MessageSpecifier, Serializable { public static function listParam( array $list, $type = 'text' ) { if ( !isset( self::$listTypeMap[$type] ) ) { throw new InvalidArgumentException( - "Invalid type '$type'. Known types are: " . join( ', ', array_keys( self::$listTypeMap ) ) + "Invalid type '$type'. Known types are: " . implode( ', ', array_keys( self::$listTypeMap ) ) ); } return [ 'list' => $list, 'type' => $type ]; @@ -1121,11 +1123,29 @@ class Message implements MessageSpecifier, Serializable { * @return string */ protected function replaceParameters( $message, $type = 'before', $format ) { + // A temporary marker for $1 parameters that is only valid + // in non-attribute contexts. However if the entire message is escaped + // then we don't want to use it because it will be mangled in all contexts + // and its unnessary as ->escaped() messages aren't html. + $marker = $format === self::FORMAT_ESCAPED ? '$' : '$\'"'; $replacementKeys = []; foreach ( $this->parameters as $n => $param ) { list( $paramType, $value ) = $this->extractParam( $param, $format ); - if ( $type === $paramType ) { - $replacementKeys['$' . ( $n + 1 )] = $value; + if ( $type === 'before' ) { + if ( $paramType === 'before' ) { + $replacementKeys['$' . ( $n + 1 )] = $value; + } else /* $paramType === 'after' */ { + // To protect against XSS from replacing parameters + // inside html attributes, we convert $1 to $'"1. + // In the event that one of the parameters ends up + // in an attribute, either the ' or the " will be + // escaped, breaking the replacement and avoiding XSS. + $replacementKeys['$' . ( $n + 1 )] = $marker . ( $n + 1 ); + } + } else { + if ( $paramType === 'after' ) { + $replacementKeys[$marker . ( $n + 1 )] = $value; + } } } $message = strtr( $message, $replacementKeys ); @@ -1165,11 +1185,17 @@ class Message implements MessageSpecifier, Serializable { } elseif ( isset( $param['list'] ) ) { return $this->formatListParam( $param['list'], $param['type'], $format ); } else { - $warning = 'Invalid parameter for message "' . $this->getKey() . '": ' . - htmlspecialchars( serialize( $param ) ); - trigger_error( $warning, E_USER_WARNING ); - $e = new Exception; - wfDebugLog( 'Bug58676', $warning . "\n" . $e->getTraceAsString() ); + if ( !is_scalar( $param ) ) { + $param = serialize( $param ); + } + \MediaWiki\Logger\LoggerFactory::getInstance( 'Bug58676' )->warning( + 'Invalid parameter for message "{msgkey}": {param}', + [ + 'exception' => new Exception, + 'msgkey' => $this->getKey(), + 'param' => htmlspecialchars( $param ), + ] + ); return [ 'before', '[INVALID]' ]; } @@ -1218,7 +1244,16 @@ class Message implements MessageSpecifier, Serializable { $this->getLanguage() ); - return $out instanceof ParserOutput ? $out->getText() : $out; + return $out instanceof ParserOutput + ? $out->getText( [ + 'enableSectionEditLinks' => false, + // Wrapping messages in an extra
is probably not expected. If + // they're outside the content area they probably shouldn't be + // targeted by CSS that's targeting the parser output, and if + // they're inside they already are from the outer div. + 'unwrap' => true, + ] ) + : $out; } /** @@ -1280,16 +1315,15 @@ class Message implements MessageSpecifier, Serializable { */ protected function formatPlaintext( $plaintext, $format ) { switch ( $format ) { - case self::FORMAT_TEXT: - case self::FORMAT_PLAIN: - return $plaintext; - - case self::FORMAT_PARSE: - case self::FORMAT_BLOCK_PARSE: - case self::FORMAT_ESCAPED: - default: - return htmlspecialchars( $plaintext, ENT_QUOTES ); - + case self::FORMAT_TEXT: + case self::FORMAT_PLAIN: + return $plaintext; + + case self::FORMAT_PARSE: + case self::FORMAT_BLOCK_PARSE: + case self::FORMAT_ESCAPED: + default: + return htmlspecialchars( $plaintext, ENT_QUOTES ); } }