* array( array( 'x' ) ),
* array( array( 'x', '2' ) ),
* array( array( 'x' ) ),
- * array( array( 'y') )
+ * array( array( 'y' ) )
* );
* returns:
* array(
*/
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 ) ) {
* 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
+ * PROTO_INTERNAL: Like PROTO_CANONICAL, but uses $wgInternalServer instead 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, $wgInternalServer;
+ $serverUrl = $wgServer;
+ if ( $defaultProto === PROTO_CANONICAL ) {
+ $serverUrl = $wgCanonicalServer;
+ }
+ // Make $wgInternalServer fall back to $wgServer if not set
+ if ( $defaultProto === PROTO_INTERNAL && $wgInternalServer !== false ) {
+ $serverUrl = $wgInternalServer;
+ }
+ if ( $defaultProto === PROTO_CURRENT ) {
+ $defaultProto = WebRequest::detectProtocol() . '://';
+ }
+
+ // Analyze $serverUrl to obtain its protocol
+ $bits = wfParseUrl( $serverUrl );
+ $serverHasProto = $bits && $bits['scheme'] != '';
+
+ if ( $defaultProto === PROTO_CANONICAL || $defaultProto === PROTO_INTERNAL ) {
+ if ( $serverHasProto ) {
+ $defaultProto = $bits['scheme'] . '://';
+ } else {
+ // $wgCanonicalServer or $wgInternalServer 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'] !== '' ? $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;
}
/**
* 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
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:
*
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;
}
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.
} else {
$prefix = sprintf( "%6.4f", microtime( true ) - $start );
}
-
- return $prefix . ' ';
+ $mem = sprintf( "%5.1fM", ( memory_get_usage( true ) / (1024*1024) ) );
+ return "$prefix $mem " ;
}
/**
if ( !$sock ) {
return;
}
- socket_sendto( $sock, $text, strlen( $text ), 0, $host, $port );
+
+ $len = strlen( $text );
+ $maxLen = socket_get_option( $sock, SOL_SOCKET, SO_SNDBUF );
+
+ if ( $len > $maxLen ) {
+ $len = $maxLen - 1;
+ }
+ socket_sendto( $sock, $text, $len, 0, $host, $port );
socket_close( $sock );
} else {
wfSuppressWarnings();
* a valid code create a language for that language, if
* it is a string but not a valid code then make a basic
* language object
- * - a boolean: if it's false then use the current users
- * language (as a fallback for the old parameter
- * functionality), or if it is true then use the wikis
+ * - a boolean: if it's false then use the global object for
+ * the current user's language (as a fallback for the old parameter
+ * functionality), or if it is true then use global object
+ * for the wiki's content language.
* @return Language object
*/
function wfGetLangObj( $langcode = false ) {
$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 );
}
* 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 ) {
}
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 );
}
function wfNegotiateType( $cprefs, $sprefs ) {
$combine = array();
- foreach( array_keys($sprefs) as $type ) {
+ foreach( array_keys( $sprefs ) as $type ) {
$parts = explode( '/', $type );
if( $parts[1] != '*' ) {
$ckey = mimeTypeMatch( $type, $cprefs );
} else {
if ( !$suppressCount ) {
// E_DEPRECATED is undefined in PHP 5.2
- if( !defined( 'E_DEPRECATED' ) ){
+ if( !defined( 'E_DEPRECATED' ) ) {
define( 'E_DEPRECATED', 8192 );
}
$originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED ) );
# TS_POSTGRES
} elseif ( preg_match( '/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)\.*\d* GMT$/', $ts, $da ) ) {
# TS_POSTGRES
- } elseif (preg_match('/^(\d{4})\-(\d\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\d$/', $ts, $da ) ) {
# TS_DB2
} elseif ( preg_match( '/^[ \t\r\n]*([A-Z][a-z]{2},[ \t\r\n]*)?' . # Day of week
'\d\d?[ \t\r\n]*[A-Z][a-z]{2}[ \t\r\n]*\d{2}(?:\d{2})?' . # dd Mon yyyy
/**
* Do any deferred updates and clear the list
*
- * @param $commit String: set to 'commit' to commit after every update to
- * prevent lock contention
+ * @deprecated since 1.19
+ * @see DeferredUpdates::doUpdate()
*/
function wfDoUpdates( $commit = '' ) {
- global $wgDeferredUpdateList;
-
- wfProfileIn( __METHOD__ );
-
- // No need to get master connections in case of empty updates array
- if ( !count( $wgDeferredUpdateList ) ) {
- wfProfileOut( __METHOD__ );
- return;
- }
-
- $doCommit = $commit == 'commit';
- if ( $doCommit ) {
- $dbw = wfGetDB( DB_MASTER );
- }
-
- foreach ( $wgDeferredUpdateList as $update ) {
- $update->doUpdate();
-
- if ( $doCommit && $dbw->trxLevel() ) {
- $dbw->commit();
- }
- }
-
- $wgDeferredUpdateList = array();
- wfProfileOut( __METHOD__ );
+ DeferredUpdates::doUpdates( $commit );
}
/**
* @return String
*/
function wfWikiID() {
- global $wgDBprefix, $wgDBname;
- if ( $wgDBprefix ) {
+ global $wgDBprefix, $wgDBname, $wgWikiID;
+ if ( $wgWikiID !== false ) {
+ return $wgWikiID;
+ } elseif ( $wgDBprefix ) {
return "$wgDBname-$wgDBprefix";
} else {
return $wgDBname;
*
* @param $wiki String
* @param $bits String
+ *
+ * @return array
*/
function wfSplitWikiID( $wiki ) {
$bits = explode( '-', $wiki, 2 );
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?
*
* Throws a warning that $function is deprecated
*
* @param $function String
+ * @param $version String
* @return null
*/
-function wfDeprecated( $function ) {
+function wfDeprecated( $function, $version = false ) {
static $functionsWarned = array();
if ( !isset( $functionsWarned[$function] ) ) {
$functionsWarned[$function] = true;
- wfWarn( "Use of $function is deprecated.", 2 );
+ if ( $version ) {
+ global $wgDeprecationReleaseLimit;
+ if ( $wgDeprecationReleaseLimit ) {
+ # Strip -* off the end of $version so that branches can use the
+ # format #.##-branchname to avoid issues if the branch is merged into
+ # a version of MediaWiki later than what it was branched from
+ $comparableVersion = preg_replace( '/-.*$/', '', $version );
+ # If the comparableVersion is larger than our release limit then
+ # skip the warning message for the deprecation
+ if ( version_compare( $wgDeprecationReleaseLimit, $comparableVersion, '<' ) ) {
+ return;
+ }
+ }
+ wfWarn( "Use of $function was deprecated in $version.", 2 );
+ } else {
+ wfWarn( "Use of $function is deprecated.", 2 );
+ }
}
}
foreach ( $codeSegment as $segNo => $seg ) {
if ( count( $codeSegment ) > 0 ) {
// when previous segment is x, it is a private segment and should be lc
- if( $segNo > 0 && strtolower( $codeSegment[($segNo - 1)] ) == 'x') {
+ if( $segNo > 0 && strtolower( $codeSegment[( $segNo - 1 )] ) == 'x' ) {
$codeBCP[$segNo] = strtolower( $seg );
// ISO 3166 country code
} elseif ( ( strlen( $seg ) == 2 ) && ( $segNo > 0 ) ) {