MediaWiki  1.27.2
WebRequest.php
Go to the documentation of this file.
1 <?php
29 
37 class WebRequest {
38  protected $data, $headers = [];
39 
44  const GETHEADER_LIST = 1;
45 
50  private static $reqId;
51 
56  private $response;
57 
62  private $ip;
63 
68  protected $requestTime;
69 
74  protected $protocol;
75 
81  protected $sessionId = null;
82 
83  public function __construct() {
84  $this->requestTime = isset( $_SERVER['REQUEST_TIME_FLOAT'] )
85  ? $_SERVER['REQUEST_TIME_FLOAT'] : microtime( true );
86 
87  // POST overrides GET data
88  // We don't use $_REQUEST here to avoid interference from cookies...
89  $this->data = $_POST + $_GET;
90  }
91 
107  public static function getPathInfo( $want = 'all' ) {
109  // PATH_INFO is mangled due to http://bugs.php.net/bug.php?id=31892
110  // And also by Apache 2.x, double slashes are converted to single slashes.
111  // So we will use REQUEST_URI if possible.
112  $matches = [];
113  if ( !empty( $_SERVER['REQUEST_URI'] ) ) {
114  // Slurp out the path portion to examine...
115  $url = $_SERVER['REQUEST_URI'];
116  if ( !preg_match( '!^https?://!', $url ) ) {
117  $url = 'http://unused' . $url;
118  }
119  MediaWiki\suppressWarnings();
120  $a = parse_url( $url );
121  MediaWiki\restoreWarnings();
122  if ( $a ) {
123  $path = isset( $a['path'] ) ? $a['path'] : '';
124 
126  if ( $path == $wgScript && $want !== 'all' ) {
127  // Script inside a rewrite path?
128  // Abort to keep from breaking...
129  return $matches;
130  }
131 
132  $router = new PathRouter;
133 
134  // Raw PATH_INFO style
135  $router->add( "$wgScript/$1" );
136 
137  if ( isset( $_SERVER['SCRIPT_NAME'] )
138  && preg_match( '/\.php5?/', $_SERVER['SCRIPT_NAME'] )
139  ) {
140  # Check for SCRIPT_NAME, we handle index.php explicitly
141  # But we do have some other .php files such as img_auth.php
142  # Don't let root article paths clober the parsing for them
143  $router->add( $_SERVER['SCRIPT_NAME'] . "/$1" );
144  }
145 
147  if ( $wgArticlePath ) {
148  $router->add( $wgArticlePath );
149  }
150 
152  if ( $wgActionPaths ) {
153  $router->add( $wgActionPaths, [ 'action' => '$key' ] );
154  }
155 
157  if ( $wgVariantArticlePath ) {
158  $router->add( $wgVariantArticlePath,
159  [ 'variant' => '$2' ],
160  [ '$2' => $wgContLang->getVariants() ]
161  );
162  }
163 
164  Hooks::run( 'WebRequestPathInfoRouter', [ $router ] );
165 
166  $matches = $router->parse( $path );
167  }
168  } elseif ( $wgUsePathInfo ) {
169  if ( isset( $_SERVER['ORIG_PATH_INFO'] ) && $_SERVER['ORIG_PATH_INFO'] != '' ) {
170  // Mangled PATH_INFO
171  // http://bugs.php.net/bug.php?id=31892
172  // Also reported when ini_get('cgi.fix_pathinfo')==false
173  $matches['title'] = substr( $_SERVER['ORIG_PATH_INFO'], 1 );
174 
175  } elseif ( isset( $_SERVER['PATH_INFO'] ) && $_SERVER['PATH_INFO'] != '' ) {
176  // Regular old PATH_INFO yay
177  $matches['title'] = substr( $_SERVER['PATH_INFO'], 1 );
178  }
179  }
180 
181  return $matches;
182  }
183 
190  public static function detectServer() {
192 
193  $proto = self::detectProtocol();
194  $stdPort = $proto === 'https' ? 443 : 80;
195 
196  $varNames = [ 'HTTP_HOST', 'SERVER_NAME', 'HOSTNAME', 'SERVER_ADDR' ];
197  $host = 'localhost';
198  $port = $stdPort;
199  foreach ( $varNames as $varName ) {
200  if ( !isset( $_SERVER[$varName] ) ) {
201  continue;
202  }
203 
204  $parts = IP::splitHostAndPort( $_SERVER[$varName] );
205  if ( !$parts ) {
206  // Invalid, do not use
207  continue;
208  }
209 
210  $host = $parts[0];
211  if ( $wgAssumeProxiesUseDefaultProtocolPorts && isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) ) {
212  // Bug 70021: Assume that upstream proxy is running on the default
213  // port based on the protocol. We have no reliable way to determine
214  // the actual port in use upstream.
215  $port = $stdPort;
216  } elseif ( $parts[1] === false ) {
217  if ( isset( $_SERVER['SERVER_PORT'] ) ) {
218  $port = $_SERVER['SERVER_PORT'];
219  } // else leave it as $stdPort
220  } else {
221  $port = $parts[1];
222  }
223  break;
224  }
225 
226  return $proto . '://' . IP::combineHostAndPort( $host, $port, $stdPort );
227  }
228 
236  public static function detectProtocol() {
237  if ( ( !empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) ||
238  ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) &&
239  $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) ) {
240  return 'https';
241  } else {
242  return 'http';
243  }
244  }
245 
253  public function getElapsedTime() {
254  return microtime( true ) - $this->requestTime;
255  }
256 
265  public static function getRequestId() {
266  if ( !self::$reqId ) {
267  self::$reqId = isset( $_SERVER['UNIQUE_ID'] )
268  ? $_SERVER['UNIQUE_ID'] : wfRandomString( 24 );
269  }
270 
271  return self::$reqId;
272  }
273 
281  public static function overrideRequestId( $id ) {
282  self::$reqId = $id;
283  }
284 
289  public function getProtocol() {
290  if ( $this->protocol === null ) {
291  $this->protocol = self::detectProtocol();
292  }
293  return $this->protocol;
294  }
295 
303  public function interpolateTitle() {
304  // bug 16019: title interpolation on API queries is useless and sometimes harmful
305  if ( defined( 'MW_API' ) ) {
306  return;
307  }
308 
309  $matches = self::getPathInfo( 'title' );
310  foreach ( $matches as $key => $val ) {
311  $this->data[$key] = $_GET[$key] = $_REQUEST[$key] = $val;
312  }
313  }
314 
325  static function extractTitle( $path, $bases, $key = false ) {
326  foreach ( (array)$bases as $keyValue => $base ) {
327  // Find the part after $wgArticlePath
328  $base = str_replace( '$1', '', $base );
329  $baseLen = strlen( $base );
330  if ( substr( $path, 0, $baseLen ) == $base ) {
331  $raw = substr( $path, $baseLen );
332  if ( $raw !== '' ) {
333  $matches = [ 'title' => rawurldecode( $raw ) ];
334  if ( $key ) {
335  $matches[$key] = $keyValue;
336  }
337  return $matches;
338  }
339  }
340  }
341  return [];
342  }
343 
351  function normalizeUnicode( $data ) {
352  if ( is_array( $data ) ) {
353  foreach ( $data as $key => $val ) {
354  $data[$key] = $this->normalizeUnicode( $val );
355  }
356  } else {
358  $data = isset( $wgContLang ) ?
359  $wgContLang->normalize( $data ) :
360  UtfNormal\Validator::cleanUp( $data );
361  }
362  return $data;
363  }
364 
373  private function getGPCVal( $arr, $name, $default ) {
374  # PHP is so nice to not touch input data, except sometimes:
375  # http://us2.php.net/variables.external#language.variables.external.dot-in-names
376  # Work around PHP *feature* to avoid *bugs* elsewhere.
377  $name = strtr( $name, '.', '_' );
378  if ( isset( $arr[$name] ) ) {
380  $data = $arr[$name];
381  if ( isset( $_GET[$name] ) && !is_array( $data ) ) {
382  # Check for alternate/legacy character encoding.
383  if ( isset( $wgContLang ) ) {
384  $data = $wgContLang->checkTitleEncoding( $data );
385  }
386  }
387  $data = $this->normalizeUnicode( $data );
388  return $data;
389  } else {
390  return $default;
391  }
392  }
393 
404  public function getVal( $name, $default = null ) {
405  $val = $this->getGPCVal( $this->data, $name, $default );
406  if ( is_array( $val ) ) {
407  $val = $default;
408  }
409  if ( is_null( $val ) ) {
410  return $val;
411  } else {
412  return (string)$val;
413  }
414  }
415 
423  public function setVal( $key, $value ) {
424  $ret = isset( $this->data[$key] ) ? $this->data[$key] : null;
425  $this->data[$key] = $value;
426  return $ret;
427  }
428 
435  public function unsetVal( $key ) {
436  if ( !isset( $this->data[$key] ) ) {
437  $ret = null;
438  } else {
439  $ret = $this->data[$key];
440  unset( $this->data[$key] );
441  }
442  return $ret;
443  }
444 
454  public function getArray( $name, $default = null ) {
455  $val = $this->getGPCVal( $this->data, $name, $default );
456  if ( is_null( $val ) ) {
457  return null;
458  } else {
459  return (array)$val;
460  }
461  }
462 
473  public function getIntArray( $name, $default = null ) {
474  $val = $this->getArray( $name, $default );
475  if ( is_array( $val ) ) {
476  $val = array_map( 'intval', $val );
477  }
478  return $val;
479  }
480 
490  public function getInt( $name, $default = 0 ) {
491  return intval( $this->getVal( $name, $default ) );
492  }
493 
502  public function getIntOrNull( $name ) {
503  $val = $this->getVal( $name );
504  return is_numeric( $val )
505  ? intval( $val )
506  : null;
507  }
508 
519  public function getFloat( $name, $default = 0.0 ) {
520  return floatval( $this->getVal( $name, $default ) );
521  }
522 
532  public function getBool( $name, $default = false ) {
533  return (bool)$this->getVal( $name, $default );
534  }
535 
545  public function getFuzzyBool( $name, $default = false ) {
546  return $this->getBool( $name, $default ) && strcasecmp( $this->getVal( $name ), 'false' ) !== 0;
547  }
548 
557  public function getCheck( $name ) {
558  # Checkboxes and buttons are only present when clicked
559  # Presence connotes truth, absence false
560  return $this->getVal( $name, null ) !== null;
561  }
562 
575  public function getText( $name, $default = '' ) {
577  $val = $this->getVal( $name, $default );
578  return str_replace( "\r\n", "\n",
579  $wgContLang->recodeInput( $val ) );
580  }
581 
589  public function getValues() {
590  $names = func_get_args();
591  if ( count( $names ) == 0 ) {
592  $names = array_keys( $this->data );
593  }
594 
595  $retVal = [];
596  foreach ( $names as $name ) {
597  $value = $this->getGPCVal( $this->data, $name, null );
598  if ( !is_null( $value ) ) {
599  $retVal[$name] = $value;
600  }
601  }
602  return $retVal;
603  }
604 
611  public function getValueNames( $exclude = [] ) {
612  return array_diff( array_keys( $this->getValues() ), $exclude );
613  }
614 
621  public function getQueryValues() {
622  return $_GET;
623  }
624 
631  public function getRawQueryString() {
632  return $_SERVER['QUERY_STRING'];
633  }
634 
641  public function getRawPostString() {
642  if ( !$this->wasPosted() ) {
643  return '';
644  }
645  return $this->getRawInput();
646  }
647 
655  public function getRawInput() {
656  static $input = null;
657  if ( $input === null ) {
658  $input = file_get_contents( 'php://input' );
659  }
660  return $input;
661  }
662 
668  public function getMethod() {
669  return isset( $_SERVER['REQUEST_METHOD'] ) ? $_SERVER['REQUEST_METHOD'] : 'GET';
670  }
671 
681  public function wasPosted() {
682  return $this->getMethod() == 'POST';
683  }
684 
692  public function getSession() {
693  if ( $this->sessionId !== null ) {
694  $session = SessionManager::singleton()->getSessionById( (string)$this->sessionId, true, $this );
695  if ( $session ) {
696  return $session;
697  }
698  }
699 
700  $session = SessionManager::singleton()->getSessionForRequest( $this );
701  $this->sessionId = $session->getSessionId();
702  return $session;
703  }
704 
711  public function setSessionId( SessionId $sessionId ) {
712  $this->sessionId = $sessionId;
713  }
714 
721  public function getSessionId() {
722  return $this->sessionId;
723  }
724 
734  public function checkSessionCookie() {
736  wfDeprecated( __METHOD__, '1.27' );
737  return $wgInitialSessionId !== null &&
738  $this->getSession()->getId() === (string)$wgInitialSessionId;
739  }
740 
749  public function getCookie( $key, $prefix = null, $default = null ) {
750  if ( $prefix === null ) {
752  $prefix = $wgCookiePrefix;
753  }
754  return $this->getGPCVal( $_COOKIE, $prefix . $key, $default );
755  }
756 
764  public static function getGlobalRequestURL() {
765  if ( isset( $_SERVER['REQUEST_URI'] ) && strlen( $_SERVER['REQUEST_URI'] ) ) {
766  $base = $_SERVER['REQUEST_URI'];
767  } elseif ( isset( $_SERVER['HTTP_X_ORIGINAL_URL'] )
768  && strlen( $_SERVER['HTTP_X_ORIGINAL_URL'] )
769  ) {
770  // Probably IIS; doesn't set REQUEST_URI
771  $base = $_SERVER['HTTP_X_ORIGINAL_URL'];
772  } elseif ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
773  $base = $_SERVER['SCRIPT_NAME'];
774  if ( isset( $_SERVER['QUERY_STRING'] ) && $_SERVER['QUERY_STRING'] != '' ) {
775  $base .= '?' . $_SERVER['QUERY_STRING'];
776  }
777  } else {
778  // This shouldn't happen!
779  throw new MWException( "Web server doesn't provide either " .
780  "REQUEST_URI, HTTP_X_ORIGINAL_URL or SCRIPT_NAME. Report details " .
781  "of your web server configuration to https://phabricator.wikimedia.org/" );
782  }
783  // User-agents should not send a fragment with the URI, but
784  // if they do, and the web server passes it on to us, we
785  // need to strip it or we get false-positive redirect loops
786  // or weird output URLs
787  $hash = strpos( $base, '#' );
788  if ( $hash !== false ) {
789  $base = substr( $base, 0, $hash );
790  }
791 
792  if ( $base[0] == '/' ) {
793  // More than one slash will look like it is protocol relative
794  return preg_replace( '!^/+!', '/', $base );
795  } else {
796  // We may get paths with a host prepended; strip it.
797  return preg_replace( '!^[^:]+://[^/]+/+!', '/', $base );
798  }
799  }
800 
808  public function getRequestURL() {
809  return self::getGlobalRequestURL();
810  }
811 
822  public function getFullRequestURL() {
823  return wfExpandUrl( $this->getRequestURL(), PROTO_CURRENT );
824  }
825 
831  public function appendQueryValue( $key, $value ) {
832  return $this->appendQueryArray( [ $key => $value ] );
833  }
834 
841  public function appendQueryArray( $array ) {
842  $newquery = $this->getQueryValues();
843  unset( $newquery['title'] );
844  $newquery = array_merge( $newquery, $array );
845 
846  return wfArrayToCgi( $newquery );
847  }
848 
858  public function getLimitOffset( $deflimit = 50, $optionname = 'rclimit' ) {
859  global $wgUser;
860 
861  $limit = $this->getInt( 'limit', 0 );
862  if ( $limit < 0 ) {
863  $limit = 0;
864  }
865  if ( ( $limit == 0 ) && ( $optionname != '' ) ) {
866  $limit = $wgUser->getIntOption( $optionname );
867  }
868  if ( $limit <= 0 ) {
869  $limit = $deflimit;
870  }
871  if ( $limit > 5000 ) {
872  $limit = 5000; # We have *some* limits...
873  }
874 
875  $offset = $this->getInt( 'offset', 0 );
876  if ( $offset < 0 ) {
877  $offset = 0;
878  }
879 
880  return [ $limit, $offset ];
881  }
882 
889  public function getFileTempname( $key ) {
890  $file = new WebRequestUpload( $this, $key );
891  return $file->getTempName();
892  }
893 
900  public function getUploadError( $key ) {
901  $file = new WebRequestUpload( $this, $key );
902  return $file->getError();
903  }
904 
916  public function getFileName( $key ) {
917  $file = new WebRequestUpload( $this, $key );
918  return $file->getName();
919  }
920 
927  public function getUpload( $key ) {
928  return new WebRequestUpload( $this, $key );
929  }
930 
937  public function response() {
938  /* Lazy initialization of response object for this request */
939  if ( !is_object( $this->response ) ) {
940  $class = ( $this instanceof FauxRequest ) ? 'FauxResponse' : 'WebResponse';
941  $this->response = new $class();
942  }
943  return $this->response;
944  }
945 
949  protected function initHeaders() {
950  if ( count( $this->headers ) ) {
951  return;
952  }
953 
954  $apacheHeaders = function_exists( 'apache_request_headers' ) ? apache_request_headers() : false;
955  if ( $apacheHeaders ) {
956  foreach ( $apacheHeaders as $tempName => $tempValue ) {
957  $this->headers[strtoupper( $tempName )] = $tempValue;
958  }
959  } else {
960  foreach ( $_SERVER as $name => $value ) {
961  if ( substr( $name, 0, 5 ) === 'HTTP_' ) {
962  $name = str_replace( '_', '-', substr( $name, 5 ) );
963  $this->headers[$name] = $value;
964  } elseif ( $name === 'CONTENT_LENGTH' ) {
965  $this->headers['CONTENT-LENGTH'] = $value;
966  }
967  }
968  }
969  }
970 
976  public function getAllHeaders() {
977  $this->initHeaders();
978  return $this->headers;
979  }
980 
993  public function getHeader( $name, $flags = 0 ) {
994  $this->initHeaders();
995  $name = strtoupper( $name );
996  if ( !isset( $this->headers[$name] ) ) {
997  return false;
998  }
999  $value = $this->headers[$name];
1000  if ( $flags & self::GETHEADER_LIST ) {
1001  $value = array_map( 'trim', explode( ',', $value ) );
1002  }
1003  return $value;
1004  }
1005 
1013  public function getSessionData( $key ) {
1014  return $this->getSession()->get( $key );
1015  }
1016 
1024  public function setSessionData( $key, $data ) {
1025  return $this->getSession()->set( $key, $data );
1026  }
1027 
1038  public function checkUrlExtension( $extWhitelist = [] ) {
1039  $extWhitelist[] = 'php';
1040  if ( IEUrlExtension::areServerVarsBad( $_SERVER, $extWhitelist ) ) {
1041  if ( !$this->wasPosted() ) {
1042  $newUrl = IEUrlExtension::fixUrlForIE6(
1043  $this->getFullRequestURL(), $extWhitelist );
1044  if ( $newUrl !== false ) {
1045  $this->doSecurityRedirect( $newUrl );
1046  return false;
1047  }
1048  }
1049  throw new HttpError( 403,
1050  'Invalid file extension found in the path info or query string.' );
1051  }
1052  return true;
1053  }
1054 
1062  protected function doSecurityRedirect( $url ) {
1063  header( 'Location: ' . $url );
1064  header( 'Content-Type: text/html' );
1065  $encUrl = htmlspecialchars( $url );
1066  echo <<<HTML
1067 <html>
1068 <head>
1069 <title>Security redirect</title>
1070 </head>
1071 <body>
1072 <h1>Security redirect</h1>
1073 <p>
1074 We can't serve non-HTML content from the URL you have requested, because
1075 Internet Explorer would interpret it as an incorrect and potentially dangerous
1076 content type.</p>
1077 <p>Instead, please use <a href="$encUrl">this URL</a>, which is the same as the
1078 URL you have requested, except that "&amp;*" is appended. This prevents Internet
1079 Explorer from seeing a bogus file extension.
1080 </p>
1081 </body>
1082 </html>
1083 HTML;
1084  echo "\n";
1085  return true;
1086  }
1087 
1097  public function getAcceptLang() {
1098  // Modified version of code found at
1099  // http://www.thefutureoftheweb.com/blog/use-accept-language-header
1100  $acceptLang = $this->getHeader( 'Accept-Language' );
1101  if ( !$acceptLang ) {
1102  return [];
1103  }
1104 
1105  // Return the language codes in lower case
1106  $acceptLang = strtolower( $acceptLang );
1107 
1108  // Break up string into pieces (languages and q factors)
1109  $lang_parse = null;
1110  preg_match_all(
1111  '/([a-z]{1,8}(-[a-z]{1,8})*|\*)\s*(;\s*q\s*=\s*(1(\.0{0,3})?|0(\.[0-9]{0,3})?)?)?/',
1112  $acceptLang,
1113  $lang_parse
1114  );
1115 
1116  if ( !count( $lang_parse[1] ) ) {
1117  return [];
1118  }
1119 
1120  $langcodes = $lang_parse[1];
1121  $qvalues = $lang_parse[4];
1122  $indices = range( 0, count( $lang_parse[1] ) - 1 );
1123 
1124  // Set default q factor to 1
1125  foreach ( $indices as $index ) {
1126  if ( $qvalues[$index] === '' ) {
1127  $qvalues[$index] = 1;
1128  } elseif ( $qvalues[$index] == 0 ) {
1129  unset( $langcodes[$index], $qvalues[$index], $indices[$index] );
1130  }
1131  }
1132 
1133  // Sort list. First by $qvalues, then by order. Reorder $langcodes the same way
1134  array_multisort( $qvalues, SORT_DESC, SORT_NUMERIC, $indices, $langcodes );
1135 
1136  // Create a list like "en" => 0.8
1137  $langs = array_combine( $langcodes, $qvalues );
1138 
1139  return $langs;
1140  }
1141 
1150  protected function getRawIP() {
1151  if ( !isset( $_SERVER['REMOTE_ADDR'] ) ) {
1152  return null;
1153  }
1154 
1155  if ( is_array( $_SERVER['REMOTE_ADDR'] ) || strpos( $_SERVER['REMOTE_ADDR'], ',' ) !== false ) {
1156  throw new MWException( __METHOD__
1157  . " : Could not determine the remote IP address due to multiple values." );
1158  } else {
1159  $ipchain = $_SERVER['REMOTE_ADDR'];
1160  }
1161 
1162  return IP::canonicalize( $ipchain );
1163  }
1164 
1174  public function getIP() {
1175  global $wgUsePrivateIPs;
1176 
1177  # Return cached result
1178  if ( $this->ip !== null ) {
1179  return $this->ip;
1180  }
1181 
1182  # collect the originating ips
1183  $ip = $this->getRawIP();
1184  if ( !$ip ) {
1185  throw new MWException( 'Unable to determine IP.' );
1186  }
1187 
1188  # Append XFF
1189  $forwardedFor = $this->getHeader( 'X-Forwarded-For' );
1190  if ( $forwardedFor !== false ) {
1191  $isConfigured = IP::isConfiguredProxy( $ip );
1192  $ipchain = array_map( 'trim', explode( ',', $forwardedFor ) );
1193  $ipchain = array_reverse( $ipchain );
1194  array_unshift( $ipchain, $ip );
1195 
1196  # Step through XFF list and find the last address in the list which is a
1197  # trusted server. Set $ip to the IP address given by that trusted server,
1198  # unless the address is not sensible (e.g. private). However, prefer private
1199  # IP addresses over proxy servers controlled by this site (more sensible).
1200  # Note that some XFF values might be "unknown" with Squid/Varnish.
1201  foreach ( $ipchain as $i => $curIP ) {
1202  $curIP = IP::sanitizeIP( IP::canonicalize( $curIP ) );
1203  if ( !$curIP || !isset( $ipchain[$i + 1] ) || $ipchain[$i + 1] === 'unknown'
1204  || !IP::isTrustedProxy( $curIP )
1205  ) {
1206  break; // IP is not valid/trusted or does not point to anything
1207  }
1208  if (
1209  IP::isPublic( $ipchain[$i + 1] ) ||
1210  $wgUsePrivateIPs ||
1211  IP::isConfiguredProxy( $curIP ) // bug 48919; treat IP as sane
1212  ) {
1213  // Follow the next IP according to the proxy
1214  $nextIP = IP::canonicalize( $ipchain[$i + 1] );
1215  if ( !$nextIP && $isConfigured ) {
1216  // We have not yet made it past CDN/proxy servers of this site,
1217  // so either they are misconfigured or there is some IP spoofing.
1218  throw new MWException( "Invalid IP given in XFF '$forwardedFor'." );
1219  }
1220  $ip = $nextIP;
1221  // keep traversing the chain
1222  continue;
1223  }
1224  break;
1225  }
1226  }
1227 
1228  # Allow extensions to improve our guess
1229  Hooks::run( 'GetIP', [ &$ip ] );
1230 
1231  if ( !$ip ) {
1232  throw new MWException( "Unable to determine IP." );
1233  }
1234 
1235  wfDebug( "IP: $ip\n" );
1236  $this->ip = $ip;
1237  return $ip;
1238  }
1239 
1245  public function setIP( $ip ) {
1246  $this->ip = $ip;
1247  }
1248 }
$wgInitialSessionId
Definition: Setup.php:730
and how to run hooks for an and one after Each event has a preferably in CamelCase For ArticleDelete hook A clump of code and data that should be run when an event happens This can be either a function and a chunk of data
Definition: hooks.txt:6
float $requestTime
The timestamp of the start of the request, with microsecond precision.
Definition: WebRequest.php:68
the array() calling protocol came about after MediaWiki 1.4rc1.
getUploadError($key)
Return the upload error or 0.
Definition: WebRequest.php:900
getRawPostString()
Return the contents of the POST with no decoding.
Definition: WebRequest.php:641
$wgScript
The URL path to index.php.
magic word the default is to use $key to get the and $key value or $key value text $key value html to format the value $key
Definition: hooks.txt:2321
I won t presume to tell you how to I m just describing the methods I chose to use for myself If you do choose to follow these it will probably be easier for you to collaborate with others on the but if you want to contribute without by all means do which work well I also use K &R brace matching style I know that s a religious issue for some
Definition: design.txt:79
static getRequestId()
Get the unique request ID.
Definition: WebRequest.php:265
getFileTempname($key)
Return the path to the temporary file where PHP has stored the upload.
Definition: WebRequest.php:889
getFullRequestURL()
Return the request URI with the canonical service and hostname, path, and query string.
Definition: WebRequest.php:822
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
Definition: hooks.txt:1798
$wgActionPaths
Definition: img_auth.php:46
static areServerVarsBad($vars, $extWhitelist=[])
Check a subset of $_SERVER (or the whole of $_SERVER if you like) to see if it indicates that the req...
response()
Return a handle to WebResponse style object, for setting cookies, headers and other stuff...
Definition: WebRequest.php:937
getUpload($key)
Return a WebRequestUpload object corresponding to the key.
Definition: WebRequest.php:927
getIntOrNull($name)
Fetch an integer value from the input or return null if empty.
Definition: WebRequest.php:502
string $protocol
Cached URL protocol.
Definition: WebRequest.php:74
getFuzzyBool($name, $default=false)
Fetch a boolean value from the input or return $default if not set.
Definition: WebRequest.php:545
This code would result in ircNotify being run twice when an article is and once for brion Hooks can return three possible true was required This is the default since MediaWiki *some string
Definition: hooks.txt:177
$value
getBool($name, $default=false)
Fetch a boolean value from the input or return $default if not set.
Definition: WebRequest.php:532
getGPCVal($arr, $name, $default)
Fetch a value from the given array or return $default if it's not set.
Definition: WebRequest.php:373
const PROTO_CURRENT
Definition: Defines.php:264
it s the revision text itself In either if gzip is the revision text is gzipped $flags
Definition: hooks.txt:2548
const GETHEADER_LIST
Flag to make WebRequest::getHeader return an array of values.
Definition: WebRequest.php:44
getSession()
Return the session for this request.
Definition: WebRequest.php:692
when a variable name is used in a it is silently declared as a new local masking the global
Definition: design.txt:93
wfExpandUrl($url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
$wgArticlePath
Definition: img_auth.php:45
add($path, $params=[], $options=[])
Add a new path pattern to the path router.
Definition: PathRouter.php:160
initHeaders()
Initialise the header list.
Definition: WebRequest.php:949
string $ip
Cached client IP address.
Definition: WebRequest.php:62
wfRandomString($length=32)
Get a random string containing a number of pseudo-random hex characters.
doSecurityRedirect($url)
Attempt to redirect to a URL with a QUERY_STRING that's not dangerous in IE 6.
getArray($name, $default=null)
Fetch an array from the input or return $default if it's not set.
Definition: WebRequest.php:454
Show an error that looks like an HTTP server error.
Definition: HttpError.php:30
getAllHeaders()
Get an array containing all request headers.
Definition: WebRequest.php:976
static detectServer()
Work out an appropriate URL prefix containing scheme and host, based on information detected from $_S...
Definition: WebRequest.php:190
setVal($key, $value)
Set an arbitrary value into our get/post data.
Definition: WebRequest.php:423
getHeader($name, $flags=0)
Get a request header, or false if it isn't set.
Definition: WebRequest.php:993
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add headers
Definition: design.txt:12
getFloat($name, $default=0.0)
Fetch a floating point value from the input or return $default if not set.
Definition: WebRequest.php:519
getProtocol()
Get the current URL protocol (http or https)
Definition: WebRequest.php:289
wasPosted()
Returns true if the present request was reached by a POST operation, false otherwise (GET...
Definition: WebRequest.php:681
getRequestURL()
Return the path and query string portion of the request URI.
Definition: WebRequest.php:808
PathRouter class.
Definition: PathRouter.php:73
static combineHostAndPort($host, $port, $defaultPort=false)
Given a host name and a port, combine them into host/port string like you might find in a URL...
Definition: IP.php:303
getSessionData($key)
Get data from the session.
getQueryValues()
Get the values passed in the query string.
Definition: WebRequest.php:621
unsetVal($key)
Unset an arbitrary value from our get/post data.
Definition: WebRequest.php:435
getCheck($name)
Return true if the named value is set in the input, whatever that value is (even "0").
Definition: WebRequest.php:557
$wgUsePathInfo
Whether to support URLs like index.php/Page_title These often break when PHP is set up in CGI mode...
getFileName($key)
Return the original filename of the uploaded file, as reported by the submitting user agent...
Definition: WebRequest.php:916
bool $wgAssumeProxiesUseDefaultProtocolPorts
When the wiki is running behind a proxy and this is set to true, assumes that the proxy exposes the w...
wfDeprecated($function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
title
static run($event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:131
static overrideRequestId($id)
Override the unique request ID.
Definition: WebRequest.php:281
getValueNames($exclude=[])
Returns the names of all input values excluding those in $exclude.
Definition: WebRequest.php:611
static detectProtocol()
Detect the protocol from $_SERVER.
Definition: WebRequest.php:236
getSessionId()
Get the session id for this request, if any.
Definition: WebRequest.php:721
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
getIntArray($name, $default=null)
Fetch an array of integers, or return $default if it's not set.
Definition: WebRequest.php:473
getValues()
Extracts the given named values into an array.
Definition: WebRequest.php:589
setSessionId(SessionId $sessionId)
Set the session for this request.
Definition: WebRequest.php:711
WebResponse $response
Lazy-init response object.
Definition: WebRequest.php:56
getVal($name, $default=null)
Fetch a scalar from the input or return $default if it's not set.
Definition: WebRequest.php:404
static splitHostAndPort($both)
Given a host/port string, like one might find in the host part of a URL per RFC 2732, split the hostname part and the port part and return an array with an element for each.
Definition: IP.php:254
SessionId null $sessionId
Session ID to use for this request.
Definition: WebRequest.php:81
A collection of public static functions to play with IP address and IP blocks.
Definition: IP.php:67
static getGlobalRequestURL()
Return the path and query string portion of the main request URI.
Definition: WebRequest.php:764
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
if($wgLocalInterwiki) if($wgSharedPrefix===false) if($wgSharedSchema===false) if(!$wgCookiePrefix) $wgCookiePrefix
Definition: Setup.php:342
getMethod()
Get the HTTP method used for this request.
Definition: WebRequest.php:668
appendQueryValue($key, $value)
Definition: WebRequest.php:831
Value object holding the session ID in a manner that can be globally updated.
Definition: SessionId.php:38
wfArrayToCgi($array1, $array2=null, $prefix= '')
This function takes one or two arrays as input, and returns a CGI-style string, e.g.
static extractTitle($path, $bases, $key=false)
URL rewriting function; tries to extract page title and, optionally, one other fixed parameter value ...
Definition: WebRequest.php:325
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context the output can only depend on parameters provided to this hook not on global state indicating whether full HTML should be generated If generation of HTML may be but other information should still be present in the ParserOutput object to manipulate or replace but no entry for that model exists in $wgContentHandlers if desired whether it is OK to use $contentModel on $title Handler functions that modify $ok should generally return false to prevent further hooks from further modifying $ok inclusive $limit
Definition: hooks.txt:1004
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the local content language as $wgContLang
Definition: design.txt:56
getRawInput()
Return the raw request body, with no processing.
Definition: WebRequest.php:655
interpolateTitle()
Check for title, action, and/or variant data in the URL and interpolate it into the GET variables...
Definition: WebRequest.php:303
This list may contain false positives That usually means there is additional text with links below the first Each row contains links to the first and second redirect
checkSessionCookie()
Returns true if the request has a persistent session.
Definition: WebRequest.php:734
getCookie($key, $prefix=null, $default=null)
Get a cookie from the $_COOKIE jar.
Definition: WebRequest.php:749
static getPathInfo($want= 'all')
Extract relevant query arguments from the http request uri's path to be merged with the normal php pr...
Definition: WebRequest.php:107
checkUrlExtension($extWhitelist=[])
Check if Internet Explorer will detect an incorrect cache extension in PATH_INFO or QUERY_STRING...
setSessionData($key, $data)
Set session data.
static string $reqId
The unique request ID.
Definition: WebRequest.php:50
getInt($name, $default=0)
Fetch an integer value from the input or return $default if not set.
Definition: WebRequest.php:490
appendQueryArray($array)
Appends or replaces value of query variables.
Definition: WebRequest.php:841
getElapsedTime()
Get the number of seconds to have elapsed since request start, in fractional seconds, with microsecond resolution.
Definition: WebRequest.php:253
$wgVariantArticlePath
Like $wgArticlePath, but on multi-variant wikis, this provides a path format that describes which par...
getLimitOffset($deflimit=50, $optionname= 'rclimit')
Check for limit and offset parameters on the input, and return sensible defaults if not given...
Definition: WebRequest.php:858
normalizeUnicode($data)
Recursively normalizes UTF-8 strings in the given array.
Definition: WebRequest.php:351
Object to access the $_FILES array.
getText($name, $default= '')
Fetch a text string from the given array or return $default if it's not set.
Definition: WebRequest.php:575
getRawQueryString()
Return the contents of the Query with no decoding.
Definition: WebRequest.php:631
$wgUser
Definition: Setup.php:794
$matches
static fixUrlForIE6($url, $extWhitelist=[])
Returns a variant of $url which will pass isUrlExtensionBad() but has the same GET parameters...
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:310