00001 <?php
00006 # Copyright (C) 2003 Brion Vibber <brion@pobox.com>
00007 # http://www.mediawiki.org/
00008 #
00009 # This program is free software; you can redistribute it and/or modify
00010 # it under the terms of the GNU General Public License as published by
00011 # the Free Software Foundation; either version 2 of the License, or
00012 # (at your option) any later version.
00013 #
00014 # This program is distributed in the hope that it will be useful,
00015 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017 # GNU General Public License for more details.
00018 #
00019 # You should have received a copy of the GNU General Public License along
00020 # with this program; if not, write to the Free Software Foundation, Inc.,
00021 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00022 # http://www.gnu.org/copyleft/gpl.html
00023
00024
00029 if ( !function_exists( '__autoload' ) ) {
00030 require_once( dirname(__FILE__) . '/normal/UtfNormal.php' );
00031 }
00032
00045 class WebRequest {
00046 var $data = array();
00047 var $headers;
00048 private $_response;
00049
00050 function __construct() {
00054 $this->checkMagicQuotes();
00055
00056
00057
00058 $this->data = $_POST + $_GET;
00059 }
00060
00068 function interpolateTitle() {
00069 global $wgUsePathInfo;
00070 if ( $wgUsePathInfo ) {
00071
00072
00073
00074 $matches = array();
00075 if ( !empty( $_SERVER['REQUEST_URI'] ) ) {
00076
00077 $url = $_SERVER['REQUEST_URI'];
00078 if ( !preg_match( '!^https?://!', $url ) ) {
00079 $url = 'http://unused' . $url;
00080 }
00081 $a = parse_url( $url );
00082 if( $a ) {
00083 $path = isset( $a['path'] ) ? $a['path'] : '';
00084
00085 global $wgScript;
00086 if( $path == $wgScript ) {
00087
00088
00089 return;
00090 }
00091
00092 $matches = $this->extractTitle( $path, "$wgScript/$1" );
00093
00094 global $wgArticlePath;
00095 if( !$matches && $wgArticlePath ) {
00096 $matches = $this->extractTitle( $path, $wgArticlePath );
00097 }
00098
00099 global $wgActionPaths;
00100 if( !$matches && $wgActionPaths ) {
00101 $matches = $this->extractTitle( $path, $wgActionPaths, 'action' );
00102 }
00103
00104 global $wgVariantArticlePath, $wgContLang;
00105 if( !$matches && $wgVariantArticlePath ) {
00106 $variantPaths = array();
00107 foreach( $wgContLang->getVariants() as $variant ) {
00108 $variantPaths[$variant] =
00109 str_replace( '$2', $variant, $wgVariantArticlePath );
00110 }
00111 $matches = $this->extractTitle( $path, $variantPaths, 'variant' );
00112 }
00113 }
00114 } elseif ( isset( $_SERVER['ORIG_PATH_INFO'] ) && $_SERVER['ORIG_PATH_INFO'] != '' ) {
00115
00116
00117
00118 $matches['title'] = substr( $_SERVER['ORIG_PATH_INFO'], 1 );
00119
00120 } elseif ( isset( $_SERVER['PATH_INFO'] ) && ($_SERVER['PATH_INFO'] != '') ) {
00121
00122 $matches['title'] = substr( $_SERVER['PATH_INFO'], 1 );
00123 }
00124 foreach( $matches as $key => $val) {
00125 $this->data[$key] = $_GET[$key] = $_REQUEST[$key] = $val;
00126 }
00127 }
00128 }
00129
00140 private function extractTitle( $path, $bases, $key=false ) {
00141 foreach( (array)$bases as $keyValue => $base ) {
00142
00143 $base = str_replace( '$1', '', $base );
00144 $baseLen = strlen( $base );
00145 if( substr( $path, 0, $baseLen ) == $base ) {
00146 $raw = substr( $path, $baseLen );
00147 if( $raw !== '' ) {
00148 $matches = array( 'title' => rawurldecode( $raw ) );
00149 if( $key ) {
00150 $matches[$key] = $keyValue;
00151 }
00152 return $matches;
00153 }
00154 }
00155 }
00156 return array();
00157 }
00158
00166 function &fix_magic_quotes( &$arr ) {
00167 foreach( $arr as $key => $val ) {
00168 if( is_array( $val ) ) {
00169 $this->fix_magic_quotes( $arr[$key] );
00170 } else {
00171 $arr[$key] = stripslashes( $val );
00172 }
00173 }
00174 return $arr;
00175 }
00176
00184 function checkMagicQuotes() {
00185 if ( function_exists( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc() ) {
00186 $this->fix_magic_quotes( $_COOKIE );
00187 $this->fix_magic_quotes( $_ENV );
00188 $this->fix_magic_quotes( $_GET );
00189 $this->fix_magic_quotes( $_POST );
00190 $this->fix_magic_quotes( $_REQUEST );
00191 $this->fix_magic_quotes( $_SERVER );
00192 }
00193 }
00194
00201 function normalizeUnicode( $data ) {
00202 if( is_array( $data ) ) {
00203 foreach( $data as $key => $val ) {
00204 $data[$key] = $this->normalizeUnicode( $val );
00205 }
00206 } else {
00207 $data = UtfNormal::cleanUp( $data );
00208 }
00209 return $data;
00210 }
00211
00221 function getGPCVal( $arr, $name, $default ) {
00222 if( isset( $arr[$name] ) ) {
00223 global $wgContLang;
00224 $data = $arr[$name];
00225 if( isset( $_GET[$name] ) && !is_array( $data ) ) {
00226 # Check for alternate/legacy character encoding.
00227 if( isset( $wgContLang ) ) {
00228 $data = $wgContLang->checkTitleEncoding( $data );
00229 }
00230 }
00231 $data = $this->normalizeUnicode( $data );
00232 return $data;
00233 } else {
00234 taint( $default );
00235 return $default;
00236 }
00237 }
00238
00249 function getVal( $name, $default = NULL ) {
00250 $val = $this->getGPCVal( $this->data, $name, $default );
00251 if( is_array( $val ) ) {
00252 $val = $default;
00253 }
00254 if( is_null( $val ) ) {
00255 return $val;
00256 } else {
00257 return (string)$val;
00258 }
00259 }
00260
00267 function setVal( $key, $value ) {
00268 $ret = isset( $this->data[$key] ) ? $this->data[$key] : null;
00269 $this->data[$key] = $value;
00270 return $ret;
00271 }
00272
00282 function getArray( $name, $default = NULL ) {
00283 $val = $this->getGPCVal( $this->data, $name, $default );
00284 if( is_null( $val ) ) {
00285 return null;
00286 } else {
00287 return (array)$val;
00288 }
00289 }
00290
00301 function getIntArray( $name, $default = NULL ) {
00302 $val = $this->getArray( $name, $default );
00303 if( is_array( $val ) ) {
00304 $val = array_map( 'intval', $val );
00305 }
00306 return $val;
00307 }
00308
00317 function getInt( $name, $default = 0 ) {
00318 return intval( $this->getVal( $name, $default ) );
00319 }
00320
00328 function getIntOrNull( $name ) {
00329 $val = $this->getVal( $name );
00330 return is_numeric( $val )
00331 ? intval( $val )
00332 : null;
00333 }
00334
00343 function getBool( $name, $default = false ) {
00344 return $this->getVal( $name, $default ) ? true : false;
00345 }
00346
00354 function getCheck( $name ) {
00355 # Checkboxes and buttons are only present when clicked
00356 # Presence connotes truth, abscense false
00357 $val = $this->getVal( $name, NULL );
00358 return isset( $val );
00359 }
00360
00373 function getText( $name, $default = '' ) {
00374 global $wgContLang;
00375 $val = $this->getVal( $name, $default );
00376 return str_replace( "\r\n", "\n",
00377 $wgContLang->recodeInput( $val ) );
00378 }
00379
00385 function getValues() {
00386 $names = func_get_args();
00387 if ( count( $names ) == 0 ) {
00388 $names = array_keys( $this->data );
00389 }
00390
00391 $retVal = array();
00392 foreach ( $names as $name ) {
00393 $value = $this->getVal( $name );
00394 if ( !is_null( $value ) ) {
00395 $retVal[$name] = $value;
00396 }
00397 }
00398 return $retVal;
00399 }
00400
00410 function wasPosted() {
00411 return $_SERVER['REQUEST_METHOD'] == 'POST';
00412 }
00413
00425 function checkSessionCookie() {
00426 return isset( $_COOKIE[session_name()] );
00427 }
00428
00433 function getRequestURL() {
00434 if( isset( $_SERVER['REQUEST_URI'] ) ) {
00435 $base = $_SERVER['REQUEST_URI'];
00436 } elseif( isset( $_SERVER['SCRIPT_NAME'] ) ) {
00437
00438 $base = $_SERVER['SCRIPT_NAME'];
00439 if( isset( $_SERVER['QUERY_STRING'] ) && $_SERVER['QUERY_STRING'] != '' ) {
00440 $base .= '?' . $_SERVER['QUERY_STRING'];
00441 }
00442 } else {
00443
00444 throw new MWException( "Web server doesn't provide either " .
00445 "REQUEST_URI or SCRIPT_NAME. Report details of your " .
00446 "web server configuration to http://bugzilla.wikimedia.org/" );
00447 }
00448
00449
00450
00451
00452 $hash = strpos( $base, '#' );
00453 if( $hash !== false ) {
00454 $base = substr( $base, 0, $hash );
00455 }
00456 if( $base{0} == '/' ) {
00457 return $base;
00458 } else {
00459
00460 return preg_replace( '!^[^:]+://[^/]+/!', '/', $base );
00461 }
00462 }
00463
00468 function getFullRequestURL() {
00469 global $wgServer;
00470 return $wgServer . $this->getRequestURL();
00471 }
00472
00478 function appendQuery( $query ) {
00479 global $wgTitle;
00480 $basequery = '';
00481 foreach( $_GET as $var => $val ) {
00482 if ( $var == 'title' )
00483 continue;
00484 if ( is_array( $val ) )
00485
00486
00487
00488 continue;
00489 $basequery .= '&' . urlencode( $var ) . '=' . urlencode( $val );
00490 }
00491 $basequery .= '&' . $query;
00492
00493 # Trim the extra &
00494 $basequery = substr( $basequery, 1 );
00495 return $wgTitle->getLocalURL( $basequery );
00496 }
00497
00503 function escapeAppendQuery( $query ) {
00504 return htmlspecialchars( $this->appendQuery( $query ) );
00505 }
00506
00507 function appendQueryValue( $key, $value, $onlyquery = false ) {
00508 return $this->appendQueryArray( array( $key => $value ), $onlyquery );
00509 }
00510
00518 function appendQueryArray( $array, $onlyquery = false ) {
00519 global $wgTitle;
00520 $newquery = $_GET;
00521 unset( $newquery['title'] );
00522 $newquery = array_merge( $newquery, $array );
00523 $query = wfArrayToCGI( $newquery );
00524 return $onlyquery ? $query : $wgTitle->getLocalURL( $query );
00525 }
00526
00536 function getLimitOffset( $deflimit = 50, $optionname = 'rclimit' ) {
00537 global $wgUser;
00538
00539 $limit = $this->getInt( 'limit', 0 );
00540 if( $limit < 0 ) $limit = 0;
00541 if( ( $limit == 0 ) && ( $optionname != '' ) ) {
00542 $limit = (int)$wgUser->getOption( $optionname );
00543 }
00544 if( $limit <= 0 ) $limit = $deflimit;
00545 if( $limit > 5000 ) $limit = 5000; # We have *some* limits...
00546
00547 $offset = $this->getInt( 'offset', 0 );
00548 if( $offset < 0 ) $offset = 0;
00549
00550 return array( $limit, $offset );
00551 }
00552
00558 function getFileTempname( $key ) {
00559 if( !isset( $_FILES[$key] ) ) {
00560 return NULL;
00561 }
00562 return $_FILES[$key]['tmp_name'];
00563 }
00564
00570 function getFileSize( $key ) {
00571 if( !isset( $_FILES[$key] ) ) {
00572 return 0;
00573 }
00574 return $_FILES[$key]['size'];
00575 }
00576
00582 function getUploadError( $key ) {
00583 if( !isset( $_FILES[$key] ) || !isset( $_FILES[$key]['error'] ) ) {
00584 return 0;
00585 }
00586 return $_FILES[$key]['error'];
00587 }
00588
00600 function getFileName( $key ) {
00601 if( !isset( $_FILES[$key] ) ) {
00602 return NULL;
00603 }
00604 $name = $_FILES[$key]['name'];
00605
00606 # Safari sends filenames in HTML-encoded Unicode form D...
00607 # Horrid and evil! Let's try to make some kind of sense of it.
00608 $name = Sanitizer::decodeCharReferences( $name );
00609 $name = UtfNormal::cleanUp( $name );
00610 wfDebug( "WebRequest::getFileName() '" . $_FILES[$key]['name'] . "' normalized to '$name'\n" );
00611 return $name;
00612 }
00613
00618 function response() {
00619
00620 if (!is_object($this->_response)) {
00621 $this->_response = new WebResponse;
00622 }
00623 return $this->_response;
00624 }
00625
00630 function getHeader( $name ) {
00631 $name = strtoupper( $name );
00632 if ( function_exists( 'apache_request_headers' ) ) {
00633 if ( !isset( $this->headers ) ) {
00634 $this->headers = array();
00635 foreach ( apache_request_headers() as $tempName => $tempValue ) {
00636 $this->headers[ strtoupper( $tempName ) ] = $tempValue;
00637 }
00638 }
00639 if ( isset( $this->headers[$name] ) ) {
00640 return $this->headers[$name];
00641 } else {
00642 return false;
00643 }
00644 } else {
00645 $name = 'HTTP_' . str_replace( '-', '_', $name );
00646 if ( isset( $_SERVER[$name] ) ) {
00647 return $_SERVER[$name];
00648 } else {
00649 return false;
00650 }
00651 }
00652 }
00653
00654
00655
00656
00657 function getSessionData( $key ) {
00658 if( !isset( $_SESSION[$key] ) )
00659 return null;
00660 return $_SESSION[$key];
00661 }
00662 function setSessionData( $key, $data ) {
00663 $_SESSION[$key] = $data;
00664 }
00665 }
00666
00672 class FauxRequest extends WebRequest {
00673 var $wasPosted = false;
00674
00680 function FauxRequest( $data, $wasPosted = false, $session = null ) {
00681 if( is_array( $data ) ) {
00682 $this->data = $data;
00683 } else {
00684 throw new MWException( "FauxRequest() got bogus data" );
00685 }
00686 $this->wasPosted = $wasPosted;
00687 $this->headers = array();
00688 $this->session = $session ? $session : array();
00689 }
00690
00691 function notImplemented( $method ) {
00692 throw new MWException( "{$method}() not implemented" );
00693 }
00694
00695 function getText( $name, $default = '' ) {
00696 # Override; don't recode since we're using internal data
00697 return (string)$this->getVal( $name, $default );
00698 }
00699
00700 function getValues() {
00701 return $this->data;
00702 }
00703
00704 function wasPosted() {
00705 return $this->wasPosted;
00706 }
00707
00708 function checkSessionCookie() {
00709 return false;
00710 }
00711
00712 function getRequestURL() {
00713 $this->notImplemented( __METHOD__ );
00714 }
00715
00716 function appendQuery( $query ) {
00717 $this->notImplemented( __METHOD__ );
00718 }
00719
00720 function getHeader( $name ) {
00721 return isset( $this->headers[$name] ) ? $this->headers[$name] : false;
00722 }
00723
00724 function getSessionData( $key ) {
00725 if( !isset( $this->session[$key] ) )
00726 return null;
00727 return $this->session[$key];
00728 }
00729 function setSessionData( $key, $data ) {
00730 $this->notImplemented( __METHOD__ );
00731 }
00732
00733 }