Beispiel #1
0
 /**
  * Send the header
  * @param string Header. Example: 'Location: http://php.net/'
  * @param boolean Optional. Replace?
  * @param int Optional. HTTP response code.
  * @return void
  * @throws RequestHeadersAlreadySent
  */
 public function header($s, $replace = true, $code = false)
 {
     if ($code !== null) {
         $this->status($code);
     }
     if ($this->headers_sent) {
         throw new RequestHeadersAlreadySent();
         return false;
     }
     $e = explode(':', $s, 2);
     if (!isset($e[1])) {
         $e[0] = 'STATUS';
         if (strncmp($s, 'HTTP/', 5) === 0) {
             $s = substr($s, 9);
         }
     }
     $k = strtr(strtoupper($e[0]), HTTPRequest::$htr);
     if ($k === 'CONTENT_TYPE') {
         HTTPRequest::parse_str(strtr(strtolower($e[1]), HTTPRequest::$hvaltr), $ctype);
         if (!isset($ctype['charset'])) {
             $ctype['charset'] = $this->upstream->config->defaultcharset->value;
             $s = $e[0] . ': ';
             $i = 0;
             foreach ($ctype as $k => $v) {
                 $s .= ($i > 0 ? '; ' : '') . $k . ($v !== '' ? '=' . $v : '');
                 ++$i;
             }
         }
     }
     if ($k === 'SET_COOKIE') {
         $k .= '_' . ++$this->cookieNum;
     } elseif (!$replace && isset($this->headers[$k])) {
         return false;
     }
     $this->headers[$k] = $s;
     if ($k === 'CONTENT_LENGTH') {
         $this->contentLength = (int) $e[1];
     } elseif ($k === 'LOCATION') {
         $this->status(301);
     }
     if (Daemon::$compatMode) {
         is_callable('header_native') ? header_native($s) : header($s);
     }
     return true;
 }
 /**
  * Called when new data received.
  * @param string New received data.
  * @return void
  */
 public function stdin($buf)
 {
     $this->buf .= $buf;
     if ($this->state === self::STATE_ROOT) {
         if (strpos($this->buf, "<policy-file-request/>") !== FALSE) {
             $FP = FlashPolicyServer::getInstance();
             if ($FP && $FP->policyData) {
                 $this->write($FP->policyData . "");
             }
             $this->finish();
             return;
         }
         $i = 0;
         while (($l = $this->gets()) !== FALSE) {
             if ($i++ > 100) {
                 break;
             }
             if ($l === "\r\n") {
                 $this->state = self::STATE_HANDSHAKING;
                 if (isset($this->server['HTTP_SEC_WEBSOCKET_EXTENSIONS'])) {
                     $str = strtolower($this->server['HTTP_SEC_WEBSOCKET_EXTENSIONS']);
                     $str = preg_replace($this->extensionsCleanRegex, '', $str);
                     $this->extensions = explode(', ', $str);
                 }
                 if (!isset($this->server['HTTP_CONNECTION']) || !preg_match('~(?:^|\\W)Upgrade(?:\\W|$)~i', $this->server['HTTP_CONNECTION']) || !isset($this->server['HTTP_UPGRADE']) || strtolower($this->server['HTTP_UPGRADE']) !== 'websocket') {
                     $this->finish();
                     return;
                 }
                 if (isset($this->server['HTTP_COOKIE'])) {
                     HTTPRequest::parse_str(strtr($this->server['HTTP_COOKIE'], HTTPRequest::$hvaltr), $this->cookie);
                 }
                 // ----------------------------------------------------------
                 // Protocol discovery, based on HTTP headers...
                 // ----------------------------------------------------------
                 if (isset($this->server['HTTP_SEC_WEBSOCKET_VERSION'])) {
                     // HYBI
                     if ($this->server['HTTP_SEC_WEBSOCKET_VERSION'] == '8') {
                         // Version 8 (FF7, Chrome14)
                         $this->protocol = new WebSocketProtocolV13($this);
                     } elseif ($this->server['HTTP_SEC_WEBSOCKET_VERSION'] == '13') {
                         // newest protocol
                         $this->protocol = new WebSocketProtocolV13($this);
                     } else {
                         Daemon::$process->log(get_class($this) . '::' . __METHOD__ . " : Websocket protocol version " . $this->server['HTTP_SEC_WEBSOCKET_VERSION'] . ' is not yet supported for client "' . $this->addr . '"');
                         $this->finish();
                         return;
                     }
                 } elseif (!isset($this->server['HTTP_SEC_WEBSOCKET_KEY1']) || !isset($this->server['HTTP_SEC_WEBSOCKET_KEY2'])) {
                     $this->protocol = new WebSocketProtocolVE($this);
                 } else {
                     // Defaulting to HIXIE (Safari5 and many non-browser clients...)
                     $this->protocol = new WebSocketProtocolV0($this);
                 }
                 // ----------------------------------------------------------
                 // End of protocol discovery
                 // ----------------------------------------------------------
             } elseif (!$this->firstline) {
                 $this->firstline = true;
                 $e = explode(' ', $l);
                 $u = parse_url(isset($e[1]) ? $e[1] : '');
                 $this->server['REQUEST_METHOD'] = $e[0];
                 $this->server['REQUEST_URI'] = $u['path'] . (isset($u['query']) ? '?' . $u['query'] : '');
                 $this->server['DOCUMENT_URI'] = $u['path'];
                 $this->server['PHP_SELF'] = $u['path'];
                 $this->server['QUERY_STRING'] = isset($u['query']) ? $u['query'] : NULL;
                 $this->server['SCRIPT_NAME'] = $this->server['DOCUMENT_URI'] = isset($u['path']) ? $u['path'] : '/';
                 $this->server['SERVER_PROTOCOL'] = isset($e[2]) ? trim($e[2]) : '';
                 list($this->server['REMOTE_ADDR'], $this->server['REMOTE_PORT']) = explode(':', $this->addr);
             } else {
                 $e = explode(': ', $l);
                 if (isset($e[1])) {
                     $this->server['HTTP_' . strtoupper(strtr($e[0], HTTPRequest::$htr))] = rtrim($e[1], "\r\n");
                 }
             }
         }
     }
     if ($this->state === self::STATE_HANDSHAKING) {
         if (!$this->handshake($this->buf)) {
             return;
         }
         $this->buf = '';
         $this->state = self::STATE_HANDSHAKED;
     }
     if ($this->state === self::STATE_HANDSHAKED) {
         if (!isset($this->protocol)) {
             Daemon::$process->log(get_class($this) . '::' . __METHOD__ . ' : Cannot find session-related websocket protocol for client "' . $this->addr . '"');
             $this->finish();
             return;
         }
         $this->protocol->onRead();
     }
 }
