Update OOjs UI to v0.1.0-pre (0fbf6bd14e)
[lhc/web/wiklou.git] / includes / HttpFunctions.php
index 78c2ac7..c9dd0c0 100644 (file)
@@ -30,7 +30,7 @@
  * @ingroup HTTP
  */
 class Http {
-       static $httpEngine = false;
+       static public $httpEngine = false;
 
        /**
         * Perform an HTTP request
@@ -55,7 +55,7 @@ class Http {
         *                                  to avoid attacks on intranet services accessible by HTTP.
         *    - userAgent           A user agent, if you want to override the default
         *                          MediaWiki/$wgVersion
-        * @return Mixed: (bool)false on failure or a string on success
+        * @return string|bool (bool)false on failure or a string on success
         */
        public static function request( $method, $url, $options = array() ) {
                wfDebug( "HTTP: $method: $url\n" );
@@ -85,9 +85,9 @@ class Http {
         * Simple wrapper for Http::request( 'GET' )
         * @see Http::request()
         *
-        * @param $url
-        * @param $timeout string
-        * @param $options array
+        * @param string $url
+        * @param string $timeout
+        * @param array $options
         * @return string
         */
        public static function get( $url, $timeout = 'default', $options = array() ) {
@@ -99,8 +99,8 @@ class Http {
         * Simple wrapper for Http::request( 'POST' )
         * @see Http::request()
         *
-        * @param $url
-        * @param $options array
+        * @param string $url
+        * @param array $options
         * @return string
         */
        public static function post( $url, $options = array() ) {
@@ -110,8 +110,8 @@ class Http {
        /**
         * Check if the URL can be served by localhost
         *
-        * @param string $url full url to check
-        * @return Boolean
+        * @param string $url Full url to check
+        * @return bool
         */
        public static function isLocalURL( $url ) {
                global $wgCommandLineMode, $wgConf;
@@ -130,7 +130,8 @@ class Http {
                        $domainParts = array_reverse( $domainParts );
 
                        $domain = '';
-                       for ( $i = 0; $i < count( $domainParts ); $i++ ) {
+                       $countParts = count( $domainParts );
+                       for ( $i = 0; $i < $countParts; $i++ ) {
                                $domainPart = $domainParts[$i];
                                if ( $i == 0 ) {
                                        $domain = $domainPart;
@@ -149,7 +150,7 @@ class Http {
 
        /**
         * A standard user-agent we can use for external requests.
-        * @return String
+        * @return string
         */
        public static function userAgent() {
                global $wgVersion;
@@ -165,8 +166,8 @@ class Http {
         *
         * @todo FIXME this is wildly inaccurate and fails to actually check most stuff
         *
-        * @param $uri Mixed: URI to check for validity
-        * @return Boolean
+        * @param string $uri URI to check for validity
+        * @return bool
         */
        public static function isValidURI( $uri ) {
                return preg_match(
@@ -204,7 +205,7 @@ class MWHttpRequest {
        protected $followRedirects = false;
 
        /**
-        * @var  CookieJar
+        * @var CookieJar
         */
        protected $cookieJar;
 
@@ -216,7 +217,7 @@ class MWHttpRequest {
        public $status;
 
        /**
-        * @param string $url url to use. If protocol-relative, will be expanded to an http:// URL
+        * @param string $url Url to use. If protocol-relative, will be expanded to an http:// URL
         * @param array $options (optional) extra params to pass (see Http::request())
         */
        protected function __construct( $url, $options = array() ) {
@@ -275,7 +276,7 @@ class MWHttpRequest {
 
        /**
         * Generate a new request object
-        * @param string $url url to use
+        * @param string $url Url to use
         * @param array $options (optional) extra params to pass (see Http::request())
         * @throws MWException
         * @return CurlHttpRequest|PhpHttpRequest
@@ -294,8 +295,11 @@ class MWHttpRequest {
                                return new CurlHttpRequest( $url, $options );
                        case 'php':
                                if ( !wfIniGetBool( 'allow_url_fopen' ) ) {
-                                       throw new MWException( __METHOD__ . ': allow_url_fopen needs to be enabled for pure PHP' .
-                                               ' http requests to work. If possible, curl should be used instead. See http://php.net/curl.' );
+                                       throw new MWException( __METHOD__ . ': allow_url_fopen ' .
+                                               'needs to be enabled for pure PHP http requests to ' .
+                                               'work. If possible, curl should be used instead. See ' .
+                                               'http://php.net/curl.'
+                                       );
                                }
                                return new PhpHttpRequest( $url, $options );
                        default:
@@ -306,7 +310,7 @@ class MWHttpRequest {
        /**
         * Get the body, or content, of the response to the request
         *
-        * @return String
+        * @return string
         */
        public function getContent() {
                return $this->content;
@@ -315,7 +319,7 @@ class MWHttpRequest {
        /**
         * Set the parameters of the request
         *
-        * @param $args Array
+        * @param array $args
         * @todo overload the args param
         */
        public function setData( $args ) {
@@ -346,16 +350,9 @@ class MWHttpRequest {
                }
        }
 
-       /**
-        * Set the referrer header
-        */
-       public function setReferer( $url ) {
-               $this->setHeader( 'Referer', $url );
-       }
-
        /**
         * Set the user agent
-        * @param $UA string
+        * @param string $UA
         */
        public function setUserAgent( $UA ) {
                $this->setHeader( 'User-Agent', $UA );
@@ -363,8 +360,8 @@ class MWHttpRequest {
 
        /**
         * Set an arbitrary header
-        * @param $name
-        * @param $value
+        * @param string $name
+        * @param string $value
         */
        public function setHeader( $name, $value ) {
                // I feel like I should normalize the case here...
@@ -408,7 +405,7 @@ class MWHttpRequest {
         * bytes are reported handled than were passed to you, the HTTP fetch
         * will be aborted.
         *
-        * @param $callback Callback
+        * @param callable $callback
         * @throws MWException
         */
        public function setCallback( $callback ) {
@@ -422,8 +419,8 @@ class MWHttpRequest {
         * A generic callback to read the body of the response from a remote
         * server.
         *
-        * @param $fh handle
-        * @param $content String
+        * @param resource $fh
+        * @param string $content
         * @return int
         */
        public function read( $fh, $content ) {
@@ -437,8 +434,6 @@ class MWHttpRequest {
         * @return Status
         */
        public function execute() {
-               global $wgTitle;
-
                wfProfileIn( __METHOD__ );
 
                $this->content = "";
@@ -447,10 +442,6 @@ class MWHttpRequest {
                        $this->headersOnly = true;
                }
 
-               if ( is_object( $wgTitle ) && !isset( $this->reqHeaders['Referer'] ) ) {
-                       $this->setReferer( wfExpandUrl( $wgTitle->getFullURL(), PROTO_CURRENT ) );
-               }
-
                $this->proxySetup(); // set up any proxy as needed
 
                if ( !$this->callback ) {
@@ -516,7 +507,7 @@ class MWHttpRequest {
         * (see RFC2616, section 10, http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
         * for a list of status codes.)
         *
-        * @return Integer
+        * @return int
         */
        public function getStatus() {
                if ( !$this->respHeaders ) {
@@ -529,7 +520,7 @@ class MWHttpRequest {
        /**
         * Returns true if the last status code was a redirect.
         *
-        * @return Boolean
+        * @return bool
         */
        public function isRedirect() {
                if ( !$this->respHeaders ) {
@@ -551,7 +542,7 @@ class MWHttpRequest {
         * (e.g. Set-Cookie) can appear more than once the, each value of
         * the associative array is an array of the values given.
         *
-        * @return Array
+        * @return array
         */
        public function getResponseHeaders() {
                if ( !$this->respHeaders ) {
@@ -564,8 +555,8 @@ class MWHttpRequest {
        /**
         * Returns the value of the given response header.
         *
-        * @param $header String
-        * @return String
+        * @param string $header
+        * @return string
         */
        public function getResponseHeader( $header ) {
                if ( !$this->respHeaders ) {
@@ -583,7 +574,7 @@ class MWHttpRequest {
        /**
         * Tells the MWHttpRequest object to use this pre-loaded CookieJar.
         *
-        * @param $jar CookieJar
+        * @param CookieJar $jar
         */
        public function setCookieJar( $jar ) {
                $this->cookieJar = $jar;
@@ -607,9 +598,9 @@ class MWHttpRequest {
         * cookies. Used internally after a request to parse the
         * Set-Cookie headers.
         * @see Cookie::set
-        * @param $name
-        * @param $value null
-        * @param $attr null
+        * @param string $name
+        * @param mixed $value
+        * @param array $attr
         */
        public function setCookie( $name, $value = null, $attr = null ) {
                if ( !$this->cookieJar ) {
@@ -642,12 +633,16 @@ class MWHttpRequest {
        /**
         * Returns the final URL after all redirections.
         *
-        * Relative values of the "Location" header are incorrect as stated in RFC, however they do happen and modern browsers support them.
-        * This function loops backwards through all locations in order to build the proper absolute URI - Marooned at wikia-inc.com
+        * Relative values of the "Location" header are incorrect as
+        * stated in RFC, however they do happen and modern browsers
+        * support them.  This function loops backwards through all
+        * locations in order to build the proper absolute URI - Marooned
+        * at wikia-inc.com
         *
-        * Note that the multiple Location: headers are an artifact of CURL -- they
-        * shouldn't actually get returned this way. Rewrite this when bug 29232 is
-        * taken care of (high-level redirect handling rewrite).
+        * Note that the multiple Location: headers are an artifact of
+        * CURL -- they shouldn't actually get returned this way. Rewrite
+        * this when bug 29232 is taken care of (high-level redirect
+        * handling rewrite).
         *
         * @return string
         */
@@ -678,7 +673,8 @@ class MWHttpRequest {
                                } else {
                                        $url = parse_url( $this->url );
                                        if ( isset( $url['host'] ) ) {
-                                               return $url['scheme'] . '://' . $url['host'] . $locations[$countLocations - 1];
+                                               return $url['scheme'] . '://' . $url['host'] .
+                                                       $locations[$countLocations - 1];
                                        }
                                }
                        } else {
@@ -709,8 +705,8 @@ class CurlHttpRequest extends MWHttpRequest {
        protected $headerText = "";
 
        /**
-        * @param $fh
-        * @param $content
+        * @param resource $fh
+        * @param string $content
         * @return int
         */
        protected function readHeader( $fh, $content ) {
@@ -730,17 +726,18 @@ class CurlHttpRequest extends MWHttpRequest {
 
                $this->curlOptions[CURLOPT_PROXY] = $this->proxy;
                $this->curlOptions[CURLOPT_TIMEOUT] = $this->timeout;
-               $this->curlOptions[CURLOPT_CONNECTTIMEOUT_MS] = $this->connectTimeout * 1000;
+
+               // Only supported in curl >= 7.16.2
+               if ( defined( 'CURLOPT_CONNECTTIMEOUT_MS' ) ) {
+                       $this->curlOptions[CURLOPT_CONNECTTIMEOUT_MS] = $this->connectTimeout * 1000;
+               }
+
                $this->curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
                $this->curlOptions[CURLOPT_WRITEFUNCTION] = $this->callback;
                $this->curlOptions[CURLOPT_HEADERFUNCTION] = array( $this, "readHeader" );
                $this->curlOptions[CURLOPT_MAXREDIRS] = $this->maxRedirects;
                $this->curlOptions[CURLOPT_ENCODING] = ""; # Enable compression
 
-               /* not sure these two are actually necessary */
-               if ( isset( $this->reqHeaders['Referer'] ) ) {
-                       $this->curlOptions[CURLOPT_REFERER] = $this->reqHeaders['Referer'];
-               }
                $this->curlOptions[CURLOPT_USERAGENT] = $this->reqHeaders['User-Agent'];
 
                $this->curlOptions[CURLOPT_SSL_VERIFYHOST] = $this->sslVerifyHost ? 2 : 0;
@@ -824,7 +821,7 @@ class CurlHttpRequest extends MWHttpRequest {
 class PhpHttpRequest extends MWHttpRequest {
 
        /**
-        * @param $url string
+        * @param string $url
         * @return string
         */
        protected function urlToTcp( $url ) {
@@ -842,12 +839,13 @@ class PhpHttpRequest extends MWHttpRequest {
                        $this->postData = wfArrayToCgi( $this->postData );
                }
 
-               if ( $this->parsedUrl['scheme'] != 'http' &&
-                        $this->parsedUrl['scheme'] != 'https' ) {
+               if ( $this->parsedUrl['scheme'] != 'http'
+                       && $this->parsedUrl['scheme'] != 'https' ) {
                        $this->status->fatal( 'http-invalid-scheme', $this->parsedUrl['scheme'] );
                }
 
                $this->reqHeaders['Accept'] = "*/*";
+               $this->reqHeaders['Connection'] = 'Close';
                if ( $this->method == 'POST' ) {
                        // Required for HTTP 1.0 POSTs
                        $this->reqHeaders['Content-Length'] = strlen( $this->postData );
@@ -856,52 +854,47 @@ class PhpHttpRequest extends MWHttpRequest {
                        }
                }
 
-               $options = array();
-               if ( $this->proxy ) {
-                       $options['proxy'] = $this->urlToTCP( $this->proxy );
-                       $options['request_fulluri'] = true;
-               }
+               // Set up PHP stream context
+               $options = array(
+                       'http' => array(
+                               'method' => $this->method,
+                               'header' => implode( "\r\n", $this->getHeaderList() ),
+                               'protocol_version' => '1.1',
+                               'max_redirects' => $this->followRedirects ? $this->maxRedirects : 0,
+                               'ignore_errors' => true,
+                               'timeout' => $this->timeout,
+                               // Curl options in case curlwrappers are installed
+                               'curl_verify_ssl_host' => $this->sslVerifyHost ? 2 : 0,
+                               'curl_verify_ssl_peer' => $this->sslVerifyCert,
+                       ),
+                       'ssl' => array(
+                               'verify_peer' => $this->sslVerifyCert,
+                               'SNI_enabled' => true,
+                       ),
+               );
 
-               if ( !$this->followRedirects ) {
-                       $options['max_redirects'] = 0;
-               } else {
-                       $options['max_redirects'] = $this->maxRedirects;
+               if ( $this->proxy ) {
+                       $options['http']['proxy'] = $this->urlToTCP( $this->proxy );
+                       $options['http']['request_fulluri'] = true;
                }
 
-               $options['method'] = $this->method;
-               $options['header'] = implode( "\r\n", $this->getHeaderList() );
-               // Note that at some future point we may want to support
-               // HTTP/1.1, but we'd have to write support for chunking
-               // in version of PHP < 5.3.1
-               $options['protocol_version'] = "1.0";
-
-               // This is how we tell PHP we want to deal with 404s (for example) ourselves.
-               // Only works on 5.2.10+
-               $options['ignore_errors'] = true;
-
                if ( $this->postData ) {
-                       $options['content'] = $this->postData;
+                       $options['http']['content'] = $this->postData;
                }
 
-               $options['timeout'] = $this->timeout;
-
                if ( $this->sslVerifyHost ) {
-                       $options['CN_match'] = $this->parsedUrl['host'];
-               }
-               if ( $this->sslVerifyCert ) {
-                       $options['verify_peer'] = true;
+                       $options['ssl']['CN_match'] = $this->parsedUrl['host'];
                }
 
                if ( is_dir( $this->caInfo ) ) {
-                       $options['capath'] = $this->caInfo;
+                       $options['ssl']['capath'] = $this->caInfo;
                } elseif ( is_file( $this->caInfo ) ) {
-                       $options['cafile'] = $this->caInfo;
+                       $options['ssl']['cafile'] = $this->caInfo;
                } elseif ( $this->caInfo ) {
                        throw new MWException( "Invalid CA info passed: {$this->caInfo}" );
                }
 
-               $scheme = $this->parsedUrl['scheme'];
-               $context = stream_context_create( array( "$scheme" => $options ) );
+               $context = stream_context_create( $options );
 
                $this->headerList = array();
                $reqCount = 0;