X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FGlobalFunctions.php;h=57bd13281ce713f82efe779879dbd10ea19c075c;hb=40745cfef875263d13f29cea01b501655d218f16;hp=0ab7818c30d5bf9ef742c529685f17cbf6870861;hpb=4b42f18b66e843f362e5e159d95fee9d2c26ef9c;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 0ab7818c30..57bd13281c 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -8,7 +8,7 @@ /** * Some globals and requires needed */ - + /** * Total number of articles * @global integer $wgNumberOfArticles @@ -67,63 +67,29 @@ if( !function_exists('is_a') ) { # UTF-8 substr function based on a PHP manual comment if ( !function_exists( 'mb_substr' ) ) { - function mb_substr( $str, $start ) { + function mb_substr( $str, $start ) { preg_match_all( '/./us', $str, $ar ); if( func_num_args() >= 3 ) { - $end = func_get_arg( 2 ); - return join( '', array_slice( $ar[0], $start, $end ) ); - } else { - return join( '', array_slice( $ar[0], $start ) ); + $end = func_get_arg( 2 ); + return join( '', array_slice( $ar[0], $start, $end ) ); + } else { + return join( '', array_slice( $ar[0], $start ) ); } } } -/** - * html_entity_decode exists in PHP 4.3.0+ but is FATALLY BROKEN even then, - * with no UTF-8 support. - * - * @param string $string String having html entities - * @param $quote_style - * @param string $charset Encoding set to use (default 'ISO-8859-1') - */ -function do_html_entity_decode( $string, $quote_style=ENT_COMPAT, $charset='ISO-8859-1' ) { - static $trans; - static $savedCharset; - static $regexp; - if( !isset( $trans ) || $savedCharset != $charset ) { - $trans = array_flip( get_html_translation_table( HTML_ENTITIES, $quote_style ) ); - $savedCharset = $charset; - - # Note - mixing latin1 named entities and unicode numbered - # ones will result in a bad link. - if( strcasecmp( 'utf-8', $charset ) == 0 ) { - $trans = array_map( 'utf8_encode', $trans ); - } - - /** - * Most links will _not_ contain these fun guys, - * and on long pages with many links we can get - * called a lot. - * - * A regular expression search is faster than - * a strtr or str_replace with a hundred-ish - * entries, though it may be slower to actually - * replace things. - * - * They all look like '&xxxx;'... - */ - foreach( $trans as $key => $val ) { - $snip[] = substr( $key, 1, -1 ); - } - $regexp = '/(&(?:' . implode( '|', $snip ) . ');)/e'; +if( !function_exists( 'floatval' ) ) { + /** + * First defined in PHP 4.2.0 + * @param mixed $var; + * @return float + */ + function floatval( $var ) { + return (float)$var; } - - $out = preg_replace( $regexp, '$trans["$1"]', $string ); - return $out; } - /** * Where as we got a random seed * @var bool $wgTotalViews @@ -157,7 +123,7 @@ function wfRandom() { # The maximum random value is "only" 2^31-1, so get two random # values to reduce the chance of dupes $max = mt_getrandmax(); - $rand = number_format( mt_rand() * mt_rand() + $rand = number_format( (mt_rand() * $max + mt_rand()) / $max / $max, 12, '.', '' ); return $rand; } @@ -177,64 +143,6 @@ function wfUrlencode ( $s ) { return $s; } -/** - * Return the UTF-8 sequence for a given Unicode code point. - * Currently doesn't work for values outside the Basic Multilingual Plane. - * - * @param string $codepoint UTF-8 code point. - * @return string HTML UTF-8 Entitie such as 'Ӓ'. - */ -function wfUtf8Sequence( $codepoint ) { - if($codepoint < 0x80) return chr($codepoint); - if($codepoint < 0x800) return chr($codepoint >> 6 & 0x3f | 0xc0) . - chr($codepoint & 0x3f | 0x80); - if($codepoint < 0x10000) return chr($codepoint >> 12 & 0x0f | 0xe0) . - chr($codepoint >> 6 & 0x3f | 0x80) . - chr($codepoint & 0x3f | 0x80); - if($codepoint < 0x110000) return chr($codepoint >> 18 & 0x07 | 0xf0) . - chr($codepoint >> 12 & 0x3f | 0x80) . - chr($codepoint >> 6 & 0x3f | 0x80) . - chr($codepoint & 0x3f | 0x80); - - # There should be no assigned code points outside this range, but... - return "&#$codepoint;"; -} - -/** - * Converts numeric character entities to UTF-8 - * - * @param string $string String to convert. - * @return string Converted string. - */ -function wfMungeToUtf8( $string ) { - global $wgInputEncoding; # This is debatable - #$string = iconv($wgInputEncoding, "UTF-8", $string); - $string = preg_replace ( '/&#([0-9]+);/e', 'wfUtf8Sequence($1)', $string ); - $string = preg_replace ( '/&#x([0-9a-f]+);/ie', 'wfUtf8Sequence(0x$1)', $string ); - # Should also do named entities here - return $string; -} - -/** - * Converts a single UTF-8 character into the corresponding HTML character - * entity (for use with preg_replace_callback) - * - * @param array $matches - * - */ -function wfUtf8Entity( $matches ) { - $codepoint = utf8ToCodepoint( $matches[0] ); - return "&#$codepoint;"; -} - -/** - * Converts all multi-byte characters in a UTF-8 string into the appropriate - * character entity - */ -function wfUtf8ToHTML($string) { - return preg_replace_callback( '/[\\xc0-\\xfd][\\x80-\\xbf]*/', 'wfUtf8Entity', $string ); -} - /** * Sends a line to the debug log if enabled or, optionally, to a comment in output. * In normal operation this is a NOP. @@ -260,7 +168,29 @@ function wfDebug( $text, $logonly = false ) { $wgOut->debug( $text ); } if ( '' != $wgDebugLogFile && !$wgProfileOnly ) { - error_log( $text, 3, $wgDebugLogFile ); + # Strip unprintables; they can switch terminal modes when binary data + # gets dumped, which is pretty annoying. + $text = preg_replace( '![\x00-\x08\x0b\x0c\x0e-\x1f]!', ' ', $text ); + @error_log( $text, 3, $wgDebugLogFile ); + } +} + +/** + * Send a line to a supplementary debug log file, if configured, or main debug log if not. + * $wgDebugLogGroups[$logGroup] should be set to a filename to send to a separate log. + * + * @param string $logGroup + * @param string $text + * @param bool $public Whether to log the event in the public log if no private + * log file is specified, (default true) + */ +function wfDebugLog( $logGroup, $text, $public = true ) { + global $wgDebugLogGroups, $wgDBname; + if( $text{strlen( $text ) - 1} != "\n" ) $text .= "\n"; + if( isset( $wgDebugLogGroups[$logGroup] ) ) { + @error_log( "$wgDBname: $text", 3, $wgDebugLogGroups[$logGroup] ); + } else if ( $public === true ) { + wfDebug( $text, true ); } } @@ -271,7 +201,8 @@ function wfDebug( $text, $logonly = false ) { function wfLogDBError( $text ) { global $wgDBerrorLog; if ( $wgDBerrorLog ) { - $text = date('D M j G:i:s T Y') . "\t".$text; + $host = trim(`hostname`); + $text = date('D M j G:i:s T Y') . "\t$host\t".$text; error_log( $text, 3, $wgDBerrorLog ); } } @@ -298,7 +229,7 @@ function logProfilingData() { $forward .= ' from ' . $_SERVER['HTTP_FROM']; if( $forward ) $forward = "\t(proxied via {$_SERVER['REMOTE_ADDR']}{$forward})"; - if($wgUser->getId() == 0) + if( $wgUser->isAnon() ) $forward .= ' anon'; $log = sprintf( "%s\t%04.3f\t%s\n", gmdate( 'YmdHis' ), $elapsed, @@ -316,17 +247,39 @@ function logProfilingData() { * @return bool */ function wfReadOnly() { - global $wgReadOnlyFile; + global $wgReadOnlyFile, $wgReadOnly; + if ( $wgReadOnly ) { + return true; + } if ( '' == $wgReadOnlyFile ) { return false; } - return is_file( $wgReadOnlyFile ); + + // Set $wgReadOnly and unset $wgReadOnlyFile, for faster access next time + if ( is_file( $wgReadOnlyFile ) ) { + $wgReadOnly = file_get_contents( $wgReadOnlyFile ); + } else { + $wgReadOnly = false; + } + $wgReadOnlyFile = ''; + return $wgReadOnly; } /** - * Get a message from anywhere, for the UI elements + * Get a message from anywhere, for the current user language. + * + * Use wfMsgForContent() instead if the message should NOT + * change depending on the user preferences. + * + * Note that the message may contain HTML, and is therefore + * not safe for insertion anywhere. Some functions such as + * addWikiText will do the escaping for you. Use wfMsgHtml() + * if you need an escaped message. + * + * @param string lookup key for the message, usually + * defined in languages/Language.php */ function wfMsg( $key ) { $args = func_get_args(); @@ -335,12 +288,59 @@ function wfMsg( $key ) { } /** - * Get a message from anywhere, for the content + * Same as above except doesn't transform the message + */ +function wfMsgNoTrans( $key ) { + $args = func_get_args(); + array_shift( $args ); + return wfMsgReal( $key, $args, true, false ); +} + +/** + * Get a message from anywhere, for the current global language + * set with $wgLanguageCode. + * + * Use this if the message should NOT change dependent on the + * language set in the user's preferences. This is the case for + * most text written into logs, as well as link targets (such as + * the name of the copyright policy page). Link titles, on the + * other hand, should be shown in the UI language. + * + * Note that MediaWiki allows users to change the user interface + * language in their preferences, but a single installation + * typically only contains content in one language. + * + * Be wary of this distinction: If you use wfMsg() where you should + * use wfMsgForContent(), a user of the software may have to + * customize over 70 messages in order to, e.g., fix a link in every + * possible language. + * + * @param string lookup key for the message, usually + * defined in languages/Language.php */ function wfMsgForContent( $key ) { + global $wgForceUIMsgAsContentMsg; + $args = func_get_args(); + array_shift( $args ); + $forcontent = true; + if( is_array( $wgForceUIMsgAsContentMsg ) && + in_array( $key, $wgForceUIMsgAsContentMsg ) ) + $forcontent = false; + return wfMsgReal( $key, $args, true, $forcontent ); +} + +/** + * Same as above except doesn't transform the message + */ +function wfMsgForContentNoTrans( $key ) { + global $wgForceUIMsgAsContentMsg; $args = func_get_args(); array_shift( $args ); - return wfMsgReal( $key, $args, true, true ); + $forcontent = true; + if( is_array( $wgForceUIMsgAsContentMsg ) && + in_array( $key, $wgForceUIMsgAsContentMsg ) ) + $forcontent = false; + return wfMsgReal( $key, $args, true, $forcontent, false ); } /** @@ -356,83 +356,139 @@ function wfMsgNoDB( $key ) { * Get a message from the language file, for the content */ function wfMsgNoDBForContent( $key ) { + global $wgForceUIMsgAsContentMsg; $args = func_get_args(); array_shift( $args ); - return wfMsgReal( $key, $args, false, true ); + $forcontent = true; + if( is_array( $wgForceUIMsgAsContentMsg ) && + in_array( $key, $wgForceUIMsgAsContentMsg ) ) + $forcontent = false; + return wfMsgReal( $key, $args, false, $forcontent ); } /** * Really get a message */ -function wfMsgReal( $key, $args, $useDB, $forContent=false ) { - static $replacementKeys = array( '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9' ); +function wfMsgReal( $key, $args, $useDB, $forContent=false, $transform = true ) { + $fname = 'wfMsgReal'; + wfProfileIn( $fname ); + + $message = wfMsgGetKey( $key, $useDB, $forContent, $transform ); + $message = wfMsgReplaceArgs( $message, $args ); + wfProfileOut( $fname ); + return $message; +} + +/** + * Fetch a message string value, but don't replace any keys yet. + * @param string $key + * @param bool $useDB + * @param bool $forContent + * @return string + * @access private + */ +function wfMsgGetKey( $key, $useDB, $forContent = false, $transform = true ) { global $wgParser, $wgMsgParserOptions; global $wgContLang, $wgLanguageCode; global $wgMessageCache, $wgLang; - - $fname = 'wfMsgReal'; - wfProfileIn( $fname ); - if( $forContent ) { - /** - * Message is needed for page content, and needs - * to be consistent with the site's configured - * language. It might be part of a page title, - * or a link, or text that will go into the - * parser cache and be served back to other - * visitors. - */ - $cache = &$wgMessageCache; - $lang = &$wgContLang; + if ( is_object( $wgMessageCache ) ) + $transstat = $wgMessageCache->getTransform(); + + if( is_object( $wgMessageCache ) ) { + if ( ! $transform ) + $wgMessageCache->disableTransform(); + $message = $wgMessageCache->get( $key, $useDB, $forContent ); } else { - /** - * Message is for display purposes only. - * The user may have selected a conversion-based - * language variant or a separate user interface - * language; if so use that. - */ - if ( is_object( $wgContLang ) ) { - if( in_array( $wgLanguageCode, $wgContLang->getVariants() ) ) { - $cache = &$wgMessageCache; - $lang = &$wgLang; - } else { - $cache = false; - $lang = &$wgLang; - } + if( $forContent ) { + $lang = &$wgContLang; } else { - $cache = false; - $lang = false; + $lang = &$wgLang; } - } + wfSuppressWarnings(); - if( is_object( $cache ) ) { - $message = $cache->get( $key, $useDB, $forContent ); - } else { - if ( !is_object( $lang ) ) { - $lang = new Language; + if( is_object( $lang ) ) { + $message = $lang->getMessage( $key ); + } else { + $message = false; } - - wfSuppressWarnings(); - $message = $lang->getMessage( $key ); wfRestoreWarnings(); - if(!$message) + if($message === false) $message = Language::getMessage($key); - if(strstr($message, '{{' ) !== false) { + if ( $transform && strstr( $message, '{{' ) !== false ) { $message = $wgParser->transformMsg($message, $wgMsgParserOptions); } } - # Replace arguments - if( count( $args ) ) { - $message = str_replace( $replacementKeys, $args, $message ); + if ( is_object( $wgMessageCache ) && ! $transform ) + $wgMessageCache->setTransform( $transstat ); + + return $message; +} + +/** + * Replace message parameter keys on the given formatted output. + * + * @param string $message + * @param array $args + * @return string + * @access private + */ +function wfMsgReplaceArgs( $message, $args ) { + # Fix windows line-endings + # Some messages are split with explode("\n", $msg) + $message = str_replace( "\r", '', $message ); + + // Replace arguments + if ( count( $args ) ) + if ( is_array( $args[0] ) ) + foreach ( $args[0] as $key => $val ) + $message = str_replace( '$' . $key, $val, $message ); + else { + foreach( $args as $n => $param ) + $replacementKeys['$' . ($n + 1)] = $param; + $message = strtr( $message, $replacementKeys ); } - wfProfileOut( $fname ); + return $message; } +/** + * Return an HTML-escaped version of a message. + * Parameter replacements, if any, are done *after* the HTML-escaping, + * so parameters may contain HTML (eg links or form controls). Be sure + * to pre-escape them if you really do want plaintext, or just wrap + * the whole thing in htmlspecialchars(). + * + * @param string $key + * @param string ... parameters + * @return string + */ +function wfMsgHtml( $key ) { + $args = func_get_args(); + array_shift( $args ); + return wfMsgReplaceArgs( htmlspecialchars( wfMsgGetKey( $key, true ) ), $args ); +} +/** + * Return an HTML version of message + * Parameter replacements, if any, are done *after* parsing the wiki-text message, + * so parameters may contain HTML (eg links or form controls). Be sure + * to pre-escape them if you really do want plaintext, or just wrap + * the whole thing in htmlspecialchars(). + * + * @param string $key + * @param string ... parameters + * @return string + */ +function wfMsgWikiHtml( $key ) { + global $wgOut; + $args = func_get_args(); + array_shift( $args ); + return wfMsgReplaceArgs( $wgOut->parse( wfMsgGetKey( $key, true ), /* can't be set to false */ true ), $args ); +} /** * Just like exit() but makes a note of it. @@ -449,8 +505,8 @@ function wfAbruptExit( $error = false ){ if( function_exists( 'debug_backtrace' ) ){ // PHP >= 4.3 $bt = debug_backtrace(); for($i = 0; $i < count($bt) ; $i++){ - $file = $bt[$i]['file']; - $line = $bt[$i]['line']; + $file = isset($bt[$i]['file']) ? $bt[$i]['file'] : "unknown"; + $line = isset($bt[$i]['line']) ? $bt[$i]['line'] : "unknown"; wfDebug("WARNING: Abrupt exit in $file at line $line\n"); } } else { @@ -479,32 +535,95 @@ function wfErrorExit() { function wfDebugDieBacktrace( $msg = '' ) { global $wgCommandLineMode; - if ( function_exists( 'debug_backtrace' ) ) { + $backtrace = wfBacktrace(); + if ( $backtrace !== false ) { if ( $wgCommandLineMode ) { - $msg .= "\nBacktrace:\n"; + $msg .= "\nBacktrace:\n$backtrace"; + } else { + $msg .= "\n

Backtrace:

\n$backtrace"; + } + } + echo $msg; + echo wfReportTime()."\n"; + die( -1 ); +} + + /** + * Returns a HTML comment with the elapsed time since request. + * This method has no side effects. + * @return string + */ + function wfReportTime() { + global $wgRequestTime; + + $now = wfTime(); + list( $usec, $sec ) = explode( ' ', $wgRequestTime ); + $start = (float)$sec + (float)$usec; + $elapsed = $now - $start; + + # Use real server name if available, so we know which machine + # in a server farm generated the current page. + if ( function_exists( 'posix_uname' ) ) { + $uname = @posix_uname(); } else { - $msg .= "\n

Backtrace:

\n