Beispiel #3
0
 /**
  * Event of SocketSession (AsyncServer). Called when new data received.
  * @param string New received data.
  * @return void
  */
 public function stdin($buf)
 {
     $this->buf .= $buf;
     if (!$this->handshaked) {
         if (Daemon::$appResolver->checkAppEnabled('FlashPolicy')) {
             if (strpos($this->buf, '<policy-file-request/>') !== FALSE) {
                 if (($FP = Daemon::$appResolver->getInstanceByAppName('FlashPolicy')) && $FP->policyData) {
                     $this->write($FP->policyData . "");
                 }
                 $this->finish();
                 return;
             }
         }
         $i = 0;
         while (($l = $this->gets()) !== FALSE) {
             if ($i++ > 100) {
                 break;
             }
             if ($l === "\r\n") {
                 if (!isset($this->server['HTTP_CONNECTION']) || $this->server['HTTP_CONNECTION'] !== 'Upgrade' || !isset($this->server['HTTP_UPGRADE']) || $this->server['HTTP_UPGRADE'] !== 'WebSocket') {
                     $this->finish();
                     return;
                 }
                 if (isset($this->server['HTTP_COOKIE'])) {
                     HTTPRequest::parse_str(strtr($this->server['HTTP_COOKIE'], HTTPRequest::$hvaltr), $this->cookie);
                 }
                 if (!($this->secprotocol = isset($this->server['HTTP_SEC_WEBSOCKET_KEY1']) && isset($this->server['HTTP_SEC_WEBSOCKET_KEY2']))) {
                     $this->handshake();
                 }
                 break;
             }
             if (!$this->firstline) {
                 $this->firstline = TRUE;
                 $e = explode(' ', $l);
                 $u = parse_url(isset($e[1]) ? $e[1] : '');
                 $this->server['REQUEST_METHOD'] = $e[0];
                 $this->server['REQUEST_URI'] = $u['path'] . (isset($u['query']) ? '?' . $u['query'] : '');
                 $this->server['DOCUMENT_URI'] = $u['path'];
                 $this->server['PHP_SELF'] = $u['path'];
                 $this->server['QUERY_STRING'] = isset($u['query']) ? $u['query'] : NULL;
                 $this->server['SCRIPT_NAME'] = $this->server['DOCUMENT_URI'] = isset($u['path']) ? $u['path'] : '/';
                 $this->server['SERVER_PROTOCOL'] = isset($e[2]) ? $e[2] : '';
                 list($this->server['REMOTE_ADDR'], $this->server['REMOTE_PORT']) = explode(':', $this->clientAddr);
             } else {
                 $e = explode(': ', $l);
                 if (isset($e[1])) {
                     $this->server['HTTP_' . strtoupper(strtr($e[0], HTTPRequest::$htr))] = rtrim($e[1], "\r\n");
                 }
             }
         }
     }
     if ($this->handshaked) {
         while (($buflen = strlen($this->buf)) >= 2) {
             $frametype = ord(binarySubstr($this->buf, 0, 1));
             if (($frametype & 0x80) === 0x80) {
                 $len = 0;
                 $i = 0;
                 do {
                     $b = ord(binarySubstr($this->buf, ++$i, 1));
                     $n = $b & 0x7f;
                     $len *= 0x80;
                     $len += $n;
                 } while ($b > 0x80);
                 if ($this->appInstance->config->maxallowedpacket->value <= $len) {
                     // Too big packet
                     $this->finish();
                     return;
                 }
                 if ($buflen < $len + 2) {
                     // not enough data yet
                     return;
                 }
                 $data = binarySubstr($this->buf, 2, $len);
                 $this->buf = binarySubstr($this->buf, 2 + $len);
                 $this->onFrame($data, $frametype);
             } else {
                 if (($p = strpos($this->buf, "ÿ")) !== FALSE) {
                     if ($this->appInstance->config->maxallowedpacket->value <= $p - 1) {
                         // Too big packet
                         $this->finish();
                         return;
                     }
                     $data = binarySubstr($this->buf, 1, $p - 1);
                     $this->buf = binarySubstr($this->buf, $p + 1);
                     $this->onFrame($data, $frametype);
                 } else {
                     // not enough data yet
                     if ($this->appInstance->config->maxallowedpacket->value <= strlen($this->buf)) {
                         // Too big packet
                         $this->finish();
                     }
                     return;
                 }
             }
         }
     } elseif ($this->secprotocol) {
         if (strlen($this->buf) >= 8) {
             $bodyData = binarySubstr($this->buf, 0, 8);
             $this->resultKey = md5($this->computeKey($this->server['HTTP_SEC_WEBSOCKET_KEY1']) . $this->computeKey($this->server['HTTP_SEC_WEBSOCKET_KEY2']) . $bodyData, TRUE);
             $this->buf = binarySubstr($this->buf, 8);
             $this->handshake();
         }
     }
 }