Пример #1
0
 public function touch()
 {
     if (!$this->cursor || $this->cursor->destroyed) {
         $tag = $this;
         $this->appInstance->db->{$this->appInstance->config->dbname->value . '.muchatevents'}->find(function ($cursor) use($tag) {
             $tag->cursor = $cursor;
             foreach ($cursor->items as $k => &$item) {
                 if ($item['type'] === 'kickUsers') {
                     foreach ($tag->sessions as $id => $v) {
                         $sess = $tag->appInstance->sessions[$id];
                         if ($sess->username !== null && $tag->appInstance->compareMask($sess->username, $item['users'])) {
                             $sess->removeTags(array($tag->tag), true);
                             $sess->sysMsg('You were kicked from #' . $tag->tag . '.' . ($item['reason'] !== '' ? ' Reason: ' . $item['reason'] : ''));
                             $sess->send(array('type' => 'youWereKicked', 'reason' => $item['reason']));
                             $tag->appInstance->broadcastEvent(array('type' => 'msg', 'mtype' => 'system', 'text' => ' Kicked: ' . $sess->username . ($item['reason'] !== '' ? ', reason: ' . $item['reason'] : ''), 'color' => 'green', 'tags' => $tag->tag));
                         }
                     }
                 } elseif ($item['type'] === 'forceChangeNick') {
                     foreach ($tag->sessions as $id => $v) {
                         $sess = $tag->appInstance->sessions[$id];
                         if ($sess->username !== null && $sess->username === $item['username']) {
                             $sess->setUsername($item['changeto'], true);
                         }
                     }
                 } else {
                     $item['_id'] = (string) $item['_id'];
                     if (isset($item['sid'])) {
                         $item['sid'] = (string) $item['sid'];
                     }
                     $packet = Session::serialize($item);
                     foreach ($tag->sessions as $id => $v) {
                         $s = $tag->appInstance->sessions[$id];
                         if (is_string($item['tags'])) {
                             $item['tags'] = array($item['tags']);
                         }
                         if (in_array('%private', $item['tags'])) {
                             if (!isset($item['to'])) {
                                 continue;
                             }
                             if (!in_array($s->username, $item['to']) && $s->username != $item['from']) {
                                 continue;
                             }
                         }
                         if ($s->putMsgId($item['_id'])) {
                             $s->client->sendFrame($packet);
                         }
                     }
                 }
                 unset($cursor->items[$k]);
             }
         }, array('tailable' => true, 'sort' => array('$natural' => 1), 'where' => array('ts' => array('$gt' => microtime(true)), 'tags' => array('$in' => binarySubstr($this->tag, 0, 1) == '%' ? array($this->tag) : array($this->tag, '%all')))));
     } elseif (!$this->cursor->session->busy) {
         try {
             $this->cursor->getMore();
         } catch (ConnectionFinished $e) {
             $this->cursor = false;
         }
     }
 }
Пример #2
0
 public function gets()
 {
     $p = strpos($this->buf, "\n");
     if ($p === FALSE) {
         return FALSE;
     }
     $r = binarySubstr($this->buf, 0, $p + 1);
     $this->buf = binarySubstr($this->buf, $p + 1);
     return $r;
 }
Пример #3
0
 /**
  * Read a first line ended with \n from buffer, removes it from buffer and returns the line
  * @return string Line. Returns false when failed to get a line
  */
 public function gets()
 {
     $p = strpos($this->buf, $this->EOL);
     if ($p === FALSE) {
         return FALSE;
     }
     $sEOL = strlen($this->EOL);
     $r = binarySubstr($this->buf, 0, $p + $sEOL);
     $this->buf = binarySubstr($this->buf, $p + $sEOL);
     return $r;
 }
Пример #4
0
 public function send($packet)
 {
     if (Daemon::$settings['logevents']) {
         Daemon::log(__METHOD__ . ' invoked (' . $this->clientAddr . '): ' . Daemon::var_dump($packet));
     }
     if ($this->http) {
         $s = json_encode($packet);
         $l = strlen($s);
         for ($o = 0; $o < $l;) {
             $c = min(Daemon::$parsedSettings['chunksize'], $l - $o);
             $chunk = dechex($c) . "\r\n" . ($c === $l ? $s : binarySubstr($s, $o, $c)) . "\r\n";
             $this->write($chunk);
             $o += $c;
         }
     } else {
         $this->writeln(json_encode($packet));
     }
 }
Пример #5
0
 public function onFrame($data, $type)
 {
     $packet = json_decode($data, true);
     if (!$packet) {
         return;
     }
     if (!isset($packet['cmd'])) {
         return;
     }
     $cmd = $packet['cmd'];
     if ($cmd === 'setUsername' && isset($packet['username'])) {
         if ($this->username !== null) {
             return;
         }
         //$this->setUsername($packet['username']);
     } elseif ($cmd === 'hello' && isset($packet['authkey'])) {
         if ($this->username !== null) {
             return;
         }
         $clientId = $this->client->connId;
         $appInstance = $this->appInstance;
         $appInstance->ORM->getAuthKey($packet['authkey'], function ($authkey) use($clientId, $appInstance, $packet) {
             if (!isset($appInstance->sessions[$clientId])) {
                 return;
             }
             $session = $appInstance->sessions[$clientId];
             if (!$authkey) {
                 $session->send(array('type' => 'youWereKicked', 'reason' => 'Incorrect auth. data.'));
                 return;
             }
             if (isset($authkey['su'])) {
                 $session->su = $authkey['su'];
             }
             $session->authkey = $authkey;
             $appInstance->db->{$appInstance->config->dbname->value . '.akicks'}->findOne(function ($akick) use($authkey, $packet, $clientId, $appInstance) {
                 if (!isset($appInstance->sessions[$clientId])) {
                     return;
                 }
                 $session = $appInstance->sessions[$clientId];
                 if ($akick) {
                     $session->send(array('type' => 'youWereKicked', 'reason' => $akick['reason']));
                     return;
                 }
                 $session->updateAvailTags();
                 Daemon::log('Incorrect auth. data.');
                 $session->setUsername($authkey['username'], false, $packet['tab']);
             });
         });
     } elseif ($cmd === 'getAvailTags') {
         $this->updateAvailTags($packet['_id']);
     } elseif ($cmd === 'setTags') {
         if ($this->username === null) {
             return;
         }
         $this->setTags($packet['tags']);
     } elseif ($cmd === 'setmuchatignore') {
         if ($this->username === null) {
             return;
         }
         $doc = array('username' => $this->username, 'blocked' => $packet['username']);
         if ($doc['username'] == $doc['blocked']) {
             return;
         }
         if ($packet['action']) {
             $this->appInstance->db->{$this->appInstance->config->dbname->value . '.muchatignore'}->insert($doc);
         } else {
             $this->appInstance->db->{$this->appInstance->config->dbname->value . '.muchatignore'}->remove($doc);
         }
     } elseif ($cmd === 'keepalive') {
         $this->updateSession(array('atime' => microtime(true)));
     } elseif ($cmd == 'getHistory') {
         if ($this->username === null) {
             return;
         }
         $session = $this;
         $condts = array('$lt' => microtime(true));
         $lastTS = isset($packet['lastTS']) ? (double) $packet['lastTS'] : 0;
         if ($lastTS > 0) {
             $condts['$gt'] = $lastTS;
         }
         $this->appInstance->db->{$this->appInstance->config->dbname->value . '.muchatevents'}->find(function ($cursor) use($session) {
             $tag->cursor = $cursor;
             $cursor->items = array_reverse($cursor->items);
             foreach ($cursor->items as $k => &$item) {
                 $item['_id'] = (string) $item['_id'];
                 if (isset($item['sid'])) {
                     $item['sid'] = (string) $item['sid'];
                 }
                 if (is_string($item['tags'])) {
                     $item['tags'] = array($item['tags']);
                 }
                 if (in_array('%private', $item['tags'])) {
                     if (!isset($item['to'])) {
                         continue;
                     }
                     if (!in_array($session->username, $item['to']) && $session->username != $item['from']) {
                         continue;
                     }
                 }
                 $item['history'] = true;
                 $session->send($item);
                 unset($cursor->items[$k]);
             }
             $cursor->destroy();
         }, array('sort' => array('ts' => -1), 'where' => array('ts' => $condts, 'tags' => array('$in' => $packet['tags'])), 'limit' => -20));
     } elseif ($cmd == 'getUserlist') {
         if ($this->username === null) {
             return;
         }
         $session = $this;
         $this->appInstance->db->{$this->appInstance->config->dbname->value . '.muchatsessions'}->find(function ($cursor) use($session) {
             $tag->cursor = $cursor;
             $cursor->items = array_reverse($cursor->items);
             foreach ($cursor->items as $k => &$item) {
                 unset($item['_id']);
                 $item['id'] = isset($item['id']) ? (string) $item['id'] : '';
             }
             $session->send(array('type' => 'userlist', 'userlist' => $cursor->items));
             $cursor->destroy();
         }, array('sort' => array('ctime' => -1), 'where' => array('tags' => array('$in' => array_diff($packet['tags'], array('%private'))), 'atime' => array('$gt' => microtime(true) - 20), 'username' => array('$exists' => true)), 'limit' => -2000));
     } elseif ($cmd === 'sendMessage') {
         if (!isset($packet['tags'])) {
             return false;
         }
         if (!$this->username) {
             return false;
         }
         $username = $this->username;
         if (!isset($packet['text']) || trim($packet['text']) === '') {
             return false;
         }
         $text = $packet['text'];
         $color = isset($packet['color']) ? (string) $packet['color'] : '';
         static $colors = array('black', 'red', 'green', 'blue');
         if (!in_array($color, $colors)) {
             $color = $colors[0];
         }
         $c = substr($text, 0, 1);
         if ($c === '/') {
             $e = explode(' ', $text, 2);
             $m = strtolower(substr($e[0], 1));
             $text = isset($e[1]) ? trim($e[1]) : '';
             if ($m === 'me') {
                 if ($text === '') {
                     $this->sysMsg('/me <message>: insufficient parameters', $packet['tab']);
                 } else {
                     $this->updateSession(array('statusmsg' => $text));
                 }
             } elseif ($m === 'tags') {
                 $tags = trim($text);
                 if ($tags !== '') {
                     $this->setTags(array_map('trim', explode(',', $tags)));
                 }
                 $this->sysMsg('/tags: ' . implode(', ', $this->tags), $packet['tab']);
             } elseif ($m === 'join') {
                 $tags = $text;
                 if ($tags !== '') {
                     $this->addTags(array_map('trim', explode(',', $tags)));
                 } else {
                     $this->sysMsg('/join <tag1>{,<tagN>}: insufficient parameters', $packet['tab']);
                 }
             } elseif ($m === 'part') {
                 $tags = $text;
                 if ($tags !== '') {
                     $this->removeTags(array_map('trim', explode(',', $tags)));
                 } else {
                     $this->sysMsg('/part <tag1>{,<tagN>}: insufficient parameters', $packet['tab']);
                 }
             } elseif ($m === 'nick') {
                 //$this->setUsername($text);
             } elseif ($m === 'thetime') {
                 $this->sysMsg('Current time: ' . date('r'), $packet['tab']);
             } elseif ($m === 'su') {
                 $password = $text;
                 if ($this->su || $password !== '' && $password === $this->appInstance->config->adminpassword->value) {
                     $this->su = true;
                     $this->send(array('type' => 'youAreModerator'));
                     $this->sysMsg('You\'ve got the power.', $packet['tab']);
                 } else {
                     $this->sysMsg('Your powers are weak, old man.', $packet['tab']);
                 }
             } elseif ($m === 'kick') {
                 $e = explode(' ', $text, 3);
                 $users = isset($e[0]) ? trim($e[0]) : '';
                 $tags = isset($e[1]) ? trim($e[1]) : '';
                 $reason = isset($e[2]) ? trim($e[2]) : '';
                 if ($users === '') {
                     $this->sysMsg('/kick <name> [<tags>] [<reason>]: insufficient parameters', $packet['tab']);
                 } else {
                     if (!$this->su) {
                         $this->sysMsg('Your powers are weak, old man.', $packet['tab']);
                     } else {
                         $this->appInstance->kickUsers($users, $tags, $reason);
                     }
                 }
             } elseif ($m === 'fchname') {
                 $e = explode(' ', $text);
                 $name = isset($e[0]) ? trim($e[0]) : '';
                 $newname = isset($e[1]) ? trim($e[1]) : '';
                 if ($name === '' || $newname === '') {
                     $this->sysMsg('/fchname <name> <newname>: insufficient parameters', $packet['tab']);
                 } elseif (!$this->appInstance->validateUsername($newname)) {
                     $this->sysMsg('/fchname: newname>', $packet['tab']);
                 } else {
                     if (!$this->su) {
                         $this->sysMsg('Your powers are weak, old man.', $packet['tab']);
                     } else {
                         $this->appInstance->forceChangeNick($name, $newname);
                     }
                 }
             } else {
                 $this->sysMsg($m . ' Unknown command', $packet['tab']);
             }
         } else {
             $doc = array('mtype' => 'pub', 'tags' => array_intersect($packet['tags'], $this->tags), 'from' => $username, 'text' => $text, 'color' => $color, 'tab' => isset($packet['tab']) ? $packet['tab'] : null);
             if (preg_match_all('~(?<=^|\\s)@([A-Za-z\\-_!0-9\\.\\wА-Яа-я]+)~u', $text, $m)) {
                 $doc['to'] = $m[1];
                 if (sizeof($doc['to']) == 1) {
                     if (binarySubstr($doc['text'], 0, $n = strlen($s = '@' . $doc['to'][0] . ': ')) == $s) {
                         $doc['text'] = binarySubstr($doc['text'], $n);
                     }
                 }
             }
             if (in_array('%private', $packet['tags'])) {
                 $clientId = $this->client->connId;
                 $appInstance = $this->appInstance;
                 $this->appInstance->db->{$this->appInstance->config->dbname->value . '.muchatignore'}->findOne(function ($item) use($clientId, $appInstance, $doc) {
                     if (!$item) {
                         if (!isset($appInstance->sessions[$clientId])) {
                             return;
                         }
                         $session = $appInstance->sessions[$clientId];
                         $session->sendMessage($doc);
                     }
                 }, array('where' => array('username' => $this->username, 'blocked' => $doc['to'][0])));
             } else {
                 $this->sendMessage($doc);
             }
         }
     }
 }
