/**
* Compatibility functions
- * PHP <4.3.x is not actively supported; 4.1.x and 4.2.x might or might not work.
- * <4.1.x will not work, as we use a number of features introduced in 4.1.0
- * such as the new autoglobals.
+ *
+ * We more or less support PHP 5.0.x and up.
+ * Re-implementations of newer functions or functions in non-standard
+ * PHP extensions may be included here.
*/
if( !function_exists('iconv') ) {
# iconv support is not in the default configuration and so may not be present.
}
}
-if( !function_exists('file_get_contents') ) {
- # Exists in PHP 4.3.0+
- function file_get_contents( $filename ) {
- return implode( '', file( $filename ) );
- }
-}
-
-if( !function_exists('is_a') ) {
- # Exists in PHP 4.2.0+
- function is_a( $object, $class_name ) {
- return
- (strcasecmp( get_class( $object ), $class_name ) == 0) ||
- is_subclass_of( $object, $class_name );
- }
-}
-
# UTF-8 substr function based on a PHP manual comment
if ( !function_exists( 'mb_substr' ) ) {
function mb_substr( $str, $start ) {
}
}
-if( !function_exists( 'floatval' ) ) {
- /**
- * First defined in PHP 4.2.0
- * @param mixed $var;
- * @return float
- */
- function floatval( $var ) {
- return (float)$var;
- }
-}
-
if ( !function_exists( 'array_diff_key' ) ) {
/**
* Exists in PHP 5.1.0+
/**
- * Wrapper for clone() for PHP 4, for the moment.
+ * Wrapper for clone(), for compatibility with PHP4-friendly extensions.
* PHP 5 won't let you declare a 'clone' function, even conditionally,
* so it has to be a wrapper with a different name.
*/
function wfClone( $object ) {
- // WARNING: clone() is not a function in PHP 5, so function_exists fails.
- if( version_compare( PHP_VERSION, '5.0' ) < 0 ) {
- return $object;
- } else {
- return clone( $object );
- }
+ return clone( $object );
}
/**
* Where as we got a random seed
- * @var bool $wgTotalViews
*/
$wgRandomSeeded = false;
/**
* Seed Mersenne Twister
- * Only necessary in PHP < 4.2.0
- *
- * @return bool
+ * No-op for compatibility; only necessary in PHP < 4.2.0
*/
function wfSeedRandom() {
- global $wgRandomSeeded;
-
- if ( ! $wgRandomSeeded && version_compare( phpversion(), '4.2.0' ) < 0 ) {
- $seed = hexdec(substr(md5(microtime()),-8)) & 0x7fffffff;
- mt_srand( $seed );
- $wgRandomSeeded = true;
- }
+ /* No-op */
}
/**
*/
function wfDebug( $text, $logonly = false ) {
global $wgOut, $wgDebugLogFile, $wgDebugComments, $wgProfileOnly, $wgDebugRawPage;
+ static $recursion = 0;
# Check for raw action using $_GET not $wgRequest, since the latter might not be initialised yet
if ( isset( $_GET['action'] ) && $_GET['action'] == 'raw' && !$wgDebugRawPage ) {
return;
}
- if ( isset( $wgOut ) && $wgDebugComments && !$logonly ) {
+ if ( $wgDebugComments && !$logonly ) {
+ if ( !isset( $wgOut ) ) {
+ return;
+ }
+ if ( !StubObject::isRealObject( $wgOut ) ) {
+ if ( $recursion ) {
+ return;
+ }
+ $recursion++;
+ $wgOut->_unstub();
+ $recursion--;
+ }
$wgOut->debug( $text );
}
if ( '' != $wgDebugLogFile && !$wgProfileOnly ) {
/**
* @todo document
*/
-function logProfilingData() {
+function wfLogProfilingData() {
global $wgRequestTime, $wgDebugLogFile, $wgDebugRawPage, $wgRequest;
global $wgProfiling, $wgUser;
- $now = wfTime();
-
- $elapsed = $now - $wgRequestTime;
if ( $wgProfiling ) {
+ $now = wfTime();
+ $elapsed = $now - $wgRequestTime;
$prof = wfGetProfilingOutput( $wgRequestTime, $elapsed );
$forward = '';
if( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) )
$forward .= ' from ' . $_SERVER['HTTP_FROM'];
if( $forward )
$forward = "\t(proxied via {$_SERVER['REMOTE_ADDR']}{$forward})";
- if( is_object($wgUser) && $wgUser->isAnon() )
+ // Don't unstub $wgUser at this late stage just for statistics purposes
+ if( StubObject::isRealObject($wgUser) && $wgUser->isAnon() )
$forward .= ' anon';
$log = sprintf( "%s\t%04.3f\t%s\n",
gmdate( 'YmdHis' ), $elapsed,
*/
function wfMsgWeirdKey ( $key ) {
$subsource = str_replace ( ' ' , '_' , $key ) ;
- $source = wfMsg ( $subsource ) ;
- if ( $source == "<{$subsource}>" ) {
+ $source = wfMsgForContentNoTrans( $subsource ) ;
+ if ( wfEmptyMsg( $subsource, $source) ) {
# Try again with first char lower case
$subsource = strtolower ( substr ( $subsource , 0 , 1 ) ) . substr ( $subsource , 1 ) ;
- $source = wfMsg ( $subsource ) ;
+ $source = wfMsgForContentNoTrans( $subsource ) ;
}
- if ( $source == "<{$subsource}>" ) {
+ if ( wfEmptyMsg( $subsource, $source ) ) {
# Didn't work either, return blank text
$source = "" ;
}
* @private
*/
function wfMsgGetKey( $key, $useDB, $forContent = false, $transform = true ) {
- global $wgParser, $wgMsgParserOptions, $wgContLang, $wgMessageCache, $wgLang;
+ global $wgParser, $wgContLang, $wgMessageCache, $wgLang;
if ( is_object( $wgMessageCache ) )
$transstat = $wgMessageCache->getTransform();
if($message === false)
$message = Language::getMessage($key);
if ( $transform && strstr( $message, '{{' ) !== false ) {
- $message = $wgParser->transformMsg($message, $wgMsgParserOptions);
+ $message = $wgParser->transformMsg($message, $wgMessageCache->getParserOptions() );
}
}
wfDebug('WARNING: Abrupt exit\n');
}
- wfProfileClose();
- logProfilingData();
+ wfLogProfilingData();
if ( !$error ) {
$wgLoadBalancer->closeAll();
*/
function wfEscapeWikiText( $text ) {
$text = str_replace(
- array( '[', '|', '\'', 'ISBN ' , '://' , "\n=", '{{' ),
- array( '[', '|', ''', 'ISBN ', '://' , "\n=", '{{' ),
+ array( '[', '|', '\'', 'ISBN ', 'RFC ', '://', "\n=", '{{' ),
+ array( '[', '|', ''', 'ISBN ', 'RFC ', '://', "\n=", '{{' ),
htmlspecialchars($text) );
return $text;
}
*/
define('TS_ORACLE', 6);
+/**
+ * Postgres format time.
+ */
+define('TS_POSTGRES', 7);
+
/**
* @param mixed $outputtype A timestamp in one of the supported formats, the
* function will autodetect which format is supplied
$da = array();
if ($ts==0) {
$uts=time();
- } elseif (preg_match("/^(\d{4})\-(\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)$/",$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)$/",$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})$/",$ts,$datearray)) {
+ } elseif (preg_match("/^(\d{1,13})$/D",$ts,$datearray)) {
# TS_UNIX
- $uts=$ts;
+ $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",
# 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)) {
+ # TS_POSTGRES
+ $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");
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';
+ case TS_POSTGRES:
+ return gmdate( 'Y-m-d H:i:s', $uts) . ' GMT';
default:
throw new MWException( 'wfTimestamp() called with illegal output type.');
}
$needParse = false;
$notice = wfMsgForContent( $name );
- if( $notice == '<'. $name . ';>' || $notice == '-' ) {
+ if( wfEmptyMsg( $name, $notice ) || $notice == '-' ) {
wfProfileOut( $fname );
return( false );
}
/**
* 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;
- }
+function wfMkdirParents( $fullDir, $mode = 0777 ) {
+ if ( strval( $fullDir ) === '' ) {
+ return true;
+ }
+
+ # Go back through the paths to find the first directory that exists
+ $currentDir = $fullDir;
+ $createList = array();
+ while ( strval( $currentDir ) !== '' && !file_exists( $currentDir ) ) {
+ # Strip trailing slashes
+ $currentDir = rtrim( $currentDir, '/\\' );
+
+ # Add to create list
+ $createList[] = $currentDir;
+
+ # Find next delimiter searching from the end
+ $p = max( strrpos( $currentDir, '/' ), strrpos( $currentDir, '\\' ) );
+ if ( $p === false ) {
+ $currentDir = false;
+ } else {
+ $currentDir = substr( $currentDir, 0, $p );
}
}
+
+ if ( count( $createList ) == 0 ) {
+ # Directory specified already exists
+ return true;
+ } elseif ( $currentDir === false ) {
+ # Went all the way back to root and it apparently doesn't exist
+ return false;
+ }
+
+ # Now go forward creating directories
+ $createList = array_reverse( $createList );
+ foreach ( $createList as $dir ) {
+ # use chmod to override the umask, as suggested by the PHP manual
+ if ( !mkdir( $dir, $mode ) || !chmod( $dir, $mode ) ) {
+ return false;
+ }
+ }
return true;
}
* @return collected stdout as a string (trailing newlines stripped)
*/
function wfShellExec( $cmd, &$retval=null ) {
- global $IP;
+ global $IP, $wgMaxShellMemory;
if( ini_get( 'safe_mode' ) ) {
wfDebug( "wfShellExec can't run in safe_mode, PHP's exec functions are too broken.\n" );
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) );
- }
+ $mem = intval( $wgMaxShellMemory );
+
if ( $time > 0 && $mem > 0 ) {
$script = "$IP/bin/ulimit.sh";
if ( is_executable( $script ) ) {
- $memKB = intval( $mem / 1024 );
- $cmd = escapeshellarg( $script ) . " $time $memKB $cmd";
+ $cmd = escapeshellarg( $script ) . " $time $mem $cmd";
}
}
} elseif ( php_uname( 's' ) == 'Windows NT' ) {
}
}
+
+/**
+ * Convert an arbitrarily-long digit string from one numeric base
+ * to another, optionally zero-padding to a minimum column width.
+ *
+ * Supports base 2 through 36; digit values 10-36 are represented
+ * as lowercase letters a-z. Input is case-insensitive.
+ *
+ * @param $input string of digits
+ * @param $sourceBase int 2-36
+ * @param $destBase int 2-36
+ * @param $pad int 1 or greater
+ * @return string or false on invalid input
+ */
+function wfBaseConvert( $input, $sourceBase, $destBase, $pad=1 ) {
+ if( $sourceBase < 2 ||
+ $sourceBase > 36 ||
+ $destBase < 2 ||
+ $destBase > 36 ||
+ $pad < 1 ||
+ $sourceBase != intval( $sourceBase ) ||
+ $destBase != intval( $destBase ) ||
+ $pad != intval( $pad ) ||
+ !is_string( $input ) ||
+ $input == '' ) {
+ return false;
+ }
+
+ $digitChars = '0123456789abcdefghijklmnopqrstuvwxyz';
+ $inDigits = array();
+ $outChars = '';
+
+ // Decode and validate input string
+ $input = strtolower( $input );
+ for( $i = 0; $i < strlen( $input ); $i++ ) {
+ $n = strpos( $digitChars, $input{$i} );
+ if( $n === false || $n > $sourceBase ) {
+ return false;
+ }
+ $inDigits[] = $n;
+ }
+
+ // Iterate over the input, modulo-ing out an output digit
+ // at a time until input is gone.
+ while( count( $inDigits ) ) {
+ $work = 0;
+ $workDigits = array();
+
+ // Long division...
+ foreach( $inDigits as $digit ) {
+ $work *= $sourceBase;
+ $work += $digit;
+
+ if( $work < $destBase ) {
+ // Gonna need to pull another digit.
+ if( count( $workDigits ) ) {
+ // Avoid zero-padding; this lets us find
+ // the end of the input very easily when
+ // length drops to zero.
+ $workDigits[] = 0;
+ }
+ } else {
+ // Finally! Actual division!
+ $workDigits[] = intval( $work / $destBase );
+
+ // Isn't it annoying that most programming languages
+ // don't have a single divide-and-remainder operator,
+ // even though the CPU implements it that way?
+ $work = $work % $destBase;
+ }
+ }
+
+ // All that division leaves us with a remainder,
+ // which is conveniently our next output digit.
+ $outChars .= $digitChars[$work];
+
+ // And we continue!
+ $inDigits = $workDigits;
+ }
+
+ while( strlen( $outChars ) < $pad ) {
+ $outChars .= '0';
+ }
+
+ return strrev( $outChars );
+}
+
+/**
+ * Create an object with a given name and an array of construct parameters
+ * @param string $name
+ * @param array $p parameters
+ */
+function wfCreateObject( $name, $p ){
+ $p = array_values( $p );
+ switch ( count( $p ) ) {
+ case 0:
+ return new $name;
+ case 1:
+ return new $name( $p[0] );
+ case 2:
+ return new $name( $p[0], $p[1] );
+ case 3:
+ return new $name( $p[0], $p[1], $p[2] );
+ case 4:
+ return new $name( $p[0], $p[1], $p[2], $p[3] );
+ case 5:
+ return new $name( $p[0], $p[1], $p[2], $p[3], $p[4] );
+ case 6:
+ return new $name( $p[0], $p[1], $p[2], $p[3], $p[4], $p[5] );
+ default:
+ throw new MWException( "Too many arguments to construtor in wfCreateObject" );
+ }
+}
+
+/**
+ * Aliases for modularized functions
+ */
+function wfGetHTTP( $url, $timeout = 'default' ) {
+ return Http::get( $url, $timeout );
+}
+function wfIsLocalURL( $url ) {
+ return Http::isLocalURL( $url );
+}
+
+/**
+ * Initialise php session
+ */
+function wfSetupSession() {
+ global $wgSessionsInMemcached, $wgCookiePath, $wgCookieDomain;
+ if( $wgSessionsInMemcached ) {
+ require_once( 'MemcachedSessions.php' );
+ } elseif( 'files' != ini_get( 'session.save_handler' ) ) {
+ # If it's left on 'user' or another setting from another
+ # application, it will end up failing. Try to recover.
+ ini_set ( 'session.save_handler', 'files' );
+ }
+ session_set_cookie_params( 0, $wgCookiePath, $wgCookieDomain );
+ session_cache_limiter( 'private, must-revalidate' );
+ @session_start();
+}
+
+/**
+ * Get an object from the precompiled serialized directory
+ *
+ * @return mixed The variable on success, false on failure
+ */
+function wfGetPrecompiledData( $name ) {
+ global $IP;
+
+ $file = "$IP/serialized/$name";
+ if ( file_exists( $file ) ) {
+ $blob = file_get_contents( $file );
+ if ( $blob ) {
+ return unserialize( $blob );
+ }
+ }
+ return false;
+}
+
+function wfGetCaller( $level = 2 ) {
+ $backtrace = debug_backtrace();
+ if ( isset( $backtrace[$level] ) ) {
+ if ( isset( $backtrace[$level]['class'] ) ) {
+ $caller = $backtrace[$level]['class'] . '::' . $backtrace[$level]['function'];
+ } else {
+ $caller = $backtrace[$level]['function'];
+ }
+ } else {
+ $caller = 'unknown';
+ }
+ return $caller;
+}
+
+/** Return a string consisting all callers in stack, somewhat useful sometimes for profiling specific points */
+function wfGetAllCallers() {
+ return implode('/', array_map(
+ create_function('$frame','
+ return isset( $frame["class"] )?
+ $frame["class"]."::".$frame["function"]:
+ $frame["function"];
+ '),
+ array_reverse(debug_backtrace())));
+}
+
?>