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 ( '/([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 .= "\nBacktrace:
\n" . + htmlspecialchars( $desc ) . + "
\n"; } /** @@ -947,7 +1099,7 @@ function wfNegotiateType( $cprefs, $sprefs ) { * Array lookup * Returns an array where the values in the first array are replaced by the * values in the second array with the corresponding keys - * + * * @return array */ function wfArrayLookup( $a, $b ) { @@ -963,17 +1115,6 @@ function wfTimestampNow() { return wfTimestamp( TS_MW, time() ); } -/** - * Sorting hack for MySQL 3, which doesn't use index sorts for DESC - */ -function wfInvertTimestamp( $ts ) { - return strtr( - $ts, - '0123456789', - '9876543210' - ); -} - /** * Reference-counted warning suppression */ @@ -983,7 +1124,7 @@ function wfSuppressWarnings( $end = false ) { if ( $end ) { if ( $suppressCount ) { - $suppressCount --; + --$suppressCount; if ( !$suppressCount ) { error_reporting( $originalLevel ); } @@ -992,7 +1133,7 @@ function wfSuppressWarnings( $end = false ) { if ( !$suppressCount ) { $originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE ) ); } - $suppressCount++; + ++$suppressCount; } } @@ -1005,21 +1146,65 @@ function wfRestoreWarnings() { # Autodetect, convert and provide timestamps of various types -/** Standard unix timestamp (number of seconds since 1 Jan 1970) */ -define('TS_UNIX',0); -/** MediaWiki concatenated string timestamp (yyyymmddhhmmss) */ -define('TS_MW',1); -/** Standard database timestamp (yyyy-mm-dd hh:mm:ss) */ -define('TS_DB',2); +/** + * Unix time - the number of seconds since 1970-01-01 00:00:00 UTC + */ +define('TS_UNIX', 0); /** - * @todo document + * MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS) + */ +define('TS_MW', 1); + +/** + * MySQL DATETIME (YYYY-MM-DD HH:MM:SS) + */ +define('TS_DB', 2); + +/** + * RFC 2822 format, for E-mail and HTTP headers + */ +define('TS_RFC2822', 3); + +/** + * ISO 8601 format with no timezone: 1986-02-09T20:00:00Z + * + * This is used by Special:Export + */ +define('TS_ISO_8601', 4); + +/** + * An Exif timestamp (YYYY:MM:DD HH:MM:SS) + * + * @link http://exif.org/Exif2-2.PDF The Exif 2.2 spec, see page 28 for the + * DateTime tag and page 36 for the DateTimeOriginal and + * DateTimeDigitized tags. + */ +define('TS_EXIF', 5); + +/** + * Oracle format time. + */ +define('TS_ORACLE', 6); + +/** + * @param mixed $outputtype A timestamp in one of the supported formats, the + * function will autodetect which format is supplied + and act accordingly. + * @return string Time in the format specified in $outputtype */ function wfTimestamp($outputtype=TS_UNIX,$ts=0) { - if (preg_match("/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)$/",$ts,$da)) { + $uts = 0; + if ($ts==0) { + $uts=time(); + } elseif (preg_match("/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)$/",$ts,$da)) { # TS_DB $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6], (int)$da[2],(int)$da[3],(int)$da[1]); + } elseif (preg_match("/^(\d{4}):(\d\d):(\d\d) (\d\d):(\d\d):(\d\d)$/",$ts,$da)) { + # TS_EXIF + $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6], + (int)$da[2],(int)$da[3],(int)$da[1]); } elseif (preg_match("/^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/",$ts,$da)) { # TS_MW $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6], @@ -1027,37 +1212,426 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) { } elseif (preg_match("/^(\d{1,13})$/",$ts,$datearray)) { # TS_UNIX $uts=$ts; + } elseif (preg_match('/^(\d{1,2})-(...)-(\d\d(\d\d)?) (\d\d)\.(\d\d)\.(\d\d)/', $ts, $da)) { + # TS_ORACLE + $uts = strtotime(preg_replace('/(\d\d)\.(\d\d)\.(\d\d)(\.(\d+))?/', "$1:$2:$3", + str_replace("+00:00", "UTC", $ts))); + } elseif (preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/', $ts, $da)) { + # TS_ISO_8601 + $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6], + (int)$da[2],(int)$da[3],(int)$da[1]); + } else { + # Bogus value; fall back to the epoch... + wfDebug("wfTimestamp() fed bogus time value: $outputtype; $ts\n"); + $uts = 0; } - if ($ts==0) - $uts=time(); + switch($outputtype) { - case TS_UNIX: - return $uts; - break; - case TS_MW: - return gmdate( 'YmdHis', $uts ); - break; - case TS_DB: - return gmdate( 'Y-m-d H:i:s', $uts ); - break; - default: - return; + case TS_UNIX: + return $uts; + case TS_MW: + return gmdate( 'YmdHis', $uts ); + case TS_DB: + return gmdate( 'Y-m-d H:i:s', $uts ); + case TS_ISO_8601: + return gmdate( 'Y-m-d\TH:i:s\Z', $uts ); + // This shouldn't ever be used, but is included for completeness + case TS_EXIF: + return gmdate( 'Y:m:d H:i:s', $uts ); + case TS_RFC2822: + return gmdate( 'D, d M Y H:i:s', $uts ) . ' GMT'; + case TS_ORACLE: + return gmdate( 'd-M-y h.i.s A', $uts) . ' +00:00'; + default: + wfDebugDieBacktrace( 'wfTimestamp() called with illegal output type.'); + } +} + +/** + * Return a formatted timestamp, or null if input is null. + * For dealing with nullable timestamp columns in the database. + * @param int $outputtype + * @param string $ts + * @return string + */ +function wfTimestampOrNull( $outputtype = TS_UNIX, $ts = null ) { + if( is_null( $ts ) ) { + return null; + } else { + return wfTimestamp( $outputtype, $ts ); } } /** * Check where as the operating system is Windows * - * @todo document * @return bool True if it's windows, False otherwise. */ -function wfIsWindows() { - if (substr(php_uname(), 0, 7) == 'Windows') { - return true; - } else { - return false; - } -} +function wfIsWindows() { + if (substr(php_uname(), 0, 7) == 'Windows') { + return true; + } else { + return false; + } +} + +/** + * Swap two variables + */ +function swap( &$x, &$y ) { + $z = $x; + $x = $y; + $y = $z; +} + +function wfGetSiteNotice() { + global $wgSiteNotice, $wgTitle, $wgOut; + $fname = 'wfGetSiteNotice'; + wfProfileIn( $fname ); + + $notice = wfMsg( 'sitenotice' ); + if( $notice == '<sitenotice>' || $notice == '-' ) { + $notice = ''; + } + if( $notice == '' ) { + # We may also need to override a message with eg downtime info + # FIXME: make this work! + $notice = $wgSiteNotice; + } + if($notice != '-' && $notice != '') { + $specialparser = new Parser(); + $parserOutput = $specialparser->parse( $notice, $wgTitle, $wgOut->mParserOptions, false ); + $notice = $parserOutput->getText(); + } + wfProfileOut( $fname ); + return $notice; +} + +/** + * Format an XML element with given attributes and, optionally, text content. + * Element and attribute names are assumed to be ready for literal inclusion. + * Strings are assumed to not contain XML-illegal characters; special + * characters (<, >, &) are escaped but illegals are not touched. + * + * @param string $element + * @param array $attribs Name=>value pairs. Values will be escaped. + * @param string $contents NULL to make an open tag only; '' for a contentless closed tag (default) + * @return string + */ +function wfElement( $element, $attribs = null, $contents = '') { + $out = '<' . $element; + if( !is_null( $attribs ) ) { + foreach( $attribs as $name => $val ) { + $out .= ' ' . $name . '="' . htmlspecialchars( $val ) . '"'; + } + } + if( is_null( $contents ) ) { + $out .= '>'; + } else { + if( $contents == '' ) { + $out .= ' />'; + } else { + $out .= '>'; + $out .= htmlspecialchars( $contents ); + $out .= "$element>"; + } + } + return $out; +} + +/** + * Format an XML element as with wfElement(), but run text through the + * UtfNormal::cleanUp() validator first to ensure that no invalid UTF-8 + * is passed. + * + * @param string $element + * @param array $attribs Name=>value pairs. Values will be escaped. + * @param string $contents NULL to make an open tag only; '' for a contentless closed tag (default) + * @return string + */ +function wfElementClean( $element, $attribs = array(), $contents = '') { + if( $attribs ) { + $attribs = array_map( array( 'UtfNormal', 'cleanUp' ), $attribs ); + } + if( $contents ) { + $contents = UtfNormal::cleanUp( $contents ); + } + return wfElement( $element, $attribs, $contents ); +} + +// Shortcuts +function wfOpenElement( $element ) { return "<$element>"; } +function wfCloseElement( $element ) { return "$element>"; } + +/** + * Create a namespace selector + * + * @param mixed $selected The namespace which should be selected, default '' + * @param string $allnamespaces Value of a special item denoting all namespaces. Null to not include (default) + * @return Html string containing the namespace selector + */ +function &HTMLnamespaceselector($selected = '', $allnamespaces = null) { + global $wgContLang; + if( $selected !== '' ) { + if( is_null( $selected ) ) { + // No namespace selected; let exact match work without hitting Main + $selected = ''; + } else { + // Let input be numeric strings without breaking the empty match. + $selected = intval( $selected ); + } + } + $s = "\n"; + return $s; +} + +/** Global singleton instance of MimeMagic. This is initialized on demand, +* please always use the wfGetMimeMagic() function to get the instance. +* +* @private +*/ +$wgMimeMagic= NULL; + +/** Factory functions for the global MimeMagic object. +* This function always returns the same singleton instance of MimeMagic. +* That objects will be instantiated on the first call to this function. +* If needed, the MimeMagic.php file is automatically included by this function. +* @return MimeMagic the global MimeMagic objects. +*/ +function &wfGetMimeMagic() { + global $wgMimeMagic; + + if (!is_null($wgMimeMagic)) { + return $wgMimeMagic; + } + + if (!class_exists("MimeMagic")) { + #include on demand + require_once("MimeMagic.php"); + } + + $wgMimeMagic= new MimeMagic(); + + return $wgMimeMagic; +} + + +/** + * Tries to get the system directory for temporary files. + * The TMPDIR, TMP, and TEMP environment variables are checked in sequence, + * and if none are set /tmp is returned as the generic Unix default. + * + * NOTE: When possible, use the tempfile() function to create temporary + * files to avoid race conditions on file creation, etc. + * + * @return string + */ +function wfTempDir() { + foreach( array( 'TMPDIR', 'TMP', 'TEMP' ) as $var ) { + $tmp = getenv( $var ); + if( $tmp && file_exists( $tmp ) && is_dir( $tmp ) && is_writable( $tmp ) ) { + return $tmp; + } + } + # Hope this is Unix of some kind! + return '/tmp'; +} + +/** + * Make directory, and make all parent directories if they don't exist + */ +function wfMkdirParents( $fullDir, $mode ) { + $parts = explode( '/', $fullDir ); + $path = ''; + + foreach ( $parts as $dir ) { + $path .= $dir . '/'; + if ( !is_dir( $path ) ) { + if ( !mkdir( $path, $mode ) ) { + return false; + } + } + } + return true; +} + +/** + * Increment a statistics counter + */ +function wfIncrStats( $key ) { + global $wgDBname, $wgMemc; + $key = "$wgDBname:stats:$key"; + if ( is_null( $wgMemc->incr( $key ) ) ) { + $wgMemc->add( $key, 1 ); + } +} + +/** + * @param mixed $nr The number to format + * @param int $acc The number of digits after the decimal point, default 2 + * @param bool $round Whether or not to round the value, default true + * @return float + */ +function wfPercent( $nr, $acc = 2, $round = true ) { + $ret = sprintf( "%.${acc}f", $nr ); + return $round ? round( $ret, $acc ) . '%' : "$ret%"; +} + +/** + * Encrypt a username/password. + * + * @param string $userid ID of the user + * @param string $password Password of the user + * @return string Hashed password + */ +function wfEncryptPassword( $userid, $password ) { + global $wgPasswordSalt; + $p = md5( $password); + + if($wgPasswordSalt) + return md5( "{$userid}-{$p}" ); + else + return $p; +} + +/** + * Appends to second array if $value differs from that in $default + */ +function wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed ) { + if ( is_null( $changed ) ) { + wfDebugDieBacktrace('GlobalFunctions::wfAppendToArrayIfNotDefault got null'); + } + if ( $default[$key] !== $value ) { + $changed[$key] = $value; + } +} + +/** + * Since wfMsg() and co suck, they don't return false if the message key they + * looked up didn't exist but a XHTML string, this function checks for the + * nonexistance of messages by looking at wfMsg() output + * + * @param $msg The message key looked up + * @param $wfMsgOut The output of wfMsg*() + * @return bool + */ +function wfEmptyMsg( $msg, $wfMsgOut ) { + return $wfMsgOut === "<$msg>"; +} + +/** + * Find out whether or not a mixed variable exists in a string + * + * @param mixed needle + * @param string haystack + * @return bool + */ +function in_string( $needle, $str ) { + return strpos( $str, $needle ) !== false; +} + +/** + * Returns a regular expression of url protocols + * + * @return string + */ +function wfUrlProtocols() { + global $wgUrlProtocols; + + $x = array(); + foreach ($wgUrlProtocols as $protocol) + $x[] = preg_quote( $protocol, '/' ); + + return implode( '|', $x ); +} + +/** + * Check if a string is well-formed XML. + * Must include the surrounding tag. + * + * @param string $text + * @return bool + * + * @todo Error position reporting return + */ +function wfIsWellFormedXml( $text ) { + $parser = xml_parser_create( "UTF-8" ); + + # case folding violates XML standard, turn it off + xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false ); + + if( !xml_parse( $parser, $text, true ) ) { + $err = xml_error_string( xml_get_error_code( $parser ) ); + $position = xml_get_current_byte_index( $parser ); + //$fragment = $this->extractFragment( $html, $position ); + //$this->mXmlError = "$err at byte $position:\n$fragment"; + xml_parser_free( $parser ); + return false; + } + xml_parser_free( $parser ); + return true; +} + +/** + * Check if a string is a well-formed XML fragment. + * Wraps fragment in an bit and doctype, so it can be a fragment + * and can use HTML named entities. + * + * @param string $text + * @return bool + */ +function wfIsWellFormedXmlFragment( $text ) { + $html = + '' . + '' . + $text . + ''; + return wfIsWellFormedXml( $html ); +} + +/** + * shell_exec() with time and memory limits mirrored from the PHP configuration, + * if supported. + */ +function wfShellExec( $cmd ) +{ + global $IP; + + if ( php_uname( 's' ) == 'Linux' ) { + $time = ini_get( 'max_execution_time' ); + $mem = ini_get( 'memory_limit' ); + if( preg_match( '/^([0-9]+)[Mm]$/', trim( $mem ), $m ) ) { + $mem = intval( $m[1] * (1024*1024) ); + } + if ( $time > 0 && $mem > 0 ) { + $script = "$IP/bin/ulimit.sh"; + if ( is_executable( $script ) ) { + $memKB = intval( $mem / 1024 ); + $cmd = escapeshellarg( $script ) . " $time $memKB $cmd"; + } + } + } + return shell_exec( $cmd ); +} ?>