120 $this->requestTime = $_SERVER[
'REQUEST_TIME_FLOAT'];
124 $this->data = $_POST + $_GET;
126 $this->queryAndPathParams = $this->queryParams = $_GET;
152 if ( isset( $_SERVER[
'REQUEST_URI'] ) ) {
154 $url = $_SERVER[
'REQUEST_URI'];
155 if ( !preg_match(
'!^https?://!', $url ) ) {
156 $url =
'http://unused' . $url;
158 $a = parse_url( $url );
162 $path = $a[
'path'] ??
'';
174 $router->
add(
"$wgScript/$1" );
184 if ( $articlePaths ) {
185 $router->add( $articlePaths, [
'action' =>
'$key' ] );
192 [
'variant' =>
'$2' ],
193 [
'$2' => MediaWikiServices::getInstance()->getContentLanguage()->
198 Hooks::runner()->onWebRequestPathInfoRouter( $router );
205 if ( !empty( $_SERVER[
'ORIG_PATH_INFO'] ) ) {
209 $matches[
'title'] = substr( $_SERVER[
'ORIG_PATH_INFO'], 1 );
210 } elseif ( !empty( $_SERVER[
'PATH_INFO'] ) ) {
212 $matches[
'title'] = substr( $_SERVER[
'PATH_INFO'], 1 );
233 $requestUrl = self::getGlobalRequestURL();
234 $qpos = strpos( $requestUrl,
'?' );
235 if ( $qpos !==
false ) {
236 $requestPath = substr( $requestUrl, 0, $qpos );
238 $requestPath = $requestUrl;
243 return rawurldecode( substr( $requestPath, strlen(
$basePath ) ) );
255 $proto = self::detectProtocol();
256 $stdPort = $proto ===
'https' ? 443 : 80;
258 $varNames = [
'HTTP_HOST',
'SERVER_NAME',
'HOSTNAME',
'SERVER_ADDR' ];
261 foreach ( $varNames as $varName ) {
262 if ( !isset( $_SERVER[$varName] ) ) {
266 $parts = IPUtils::splitHostAndPort( $_SERVER[$varName] );
278 } elseif ( $parts[1] ===
false ) {
279 if ( isset( $_SERVER[
'SERVER_PORT'] ) ) {
280 $port = $_SERVER[
'SERVER_PORT'];
288 return $proto .
'://' . IPUtils::combineHostAndPort( $host, $port, $stdPort );
299 if ( ( !empty( $_SERVER[
'HTTPS'] ) && $_SERVER[
'HTTPS'] !==
'off' ) ||
300 ( isset( $_SERVER[
'HTTP_X_FORWARDED_PROTO'] ) &&
301 $_SERVER[
'HTTP_X_FORWARDED_PROTO'] ===
'https' ) ) {
316 return microtime(
true ) - $this->requestTime;
330 if ( !self::$reqId ) {
333 ? RequestContext::getMain()->getRequest()->getHeader(
'X-Request-Id' )
360 if ( $this->protocol ===
null ) {
361 $this->protocol = self::detectProtocol();
363 return $this->protocol;
375 if ( defined(
'MW_API' ) ) {
379 $matches = self::getPathInfo(
'title' );
380 foreach (
$matches as $key => $val ) {
381 $this->data[$key] = $this->queryAndPathParams[$key] = $val;
396 foreach ( (array)$bases as $keyValue =>
$base ) {
399 $baseLen = strlen(
$base );
400 if ( substr(
$path, 0, $baseLen ) ==
$base ) {
401 $raw = substr(
$path, $baseLen );
403 $matches = [
'title' => rawurldecode( $raw ) ];
422 if ( is_array(
$data ) ) {
423 foreach (
$data as $key => $val ) {
427 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
442 # PHP is so nice to not touch input data, except sometimes:
444 # Work around PHP *feature* to avoid *bugs* elsewhere.
445 $name = strtr( $name,
'.',
'_' );
447 if ( !isset( $arr[$name] ) ) {
452 # Optimisation: Skip UTF-8 normalization and legacy transcoding for simple ASCII strings.
453 $isAsciiStr = ( is_string(
$data ) && preg_match(
'/[^\x20-\x7E]/',
$data ) === 0 );
454 if ( !$isAsciiStr ) {
455 if ( isset( $_GET[$name] ) && is_string(
$data ) ) {
456 # Check for alternate/legacy character encoding.
457 $data = MediaWikiServices::getInstance()
458 ->getContentLanguage()
459 ->checkTitleEncoding(
$data );
480 $name = strtr( $name,
'.',
'_' );
481 if ( isset( $this->data[$name] ) && !is_array( $this->data[$name] ) ) {
482 $val = $this->data[$name];
486 if ( $val ===
null ) {
503 public function getVal( $name, $default =
null ) {
504 $val = $this->
getGPCVal( $this->data, $name, $default );
505 if ( is_array( $val ) ) {
508 if ( $val ===
null ) {
523 $ret = $this->data[$key] ??
null;
524 $this->data[$key] = $value;
535 if ( !isset( $this->data[$key] ) ) {
538 $ret = $this->data[$key];
539 unset( $this->data[$key] );
553 public function getArray( $name, $default =
null ) {
554 $val = $this->
getGPCVal( $this->data, $name, $default );
555 if ( $val ===
null ) {
573 $val = $this->
getArray( $name, $default );
574 if ( is_array( $val ) ) {
575 $val = array_map(
'intval', $val );
589 public function getInt( $name, $default = 0 ) {
590 return intval( $this->
getRawVal( $name, $default ) );
603 return is_numeric( $val )
618 public function getFloat( $name, $default = 0.0 ) {
619 return floatval( $this->
getRawVal( $name, $default ) );
631 public function getBool( $name, $default =
false ) {
632 return (
bool)$this->
getRawVal( $name, $default );
645 return $this->
getBool( $name, $default )
646 && strcasecmp( $this->
getRawVal( $name ),
'false' ) !== 0;
658 # Checkboxes and buttons are only present when clicked
659 # Presence connotes truth, absence false
660 return $this->
getRawVal( $name,
null ) !==
null;
673 public function getText( $name, $default =
'' ) {
674 $val = $this->
getVal( $name, $default );
675 return str_replace(
"\r\n",
"\n", $val );
686 $names = func_get_args();
687 if ( count( $names ) == 0 ) {
688 $names = array_keys( $this->data );
692 foreach ( $names as $name ) {
693 $value = $this->
getGPCVal( $this->data, $name,
null );
694 if ( $value !==
null ) {
695 $retVal[$name] = $value;
708 return array_diff( array_keys( $this->
getValues() ), $exclude );
719 return $this->queryAndPathParams;
732 return $this->queryParams;
755 return $_SERVER[
'QUERY_STRING'];
779 static $input =
null;
780 if ( $input ===
null ) {
781 $input = file_get_contents(
'php://input' );
792 return $_SERVER[
'REQUEST_METHOD'] ??
'GET';
819 if ( $this->sessionId !==
null ) {
820 $session = SessionManager::singleton()->getSessionById( (
string)$this->sessionId,
true, $this );
826 $session = SessionManager::singleton()->getSessionForRequest( $this );
827 $this->sessionId = $session->getSessionId();
838 $this->sessionId = $sessionId;
848 return $this->sessionId;
859 public function getCookie( $key, $prefix =
null, $default =
null ) {
860 if ( $prefix ===
null ) {
864 $name = $prefix . $key;
866 $name = strtr( $name,
'.',
'_' );
867 if ( isset( $_COOKIE[$name] ) ) {
868 return $_COOKIE[$name];
884 $name = $prefix . $key;
886 $name = strtr( $name,
'.',
'_' );
887 if ( isset( $_COOKIE[$name] ) ) {
888 return $_COOKIE[$name];
891 $legacyName = $prefix .
"ss0-" . $key;
892 $legacyName = strtr( $legacyName,
'.',
'_' );
893 if ( isset( $_COOKIE[$legacyName] ) ) {
894 return $_COOKIE[$legacyName];
910 if ( isset( $_SERVER[
'REQUEST_URI'] ) && strlen( $_SERVER[
'REQUEST_URI'] ) ) {
911 $base = $_SERVER[
'REQUEST_URI'];
912 } elseif ( isset( $_SERVER[
'HTTP_X_ORIGINAL_URL'] )
913 && strlen( $_SERVER[
'HTTP_X_ORIGINAL_URL'] )
916 $base = $_SERVER[
'HTTP_X_ORIGINAL_URL'];
917 } elseif ( isset( $_SERVER[
'SCRIPT_NAME'] ) ) {
918 $base = $_SERVER[
'SCRIPT_NAME'];
919 if ( isset( $_SERVER[
'QUERY_STRING'] ) && $_SERVER[
'QUERY_STRING'] !=
'' ) {
920 $base .=
'?' . $_SERVER[
'QUERY_STRING'];
924 throw new MWException(
"Web server doesn't provide either " .
925 "REQUEST_URI, HTTP_X_ORIGINAL_URL or SCRIPT_NAME. Report details " .
926 "of your web server configuration to https://phabricator.wikimedia.org/" );
932 $hash = strpos(
$base,
'#' );
933 if ( $hash !==
false ) {
937 if (
$base[0] ==
'/' ) {
939 return preg_replace(
'!^/+!',
'/',
$base );
942 return preg_replace(
'!^[^:]+://[^/]+/+!',
'/',
$base );
954 return self::getGlobalRequestURL();
995 unset( $newquery[
'title'] );
996 $newquery = array_merge( $newquery, $array );
1028 $limit = $this->
getInt(
'limit', 0 );
1032 if ( ( $limit == 0 ) && ( $optionname !=
'' ) ) {
1035 if ( $limit <= 0 ) {
1038 if ( $limit > 5000 ) {
1039 $limit = 5000; # We have *some* limits...
1042 $offset = $this->
getInt(
'offset', 0 );
1043 if ( $offset < 0 ) {
1047 return [ $limit, $offset ];
1058 return $file->getTempName();
1069 return $file->getError();
1085 return $file->getName();
1106 if ( !is_object( $this->
response ) ) {
1107 $class = ( $this instanceof
FauxRequest ) ? FauxResponse::class : WebResponse::class;
1110 return $this->response;
1117 if ( count( $this->headers ) ) {
1121 $this->headers = array_change_key_case( getallheaders(), CASE_UPPER );
1131 return $this->headers;
1148 $name = strtoupper( $name );
1149 if ( !isset( $this->headers[$name] ) ) {
1152 $value = $this->headers[$name];
1153 if ( $flags & self::GETHEADER_LIST ) {
1154 $value = array_map(
'trim', explode(
',', $value ) );
1211 $acceptLang = $this->
getHeader(
'Accept-Language' );
1212 if ( !$acceptLang ) {
1217 $acceptLang = strtolower( $acceptLang );
1220 if ( !preg_match_all(
1221 '/([a-z]{1,8}(?:-[a-z]{1,8})*|\*)\s*(?:;\s*q\s*=\s*(1(?:\.0{0,3})?|0(?:\.[0-9]{0,3})?)?)?/',
1232 $languageCode = $match[1];
1234 $qValue = $match[2] ?? 1;
1235 if ( $qValue > 0 ) {
1236 $langs[$languageCode] = $qValue;
1241 arsort( $langs, SORT_NUMERIC );
1254 if ( !isset( $_SERVER[
'REMOTE_ADDR'] ) ) {
1258 if ( is_array( $_SERVER[
'REMOTE_ADDR'] ) || strpos( $_SERVER[
'REMOTE_ADDR'],
',' ) !==
false ) {
1260 .
" : Could not determine the remote IP address due to multiple values." );
1262 $ipchain = $_SERVER[
'REMOTE_ADDR'];
1265 return IPUtils::canonicalize( $ipchain );
1280 # Return cached result
1281 if ( $this->ip !==
null ) {
1285 # collect the originating ips
1288 throw new MWException(
'Unable to determine IP.' );
1292 $forwardedFor = $this->
getHeader(
'X-Forwarded-For' );
1293 if ( $forwardedFor !==
false ) {
1294 $proxyLookup = MediaWikiServices::getInstance()->getProxyLookup();
1295 $isConfigured = $proxyLookup->isConfiguredProxy(
$ip );
1296 $ipchain = array_map(
'trim', explode(
',', $forwardedFor ) );
1297 $ipchain = array_reverse( $ipchain );
1298 array_unshift( $ipchain,
$ip );
1300 # Step through XFF list and find the last address in the list which is a
1301 # trusted server. Set $ip to the IP address given by that trusted server,
1302 # unless the address is not sensible (e.g. private). However, prefer private
1303 # IP addresses over proxy servers controlled by this site (more sensible).
1304 # Note that some XFF values might be "unknown" with Squid/Varnish.
1305 foreach ( $ipchain as $i => $curIP ) {
1306 $curIP = IPUtils::sanitizeIP( IPUtils::canonicalize( $curIP ) );
1307 if ( !$curIP || !isset( $ipchain[$i + 1] ) || $ipchain[$i + 1] ===
'unknown'
1308 || !$proxyLookup->isTrustedProxy( $curIP )
1313 IPUtils::isPublic( $ipchain[$i + 1] ) ||
1315 $proxyLookup->isConfiguredProxy( $curIP )
1318 $nextIP = IPUtils::canonicalize( $ipchain[$i + 1] );
1319 if ( !$nextIP && $isConfigured ) {
1322 throw new MWException(
"Invalid IP given in XFF '$forwardedFor'." );
1332 # Allow extensions to improve our guess
1333 Hooks::runner()->onGetIP(
$ip );
1336 throw new MWException(
"Unable to determine IP." );
1365 if ( !isset( $_SERVER[
'REQUEST_METHOD'] ) ) {
1369 return in_array( $_SERVER[
'REQUEST_METHOD'], [
'GET',
'HEAD',
'OPTIONS',
'TRACE' ] );
1391 if ( $this->markedAsSafe && $this->
wasPosted() ) {
1409 $this->markedAsSafe =
true;
$wgUsePathInfo
Whether to support URLs like index.php/Page_title These often break when PHP is set up in CGI mode.
$wgScript
The URL path to index.php.
$wgActionPaths
To set 'pretty' URL paths for actions other than plain page views, add to this array.
bool $wgUseSameSiteLegacyCookies
If true, when a cross-site cookie with SameSite=None is sent, a legacy cookie with an "ss0" prefix wi...
$wgArticlePath
The URL path for primary article page views.
$wgAllowExternalReqID
Whether to respect/honour the request ID provided by the incoming request via the X-Request-Id header...
bool $wgAssumeProxiesUseDefaultProtocolPorts
When the wiki is running behind a proxy and this is set to true, assumes that the proxy exposes the w...
$wgVariantArticlePath
Like $wgArticlePath, but on multi-variant wikis, this provides a path format that describes which par...
$wgCookiePrefix
Cookies generated by MediaWiki have names starting with this prefix.
$wgUsePrivateIPs
Should forwarded Private IPs be accepted?
wfRandomString( $length=32)
Get a random string containing a number of pseudo-random hex characters.
wfGetServerUrl( $proto)
Get the wiki's "server", i.e.
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
WebRequest clone which takes values from a provided array.
add( $path, $params=[], $options=[])
Add a new path pattern to the path router.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
getIntOption( $oname, $defaultOverride=0)
Get the user's current setting for a given option, as an integer value.
Object to access the $_FILES array.
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
markAsSafeRequest()
Mark this request as identified as being nullipotent even if it is a POST request.
array $headers
Lazy-initialized request headers indexed by upper-case header name.
getIntOrNull( $name)
Fetch an integer value from the input or return null if empty.
getValueNames( $exclude=[])
Returns the names of all input values excluding those in $exclude.
bool $markedAsSafe
Whether this HTTP request is "safe" (even if it is an HTTP post)
getUpload( $key)
Return a WebRequestUpload object corresponding to the key.
string $protocol
Cached URL protocol.
getArray( $name, $default=null)
Fetch an array from the input or return $default if it's not set.
interpolateTitle()
Check for title, action, and/or variant data in the URL and interpolate it into the GET variables.
getPostValues()
Get the values passed via POST.
static detectProtocol()
Detect the protocol from $_SERVER.
isSafeRequest()
Whether this request should be identified as being "safe".
getSession()
Return the session for this request.
getRawInput()
Return the raw request body, with no processing.
getRawQueryString()
Return the contents of the Query with no decoding.
getFileTempname( $key)
Return the path to the temporary file where PHP has stored the upload.
getVal( $name, $default=null)
Fetch a scalar from the input or return $default if it's not set.
getFloat( $name, $default=0.0)
Fetch a floating point value from the input or return $default if not set.
WebResponse $response
Lazy-init response object.
getUploadError( $key)
Return the upload error or 0.
getAllHeaders()
Get an array containing all request headers.
getFuzzyBool( $name, $default=false)
Fetch a boolean value from the input or return $default if not set.
getGPCVal( $arr, $name, $default)
Fetch a value from the given array or return $default if it's not set.
static getRequestId()
Get the unique request ID.
getProtocol()
Get the current URL protocol (http or https)
getMethod()
Get the HTTP method used for this request.
initHeaders()
Initialise the header list.
getBool( $name, $default=false)
Fetch a boolean value from the input or return $default if not set.
static getRequestPathSuffix( $basePath)
If the request URL matches a given base path, extract the path part of the request URL after that bas...
string $ip
Cached client IP address.
static getGlobalRequestURL()
Return the path and query string portion of the main request URI.
setVal( $key, $value)
Set an arbitrary value into our get/post data.
static string $reqId
The unique request ID.
getFullRequestURL()
Return the request URI with the canonical service and hostname, path, and query string.
checkUrlExtension( $extWhitelist=[])
This function formerly did a security check to prevent an XSS vulnerability in IE6,...
getElapsedTime()
Get the number of seconds to have elapsed since request start, in fractional seconds,...
float $requestTime
The timestamp of the start of the request, with microsecond precision.
getCrossSiteCookie( $key, $prefix='', $default=null)
Get a cookie set with SameSite=None possibly with a legacy fallback cookie.
getCheck( $name)
Return true if the named value is set in the input, whatever that value is (even "0").
appendQueryArray( $array)
Appends or replaces value of query variables.
static detectServer()
Work out an appropriate URL prefix containing scheme and host, based on information detected from $_S...
getSessionId()
Get the session id for this request, if any.
getAcceptLang()
Parse the Accept-Language header sent by the client into an array.
getRawPostString()
Return the contents of the POST with no decoding.
getQueryValues()
Get the values passed in the query string and the path router parameters.
response()
Return a handle to WebResponse style object, for setting cookies, headers and other stuff,...
getIP()
Work out the IP address based on various globals For trusted proxies, use the XFF client IP (first of...
$queryParams
The parameters from $_GET only.
getInt( $name, $default=0)
Fetch an integer value from the input or return $default if not set.
wasPosted()
Returns true if the present request was reached by a POST operation, false otherwise (GET,...
setSessionData( $key, $data)
Set session data.
getFileName( $key)
Return the original filename of the uploaded file, as reported by the submitting user agent.
const GETHEADER_LIST
Flag to make WebRequest::getHeader return an array of values.
hasSafeMethod()
Check if this request uses a "safe" HTTP method.
getRawVal( $name, $default=null)
Fetch a scalar from the input without normalization, or return $default if it's not set.
getIntArray( $name, $default=null)
Fetch an array of integers, or return $default if it's not set.
appendQueryValue( $key, $value)
normalizeUnicode( $data)
Recursively normalizes UTF-8 strings in the given array.
static overrideRequestId( $id)
Override the unique request ID.
unsetVal( $key)
Unset an arbitrary value from our get/post data.
static getPathInfo( $want='all')
Extract relevant query arguments from the http request uri's path to be merged with the normal php pr...
SessionId null $sessionId
Session ID to use for this request.
array $queryAndPathParams
The parameters from $_GET.
getRawIP()
Fetch the raw IP from the request.
setSessionId(SessionId $sessionId)
Set the session for this request.
getCookie( $key, $prefix=null, $default=null)
Get a cookie from the $_COOKIE jar.
array $data
The parameters from $_GET, $_POST and the path router.
getLimitOffset( $deflimit=50, $optionname='rclimit')
Same as ::getLimitOffsetForUser, but without a user parameter, instead using $wgUser.
static extractTitle( $path, $bases, $key=false)
URL rewriting function; tries to extract page title and, optionally, one other fixed parameter value ...
getText( $name, $default='')
Fetch a text string from the given array or return $default if it's not set.
getLimitOffsetForUser(User $user, $deflimit=50, $optionname='rclimit')
Check for limit and offset parameters on the input, and return sensible defaults if not given.
getRequestURL()
Return the path and query string portion of the request URI.
getHeader( $name, $flags=0)
Get a request header, or false if it isn't set.
getSessionData( $key)
Get data from the session.
getValues()
Extracts the given named values into an array.
getQueryValuesOnly()
Get the values passed in the query string only, not including the path router parameters.
Allow programs to request this object from WebRequest::response() and handle all outputting (or lack ...
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.