+ /**
+ * Extract the PATH_INFO variable even when it isn't a reasonable
+ * value. On some large webhosts, PATH_INFO includes the script
+ * path as well as everything after it.
+ *
+ * @param $want string: If this is not 'all', then the function
+ * will return an empty array if it determines that the URL is
+ * inside a rewrite path.
+ *
+ * @return Array: 'title' key is the title of the article.
+ */
+ static public function getPathInfo( $want = 'all' ) {
+ // 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 = isset( $a['path'] ) ? $a['path'] : '';
+
+ global $wgScript;
+ if( $path == $wgScript && $want !== 'all' ) {
+ // Script inside a rewrite path?
+ // Abort to keep from breaking...
+ return $matches;
+ }
+ // Raw PATH_INFO style
+ $matches = self::extractTitle( $path, "$wgScript/$1" );
+
+ if( !$matches
+ && isset( $_SERVER['SCRIPT_NAME'] )
+ && preg_match( '/\.php5?/', $_SERVER['SCRIPT_NAME'] ) )
+ {
+ # Check for SCRIPT_NAME, we handle index.php explicitly
+ # But we do have some other .php files such as img_auth.php
+ # Don't let root article paths clober the parsing for them
+ $matches = self::extractTitle( $path, $_SERVER['SCRIPT_NAME'] . "/$1" );
+ }
+
+ global $wgArticlePath;
+ if( !$matches && $wgArticlePath ) {
+ $matches = self::extractTitle( $path, $wgArticlePath );
+ }
+
+ global $wgActionPaths;
+ if( !$matches && $wgActionPaths ) {
+ $matches = self::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 = self::extractTitle( $path, $variantPaths, 'variant' );
+ }
+
+ wfRunHooks( 'WebRequestGetPathInfoRequestURI', array( $path, &$matches ) );
+ }
+ } 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 );
+ }
+
+ return $matches;
+ }
+
+ /**
+ * Work out an appropriate URL prefix containing scheme and host, based on
+ * information detected from $_SERVER
+ *
+ * @return string
+ */
+ public static function detectServer() {
+ list( $proto, $stdPort ) = self::detectProtocolAndStdPort();
+
+ $varNames = array( 'HTTP_HOST', 'SERVER_NAME', 'HOSTNAME', 'SERVER_ADDR' );
+ $host = 'localhost';
+ $port = $stdPort;
+ foreach ( $varNames as $varName ) {
+ if ( !isset( $_SERVER[$varName] ) ) {
+ continue;
+ }
+ $parts = IP::splitHostAndPort( $_SERVER[$varName] );
+ if ( !$parts ) {
+ // Invalid, do not use
+ continue;
+ }
+ $host = $parts[0];
+ if ( $parts[1] === false ) {
+ if ( isset( $_SERVER['SERVER_PORT'] ) ) {
+ $port = $_SERVER['SERVER_PORT'];
+ } // else leave it as $stdPort
+ } else {
+ $port = $parts[1];
+ }
+ break;
+ }
+
+ return $proto . '://' . IP::combineHostAndPort( $host, $port, $stdPort );
+ }
+
+ /**
+ * @return array
+ */
+ public static function detectProtocolAndStdPort() {
+ return ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ) ? array( 'https', 443 ) : array( 'http', 80 );
+ }
+
+ /**
+ * @return string
+ */
+ public static function detectProtocol() {
+ list( $proto, $stdPort ) = self::detectProtocolAndStdPort();
+ return $proto;
+ }
+