/**
* The WebRequest class encapsulates getting at data passed in the
- * URL or via a POSTed form, handling remove of "magic quotes" slashes,
- * stripping illegal input characters and normalizing Unicode sequences.
+ * URL or via a POSTed form stripping illegal input characters and
+ * normalizing Unicode sequences.
*
* Usually this is used via a global singleton, $wgRequest. You should
* not create a second WebRequest object; make a FauxRequest object if
protected $protocol;
public function __construct() {
- /// @todo FIXME: This preemptive de-quoting can interfere with other web libraries
- /// and increases our memory footprint. It would be cleaner to do on
- /// demand; but currently we have no wrapper for $_SERVER etc.
- $this->checkMagicQuotes();
+ if ( function_exists( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc() ) {
+ throw new MWException( "MediaWiki does not function when magic quotes are enabled." );
+ }
// POST overrides GET data
// We don't use $_REQUEST here to avoid interference from cookies...
continue;
}
$host = $parts[0];
- if ( $parts[1] === false ) {
+ if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) ) {
+ // Bug 70021: Assume that upstream proxy is running on the default
+ // port based on the protocol. We have no reliable way to determine
+ // the actual port in use upstream.
+ $port = $stdPort;
+ } elseif ( $parts[1] === false ) {
if ( isset( $_SERVER['SERVER_PORT'] ) ) {
$port = $_SERVER['SERVER_PORT'];
} // else leave it as $stdPort
return array();
}
- /**
- * Recursively strips slashes from the given array;
- * used for undoing the evil that is magic_quotes_gpc.
- *
- * @param array $arr will be modified
- * @param bool $topLevel Specifies if the array passed is from the top
- * level of the source. In PHP5 magic_quotes only escapes the first level
- * of keys that belong to an array.
- * @return array The original array
- * @see http://www.php.net/manual/en/function.get-magic-quotes-gpc.php#49612
- */
- private function &fix_magic_quotes( &$arr, $topLevel = true ) {
- $clean = array();
- foreach ( $arr as $key => $val ) {
- if ( is_array( $val ) ) {
- $cleanKey = $topLevel ? stripslashes( $key ) : $key;
- $clean[$cleanKey] = $this->fix_magic_quotes( $arr[$key], false );
- } else {
- $cleanKey = stripslashes( $key );
- $clean[$cleanKey] = stripslashes( $val );
- }
- }
- $arr = $clean;
- return $arr;
- }
-
- /**
- * If magic_quotes_gpc option is on, run the global arrays
- * through fix_magic_quotes to strip out the stupid slashes.
- * WARNING: This should only be done once! Running a second
- * time could damage the values.
- */
- private function checkMagicQuotes() {
- $mustFixQuotes = function_exists( 'get_magic_quotes_gpc' )
- && get_magic_quotes_gpc();
- if ( $mustFixQuotes ) {
- $this->fix_magic_quotes( $_COOKIE );
- $this->fix_magic_quotes( $_ENV );
- $this->fix_magic_quotes( $_GET );
- $this->fix_magic_quotes( $_POST );
- $this->fix_magic_quotes( $_REQUEST );
- $this->fix_magic_quotes( $_SERVER );
- }
- }
-
/**
* Recursively normalizes UTF-8 strings in the given array.
*
* @param float $default
* @return float
*/
- public function getFloat( $name, $default = 0 ) {
+ public function getFloat( $name, $default = 0.0 ) {
return floatval( $this->getVal( $name, $default ) );
}
/**
* Take an arbitrary query and rewrite the present URL to include it
- * @param string $query query string fragment; do not include initial '?'
+ * @param string $query Query string fragment; do not include initial '?'
*
* @return string
*/
return $this->appendQueryArray( wfCgiToArray( $query ) );
}
- /**
- * HTML-safe version of appendQuery().
- * @deprecated: Deprecated in 1.20, warnings in 1.21, remove in 1.22.
- *
- * @param string $query Query string fragment; do not include initial '?'
- * @return string
- */
- public function escapeAppendQuery( $query ) {
- return htmlspecialchars( $this->appendQuery( $query ) );
- }
-
/**
* @param string $key
* @param string $value
* Return the path to the temporary file where PHP has stored the upload.
*
* @param string $key
- * @return string|null string or null if no such file.
+ * @return string|null String or null if no such file.
*/
public function getFileTempname( $key ) {
$file = new WebRequestUpload( $this, $key );
* Other than this the name is not verified for being a safe filename.
*
* @param string $key
- * @return string|null string or null if no such file.
+ * @return string|null String or null if no such file.
*/
public function getFileName( $key ) {
$file = new WebRequestUpload( $this, $key );
/**
* Get a request header, or false if it isn't set
- * @param string $name case-insensitive header name
+ * @param string $name Case-insensitive header name
*
* @return string|bool False on failure
*/
/**
* Parse the Accept-Language header sent by the client into an array
*
- * @return array array( languageCode => q-value ) sorted by q-value in
+ * @return array Array( languageCode => q-value ) sorted by q-value in
* descending order then appearing time in the header in ascending order.
* May contain the "language" '*', which applies to languages other than those explicitly listed.
* This is aligned with rfc2616 section 14.4
# collect the originating ips
$ip = $this->getRawIP();
+ if ( !$ip ) {
+ throw new MWException( 'Unable to determine IP.' );
+ }
# Append XFF
$forwardedFor = $this->getHeader( 'X-Forwarded-For' );
$isConfigured = IP::isConfiguredProxy( $ip );
$ipchain = array_map( 'trim', explode( ',', $forwardedFor ) );
$ipchain = array_reverse( $ipchain );
- if ( $ip ) {
- array_unshift( $ipchain, $ip );
- }
+ array_unshift( $ipchain, $ip );
# Step through XFF list and find the last address in the list which is a
# trusted server. Set $ip to the IP address given by that trusted server,
# unless the address is not sensible (e.g. private). However, prefer private
# IP addresses over proxy servers controlled by this site (more sensible).
+ # Note that some XFF values might be "unknown" with Squid/Varnish.
foreach ( $ipchain as $i => $curIP ) {
- // ignore 'unknown' value from Squid when 'forwarded_for off' and try next
- if ( $curIP === 'unknown' ) {
- continue;
- }
$curIP = IP::sanitizeIP( IP::canonicalize( $curIP ) );
- if ( IP::isTrustedProxy( $curIP ) && isset( $ipchain[$i + 1] ) ) {
- if ( IP::isConfiguredProxy( $curIP ) || // bug 48919; treat IP as sane
- IP::isPublic( $ipchain[$i + 1] ) ||
- $wgUsePrivateIPs
- ) {
- $nextIP = IP::canonicalize( $ipchain[$i + 1] );
- if ( !$nextIP && $isConfigured ) {
- // We have not yet made it past CDN/proxy servers of this site,
- // so either they are misconfigured or there is some IP spoofing.
- throw new MWException( "Invalid IP given in XFF '$forwardedFor'." );
- }
- $ip = $nextIP;
- continue;
+ if ( !$curIP || !isset( $ipchain[$i + 1] ) || $ipchain[$i + 1] === 'unknown'
+ || !IP::isTrustedProxy( $curIP )
+ ) {
+ break; // IP is not valid/trusted or does not point to anything
+ }
+ if (
+ IP::isPublic( $ipchain[$i + 1] ) ||
+ $wgUsePrivateIPs ||
+ IP::isConfiguredProxy( $curIP ) // bug 48919; treat IP as sane
+ ) {
+ // Follow the next IP according to the proxy
+ $nextIP = IP::canonicalize( $ipchain[$i + 1] );
+ if ( !$nextIP && $isConfigured ) {
+ // We have not yet made it past CDN/proxy servers of this site,
+ // so either they are misconfigured or there is some IP spoofing.
+ throw new MWException( "Invalid IP given in XFF '$forwardedFor'." );
}
+ $ip = $nextIP;
+ // keep traversing the chain
+ continue;
}
break;
}
private $session = array();
/**
- * @param array $data of *non*-urlencoded key => value pairs, the
+ * @param array $data Array of *non*-urlencoded key => value pairs, the
* fake GET/POST values
* @param bool $wasPosted Whether to treat the data as POST
* @param array|null $session Session array or null