Пример #6
0
 /**
  * Convert bitmap into bytes
  * @param  string  $bitmap    Bitmap
  * @param  integer $check_len Check length?
  * @return string|false
  */
 public static function bitmap2bytes($bitmap, $check_len = 0)
 {
     $r = '';
     $bitmap = str_pad($bitmap, ceil(strlen($bitmap) / 8) * 8, '0', STR_PAD_LEFT);
     for ($i = 0, $n = strlen($bitmap) / 8; $i < $n; ++$i) {
         $r .= chr((int) bindec(binarySubstr($bitmap, $i * 8, 8)));
     }
     if ($check_len && strlen($r) !== $check_len) {
         return false;
     }
     return $r;
 }
Пример #7
0
 /**
  * Called when new data received
  * @return void
  */
 public function onRead()
 {
     Timer::setTimeout($this->keepaliveTimer);
     while (($line = $this->readline()) !== null) {
         if ($line === '') {
             continue;
         }
         if (strlen($line) > 512) {
             Daemon::$process->log('IRCBouncerConnection error: buffer overflow.');
             $this->finish();
             return;
         }
         $line = binarySubstr($line, 0, -strlen($this->EOL));
         $p = strpos($line, ':', 1);
         $max = $p ? substr_count($line, " ", 0, $p) + 1 : 18;
         $e = explode(" ", $line, $max);
         $i = 0;
         $cmd = $e[$i++];
         $args = [];
         for ($s = min(sizeof($e), 14); $i < $s; ++$i) {
             if ($e[$i][0] === ':') {
                 $args[] = binarySubstr($e[$i], 1);
                 break;
             }
             $args[] = $e[$i];
         }
         if (ctype_digit($cmd)) {
             $code = (int) $cmd;
             $cmd = isset(IRC::$codes[$code]) ? IRC::$codes[$code] : 'UNKNOWN-' . $code;
         }
         $this->onCommand($cmd, $args);
     }
     if (strlen($this->buf) > 512) {
         Daemon::$process->log('IRCClientConnection error: buffer overflow.');
         $this->finish();
     }
 }
