From: Matteo Nastasi (mop) Date: Fri, 16 Aug 2013 08:55:18 +0000 (+0200) Subject: Merge branch 'master' into ws X-Git-Tag: v4.9.0~2 X-Git-Url: http://mop.ddnsfree.com/gitweb/?a=commitdiff_plain;h=b41e2233431a8862b741c7eb4c998c1a47263ed7;hp=-c;p=brisk.git Merge branch 'master' into ws --- b41e2233431a8862b741c7eb4c998c1a47263ed7 diff --combined web/Obj/brisk.phh index 0e3c67a,593b6e2..707b20a --- a/web/Obj/brisk.phh +++ b/web/Obj/brisk.phh @@@ -2366,9 -2366,9 +2366,9 @@@ class Roo } $content = ""; - $user->stream_init($s_a_p->rndstr, $enc, $header_out, $content, $get, $post, $cookie); + $user->stream_init($s_a_p->rndstr, $enc, $header, $header_out, $content, $get, $post, $cookie); - $response = headers_render($header_out, -1).chunked_content($user->rd_zls_get(), $content); + $response = headers_render($header_out, -1).$user->chunked_content($content); $response_l = mb_strlen($response, "ASCII"); $wret = @fwrite($new_socket, $response, $response_l); diff --combined web/Obj/transports.phh index 32befba,a77fad7..3b6e79c --- a/web/Obj/transports.phh +++ b/web/Obj/transports.phh @@@ -58,8 -58,7 +58,8 @@@ class Transport_template function Transport_template() { } - function init($enc, &$header_out, $init_string, $base, $step) + // return string value is appended to the content of the returned page + function init($enc, $header, &$header_out, $init_string, $base, $step) { } @@@ -70,122 -69,18 +70,126 @@@ function chunk($step, $cont) { } + + function is_chunked() + { + } } +class Transport_websocket { + $magicGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + + function Transport_websocket() { + } + + protected function doHandshake($user, $buffer) { + $magicGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + $headers = array(); + $lines = explode("\n",$buffer); + foreach ($lines as $line) { + if (strpos($line,":") !== false) { + $header = explode(":",$line,2); + $headers[strtolower(trim($header[0]))] = trim($header[1]); + } else if (stripos($line,"get ") !== false) { + preg_match("/GET (.*) HTTP/i", $buffer, $reqResource); + $headers['get'] = trim($reqResource[1]); + } + } + if (isset($headers['get'])) { + $user->requestedResource = $headers['get']; + } else { + // todo: fail the connection + $handshakeResponse = "HTTP/1.1 405 Method Not Allowed\r\n\r\n"; + } + if (!isset($headers['host']) || !$this->checkHost($headers['host'])) { + $handshakeResponse = "HTTP/1.1 400 Bad Request"; + } + if (!isset($headers['upgrade']) || strtolower($headers['upgrade']) != 'websocket') { + $handshakeResponse = "HTTP/1.1 400 Bad Request"; + } + if (!isset($headers['connection']) || strpos(strtolower($headers['connection']), 'upgrade') === FALSE) { + $handshakeResponse = "HTTP/1.1 400 Bad Request"; + } + if (!isset($headers['sec-websocket-key'])) { + $handshakeResponse = "HTTP/1.1 400 Bad Request"; + } else { + + } + if (!isset($headers['sec-websocket-version']) || strtolower($headers['sec-websocket-version']) != 13) { + $handshakeResponse = "HTTP/1.1 426 Upgrade Required\r\nSec-WebSocketVersion: 13"; + } + if (($this->headerOriginRequired && !isset($headers['origin']) ) || ($this->headerOriginRequired && !$this->checkOrigin($headers['origin']))) { + $handshakeResponse = "HTTP/1.1 403 Forbidden"; + } + if (($this->headerSecWebSocketProtocolRequired && !isset($headers['sec-websocket-protocol'])) || ($this->headerSecWebSocketProtocolRequired && !$this->checkWebsocProtocol($header['sec-websocket-protocol']))) { + $handshakeResponse = "HTTP/1.1 400 Bad Request"; + } + if (($this->headerSecWebSocketExtensionsRequired && !isset($headers['sec-websocket-extensions'])) || ($this->headerSecWebSocketExtensionsRequired && !$this->checkWebsocExtensions($header['sec-websocket-extensions']))) { + $handshakeResponse = "HTTP/1.1 400 Bad Request"; + } + + // Done verifying the _required_ headers and optionally required headers. + + if (isset($handshakeResponse)) { + socket_write($user->socket,$handshakeResponse,strlen($handshakeResponse)); + $this->disconnect($user->socket); + return false; + } + + $user->headers = $headers; + $user->handshake = $buffer; + + $webSocketKeyHash = sha1($headers['sec-websocket-key'] . $magicGUID); + + $rawToken = ""; + for ($i = 0; $i < 20; $i++) { + $rawToken .= chr(hexdec(substr($webSocketKeyHash,$i*2, 2))); + } + $handshakeToken = base64_encode($rawToken) . "\r\n"; + + $subProtocol = (isset($headers['sec-websocket-protocol'])) ? $this->processProtocol($headers['sec-websocket-protocol']) : ""; + $extensions = (isset($headers['sec-websocket-extensions'])) ? $this->processExtensions($headers['sec-websocket-extensions']) : ""; + + $handshakeResponse = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: $handshakeToken$subProtocol$extensions\r\n"; + socket_write($user->socket,$handshakeResponse,strlen($handshakeResponse)); + $this->connected($user); + } + + + function init($enc, $header, &$header_out, $init_string, $base, $step) + { + + + + + $ret = sprintf("@BEGIN@ /* %s */ @END@", $init_string); + if ($enc != 'plain') + $header_out['Content-Encoding'] = $enc; + $header_out['Cache-Control'] = 'no-cache, must-revalidate'; // HTTP/1.1 + $header_out['Expires'] = 'Mon, 26 Jul 1997 05:00:00 GMT'; // Date in the past + $header_out['Content-type'] = 'application/xml; charset="utf-8"'; + + return ($ret); + } + + static function fini($init_string, $base, $blockerr) + { + return (sprintf('@BEGIN@ %s window.onbeforeunload = null; window.onunload = null; document.location.assign("%sindex.php"); @END@', ($blockerr ? 'xstm.stop(); ' : ''), $base)); + return (""); + } + + function chunk($step, $cont) + { + return ("@BEGIN@".$cont."@END@"); + } +} + class Transport_xhr { function Transport_xhr() { } - function init($enc, &$header_out, $init_string, $base, $step) + function init($enc, $header, &$header_out, $init_string, $base, $step) { $ret = sprintf("@BEGIN@ /* %s */ @END@", $init_string); if ($enc != 'plain') @@@ -207,6 -102,11 +211,11 @@@ { return ("@BEGIN@".$cont."@END@"); } + + function is_chunked() + { + return TRUE; + } } class Transport_iframe { @@@ -214,7 -114,7 +223,7 @@@ function Transport_iframe() { } - function init($enc, &$header_out, $init_string, $base, $step) + function init($enc, $header, &$header_out, $init_string, $base, $step) { $ret = ""; @@@ -275,6 -175,11 +284,11 @@@ push(null);\n// -->\n", $step) push(\"%s\");\n// -->\n", $step, escpush($cont) ); } } + + function is_chunked() + { + return TRUE; + } } class Transport_htmlfile extends Transport_iframe { diff --combined web/Obj/user.phh index 97b0a38,f52bc3e..55a3a75 --- a/web/Obj/user.phh +++ b/web/Obj/user.phh @@@ -108,6 -108,7 +108,7 @@@ class User var $rd_cache; // place where store failed fwrite data var $rd_zls; // zlibstream object handle if compressed stream, else FALSE var $rd_transp; // class that define stream encapsulation type (iframe, xhr, ...) + var $rd_is_chunked; // is the transport chunked or not ? var $comm; // commands array // var $asta_card; // @@@ -168,6 -169,7 +169,7 @@@ $thiz->rd_cache = ""; $thiz->rd_zls = FALSE; $thiz->rd_transp = NULL; + $thiz->rd_is_chunked = FALSE; $thiz->asta_card = -2; $thiz->asta_pnt = -1; @@@ -330,6 -332,7 +332,7 @@@ $this->rd_kalive = $curtime + RD_KEEPALIVE_TOUT; $this->rd_zls = ZLibStream::create($enc); $this->rd_transp = Transport::create($transp); + $this->rd_is_chunked = $this->rd_transp->is_chunked(); } function rd_socket_get() { @@@ -696,7 -699,7 +699,7 @@@ stat step */ -function stream_init($init_string, $enc, &$header_out, &$body, $get, $post, $cookie) +function stream_init($init_string, $enc, $header, &$header_out, &$body, $get, $post, $cookie) { $curtime = time(); @@@ -717,7 -720,7 +720,7 @@@ $this->rd_data_set($curtime, $transp, $enc, $stat, $subst, $step, $from); - $body .= $this->rd_transp->init($enc, &$header_out, $init_string, self::base_get(), $this->rd_scristp); + $body .= $this->rd_transp->init($enc, $header, &$header_out, $init_string, self::base_get(), $this->rd_scristp); return TRUE; } @@@ -779,6 -782,37 +782,37 @@@ function is_supp_custom( return (FALSE); } + function is_chunked() + { + return $this->rd_is_chunked; + } + + + function chunked_content($content) + { + if ($this->rd_zls) { + $cont_comp = $this->rd_zls->compress_chunk($content); + } + else { + $cont_comp = $content; + } + $cont_comp_l = mb_strlen($cont_comp, "ASCII"); + // printf("CHUNK: [%s]\n", $content); + + if ($this->is_chunked()) { + return (sprintf("%X\r\n", $cont_comp_l).$cont_comp."\r\n"); + } + else { + return $content; + } + } + + function chunked_fini() + { + return sprintf("0\r\n"); + } + + } // end class User diff --combined web/briskin5/Obj/briskin5.phh index 0f49f59,6e3a52f..f45b210 --- a/web/briskin5/Obj/briskin5.phh +++ b/web/briskin5/Obj/briskin5.phh @@@ -1233,8 -1233,8 +1233,9 @@@ class Bin5 } $content = ""; - $user->stream_init($s_a_p->rndstr, $enc, $header_out, $content, $get, $post, $cookie); + $user->stream_init($s_a_p->rndstr, $enc, $header, $header_out, $content, $get, $post, $cookie); - $response = headers_render($header_out, -1).chunked_content($user->rd_zls_get(), $content); ++ + $response = headers_render($header_out, -1).$user->chunked_content($content); $response_l = mb_strlen($response, "ASCII"); $wret = @fwrite($new_socket, $response, $response_l);