Fixup HTTPRequest.class.php
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / util / HTTPRequest.class.php
index 591c4628386c2d204a61972156058af37ffa2e4c..5853c0b7f35059bf5a3fe4c3afbfcb7a64e49a9b 100644 (file)
@@ -13,7 +13,7 @@ use wcf\system\WCF;
  * It supports POST, SSL, Basic Auth etc.
  * 
  * @author     Tim Duesterhus
- * @copyright  2001-2014 WoltLab GmbH
+ * @copyright  2001-2015 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage util
@@ -44,18 +44,36 @@ final class HTTPRequest {
         */
        private $useSSL = false;
        
+       /**
+        * indicates if the connection to the proxy target will be made via SSL
+        * @var boolean
+        */
+       private $originUseSSL = false;
+       
        /**
         * target host
         * @var string
         */
        private $host;
        
+       /**
+        * target host if a proxy is used
+        * @var string
+        */
+       private $originHost;
+       
        /**
         * target port
         * @var integer
         */
        private $port;
        
+       /**
+        * target port if a proxy is used
+        * @var integer
+        */
+       private $originPort;
+       
        /**
         * target path
         * @var string
@@ -201,14 +219,22 @@ final class HTTPRequest {
         */
        private function setURL($url) {
                $parsedUrl = $originUrl = parse_url($url);
-               if (PROXY_SERVER_HTTP) {
-                       $parsedUrl = parse_url(PROXY_SERVER_HTTP);
+               
+               $this->originUseSSL = $originUrl['scheme'] === 'https';
+               $this->originHost = $originUrl['host'];
+               $this->originPort = isset($originUrl['port']) ? $originUrl['port'] : ($this->originUseSSL ? 443 : 80);
+               
+               if (PROXY_SERVER_HTTP && !$this->originUseSSL) {
                        $this->path = $url;
                }
                else {
                        $this->path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '/';
                }
                
+               if (PROXY_SERVER_HTTP) {
+                       $parsedUrl = parse_url(PROXY_SERVER_HTTP);
+               }
+               
                $this->useSSL = $parsedUrl['scheme'] === 'https';
                $this->host = $parsedUrl['host'];
                $this->port = isset($parsedUrl['port']) ? $parsedUrl['port'] : ($this->useSSL ? 443 : 80);
@@ -216,10 +242,7 @@ final class HTTPRequest {
                
                // update the 'Host:' header if URL has changed
                if ($this->url != $url) {
-                       $originUseSSL = $originUrl['scheme'] === 'https';
-                       $originHost = $originUrl['host'];
-                       $originPort = isset($originUrl['port']) ? $originUrl['port'] : ($originUseSSL ? 443 : 80);
-                       $this->addHeader('host', $originHost.($originPort != ($originUseSSL ? 443 : 80) ? ':'.$originPort : ''));
+                       $this->addHeader('host', $this->originHost.($this->originPort != ($this->originUseSSL ? 443 : 80) ? ':'.$this->originPort : ''));
                }
                
                $this->url = $url;
@@ -230,7 +253,35 @@ final class HTTPRequest {
         */
        public function execute() {
                // connect
-               $remoteFile = new RemoteFile(($this->useSSL ? 'ssl://' : '').$this->host, $this->port, $this->options['timeout']);
+               $remoteFile = new RemoteFile(($this->useSSL ? 'ssl://' : '').$this->host, $this->port, $this->options['timeout'], array(
+                       'ssl' => array(
+                               'peer_name' => $this->originHost
+                       )
+               ));
+               
+               if ($this->originUseSSL && PROXY_SERVER_HTTP) {
+                       if ($this->useSSL) throw new SystemException("Unable to proxy HTTPS when using TLS for proxy connection");
+                       
+                       $request = "CONNECT ".$this->originHost.":".$this->originPort." HTTP/1.0\r\n";
+                       if (isset($this->headers['user-agent'])) {
+                               $request .= 'user-agent: '.reset($this->headers['user-agent'])."\r\n";
+                       }
+                       $request .= "Host: ".$this->originHost.":".$this->originPort."\r\n";
+                       $request .= "\r\n";
+                       $remoteFile->puts($request);
+                       $this->replyHeaders = array();
+                       while (!$remoteFile->eof()) {
+                               $line = $remoteFile->gets();
+                               if (rtrim($line) === '') {
+                                       $this->parseReplyHeaders();
+                                       
+                                       break;
+                               }
+                               $this->replyHeaders[] = $line;
+                       }
+                       if ($this->statusCode != 200) throw new SystemException("Expected 200 Ok as reply to my CONNECT, got '".$this->statusCode."'");
+                       $remoteFile->setTLS(true);
+               }
                
                $request = $this->options['method']." ".$this->path.($this->query ? '?'.$this->query : '')." HTTP/1.1\r\n";