X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FWebRequest.php;h=c20110edb15f695554aae04726fc765cd7edd039;hb=24c478b815585a32fd9c4441f8a3ff59e505db59;hp=c75763e971e196a45a34d832b058f1b0117aa5c2;hpb=dc8ac4172432261faae9bb157583ddccff0c42fe;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/WebRequest.php b/includes/WebRequest.php index c75763e971..c20110edb1 100644 --- a/includes/WebRequest.php +++ b/includes/WebRequest.php @@ -1,38 +1,158 @@ # http://www.mediawiki.org/ -# +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # http://www.gnu.org/copyleft/gpl.html -# Hypothetically, we could use a WebRequest object to fake a -# self-contained request. -## Enable this to debug total elimination of register_globals -#define( "DEBUG_GLOBALS", 1 ); +/** + * Some entry points may use this file without first enabling the + * autoloader. + */ +if ( !function_exists( '__autoload' ) ) { + require_once( dirname(__FILE__) . '/normal/UtfNormal.php' ); +} +/** + * The WebRequest class encapsulates getting at data passed in the + * URL or via a POSTed form, handling remove of "magic quotes" slashes, + * stripping illegal input characters and normalizing Unicode sequences. + * + * Usually this is used via a global singleton, $wgRequest. You should + * not create a second WebRequest object; make a FauxRequest object if + * you want to pass arbitrary data to some function in place of the web + * input. + * + */ class WebRequest { - function WebRequest() { - if( defined('DEBUG_GLOBALS') ) error_reporting(E_ALL); - + function __construct() { $this->checkMagicQuotes(); - $this->checkRegisterGlobals(); } + + /** + * Check for title, action, and/or variant data in the URL + * and interpolate it into the GET variables. + * This should only be run after $wgContLang is available, + * as we may need the list of language variants to determine + * available variant URLs. + */ + function interpolateTitle() { + global $wgUsePathInfo; + if ( $wgUsePathInfo ) { + // PATH_INFO is mangled due to http://bugs.php.net/bug.php?id=31892 + // And also by Apache 2.x, double slashes are converted to single slashes. + // So we will use REQUEST_URI if possible. + $matches = array(); + if ( !empty( $_SERVER['REQUEST_URI'] ) ) { + // Slurp out the path portion to examine... + $url = $_SERVER['REQUEST_URI']; + if ( !preg_match( '!^https?://!', $url ) ) { + $url = 'http://unused' . $url; + } + $a = parse_url( $url ); + if( $a ) { + $path = $a['path']; + + global $wgScript; + if( $path == $wgScript ) { + // Script inside a rewrite path? + // Abort to keep from breaking... + return; + } + // Raw PATH_INFO style + $matches = $this->extractTitle( $path, "$wgScript/$1" ); + + global $wgArticlePath; + if( !$matches && $wgArticlePath ) { + $matches = $this->extractTitle( $path, $wgArticlePath ); + } + + global $wgActionPaths; + if( !$matches && $wgActionPaths ) { + $matches = $this->extractTitle( $path, $wgActionPaths, 'action' ); + } + + global $wgVariantArticlePath, $wgContLang; + if( !$matches && $wgVariantArticlePath ) { + $variantPaths = array(); + foreach( $wgContLang->getVariants() as $variant ) { + $variantPaths[$variant] = + str_replace( '$2', $variant, $wgVariantArticlePath ); + } + $matches = $this->extractTitle( $path, $variantPaths, 'variant' ); + } + } + } elseif ( isset( $_SERVER['ORIG_PATH_INFO'] ) && $_SERVER['ORIG_PATH_INFO'] != '' ) { + // Mangled PATH_INFO + // http://bugs.php.net/bug.php?id=31892 + // Also reported when ini_get('cgi.fix_pathinfo')==false + $matches['title'] = substr( $_SERVER['ORIG_PATH_INFO'], 1 ); + + } elseif ( isset( $_SERVER['PATH_INFO'] ) && ($_SERVER['PATH_INFO'] != '') ) { + // Regular old PATH_INFO yay + $matches['title'] = substr( $_SERVER['PATH_INFO'], 1 ); + } + foreach( $matches as $key => $val) { + $_GET[$key] = $_REQUEST[$key] = $val; + } + } + } + + /** + * Internal URL rewriting function; tries to extract page title and, + * optionally, one other fixed parameter value from a URL path. + * + * @param string $path the URL path given from the client + * @param array $bases one or more URLs, optionally with $1 at the end + * @param string $key if provided, the matching key in $bases will be + * passed on as the value of this URL parameter + * @return array of URL variables to interpolate; empty if no match + */ + private function extractTitle( $path, $bases, $key=false ) { + foreach( (array)$bases as $keyValue => $base ) { + // Find the part after $wgArticlePath + $base = str_replace( '$1', '', $base ); + $baseLen = strlen( $base ); + if( substr( $path, 0, $baseLen ) == $base ) { + $raw = substr( $path, $baseLen ); + if( $raw !== '' ) { + $matches = array( 'title' => rawurldecode( $raw ) ); + if( $key ) { + $matches[$key] = $keyValue; + } + return $matches; + } + } + } + return array(); + } + + private $_response; + /** + * Recursively strips slashes from the given array; + * used for undoing the evil that is magic_quotes_gpc. + * @param array &$arr will be modified + * @return array the original array + * @private + */ function &fix_magic_quotes( &$arr ) { foreach( $arr as $key => $val ) { if( is_array( $val ) ) { @@ -43,7 +163,14 @@ class WebRequest { } return $arr; } - + + /** + * If magic_quotes_gpc option is on, run the global arrays + * through fix_magic_quotes to strip out the stupid slashes. + * WARNING: This should only be done once! Running a second + * time could damage the values. + * @private + */ function checkMagicQuotes() { if ( get_magic_quotes_gpc() ) { $this->fix_magic_quotes( $_COOKIE ); @@ -52,102 +179,460 @@ class WebRequest { $this->fix_magic_quotes( $_POST ); $this->fix_magic_quotes( $_REQUEST ); $this->fix_magic_quotes( $_SERVER ); - } elseif( defined('DEBUG_GLOBALS') ) { - die("DEBUG_GLOBALS: turn on magic_quotes_gpc" ); } } - function checkRegisterGlobals() { - if( ini_get( "register_globals" ) ) { - if( defined( "DEBUG_GLOBALS" ) ) { - die( "DEBUG_GLOBALS: Turn register_globals off!" ); + /** + * Recursively normalizes UTF-8 strings in the given array. + * @param array $data string or array + * @return cleaned-up version of the given + * @private + */ + function normalizeUnicode( $data ) { + if( is_array( $data ) ) { + foreach( $data as $key => $val ) { + $data[$key] = $this->normalizeUnicode( $val ); } } else { - if( !defined( "DEBUG_GLOBALS" ) ) { - # Insecure, but at least it'll run - import_request_variables( "GPC" ); - } + $data = UtfNormal::cleanUp( $data ); } + return $data; } - - function getGPCVal( &$arr, $name, $default ) { + + /** + * Fetch a value from the given array or return $default if it's not set. + * + * @param array $arr + * @param string $name + * @param mixed $default + * @return mixed + * @private + */ + function getGPCVal( $arr, $name, $default ) { if( isset( $arr[$name] ) ) { - return $arr[$name]; + global $wgContLang; + $data = $arr[$name]; + if( isset( $_GET[$name] ) && !is_array( $data ) ) { + # Check for alternate/legacy character encoding. + if( isset( $wgContLang ) ) { + $data = $wgContLang->checkTitleEncoding( $data ); + } + } + $data = $this->normalizeUnicode( $data ); + return $data; } else { return $default; } } - - function getGPCText( &$arr, $name, $default ) { - # Text fields may be in an alternate encoding which we should check. - # Also, strip CRLF line endings down to LF to achieve consistency. - global $wgLang; - if( isset( $arr[$name] ) ) { - return str_replace( "\r\n", "\n", $wgLang->recodeInput( $arr[$name] ) ); + + /** + * Fetch a scalar from the input or return $default if it's not set. + * Returns a string. Arrays are discarded. Useful for + * non-freeform text inputs (e.g. predefined internal text keys + * selected by a drop-down menu). For freeform input, see getText(). + * + * @param string $name + * @param string $default optional default (or NULL) + * @return string + */ + function getVal( $name, $default = NULL ) { + $val = $this->getGPCVal( $_REQUEST, $name, $default ); + if( is_array( $val ) ) { + $val = $default; + } + if( is_null( $val ) ) { + return null; } else { - return $default; + return (string)$val; } } - - function getVal( $name, $default = NULL ) { - return $this->getGPCVal( $_REQUEST, $name, $default ); + + /** + * Fetch an array from the input or return $default if it's not set. + * If source was scalar, will return an array with a single element. + * If no source and no default, returns NULL. + * + * @param string $name + * @param array $default optional default (or NULL) + * @return array + */ + function getArray( $name, $default = NULL ) { + $val = $this->getGPCVal( $_REQUEST, $name, $default ); + if( is_null( $val ) ) { + return null; + } else { + return (array)$val; + } } + /** + * Fetch an array of integers, or return $default if it's not set. + * If source was scalar, will return an array with a single element. + * If no source and no default, returns NULL. + * If an array is returned, contents are guaranteed to be integers. + * + * @param string $name + * @param array $default option default (or NULL) + * @return array of ints + */ + function getIntArray( $name, $default = NULL ) { + $val = $this->getArray( $name, $default ); + if( is_array( $val ) ) { + $val = array_map( 'intval', $val ); + } + return $val; + } + + /** + * Fetch an integer value from the input or return $default if not set. + * Guaranteed to return an integer; non-numeric input will typically + * return 0. + * @param string $name + * @param int $default + * @return int + */ function getInt( $name, $default = 0 ) { - return IntVal( $this->getVal( $name, $default ) ); + return intval( $this->getVal( $name, $default ) ); } - + + /** + * Fetch an integer value from the input or return null if empty. + * Guaranteed to return an integer or null; non-numeric input will + * typically return null. + * @param string $name + * @return int + */ + function getIntOrNull( $name ) { + $val = $this->getVal( $name ); + return is_numeric( $val ) + ? intval( $val ) + : null; + } + + /** + * Fetch a boolean value from the input or return $default if not set. + * Guaranteed to return true or false, with normal PHP semantics for + * boolean interpretation of strings. + * @param string $name + * @param bool $default + * @return bool + */ function getBool( $name, $default = false ) { return $this->getVal( $name, $default ) ? true : false; } - + + /** + * Return true if the named value is set in the input, whatever that + * value is (even "0"). Return false if the named value is not set. + * Example use is checking for the presence of check boxes in forms. + * @param string $name + * @return bool + */ function getCheck( $name ) { # Checkboxes and buttons are only present when clicked # Presence connotes truth, abscense false $val = $this->getVal( $name, NULL ); return isset( $val ); } - - function getText( $name, $default = "" ) { - return $this->getGPCText( $_REQUEST, $name, $default ); + + /** + * Fetch a text string from the given array or return $default if it's not + * set. \r is stripped from the text, and with some language modules there + * is an input transliteration applied. This should generally be used for + * form