X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FGlobalFunctions.php;h=ddb39ffb919570b2036fd3b81e26663be36bff82;hb=c0401123da9d021f4cfe2244bbd349bddeb02be8;hp=af18dfcd83d5d0e947414218575646c6b05b661c;hpb=32c223e2a137eaf57e779796f507542cacdc51a3;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index af18dfcd83..ddb39ffb91 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -1,5 +1,4 @@ = 3) { - $end = func_get_arg(2); - return join("",array_slice($ar[0],$start,$end)); - } else { - return join("",array_slice($ar[0],$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 ) ); } } } -/** - * 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; - if( !isset( $trans ) ) { - $trans = array_flip( get_html_translation_table( HTML_ENTITIES, $quote_style ) ); - # Assumes $charset will always be the same through a run, and only understands - # utf-8 or default. 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 ); - } +if( !function_exists( 'floatval' ) ) { + /** + * First defined in PHP 4.2.0 + * @param mixed $var; + * @return float + */ + function floatval( $var ) { + return (float)$var; } - return strtr( $string, $trans ); } - /** * Where as we got a random seed * @var bool $wgTotalViews @@ -126,42 +113,19 @@ function wfSeedRandom() { } /** - * Generates a URL from a URL-encoded title and a query string - * Title::getLocalURL() is preferred in most cases + * Get a random decimal value between 0 and 1, in a way + * not likely to give duplicate values for any realistic + * number of articles. * - * @param string $a URL encoded title - * @param string $q URL (default '') - */ -function wfLocalUrl( $a, $q = '' ) { - global $wgServer, $wgScript, $wgArticlePath; - - $a = str_replace( ' ', '_', $a ); - - if ( '' == $a ) { - if( '' == $q ) { - $a = $wgScript; - } else { - $a = $wgScript.'?'.$q; - } - } else if ( '' == $q ) { - $a = str_replace( '$1', $a, $wgArticlePath ); - } else if ($wgScript != '' ) { - $a = "{$wgScript}?title={$a}&{$q}"; - } else { //XXX hackish solution for toplevel wikis - $a = "/{$a}?{$q}"; - } - return $a; -} - -/** - * @todo document - * @param string $a URL encoded title - * @param string $q URL (default '') + * @return string */ -function wfLocalUrlE( $a, $q = '' ) -{ - return htmlspecialchars( wfLocalUrl( $a, $q ) ); - # die( "Call to obsolete function wfLocalUrlE()" ); +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() * $max + mt_rand()) + / $max / $max, 12, '.', '' ); + return $rand; } /** @@ -180,95 +144,17 @@ function wfUrlencode ( $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) + * Sends a line to the debug log if enabled or, optionally, to a comment in output. + * In normal operation this is a NOP. * - * @param array $matches + * Controlling globals: + * $wgDebugLogFile - points to the log file + * $wgProfileOnly - if set, normal debug messages will not be recorded. + * $wgDebugRawPage - if false, 'action=raw' hits will not result in debug output. + * $wgDebugComments - if on, some debug items may appear in comments in the HTML output. * - */ -function wfUtf8Entity( $matches ) { - $char = $matches[0]; - # Find the length - $z = ord( $char{0} ); - if ( $z & 0x80 ) { - $length = 0; - while ( $z & 0x80 ) { - $length++; - $z <<= 1; - } - } else { - $length = 1; - } - - if ( $length != strlen( $char ) ) { - return ''; - } - if ( $length == 1 ) { - return $char; - } - - # Mask off the length-determining bits and shift back to the original location - $z &= 0xff; - $z >>= $length; - - # Add in the free bits from subsequent bytes - for ( $i=1; $i<$length; $i++ ) { - $z <<= 6; - $z |= ord( $char{$i} ) & 0x3f; - } - - # Make entity - return "$z;"; -} - -/** - * 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 ); -} - -/** - * @todo document + * @param string $text + * @param bool $logonly Set true to avoid appearing in HTML when $wgDebugComments is set */ function wfDebug( $text, $logonly = false ) { global $wgOut, $wgDebugLogFile, $wgDebugComments, $wgProfileOnly, $wgDebugRawPage; @@ -282,7 +168,26 @@ 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 + */ +function wfDebugLog( $logGroup, $text ) { + global $wgDebugLogGroups, $wgDBname; + if( $text{strlen( $text ) - 1} != "\n" ) $text .= "\n"; + if( isset( $wgDebugLogGroups[$logGroup] ) ) { + @error_log( "$wgDBname: $text", 3, $wgDebugLogGroups[$logGroup] ); + } else { + wfDebug( $text, true ); } } @@ -320,7 +225,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, @@ -338,57 +243,49 @@ 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; } -/** - * Keys strings for replacement - * @global array $wgReplacementKeys - */ -$wgReplacementKeys = array( '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9' ); /** - * Get a message from anywhere, for the UI elements + * Get a message from anywhere, for the current user language + * + * @param string */ function wfMsg( $key ) { - global $wgRequest; - - if ( $wgRequest->getVal( 'debugmsg' ) ) { - if ( $key == 'linktrail' /* a special case where we want to return something specific */ ) - return "/^()(.*)$/sD"; - else - return $key; - } $args = func_get_args(); - if ( count( $args ) ) { - array_shift( $args ); - } + array_shift( $args ); return wfMsgReal( $key, $args, true ); } /** - * Get a message from anywhere, for the content + * Get a message from anywhere, for the current global language */ function wfMsgForContent( $key ) { - global $wgRequest; - if ( $wgRequest->getVal( 'debugmsg' ) ) { - if ( $key == 'linktrail' /* a special case where we want to return something specific */ ) - return "/^()(.*)$/sD"; - else - return $key; - } + global $wgForceUIMsgAsContentMsg; $args = func_get_args(); - if ( count( $args ) ) { - array_shift( $args ); - } - return wfMsgReal( $key, $args, true, true ); - - + array_shift( $args ); + $forcontent = true; + if( is_array( $wgForceUIMsgAsContentMsg ) && + in_array( $key, $wgForceUIMsgAsContentMsg ) ) + $forcontent = false; + return wfMsgReal( $key, $args, true, $forcontent ); } /** @@ -396,9 +293,7 @@ function wfMsgForContent( $key ) { */ function wfMsgNoDB( $key ) { $args = func_get_args(); - if ( count( $args ) ) { - array_shift( $args ); - } + array_shift( $args ); return wfMsgReal( $key, $args, false ); } @@ -406,12 +301,14 @@ function wfMsgNoDB( $key ) { * Get a message from the language file, for the content */ function wfMsgNoDBForContent( $key ) { - + global $wgForceUIMsgAsContentMsg; $args = func_get_args(); - if ( count( $args ) ) { - array_shift( $args ); - } - return wfMsgReal( $key, $args, false, true ); + array_shift( $args ); + $forcontent = true; + if( is_array( $wgForceUIMsgAsContentMsg ) && + in_array( $key, $wgForceUIMsgAsContentMsg ) ) + $forcontent = false; + return wfMsgReal( $key, $args, false, $forcontent ); } @@ -419,42 +316,110 @@ function wfMsgNoDBForContent( $key ) { * Really get a message */ function wfMsgReal( $key, $args, $useDB, $forContent=false ) { - global $wgReplacementKeys, $wgParser, $wgMsgParserOptions; - - if($forContent) { - global $wgMessageCache, $wgContLang; - $cache = &$wgMessageCache; - $lang = &$wgContLang; - } - else { - global $wgLang; - $cache = false; - $lang = &$wgLang; - } - - $fname = 'wfMsg'; + $fname = 'wfMsgReal'; wfProfileIn( $fname ); - if ( is_object($cache) ) { - $message = $cache->get( $key, $useDB ); - } elseif (is_object($lang)) { - $message = $lang->getMessage( $key ); + + $message = wfMsgGetKey( $key, $useDB, $forContent ); + $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 ) { + global $wgParser, $wgMsgParserOptions; + global $wgContLang, $wgLanguageCode; + global $wgMessageCache, $wgLang; + + if( is_object( $wgMessageCache ) ) { + $message = $wgMessageCache->get( $key, $useDB, $forContent ); + } else { + if( $forContent ) { + $lang = &$wgContLang; + } else { + $lang = &$wgLang; + } + + wfSuppressWarnings(); + + if( is_object( $lang ) ) { + $message = $lang->getMessage( $key ); + } else { + $message = ''; + } + wfRestoreWarnings(); + if(!$message) + $message = Language::getMessage($key); if(strstr($message, '{{' ) !== false) { $message = $wgParser->transformMsg($message, $wgMsgParserOptions); } - } else { - wfDebug( "No language object when getting $key\n" ); - $message = "<$key>"; } + 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 ) { + static $replacementKeys = array( '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9' ); + + # Fix windows line-endings + # Some messages are split with explode("\n", $msg) + $message = str_replace( "\r", '', $message ); # Replace arguments if( count( $args ) ) { - $message = str_replace( $wgReplacementKeys, $args, $message ); + $message = str_replace( $replacementKeys, $args, $message ); } - 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. @@ -501,32 +466,63 @@ 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:
\nBacktrace:
\n$backtrace"; } - $backtrace = debug_backtrace(); - foreach( $backtrace as $call ) { + } + echo $msg; + die( -1 ); +} + +function wfBacktrace() { + global $wgCommandLineMode; + if ( !function_exists( 'debug_backtrace' ) ) { + return false; + } + + if ( $wgCommandLineMode ) { + $msg = ''; + } else { + $msg = "" . + htmlspecialchars( $desc ) . + "
\n"; } /** @@ -882,8 +919,16 @@ function wfAcceptToPrefs( $accept, $def = '*/*' ) { } /** - * @todo document - * @private + * Checks if a given MIME type matches any of the keys in the given + * array. Basic wildcards are accepted in the array keys. + * + * Returns the matching MIME type (or wildcard) if a match, otherwise + * NULL if no match. + * + * @param string $type + * @param array $avail + * @return string + * @access private */ function mimeTypeMatch( $type, $avail ) { if( array_key_exists($type, $avail) ) { @@ -901,6 +946,15 @@ function mimeTypeMatch( $type, $avail ) { } /** + * Returns the 'best' match between a client's requested internet media types + * and the server's list of available types. Each list should be an associative + * array of type to preference (preference is a float between 0.0 and 1.0). + * Wildcards in the types are acceptable. + * + * @param array $cprefs Client's acceptable type list + * @param array $sprefs Server's offered types + * @return string + * * @todo FIXME: doesn't handle params like 'text/plain; charset=UTF-8' * XXX: generalize to negotiate other stuff */ @@ -944,49 +998,20 @@ 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 ) { return array_flip( array_intersect( array_flip( $a ), array_keys( $b ) ) ); } - -/** - * Ideally we'd be using actual time fields in the db - * @todo fixme - */ -function wfTimestamp2Unix( $ts ) { - return gmmktime( ( (int)substr( $ts, 8, 2) ), - (int)substr( $ts, 10, 2 ), (int)substr( $ts, 12, 2 ), - (int)substr( $ts, 4, 2 ), (int)substr( $ts, 6, 2 ), - (int)substr( $ts, 0, 4 ) ); -} - /** - * @todo document - */ -function wfUnix2Timestamp( $unixtime ) { - return gmdate( 'YmdHis', $unixtime ); -} - -/** - * @todo document + * Convenience function; returns MediaWiki timestamp for the present time. + * @return string */ function wfTimestampNow() { # return NOW - return gmdate( 'YmdHis' ); -} - -/** - * Sorting hack for MySQL 3, which doesn't use index sorts for DESC - */ -function wfInvertTimestamp( $ts ) { - return strtr( - $ts, - '0123456789', - '9876543210' - ); + return wfTimestamp( TS_MW, time() ); } /** @@ -1020,21 +1045,57 @@ 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); + +/** + * 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', 4); + +/** + * Oracle format time. + */ +define('TS_ORACLE', 5); + +/** + * @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)) { + 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], @@ -1042,37 +1103,310 @@ 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))); + } 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 ); + // 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 ); +} + +/** + * 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; + $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 = ''; + $success = false; + 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 wfNoMsg( $msg, $wfMsgOut ) { + return $wfMsgOut === "<$msg>"; +} ?>