1<?php 2/** 3 * Deal with importing all those nasty globals and things 4 * 5 * Copyright © 2003 Brion Vibber <brion@pobox.com> 6 * https://www.mediawiki.org/ 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License along 19 * with this program; if not, write to the Free Software Foundation, Inc., 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 * http://www.gnu.org/copyleft/gpl.html 22 * 23 * @file 24 */ 25 26use MediaWiki\Session\SessionManager; 27 28/** 29 * WebRequest clone which takes values from a provided array. 30 * 31 * @newable 32 * 33 * @ingroup HTTP 34 */ 35class FauxRequest extends WebRequest { 36 private $wasPosted = false; 37 private $requestUrl; 38 protected $cookies = []; 39 /** @var array */ 40 private $uploadData = []; 41 42 /** 43 * @stable to call 44 * 45 * @param array $data Array of *non*-urlencoded key => value pairs, the 46 * fake GET/POST values 47 * @param bool $wasPosted Whether to treat the data as POST 48 * @param MediaWiki\Session\Session|array|null $session Session, session 49 * data array, or null 50 * @param string $protocol 'http' or 'https' 51 * @throws MWException 52 */ 53 public function __construct( $data = [], $wasPosted = false, 54 $session = null, $protocol = 'http' 55 ) { 56 $this->requestTime = microtime( true ); 57 58 if ( is_array( $data ) ) { 59 $this->data = $data; 60 } else { 61 throw new MWException( "FauxRequest() got bogus data" ); 62 } 63 $this->wasPosted = $wasPosted; 64 if ( $session instanceof MediaWiki\Session\Session ) { 65 $this->sessionId = $session->getSessionId(); 66 } elseif ( is_array( $session ) ) { 67 $mwsession = SessionManager::singleton()->getEmptySession( $this ); 68 $this->sessionId = $mwsession->getSessionId(); 69 foreach ( $session as $key => $value ) { 70 $mwsession->set( $key, $value ); 71 } 72 } elseif ( $session !== null ) { 73 throw new MWException( "FauxRequest() got bogus session" ); 74 } 75 $this->protocol = $protocol; 76 } 77 78 /** 79 * Initialise the header list 80 */ 81 protected function initHeaders() { 82 // Nothing to init 83 } 84 85 /** 86 * @param string $name 87 * @param string $default 88 * @return string 89 */ 90 public function getText( $name, $default = '' ) { 91 # Override; don't recode since we're using internal data 92 return (string)$this->getVal( $name, $default ); 93 } 94 95 /** 96 * @return array 97 */ 98 public function getQueryValues() { 99 if ( $this->wasPosted ) { 100 return []; 101 } else { 102 return $this->data; 103 } 104 } 105 106 public function getMethod() { 107 return $this->wasPosted ? 'POST' : 'GET'; 108 } 109 110 /** 111 * @return bool 112 */ 113 public function wasPosted() { 114 return $this->wasPosted; 115 } 116 117 public function getCookie( $key, $prefix = null, $default = null ) { 118 if ( $prefix === null ) { 119 global $wgCookiePrefix; 120 $prefix = $wgCookiePrefix; 121 } 122 $name = $prefix . $key; 123 return $this->cookies[$name] ?? $default; 124 } 125 126 /** 127 * @since 1.26 128 * @param string $key Unprefixed name of the cookie to set 129 * @param string|null $value Value of the cookie to set 130 * @param string|null $prefix Cookie prefix. Defaults to $wgCookiePrefix 131 */ 132 public function setCookie( $key, $value, $prefix = null ) { 133 $this->setCookies( [ $key => $value ], $prefix ); 134 } 135 136 /** 137 * @since 1.26 138 * @param array $cookies 139 * @param string|null $prefix Cookie prefix. Defaults to $wgCookiePrefix 140 */ 141 public function setCookies( $cookies, $prefix = null ) { 142 if ( $prefix === null ) { 143 global $wgCookiePrefix; 144 $prefix = $wgCookiePrefix; 145 } 146 foreach ( $cookies as $key => $value ) { 147 $name = $prefix . $key; 148 $this->cookies[$name] = $value; 149 } 150 } 151 152 /** 153 * Set fake upload data for all files 154 * 155 * @since 1.37 156 * @param (array|WebRequestUpload)[] $uploadData 157 */ 158 public function setUploadData( $uploadData ) { 159 foreach ( $uploadData as $key => $data ) { 160 $this->setUpload( $key, $data ); 161 } 162 } 163 164 /** 165 * Set fake upload data for one file with specific key 166 * 167 * @since 1.37 168 * @param string $key 169 * @param array|WebRequestUpload $data 170 */ 171 public function setUpload( $key, $data ) { 172 if ( $data instanceof WebRequestUpload ) { 173 // cannot reuse WebRequestUpload, because it contains the original web request object 174 $data = [ 175 'name' => $data->getName(), 176 'type' => $data->getType(), 177 'tmp_name' => $data->getTempName(), 178 'size' => $data->getSize(), 179 'error' => $data->getError(), 180 ]; 181 } 182 // Check if everything is provided 183 if ( !is_array( $data ) || 184 array_diff( WebRequestUpload::REQUIRED_FILEINFO_KEYS, array_keys( $data ) ) !== [] 185 ) { 186 throw new MWException( __METHOD__ . ' got bogus data' ); 187 } 188 $this->uploadData[$key] = $data; 189 } 190 191 /** 192 * Return a FauxRequestUpload object corresponding to the key 193 * 194 * @param string $key 195 * @return FauxRequestUpload 196 */ 197 public function getUpload( $key ) { 198 return new FauxRequestUpload( $this->uploadData, $this, $key ); 199 } 200 201 /** 202 * @since 1.25 203 * @param string $url 204 */ 205 public function setRequestURL( $url ) { 206 $this->requestUrl = $url; 207 } 208 209 /** 210 * @since 1.25 MWException( "getRequestURL not implemented" ) 211 * no longer thrown. 212 * @return string 213 */ 214 public function getRequestURL() { 215 if ( $this->requestUrl === null ) { 216 throw new MWException( 'Request URL not set' ); 217 } 218 return $this->requestUrl; 219 } 220 221 public function getProtocol() { 222 return $this->protocol; 223 } 224 225 /** 226 * @param string $name 227 * @param string $val 228 */ 229 public function setHeader( $name, $val ) { 230 $this->setHeaders( [ $name => $val ] ); 231 } 232 233 /** 234 * @since 1.26 235 * @param array $headers 236 */ 237 public function setHeaders( $headers ) { 238 foreach ( $headers as $name => $val ) { 239 $name = strtoupper( $name ); 240 $this->headers[$name] = $val; 241 } 242 } 243 244 /** 245 * @return array|null 246 */ 247 public function getSessionArray() { 248 if ( $this->sessionId !== null ) { 249 return iterator_to_array( $this->getSession() ); 250 } 251 return null; 252 } 253 254 public function getPostValues() { 255 return $this->wasPosted ? $this->data : []; 256 } 257 258 /** 259 * FauxRequests shouldn't depend on raw request data (but that could be implemented here) 260 * @return string 261 */ 262 public function getRawQueryString() { 263 return ''; 264 } 265 266 /** 267 * FauxRequests shouldn't depend on raw request data (but that could be implemented here) 268 * @return string 269 */ 270 public function getRawPostString() { 271 return ''; 272 } 273 274 /** 275 * FauxRequests shouldn't depend on raw request data (but that could be implemented here) 276 * @return string 277 */ 278 public function getRawInput() { 279 return ''; 280 } 281 282 /** 283 * @codeCoverageIgnore 284 * @return string 285 */ 286 protected function getRawIP() { 287 return '127.0.0.1'; 288 } 289} 290