X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FGlobalFunctions.php;h=04738d66969717cd0598ab427ae36c9d7bd7956f;hb=ee1f2b3c31e9b187334a013b8acbeed764082d6b;hp=e5f6f4cadd98d2b2d4b708c83595b40ebadd1672;hpb=28de6d99d21c90d554345f64650d95d62bbc8fea;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index e5f6f4cadd..04738d6696 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -84,10 +84,11 @@ if ( !function_exists( 'mb_substr' ) ) { * 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') + * @param $quote_style the quote style to pass as the second argument to + * get_html_translation_table() + * @param string $charset Encoding set to use (default 'UTF-8') */ -function do_html_entity_decode( $string, $quote_style=ENT_COMPAT, $charset='ISO-8859-1' ) { +function do_html_entity_decode( $string, $quote_style=ENT_COMPAT, $charset='UTF-8' ) { $fname = 'do_html_entity_decode'; wfProfileIn( $fname ); @@ -161,7 +162,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; } @@ -183,23 +184,26 @@ 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. + * 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 'Ӓ'. + * @return string An UTF-8 character if the codepoint is in the BMP and + * $codepoint if it isn't; */ 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); - + 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;"; } @@ -207,15 +211,16 @@ function wfUtf8Sequence( $codepoint ) { /** * Converts numeric character entities to UTF-8 * + * @todo Do named entities + * * @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-9]+);/e', 'wfUtf8Sequence($1)', $string ); $string = preg_replace ( '/([0-9a-f]+);/ie', 'wfUtf8Sequence(0x$1)', $string ); - # Should also do named entities here return $string; } @@ -264,7 +269,10 @@ 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 ); } } @@ -302,7 +310,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, @@ -330,7 +338,9 @@ function wfReadOnly() { /** - * Get a message from anywhere, for the UI elements + * Get a message from anywhere, for the current user language + * + * @param string */ function wfMsg( $key ) { $args = func_get_args(); @@ -339,7 +349,7 @@ function wfMsg( $key ) { } /** - * Get a message from anywhere, for the content + * Get a message from anywhere, for the current global language */ function wfMsgForContent( $key ) { global $wgForceUIMsgAsContentMsg; @@ -390,8 +400,7 @@ function wfMsgReal( $key, $args, $useDB, $forContent=false ) { if( is_object( $wgMessageCache ) ) { $message = $wgMessageCache->get( $key, $useDB, $forContent ); - } - else { + } else { if( $forContent ) { $lang = &$wgContLang; } else { @@ -399,7 +408,12 @@ function wfMsgReal( $key, $args, $useDB, $forContent=false ) { } wfSuppressWarnings(); - $message = $lang->getMessage( $key ); + + if( is_object( $lang ) ) { + $message = $lang->getMessage( $key ); + } else { + $message = ''; + } wfRestoreWarnings(); if(!$message) $message = Language::getMessage($key); @@ -407,6 +421,10 @@ function wfMsgReal( $key, $args, $useDB, $forContent=false ) { $message = $wgParser->transformMsg($message, $wgMsgParserOptions); } } + + # Fix windows line-endings + # Some messages are split with explode("\n", $msg) + $message = str_replace( "\r", '', $message ); # Replace arguments if( count( $args ) ) { @@ -463,32 +481,62 @@ 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 ) { + } + die( $msg ); +} + +function wfBacktrace() { + global $wgCommandLineMode; + if ( !function_exists( 'debug_backtrace' ) ) { + return false; + } + + if ( $wgCommandLineMode ) { + $msg = ''; + } else { + $msg = "" . + htmlspecialchars( $desc ) . + "
\n"; } /** @@ -947,25 +1022,6 @@ function wfTimestampNow() { return wfTimestamp( TS_MW, time() ); } -/** - * Convenience function; adds seconds to a MediaWiki timestamp. - * @return string - */ -function wfTimestampPlus ( $ts, $moreseconds ) { - return gmdate( 'YmdHis', wfTimestamp( TS_UNIX, $ts ) + $moreseconds ); -} - -/** - * 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 */ @@ -997,21 +1053,53 @@ 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); + + +/** + * @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], @@ -1019,29 +1107,48 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) { } elseif (preg_match("/^(\d{1,13})$/",$ts,$datearray)) { # TS_UNIX $uts=$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'; + 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() { @@ -1052,4 +1159,154 @@ function wfIsWindows() { } } +/** + * 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 = ''; + # Allow individual wikis to turn it off + if ( $notice == '-' ) { + $notice = ''; + } else { + if ($notice == '') { + $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 bool $contents NULL to make an open tag only; '' for a contentless closed tag (default) + * @return string + */ +function wfElement( $element, $attribs = array(), $contents = '') { + $out = '<' . $element; + 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 bool $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 ); + } + return wfElement( $element, $attribs, UtfNormal::cleanUp( $contents ) ); +} + +/** 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( 'TMPDIR' ); + 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; +} + ?>