X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=languages%2FLanguageConverter.php;h=8fdf4f5e51569bf041d8cf2115d5ae229e05c1a0;hb=ebd1cbe08942ae8f916b8a76f5c22eced261853d;hp=c098518a964fc3df37ed073fed84feb890b30050;hpb=5354c219cd436583c0a0e401718018e8569f84e2;p=lhc%2Fweb%2Fwiklou.git diff --git a/languages/LanguageConverter.php b/languages/LanguageConverter.php index c098518a96..8fdf4f5e51 100644 --- a/languages/LanguageConverter.php +++ b/languages/LanguageConverter.php @@ -140,10 +140,7 @@ class LanguageConverter { * main code if there is no fallback */ public function getVariantFallbacks( $variant ) { - if ( isset( $this->mVariantFallbacks[$variant] ) ) { - return $this->mVariantFallbacks[$variant]; - } - return $this->mMainLanguageCode; + return $this->mVariantFallbacks[$variant] ?? $this->mMainLanguageCode; } /** @@ -175,11 +172,13 @@ class LanguageConverter { $req = $this->validateVariant( $wgDefaultLanguageVariant ); } + $req = $this->validateVariant( $req ); + // This function, unlike the other get*Variant functions, is // not memoized (i.e. there return value is not cached) since // new information might appear during processing after this // is first called. - if ( $this->validateVariant( $req ) ) { + if ( $req ) { return $req; } return $this->mMainLanguageCode; @@ -210,14 +209,34 @@ class LanguageConverter { } /** - * Validate the variant + * Validate the variant and return an appropriate strict internal + * variant code if one exists. Compare to Language::hasVariant() + * which does a strict test. + * * @param string|null $variant The variant to validate - * @return mixed Returns the variant if it is valid, null otherwise + * @return mixed Returns an equivalent valid variant code if possible, + * null otherwise */ public function validateVariant( $variant = null ) { - if ( $variant !== null && in_array( $variant, $this->mVariants ) ) { + if ( $variant === null ) { + return null; + } + // Our internal variants are always lower-case; the variant we + // are validating may have mixed case. + $variant = LanguageCode::replaceDeprecatedCodes( strtolower( $variant ) ); + if ( in_array( $variant, $this->mVariants ) ) { return $variant; } + // Browsers are supposed to use BCP 47 standard in the + // Accept-Language header, but not all of our internal + // mediawiki variant codes are BCP 47. Map BCP 47 code + // to our internal code. + foreach ( $this->mVariants as $v ) { + // Case-insensitive match (BCP 47 is mixed case) + if ( strtolower( LanguageCode::bcp47( $v ) ) === $variant ) { + return $v; + } + } return null; } @@ -296,7 +315,7 @@ class LanguageConverter { return $this->mHeaderVariant; } - // see if some supported language variant is set in the + // See if some supported language variant is set in the // HTTP header. $languages = array_keys( $wgRequest->getAcceptLang() ); if ( empty( $languages ) ) { @@ -548,17 +567,18 @@ class LanguageConverter { $convTable = $convRule->getConvTable(); $action = $convRule->getRulesAction(); foreach ( $convTable as $variant => $pair ) { - if ( !$this->validateVariant( $variant ) ) { + $v = $this->validateVariant( $variant ); + if ( !$v ) { continue; } if ( $action == 'add' ) { // More efficient than array_merge(), about 2.5 times. foreach ( $pair as $from => $to ) { - $this->mTables[$variant]->setPair( $from, $to ); + $this->mTables[$v]->setPair( $from, $to ); } } elseif ( $action == 'remove' ) { - $this->mTables[$variant]->removeArray( $pair ); + $this->mTables[$v]->removeArray( $pair ); } } } @@ -642,8 +662,12 @@ class LanguageConverter { * -{flags|code1:text1;code2:text2;...}- or * -{text}- in which case no conversion should take place for text * - * @param string $text Text to be converted - * @return string Converted text + * @warning Glossary state is maintained between calls. Never feed this + * method input that hasn't properly been escaped as it may result in + * an XSS in subsequent calls, even if those subsequent calls properly + * escape things. + * @param string $text Text to be converted, already html escaped. + * @return string Converted text (html) */ public function convert( $text ) { $variant = $this->getPreferredVariant(); @@ -653,9 +677,11 @@ class LanguageConverter { /** * Same as convert() except a extra parameter to custom variant. * - * @param string $text Text to be converted + * @param string $text Text to be converted, already html escaped + * @param-taint $text exec_html * @param string $variant The target variant code * @return string Converted text + * @return-taint escaped */ public function convertTo( $text, $variant ) { global $wgDisableLangConversion; @@ -773,7 +799,7 @@ class LanguageConverter { $warningDone = true; } $startPos += 2; - continue; + break; } // Recursively parse another rule $inner .= $this->recursiveConvertRule( $text, $variant, $startPos, $depth + 1 ); @@ -1150,8 +1176,21 @@ class LanguageConverter { // [1] => 'zh-hant:yyy' // [2] => '' // ] - $pat = '/;\s*(?='; + $expandedVariants = []; foreach ( $this->mVariants as $variant ) { + $expandedVariants[ $variant ] = 1; + // Accept standard BCP 47 names for variants as well. + $expandedVariants[ LanguageCode::bcp47( $variant ) ] = 1; + } + // Accept old deprecated names for variants + foreach ( LanguageCode::getDeprecatedCodeMapping() as $old => $new ) { + if ( isset( $expandedVariants[ $new ] ) ) { + $expandedVariants[ $old ] = 1; + } + } + + $pat = '/;\s*(?='; + foreach ( $expandedVariants as $variant => $ignore ) { // zh-hans:xxx;zh-hant:yyy $pat .= $variant . '\s*:|'; // xxx=>zh-hans:yyy; xxx=>zh-hant:zzz