diff options
Diffstat (limited to 'includes/GlobalFunctions.php')
-rw-r--r-- | includes/GlobalFunctions.php | 252 |
1 files changed, 162 insertions, 90 deletions
diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 623f9d3b..08094ca1 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -9,24 +9,16 @@ * Some globals and requires needed */ -/** - * Total number of articles - * @global integer $wgNumberOfArticles - */ +/** Total number of articles */ $wgNumberOfArticles = -1; # Unset -/** - * Total number of views - * @global integer $wgTotalViews - */ + +/** Total number of views */ $wgTotalViews = -1; -/** - * Total number of edits - * @global integer $wgTotalEdits - */ + +/** Total number of edits */ $wgTotalEdits = -1; -require_once( 'DatabaseFunctions.php' ); require_once( 'LogPage.php' ); require_once( 'normal/UtfNormalUtil.php' ); require_once( 'XmlFunctions.php' ); @@ -53,6 +45,7 @@ if( !function_exists('iconv') ) { # UTF-8 substr function based on a PHP manual comment if ( !function_exists( 'mb_substr' ) ) { function mb_substr( $str, $start ) { + $ar = array(); preg_match_all( '/./us', $str, $ar ); if( func_num_args() >= 3 ) { @@ -72,7 +65,7 @@ if ( !function_exists( 'array_diff_key' ) ) { */ function array_diff_key( $left, $right ) { $result = $left; - foreach ( $left as $key => $value ) { + foreach ( $left as $key => $unused ) { if ( isset( $right[$key] ) ) { unset( $result[$key] ); } @@ -114,7 +107,7 @@ function wfSeedRandom() { 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(); + $max = mt_getrandmax() + 1; $rand = number_format( (mt_rand() * $max + mt_rand()) / $max / $max, 12, '.', '' ); return $rand; @@ -282,6 +275,10 @@ function wfReadOnly() { * * @param $key String: lookup key for the message, usually * defined in languages/Language.php + * + * This function also takes extra optional parameters (not + * shown in the function definition), which can by used to + * insert variable text into the predefined message. */ function wfMsg( $key ) { $args = func_get_args(); @@ -295,7 +292,7 @@ function wfMsg( $key ) { function wfMsgNoTrans( $key ) { $args = func_get_args(); array_shift( $args ); - return wfMsgReal( $key, $args, true, false ); + return wfMsgReal( $key, $args, true, false, false ); } /** @@ -371,14 +368,14 @@ function wfMsgNoDBForContent( $key ) { /** * Really get a message - * @return $key String: key to get. - * @return $args - * @return $useDB Boolean + * @param $key String: key to get. + * @param $args + * @param $useDB Boolean + * @param $transform Boolean: Whether or not to transform the message. + * @param $forContent Boolean * @return String: the requested message. */ function wfMsgReal( $key, $args, $useDB = true, $forContent=false, $transform = true ) { - $fname = 'wfMsgReal'; - $message = wfMsgGetKey( $key, $useDB, $forContent, $transform ); $message = wfMsgReplaceArgs( $message, $args ); return $message; @@ -522,9 +519,10 @@ function wfMsgWikiHtml( $key ) { * <i>parseinline<i>: parses wikitext to html and removes the surrounding p's added by parser or tidy * <i>escape<i>: filters message trough htmlspecialchars * <i>replaceafter<i>: parameters are substituted after parsing or escaping + * <i>parsemag<i>: ?? */ function wfMsgExt( $key, $options ) { - global $wgOut, $wgMsgParserOptions, $wgParser; + global $wgOut, $wgParser; $args = func_get_args(); array_shift( $args ); @@ -549,12 +547,10 @@ function wfMsgExt( $key, $options ) { $string = $m[1]; } } elseif ( in_array('parsemag', $options) ) { - global $wgTitle; - $parser = new Parser(); - $parserOptions = new ParserOptions(); - $parserOptions->setInterfaceMessage( true ); - $parser->startExternalParse( $wgTitle, $parserOptions, OT_MSG ); - $string = $parser->transformMsg( $string, $parserOptions ); + global $wgMessageCache; + if ( isset( $wgMessageCache ) ) { + $string = $wgMessageCache->transform( $string ); + } } if ( in_array('escape', $options) ) { @@ -583,8 +579,8 @@ function wfAbruptExit( $error = false ){ } $called = true; - if( function_exists( 'debug_backtrace' ) ){ // PHP >= 4.3 - $bt = debug_backtrace(); + $bt = wfDebugBacktrace(); + if( $bt ) { for($i = 0; $i < count($bt) ; $i++){ $file = isset($bt[$i]['file']) ? $bt[$i]['file'] : "unknown"; $line = isset($bt[$i]['line']) ? $bt[$i]['line'] : "unknown"; @@ -666,18 +662,36 @@ function wfHostname() { return $com; } +/** + * Safety wrapper for debug_backtrace(). + * + * With Zend Optimizer 3.2.0 loaded, this causes segfaults under somewhat + * murky circumstances, which may be triggered in part by stub objects + * or other fancy talkin'. + * + * Will return an empty array if Zend Optimizer is detected, otherwise + * the output from debug_backtrace() (trimmed). + * + * @return array of backtrace information + */ +function wfDebugBacktrace() { + if( extension_loaded( 'Zend Optimizer' ) ) { + wfDebug( "Zend Optimizer detected; skipping debug_backtrace for safety.\n" ); + return array(); + } else { + return array_slice( debug_backtrace(), 1 ); + } +} + function wfBacktrace() { global $wgCommandLineMode; - if ( !function_exists( 'debug_backtrace' ) ) { - return false; - } if ( $wgCommandLineMode ) { $msg = ''; } else { $msg = "<ul>\n"; } - $backtrace = debug_backtrace(); + $backtrace = wfDebugBacktrace(); foreach( $backtrace as $call ) { if( isset( $call['file'] ) ) { $f = explode( DIRECTORY_SEPARATOR, $call['file'] ); @@ -801,6 +815,7 @@ function wfClientAcceptsGzip() { global $wgUseGzip; if( $wgUseGzip ) { # FIXME: we may want to blacklist some broken browsers + $m = array(); if( preg_match( '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/', $_SERVER['HTTP_ACCEPT_ENCODING'], @@ -966,6 +981,7 @@ function wfEscapeShellArg( ) { } // Double the backslashes before the end of the string, because // we will soon add a quote + $m = array(); if ( preg_match( '/^(.*?)(\\\\+)$/', $arg, $m ) ) { $arg = $m[1] . str_replace( '\\', '\\\\', $m[2] ); } @@ -1063,16 +1079,75 @@ function wfHttpError( $code, $label, $desc ) { $wgOut->sendCacheControl(); header( 'Content-type: text/html' ); - print "<html><head><title>" . + print "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">". + "<html><head><title>" . htmlspecialchars( $label ) . "</title></head><body><h1>" . htmlspecialchars( $label ) . "</h1><p>" . - htmlspecialchars( $desc ) . + nl2br( htmlspecialchars( $desc ) ) . "</p></body></html>\n"; } /** + * Clear away any user-level output buffers, discarding contents. + * + * Suitable for 'starting afresh', for instance when streaming + * relatively large amounts of data without buffering, or wanting to + * output image files without ob_gzhandler's compression. + * + * The optional $resetGzipEncoding parameter controls suppression of + * the Content-Encoding header sent by ob_gzhandler; by default it + * is left. See comments for wfClearOutputBuffers() for why it would + * be used. + * + * Note that some PHP configuration options may add output buffer + * layers which cannot be removed; these are left in place. + * + * @parameter bool $resetGzipEncoding + */ +function wfResetOutputBuffers( $resetGzipEncoding=true ) { + while( $status = ob_get_status() ) { + if( $status['type'] == 0 /* PHP_OUTPUT_HANDLER_INTERNAL */ ) { + // Probably from zlib.output_compression or other + // PHP-internal setting which can't be removed. + // + // Give up, and hope the result doesn't break + // output behavior. + break; + } + if( !ob_end_clean() ) { + // Could not remove output buffer handler; abort now + // to avoid getting in some kind of infinite loop. + break; + } + if( $resetGzipEncoding ) { + if( $status['name'] == 'ob_gzhandler' ) { + // Reset the 'Content-Encoding' field set by this handler + // so we can start fresh. + header( 'Content-Encoding:' ); + } + } + } +} + +/** + * More legible than passing a 'false' parameter to wfResetOutputBuffers(): + * + * Clear away output buffers, but keep the Content-Encoding header + * produced by ob_gzhandler, if any. + * + * This should be used for HTTP 304 responses, where you need to + * preserve the Content-Encoding header of the real result, but + * also need to suppress the output of ob_gzhandler to keep to spec + * and avoid breaking Firefox in rare cases where the headers and + * body are broken over two packets. + */ +function wfClearOutputBuffers() { + wfResetOutputBuffers( false ); +} + +/** * Converts an Accept-* header into an array mapping string values to quality * factors */ @@ -1089,6 +1164,7 @@ function wfAcceptToPrefs( $accept, $def = '*/*' ) { foreach( $parts as $part ) { # FIXME: doesn't deal with params like 'text/html; level=1' @list( $value, $qpart ) = explode( ';', $part ); + $match = array(); if( !isset( $qpart ) ) { $prefs[$value] = 1; } elseif( preg_match( '/q\s*=\s*(\d*\.\d+)/', $qpart, $match ) ) { @@ -1283,19 +1359,19 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) { $da = array(); if ($ts==0) { $uts=time(); - } elseif (preg_match("/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)$/D",$ts,$da)) { + } elseif (preg_match('/^(\d{4})\-(\d\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)$/D",$ts,$da)) { + } elseif (preg_match('/^(\d{4}):(\d\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)$/D",$ts,$da)) { + } elseif (preg_match('/^(\d{4})(\d\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], (int)$da[2],(int)$da[3],(int)$da[1]); - } elseif (preg_match("/^(\d{1,13})$/D",$ts,$datearray)) { + } elseif (preg_match('/^(\d{1,13})$/D',$ts,$da)) { # TS_UNIX $uts = $ts; } elseif (preg_match('/^(\d{1,2})-(...)-(\d\d(\d\d)?) (\d\d)\.(\d\d)\.(\d\d)/', $ts, $da)) { @@ -1306,7 +1382,11 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) { # TS_ISO_8601 $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)[\+\- ](\d\d)$/",$ts,$da)) { + } elseif (preg_match('/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)[\+\- ](\d\d)$/',$ts,$da)) { + # TS_POSTGRES + $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) GMT$/',$ts,$da)) { # TS_POSTGRES $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6], (int)$da[2],(int)$da[3],(int)$da[1]); @@ -1383,10 +1463,21 @@ function wfGetCachedNotice( $name ) { wfProfileIn( $fname ); $needParse = false; - $notice = wfMsgForContent( $name ); - if( wfEmptyMsg( $name, $notice ) || $notice == '-' ) { - wfProfileOut( $fname ); - return( false ); + + if( $name === 'default' ) { + // special case + global $wgSiteNotice; + $notice = $wgSiteNotice; + if( empty( $notice ) ) { + wfProfileOut( $fname ); + return false; + } + } else { + $notice = wfMsgForContentNoTrans( $name ); + if( wfEmptyMsg( $name, $notice ) || $notice == '-' ) { + wfProfileOut( $fname ); + return( false ); + } } $cachedNotice = $parserMemc->get( wfMemcKey( $name ) ); @@ -1446,16 +1537,17 @@ function wfGetSiteNotice() { if( wfRunHooks( 'SiteNoticeBefore', array( &$siteNotice ) ) ) { if( is_object( $wgUser ) && $wgUser->isLoggedIn() ) { $siteNotice = wfGetCachedNotice( 'sitenotice' ); - $siteNotice = !$siteNotice ? $wgSiteNotice : $siteNotice; } else { $anonNotice = wfGetCachedNotice( 'anonnotice' ); if( !$anonNotice ) { $siteNotice = wfGetCachedNotice( 'sitenotice' ); - $siteNotice = !$siteNotice ? $wgSiteNotice : $siteNotice; } else { $siteNotice = $anonNotice; } } + if( !$siteNotice ) { + $siteNotice = wfGetCachedNotice( 'default' ); + } } wfRunHooks( 'SiteNoticeAfter', array( &$siteNotice ) ); @@ -1677,7 +1769,7 @@ function wfShellExec( $cmd, &$retval=null ) { $output = array(); $retval = 1; // error by default? - $lastline = exec( $cmd, $output, $retval ); + exec( $cmd, $output, $retval ); // returns the last line of output. return implode( "\n", $output ); } @@ -1725,16 +1817,10 @@ function wfUseMW( $req_ver ) { } /** - * Escape a string to make it suitable for inclusion in a preg_replace() - * replacement parameter. - * - * @param string $string - * @return string + * @deprecated use StringUtils::escapeRegexReplacement */ function wfRegexReplacement( $string ) { - $string = str_replace( '\\', '\\\\', $string ); - $string = str_replace( '$', '\\$', $string ); - return $string; + return StringUtils::escapeRegexReplacement( $string ); } /** @@ -1749,6 +1835,7 @@ function wfRegexReplacement( $string ) { * @return string */ function wfBaseName( $path ) { + $matches = array(); if( preg_match( '#([^/\\\\]*)[/\\\\]*$#', $path, $matches ) ) { return $matches[1]; } else { @@ -1804,42 +1891,12 @@ function wfDoUpdates() } /** - * More or less "markup-safe" explode() - * Ignores any instances of the separator inside <...> - * @param string $separator - * @param string $text - * @return array + * @deprecated use StringUtils::explodeMarkup */ function wfExplodeMarkup( $separator, $text ) { - $placeholder = "\x00"; - - // Just in case... - $text = str_replace( $placeholder, '', $text ); - - // Trim stuff - $replacer = new ReplacerCallback( $separator, $placeholder ); - $cleaned = preg_replace_callback( '/(<.*?>)/', array( $replacer, 'go' ), $text ); - - $items = explode( $separator, $cleaned ); - foreach( $items as $i => $str ) { - $items[$i] = str_replace( $placeholder, $separator, $str ); - } - - return $items; + return StringUtils::explodeMarkup( $separator, $text ); } -class ReplacerCallback { - function ReplacerCallback( $from, $to ) { - $this->from = $from; - $this->to = $to; - } - - function go( $matches ) { - return str_replace( $this->from, $this->to, $matches[1] ); - } -} - - /** * Convert an arbitrarily-long digit string from one numeric base * to another, optionally zero-padding to a minimum column width. @@ -1999,7 +2056,7 @@ function wfGetPrecompiledData( $name ) { } function wfGetCaller( $level = 2 ) { - $backtrace = debug_backtrace(); + $backtrace = wfDebugBacktrace(); if ( isset( $backtrace[$level] ) ) { if ( isset( $backtrace[$level]['class'] ) ) { $caller = $backtrace[$level]['class'] . '::' . $backtrace[$level]['function']; @@ -2020,7 +2077,7 @@ function wfGetAllCallers() { $frame["class"]."::".$frame["function"]: $frame["function"]; '), - array_reverse(debug_backtrace()))); + array_reverse(wfDebugBacktrace()))); } /** @@ -2063,4 +2120,19 @@ function wfWikiID() { } } +/* + * Get a Database object + * @param integer $db Index of the connection to get. May be DB_MASTER for the + * master (for write queries), DB_SLAVE for potentially lagged + * read queries, or an integer >= 0 for a particular server. + * + * @param mixed $groups Query groups. An array of group names that this query + * belongs to. May contain a single string if the query is only + * in one group. + */ +function &wfGetDB( $db = DB_LAST, $groups = array() ) { + global $wgLoadBalancer; + $ret = $wgLoadBalancer->getConnection( $db, true, $groups ); + return $ret; +} ?> |