Пример #8
0
 public function stdin($buf)
 {
     $this->buf .= $buf;
     if (!$this->handshaked) {
         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 (!($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], Request::$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 (Daemon::$parsedSettings['mod' . $this->appInstance->modname . 'maxallowedpacket'] <= $len) {
                     $this->finish();
                     return;
                 }
                 if ($buflen < $len + 2) {
                     return;
                 }
                 // not enough data yet
                 $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 (Daemon::$parsedSettings['mod' . $this->appInstance->modname . 'maxallowedpacket'] <= $p - 1) {
                         $this->finish();
                         return;
                     }
                     $data = binarySubstr($this->buf, 1, $p - 1);
                     $this->buf = binarySubstr($this->buf, $p + 1);
                     $this->onFrame($data, $frametype);
                 } else {
                     if (Daemon::$parsedSettings['mod' . $this->appInstance->modname . 'maxallowedpacket'] <= strlen($this->buf)) {
                         $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();
         }
     }
 }
Пример #9
0
 public function onRead()
 {
     while ($this->connection && ($buflen = strlen($this->connection->buf)) >= 1) {
         $frametype = ord(binarySubstr($this->connection->buf, 0, 1));
         if (($frametype & 0x80) === 0x80) {
             $len = 0;
             $i = 0;
             do {
                 $b = ord(binarySubstr($this->connection->buf, ++$i, 1));
                 $n = $b & 0x7f;
                 $len *= 0x80;
                 $len += $n;
             } while ($b > 0x80);
             if ($this->connection->pool->maxAllowedPacket <= $len) {
                 // Too big packet
                 $this->connection->finish();
                 return FALSE;
             }
             if ($buflen < $len + 2) {
                 // not enough data yet
                 return FALSE;
             }
             $decodedData = binarySubstr($this->connection->buf, 2, $len);
             $this->connection->buf = binarySubstr($this->connection->buf, 2 + $len);
             $this->connection->onFrame($decodedData, 'BINARY');
         } else {
             if (($p = strpos($this->connection->buf, "ÿ")) !== FALSE) {
                 if ($this->connection->pool->maxAllowedPacket <= $p - 1) {
                     // Too big packet
                     $this->connection->finish();
                     return FALSE;
                 }
                 $decodedData = binarySubstr($this->connection->buf, 1, $p - 1);
                 $this->connection->buf = binarySubstr($this->connection->buf, $p + 1);
                 $this->connection->onFrame($decodedData, 'STRING');
             } else {
                 if ($this->connection->pool->maxAllowedPacket <= $buflen - 1) {
                     // Too big packet
                     $this->connection->finish();
                     return FALSE;
                 }
                 // not enough data yet
                 return;
             }
         }
     }
 }
 /**
  * Handles the output from downstream requests.
  * @param object Request.
  * @param string The output.
  * @return void
  */
 public function requestOut($req, $output)
 {
     $outlen = strlen($output);
     /* 
      * Iterate over every character in the string, 
      * escaping with a slash or encoding to UTF-8 where necessary 
      */
     // string bytes counter
     $d = 0;
     for ($c = 0; $c < $outlen; ++$c) {
         $ord_var_c = ord($output[$d]);
         switch (true) {
             case $ord_var_c >= 0x20 && $ord_var_c <= 0x7f:
                 // characters U-00000000 - U-0000007F (same as ASCII)
                 $d++;
                 break;
             case ($ord_var_c & 0xe0) == 0xc0:
                 // characters U-00000080 - U-000007FF, mask 110XXXXX
                 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                 $d += 2;
                 break;
             case ($ord_var_c & 0xf0) == 0xe0:
                 // characters U-00000800 - U-0000FFFF, mask 1110XXXX
                 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                 $d += 3;
                 break;
             case ($ord_var_c & 0xf8) == 0xf0:
                 // characters U-00010000 - U-001FFFFF, mask 11110XXX
                 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                 $d += 4;
                 break;
             case ($ord_var_c & 0xfc) == 0xf8:
                 // characters U-00200000 - U-03FFFFFF, mask 111110XX
                 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                 $d += 5;
                 break;
             case ($ord_var_c & 0xfe) == 0xfc:
                 // characters U-04000000 - U-7FFFFFFF, mask 1111110X
                 // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                 $d += 6;
                 break;
             default:
                 $d++;
         }
     }
     for ($o = 0; $o < $d;) {
         $c = min($this->pool->config->chunksize->value, $d - $o);
         $w = $this->write("" . "" . pack('nn', $req->attrs->id, $c) . "" . "" . ($c === $d ? $output : binarySubstr($output, $o, $c)));
         if ($w === false) {
             $req->abort();
             return false;
         }
         $o += $c;
     }
     return true;
 }
Пример #11
0
 /**
  * Called when new data received
  * @return void
  */
 public function onRead()
 {
     while (($line = $this->readline()) !== null) {
         if ($line === '') {
             continue;
         }
         if (strlen($line) > 512) {
             Daemon::$process->log('IRCClientConnection error: buffer overflow.');
             $this->finish();
             return;
         }
         $line = binarySubstr($line, 0, -strlen($this->EOL));
         $p = strpos($line, ' :', 1);
         $max = $p !== false ? substr_count($line, " ", 0, $p + 1) + 1 : 18;
         $e = explode(" ", $line, $max);
         $i = 0;
         $from = IRC::parseUsermask($e[$i][0] === ':' ? binarySubstr($e[$i++], 1) : null);
         $cmd = $e[$i++];
         $args = [];
         for ($s = min(sizeof($e), 14); $i < $s; ++$i) {
             if ($e[$i][0] === ':') {
                 $args[] = binarySubstr($e[$i], 1);
                 break;
             }
             $args[] = $e[$i];
         }
         if (ctype_digit($cmd)) {
             $code = (int) $cmd;
             $cmd = isset(IRC::$codes[$code]) ? IRC::$codes[$code] : $code;
         }
         $this->lastLine = $line;
         $this->onCommand($from, $cmd, $args);
     }
     if (strlen($this->buf) > 512) {
         Daemon::$process->log('IRCClientConnection error: buffer overflow.');
         $this->finish();
     }
 }
Пример #12
0
 /**
  * Called when new data received
  * @param string New data
  * @return void
  */
 public function stdin($buf)
 {
     if ($this->state === self::STATE_BODY) {
         goto body;
     }
     $this->buf .= $buf;
     $buf = '';
     while (($line = $this->gets()) !== FALSE) {
         if ($line === $this->EOL) {
             if (isset($this->headers['HTTP_CONTENT_LENGTH'])) {
                 $this->contentLength = (int) $this->headers['HTTP_CONTENT_LENGTH'];
             } else {
                 $this->contentLength = -1;
             }
             if (isset($this->headers['HTTP_TRANSFER_ENCODING'])) {
                 $e = explode(', ', strtolower($this->headers['HTTP_TRANSFER_ENCODING']));
                 $this->chunked = in_array('chunked', $e, true);
             } else {
                 $this->chunked = false;
             }
             if (isset($this->headers['HTTP_CONNECTION'])) {
                 $e = explode(', ', strtolower($this->headers['HTTP_CONNECTION']));
                 $this->keepalive = in_array('keep-alive', $e, true);
             }
             if (!$this->chunked) {
                 $this->body .= $this->buf;
                 $this->buf = '';
             }
             $this->state = self::STATE_BODY;
             break;
         }
         if ($this->state === self::STATE_ROOT) {
             $this->headers['STATUS'] = rtrim($line);
             $this->state = self::STATE_HEADERS;
         } elseif ($this->state === self::STATE_HEADERS) {
             $e = explode(': ', rtrim($line));
             if (isset($e[1])) {
                 $this->headers['HTTP_' . strtoupper(strtr($e[0], HTTPRequest::$htr))] = $e[1];
             }
         }
     }
     if ($this->state !== self::STATE_BODY) {
         return;
         // not enough data yet
     }
     body:
     if ($this->chunked) {
         $this->buf .= $buf;
         chunk:
         if ($this->curChunkSize === null) {
             // outside of chunk
             $l = $this->gets();
             if ($l === $this->EOL) {
                 // skip empty line
                 goto chunk;
             }
             if ($l === false) {
                 return;
                 // not enough data yet
             }
             $l = rtrim($l);
             if (!ctype_xdigit($l)) {
                 $this->protocolError = __LINE__;
                 $this->finish();
                 // protocol error
                 return;
             }
             $this->curChunkSize = hexdec($l);
         }
         if ($this->curChunkSize !== null) {
             if ($this->curChunkSize === 0) {
                 if ($this->gets() === $this->EOL) {
                     $this->requestFinished();
                     return;
                 } else {
                     // protocol error
                     $this->protocolError = __LINE__;
                     $this->finish();
                     return;
                 }
             }
             $len = strlen($this->buf);
             $n = $this->curChunkSize - strlen($this->curChunk);
             if ($n >= $len) {
                 $this->curChunk .= $this->buf;
                 $this->buf = '';
             } else {
                 $this->curChunk .= binarySubstr($this->buf, 0, $n);
                 $this->buf = binarySubstr($this->buf, $n);
             }
             if ($this->curChunkSize <= strlen($this->curChunk)) {
                 $this->body .= $this->curChunk;
                 $this->curChunkSize = null;
                 $this->curChunk = '';
                 goto chunk;
             }
         }
     } else {
         $this->body .= $buf;
         if ($this->contentLength !== -1 && strlen($this->body) >= $this->contentLength) {
             $this->requestFinished();
         }
     }
 }
Пример #13
0
 /**
  * Handles the output from downstream requests
  * @param  object  $req Request
  * @param  string  $out The output
  * @return boolean      Success
  */
 public function requestOut($req, $out)
 {
     $cs = $this->pool->config->chunksize->value;
     if (strlen($out) > $cs) {
         while (($ol = strlen($out)) > 0) {
             $l = min($cs, $ol);
             if ($this->sendChunk($req, binarySubstr($out, 0, $l)) === false) {
                 $req->abort();
                 return false;
             }
             $out = binarySubstr($out, $l);
         }
     } elseif ($this->sendChunk($req, $out) === false) {
         $req->abort();
         return false;
     }
     return true;
 }
Пример #14
0
 /**
  * Write to shared memory
  * @param  string  $data   Data
  * @param  integer $offset Offset
  * @return boolean         Success
  */
 public function write($data, $offset)
 {
     $segno = floor($offset / $this->segsize);
     if (!isset($this->segments[$segno])) {
         if (!$this->open($segno, true)) {
             return false;
         }
     }
     $sOffset = $offset % $this->segsize;
     $d = $this->segsize - ($sOffset + strlen($data));
     if ($d < 0) {
         $this->write(binarySubstr($data, $d), ($segno + 1) * $this->segsize);
         $data = binarySubstr($data, 0, $d);
     }
     //Daemon::log('writing to #'.$offset.' (segno '.$segno.')');
     shmop_write($this->segments[$segno], $data, $sOffset);
     return true;
 }
Пример #15
0
 /**
  * Data decoding, according to related IETF draft
  * 
  * @see http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10#page-16
  */
 public function onRead()
 {
     $data = '';
     while ($this->connection && ($buflen = strlen($this->connection->buf)) >= 1) {
         $p = 0;
         // offset
         $first = ord(binarySubstr($this->connection->buf, $p++, 1));
         // first byte integer (fin, opcode)
         $firstBits = decbin($first);
         $rsv1 = (bool) $firstBits[1];
         $rsv2 = (bool) $firstBits[2];
         $rsv3 = (bool) $firstBits[3];
         $opcode = (int) bindec(substr($firstBits, 4, 4));
         if ($opcode === 0x8) {
             // CLOSE
             $this->connection->finish();
             return;
         }
         $opcodeName = $this->opcodes[$opcode];
         $second = ord(binarySubstr($this->connection->buf, $p++, 1));
         // second byte integer (masked, payload length)
         $fin = (bool) ($first >> 7);
         $isMasked = (bool) ($second >> 7);
         $dataLength = $second & 0x7f;
         if ($dataLength === 0x7e) {
             // 2 bytes-length
             if ($buflen < $p + 2) {
                 return;
                 // not enough data yet
             }
             $dataLength = $this->bytes2int(binarySubstr($this->connection->buf, $p, 2), false);
             $p += 2;
         } elseif ($dataLength === 0x7f) {
             // 4 bytes-length
             if ($buflen < $p + 4) {
                 return;
                 // not enough data yet
             }
             $dataLength = $this->bytes2int(binarySubstr($this->connection->buf, $p, 4));
             $p += 4;
         }
         if ($this->connection->pool->maxAllowedPacket <= $dataLength) {
             // Too big packet
             $this->connection->finish();
             return;
         }
         if ($isMasked) {
             if ($buflen < $p + 4) {
                 return;
                 // not enough data yet
             }
             $mask = binarySubstr($this->connection->buf, $p, 4);
             $p += 4;
         }
         if ($buflen < $p + $dataLength) {
             return;
             // not enough data yet
         }
         $data = binarySubstr($this->connection->buf, $p, $dataLength);
         $p += $dataLength;
         if ($isMasked) {
             $data = $this->mask($data, $mask);
         }
         $this->connection->buf = binarySubstr($this->connection->buf, $p);
         //Daemon::log(Debug::dump(array('ext' => $this->connection->extensions, 'rsv1' => $rsv1, 'data' => Debug::exportBytes($data))));
         if ($rsv1 && in_array('deflate-frame', $this->connection->extensions)) {
             // deflate frame
             $data = gzuncompress($data, $this->connection->pool->maxAllowedPacket);
         }
         if (!$fin) {
             $this->connection->framebuf .= $data;
         } else {
             $this->connection->onFrame($this->connection->framebuf . $data, $opcodeName);
             if ($this->connection) {
                 $this->connection->framebuf = '';
             }
         }
     }
 }
Пример #16
0
 /**
  * Called when new data received
  * @param string New data
  * @return void
  */
 public function stdin($buf)
 {
     $this->buf .= $buf;
     start:
     $this->buflen = strlen($this->buf);
     if (($packet = $this->getPacketHeader()) === FALSE) {
         return;
     }
     $this->seq = $packet[1] + 1;
     if ($this->buflen < 4 + $packet[0]) {
         // not whole packet yet
         return;
     }
     $p = 4;
     if ($this->cstate === self::STATE_ROOT) {
         $this->cstate = self::STATE_GOT_INIT;
         $p = 4;
         $this->protover = ord(binarySubstr($this->buf, $p++, 1));
         if ($this->protover === 0xff) {
             // error
             $fieldCount = $this->protover;
             $this->protover = 0;
             $this->onResponse->push($this->onConnected);
             $this->onConnected = null;
             goto field;
         }
         $this->serverver = '';
         while ($p < $this->buflen) {
             $c = binarySubstr($this->buf, $p++, 1);
             if ($c === "") {
                 break;
             }
             $this->serverver .= $c;
         }
         $this->threadId = $this->bytes2int(binarySubstr($this->buf, $p, 4));
         $p += 4;
         $this->scramble = binarySubstr($this->buf, $p, 8);
         $p += 9;
         $this->serverCaps = $this->bytes2int(binarySubstr($this->buf, $p, 2));
         $p += 2;
         $this->serverLang = ord(binarySubstr($this->buf, $p++, 1));
         $this->serverStatus = $this->bytes2int(binarySubstr($this->buf, $p, 2));
         $p += 2;
         $p += 13;
         $restScramble = binarySubstr($this->buf, $p, 12);
         $this->scramble .= $restScramble;
         $p += 13;
         $this->auth();
     } else {
         $fieldCount = ord(binarySubstr($this->buf, $p++, 1));
         field:
         if ($fieldCount === 0xff) {
             // Error packet
             $u = unpack('v', binarySubstr($this->buf, $p, 2));
             $p += 2;
             $this->errno = $u[1];
             $state = binarySubstr($this->buf, $p, 6);
             $p = +6;
             $this->errmsg = binarySubstr($this->buf, $p, $packet[0] + 4 - $p);
             $this->onError();
         } elseif ($fieldCount === 0x0) {
             // OK Packet Empty
             if ($this->cstate === self::STATE_AUTH_SENT) {
                 $this->cstate = self::STATE_HANDSHAKED;
                 if ($this->path !== '') {
                     $this->query('USE `' . $this->path . '`');
                 }
             }
             $this->affectedRows = $this->parseEncodedBinary($this->buf, $p);
             $this->insertId = $this->parseEncodedBinary($this->buf, $p);
             $u = unpack('v', binarySubstr($this->buf, $p, 2));
             $p += 2;
             $this->serverStatus = $u[1];
             $u = unpack('v', binarySubstr($this->buf, $p, 2));
             $p += 2;
             $this->warnCount = $u[1];
             $this->message = binarySubstr($this->buf, $p, $packet[0] + 4 - $p);
             $this->onResultDone();
         } elseif ($fieldCount === 0xfe) {
             // EOF Packet
             if ($this->instate === self::INSTATE_ROW) {
                 $this->onResultDone();
             } else {
                 ++$this->instate;
             }
         } else {
             // Data packet
             --$p;
             if ($this->instate === self::INSTATE_HEADER) {
                 // Result Set Header Packet
                 $extra = $this->parseEncodedBinary($this->buf, $p);
                 $this->instate = self::INSTATE_FIELD;
             } elseif ($this->instate === self::INSTATE_FIELD) {
                 // Field Packet
                 $field = array('catalog' => $this->parseEncodedString($this->buf, $p), 'db' => $this->parseEncodedString($this->buf, $p), 'table' => $this->parseEncodedString($this->buf, $p), 'org_table' => $this->parseEncodedString($this->buf, $p), 'name' => $this->parseEncodedString($this->buf, $p), 'org_name' => $this->parseEncodedString($this->buf, $p));
                 ++$p;
                 // filler
                 $u = unpack('v', binarySubstr($this->buf, $p, 2));
                 $p += 2;
                 $field['charset'] = $u[1];
                 $u = unpack('V', binarySubstr($this->buf, $p, 4));
                 $p += 4;
                 $field['length'] = $u[1];
                 $field['type'] = ord(binarySubstr($this->buf, $p, 1));
                 ++$p;
                 $u = unpack('v', binarySubstr($this->buf, $p, 2));
                 $p += 2;
                 $field['flags'] = $u[1];
                 $field['decimals'] = ord(binarySubstr($this->buf, $p, 1));
                 ++$p;
                 $this->resultFields[] = $field;
             } elseif ($this->instate === self::INSTATE_ROW) {
                 // Row Packet
                 $row = array();
                 for ($i = 0, $nf = sizeof($this->resultFields); $i < $nf; ++$i) {
                     $row[$this->resultFields[$i]['name']] = $this->parseEncodedString($this->buf, $p);
                 }
                 $this->resultRows[] = $row;
             }
         }
     }
     $this->buf = binarySubstr($this->buf, 4 + $packet[0]);
     goto start;
 }
Пример #17
0
 public function stdin($buf)
 {
     $this->buf .= $buf;
     start:
     if ($this->state === 0) {
         while (($l = $this->gets()) !== FALSE) {
             $e = explode(' ', rtrim($l, "\r\n"));
             if ($e[0] == 'VALUE') {
                 $this->key = $e[1];
                 $this->valueFlags = $e[2];
                 $this->valueLength = $e[3];
                 $this->result = '';
                 $this->state = 1;
                 break;
             } elseif ($e[0] == 'STAT') {
                 if ($this->result === NULL) {
                     $this->result = array();
                 }
                 $this->result[$e[1]] = $e[2];
             } elseif ($e[0] === 'END' || $e[0] === 'DELETED' || $e[0] === 'ERROR' || $e[0] === 'CLIENT_ERROR' || $e[0] === 'SERVER_ERROR') {
                 if ($e[0] !== 'END') {
                     $this->result = FALSE;
                     $this->error = isset($e[1]) ? $e[1] : NULL;
                 }
                 $f = array_shift($this->onResponse);
                 if ($f) {
                     call_user_func($f, $this);
                 }
                 $this->valueSize = 0;
                 $this->result = NULL;
             }
         }
     }
     if ($this->state === 1) {
         if ($this->valueSize < $this->valueLength) {
             $n = $this->valueLength - $this->valueSize;
             $buflen = strlen($this->buf);
             if ($buflen > $n) {
                 $this->result .= binarySubstr($this->buf, 0, $n);
                 $this->buf = binarySubstr($this->buf, $n);
             } else {
                 $this->result .= $this->buf;
                 $n = $buflen;
                 $this->buf = '';
             }
             $this->valueSize += $n;
             if ($this->valueSize >= $this->valueLength) {
                 $this->state = 0;
                 goto start;
             }
         }
     }
 }
Пример #18
0
 public function readConn($connId)
 {
     static $roles = array(1 => 'FCGI_RESPONDER', 2 => 'FCGI_AUTHORIZER', 3 => 'FCGI_FILTER');
     $buf = $this->read($connId, $this->readPacketSize);
     if (sizeof($this->poolState[$connId]) < 3) {
         return;
     }
     if ($this->poolState[$connId]['state'] === 0) {
         if (strpos($buf, '<policy-file-request/>') !== FALSE) {
             if (($FP = Daemon::$appResolver->getInstanceByAppName('FlashPolicy')) && $FP->policyData) {
                 Daemon::$worker->writePoolState[$connId] = TRUE;
                 event_buffer_write($this->buf[$connId], $FP->policyData . "");
             }
             $this->finishConnection($connId);
             return;
         }
         ++Daemon::$worker->queryCounter;
         ++$this->poolState[$connId]['n'];
         $rid = $connId . '-' . $this->poolState[$connId]['n'];
         $this->poolState[$connId]['state'] = 1;
         $req = new stdClass();
         $req->attrs = new stdClass();
         $req->attrs->request = array();
         $req->attrs->get = array();
         $req->attrs->post = array();
         $req->attrs->cookie = array();
         $req->attrs->server = array();
         $req->attrs->files = array();
         $req->attrs->session = NULL;
         $req->attrs->connId = $connId;
         $req->attrs->id = $this->poolState[$connId]['n'];
         $req->attrs->params_done = FALSE;
         $req->attrs->stdin_done = FALSE;
         $req->attrs->stdinbuf = '';
         $req->attrs->stdinlen = 0;
         $req->attrs->inbuf = '';
         $req->attrs->chunked = FALSE;
         if (Daemon::$settings['mod' . $this->modname . 'logqueue']) {
             Daemon::log('[WORKER ' . Daemon::$worker->pid . '] new request queued.');
         }
         Daemon::$worker->queue[$rid] = $req;
         $this->poolQueue[$connId][$req->attrs->id] = $req;
     } else {
         $rid = $connId . '-' . $this->poolState[$connId]['n'];
         if (isset(Daemon::$worker->queue[$rid])) {
             $req = Daemon::$worker->queue[$rid];
         } else {
             Daemon::log('Unexpected input. Request ID: ' . $rid . '.');
             return;
         }
     }
     if ($this->poolState[$connId]['state'] === 1) {
         $req->attrs->inbuf .= $buf;
         if (strpos($req->attrs->inbuf, '<policy-file-request/>') !== FALSE) {
             if (($FP = Daemon::$appResolver->getInstanceByAppName('FlashPolicy')) && $FP->policyData) {
                 Daemon::$worker->writePoolState[$req->attrs->connId] = TRUE;
                 event_buffer_write($this->buf[$req->attrs->connId], $FP->policyData . "");
             }
             $this->finishConnection($req->attrs->connId);
             return;
         }
         $buf = '';
         if (($p = strpos($req->attrs->inbuf, "\r\n\r\n")) !== FALSE) {
             $headers = binarySubstr($req->attrs->inbuf, 0, $p);
             $h = explode("\r\n", $headers);
             $req->attrs->inbuf = binarySubstr($req->attrs->inbuf, $p + 4);
             $e = explode(' ', $h[0]);
             $u = parse_url($e[1]);
             $req->attrs->server['REQUEST_METHOD'] = $e[0];
             $req->attrs->server['REQUEST_URI'] = $u['path'] . (isset($u['query']) ? '?' . $u['query'] : '');
             $req->attrs->server['DOCUMENT_URI'] = $u['path'];
             $req->attrs->server['PHP_SELF'] = $u['path'];
             $req->attrs->server['QUERY_STRING'] = isset($u['query']) ? $u['query'] : NULL;
             $req->attrs->server['SCRIPT_NAME'] = $req->attrs->server['DOCUMENT_URI'] = isset($u['path']) ? $u['path'] : '/';
             $req->attrs->server['SERVER_PROTOCOL'] = $e[2];
             list($req->attrs->server['REMOTE_ADDR'], $req->attrs->server['REMOTE_PORT']) = explode(':', $this->poolState[$connId]['addr']);
             for ($i = 1, $n = sizeof($h); $i < $n; ++$i) {
                 $e = explode(': ', $h[$i]);
                 if (isset($e[1])) {
                     $req->attrs->server['HTTP_' . strtoupper(strtr($e[0], Request::$htr))] = $e[1];
                 }
             }
             $req->attrs->params_done = TRUE;
             if (isset($req->attrs->server['HTTP_CONNECTION']) && $req->attrs->server['HTTP_CONNECTION'] === 'Upgrade' && isset($req->attrs->server['HTTP_UPGRADE']) && $req->attrs->server['HTTP_UPGRADE'] === 'WebSocket') {
                 if ($this->WS) {
                     $this->WS->inheritFromRequest($req, $this);
                     return;
                 }
             } else {
                 $req = Daemon::$appResolver->getRequest($req, $this, isset(Daemon::$settings[$k = 'mod' . $this->modname . 'responder']) ? Daemon::$settings[$k] : NULL);
             }
             if ($req instanceof stdClass) {
                 $this->endRequest($req, 0, 0);
                 unset(Daemon::$worker->queue[$rid]);
             } else {
                 if (Daemon::$settings['mod' . $this->modname . 'sendfile'] && (!Daemon::$settings['mod' . $this->modname . 'sendfileonlybycommand'] || isset($req->attrs->server['USE_SENDFILE'])) && !isset($req->attrs->server['DONT_USE_SENDFILE'])) {
                     $fn = tempnam(Daemon::$settings['mod' . $this->modname . 'sendfiledir'], Daemon::$settings['mod' . $this->modname . 'sendfileprefix']);
                     $req->sendfp = fopen($fn, 'wb');
                     $req->header('X-Sendfile: ' . $fn);
                 }
                 $req->stdin($req->attrs->inbuf);
                 $req->attrs->inbuf = '';
                 Daemon::$worker->queue[$rid] = $req;
                 $this->poolQueue[$connId][$req->attrs->id] = $req;
                 $this->poolState[$connId]['state'] = 2;
             }
         }
     }
     if ($this->poolState[$connId]['state'] === 2) {
         $req->stdin($buf);
         if (Daemon::$settings['logevents']) {
             Daemon::log('stdin_done = ' . ($req->attrs->stdin_done ? '1' : '0'));
         }
         if ($req->attrs->stdin_done) {
             $this->poolState[$req->attrs->connId]['state'] = 0;
         }
     }
     if ($req->attrs->stdin_done && $req->attrs->params_done) {
         if (($order = ini_get('request_order')) || ($order = ini_get('variables_order'))) {
             for ($i = 0, $s = strlen($order); $i < $s; ++$i) {
                 $char = $order[$i];
                 if ($char == 'G') {
                     $req->attrs->request += $req->attrs->get;
                 } elseif ($char == 'P') {
                     $req->attrs->request += $req->attrs->post;
                 } elseif ($char == 'C') {
                     $req->attrs->request += $req->attrs->cookie;
                 }
             }
         } else {
             $req->attrs->request = $req->attrs->get + $req->attrs->post + $req->attrs->cookie;
         }
         $this->timeLastReq = time();
     }
 }
Пример #19
0
 public function stdin($buf)
 {
     $this->buf .= $buf;
     if (Daemon::$settings['mod' . $this->appInstance->modname . 'protologging']) {
         Daemon::log('Server --> Client: ' . Daemon::exportBytes($buf) . "\n\n");
     }
     start:
     $this->buflen = strlen($this->buf);
     if (($packet = $this->getPacketHeader()) === FALSE) {
         return;
     }
     $this->seq = $packet[1] + 1;
     if ($this->cstate === 0) {
         if ($this->buflen < 4 + $packet[0]) {
             return;
         }
         // no whole packet yet
         $this->cstate = 1;
         $p = 4;
         $this->protover = ord(binarySubstr($this->buf, $p++, 1));
         $this->serverver = '';
         while ($p < $this->buflen) {
             $c = binarySubstr($this->buf, $p++, 1);
             if ($c === "") {
                 break;
             }
             $this->serverver .= $c;
         }
         $this->threadId = $this->bytes2int(binarySubstr($this->buf, $p, 4));
         $p += 4;
         $this->scramble = binarySubstr($this->buf, $p, 8);
         $p += 9;
         $this->serverCaps = $this->bytes2int(binarySubstr($this->buf, $p, 2));
         $p += 2;
         $this->serverLang = ord(binarySubstr($this->buf, $p++, 1));
         $this->serverStatus = $this->bytes2int(binarySubstr($this->buf, $p, 2));
         $p += 2;
         $p += 13;
         $restScramble = binarySubstr($this->buf, $p, 12);
         $this->scramble .= $restScramble;
         $p += 13;
         $this->auth();
     } else {
         if ($this->buflen < 4 + $packet[0]) {
             return;
         }
         // not whole packet yet
         $p = 4;
         $fieldCount = ord(binarySubstr($this->buf, $p, 1));
         $p += 1;
         if ($fieldCount === 0xff) {
             $u = unpack('v', binarySubstr($this->buf, $p, 2));
             $p += 2;
             $this->errno = $u[1];
             $state = binarySubstr($this->buf, $p, 6);
             $p = +6;
             $this->errmsg = binarySubstr($this->buf, $p, $packet[0] + 4 - $p);
             $this->onError();
         } elseif ($fieldCount === 0x0) {
             if ($this->cstate === 2) {
                 $this->cstate = 4;
             }
             $this->affectedRows = $this->parseEncodedBinary($this->buf, $p);
             $this->insertId = $this->parseEncodedBinary($this->buf, $p);
             $u = unpack('v', binarySubstr($this->buf, $p, 2));
             $p += 2;
             $this->serverStatus = $u[1];
             $u = unpack('v', binarySubstr($this->buf, $p, 2));
             $p += 2;
             $this->warnCount = $u[1];
             $this->message = binarySubstr($this->buf, $p, $packet[0] + 4 - $p);
             $this->onResultDone();
         } elseif ($fieldCount === 0xfe) {
             ++$this->instate;
             if ($this->instate === 3) {
                 $this->onResultDone();
             }
         } else {
             --$p;
             if ($this->instate === 0) {
                 $extra = $this->parseEncodedBinary($this->buf, $p);
                 ++$this->instate;
             } elseif ($this->instate === 1) {
                 $field = array();
                 $field['catalog'] = $this->parseEncodedString($this->buf, $p);
                 $field['db'] = $this->parseEncodedString($this->buf, $p);
                 $field['table'] = $this->parseEncodedString($this->buf, $p);
                 $field['org_table'] = $this->parseEncodedString($this->buf, $p);
                 $field['name'] = $this->parseEncodedString($this->buf, $p);
                 $field['org_name'] = $this->parseEncodedString($this->buf, $p);
                 ++$p;
                 // filler
                 $u = unpack('v', binarySubstr($this->buf, $p, 2));
                 $p += 2;
                 $field['charset'] = $u[1];
                 $u = unpack('V', binarySubstr($this->buf, $p, 4));
                 $p += 4;
                 $field['length'] = $u[1];
                 $field['type'] = ord(binarySubstr($this->buf, $p, 1));
                 ++$p;
                 $u = unpack('v', binarySubstr($this->buf, $p, 2));
                 $p += 2;
                 $field['flags'] = $u[1];
                 $field['decimals'] = ord(binarySubstr($this->buf, $p, 1));
                 ++$p;
                 $this->resultFields[] = $field;
             } elseif ($this->instate === 2) {
                 $row = array();
                 for ($i = 0, $nf = sizeof($this->resultFields); $i < $nf; ++$i) {
                     $row[$this->resultFields[$i]['name']] = $this->parseEncodedString($this->buf, $p);
                 }
                 $this->resultRows[] = $row;
             }
         }
     }
     $this->buf = binarySubstr($this->buf, 4 + $packet[0]);
     goto start;
 }
Пример #20
0
 public function stdin($buf)
 {
     if ($this->state === 4) {
         if ($this->slave) {
             $this->slave->write($buf);
         }
         return;
     }
     $this->buf .= $buf;
     start:
     $l = strlen($this->buf);
     if ($this->state === 0) {
         if ($l < 2) {
             return;
         }
         // Not enough data yet
         $n = ord(binarySubstr($this->buf, 1, 1));
         if ($l < $n + 2) {
             return;
         }
         // Not enough data yet
         $this->ver = binarySubstr($this->buf, 0, 1);
         $methods = binarySubstr($this->buf, 2, $n);
         $this->buf = binarySubstr($this->buf, $n + 2);
         if (!Daemon::$settings['mod' . $this->appInstance->modname . 'auth']) {
             $m = "";
             $this->state = 3;
         } elseif (strpos($methods, "") !== FALSE) {
             $m = "";
             $this->state = 2;
         } else {
             $m = "ÿ";
             $this->state = 1;
         }
         $this->write($this->ver . $m);
         if ($this->state === 1) {
             $this->finish();
         } else {
             goto start;
         }
     } elseif ($this->state === 2) {
         if ($l < 3) {
             return;
         }
         // Not enough data yet
         $ver = binarySubstr($this->buf, 0, 1);
         if ($ver !== $this->ver) {
             $this->finish();
             return;
         }
         $ulen = ord(binarySubstr($this->buf, 1, 1));
         if ($l < 3 + $ulen) {
             return;
         }
         // Not enough data yet
         $username = binarySubstr($this->buf, 2, $ulen);
         $plen = ord(binarySubstr($this->buf, 1, 1));
         if ($l < 3 + $ulen + $plen) {
             return;
         }
         // Not enough data yet
         $password = binarySubstr($this->buf, 2 + $ulen, $plen);
         if ($username != Daemon::$settings['mod' . $this->appInstance->modname . 'username'] || $password != Daemon::$settings['mod' . $this->appInstance->modname . 'password']) {
             $this->state = 1;
             $m = "";
         } else {
             $this->state = 3;
             $m = "";
         }
         $this->buf = binarySubstr($this->buf, 3 + $ulen + $plen);
         $this->write($this->ver . $m);
         if ($this->state === 1) {
             $this->finish();
         } else {
             goto start;
         }
     } elseif ($this->state === 3) {
         if ($l < 4) {
             return;
         }
         // Not enough data yet
         $ver = binarySubstr($this->buf, 0, 1);
         if ($ver !== $this->ver) {
             $this->finish();
             return;
         }
         $cmd = binarySubstr($this->buf, 1, 1);
         $atype = binarySubstr($this->buf, 3, 1);
         $pl = 4;
         if ($atype === "") {
             $address = inet_ntop(binarySubstr($this->buf, $pl, 4));
             $pl += 4;
         } elseif ($atype === "") {
             $len = ord(binarySubstr($this->buf, $pl, 1));
             ++$pl;
             $address = binarySubstr($this->buf, $pl, $len);
             $pl += $len;
         } elseif ($atype === "") {
             $address = inet_ntop(binarySubstr($this->buf, $pl, 16));
             $pl += 16;
         } else {
             $this->finish();
             return;
         }
         $u = unpack('nport', $bin = binarySubstr($this->buf, $pl, 2));
         $port = $u['port'];
         $pl += 2;
         $this->buf = binarySubstr($this->buf, $pl);
         $connId = $this->appInstance->connectTo($this->destAddr = $address, $this->destPort = $port);
         if (!$connId) {
             $this->write($this->ver . "");
             $this->finish();
         } else {
             $this->slave = $this->appInstance->sessions[$connId] = new SocksServerSlaveSession($connId, $this->appInstance);
             $this->slave->client = $this;
             $this->slave->write($this->buf);
             $this->buf = '';
             $this->state = 4;
         }
     }
 }
Пример #21
0
 /**
  * Parse request body
  * @return void
  */
 public function parseStdin()
 {
     do {
         if ($this->boundary === false) {
             break;
         }
         $continue = false;
         if ($this->mpartstate === 0) {
             // seek to the nearest boundary
             if (($p = strpos($this->attrs->stdinbuf, $ndl = '--' . $this->boundary . "\r\n", $this->mpartoffset)) !== false) {
                 // we have found the nearest boundary at position $p
                 $this->mpartoffset = $p + strlen($ndl);
                 $this->mpartstate = 1;
                 $continue = true;
             }
         } elseif ($this->mpartstate === 1) {
             // parse the part's headers
             $this->mpartcondisp = false;
             if (($p = strpos($this->attrs->stdinbuf, "\r\n\r\n", $this->mpartoffset)) !== false) {
                 // we got all of the headers
                 $h = explode("\r\n", binarySubstr($this->attrs->stdinbuf, $this->mpartoffset, $p - $this->mpartoffset));
                 $this->mpartoffset = $p + 4;
                 $this->attrs->stdinbuf = binarySubstr($this->attrs->stdinbuf, $this->mpartoffset);
                 $this->mpartoffset = 0;
                 for ($i = 0, $s = sizeof($h); $i < $s; ++$i) {
                     $e = explode(':', $h[$i], 2);
                     $e[0] = strtr(strtoupper($e[0]), HTTPRequest::$htr);
                     if (isset($e[1])) {
                         $e[1] = ltrim($e[1]);
                     }
                     if ($e[0] == 'CONTENT_DISPOSITION' && isset($e[1])) {
                         parse_str(strtr($e[1], HTTPRequest::$hvaltr), $this->mpartcondisp);
                         if (!isset($this->mpartcondisp['form-data'])) {
                             break;
                         }
                         if (!isset($this->mpartcondisp['name'])) {
                             break;
                         }
                         $this->mpartcondisp['name'] = trim($this->mpartcondisp['name'], '"');
                         if (isset($this->mpartcondisp['filename'])) {
                             $this->mpartcondisp['filename'] = trim($this->mpartcondisp['filename'], '"');
                             if (!ini_get('file_uploads')) {
                                 break;
                             }
                             $this->attrs->files[$this->mpartcondisp['name']] = array('name' => $this->mpartcondisp['filename'], 'type' => '', 'tmp_name' => '', 'error' => UPLOAD_ERR_OK, 'size' => 0);
                             $tmpdir = ini_get('upload_tmp_dir');
                             if ($tmpdir === false) {
                                 $this->attrs->files[$this->mpartcondisp['name']]['fp'] = false;
                                 $this->attrs->files[$this->mpartcondisp['name']]['error'] = UPLOAD_ERR_NO_TMP_DIR;
                             } else {
                                 $this->attrs->files[$this->mpartcondisp['name']]['fp'] = @fopen($this->attrs->files[$this->mpartcondisp['name']]['tmp_name'] = tempnam($tmpdir, 'php'), 'w');
                                 if (!$this->attrs->files[$this->mpartcondisp['name']]['fp']) {
                                     $this->attrs->files[$this->mpartcondisp['name']]['error'] = UPLOAD_ERR_CANT_WRITE;
                                 }
                             }
                             $this->mpartstate = 3;
                         } else {
                             $this->attrs->post[$this->mpartcondisp['name']] = '';
                         }
                     } elseif ($e[0] == 'CONTENT_TYPE' && isset($e[1])) {
                         if (isset($this->mpartcondisp['name']) && isset($this->mpartcondisp['filename'])) {
                             $this->attrs->files[$this->mpartcondisp['name']]['type'] = $e[1];
                         }
                     }
                 }
                 if ($this->mpartstate === 1) {
                     $this->mpartstate = 2;
                 }
                 $continue = true;
             }
         } elseif ($this->mpartstate === 2 || $this->mpartstate === 3) {
             // process the body
             if (($p = strpos($this->attrs->stdinbuf, $ndl = "\r\n--" . $this->boundary . "\r\n", $this->mpartoffset)) !== false || ($p = strpos($this->attrs->stdinbuf, $ndl = "\r\n--" . $this->boundary . "--\r\n", $this->mpartoffset)) !== false) {
                 if ($this->mpartstate === 2 && isset($this->mpartcondisp['name'])) {
                     $this->attrs->post[$this->mpartcondisp['name']] .= binarySubstr($this->attrs->stdinbuf, $this->mpartoffset, $p - $this->mpartoffset);
                 } elseif ($this->mpartstate === 3 && isset($this->mpartcondisp['filename'])) {
                     if ($this->attrs->files[$this->mpartcondisp['name']]['fp']) {
                         fwrite($this->attrs->files[$this->mpartcondisp['name']]['fp'], binarySubstr($this->attrs->stdinbuf, $this->mpartoffset, $p - $this->mpartoffset));
                     }
                     $this->attrs->files[$this->mpartcondisp['name']]['size'] += $p - $this->mpartoffset;
                 }
                 if ($ndl === "\r\n--" . $this->boundary . "--\r\n") {
                     $this->mpartoffset = $p + strlen($ndl);
                     $this->mpartstate = 0;
                     // we done at all
                 } else {
                     $this->mpartoffset = $p;
                     $this->mpartstate = 1;
                     // let us parse the next part
                     $continue = true;
                 }
                 $this->attrs->stdinbuf = binarySubstr($this->attrs->stdinbuf, $this->mpartoffset);
                 $this->mpartoffset = 0;
             } else {
                 $p = strrpos($this->attrs->stdinbuf, "\r\n", $this->mpartoffset);
                 if ($p !== false) {
                     if ($this->mpartstate === 2 && isset($this->mpartcondisp['name'])) {
                         $this->attrs->post[$this->mpartcondisp['name']] .= binarySubstr($this->attrs->stdinbuf, $this->mpartoffset, $p - $this->mpartoffset);
                     } elseif ($this->mpartstate === 3 && isset($this->mpartcondisp['filename'])) {
                         if ($this->attrs->files[$this->mpartcondisp['name']]['fp']) {
                             fwrite($this->attrs->files[$this->mpartcondisp['name']]['fp'], binarySubstr($this->attrs->stdinbuf, $this->mpartoffset, $p - $this->mpartoffset));
                         }
                         $this->attrs->files[$this->mpartcondisp['name']]['size'] += $p - $this->mpartoffset;
                         if ($this->parseSize(ini_get('upload_max_filesize')) < $this->attrs->files[$this->mpartcondisp['name']]['size']) {
                             $this->attrs->files[$this->mpartcondisp['name']]['error'] = UPLOAD_ERR_INI_SIZE;
                         }
                         if (isset($this->attrs->post['MAX_FILE_SIZE']) && $this->attrs->post['MAX_FILE_SIZE'] < $this->attrs->files[$this->mpartcondisp['name']]['size']) {
                             $this->attrs->files[$this->mpartcondisp['name']]['error'] = UPLOAD_ERR_FORM_SIZE;
                         }
                     }
                     $this->mpartoffset = $p;
                     $this->attrs->stdinbuf = binarySubstr($this->attrs->stdinbuf, $this->mpartoffset);
                     $this->mpartoffset = 0;
                 }
             }
         }
     } while ($continue);
 }
Пример #22
0
 /**
  * Called when new data received
  * @param string New data
  * @return void
  */
 public function stdin($buf)
 {
     $this->buf .= $buf;
     start:
     $l = strlen($this->buf);
     if ($l < 16) {
         // we have not enough data yet
         return;
     }
     $h = unpack('Vlen/VreqId/VresponseTo/VopCode', binarySubstr($this->buf, 0, 16));
     $plen = (int) $h['len'];
     if ($plen > $l) {
         // we have not enough data yet
         return;
     }
     if ($h['opCode'] === MongoClient::OP_REPLY) {
         $r = unpack('Vflag/VcursorID1/VcursorID2/Voffset/Vlength', binarySubstr($this->buf, 16, 20));
         //Daemon::log(array($r,$h));
         $r['cursorId'] = binarySubstr($this->buf, 20, 8);
         $id = (int) $h['responseTo'];
         $flagBits = str_pad(strrev(decbin($r['flag'])), 8, '0', STR_PAD_LEFT);
         $cur = $r['cursorId'] !== "" ? 'c' . $r['cursorId'] : 'r' . $h['responseTo'];
         if (isset($this->pool->requests[$id][2]) && $this->pool->requests[$id][2] === false && !isset($this->pool->cursors[$cur])) {
             $this->pool->cursors[$cur] = new MongoClientCursor($cur, $this->pool->requests[$id][0], $this);
             $this->pool->cursors[$cur]->failure = $flagBits[1] == '1';
             $this->pool->cursors[$cur]->await = $flagBits[3] == '1';
             $this->pool->cursors[$cur]->callback = $this->pool->requests[$id][1];
             $this->pool->cursors[$cur]->parseOplog = isset($this->pool->requests[$id][3]) && $this->pool->requests[$id][3];
             $this->pool->cursors[$cur]->tailable = isset($this->pool->requests[$id][4]) && $this->pool->requests[$id][4];
         }
         //Daemon::log(array(Debug::exportBytes($cur),get_Class($this->pool->cursors[$cur])));
         if (isset($this->pool->cursors[$cur]) && ($r['length'] === 0 || binarySubstr($cur, 0, 1) === 'r')) {
             if ($this->pool->cursors[$cur]->tailable) {
                 if ($this->pool->cursors[$cur]->finished = $flagBits[0] == '1') {
                     $this->pool->cursors[$cur]->destroy();
                 }
             } else {
                 $this->pool->cursors[$cur]->finished = true;
             }
         }
         $p = 36;
         while ($p < $plen) {
             $dl = unpack('Vlen', binarySubstr($this->buf, $p, 4));
             $doc = bson_decode(binarySubstr($this->buf, $p, $dl['len']));
             if (isset($this->pool->cursors[$cur]) && @$this->pool->cursors[$cur]->parseOplog && isset($doc['ts'])) {
                 $tsdata = unpack('Vsec/Vinc', binarySubstr($this->buf, $p + 1 + 4 + 3, 8));
                 $doc['ts'] = $tsdata['sec'] . ' ' . $tsdata['inc'];
             }
             $this->pool->cursors[$cur]->items[] = $doc;
             $p += $dl['len'];
         }
         $this->setFree(true);
         if (isset($this->pool->requests[$id][2]) && $this->pool->requests[$id][2] && $this->pool->requests[$id][1]) {
             call_user_func($this->pool->requests[$id][1], isset($this->pool->cursors[$cur]->items[0]) ? $this->pool->cursors[$cur]->items[0] : false);
             if (isset($this->pool->cursors[$cur])) {
                 if ($this->pool->cursors[$cur] instanceof MongoClientCursor) {
                     $this->pool->cursors[$cur]->destroy();
                 } else {
                     unset($this->pool->cursors[$cur]);
                 }
             }
         } elseif (isset($this->pool->cursors[$cur])) {
             call_user_func($this->pool->cursors[$cur]->callback, $this->pool->cursors[$cur]);
         }
         unset($this->pool->requests[$id]);
     }
     $this->buf = binarySubstr($this->buf, $plen);
     goto start;
 }
Пример #23
0
 /**
  * Called when new UDP packet received.
  * @param  string $pct
  * @return void
  */
 public function onUdpPacket($pct)
 {
     $orig = $pct;
     $this->response = [];
     /*$id = */
     Binary::getWord($pct);
     $bitmap = Binary::getBitmap(Binary::getByte($pct)) . Binary::getBitmap(Binary::getByte($pct));
     //$qr = (int) $bitmap[0];
     $opcode = bindec(substr($bitmap, 1, 4));
     //$aa = (int) $bitmap[5];
     //$tc = (int) $bitmap[6];
     //$rd = (int) $bitmap[7];
     //$ra = (int) $bitmap[8];
     //$z = bindec(substr($bitmap, 9, 3));
     //$rcode = bindec(substr($bitmap, 12));
     $qdcount = Binary::getWord($pct);
     $ancount = Binary::getWord($pct);
     $nscount = Binary::getWord($pct);
     $arcount = Binary::getWord($pct);
     for ($i = 0; $i < $qdcount; ++$i) {
         $name = Binary::parseLabels($pct, $orig);
         $typeInt = Binary::getWord($pct);
         $type = isset(Pool::$type[$typeInt]) ? Pool::$type[$typeInt] : 'UNK(' . $typeInt . ')';
         $classInt = Binary::getWord($pct);
         $class = isset(Pool::$class[$classInt]) ? Pool::$class[$classInt] : 'UNK(' . $classInt . ')';
         if (!isset($this->response[$type])) {
             $this->response[$type] = [];
         }
         $record = ['name' => $name, 'type' => $type, 'class' => $class];
         $this->response['query'][] = $record;
     }
     $getResRecord = function (&$pct) use($orig) {
         $name = Binary::parseLabels($pct, $orig);
         $typeInt = Binary::getWord($pct);
         $type = isset(Pool::$type[$typeInt]) ? Pool::$type[$typeInt] : 'UNK(' . $typeInt . ')';
         $classInt = Binary::getWord($pct);
         $class = isset(Pool::$class[$classInt]) ? Pool::$class[$classInt] : 'UNK(' . $classInt . ')';
         $ttl = Binary::getDWord($pct);
         $length = Binary::getWord($pct);
         $data = binarySubstr($pct, 0, $length);
         $pct = binarySubstr($pct, $length);
         $record = ['name' => $name, 'type' => $type, 'class' => $class, 'ttl' => $ttl];
         if ($type === 'A') {
             if ($data === "") {
                 $record['ip'] = false;
                 $record['ttl'] = 5;
             } else {
                 $record['ip'] = inet_ntop($data);
             }
         } elseif ($type === 'NS') {
             $record['ns'] = Binary::parseLabels($data);
         } elseif ($type === 'CNAME') {
             $record['cname'] = Binary::parseLabels($data, $orig);
         }
         return $record;
     };
     for ($i = 0; $i < $ancount; ++$i) {
         $record = $getResRecord($pct);
         if (!isset($this->response[$record['type']])) {
             $this->response[$record['type']] = [];
         }
         $this->response[$record['type']][] = $record;
     }
     for ($i = 0; $i < $nscount; ++$i) {
         $record = $getResRecord($pct);
         if (!isset($this->response[$record['type']])) {
             $this->response[$record['type']] = [];
         }
         $this->response[$record['type']][] = $record;
     }
     for ($i = 0; $i < $arcount; ++$i) {
         $record = $getResRecord($pct);
         if (!isset($this->response[$record['type']])) {
             $this->response[$record['type']] = [];
         }
         $this->response[$record['type']][] = $record;
     }
     $this->onResponse->executeOne($this->response);
     if (!$this->keepalive) {
         $this->finish();
         return;
     } else {
         $this->checkFree();
     }
 }
Пример #24
0
 public function readConn($connId)
 {
     static $roles = array(1 => 'FCGI_RESPONDER', 2 => 'FCGI_AUTHORIZER', 3 => 'FCGI_FILTER');
     static $reqtypes = array(1 => 'FCGI_BEGIN_REQUEST', 2 => 'FCGI_ABORT_REQUEST', 3 => 'FCGI_END_REQUEST', 4 => 'FCGI_PARAMS', 5 => 'FCGI_STDIN', 6 => 'FCGI_STDOUT', 7 => 'FCGI_STDERR', 8 => 'FCGI_DATA', 9 => 'FCGI_GET_VALUES', 10 => 'FCGI_GET_VALUES_RESULT', 11 => 'FCGI_UNKNOWN_TYPE', 11 => 'FCGI_MAXTYPE');
     $state = sizeof($this->poolState[$connId]);
     if ($state === 0) {
         $header = $this->read($connId, 8);
         if ($header === FALSE) {
             return;
         }
         $r = unpack('Cver/Ctype/nreqid/nconlen/Cpadlen/Creserved', $header);
         if ($r['conlen'] > 0) {
             event_buffer_watermark_set($this->buf[$connId], EV_READ, $r['conlen'], 0xffffff);
         }
         $this->poolState[$connId][0] = $r;
         ++$state;
     } else {
         $r = $this->poolState[$connId][0];
     }
     if ($state === 1) {
         $c = $r['conlen'] === 0 ? '' : $this->read($connId, $r['conlen']);
         if ($c === FALSE) {
             return;
         }
         if ($r['padlen'] > 0) {
             event_buffer_watermark_set($this->buf[$connId], EV_READ, $r['padlen'], 0xffffff);
         }
         $this->poolState[$connId][1] = $c;
         ++$state;
     } else {
         $c = $this->poolState[$connId][1];
     }
     if ($state === 2) {
         $pad = $r['padlen'] === 0 ? '' : $this->read($connId, $r['padlen']);
         if ($pad === FALSE) {
             return;
         }
         $this->poolState[$connId][2] = $pad;
     } else {
         $pad = $this->poolState[$connId][2];
     }
     $this->poolState[$connId] = array();
     $type =& $r['type'];
     $r['ttype'] = isset($reqtypes[$type]) ? $reqtypes[$type] : $type;
     $rid = $connId . '-' . $r['reqid'];
     if (Daemon::$settings['mod' . $this->modname . 'logrecords']) {
         Daemon::log('[DEBUG] FastCGI-record #' . $r['type'] . ' (' . $r['ttype'] . '). Request ID: ' . $rid . '. Content length: ' . $r['conlen'] . ' (' . strlen($c) . ') Padding length: ' . $r['padlen'] . ' (' . strlen($pad) . ')');
     }
     if ($type == 1) {
         ++Daemon::$worker->queryCounter;
         $rr = unpack('nrole/Cflags', $c);
         $req = new stdClass();
         $req->attrs = new stdClass();
         $req->attrs->request = array();
         $req->attrs->get = array();
         $req->attrs->post = array();
         $req->attrs->cookie = array();
         $req->attrs->server = array();
         $req->attrs->files = array();
         $req->attrs->session = NULL;
         $req->attrs->connId = $connId;
         $req->attrs->trole = $roles[$rr['role']];
         $req->attrs->flags = $rr['flags'];
         $req->attrs->id = $r['reqid'];
         $req->attrs->params_done = FALSE;
         $req->attrs->stdin_done = FALSE;
         $req->attrs->stdinbuf = '';
         $req->attrs->stdinlen = 0;
         $req->attrs->chunked = FALSE;
         if (Daemon::$settings['mod' . $this->modname . 'logqueue']) {
             Daemon::log('[WORKER ' . Daemon::$worker->pid . '] new request queued.');
         }
         Daemon::$worker->queue[$rid] = $req;
         $this->poolQueue[$connId][$req->attrs->id] = $req;
     } elseif (isset(Daemon::$worker->queue[$rid])) {
         $req = Daemon::$worker->queue[$rid];
     } else {
         Daemon::log('Unexpected FastCGI-record #' . $r['type'] . ' (' . $r['ttype'] . '). Request ID: ' . $rid . '.');
         return;
     }
     if ($type === 2) {
         $req->abort();
     } elseif ($type === 4) {
         if ($c === '') {
             $req->attrs->params_done = TRUE;
             $req = Daemon::$appResolver->getRequest($req, $this);
             if ($req instanceof stdClass) {
                 $this->endRequest($req, 0, 0);
                 unset(Daemon::$worker->queue[$rid]);
             } else {
                 if (Daemon::$settings['mod' . $this->modname . 'sendfile'] && (!Daemon::$settings['mod' . $this->modname . 'sendfileonlybycommand'] || isset($req->attrs->server['USE_SENDFILE'])) && !isset($req->attrs->server['DONT_USE_SENDFILE'])) {
                     $fn = tempnam(Daemon::$settings['mod' . $this->modname . 'sendfiledir'], Daemon::$settings['mod' . $this->modname . 'sendfileprefix']);
                     $req->sendfp = fopen($fn, 'wb');
                     $req->header('X-Sendfile: ' . $fn);
                 }
                 Daemon::$worker->queue[$rid] = $req;
             }
         } else {
             $p = 0;
             while ($p < $r['conlen']) {
                 if (($namelen = ord($c[$p])) < 128) {
                     ++$p;
                 } else {
                     $u = unpack('Nlen', chr(ord($c[$p]) & 0x7f) . binarySubstr($c, $p + 1, 3));
                     $namelen = $u['len'];
                     $p += 4;
                 }
                 if (($vlen = ord($c[$p])) < 128) {
                     ++$p;
                 } else {
                     $u = unpack('Nlen', chr(ord($c[$p]) & 0x7f) . binarySubstr($c, $p + 1, 3));
                     $vlen = $u['len'];
                     $p += 4;
                 }
                 $req->attrs->server[binarySubstr($c, $p, $namelen)] = binarySubstr($c, $p + $namelen, $vlen);
                 $p += $namelen + $vlen;
             }
         }
     } elseif ($type === 5) {
         if ($c === '') {
             $req->attrs->stdin_done = TRUE;
         }
         $req->stdin($c);
     }
     if ($req->attrs->stdin_done && $req->attrs->params_done) {
         if (($order = ini_get('request_order')) || ($order = ini_get('variables_order'))) {
             for ($i = 0, $s = strlen($order); $i < $s; ++$i) {
                 $char = $order[$i];
                 if ($char == 'G') {
                     $req->attrs->request += $req->attrs->get;
                 } elseif ($char == 'P') {
                     $req->attrs->request += $req->attrs->post;
                 } elseif ($char == 'C') {
                     $req->attrs->request += $req->attrs->cookie;
                 }
             }
         } else {
             $req->attrs->request = $req->attrs->get + $req->attrs->post + $req->attrs->cookie;
         }
         $this->timeLastReq = time();
     }
 }
Пример #25
0
 /**
  * @TODO
  * @param  string $mask
  * @param  string $str
  * @return string
  */
 protected static function mask($mask, $str)
 {
     $out = '';
     $l = strlen($str);
     $ml = strlen($mask);
     while (($o = strlen($out)) < $l) {
         $out .= binarySubstr($str, $o, $ml) ^ $mask;
     }
     return $out;
 }
Пример #26
0
 /**
  * Called when new data received.
  * @param string New data.
  * @return void
  */
 public function stdin($buf)
 {
     if ($this->state === self::STATE_DATAFLOW) {
         // Data exchange
         if ($this->slave) {
             $this->slave->write($buf);
         }
         return;
     }
     $this->buf .= $buf;
     start:
     $l = strlen($this->buf);
     if ($this->state === self::STATE_ROOT) {
         // Start
         if ($l < 2) {
             // Not enough data yet
             return;
         }
         $n = ord(binarySubstr($this->buf, 1, 1));
         if ($l < $n + 2) {
             // Not enough data yet
             return;
         }
         $this->ver = binarySubstr($this->buf, 0, 1);
         $methods = binarySubstr($this->buf, 2, $n);
         $this->buf = binarySubstr($this->buf, $n + 2);
         if (!$this->pool->config->auth->value) {
             // No auth
             $m = "";
             $this->state = self::STATE_AUTHORIZED;
         } elseif (strpos($methods, "") !== FALSE) {
             // Username/Password authentication
             $m = "";
             $this->state = self::STATE_HANDSHAKED;
         } else {
             // No allowed methods
             $m = "ÿ";
             $this->state = self::STATE_ABORTED;
         }
         $this->write($this->ver . $m);
         if ($this->state === self::STATE_ABORTED) {
             $this->finish();
         } else {
             goto start;
         }
     } elseif ($this->state === self::STATE_HANDSHAKED) {
         // Handshaked
         if ($l < 3) {
             // Not enough data yet
             return;
         }
         $ver = binarySubstr($this->buf, 0, 1);
         if ($ver !== $this->ver) {
             $this->finish();
             return;
         }
         $ulen = ord(binarySubstr($this->buf, 1, 1));
         if ($l < 3 + $ulen) {
             // Not enough data yet
             return;
         }
         $username = binarySubstr($this->buf, 2, $ulen);
         $plen = ord(binarySubstr($this->buf, 1, 1));
         if ($l < 3 + $ulen + $plen) {
             // Not enough data yet
             return;
         }
         $password = binarySubstr($this->buf, 2 + $ulen, $plen);
         if ($username != $this->pool->config->username->value || $password != $this->pool->config->password->value) {
             $this->state = 1;
             $m = "";
         } else {
             $this->state = 3;
             $m = "";
         }
         $this->buf = binarySubstr($this->buf, 3 + $ulen + $plen);
         $this->write($this->ver . $m);
         if ($this->state === self::STATE_ABORTED) {
             $this->finish();
         } else {
             goto start;
         }
     } elseif ($this->state === self::STATE_AUTHORIZED) {
         // Ready for query
         if ($l < 4) {
             // Not enough data yet
             return;
         }
         $ver = binarySubstr($this->buf, 0, 1);
         if ($ver !== $this->ver) {
             $this->finish();
             return;
         }
         $cmd = binarySubstr($this->buf, 1, 1);
         $atype = binarySubstr($this->buf, 3, 1);
         $pl = 4;
         if ($atype === "") {
             $address = inet_ntop(binarySubstr($this->buf, $pl, 4));
             $pl += 4;
         } elseif ($atype === "") {
             $len = ord(binarySubstr($this->buf, $pl, 1));
             ++$pl;
             $address = binarySubstr($this->buf, $pl, $len);
             $pl += $len;
         } elseif ($atype === "") {
             $address = inet_ntop(binarySubstr($this->buf, $pl, 16));
             $pl += 16;
         } else {
             $this->finish();
             return;
         }
         $u = unpack('nport', $bin = binarySubstr($this->buf, $pl, 2));
         $port = $u['port'];
         $pl += 2;
         $this->buf = binarySubstr($this->buf, $pl);
         $connId = $this->pool->connectTo($this->destAddr = $address, $this->destPort = $port, 'SocksServerSlaveConnection');
         if (!$connId) {
             // Early connection error
             $this->write($this->ver . "");
             $this->finish();
         } else {
             $this->slave = $this->pool->getConnectionById($connId);
             $this->slave->client = $this;
             $this->slave->write($this->buf);
             $this->buf = '';
             $this->state = self::STATE_DATAFLOW;
         }
     }
 }
Пример #27
0
 /**
  * Cursor's destructor. Sends a signal to the server.
  * @return void
  */
 public function __destruct()
 {
     if (binarySubstr($this->id, 0, 1) === 'c') {
         $this->conn->pool->killCursors(array(binarySubstr($this->id, 1)));
     }
 }
Пример #28
0
 public function __destruct()
 {
     if (binarySubstr($this->id, 0, 1) === 'c') {
         $this->appInstance->killCursors(array(binarySubstr($this->id, 1)));
     }
 }
Пример #29
0
 public function stdin($buf)
 {
     $this->buf .= $buf;
     start:
     $l = strlen($this->buf);
     if ($l < 6) {
         return;
     }
     // not enough data yet.
     extract(unpack('Ctype/Chlen/Nblen', binarySubstr($this->buf, 0, 6)));
     if ($l < 6 + $hlen + $blen) {
         return;
     }
     // not enough data yet.
     $header = binarySubstr($this->buf, 6, $hlen);
     $body = binarySubstr($this->buf, 6 + $hlen, $blen);
     $this->buf = binarySubstr($this->buf, 6 + $hlen + $blen);
     list($reqId, $authKey) = explode('.', $header);
     if (isset($this->appInstance->queue[$reqId]->downstream) && $this->appInstance->queue[$reqId]->authKey == $authKey) {
         if ($type === WebSocketOverCOMET::IPCPacketType_C2S) {
             $this->appInstance->queue[$reqId]->downstream->onFrame($body, WebSocketServer::STRING);
             $this->appInstance->queue[$reqId]->atime = time();
         } elseif ($type === WebSocketOverCOMET::IPCPacketType_S2C) {
             if (isset($this->appInstance->polling[$header])) {
                 foreach ($this->appInstance->polling[$header] as $pollReqId) {
                     if (isset($this->appInstance->queue[$pollReqId])) {
                         $req = $this->appInstance->queue[$pollReqId];
                         if (isset($req->attrs->get['_script'])) {
                             $q = Request::getString($req->attrs->get['q']);
                             $body = 'var Response' . $q . ' = ' . $body . ";\n";
                         } else {
                             $body .= "\n";
                         }
                         $req->out($body);
                         $req->finish();
                     }
                 }
             }
         } elseif ($type === WebSocketOverCOMET::IPCPacketType_POLL) {
             $this->appInstance->queue[$reqId]->polling[] = $this->connId;
             $this->appInstance->queue[$reqId]->flushBufferedPackets($body);
             $this->appInstance->queue[$reqId]->atime = time();
         }
     } else {
         if (Daemon::$settings['logerrors']) {
             Daemon::log('Undispatched packet (type = ' . $type . ', reqId = ' . $reqId . ', authKey = ' . $authKey . ', exists = ' . (isset($this->appInstance->queue[$reqId]) ? '1 - ' . get_class($this->appInstance->queue[$reqId]) : '0') . ').');
         }
     }
     goto start;
 }
Пример #30
0
 /**
  * Output some data
  * @param  string  $s     String to out
  * @param  boolean $flush ob_flush?
  * @return boolean        Success
  */
 public function out($s, $flush = true)
 {
     if ($flush) {
         if (!Daemon::$obInStack) {
             // preventing recursion
             ob_flush();
         }
     }
     if ($this->aborted) {
         return false;
     }
     if (!isset($this->upstream)) {
         return false;
     }
     $l = strlen($s);
     $this->responseLength += $l;
     $this->ensureSentHeaders();
     if ($this->attrs->chunked) {
         for ($o = 0; $o < $l;) {
             $c = min($this->upstream->pool->config->chunksize->value, $l - $o);
             $chunk = dechex($c) . "\r\n" . ($c === $l ? $s : binarySubstr($s, $o, $c)) . "\r\n";
             if ($this->sendfp) {
                 $this->sendfp->write($chunk);
             } else {
                 $this->upstream->requestOut($this, $chunk);
             }
             $o += $c;
         }
         return true;
     } else {
         if ($this->sendfp) {
             $this->sendfp->write($s);
             return true;
         }
         if (Daemon::$compatMode) {
             echo $s;
             return true;
         }
         return $this->upstream->requestOut($this, $s);
     }
 }