Parse HTTP header fix
Using a standard method to parse the HTTP headers, with partial fallback
This commit is contained in:
		
							parent
							
								
									1495354e7c
								
							
						
					
					
						commit
						1ba8021df8
					
				@ -1,6 +1,5 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
namespace Ratchet\Protocol;
 | 
					namespace Ratchet\Protocol;
 | 
				
			||||||
use Ratchet\Server;
 | 
					 | 
				
			||||||
use Ratchet\Protocol\WebSocket\Client;
 | 
					use Ratchet\Protocol\WebSocket\Client;
 | 
				
			||||||
use Ratchet\Protocol\WebSocket\Version;
 | 
					use Ratchet\Protocol\WebSocket\Version;
 | 
				
			||||||
use Ratchet\Protocol\WebSocket\VersionInterface;
 | 
					use Ratchet\Protocol\WebSocket\VersionInterface;
 | 
				
			||||||
@ -9,6 +8,7 @@ use Ratchet\SocketObserver;
 | 
				
			|||||||
use Ratchet\Command\CommandInterface;
 | 
					use Ratchet\Command\CommandInterface;
 | 
				
			||||||
use Ratchet\Command\Action\SendMessage;
 | 
					use Ratchet\Command\Action\SendMessage;
 | 
				
			||||||
use Ratchet\Command\Composite;
 | 
					use Ratchet\Command\Composite;
 | 
				
			||||||
 | 
					use Ratchet\Protocol\WebSocket\Util\HTTP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The adapter to handle WebSocket requests/responses
 | 
					 * The adapter to handle WebSocket requests/responses
 | 
				
			||||||
@ -146,7 +146,7 @@ class WebSocket implements ProtocolInterface {
 | 
				
			|||||||
     * @return Version\VersionInterface
 | 
					     * @return Version\VersionInterface
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function getVersion($message) {
 | 
					    protected function getVersion($message) {
 | 
				
			||||||
        $headers = $this->getHeaders($message);
 | 
					        $headers = HTTP::getHeaders($message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (isset($headers['Sec-Websocket-Version'])) { // HyBi
 | 
					        if (isset($headers['Sec-Websocket-Version'])) { // HyBi
 | 
				
			||||||
            if ($headers['Sec-Websocket-Version'] == '8') {
 | 
					            if ($headers['Sec-Websocket-Version'] == '8') {
 | 
				
			||||||
@ -170,38 +170,4 @@ class WebSocket implements ProtocolInterface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return $this->_version[$version];
 | 
					        return $this->_version[$version];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @param string
 | 
					 | 
				
			||||||
     * @return array
 | 
					 | 
				
			||||||
     * @todo Consider strtolower all the header keys...right now PHP Changes Sec-WebSocket-X to Sec-Websocket-X...this could change
 | 
					 | 
				
			||||||
      */
 | 
					 | 
				
			||||||
    protected function getHeaders($http_message) {
 | 
					 | 
				
			||||||
        return function_exists('http_parse_headers') ? http_parse_headers($http_message) : $this->http_parse_headers($http_message);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * This is a fallback method for http_parse_headers as not all php installs have the HTTP module present
 | 
					 | 
				
			||||||
     * @internal
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected function http_parse_headers($http_message) {
 | 
					 | 
				
			||||||
        $retVal = array();
 | 
					 | 
				
			||||||
        $fields = explode("br", preg_replace("%(<|/\>|>)%", "", nl2br($http_message)));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach ($fields as $field) {
 | 
					 | 
				
			||||||
            if (preg_match('%^(GET|POST|PUT|DELETE|PATCH)(\s)(.*)%', $field, $matchReq)) {
 | 
					 | 
				
			||||||
                $retVal["Request Method"] = $matchReq[1];
 | 
					 | 
				
			||||||
                $retVal["Request Url"]    = $matchReq[3];
 | 
					 | 
				
			||||||
            } elseif (preg_match('/([^:]+): (.+)/m', $field, $match) ) {
 | 
					 | 
				
			||||||
                $match[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($match[1])));
 | 
					 | 
				
			||||||
                if (isset($retVal[$match[1]])) {
 | 
					 | 
				
			||||||
                    $retVal[$match[1]] = array($retVal[$match[1]], $match[2]);
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    $retVal[$match[1]] = trim($match[2]);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return $retVal;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										39
									
								
								lib/Ratchet/Protocol/WebSocket/Util/HTTP.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								lib/Ratchet/Protocol/WebSocket/Util/HTTP.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					namespace Ratchet\Protocol\WebSocket\Util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class HTTP {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param string
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static function getHeaders($http_message) {
 | 
				
			||||||
 | 
					        return function_exists('http_parse_headers') ? http_parse_headers($http_message) : self::http_parse_headers($http_message);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param string
 | 
				
			||||||
 | 
					     * @return array
 | 
				
			||||||
 | 
					     * This is a fallback method for http_parse_headers as not all php installs have the HTTP module present
 | 
				
			||||||
 | 
					     * @internal
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected static function http_parse_headers($http_message) {
 | 
				
			||||||
 | 
					        $retVal = array();
 | 
				
			||||||
 | 
					        $fields = explode("br", preg_replace("%(<|/\>|>)%", "", nl2br($http_message)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach ($fields as $field) {
 | 
				
			||||||
 | 
					            if (preg_match('%^(GET|POST|PUT|DELETE|PATCH)(\s)(.*)%', $field, $matchReq)) {
 | 
				
			||||||
 | 
					                $retVal["Request Method"] = $matchReq[1];
 | 
				
			||||||
 | 
					                $retVal["Request Url"]    = $matchReq[3];
 | 
				
			||||||
 | 
					            } elseif (preg_match('/([^:]+): (.+)/m', $field, $match) ) {
 | 
				
			||||||
 | 
					                $match[1] = preg_replace('/(?<=^|[\x09\x20\x2D])./e', 'strtoupper("\0")', strtolower(trim($match[1])));
 | 
				
			||||||
 | 
					                if (isset($retVal[$match[1]])) {
 | 
				
			||||||
 | 
					                    $retVal[$match[1]] = array($retVal[$match[1]], $match[2]);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    $retVal[$match[1]] = trim($match[2]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $retVal;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
namespace Ratchet\Protocol\WebSocket\Version;
 | 
					namespace Ratchet\Protocol\WebSocket\Version;
 | 
				
			||||||
 | 
					use Ratchet\Protocol\WebSocket\Util\HTTP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The HyBi-10 version, identified in the headers as version 8, is currently implemented by the latest Chrome and Firefix version
 | 
					 * The HyBi-10 version, identified in the headers as version 8, is currently implemented by the latest Chrome and Firefix version
 | 
				
			||||||
@ -10,10 +11,9 @@ class HyBi10 implements VersionInterface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @return array
 | 
					     * @return array
 | 
				
			||||||
     * @todo Use the WebSocket::http_parse_headers wrapper instead of native function (how to get to method is question)
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function handshake($message) {
 | 
					    public function handshake($message) {
 | 
				
			||||||
        $headers = http_parse_headers($message);
 | 
					        $headers = HTTP::getHeaders($message);
 | 
				
			||||||
        $key     = $this->sign($headers['Sec-Websocket-Key']);
 | 
					        $key     = $this->sign($headers['Sec-Websocket-Key']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user