X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2FGlobalFunctions.php;h=017b842d414b8def8a18a0d84c609458612b97c5;hb=41ac01dfc839b4f1c32a354fe37ed064b8a31585;hp=edf8b88772523a852fd5446e9f39113e9d98293b;hpb=0572c46e6df452f478303db1a4fb4b099d3c30a3;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index edf8b88772..017b842d41 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -294,6 +294,11 @@ function wfRandom() { */ function wfUrlencode( $s ) { static $needle; + if ( is_null( $s ) ) { + $needle = null; + return; + } + if ( is_null( $needle ) ) { $needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F' ); if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) || ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false ) ) { @@ -427,20 +432,49 @@ function wfAppendQuery( $url, $query ) { * Expand a potentially local URL to a fully-qualified URL. Assumes $wgServer * is correct. * + * The meaning of the PROTO_* constants is as follows: + * PROTO_HTTP: Output a URL starting with http:// + * PROTO_HTTPS: Output a URL starting with https:// + * PROTO_RELATIVE: Output a URL starting with // (protocol-relative URL) + * PROTO_CURRENT: Output a URL starting with either http:// or https:// , depending on which protocol was used for the current incoming request + * PROTO_CANONICAL: For URLs without a domain, like /w/index.php , use $wgCanonicalServer. For protocol-relative URLs, use the protocol of $wgCanonicalServer + * * @todo this won't work with current-path-relative URLs * like "subdir/foo.html", etc. * * @param $url String: either fully-qualified or a local path + query + * @param $defaultProto Mixed: one of the PROTO_* constants. Determines the protocol to use if $url or $wgServer is protocol-relative * @return string Fully-qualified URL */ -function wfExpandUrl( $url ) { - global $wgServer; +function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) { + global $wgServer, $wgCanonicalServer; + $serverUrl = $defaultProto === PROTO_CANONICAL ? $wgCanonicalServer : $wgServer; + + if ( $defaultProto === PROTO_CURRENT ) { + $defaultProto = WebRequest::detectProtocol() . '://'; + } + + // Analyze $serverUrl to obtain its protocol + $bits = wfParseUrl( $serverUrl ); + $serverHasProto = $bits && $bits['scheme'] != ''; + + if ( $defaultProto === PROTO_CANONICAL ) { + if ( $serverHasProto ) { + $defaultProto = $bits['scheme'] . '://'; + } else { + // $wgCanonicalServer doesn't have a protocol. This really isn't supposed to happen + // Fall back to HTTP in this ridiculous case + $defaultProto = PROTO_HTTP; + } + } + + $defaultProtoWithoutSlashes = substr( $defaultProto, 0, -2 ); + if( substr( $url, 0, 2 ) == '//' ) { - $bits = wfParseUrl( $wgServer ); - $scheme = $bits ? $bits['scheme'] : 'http'; - return $scheme . ':' . $url; + return $defaultProtoWithoutSlashes . $url; } elseif( substr( $url, 0, 1 ) == '/' ) { - return $wgServer . $url; + // If $serverUrl is protocol-relative, prepend $defaultProtoWithoutSlashes, otherwise leave it alone + return ( $serverHasProto ? '' : $defaultProtoWithoutSlashes ) . $serverUrl . $url; } else { return $url; } @@ -449,14 +483,18 @@ function wfExpandUrl( $url ) { /** * Returns a regular expression of url protocols * + * @param $includeProtocolRelative bool If false, remove '//' from the returned protocol list. + * DO NOT USE this directy, use wfUrlProtocolsWithoutProtRel() instead * @return String */ -function wfUrlProtocols() { +function wfUrlProtocols( $includeProtocolRelative = true ) { global $wgUrlProtocols; - static $retval = null; - if ( !is_null( $retval ) ) { - return $retval; + // Cache return values separately based on $includeProtocolRelative + static $withProtRel = null, $withoutProtRel = null; + $cachedValue = $includeProtocolRelative ? $withProtRel : $withoutProtRel; + if ( !is_null( $cachedValue ) ) { + return $cachedValue; } // Support old-style $wgUrlProtocols strings, for backwards compatibility @@ -464,32 +502,64 @@ function wfUrlProtocols() { if ( is_array( $wgUrlProtocols ) ) { $protocols = array(); foreach ( $wgUrlProtocols as $protocol ) { - $protocols[] = preg_quote( $protocol, '/' ); + // Filter out '//' if !$includeProtocolRelative + if ( $includeProtocolRelative || $protocol !== '//' ) { + $protocols[] = preg_quote( $protocol, '/' ); + } } $retval = implode( '|', $protocols ); } else { + // Ignore $includeProtocolRelative in this case + // This case exists for pre-1.6 compatibility, and we can safely assume + // that '//' won't appear in a pre-1.6 config because protocol-relative + // URLs weren't supported until 1.18 $retval = $wgUrlProtocols; } + + // Cache return value + if ( $includeProtocolRelative ) { + $withProtRel = $retval; + } else { + $withoutProtRel = $retval; + } return $retval; } +/** + * Like wfUrlProtocols(), but excludes '//' from the protocol list. Use this if + * you need a regex that matches all URL protocols but does not match protocol- + * relative URLs + */ +function wfUrlProtocolsWithoutProtRel() { + return wfUrlProtocols( false ); +} + /** * parse_url() work-alike, but non-broken. Differences: * * 1) Does not raise warnings on bad URLs (just returns false) - * 2) Handles protocols that don't use :// (e.g., mailto: and news:) correctly - * 3) Adds a "delimiter" element to the array, either '://' or ':' (see (2)) + * 2) Handles protocols that don't use :// (e.g., mailto: and news: , as well as protocol-relative URLs) correctly + * 3) Adds a "delimiter" element to the array, either '://', ':' or '//' (see (2)) * * @param $url String: a URL to parse * @return Array: bits of the URL in an associative array, per PHP docs */ function wfParseUrl( $url ) { global $wgUrlProtocols; // Allow all protocols defined in DefaultSettings/LocalSettings.php + + // Protocol-relative URLs are handled really badly by parse_url(). It's so bad that the easiest + // way to handle them is to just prepend 'http:' and strip the protocol out later + $wasRelative = substr( $url, 0, 2 ) == '//'; + if ( $wasRelative ) { + $url = "http:$url"; + } wfSuppressWarnings(); $bits = parse_url( $url ); wfRestoreWarnings(); - if ( !$bits ) { + // parse_url() returns an array without scheme for some invalid URLs, e.g. + // parse_url("%0Ahttp://example.com") == array( 'host' => '%0Ahttp', 'path' => 'example.com' ) + if ( !$bits || !isset( $bits['scheme'] ) ) { return false; } @@ -517,6 +587,12 @@ function wfParseUrl( $url ) { $bits['path'] = '/' . $bits['path']; } } + + // If the URL was protocol-relative, fix scheme and delimiter + if ( $wasRelative ) { + $bits['scheme'] = ''; + $bits['delimiter'] = '//'; + } return $bits; } @@ -569,6 +645,26 @@ function wfMakeUrlIndex( $url ) { return $index; } +/** + * Check whether a given URL has a domain that occurs in a given set of domains + * @param $url string URL + * @param $domains array Array of domains (strings) + * @return bool True if the host part of $url ends in one of the strings in $domains + */ +function wfMatchesDomainList( $url, $domains ) { + $bits = wfParseUrl( $url ); + if ( is_array( $bits ) && isset( $bits['host'] ) ) { + foreach ( (array)$domains as $domain ) { + // FIXME: This gives false positives. http://nds-nl.wikipedia.org will match nl.wikipedia.org + // We should use something that interprets dots instead + if ( substr( $bits['host'], -strlen( $domain ) ) === $domain ) { + return true; + } + } + } + return false; +} + /** * Sends a line to the debug log if enabled or, optionally, to a comment in output. * In normal operation this is a NOP. @@ -913,7 +1009,7 @@ function wfGetLangObj( $langcode = false ) { * Old function when $wgBetterDirectionality existed * Removed in core, kept in extensions for backwards compat. * - * @deprecated since 1.19 + * @deprecated since 1.18 * @return Language */ function wfUILang() { @@ -1143,7 +1239,8 @@ function wfMsgWikiHtml( $key ) { $args = func_get_args(); array_shift( $args ); return wfMsgReplaceArgs( - MessageCache::singleton()->parse( wfMsgGetKey( $key ), null, /* can't be set to false */ true )->getText(), + MessageCache::singleton()->parse( wfMsgGetKey( $key ), null, + /* can't be set to false */ true, /* interface */ true )->getText(), $args ); } @@ -1243,24 +1340,6 @@ function wfEmptyMsg( $key ) { return MessageCache::singleton()->get( $key, /*useDB*/true, /*content*/false ) === false; } -/** - * Print an error message and die, returning nonzero to the shell if any. Plain die() - * fails to return nonzero to the shell if you pass a string. Entry points may customise - * this function to return a prettier error message, but implementations must not assume - * access to any of the usual MediaWiki infrastructure (AutoLoader, localisation, database, - * etc). This should not be called directly once $wgFullyInitialised is set; instead, - * throw an exception and let Exception.php handle whether or not it's possible to show - * a prettier error. - * - * @param $msg String - */ -if( !function_exists( 'wfDie' ) ){ - function wfDie( $msg = '' ) { - echo $msg; - die( 1 ); - } -} - /** * Throw a debugging exception. This function previously once exited the process, * but now throws an exception instead, with similar results. @@ -1328,6 +1407,8 @@ function wfReportTime() { * debug_backtrace is disabled, otherwise the output from * debug_backtrace() (trimmed). * + * @param $limit int This parameter can be used to limit the number of stack frames returned + * * @return array of backtrace information */ function wfDebugBacktrace( $limit = 0 ) { @@ -1353,7 +1434,7 @@ function wfDebugBacktrace( $limit = 0 ) { } if ( $limit && version_compare( PHP_VERSION, '5.4.0', '>=' ) ) { - return array_slice( debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 1 ), 1 ); + return array_slice( debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, $limit ), 1 ); } else { return array_slice( debug_backtrace(), 1 ); } @@ -2534,7 +2615,7 @@ function wfSpecialList( $page, $details, $oppositedm = true ) { global $wgLang; $dirmark = ( $oppositedm ? $wgLang->getDirMark( true ) : '' ) . $wgLang->getDirMark(); - $details = $details ? $dirmark . "($details)" : ''; + $details = $details ? $dirmark . " ($details)" : ''; return $page . $details; } @@ -2953,7 +3034,7 @@ function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1, $lowercase = t * * @param $name String * @param $p Array: parameters - * @deprecated since 1.18, warnings in 1.19, removal in 1.20 + * @deprecated since 1.18, warnings in 1.18, removal in 1.20 */ function wfCreateObject( $name, $p ) { wfDeprecated( __FUNCTION__ ); @@ -3178,6 +3259,14 @@ function wfLocalFile( $title ) { return RepoGroup::singleton()->getLocalRepo()->newFile( $title ); } +/** + * Stream a file to the browser. Back-compat alias for StreamFile::stream() + * @deprecated since 1.19 + */ +function wfStreamFile( $fname, $headers = array() ) { + StreamFile::stream( $fname, $headers ); +} + /** * Should low-performance queries be disabled? * @@ -3336,7 +3425,7 @@ function wfWaitForSlaves( $maxLag = false, $wiki = false ) { /** * Used to be used for outputting text in the installer/updater - * @deprecated since 1.18, warnings in 1.19, remove in 1.20 + * @deprecated since 1.18, warnings in 1.18, remove in 1.20 */ function wfOut( $s ) { wfDeprecated( __METHOD__ );