From 7bb50c630a6b760c0cdc7662c44f8c3607954a19 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Mon, 4 Apr 2011 12:59:55 +0000 Subject: [PATCH] The beginnings of HipHop compiled mode support. It works now for parser cache hits. * Work around HipHop issue 314 (volatile broken) and issue 308 (no compilation detection) by adding some large and ugly compilation detection code to WebStart.php and doMaintenance.php. * Provide an MW_COMPILED constant which can be used to detect compiled mode throughout the codebase. * Introduced wfIsHipHop(), which detects either compiled or interpreted mode. Used this to work around unusual eval() return value in eval.php. * Work around lack of ini_get() in Maintenance.php, by duplicating wfIsHipHop(). * In Maintenance::shouldExecute(), accept "include" as an inclusion function name, since all kinds of inclusion give this string in HipHop. * Introduced new class MWInit, which provides some static functions in the pre-autoloader environment. * Introduced MWInit::compiledPath(), which provides a relative path for invoking a compiled file, and MWInit::interpretedPath(), which provides an absolute path for interpreting a PHP file. Used these new functions in the appropriate places. * When we are running compiled code, don't include files which would generate duplicate class, function or constant definitions. Documented the new requirements on the contents of Defines.php and UtfNormalDefines.php. * In HipHop compiled mode, it's not possible to have executable code in the same file as a class definition. ** Moved MimeMagic initialisation to the constructor. ** Moved Namespace.php global variable initialisation to Setup.php. ** Moved MemcachedSessions.php initialisation to the caller in GlobalFunctions.php. ** Moved Sanitizer.php constants and global variables to static class members. Introduced an accessor function for the attribs regex, as a new place to put code formerly at file level. ** Moved Language.php initialisation of $wgLanguageNames to Language::getLanguageNames(). Removed the global variable, marked "private" since forever. * In two places: don't use error_log() with type=3 to append to a file, HipHop doesn't support it. Use file_put_contents() with FILE_APPEND instead. * Work around the terrible breakage of class_exists() by using MWInit::classExists() instead in various places. In WebInstaller::getPageByName(), the class_exists() was marked with a fixme comment already, so I replaced it with an autoloader solution. --- includes/AutoLoader.php | 16 + includes/DefaultSettings.php | 4 +- includes/Defines.php | 7 +- includes/ExternalStore.php | 2 +- includes/GlobalFunctions.php | 27 +- includes/MemcachedSessions.php | 7 - includes/MimeMagic.php | 19 +- includes/Namespace.php | 29 -- includes/Sanitizer.php | 656 +++++++++++++-------------- includes/Setup.php | 61 ++- includes/Skin.php | 20 +- includes/Title.php | 9 - includes/User.php | 2 +- includes/WebStart.php | 81 ++-- includes/installer/WebInstaller.php | 3 - includes/normal/UtfNormalDefines.php | 6 +- includes/normal/UtfNormalUtil.php | 2 +- languages/Language.php | 26 +- languages/LanguageConverter.php | 4 +- languages/Names.php | 2 +- maintenance/Maintenance.php | 8 +- maintenance/addwiki.php | 2 +- maintenance/doMaintenance.php | 38 +- maintenance/eval.php | 2 +- maintenance/hiphop/file-list.small | 3 + 25 files changed, 562 insertions(+), 474 deletions(-) diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index a4c7ae59a6..6bf28544d4 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -457,6 +457,22 @@ $wgAutoloadLocalClasses = array( 'LBFactory_InstallerFake' => 'includes/installer/Installer.php', 'LocalSettingsGenerator' => 'includes/installer/LocalSettingsGenerator.php', 'WebInstaller' => 'includes/installer/WebInstaller.php', + 'WebInstaller_Complete' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_Copying' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_DBConnect' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_DBSettings' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_Document' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_ExistingWiki' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_Install' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_Language' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_Name' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_Options' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_Readme' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_ReleaseNotes' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_Restart' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_Upgrade' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_UpgradeDoc' => 'includes/installer/WebInstallerPage.php', + 'WebInstaller_Welcome' => 'includes/installer/WebInstallerPage.php', 'WebInstallerPage' => 'includes/installer/WebInstallerPage.php', 'WebInstallerOutput' => 'includes/installer/WebInstallerOutput.php', 'MysqlInstaller' => 'includes/installer/MysqlInstaller.php', diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 36daef4b1d..716162a6bd 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -28,7 +28,9 @@ if( !defined( 'MEDIAWIKI' ) ) { # Create a site configuration object. Not used for much in a default install if ( !defined( 'MW_PHP4' ) ) { - require_once( "$IP/includes/SiteConfiguration.php" ); + if ( !defined( 'MW_COMPILED' ) ) { + require_once( "$IP/includes/SiteConfiguration.php" ); + } $wgConf = new SiteConfiguration; } /** @endcond */ diff --git a/includes/Defines.php b/includes/Defines.php index 94fcf03525..693bd447a3 100644 --- a/includes/Defines.php +++ b/includes/Defines.php @@ -1,6 +1,11 @@ 'Media', - NS_SPECIAL => 'Special', - NS_TALK => 'Talk', - NS_USER => 'User', - NS_USER_TALK => 'User_talk', - NS_PROJECT => 'Project', - NS_PROJECT_TALK => 'Project_talk', - NS_FILE => 'File', - NS_FILE_TALK => 'File_talk', - NS_MEDIAWIKI => 'MediaWiki', - NS_MEDIAWIKI_TALK => 'MediaWiki_talk', - NS_TEMPLATE => 'Template', - NS_TEMPLATE_TALK => 'Template_talk', - NS_HELP => 'Help', - NS_HELP_TALK => 'Help_talk', - NS_CATEGORY => 'Category', - NS_CATEGORY_TALK => 'Category_talk', -); - -/// @todo UGLY UGLY -if( is_array( $wgExtraNamespaces ) ) { - $wgCanonicalNamespaceNames = $wgCanonicalNamespaceNames + $wgExtraNamespaces; -} - /** * This is a utility class with only static functions * for dealing with namespaces that encodes all the diff --git a/includes/Sanitizer.php b/includes/Sanitizer.php index 4c99e82d55..27b17ce9f9 100644 --- a/includes/Sanitizer.php +++ b/includes/Sanitizer.php @@ -25,322 +25,323 @@ */ /** - * Regular expression to match various types of character references in - * Sanitizer::normalizeCharReferences and Sanitizer::decodeCharReferences - */ -define( 'MW_CHAR_REFS_REGEX', - '/&([A-Za-z0-9\x80-\xff]+); - |&\#([0-9]+); - |&\#[xX]([0-9A-Fa-f]+); - |(&)/x' ); - -/** - * Regular expression to match HTML/XML attribute pairs within a tag. - * Allows some... latitude. - * Used in Sanitizer::fixTagAttributes and Sanitizer::decodeTagAttributes + * XHTML sanitizer for MediaWiki + * @ingroup Parser */ -$attribFirst = '[:A-Z_a-z0-9]'; -$attrib = '[:A-Z_a-z-.0-9]'; -$space = '[\x09\x0a\x0d\x20]'; -define( 'MW_ATTRIBS_REGEX', - "/(?:^|$space)({$attribFirst}{$attrib}*) - ($space*=$space* - (?: - # The attribute value: quoted or alone - \"([^<\"]*)\" - | '([^<']*)' - | ([a-zA-Z0-9!#$%&()*,\\-.\\/:;<>?@[\\]^_`{|}~]+) - | (\#[0-9a-fA-F]+) # Technically wrong, but lots of - # colors are specified like this. - # We'll be normalizing it. - ) - )?(?=$space|\$)/sx" ); +class Sanitizer { + /** + * Regular expression to match various types of character references in + * Sanitizer::normalizeCharReferences and Sanitizer::decodeCharReferences + */ + const CHAR_REFS_REGEX = + '/&([A-Za-z0-9\x80-\xff]+); + |&\#([0-9]+); + |&\#[xX]([0-9A-Fa-f]+); + |(&)/x'; -/** - * Regular expression to match URIs that could trigger script execution - */ -define( 'MW_EVIL_URI_PATTERN', '!(^|\s|\*/\s*)(javascript|vbscript)([^\w]|$)!i' ); + const EVIL_URI_PATTERN = '!(^|\s|\*/\s*)(javascript|vbscript)([^\w]|$)!i'; + const XMLNS_ATTRIBUTE_PATTERN = "/^xmlns:[:A-Z_a-z-.0-9]+$/"; -/** - * Regular expression to match namespace attributes - */ -define( 'MW_XMLNS_ATTRIBUTE_PATTRN', "/^xmlns:$attrib+$/" ); + /** + * List of all named character entities defined in HTML 4.01 + * http://www.w3.org/TR/html4/sgml/entities.html + * @private + */ + static $htmlEntities = array( + 'Aacute' => 193, + 'aacute' => 225, + 'Acirc' => 194, + 'acirc' => 226, + 'acute' => 180, + 'AElig' => 198, + 'aelig' => 230, + 'Agrave' => 192, + 'agrave' => 224, + 'alefsym' => 8501, + 'Alpha' => 913, + 'alpha' => 945, + 'amp' => 38, + 'and' => 8743, + 'ang' => 8736, + 'Aring' => 197, + 'aring' => 229, + 'asymp' => 8776, + 'Atilde' => 195, + 'atilde' => 227, + 'Auml' => 196, + 'auml' => 228, + 'bdquo' => 8222, + 'Beta' => 914, + 'beta' => 946, + 'brvbar' => 166, + 'bull' => 8226, + 'cap' => 8745, + 'Ccedil' => 199, + 'ccedil' => 231, + 'cedil' => 184, + 'cent' => 162, + 'Chi' => 935, + 'chi' => 967, + 'circ' => 710, + 'clubs' => 9827, + 'cong' => 8773, + 'copy' => 169, + 'crarr' => 8629, + 'cup' => 8746, + 'curren' => 164, + 'dagger' => 8224, + 'Dagger' => 8225, + 'darr' => 8595, + 'dArr' => 8659, + 'deg' => 176, + 'Delta' => 916, + 'delta' => 948, + 'diams' => 9830, + 'divide' => 247, + 'Eacute' => 201, + 'eacute' => 233, + 'Ecirc' => 202, + 'ecirc' => 234, + 'Egrave' => 200, + 'egrave' => 232, + 'empty' => 8709, + 'emsp' => 8195, + 'ensp' => 8194, + 'Epsilon' => 917, + 'epsilon' => 949, + 'equiv' => 8801, + 'Eta' => 919, + 'eta' => 951, + 'ETH' => 208, + 'eth' => 240, + 'Euml' => 203, + 'euml' => 235, + 'euro' => 8364, + 'exist' => 8707, + 'fnof' => 402, + 'forall' => 8704, + 'frac12' => 189, + 'frac14' => 188, + 'frac34' => 190, + 'frasl' => 8260, + 'Gamma' => 915, + 'gamma' => 947, + 'ge' => 8805, + 'gt' => 62, + 'harr' => 8596, + 'hArr' => 8660, + 'hearts' => 9829, + 'hellip' => 8230, + 'Iacute' => 205, + 'iacute' => 237, + 'Icirc' => 206, + 'icirc' => 238, + 'iexcl' => 161, + 'Igrave' => 204, + 'igrave' => 236, + 'image' => 8465, + 'infin' => 8734, + 'int' => 8747, + 'Iota' => 921, + 'iota' => 953, + 'iquest' => 191, + 'isin' => 8712, + 'Iuml' => 207, + 'iuml' => 239, + 'Kappa' => 922, + 'kappa' => 954, + 'Lambda' => 923, + 'lambda' => 955, + 'lang' => 9001, + 'laquo' => 171, + 'larr' => 8592, + 'lArr' => 8656, + 'lceil' => 8968, + 'ldquo' => 8220, + 'le' => 8804, + 'lfloor' => 8970, + 'lowast' => 8727, + 'loz' => 9674, + 'lrm' => 8206, + 'lsaquo' => 8249, + 'lsquo' => 8216, + 'lt' => 60, + 'macr' => 175, + 'mdash' => 8212, + 'micro' => 181, + 'middot' => 183, + 'minus' => 8722, + 'Mu' => 924, + 'mu' => 956, + 'nabla' => 8711, + 'nbsp' => 160, + 'ndash' => 8211, + 'ne' => 8800, + 'ni' => 8715, + 'not' => 172, + 'notin' => 8713, + 'nsub' => 8836, + 'Ntilde' => 209, + 'ntilde' => 241, + 'Nu' => 925, + 'nu' => 957, + 'Oacute' => 211, + 'oacute' => 243, + 'Ocirc' => 212, + 'ocirc' => 244, + 'OElig' => 338, + 'oelig' => 339, + 'Ograve' => 210, + 'ograve' => 242, + 'oline' => 8254, + 'Omega' => 937, + 'omega' => 969, + 'Omicron' => 927, + 'omicron' => 959, + 'oplus' => 8853, + 'or' => 8744, + 'ordf' => 170, + 'ordm' => 186, + 'Oslash' => 216, + 'oslash' => 248, + 'Otilde' => 213, + 'otilde' => 245, + 'otimes' => 8855, + 'Ouml' => 214, + 'ouml' => 246, + 'para' => 182, + 'part' => 8706, + 'permil' => 8240, + 'perp' => 8869, + 'Phi' => 934, + 'phi' => 966, + 'Pi' => 928, + 'pi' => 960, + 'piv' => 982, + 'plusmn' => 177, + 'pound' => 163, + 'prime' => 8242, + 'Prime' => 8243, + 'prod' => 8719, + 'prop' => 8733, + 'Psi' => 936, + 'psi' => 968, + 'quot' => 34, + 'radic' => 8730, + 'rang' => 9002, + 'raquo' => 187, + 'rarr' => 8594, + 'rArr' => 8658, + 'rceil' => 8969, + 'rdquo' => 8221, + 'real' => 8476, + 'reg' => 174, + 'rfloor' => 8971, + 'Rho' => 929, + 'rho' => 961, + 'rlm' => 8207, + 'rsaquo' => 8250, + 'rsquo' => 8217, + 'sbquo' => 8218, + 'Scaron' => 352, + 'scaron' => 353, + 'sdot' => 8901, + 'sect' => 167, + 'shy' => 173, + 'Sigma' => 931, + 'sigma' => 963, + 'sigmaf' => 962, + 'sim' => 8764, + 'spades' => 9824, + 'sub' => 8834, + 'sube' => 8838, + 'sum' => 8721, + 'sup' => 8835, + 'sup1' => 185, + 'sup2' => 178, + 'sup3' => 179, + 'supe' => 8839, + 'szlig' => 223, + 'Tau' => 932, + 'tau' => 964, + 'there4' => 8756, + 'Theta' => 920, + 'theta' => 952, + 'thetasym' => 977, + 'thinsp' => 8201, + 'THORN' => 222, + 'thorn' => 254, + 'tilde' => 732, + 'times' => 215, + 'trade' => 8482, + 'Uacute' => 218, + 'uacute' => 250, + 'uarr' => 8593, + 'uArr' => 8657, + 'Ucirc' => 219, + 'ucirc' => 251, + 'Ugrave' => 217, + 'ugrave' => 249, + 'uml' => 168, + 'upsih' => 978, + 'Upsilon' => 933, + 'upsilon' => 965, + 'Uuml' => 220, + 'uuml' => 252, + 'weierp' => 8472, + 'Xi' => 926, + 'xi' => 958, + 'Yacute' => 221, + 'yacute' => 253, + 'yen' => 165, + 'Yuml' => 376, + 'yuml' => 255, + 'Zeta' => 918, + 'zeta' => 950, + 'zwj' => 8205, + 'zwnj' => 8204 + ); -/** - * List of all named character entities defined in HTML 4.01 - * http://www.w3.org/TR/html4/sgml/entities.html - * @private - */ -global $wgHtmlEntities; -$wgHtmlEntities = array( - 'Aacute' => 193, - 'aacute' => 225, - 'Acirc' => 194, - 'acirc' => 226, - 'acute' => 180, - 'AElig' => 198, - 'aelig' => 230, - 'Agrave' => 192, - 'agrave' => 224, - 'alefsym' => 8501, - 'Alpha' => 913, - 'alpha' => 945, - 'amp' => 38, - 'and' => 8743, - 'ang' => 8736, - 'Aring' => 197, - 'aring' => 229, - 'asymp' => 8776, - 'Atilde' => 195, - 'atilde' => 227, - 'Auml' => 196, - 'auml' => 228, - 'bdquo' => 8222, - 'Beta' => 914, - 'beta' => 946, - 'brvbar' => 166, - 'bull' => 8226, - 'cap' => 8745, - 'Ccedil' => 199, - 'ccedil' => 231, - 'cedil' => 184, - 'cent' => 162, - 'Chi' => 935, - 'chi' => 967, - 'circ' => 710, - 'clubs' => 9827, - 'cong' => 8773, - 'copy' => 169, - 'crarr' => 8629, - 'cup' => 8746, - 'curren' => 164, - 'dagger' => 8224, - 'Dagger' => 8225, - 'darr' => 8595, - 'dArr' => 8659, - 'deg' => 176, - 'Delta' => 916, - 'delta' => 948, - 'diams' => 9830, - 'divide' => 247, - 'Eacute' => 201, - 'eacute' => 233, - 'Ecirc' => 202, - 'ecirc' => 234, - 'Egrave' => 200, - 'egrave' => 232, - 'empty' => 8709, - 'emsp' => 8195, - 'ensp' => 8194, - 'Epsilon' => 917, - 'epsilon' => 949, - 'equiv' => 8801, - 'Eta' => 919, - 'eta' => 951, - 'ETH' => 208, - 'eth' => 240, - 'Euml' => 203, - 'euml' => 235, - 'euro' => 8364, - 'exist' => 8707, - 'fnof' => 402, - 'forall' => 8704, - 'frac12' => 189, - 'frac14' => 188, - 'frac34' => 190, - 'frasl' => 8260, - 'Gamma' => 915, - 'gamma' => 947, - 'ge' => 8805, - 'gt' => 62, - 'harr' => 8596, - 'hArr' => 8660, - 'hearts' => 9829, - 'hellip' => 8230, - 'Iacute' => 205, - 'iacute' => 237, - 'Icirc' => 206, - 'icirc' => 238, - 'iexcl' => 161, - 'Igrave' => 204, - 'igrave' => 236, - 'image' => 8465, - 'infin' => 8734, - 'int' => 8747, - 'Iota' => 921, - 'iota' => 953, - 'iquest' => 191, - 'isin' => 8712, - 'Iuml' => 207, - 'iuml' => 239, - 'Kappa' => 922, - 'kappa' => 954, - 'Lambda' => 923, - 'lambda' => 955, - 'lang' => 9001, - 'laquo' => 171, - 'larr' => 8592, - 'lArr' => 8656, - 'lceil' => 8968, - 'ldquo' => 8220, - 'le' => 8804, - 'lfloor' => 8970, - 'lowast' => 8727, - 'loz' => 9674, - 'lrm' => 8206, - 'lsaquo' => 8249, - 'lsquo' => 8216, - 'lt' => 60, - 'macr' => 175, - 'mdash' => 8212, - 'micro' => 181, - 'middot' => 183, - 'minus' => 8722, - 'Mu' => 924, - 'mu' => 956, - 'nabla' => 8711, - 'nbsp' => 160, - 'ndash' => 8211, - 'ne' => 8800, - 'ni' => 8715, - 'not' => 172, - 'notin' => 8713, - 'nsub' => 8836, - 'Ntilde' => 209, - 'ntilde' => 241, - 'Nu' => 925, - 'nu' => 957, - 'Oacute' => 211, - 'oacute' => 243, - 'Ocirc' => 212, - 'ocirc' => 244, - 'OElig' => 338, - 'oelig' => 339, - 'Ograve' => 210, - 'ograve' => 242, - 'oline' => 8254, - 'Omega' => 937, - 'omega' => 969, - 'Omicron' => 927, - 'omicron' => 959, - 'oplus' => 8853, - 'or' => 8744, - 'ordf' => 170, - 'ordm' => 186, - 'Oslash' => 216, - 'oslash' => 248, - 'Otilde' => 213, - 'otilde' => 245, - 'otimes' => 8855, - 'Ouml' => 214, - 'ouml' => 246, - 'para' => 182, - 'part' => 8706, - 'permil' => 8240, - 'perp' => 8869, - 'Phi' => 934, - 'phi' => 966, - 'Pi' => 928, - 'pi' => 960, - 'piv' => 982, - 'plusmn' => 177, - 'pound' => 163, - 'prime' => 8242, - 'Prime' => 8243, - 'prod' => 8719, - 'prop' => 8733, - 'Psi' => 936, - 'psi' => 968, - 'quot' => 34, - 'radic' => 8730, - 'rang' => 9002, - 'raquo' => 187, - 'rarr' => 8594, - 'rArr' => 8658, - 'rceil' => 8969, - 'rdquo' => 8221, - 'real' => 8476, - 'reg' => 174, - 'rfloor' => 8971, - 'Rho' => 929, - 'rho' => 961, - 'rlm' => 8207, - 'rsaquo' => 8250, - 'rsquo' => 8217, - 'sbquo' => 8218, - 'Scaron' => 352, - 'scaron' => 353, - 'sdot' => 8901, - 'sect' => 167, - 'shy' => 173, - 'Sigma' => 931, - 'sigma' => 963, - 'sigmaf' => 962, - 'sim' => 8764, - 'spades' => 9824, - 'sub' => 8834, - 'sube' => 8838, - 'sum' => 8721, - 'sup' => 8835, - 'sup1' => 185, - 'sup2' => 178, - 'sup3' => 179, - 'supe' => 8839, - 'szlig' => 223, - 'Tau' => 932, - 'tau' => 964, - 'there4' => 8756, - 'Theta' => 920, - 'theta' => 952, - 'thetasym' => 977, - 'thinsp' => 8201, - 'THORN' => 222, - 'thorn' => 254, - 'tilde' => 732, - 'times' => 215, - 'trade' => 8482, - 'Uacute' => 218, - 'uacute' => 250, - 'uarr' => 8593, - 'uArr' => 8657, - 'Ucirc' => 219, - 'ucirc' => 251, - 'Ugrave' => 217, - 'ugrave' => 249, - 'uml' => 168, - 'upsih' => 978, - 'Upsilon' => 933, - 'upsilon' => 965, - 'Uuml' => 220, - 'uuml' => 252, - 'weierp' => 8472, - 'Xi' => 926, - 'xi' => 958, - 'Yacute' => 221, - 'yacute' => 253, - 'yen' => 165, - 'Yuml' => 376, - 'yuml' => 255, - 'Zeta' => 918, - 'zeta' => 950, - 'zwj' => 8205, - 'zwnj' => 8204 ); + /** + * Character entity aliases accepted by MediaWiki + */ + static $htmlEntityAliases = array( + 'רלמ' => 'rlm', + 'رلم' => 'rlm', + ); -/** - * Character entity aliases accepted by MediaWiki - */ -global $wgHtmlEntityAliases; -$wgHtmlEntityAliases = array( - 'רלמ' => 'rlm', - 'رلم' => 'rlm', -); + /** + * Lazy-initialised attributes regex, see getAttribsRegex() + */ + static $attribsRegex; + /** + * Regular expression to match HTML/XML attribute pairs within a tag. + * Allows some... latitude. + * Used in Sanitizer::fixTagAttributes and Sanitizer::decodeTagAttributes + */ + static function getAttribsRegex() { + if ( self::$attribsRegex === null ) { + $attribFirst = '[:A-Z_a-z0-9]'; + $attrib = '[:A-Z_a-z-.0-9]'; + $space = '[\x09\x0a\x0d\x20]'; + self::$attribsRegex = + "/(?:^|$space)({$attribFirst}{$attrib}*) + ($space*=$space* + (?: + # The attribute value: quoted or alone + \"([^<\"]*)\" + | '([^<']*)' + | ([a-zA-Z0-9!#$%&()*,\\-.\\/:;<>?@[\\]^_`{|}~]+) + | (\#[0-9a-fA-F]+) # Technically wrong, but lots of + # colors are specified like this. + # We'll be normalizing it. + ) + )?(?=$space|\$)/sx"; + } + return self::$attribsRegex; + } -/** - * XHTML sanitizer for MediaWiki - * @ingroup Parser - */ -class Sanitizer { /** * Cleans up HTML, removes dangerous tags and attributes, and * removes HTML comments @@ -635,8 +636,8 @@ class Sanitizer { $out = array(); foreach( $attribs as $attribute => $value ) { #allow XML namespace declaration if RDFa is enabled - if ( $wgAllowRdfaAttributes && preg_match( MW_XMLNS_ATTRIBUTE_PATTRN, $attribute ) ) { - if ( !preg_match( MW_EVIL_URI_PATTERN, $value ) ) { + if ( $wgAllowRdfaAttributes && preg_match( self::XMLNS_ATTRIBUTE_PATTERN, $attribute ) ) { + if ( !preg_match( self::EVIL_URI_PATTERN, $value ) ) { $out[$attribute] = $value; } @@ -666,7 +667,7 @@ class Sanitizer { $attribute === 'itemscope' || $attribute === 'itemtype' ) { #HTML5 microdata //Paranoia. Allow "simple" values but suppress javascript - if ( preg_match( MW_EVIL_URI_PATTERN, $value ) ) { + if ( preg_match( self::EVIL_URI_PATTERN, $value ) ) { continue; } } @@ -1002,7 +1003,7 @@ class Sanitizer { $attribs = array(); $pairs = array(); if( !preg_match_all( - MW_ATTRIBS_REGEX, + self::getAttribsRegex(), $text, $pairs, PREG_SET_ORDER ) ) { @@ -1025,7 +1026,7 @@ class Sanitizer { /** * Pick the appropriate attribute value from a match set from the - * MW_ATTRIBS_REGEX matches. + * attribs regex matches. * * @param $set Array * @return String @@ -1105,7 +1106,7 @@ class Sanitizer { */ static function normalizeCharReferences( $text ) { return preg_replace_callback( - MW_CHAR_REFS_REGEX, + self::CHAR_REFS_REGEX, array( 'Sanitizer', 'normalizeCharReferencesCallback' ), $text ); } @@ -1140,14 +1141,13 @@ class Sanitizer { * @return String */ static function normalizeEntity( $name ) { - global $wgHtmlEntities, $wgHtmlEntityAliases; - if ( isset( $wgHtmlEntityAliases[$name] ) ) { - return "&{$wgHtmlEntityAliases[$name]};"; + if ( isset( self::$htmlEntityAliases[$name] ) ) { + return '&' . self::$htmlEntityAliases[$name] . ';'; } elseif ( in_array( $name, array( 'lt', 'gt', 'amp', 'quot' ) ) ) { return "&$name;"; - } elseif ( isset( $wgHtmlEntities[$name] ) ) { - return "&#{$wgHtmlEntities[$name]};"; + } elseif ( isset( self::$htmlEntities[$name] ) ) { + return '&#' . self::$htmlEntities[$name] . ';'; } else { return "&$name;"; } @@ -1194,7 +1194,7 @@ class Sanitizer { */ public static function decodeCharReferences( $text ) { return preg_replace_callback( - MW_CHAR_REFS_REGEX, + self::CHAR_REFS_REGEX, array( 'Sanitizer', 'decodeCharReferencesCallback' ), $text ); } @@ -1212,7 +1212,7 @@ class Sanitizer { public static function decodeCharReferencesAndNormalize( $text ) { global $wgContLang; $text = preg_replace_callback( - MW_CHAR_REFS_REGEX, + self::CHAR_REFS_REGEX, array( 'Sanitizer', 'decodeCharReferencesCallback' ), $text, /* limit */ -1, $count ); @@ -1263,12 +1263,11 @@ class Sanitizer { * @return String */ static function decodeEntity( $name ) { - global $wgHtmlEntities, $wgHtmlEntityAliases; - if ( isset( $wgHtmlEntityAliases[$name] ) ) { - $name = $wgHtmlEntityAliases[$name]; + if ( isset( self::$htmlEntityAliases[$name] ) ) { + $name = self::$htmlEntityAliases[$name]; } - if( isset( $wgHtmlEntities[$name] ) ) { - return codepointToUtf8( $wgHtmlEntities[$name] ); + if( isset( self::$htmlEntities[$name] ) ) { + return codepointToUtf8( self::$htmlEntities[$name] ); } else { return "&$name;"; } @@ -1493,9 +1492,8 @@ class Sanitizer { * @return String */ static function hackDocType() { - global $wgHtmlEntities; $out = " $codepoint ) { + foreach( self::$htmlEntities as $entity => $codepoint ) { $out .= ""; } $out .= "]>\n"; diff --git a/includes/Setup.php b/includes/Setup.php index 9bfe418078..95271df7e3 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -218,6 +218,35 @@ if ( $wgMetaNamespace === false ) { $wgMetaNamespace = str_replace( ' ', '_', $wgSitename ); } +/** + * Definitions of the NS_ constants are in Defines.php + * @private + */ +$wgCanonicalNamespaceNames = array( + NS_MEDIA => 'Media', + NS_SPECIAL => 'Special', + NS_TALK => 'Talk', + NS_USER => 'User', + NS_USER_TALK => 'User_talk', + NS_PROJECT => 'Project', + NS_PROJECT_TALK => 'Project_talk', + NS_FILE => 'File', + NS_FILE_TALK => 'File_talk', + NS_MEDIAWIKI => 'MediaWiki', + NS_MEDIAWIKI_TALK => 'MediaWiki_talk', + NS_TEMPLATE => 'Template', + NS_TEMPLATE_TALK => 'Template_talk', + NS_HELP => 'Help', + NS_HELP_TALK => 'Help_talk', + NS_CATEGORY => 'Category', + NS_CATEGORY_TALK => 'Category_talk', +); + +/// @todo UGLY UGLY +if( is_array( $wgExtraNamespaces ) ) { + $wgCanonicalNamespaceNames = $wgCanonicalNamespaceNames + $wgExtraNamespaces; +} + # These are now the same, always # To determine the user language, use $wgLang->getCode() $wgContLanguageCode = $wgLanguageCode; @@ -274,22 +303,24 @@ if ( $wgNewUserLog ) { $wgLogActions['newusers/autocreate'] = 'newuserlog-autocreate-entry'; } -if ( !class_exists( 'AutoLoader' ) ) { - require_once( "$IP/includes/AutoLoader.php" ); -} +if ( !defined( 'MW_COMPILED' ) ) { + if ( !MWInit::classExists( 'AutoLoader' ) ) { + require_once( "$IP/includes/AutoLoader.php" ); + } -wfProfileIn( $fname . '-exception' ); -require_once( "$IP/includes/Exception.php" ); -wfInstallExceptionHandler(); -wfProfileOut( $fname . '-exception' ); - -wfProfileIn( $fname . '-includes' ); -require_once( "$IP/includes/GlobalFunctions.php" ); -require_once( "$IP/includes/Hooks.php" ); -require_once( "$IP/includes/Namespace.php" ); -require_once( "$IP/includes/ProxyTools.php" ); -require_once( "$IP/includes/ImageFunctions.php" ); -wfProfileOut( $fname . '-includes' ); + wfProfileIn( $fname . '-exception' ); + require_once( "$IP/includes/Exception.php" ); + wfInstallExceptionHandler(); + wfProfileOut( $fname . '-exception' ); + + wfProfileIn( $fname . '-includes' ); + require_once( "$IP/includes/GlobalFunctions.php" ); + require_once( "$IP/includes/Hooks.php" ); + require_once( "$IP/includes/Namespace.php" ); + require_once( "$IP/includes/ProxyTools.php" ); + require_once( "$IP/includes/ImageFunctions.php" ); + wfProfileOut( $fname . '-includes' ); +} wfProfileIn( $fname . '-misc1' ); # Raise the memory limit if it's too low diff --git a/includes/Skin.php b/includes/Skin.php index 7fbce41fd5..f1f0cde8cb 100644 --- a/includes/Skin.php +++ b/includes/Skin.php @@ -138,24 +138,28 @@ abstract class Skin { $className = "Skin{$skinName}"; # Grab the skin class and initialise it. - if ( !class_exists( $className ) ) { - // Preload base classes to work around APC/PHP5 bug - $deps = "{$wgStyleDirectory}/{$skinName}.deps.php"; + if ( !MWInit::classExists( $className ) ) { - if ( file_exists( $deps ) ) { - include_once( $deps ); + if ( !defined( 'MW_COMPILED' ) ) { + // Preload base classes to work around APC/PHP5 bug + $deps = "{$wgStyleDirectory}/{$skinName}.deps.php"; + if ( file_exists( $deps ) ) { + include_once( $deps ); + } + require_once( "{$wgStyleDirectory}/{$skinName}.php" ); } - require_once( "{$wgStyleDirectory}/{$skinName}.php" ); # Check if we got if not failback to default skin - if ( !class_exists( $className ) ) { + if ( !MWInit::classExists( $className ) ) { # DO NOT die if the class isn't found. This breaks maintenance # scripts and can cause a user account to be unrecoverable # except by SQL manipulation if a previously valid skin name # is no longer valid. wfDebug( "Skin class does not exist: $className\n" ); $className = 'SkinVector'; - require_once( "{$wgStyleDirectory}/Vector.php" ); + if ( !defined( 'MW_COMPILED' ) ) { + require_once( "{$wgStyleDirectory}/Vector.php" ); + } } } $skin = new $className; diff --git a/includes/Title.php b/includes/Title.php index c5fd079c22..051998c0ef 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -4,15 +4,6 @@ * @file */ -/** - * @todo: determine if it is really necessary to load this. Appears to be left over from pre-autoloader versions, and - * is only really needed to provide access to constant UTF8_REPLACEMENT, which actually resides in UtfNormalDefines.php - * and is loaded by UtfNormalUtil.php, which is loaded by UtfNormal.php. - */ -if ( !class_exists( 'UtfNormal' ) ) { - require_once( dirname( __FILE__ ) . '/normal/UtfNormal.php' ); -} - /** * @deprecated This used to be a define, but was moved to * Title::GAID_FOR_UPDATE in 1.17. This will probably be removed in 1.18 diff --git a/includes/User.php b/includes/User.php index 968a830056..3ffd4a9276 100644 --- a/includes/User.php +++ b/includes/User.php @@ -1333,7 +1333,7 @@ class User { if( $count > $max ) { wfDebug( __METHOD__ . ": tripped! $key at $count $summary\n" ); if( $wgRateLimitLog ) { - @error_log( wfTimestamp( TS_MW ) . ' ' . wfWikiID() . ': ' . $this->getName() . " tripped $key at $count $summary\n", 3, $wgRateLimitLog ); + @file_put_contents( $wgRateLimitLog, wfTimestamp( TS_MW ) . ' ' . wfWikiID() . ': ' . $this->getName() . " tripped $key at $count $summary\n", FILE_APPEND ); } $triggered = true; } else { diff --git a/includes/WebStart.php b/includes/WebStart.php index 2c21cdb2db..4a40343e31 100644 --- a/includes/WebStart.php +++ b/includes/WebStart.php @@ -8,6 +8,20 @@ * @file */ +/** + * Detect compiled mode by looking for a function that only exists if compiled + * in. Note that we can't use function_exists(), because it is terribly broken + * under HipHop due to the "volatile" feature. + */ +function wfDetectCompiledMode() { + try { + $r = new ReflectionFunction( 'wfHipHopCompilerVersion' ); + } catch ( ReflectionException $e ) { + $r = false; + } + return $r !== false; +} + # Protect against register_globals # This must be done before any globals are set by the code if ( ini_get( 'register_globals' ) ) { @@ -67,40 +81,51 @@ if ( $IP === false ) { $IP = realpath( '.' ); } - -# Start profiler -if( file_exists("$IP/StartProfiler.php") ) { - require_once( "$IP/StartProfiler.php" ); -} else { - require_once( "$IP/includes/ProfilerStub.php" ); +if ( wfDetectCompiledMode() ) { + define( 'MW_COMPILED', 1 ); } -wfProfileIn( 'WebStart.php-conf' ); -# Load up some global defines. -require_once( "$IP/includes/Defines.php" ); - -# Check for PHP 5 -if ( !function_exists( 'version_compare' ) - || version_compare( phpversion(), '5.0.0' ) < 0 -) { - define( 'MW_PHP4', '1' ); - require( "$IP/includes/DefaultSettings.php" ); - require( "$IP/includes/templates/PHP4.php" ); - exit; +if ( !defined( 'MW_COMPILED' ) ) { + # Get MWInit class + require_once( "$IP/includes/Init.php" ); + + # Start profiler + # FIXME: rewrite wfProfileIn/wfProfileOut so that they can work in compiled mode + if ( file_exists( "$IP/StartProfiler.php" ) ) { + require_once( "$IP/StartProfiler.php" ); + } else { + require_once( "$IP/includes/ProfilerStub.php" ); + } + + # Load up some global defines. + require_once( "$IP/includes/Defines.php" ); + + # Check for PHP 5 + if ( !function_exists( 'version_compare' ) + || version_compare( phpversion(), '5.0.0' ) < 0 + ) { + define( 'MW_PHP4', '1' ); + require( "$IP/includes/DefaultSettings.php" ); + require( "$IP/includes/templates/PHP4.php" ); + exit; + } + + # Start the autoloader, so that extensions can derive classes from core files + require_once( "$IP/includes/AutoLoader.php" ); } -# Start the autoloader, so that extensions can derive classes from core files -require_once( "$IP/includes/AutoLoader.php" ); +wfProfileIn( 'WebStart.php-conf' ); + # Load default settings -require_once( "$IP/includes/DefaultSettings.php" ); +require_once( MWInit::compiledPath( "includes/DefaultSettings.php" ) ); if ( defined( 'MW_CONFIG_CALLBACK' ) ) { # Use a callback function to configure MediaWiki MWFunction::call( MW_CONFIG_CALLBACK ); - } else { - if ( !defined('MW_CONFIG_FILE') ) - define('MW_CONFIG_FILE', "$IP/LocalSettings.php"); + if ( !defined( 'MW_CONFIG_FILE' ) ) { + define('MW_CONFIG_FILE', MWInit::interpretedPath( 'LocalSettings.php' ) ); + } # LocalSettings.php is the per site customization file. If it does not exist # the wiki installer needs to be launched or the generated file uploaded to @@ -115,7 +140,7 @@ if ( defined( 'MW_CONFIG_CALLBACK' ) ) { } if ( $wgEnableSelenium ) { - require_once( "$IP/includes/SeleniumWebSettings.php" ); + require_once( MWInit::compiledPath( "includes/SeleniumWebSettings.php" ) ); } wfProfileOut( 'WebStart.php-conf' ); @@ -126,12 +151,14 @@ wfProfileIn( 'WebStart.php-ob_start' ); # that would cause us to potentially mix gzip and non-gzip output, creating a # big mess. if ( !defined( 'MW_NO_OUTPUT_BUFFER' ) && ob_get_level() == 0 ) { - require_once( "$IP/includes/OutputHandler.php" ); + if ( !defined( 'MW_COMPILED' ) ) { + require_once( "$IP/includes/OutputHandler.php" ); + } ob_start( 'wfOutputHandler' ); } wfProfileOut( 'WebStart.php-ob_start' ); if ( !defined( 'MW_NO_SETUP' ) ) { - require_once( "$IP/includes/Setup.php" ); + require_once( MWInit::compiledPath( "includes/Setup.php" ) ); } diff --git a/includes/installer/WebInstaller.php b/includes/installer/WebInstaller.php index 493e81f193..0d007260c3 100644 --- a/includes/installer/WebInstaller.php +++ b/includes/installer/WebInstaller.php @@ -408,9 +408,6 @@ class WebInstaller extends Installer { * @return WebInstallerPage */ public function getPageByName( $pageName ) { - // Totally lame way to force autoload of WebInstallerPage.php - class_exists( 'WebInstallerPage' ); - $pageClass = 'WebInstaller_' . $pageName; return new $pageClass( $this ); diff --git a/includes/normal/UtfNormalDefines.php b/includes/normal/UtfNormalDefines.php index d759c64c62..6c4d8b76d8 100644 --- a/includes/normal/UtfNormalDefines.php +++ b/includes/normal/UtfNormalDefines.php @@ -1,6 +1,10 @@ mLangObj = $langobj; $this->mMainLanguageCode = $maincode; $this->mVariants = array_diff( $variants, $wgDisabledVariants ); $this->mVariantFallbacks = $variantfallbacks; - $this->mVariantNames = $wgLanguageNames; + $this->mVariantNames = Language::getLanguageNames(); $this->mCacheKey = wfMemcKey( 'conversiontables', $maincode ); $defaultflags = array( // 'S' show converted text diff --git a/languages/Names.php b/languages/Names.php index e9153b5e0e..89027e7d02 100644 --- a/languages/Names.php +++ b/languages/Names.php @@ -5,7 +5,7 @@ * * @ingroup Language */ -/* private */ $wgLanguageNames = array( +/* private */ $coreLanguageNames = array( 'aa' => 'Qafár af', # Afar 'ab' => 'Аҧсуа', # Abkhaz, should possibly add ' бысжѡа' 'ace' => 'Acèh', # Aceh diff --git a/maintenance/Maintenance.php b/maintenance/Maintenance.php index c238b9c12e..67c5faf035 100644 --- a/maintenance/Maintenance.php +++ b/maintenance/Maintenance.php @@ -139,7 +139,7 @@ abstract class Maintenance { if( count( $bt ) !== 2 ) { return false; } - return ( $bt[1]['function'] == 'require_once' || $bt[1]['function'] == 'require' ) && + return in_array( $bt[1]['function'], array( 'require_once', 'require', 'include' ) ) && $bt[0]['class'] == 'Maintenance' && $bt[0]['function'] == 'shouldExecute'; } @@ -430,11 +430,11 @@ abstract class Maintenance { */ public function runChild( $maintClass, $classFile = null ) { // Make sure the class is loaded first - if ( !class_exists( $maintClass ) ) { + if ( !MWInit::classExists( $maintClass ) ) { if ( $classFile ) { require_once( $classFile ); } - if ( !class_exists( $maintClass ) ) { + if ( !MWInit::classExists( $maintClass ) ) { $this->error( "Cannot spawn child: $maintClass" ); } } @@ -456,7 +456,7 @@ abstract class Maintenance { } # Make sure we can handle script parameters - if ( !ini_get( 'register_argc_argv' ) ) { + if ( !function_exists( 'hphp_thread_set_warmup_enabled' ) && !ini_get( 'register_argc_argv' ) ) { $this->error( 'Cannot get command line arguments, register_argc_argv is set to false', true ); } diff --git a/maintenance/addwiki.php b/maintenance/addwiki.php index bed2ad6940..5d0a54a68f 100644 --- a/maintenance/addwiki.php +++ b/maintenance/addwiki.php @@ -57,7 +57,7 @@ class AddWiki extends Maintenance { $languageNames = Language::getLanguageNames(); if ( !isset( $languageNames[$lang] ) ) { - $this->error( "Language $lang not found in \$wgLanguageNames", true ); + $this->error( "Language $lang not found in Names.php", true ); } $name = $languageNames[$lang]; diff --git a/maintenance/doMaintenance.php b/maintenance/doMaintenance.php index 0ed50bad75..437ca83c32 100644 --- a/maintenance/doMaintenance.php +++ b/maintenance/doMaintenance.php @@ -53,17 +53,35 @@ $maintenance->setup(); // to $maintenance->mSelf. Keep that here for b/c $self = $maintenance->getName(); +// Detect compiled mode +try { + $r = new ReflectionFunction( 'wfHipHopCompilerVersion' ); +} catch ( ReflectionException $e ) { + $r = false; +} + +if ( $r ) { + define( 'MW_COMPILED', 1 ); +} + +# Get the MWInit class +if ( !defined( 'MW_COMPILED' ) ) { + require_once( "$IP/includes/Init.php" ); +} + # Setup the profiler global $IP; -if ( file_exists( "$IP/StartProfiler.php" ) ) { +if ( !defined( 'MW_COMPILED' ) && file_exists( "$IP/StartProfiler.php" ) ) { require_once( "$IP/StartProfiler.php" ); } else { - require_once( "$IP/includes/ProfilerStub.php" ); + require_once( MWInit::compiledPath( 'includes/ProfilerStub.php' ) ); } // Some other requires -require_once( "$IP/includes/AutoLoader.php" ); -require_once( "$IP/includes/Defines.php" ); +if ( !defined( 'MW_COMPILED' ) ) { + require_once( "$IP/includes/AutoLoader.php" ); + require_once( "$IP/includes/Defines.php" ); +} require_once( "$IP/includes/DefaultSettings.php" ); if ( defined( 'MW_CONFIG_CALLBACK' ) ) { @@ -77,10 +95,10 @@ if ( defined( 'MW_CONFIG_CALLBACK' ) ) { global $cluster; $wgWikiFarm = true; $cluster = 'pmtpa'; - require_once( "$IP/includes/SiteConfiguration.php" ); - require( "$IP/wmf-config/wgConf.php" ); + require_once( MWInit::compiledPath( 'includes/SiteConfiguration.php' ) ); + require( MWInit::interpretedPath( 'wmf-config/wgConf.php' ) ); $maintenance->loadWikimediaSettings(); - require( $IP . '/wmf-config/CommonSettings.php' ); + require( MWInit::interpretedPath( '/wmf-config/CommonSettings.php' ) ); } else { require_once( $maintenance->loadSettings() ); } @@ -88,12 +106,12 @@ if ( defined( 'MW_CONFIG_CALLBACK' ) ) { if ( $maintenance->getDbType() === Maintenance::DB_ADMIN && is_readable( "$IP/AdminSettings.php" ) ) { - require( "$IP/AdminSettings.php" ); + require( MWInit::interpretedPath( 'AdminSettings.php' ) ); } $maintenance->finalSetup(); // Some last includes -require_once( "$IP/includes/Setup.php" ); -require_once( "$IP/maintenance/install-utils.inc" ); +require_once( MWInit::compiledPath( 'includes/Setup.php' ) ); +require_once( MWInit::compiledPath( 'maintenance/install-utils.inc' ) ); // Much much faster startup than creating a title object $wgTitle = null; diff --git a/maintenance/eval.php b/maintenance/eval.php index 9229ae2421..74143b5dd4 100644 --- a/maintenance/eval.php +++ b/maintenance/eval.php @@ -74,7 +74,7 @@ while ( ( $line = Maintenance::readconsole() ) !== false ) { readline_write_history( $historyFile ); } $val = eval( $line . ";" ); - if ( is_null( $val ) ) { + if ( wfIsHipHop() || is_null( $val ) ) { echo "\n"; } elseif ( is_string( $val ) || is_numeric( $val ) ) { echo "$val\n"; diff --git a/maintenance/hiphop/file-list.small b/maintenance/hiphop/file-list.small index 84acdda147..0f7a8ba0fe 100644 --- a/maintenance/hiphop/file-list.small +++ b/maintenance/hiphop/file-list.small @@ -158,6 +158,7 @@ includes/filerepo/NullRepo.php includes/filerepo/OldLocalFile.php includes/filerepo/RepoGroup.php includes/filerepo/UnregisteredLocalFile.php +includes/installer/Installer.php includes/job/DoubleRedirectJob.php includes/job/EmaillingJob.php includes/job/EnotifNotifyJob.php @@ -280,6 +281,8 @@ profileinfo.php redirect.php resources/Resources.php serialized/serialize.php +skins/MonoBook.deps.php +skins/MonoBook.php skins/Vector.deps.php skins/Vector.php thumb.php -- 2.20.1