From 1e679228423f77dd28112fae9b16df254234a25b Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Mon, 28 Feb 2011 03:15:39 +0000 Subject: [PATCH] Followup for r81340: * Allow any language code which consists entirely of valid title characters, and does not contain any path-traversal characters, to be customised via the uselang parameter. Language::isValidCode() represents this concept. * Add some shortcuts preventing Language and LocalisationCache from looking for localisation files for a language code which does not follow the usual form of language codes in MediaWiki, i.e. /[a-z-]*/. This concept is represented by Language::isValidBuiltInCode(). * Do not allow colon characters in file names, per Platonides' suggestion on CR. --- includes/LocalisationCache.php | 6 ++++++ languages/Language.php | 27 +++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/includes/LocalisationCache.php b/includes/LocalisationCache.php index 888722ad23..e98710420a 100644 --- a/includes/LocalisationCache.php +++ b/includes/LocalisationCache.php @@ -343,6 +343,12 @@ class LocalisationCache { } $this->initialisedLangs[$code] = true; + # If the code is of the wrong form for a Messages*.php file, do a shallow fallback + if ( !Language::isValidBuiltInCode( $code ) ) { + $this->initShallowFallback( $code, 'en' ); + return; + } + # Recache the data if necessary if ( !$this->manualRecache && $this->isExpired( $code ) ) { if ( file_exists( Language::getMessagesFileName( $code ) ) ) { diff --git a/languages/Language.php b/languages/Language.php index 3501bd5a7a..3fa1032375 100644 --- a/languages/Language.php +++ b/languages/Language.php @@ -157,11 +157,19 @@ class Language { // Protect against path traversal below if ( !Language::isValidCode( $code ) - || strcspn( $code, "/\\\000" ) !== strlen( $code ) ) + || strcspn( $code, ":/\\\000" ) !== strlen( $code ) ) { throw new MWException( "Invalid language code \"$code\"" ); } + if ( !Language::isValidBuiltInCode( $code ) ) { + // It's not possible to customise this code with class files, so + // just return a Language object. This is to support uselang= hacks. + $lang = new Language; + $lang->setCode( $code ); + return $lang; + } + if ( $code == 'en' ) { $class = 'Language'; } else { @@ -193,10 +201,21 @@ class Language { /** * Returns true if a language code string is of a valid form, whether or - * not it exists. + * not it exists. This includes codes which are used solely for + * customisation via the MediaWiki namespace. */ public static function isValidCode( $code ) { - return strcspn( $code, "/\\\000" ) === strlen( $code ); + return + strcspn( $code, ":/\\\000" ) === strlen( $code ) + && !preg_match( Title::getTitleInvalidRegex(), $code ); + } + + /** + * Returns true if a language code is of a valid form for the purposes of + * internal customisation of MediaWiki, via Messages*.php. + */ + public static function isValidBuiltInCode( $code ) { + return preg_match( '/^[a-z0-9-]*$/', $code ); } /** @@ -2859,7 +2878,7 @@ class Language { static function getFileName( $prefix = 'Language', $code, $suffix = '.php' ) { // Protect against path traversal if ( !Language::isValidCode( $code ) - || strcspn( $code, "/\\\000" ) !== strlen( $code ) ) + || strcspn( $code, ":/\\\000" ) !== strlen( $code ) ) { throw new MWException( "Invalid language code \"$code\"" ); } -- 2.20.1