]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/WebRequest.php
MediaWiki 1.5.8 (initial commit)
[autoinstalls/mediawiki.git] / includes / WebRequest.php
1 <?php
2 /**
3  * Deal with importing all those nasssty globals and things
4  * @package MediaWiki
5  */
6
7 # Copyright (C) 2003 Brion Vibber <brion@pobox.com>
8 # http://www.mediawiki.org/
9
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or 
13 # (at your option) any later version.
14
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
19
20 # You should have received a copy of the GNU General Public License along
21 # with this program; if not, write to the Free Software Foundation, Inc.,
22 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 # http://www.gnu.org/copyleft/gpl.html
24
25 /**
26  * The WebRequest class encapsulates getting at data passed in the
27  * URL or via a POSTed form, handling remove of "magic quotes" slashes,
28  * stripping illegal input characters and normalizing Unicode sequences.
29  *
30  * Usually this is used via a global singleton, $wgRequest. You should
31  * not create a second WebRequest object; make a FauxRequest object if
32  * you want to pass arbitrary data to some function in place of the web
33  * input.
34  *
35  * @package MediaWiki
36  */
37 class WebRequest {
38         function WebRequest() {
39                 $this->checkMagicQuotes();
40                 global $wgUsePathInfo;
41                 if( isset( $_SERVER['PATH_INFO'] ) && ($_SERVER['PATH_INFO'] != '') && $wgUsePathInfo ) {
42                         # Stuff it!
43                         $_GET['title'] = $_REQUEST['title'] =
44                                 substr( $_SERVER['PATH_INFO'], 1 );
45                 }
46         }
47
48         /**
49          * Recursively strips slashes from the given array;
50          * used for undoing the evil that is magic_quotes_gpc.
51          * @param array &$arr will be modified
52          * @return array the original array
53          * @private
54          */
55         function &fix_magic_quotes( &$arr ) {
56                 foreach( $arr as $key => $val ) {
57                         if( is_array( $val ) ) {
58                                 $this->fix_magic_quotes( $arr[$key] );
59                         } else {
60                                 $arr[$key] = stripslashes( $val );
61                         }
62                 }
63                 return $arr;
64         }
65         
66         /**
67          * If magic_quotes_gpc option is on, run the global arrays
68          * through fix_magic_quotes to strip out the stupid slashes.
69          * WARNING: This should only be done once! Running a second
70          * time could damage the values.
71          * @private
72          */
73         function checkMagicQuotes() {
74                 if ( get_magic_quotes_gpc() ) {
75                         $this->fix_magic_quotes( $_COOKIE );
76                         $this->fix_magic_quotes( $_ENV );
77                         $this->fix_magic_quotes( $_GET );
78                         $this->fix_magic_quotes( $_POST );
79                         $this->fix_magic_quotes( $_REQUEST );
80                         $this->fix_magic_quotes( $_SERVER );
81                 }
82         }
83         
84         /**
85          * Recursively normalizes UTF-8 strings in the given array.
86          * @param array $data string or array
87          * @return cleaned-up version of the given
88          * @private
89          */
90         function normalizeUnicode( $data ) {
91                 if( is_array( $data ) ) {
92                         foreach( $data as $key => $val ) {
93                                 $data[$key] = $this->normalizeUnicode( $val );
94                         }
95                 } else {
96                         $data = UtfNormal::cleanUp( $data );
97                 }
98                 return $data;
99         }
100         
101         /**
102          * Fetch a value from the given array or return $default if it's not set.
103          *
104          * @param array &$arr
105          * @param string $name
106          * @param mixed $default
107          * @return mixed
108          * @private
109          */
110         function getGPCVal( &$arr, $name, $default ) {
111                 if( isset( $arr[$name] ) ) {
112                         global $wgServer, $wgContLang;
113                         $data = $arr[$name];
114                         if( isset( $_GET[$name] ) && !is_array( $data ) ) {
115                                 # Check for alternate/legacy character encoding.
116                                 if( isset( $wgContLang ) ) {
117                                         $data = $wgContLang->checkTitleEncoding( $data );
118                                 }
119                         }
120                         require_once( 'normal/UtfNormal.php' );
121                         $data = $this->normalizeUnicode( $data );
122                         return $data;
123                 } else {
124                         return $default;
125                 }
126         }
127
128         /**
129          * Fetch a scalar from the input or return $default if it's not set.
130          * Returns a string. Arrays are discarded.
131          *
132          * @param string $name
133          * @param string $default optional default (or NULL)
134          * @return string
135          */
136         function getVal( $name, $default = NULL ) {
137                 $val = $this->getGPCVal( $_REQUEST, $name, $default );
138                 if( is_array( $val ) ) {
139                         $val = $default;
140                 }
141                 if( is_null( $val ) ) {
142                         return null;
143                 } else {
144                         return (string)$val;
145                 }
146         }
147         
148         /**
149          * Fetch an array from the input or return $default if it's not set.
150          * If source was scalar, will return an array with a single element.
151          * If no source and no default, returns NULL.
152          *
153          * @param string $name
154          * @param array $default optional default (or NULL)
155          * @return array
156          */
157         function getArray( $name, $default = NULL ) {
158                 $val = $this->getGPCVal( $_REQUEST, $name, $default );
159                 if( is_null( $val ) ) {
160                         return null;
161                 } else {
162                         return (array)$val;
163                 }
164         }
165
166         /**
167          * Fetch an integer value from the input or return $default if not set.
168          * Guaranteed to return an integer; non-numeric input will typically
169          * return 0.
170          * @param string $name
171          * @param int $default
172          * @return int
173          */
174         function getInt( $name, $default = 0 ) {
175                 return IntVal( $this->getVal( $name, $default ) );
176         }
177         
178         /**
179          * Fetch an integer value from the input or return null if empty.
180          * Guaranteed to return an integer or null; non-numeric input will
181          * typically return null.
182          * @param string $name
183          * @return int
184          */
185         function getIntOrNull( $name ) {
186                 $val = $this->getVal( $name );
187                 return is_numeric( $val )
188                         ? IntVal( $val )
189                         : null;
190         }
191         
192         /**
193          * Fetch a boolean value from the input or return $default if not set.
194          * Guaranteed to return true or false, with normal PHP semantics for
195          * boolean interpretation of strings.
196          * @param string $name
197          * @param bool $default
198          * @return bool
199          */
200         function getBool( $name, $default = false ) {
201                 return $this->getVal( $name, $default ) ? true : false;
202         }
203         
204         /**
205          * Return true if the named value is set in the input, whatever that
206          * value is (even "0"). Return false if the named value is not set.
207          * Example use is checking for the presence of check boxes in forms.
208          * @param string $name
209          * @return bool
210          */
211         function getCheck( $name ) {
212                 # Checkboxes and buttons are only present when clicked
213                 # Presence connotes truth, abscense false
214                 $val = $this->getVal( $name, NULL );
215                 return isset( $val );
216         }
217         
218         /**
219          * Fetch a text string from the given array or return $default if it's not
220          * set. \r is stripped from the text, and with some language modules there 
221          * is an input transliteration applied. This should generally be used for
222          * form <textarea> and <input> fields.
223          *
224          * @param string $name
225          * @param string $default optional
226          * @return string
227          */
228         function getText( $name, $default = '' ) {
229                 global $wgContLang;
230                 $val = $this->getVal( $name, $default );
231                 return str_replace( "\r\n", "\n",
232                         $wgContLang->recodeInput( $val ) );
233         }
234         
235         /**
236          * Extracts the given named values into an array.
237          * If no arguments are given, returns all input values.
238          * No transformation is performed on the values.
239          */
240         function getValues() {  
241                 $names = func_get_args();
242                 if ( count( $names ) == 0 ) {
243                         $names = array_keys( $_REQUEST );
244                 }
245
246                 $retVal = array();
247                 foreach ( $names as $name ) { 
248                         $value = $this->getVal( $name );
249                         if ( !is_null( $value ) ) {
250                                 $retVal[$name] = $value;
251                         }
252                 }
253                 return $retVal;
254         }
255
256         /**
257          * Returns true if the present request was reached by a POST operation,
258          * false otherwise (GET, HEAD, or command-line).
259          *
260          * Note that values retrieved by the object may come from the
261          * GET URL etc even on a POST request.
262          *
263          * @return bool
264          */
265         function wasPosted() {
266                 return $_SERVER['REQUEST_METHOD'] == 'POST';
267         }
268         
269         /**
270          * Returns true if there is a session cookie set.
271          * This does not necessarily mean that the user is logged in!
272          *
273          * @return bool
274          */
275         function checkSessionCookie() {
276                 return isset( $_COOKIE[ini_get('session.name')] );
277         }
278         
279         /**
280          * Return the path portion of the request URI.
281          * @return string
282          */
283         function getRequestURL() {
284                 return $_SERVER['REQUEST_URI'];
285         }
286         
287         /**
288          * Return the request URI with the canonical service and hostname.
289          * @return string
290          */
291         function getFullRequestURL() {
292                 global $wgServer;
293                 return $wgServer . $this->getRequestURL();
294         }
295         
296         /**
297          * Take an arbitrary query and rewrite the present URL to include it
298          * @param string $query Query string fragment; do not include initial '?'
299          * @return string
300          */
301         function appendQuery( $query ) {
302                 global $wgTitle;
303                 $basequery = '';
304                 foreach( $_GET as $var => $val ) {
305                         if( $var == 'title' ) continue;
306                         $basequery .= '&' . urlencode( $var ) . '=' . urlencode( $val );
307                 }
308                 $basequery .= '&' . $query;
309                 
310                 # Trim the extra &
311                 $basequery = substr( $basequery, 1 );
312                 return $wgTitle->getLocalURL( $basequery );
313         }
314         
315         /**
316          * HTML-safe version of appendQuery().
317          * @param string $query Query string fragment; do not include initial '?'
318          * @return string
319          */
320         function escapeAppendQuery( $query ) {
321                 return htmlspecialchars( $this->appendQuery( $query ) );
322         }
323         
324         /**
325          * Check for limit and offset parameters on the input, and return sensible
326          * defaults if not given. The limit must be positive and is capped at 5000.
327          * Offset must be positive but is not capped.
328          *
329          * @param int $deflimit Limit to use if no input and the user hasn't set the option.
330          * @param string $optionname To specify an option other than rclimit to pull from.
331          * @return array first element is limit, second is offset
332          */
333         function getLimitOffset( $deflimit = 50, $optionname = 'rclimit' ) {
334                 global $wgUser;
335         
336                 $limit = $this->getInt( 'limit', 0 );
337                 if( $limit < 0 ) $limit = 0;
338                 if( ( $limit == 0 ) && ( $optionname != '' ) ) {
339                         $limit = (int)$wgUser->getOption( $optionname );
340                 }
341                 if( $limit <= 0 ) $limit = $deflimit;
342                 if( $limit > 5000 ) $limit = 5000; # We have *some* limits...
343         
344                 $offset = $this->getInt( 'offset', 0 );
345                 if( $offset < 0 ) $offset = 0;
346         
347                 return array( $limit, $offset );
348         }
349         
350         /**
351          * Return the path to the temporary file where PHP has stored the upload.
352          * @param string $key
353          * @return string or NULL if no such file.
354          */
355         function getFileTempname( $key ) {
356                 if( !isset( $_FILES[$key] ) ) {
357                         return NULL;
358                 }
359                 return $_FILES[$key]['tmp_name'];
360         }
361         
362         /**
363          * Return the size of the upload, or 0.
364          * @param string $key
365          * @return integer
366          */
367         function getFileSize( $key ) {
368                 if( !isset( $_FILES[$key] ) ) {
369                         return 0;
370                 }
371                 return $_FILES[$key]['size'];
372         }
373         
374         /**
375          * Return the original filename of the uploaded file, as reported by
376          * the submitting user agent. HTML-style character entities are
377          * interpreted and normalized to Unicode normalization form C, in part
378          * to deal with weird input from Safari with non-ASCII filenames.
379          *
380          * Other than this the name is not verified for being a safe filename.
381          *
382          * @param string $key
383          * @return string or NULL if no such file.
384          */
385         function getFileName( $key ) {
386                 if( !isset( $_FILES[$key] ) ) {
387                         return NULL;
388                 }
389                 $name = $_FILES[$key]['name'];
390                 
391                 # Safari sends filenames in HTML-encoded Unicode form D...
392                 # Horrid and evil! Let's try to make some kind of sense of it.
393                 $name = Sanitizer::decodeCharReferences( $name );
394                 $name = UtfNormal::cleanUp( $name );
395                 wfDebug( "WebRequest::getFileName() '" . $_FILES[$key]['name'] . "' normalized to '$name'\n" );
396                 return $name;
397         }
398 }
399
400 /**
401  * WebRequest clone which takes values from a provided array.
402  *
403  * @package MediaWiki
404  */
405 class FauxRequest extends WebRequest {
406         var $data = null;
407         var $wasPosted = false;
408         
409         function FauxRequest( $data, $wasPosted = false ) {
410                 if( is_array( $data ) ) {
411                         $this->data = $data;
412                 } else {
413                         wfDebugDieBacktrace( "FauxRequest() got bogus data" );
414                 }
415                 $this->wasPosted = $wasPosted;
416         }
417
418         function getVal( $name, $default = NULL ) {
419                 return $this->getGPCVal( $this->data, $name, $default );
420         }
421         
422         function getText( $name, $default = '' ) {
423                 # Override; don't recode since we're using internal data
424                 return $this->getVal( $name, $default );
425         }
426         
427         function getValues() {  
428                 return $this->data;
429         }
430
431         function wasPosted() {
432                 return $this->wasPosted;
433         }
434         
435         function checkSessionCookie() {
436                 return false;
437         }
438         
439         function getRequestURL() {
440                 wfDebugDieBacktrace( 'FauxRequest::getRequestURL() not implemented' );
441         }
442         
443         function appendQuery( $query ) {
444                 wfDebugDieBacktrace( 'FauxRequest::appendQuery() not implemented' );
445         }
446         
447 }
448
449 ?>