X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FGlobalFunctions.php;h=56a313fa0f481bd152caf11c4ca7ab31c048196d;hb=3ee081b24bd30a9d61c348a5a7a2eccd073594be;hp=61e9e629dc0ee9b0300aa4d3693495cab0490b36;hpb=79d5225c0e864482269e2315f47b899697681e52;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 61e9e629dc..56a313fa0f 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -176,12 +176,16 @@ function wfDebug( $text, $logonly = false ) { global $wgOut, $wgDebugLogFile, $wgDebugComments, $wgProfileOnly, $wgDebugRawPage; static $recursion = 0; + static $cache = array(); // Cache of unoutputted messages + # 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 ( $wgDebugComments && !$logonly ) { + $cache[] = $text; + if ( !isset( $wgOut ) ) { return; } @@ -193,7 +197,10 @@ function wfDebug( $text, $logonly = false ) { $wgOut->_unstub(); $recursion--; } - $wgOut->debug( $text ); + + // add the message and possible cached ones to the output + array_map( array( $wgOut, 'debug' ), $cache ); + $cache = array(); } if ( '' != $wgDebugLogFile && !$wgProfileOnly ) { # Strip unprintables; they can switch terminal modes when binary data @@ -444,24 +451,38 @@ function wfMsgWeirdKey ( $key ) { * Fetch a message string value, but don't replace any keys yet. * @param string $key * @param bool $useDB - * @param bool $forContent + * @param string $langcode Code of the language to get the message for, or + * behaves as a content language switch if it is a + * boolean. * @return string * @private */ -function wfMsgGetKey( $key, $useDB, $forContent = false, $transform = true ) { +function wfMsgGetKey( $key, $useDB, $langCode = false, $transform = true ) { global $wgParser, $wgContLang, $wgMessageCache, $wgLang; + wfRunHooks('NormalizeMessageKey', array(&$key, &$useDB, &$langCode, &$transform)); + # If $wgMessageCache isn't initialised yet, try to return something sensible. if( is_object( $wgMessageCache ) ) { - $message = $wgMessageCache->get( $key, $useDB, $forContent ); + $message = $wgMessageCache->get( $key, $useDB, $langCode ); if ( $transform ) { $message = $wgMessageCache->transform( $message ); } } else { - if( $forContent ) { + if( $langCode === true ) { $lang = &$wgContLang; - } else { + } elseif( $langCode === false ) { $lang = &$wgLang; + } else { + $validCodes = array_keys( Language::getLanguageNames() ); + if( in_array( $langCode, $validCodes ) ) { + # $langcode corresponds to a valid language. + $lang = Language::factory( $langCode ); + } else { + # $langcode is a string, but not a valid language code; use content language. + $lang =& $wgContLang; + wfDebug( 'Invalid language code passed to wfMsgGetKey, falling back to content language.' ); + } } # MessageCache::get() does this already, Language::getMessage() doesn't @@ -552,6 +573,8 @@ function wfMsgWikiHtml( $key ) { * replaceafter: parameters are substituted after parsing or escaping * parsemag: transform the message using magic phrases * content: fetch message for content language instead of interface + * language: language code to fetch message for (overriden by content), its behaviour + * with parser, parseinline and parsemag is undefined. * Behavior for conflicting options (e.g., parse+parseinline) is undefined. */ function wfMsgExt( $key, $options ) { @@ -565,12 +588,23 @@ function wfMsgExt( $key, $options ) { $options = array($options); } - $forContent = false; if( in_array('content', $options) ) { $forContent = true; + $langCode = true; + } elseif( array_key_exists('language', $options) ) { + $forContent = false; + $langCode = $options['language']; + $validCodes = array_keys( Language::getLanguageNames() ); + if( !in_array($options['language'], $validCodes) ) { + # Fallback to en, instead of whatever interface language we might have + $langCode = 'en'; + } + } else { + $forContent = false; + $langCode = false; } - $string = wfMsgGetKey( $key, /*DB*/true, $forContent, /*Transform*/false ); + $string = wfMsgGetKey( $key, /*DB*/true, $langCode, /*Transform*/false ); if( !in_array('replaceafter', $options) ) { $string = wfMsgReplaceArgs( $string, $args ); @@ -975,7 +1009,20 @@ function wfArrayToCGI( $array1, $array2 = NULL ) if ( '' != $cgi ) { $cgi .= '&'; } - $cgi .= urlencode( $key ) . '=' . urlencode( $value ); + if(is_array($value)) + { + $firstTime = true; + foreach($value as $v) + { + $cgi .= ($firstTime ? '' : '&') . + urlencode( $key . '[]' ) . '=' . + urlencode( $v ); + $firstTime = false; + } + } + else + $cgi .= urlencode( $key ) . '=' . + urlencode( $value ); } } return $cgi; @@ -1236,7 +1283,7 @@ function wfClearOutputBuffers() { function wfAcceptToPrefs( $accept, $def = '*/*' ) { # No arg means accept anything (per HTTP spec) if( !$accept ) { - return array( $def => 1 ); + return array( $def => 1.0 ); } $prefs = array(); @@ -1245,12 +1292,12 @@ function wfAcceptToPrefs( $accept, $def = '*/*' ) { foreach( $parts as $part ) { # FIXME: doesn't deal with params like 'text/html; level=1' - @list( $value, $qpart ) = explode( ';', $part ); + @list( $value, $qpart ) = explode( ';', trim( $part ) ); $match = array(); if( !isset( $qpart ) ) { - $prefs[$value] = 1; + $prefs[$value] = 1.0; } elseif( preg_match( '/q\s*=\s*(\d*\.\d+)/', $qpart, $match ) ) { - $prefs[$value] = $match[1]; + $prefs[$value] = floatval($match[1]); } } @@ -1443,41 +1490,35 @@ function wfTimestamp($outputtype=TS_UNIX,$ts=0) { $uts=time(); } 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)) { # 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)) { # 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,$da)) { + } elseif (preg_match('/^\d{1,13}$/D',$ts)) { # TS_UNIX $uts = $ts; - } elseif (preg_match('/^(\d{1,2})-(...)-(\d\d(\d\d)?) (\d\d)\.(\d\d)\.(\d\d)/', $ts, $da)) { + } elseif (preg_match('/^\d{1,2}-...-\d\d(?:\d\d)? \d\d\.\d\d\.\d\d/', $ts)) { # 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]); } 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]); } else { # Bogus value; fall back to the epoch... wfDebug("wfTimestamp() fed bogus time value: $outputtype; $ts\n"); $uts = 0; } + if (count( $da ) ) { + // Warning! gmmktime() acts oddly if the month or day is set to 0 + // We may want to handle that explicitly at some point + $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6], + (int)$da[2],(int)$da[3],(int)$da[1]); + } switch($outputtype) { case TS_UNIX: @@ -1674,7 +1715,54 @@ function wfMkdirParents( $fullDir, $mode = 0777 ) { return true; if( file_exists( $fullDir ) ) return true; - return mkdir( str_replace( '/', DIRECTORY_SEPARATOR, $fullDir ), $mode, 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 + wfDebugLog( 'mkdir', "Root doesn't exist?\n" ); + return false; + } + # Now go forward creating directories + $createList = array_reverse( $createList ); + + # Is the parent directory writable? + if ( $currentDir === '' ) { + $currentDir = '/'; + } + if ( !is_writable( $currentDir ) ) { + wfDebugLog( 'mkdir', "Not writable: $currentDir\n" ); + return false; + } + + foreach ( $createList as $dir ) { + # use chmod to override the umask, as suggested by the PHP manual + if ( !mkdir( $dir, $mode ) || !chmod( $dir, $mode ) ) { + wfDebugLog( 'mkdir', "Unable to create directory $dir\n" ); + return false; + } + } + return true; } /** @@ -1721,15 +1809,12 @@ function wfPercent( $nr, $acc = 2, $round = true ) { * @param string $userid ID of the user * @param string $password Password of the user * @return string Hashed password + * @deprecated Use User::crypt() or User::oldCrypt() instead */ function wfEncryptPassword( $userid, $password ) { - global $wgPasswordSalt; - $p = md5( $password); - - if($wgPasswordSalt) - return md5( "{$userid}-{$p}" ); - else - return $p; + wfDeprecated(__FUNCTION__); + # Just wrap around User::oldCrypt() + return User::oldCrypt($password, $userid); } /** @@ -2211,20 +2296,44 @@ function wfCreateObject( $name, $p ){ } /** - * Aliases for modularized functions + * Alias for modularized function + * @deprecated Use Http::get() instead */ function wfGetHTTP( $url, $timeout = 'default' ) { + wfDeprecated(__FUNCTION__); return Http::get( $url, $timeout ); } + +/** + * Alias for modularized function + * @deprecated Use Http::isLocalURL() instead + */ function wfIsLocalURL( $url ) { + wfDeprecated(__FUNCTION__); return Http::isLocalURL( $url ); } +function wfHttpOnlySafe() { + global $wgHttpOnlyBlacklist; + if( !version_compare("5.2", PHP_VERSION, "<") ) + return false; + + if( isset( $_SERVER['HTTP_USER_AGENT'] ) ) { + foreach( $wgHttpOnlyBlacklist as $regex ) { + if( preg_match( $regex, $_SERVER['HTTP_USER_AGENT'] ) ) { + return false; + } + } + } + + return true; +} + /** * Initialise php session */ function wfSetupSession() { - global $wgSessionsInMemcached, $wgCookiePath, $wgCookieDomain, $wgCookieSecure; + global $wgSessionsInMemcached, $wgCookiePath, $wgCookieDomain, $wgCookieSecure, $wgCookieHttpOnly; if( $wgSessionsInMemcached ) { require_once( 'MemcachedSessions.php' ); } elseif( 'files' != ini_get( 'session.save_handler' ) ) { @@ -2232,7 +2341,21 @@ function wfSetupSession() { # application, it will end up failing. Try to recover. ini_set ( 'session.save_handler', 'files' ); } - session_set_cookie_params( 0, $wgCookiePath, $wgCookieDomain, $wgCookieSecure); + $httpOnlySafe = wfHttpOnlySafe(); + wfDebugLog( 'cookie', + 'session_set_cookie_params: "' . implode( '", "', + array( + 0, + $wgCookiePath, + $wgCookieDomain, + $wgCookieSecure, + $httpOnlySafe && $wgCookieHttpOnly ) ) . '"' ); + if( $httpOnlySafe && $wgCookieHttpOnly ) { + session_set_cookie_params( 0, $wgCookiePath, $wgCookieDomain, $wgCookieSecure, $wgCookieHttpOnly ); + } else { + // PHP 5.1 throws warnings if you pass the HttpOnly parameter for 5.2. + session_set_cookie_params( 0, $wgCookiePath, $wgCookieDomain, $wgCookieSecure ); + } session_cache_limiter( 'private, must-revalidate' ); wfSuppressWarnings(); session_start(); @@ -2283,13 +2406,8 @@ function wfFormatStackFrame($frame) { * Get a cache key */ function wfMemcKey( /*... */ ) { - global $wgDBprefix, $wgDBname; $args = func_get_args(); - if ( $wgDBprefix ) { - $key = "$wgDBname-$wgDBprefix:" . implode( ':', $args ); - } else { - $key = $wgDBname . ':' . implode( ':', $args ); - } + $key = wfWikiID() . ':' . implode( ':', $args ); return $key; } @@ -2310,12 +2428,16 @@ function wfForeignMemcKey( $db, $prefix /*, ... */ ) { * Get an ASCII string identifying this wiki * This is used as a prefix in memcached keys */ -function wfWikiID() { - global $wgDBprefix, $wgDBname; - if ( $wgDBprefix ) { - return "$wgDBname-$wgDBprefix"; +function wfWikiID( $db = null ) { + if( $db instanceof Database ) { + return $db->getWikiID(); } else { - return $wgDBname; + global $wgDBprefix, $wgDBname; + if ( $wgDBprefix ) { + return "$wgDBname-$wgDBprefix"; + } else { + return $wgDBname; + } } } @@ -2331,7 +2453,7 @@ function wfSplitWikiID( $wiki ) { } /* - * Get a Database object + * 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. @@ -2341,6 +2463,10 @@ function wfSplitWikiID( $wiki ) { * in one group. * * @param string $wiki The wiki ID, or false for the current wiki + * + * Note: multiple calls to wfGetDB(DB_SLAVE) during the course of one request + * will always return the same object, unless the underlying connection or load + * balancer is manually destroyed. */ function &wfGetDB( $db = DB_LAST, $groups = array(), $wiki = false ) { return wfGetLB( $wiki )->getConnection( $db, $groups, $wiki ); @@ -2371,10 +2497,11 @@ function &wfGetLBFactory() { * @param mixed $time Requested time for an archived image, or false for the * current version. An image object will be returned which * was created at the specified time. + * @param mixed $flags FileRepo::FIND_ flags * @return File, or false if the file does not exist */ -function wfFindFile( $title, $time = false ) { - return RepoGroup::singleton()->findFile( $title, $time ); +function wfFindFile( $title, $time = false, $flags = 0 ) { + return RepoGroup::singleton()->findFile( $title, $time, $flags ); } /** @@ -2423,13 +2550,39 @@ function wfBoolToStr( $value ) { /** * Load an extension messages file + * + * @param string $extensionName Name of extension to load messages from\for. + * @param string $langcode Language to load messages for, or false for default + * behvaiour (en, content language and user language). */ -function wfLoadExtensionMessages( $extensionName ) { - global $wgExtensionMessagesFiles, $wgMessageCache; - if ( !empty( $wgExtensionMessagesFiles[$extensionName] ) ) { - $wgMessageCache->loadMessagesFile( $wgExtensionMessagesFiles[$extensionName] ); - // Prevent double-loading - $wgExtensionMessagesFiles[$extensionName] = false; +function wfLoadExtensionMessages( $extensionName, $langcode = false ) { + global $wgExtensionMessagesFiles, $wgMessageCache, $wgLang, $wgContLang; + + #For recording whether extension message files have been loaded in a given language. + static $loaded = array(); + + if( !array_key_exists( $extensionName, $loaded ) ) { + $loaded[$extensionName] = array(); + } + + if ( !isset($wgExtensionMessagesFiles[$extensionName]) ) { + throw new MWException( "Messages file for extensions $extensionName is not defined" ); + } + + if( !$langcode && !array_key_exists( '*', $loaded[$extensionName] ) ) { + # Just do en, content language and user language. + $wgMessageCache->loadMessagesFile( $wgExtensionMessagesFiles[$extensionName], false ); + # Mark that they have been loaded. + $loaded[$extensionName]['en'] = true; + $loaded[$extensionName][$wgLang->getCode()] = true; + $loaded[$extensionName][$wgContLang->getCode()] = true; + # Mark that this part has been done to avoid weird if statements. + $loaded[$extensionName]['*'] = true; + } elseif( is_string( $langcode ) && !array_key_exists( $langcode, $loaded[$extensionName] ) ) { + # Load messages for specified language. + $wgMessageCache->loadMessagesFile( $wgExtensionMessagesFiles[$extensionName], $langcode ); + # Mark that they have been loaded. + $loaded[$extensionName][$langcode] = true; } } @@ -2471,7 +2624,28 @@ function wfMaxlagError( $host, $lag, $maxLag ) { * @return null */ function wfDeprecated( $function ) { - trigger_error( "Use of $function is deprecated", E_USER_NOTICE ); + global $wgDebugLogFile; + if ( !$wgDebugLogFile ) { + return; + } + $callers = wfDebugBacktrace(); + if( isset( $callers[2] ) ){ + $callerfunc = $callers[2]; + $callerfile = $callers[1]; + if( isset( $callerfile['file'] ) && isset( $callerfile['line'] ) ){ + $file = $callerfile['file'] . ' at line ' . $callerfile['line']; + } else { + $file = '(internal function)'; + } + $func = ''; + if( isset( $callerfunc['class'] ) ) + $func .= $callerfunc['class'] . '::'; + $func .= @$callerfunc['function']; + $msg = "Use of $function is deprecated. Called from $func in $file"; + } else { + $msg = "Use of $function is deprecated."; + } + wfDebug( "$msg\n" ); } /** @@ -2506,8 +2680,18 @@ function wfWaitForSlaves( $maxLag ) { /** Generate a random 32-character hexadecimal token. * @param mixed $salt Some sort of salt, if necessary, to add to random characters before hashing. */ - function wfGenerateToken( $salt = '' ) { +function wfGenerateToken( $salt = '' ) { $salt = serialize($salt); return md5( mt_rand( 0, 0x7fffffff ) . $salt ); } + +/** + * Replace all invalid characters with - + * @param mixed $title Filename to process + */ +function wfStripIllegalFilenameChars( $name ) { + $name = wfBaseName( $name ); + $name = preg_replace ( "/[^".Title::legalChars()."]|:/", '-', $name ); + return $name; +}