/** * Import * @param mixed $id ID * @return mixed */ public static function import($id) { if ($id instanceof static) { return $id; } elseif ($id instanceof \MongoId) { $id = (string) $id; } elseif (!is_string($id)) { if (is_array($id) && isset($id['$id'])) { return static::import($id['$id']); } return false; } elseif (mb_orig_strlen($id) === 24) { if (!ctype_xdigit($id)) { return false; } } elseif (ctype_alnum($id)) { $id = gmp_strval(gmp_init(strrev($id), 62), 16); if (mb_orig_strlen($id) > 24) { return false; } if (mb_orig_strlen($id) < 24) { $id = str_pad($id, 24, '0', STR_PAD_LEFT); } } else { return false; } return new static($id); }
/** * @TODO DESCR * @param $p */ public function sendPacket($p) { if ($p === null) { return; } $data = \igbinary_serialize($p); $this->write(pack('N', mb_orig_strlen($data)) . $data); }
/** * Build checksum * @param string $data Source * @return string Checksum */ protected static function checksum($data) { $bit = unpack('n*', $data); $sum = array_sum($bit); if (mb_orig_strlen($data) % 2) { $temp = unpack('C*', $data[mb_orig_strlen($data) - 1]); $sum += $temp[1]; } $sum = ($sum >> 16) + ($sum & 0xffff); $sum += $sum >> 16; return pack('n*', ~$sum); }
/** * Magic __call * Example: * $gibson->set(3600, 'key', 'value'); * $gibson->get('key', function ($conn) {...}); * @param string $name Command name * @param array $args Arguments * @return void */ public function __call($name, $args) { $name = strtolower($name); $onResponse = null; if (($e = end($args)) && (is_array($e) || is_object($e)) && is_callable($e)) { $onResponse = array_pop($args); } if (!isset($this->opCodes[$name])) { throw new UndefinedMethodCalled(); } $data = implode(" ", $args); $this->requestByServer(null, pack('LS', mb_orig_strlen($data) + 2, $this->opCodes[$name]) . $data, $onResponse); }
function compareStrings($expected, $actual) { if (function_exists('mb_orig_strlen')) { $lenExpected = mb_orig_strlen($expected); $lenActual = mb_orig_strlen($actual); } else { $lenExpected = strlen($expected); $lenActual = strlen($actual); } $status = $lenExpected ^ $lenActual; $len = min($lenExpected, $lenActual); for ($i = 0; $i < $len; $i++) { $status |= ord($expected[$i]) ^ ord($actual[$i]); } return $status === 0; }
/** * Extract key and value pair from line. * @param string $line * @return array */ public static function extract($line) { $e = explode(': ', $line, 2); $header = strtolower(trim($e[0])); $value = isset($e[1]) ? trim($e[1]) : null; $safe = false; foreach (self::$safeCaseValues as $item) { if (strncasecmp($header, $item, mb_orig_strlen($item)) === 0) { $safe = true; break; } if (strncasecmp($value, $item, mb_orig_strlen($item)) === 0) { $safe = true; break; } } if (!$safe) { $value = strtolower($value); } return [$header, $value]; }
/** * A timing safe comparison method. * * C function memcmp() internally used by PHP, exits as soon as a difference * is found in the two buffers. That makes possible of leaking * timing information useful to an attacker attempting to iteratively guess * the unknown string (e.g. password). * * @param string $expected * @param string $actual * @throws \Freetrix\Main\ArgumentTypeException * @return bool */ protected function compareStrings($expected, $actual) { if (!is_string($expected)) { throw new ArgumentTypeException('expected', 'string'); } if (!is_string($actual)) { throw new ArgumentTypeException('actual', 'string'); } if (function_exists('mb_orig_strlen')) { $lenExpected = mb_orig_strlen($expected); $lenActual = mb_orig_strlen($actual); } else { $lenExpected = strlen($expected); $lenActual = strlen($actual); } $status = $lenExpected ^ $lenActual; $len = min($lenExpected, $lenActual); for ($i = 0; $i < $len; $i++) { $status |= ord($expected[$i]) ^ ord($actual[$i]); } return $status === 0; }
/** * Constructor * @return void */ public function init() { parent::init(); if (isset($this->attrs->version)) { $this->version = $this->attrs->version; } $this->header('Cache-Control: max-age=31536000, public, pre-check=0, post-check=0'); $this->header('Expires: ' . date('r', strtotime('+1 year'))); $html = '<!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script> document.domain = document.domain; _sockjs_onload = function(){SockJS.bootstrap_iframe();}; </script> <script src="https://cdn.jsdelivr.net/sockjs/' . htmlentities($this->version, ENT_QUOTES, 'UTF-8') . '/sockjs.min.js"></script> </head> <body> <h2>Don\'t panic!</h2> <p>This is a SockJS hidden iframe. It\'s used for cross domain magic.</p> </body> </html>'; $etag = 'W/"' . sha1($html) . '"'; $this->header('ETag: ' . $etag); if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) { if ($_SERVER['HTTP_IF_NONE_MATCH'] === $etag) { $this->status(304); $this->removeHeader('Content-Type'); $this->finish(); return; } } $this->header('Content-Length: ' . mb_orig_strlen($html)); echo $html; $this->finish(); }
function strlen($s) { if (function_exists('mb_orig_strlen')) { return mb_orig_strlen($s); } return strlen($s); }
/** * Draw a table * @param array Array of table's rows * @return void */ public function drawTable($rows) { $pad = []; foreach ($rows as $row) { foreach ($row as $k => $v) { if (substr($k, 0, 1) === '_') { continue; } if (!isset($pad[$k]) || strlen($v) > $pad[$k]) { $pad[$k] = mb_orig_strlen($v); } } } foreach ($rows as $row) { if (isset($row['_color'])) { $this->setStyle($row['_color']); } if (isset($row['_bold'])) { $this->setStyle('1'); } if (isset($row['_'])) { echo $row['_']; } else { $i = 0; foreach ($row as $k => $v) { if (substr($k, 0, 1) === '_') { continue; } if ($i > 0) { echo "\t"; } echo str_pad($v, $pad[$k]); ++$i; } } $this->resetStyle(); echo "\n"; } }
/** * @TODO DESCR */ public function createXMLStream() { $this->xml = new XMLStream(); $this->xml->setDefaultNS('jabber:client'); $this->xml->addXPathHandler('{http://etherx.jabber.org/streams}features', function ($xml) { /** @var XMLStream $xml */ if ($xml->hasSub('starttls') and $this->use_encryption) { $this->sendXML("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required /></starttls>"); } elseif ($xml->hasSub('bind') and $this->authorized) { $id = $this->getId(); $this->iqSet('<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><resource>' . $this->path . '</resource></bind>', function ($xml) { if ($xml->attrs['type'] === 'result') { $this->fulljid = $xml->sub('bind')->sub('jid')->data; $jidarray = explode('/', $this->fulljid); $this->jid = $jidarray[0]; } $this->iqSet('<session xmlns="urn:ietf:params:xml:ns:xmpp-session" />', function ($xml) { $this->roster = new XMPPRoster($this); if ($this->onConnected) { $this->connected = true; $this->onConnected->executeAll($this); $this->onConnected = null; } $this->event('connected'); }); }); } else { if (mb_orig_strlen($this->password)) { $this->sendXML("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" . base64_encode("" . $this->user . "" . $this->password) . "</auth>"); } else { $this->sendXML("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>"); } } }); $this->xml->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}success', function ($xml) { $this->authorized = true; $this->xml->finish(); $this->createXMLStream(); $this->startXMLStream(); }); $this->xml->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}failure', function ($xml) { if ($this->onConnected) { $this->connected = false; $func = $this->onConnected; $func($this); $this->onConnected = null; } $this->finish(); }); $this->xml->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-tls}proceed', function ($xml) { Daemon::log("XMPPClient: TLS not supported."); }); $this->xml->addXPathHandler('{jabber:client}message', function ($xml) { if (isset($xml->attrs['type'])) { $payload['type'] = $xml->attrs['type']; } else { $payload['type'] = 'chat'; } $payload['xml'] = $xml; $payload['from'] = $xml->attrs['from']; if ($xml->hasSub('body')) { $payload['body'] = $xml->sub('body')->data; $this->event('message', $payload); } }); }
/** * Read from shared memory * @param integer $offset Offset * @param integer $length Length * @return string Data */ public function read($offset, $length = 1) { $ret = ''; $segno = floor($offset / $this->segsize); $sOffset = $offset % $this->segsize; while (true) { if (!isset($this->segments[$segno])) { if (!$this->open($segno)) { goto ret; } } $ret .= shmop_read($this->segments[$segno], $sOffset, min($length - mb_orig_strlen($ret), $this->segsize)); if (mb_orig_strlen($ret) >= $length) { goto ret; } ++$segno; $sOffset = 0; } ret: return $ret === '' ? false : $ret; }
/** * Sends a chunk * @param object $req Request * @param string $chunk Data * @return bool */ public function sendChunk($req, $chunk) { $packet = "" . "" . pack('nn', $req->attrs->id, mb_orig_strlen($chunk)) . "" . ""; // reserved return $this->write($packet) && $this->write($chunk); // content }
public function _get_xml_chunk_mb_orig($fp) { if ($this->buf_position >= $this->buf_len) { if (!feof($fp)) { $this->buf = fread($fp, $this->read_size); $this->buf_position = 0; $this->buf_len = mb_orig_strlen($this->buf); } else { return false; } } //Skip line delimiters (ltrim) $xml_position = mb_orig_strpos($this->buf, "<", $this->buf_position); while ($xml_position === $this->buf_position) { $this->buf_position++; $this->file_position++; //Buffer ended with white space so we can refill it if ($this->buf_position >= $this->buf_len) { if (!feof($fp)) { $this->buf = fread($fp, $this->read_size); $this->buf_position = 0; $this->buf_len = mb_orig_strlen($this->buf); } else { return false; } } $xml_position = mb_orig_strpos($this->buf, "<", $this->buf_position); } //Let's find next line delimiter while ($xml_position === false) { $next_search = $this->buf_len; //Delimiter not in buffer so try to add more data to it if (!feof($fp)) { $this->buf .= fread($fp, $this->read_size); $this->buf_len = mb_orig_strlen($this->buf); } else { break; } //Let's find xml tag start $xml_position = mb_orig_strpos($this->buf, "<", $next_search); } if ($xml_position === false) { $xml_position = $this->buf_len + 1; } $len = $xml_position - $this->buf_position; $this->file_position += $len; $result = mb_orig_substr($this->buf, $this->buf_position, $len); $this->buf_position = $xml_position; return $result; }
/** * Apply mask * @param $data * @param string|false $mask * @return mixed */ public function mask($data, $mask) { for ($i = 0, $l = mb_orig_strlen($data), $ml = mb_orig_strlen($mask); $i < $l; $i++) { $data[$i] = $data[$i] ^ $mask[$i % $ml]; } return $data; }
/** * Returns the character at index $idx in $str in constant time * @param string $str String * @param integer $idx Index * @return string */ public static function stringIdx($str, $idx) { // FIXME: Make the const-time hack below work for all integer sizes, or // check it properly $l = mb_orig_strlen($str); if ($l > 65535 || $idx > $l) { return false; } $r = 0; for ($i = 0; $i < $l; ++$i) { $x = $i ^ $idx; $mask = ((($x | $x >> 16) & 0xffff) + 0xffff >> 16) - 1; $r |= ord($str[$i]) & $mask; } return chr($r); }
/** * onRead * @return void */ protected function onRead() { if (!$this->policyReqNotFound) { $d = $this->drainIfMatch("<policy-file-request/>"); if ($d === null) { // partially match return; } if ($d) { $FP = \PHPDaemon\Servers\FlashPolicy\Pool::getInstance($this->pool->config->fpsname->value, false); if ($FP && $FP->policyData) { $this->write($FP->policyData . ""); } $this->finish(); return; } else { $this->policyReqNotFound = true; } } start: if ($this->finished) { return; } if ($this->state === self::STATE_ROOT) { if ($this->req !== null) { // we have to wait the current request return; } if (!($this->req = $this->newRequest())) { $this->finish(); return; } $this->state = self::STATE_FIRSTLINE; } else { if (!$this->req || $this->state === self::STATE_PROCESSING) { if (isset($this->bev) && $this->bev->input->length > 0) { Daemon::log('Unexpected input (HTTP request, ' . $this->state . '): ' . json_encode($this->read($this->bev->input->length))); } return; } } if ($this->state === self::STATE_FIRSTLINE) { if (!$this->httpReadFirstline()) { return; } Timer::remove($this->keepaliveTimer); $this->state = self::STATE_HEADERS; } if ($this->state === self::STATE_HEADERS) { if (!$this->httpReadHeaders()) { return; } if (!$this->httpProcessHeaders()) { $this->finish(); return; } $this->state = self::STATE_CONTENT; } if ($this->state === self::STATE_CONTENT) { if (!isset($this->req->attrs->input) || !$this->req->attrs->input) { $this->finish(); return; } $this->req->attrs->input->readFromBuffer($this->bev->input); if (!$this->req->attrs->input->isEOF()) { return; } $this->state = self::STATE_PROCESSING; if ($this->freedBeforeProcessing) { $this->freeRequest($this->req); $this->freedBeforeProcessing = false; goto start; } $this->freezeInput(); if ($this->req->attrs->inputDone && $this->req->attrs->paramsDone) { if ($this->pool->variablesOrder === null) { $this->req->attrs->request = $this->req->attrs->get + $this->req->attrs->post + $this->req->attrs->cookie; } else { for ($i = 0, $s = mb_orig_strlen($this->pool->variablesOrder); $i < $s; ++$i) { $char = $this->pool->variablesOrder[$i]; if ($char === 'G') { if (is_array($this->req->attrs->get)) { $this->req->attrs->request += $this->req->attrs->get; } } elseif ($char === 'P') { if (is_array($this->req->attrs->post)) { $this->req->attrs->request += $this->req->attrs->post; } } elseif ($char === 'C') { if (is_array($this->req->attrs->cookie)) { $this->req->attrs->request += $this->req->attrs->cookie; } } } } Daemon::$process->timeLastActivity = time(); } } }
/** * Parses multipart * @return void */ public function parseMultipart() { start: if ($this->frozen) { return; } if ($this->state === self::STATE_SEEKBOUNDARY) { // seek to the nearest boundary if (($p = $this->search('--' . $this->boundary . "\r\n")) === false) { return; } // we have found the nearest boundary at position $p if ($p > 0) { $extra = $this->read($p); if ($extra !== "\r\n") { $this->log('parseBody(): SEEKBOUNDARY: got unexpected data before boundary (length = ' . $p . '): ' . Debug::exportBytes($extra)); } } $this->drain(mb_orig_strlen($this->boundary) + 4); // drain $this->state = self::STATE_HEADERS; } if ($this->state === self::STATE_HEADERS) { // parse the part's headers $this->curPartDisp = false; $i = 0; do { $l = $this->readline(\EventBuffer::EOL_CRLF); if ($l === null) { return; } if ($l === '') { break; } $e = explode(':', $l, 2); $e[0] = strtr(strtoupper($e[0]), Generic::$htr); if (isset($e[1])) { $e[1] = ltrim($e[1]); } if ($e[0] === 'CONTENT_DISPOSITION' && isset($e[1])) { Generic::parseStr($e[1], $this->curPartDisp, true); if (!isset($this->curPartDisp['form-data'])) { break; } if (!isset($this->curPartDisp['name'])) { break; } $this->curPartDisp['name'] = trim($this->curPartDisp['name'], '"'); $name = $this->curPartDisp['name']; if (isset($this->curPartDisp['filename'])) { $this->curPartDisp['filename'] = trim($this->curPartDisp['filename'], '"'); if (!ini_get('file_uploads')) { break; } $this->req->attrs->files[$name] = ['name' => $this->curPartDisp['filename'], 'type' => '', 'tmp_name' => null, 'fp' => null, 'error' => UPLOAD_ERR_OK, 'size' => 0]; $this->curPart =& $this->req->attrs->files[$name]; $this->req->onUploadFileStart($this); $this->state = self::STATE_UPLOAD; } else { $this->curPart =& $this->req->attrs->post[$name]; $this->curPart = ''; } } elseif ($e[0] === 'CONTENT_TYPE' && isset($e[1])) { if (isset($this->curPartDisp['name']) && isset($this->curPartDisp['filename'])) { $this->curPart['type'] = $e[1]; } } } while ($i++ < 10); if ($this->state === self::STATE_HEADERS) { $this->state = self::STATE_BODY; } goto start; } if ($this->state === self::STATE_BODY || $this->state === self::STATE_UPLOAD) { // process the body $chunkEnd1 = $this->search("\r\n--" . $this->boundary . "\r\n"); $chunkEnd2 = $this->search("\r\n--" . $this->boundary . "--\r\n"); if ($chunkEnd1 === false && $chunkEnd2 === false) { /* we have only piece of Part in buffer */ $l = $this->length - mb_orig_strlen($this->boundary) - 8; if ($l <= 0) { return; } if ($this->state === self::STATE_BODY && isset($this->curPartDisp['name'])) { $this->curPart .= $this->read($l); } elseif ($this->state === self::STATE_UPLOAD && isset($this->curPartDisp['filename'])) { $this->curPart['size'] += $l; if ($this->req->getUploadMaxSize() < $this->curPart['size']) { $this->curPart['error'] = UPLOAD_ERR_INI_SIZE; $this->req->header('413 Request Entity Too Large'); $this->req->out(''); $this->req->finish(); } elseif ($this->maxFileSize && $this->maxFileSize < $this->curPart['size']) { $this->curPart['error'] = UPLOAD_ERR_FORM_SIZE; $this->req->header('413 Request Entity Too Large'); $this->req->out(''); $this->req->finish(); } else { $this->curChunkSize = $l; $this->req->onUploadFileChunk($this); } } } else { /* we have entire Part in buffer */ if ($chunkEnd1 === false) { $l = $chunkEnd2; $endOfMsg = true; } else { $l = $chunkEnd1; $endOfMsg = false; } if ($this->state === self::STATE_BODY && isset($this->curPartDisp['name'])) { $this->curPart .= $this->read($l); if ($this->curPartDisp['name'] === 'MAX_FILE_SIZE') { $this->maxFileSize = (int) $this->curPart; } } elseif ($this->state === self::STATE_UPLOAD && isset($this->curPartDisp['filename'])) { $this->curPart['size'] += $l; $this->curChunkSize = $l; $this->req->onUploadFileChunk($this, true); } $this->state = self::STATE_SEEKBOUNDARY; if ($endOfMsg) { // end of whole message $this->sendEOF(); } else { goto start; // let's read the next part } } } }
/** * Send a command * * @param $commandName * @param $payload * @param callable $cb = null */ public function sendCommand($commandName, $payload, $cb = null) { $pct = implode(static::ARGS_DELIMITER, array_map(function ($item) { return !is_scalar($item) ? serialize($item) : $item; }, (array) $payload)); $this->onResponse->push($cb); $this->write(pack(static::HEADER_WRITE_FORMAT, static::MAGIC_REQUEST, $this->requestCommandList[$commandName], mb_orig_strlen($pct))); $this->write($pct); }
/** * Gets the host information * @param string $hostname Hostname * @param callable $cb Callback * @callback $cb ( ) * @return void */ public function get($hostname, $cb) { $this->onResponse->push($cb); $this->setFree(false); $e = explode(':', $hostname, 3); $hostname = $e[0]; $qtype = isset($e[1]) ? $e[1] : 'A'; $qclass = isset($e[2]) ? $e[2] : 'IN'; $QD = []; $qtypeInt = array_search($qtype, Pool::$type, true); $qclassInt = array_search($qclass, Pool::$class, true); if ($qtypeInt === false || $qclassInt === false) { $cb(false); return; } $q = Binary::labels($hostname) . Binary::word($qtypeInt) . Binary::word($qclassInt); $QD[] = $q; $packet = Binary::word(++$this->seq) . Binary::bitmap2bytes('0' . '0000' . '0' . '0' . '1' . '0' . '000' . '0000', 2) . Binary::word(sizeof($QD)) . Binary::word(0) . Binary::word(0) . Binary::word(0) . implode('', $QD); if ($this->type === 'udp') { $this->write($packet); } else { $this->write(Binary::word(mb_orig_strlen($packet)) . $packet); } }
public function saslScrumSHA1Step($session, $input = null) { $session['step']++; $query = []; if (!is_null($input) && (!empty($input['$err']) || !empty($input['errmsg']))) { $session['cb']($input); return; } if ($session['step'] == 1) { $session['nonce'] = base64_encode(openssl_random_pseudo_bytes(24)); $payload = 'n,,n=' . $session['user'] . ',r=' . $session['nonce']; $query = ['saslStart' => 1, 'mechanism' => 'SCRAM-SHA-1', 'payload' => base64_encode($payload)]; $session['auth_message'] .= 'n=' . $session['user'] . ',r=' . $session['nonce'] . ','; } elseif ($session['step'] == 2) { $in_payload = $this->saslScrumSHA1ExtractPayload($input['payload']); $error = null; if (count($in_payload) != 3) { $error = 'Incorrect number of arguments for first SCRAM-SHA-1 server message, got ' . count($in_payload) . 'expected 3'; } elseif (mb_orig_strlen($in_payload['r']) < 2) { $error = 'Incorrect SCRAM-SHA-1 client|server nonce: ' . $in_payload['r']; } elseif (mb_orig_strlen($in_payload['s']) < 6) { $error = 'Incorrect SCRAM-SHA-1 salt: ' . $in_payload['s']; } elseif (mb_orig_strlen($in_payload['i']) < 3) { $error = 'Incorrect SCRAM-SHA-1 iteration count: ' . $in_payload['i']; } elseif (mb_orig_strpos($in_payload['r'], $session['nonce']) !== 0) { $error = 'Server SCRAM-SHA-1 nonce does not match client nonce'; } if (!empty($error)) { $session['cb'](['ok' => 0, 'errmsg' => $error]); return; } else { $session['conversation_id'] = $input['conversationId']; $session['nonce'] = $in_payload['r']; } $payload = 'c=biws,r=' . $session['nonce']; $session['auth_message'] .= base64_decode($input['payload']) . ',' . $payload; $decoded_salt = base64_decode($in_payload['s']); $password = md5($session['user'] . ':mongo:' . $session['password']); $salted_password = hash_pbkdf2('sha1', $password, $decoded_salt, (int) $in_payload['i'], 0, true); $client_key = hash_hmac('sha1', 'Client Key', $salted_password, true); $stored_key = sha1($client_key, true); $client_sign = hash_hmac('sha1', $session['auth_message'], $stored_key, true); $client_proof = $client_key ^ $client_sign; $payload .= ',p=' . base64_encode($client_proof); $query = ['saslContinue' => 1, 'conversationId' => $session['conversation_id'], 'payload' => base64_encode($payload)]; } elseif ($session['step'] == 3) { $in_payload = $this->saslScrumSHA1ExtractPayload($input['payload']); if (!empty($in_payload['v'])) { $session['server_signature'] = $in_payload['v']; $query = ['saslContinue' => 1, 'conversationId' => $session['conversation_id'], 'payload' => base64_encode('')]; } } elseif ($session['step'] == 4) { $in_payload = $this->saslScrumSHA1ExtractPayload($input['payload']); $res = $input['done'] ? ['ok' => 1, 'server_signature' => $session['server_signature']] : ['ok' => 0, 'errmsg' => 'Authentication failed.']; $session['cb']($res); return; } $this->saslScrumSHA1Conversation($session['dbname'], $query, function ($res) use($session) { $this->saslScrumSHA1Step($session, $res); }, $session['conn']); }
/** * Get state of workers. * @return array - information. */ public static function getStateOfWorkers() { $offset = 0; $stat = ['idle' => 0, 'busy' => 0, 'alive' => 0, 'shutdown' => 0, 'preinit' => 0, 'init' => 0, 'reloading' => 0]; $readed = 0; while (($buf = Daemon::$shm_wstate->read($readed, 1024)) !== false) { $buflen = mb_orig_strlen($buf); $readed += $buflen; for ($i = 0; $i < $buflen; ++$i) { $code = ord($buf[$i]); if ($code >= 100) { // reloaded (shutdown) $code -= 100; if ($code !== Daemon::WSTATE_SHUTDOWN) { ++$stat['alive']; if (Daemon::$process instanceof Thread\Master) { Daemon::$process->reloadWorker($offset + $i + 1); ++$stat['reloading']; continue; } } } if ($code === Daemon::WSTATE_IDLE) { // idle ++$stat['alive']; ++$stat['idle']; } elseif ($code === Daemon::WSTATE_BUSY) { // busy ++$stat['alive']; ++$stat['busy']; } elseif ($code === Daemon::WSTATE_SHUTDOWN) { // shutdown ++$stat['shutdown']; } elseif ($code === Daemon::WSTATE_PREINIT) { // pre-init ++$stat['alive']; ++$stat['preinit']; ++$stat['idle']; } elseif ($code === Daemon::WSTATE_INIT) { // init ++$stat['alive']; ++$stat['init']; ++$stat['idle']; } } } return $stat; }
protected function _writeResult(&$result, $bForceWrite = false) { $this->_buffer .= $result; if (static::$_bMBStringOrig) { $this->_bufferLoaded += mb_orig_strlen($result); } else { $this->_bufferLoaded += strlen($result); } if (true === $bForceWrite || $this->_bufferLoaded >= $this->_bufferSize || $this->_bComplete) { if (!$this->_dwnFileHandler) { $this->_dwnFileHandler = fopen(OBX_DOC_ROOT . $this->_dwnFolder . '/' . $this->_dwnFileBaseName . '.' . $this->_dwnFileExt, $this->_dwnFileOpenMode); if (!$this->_dwnFileHandler) { $this->throwErrorException(new DownloadError('', DownloadError::E_CANT_OPEN_DWN_FILE)); } } $bytesWritten = fwrite($this->_dwnFileHandler, $this->_buffer); if (false === $bytesWritten || $this->_bufferLoaded !== $bytesWritten) { $this->throwErrorException(new DownloadError('', DownloadError::E_CANT_WRT_2_DWN_FILE)); } $this->_fileLoaded += $this->_bufferLoaded; $this->_buffer = null; $this->_bufferLoaded = 0; } }
/** * Generates closure-callback for readAllChunked * @param callable $cb * @param callable $chunkcb * @param integer $size * @param integer $offset * @param integer $pri * @return callable */ protected function readAllChunkedGenHandler($cb, $chunkcb, $size, &$offset, $pri) { return function ($file, $data) use($cb, $chunkcb, $size, &$offset, $pri) { $chunkcb($file, $data); $offset += mb_orig_strlen($data); $len = min($file->chunkSize, $size - $offset); if ($offset >= $size) { $cb($file, true); return; } eio_read($file->fd, $len, $offset, $pri, $this->readAllChunkedGenHandler($cb, $chunkcb, $size, $offset, $pri), $file); }; }
/** * 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 = mb_orig_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 : mb_orig_substr($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); } }
/** * Creates Request. * @param object $req Request. * @param object $upstream Upstream application instance. * @return object Request. */ public function beginRequest($req, $upstream) { $e = array_map('rawurldecode', explode('/', $req->attrs->server['DOCUMENT_URI'])); $serverId = null; $sessId = null; /* Route discovery */ $path = null; $extra = []; do { foreach ($this->wss as $wss) { $try = implode('/', $e); if ($try === '') { $try = '/'; } if ($wss->routeExists($try)) { $path = $try; break 2; } } array_unshift($extra, array_pop($e)); } while (sizeof($e) > 0); if ($path === null) { return $this->callMethod('NotFound', $req, $upstream); } if (sizeof($extra) > 0 && end($extra) === '') { array_pop($extra); } $method = sizeof($extra) ? array_pop($extra) : null; if ($method === null) { $method = 'Welcome'; } elseif ($method === 'info') { } elseif (preg_match('~^iframe(?:-([^/]*))?\\.html$~', $method, $m)) { $method = 'Iframe'; $version = isset($m[1]) ? $m[1] : null; } else { if (sizeof($extra) < 2) { return $this->callMethod('NotFound', $req, $upstream); } $sessId = array_pop($extra); $serverId = array_pop($extra); if ($sessId === '' || $serverId === '' || mb_orig_strpos($sessId, '.') !== false || mb_orig_strpos($serverId, '.') !== false) { return $this->callMethod('NotFound', $req, $upstream); } } $req->attrs->sessId = $sessId; $req->attrs->serverId = $serverId; $req->attrs->path = $path; $req = $this->callMethod($method, $req, $upstream); if ($req instanceof Methods\Iframe && mb_orig_strlen($version)) { $req->attrs->version = $version; } return $req; }
public static function strlen($s) { if (function_exists('mb_orig_strlen')) return mb_orig_strlen($s); return strlen($s); }
/** * Called when new data received * @return void */ public function onRead() { Timer::setTimeout($this->keepaliveTimer); while (($line = $this->readline()) !== null) { if ($line === '') { continue; } if (mb_orig_strlen($line) > 512) { Daemon::$process->log('IRCBouncerConnection error: buffer overflow.'); $this->finish(); return; } $line = mb_orig_substr($line, 0, -mb_orig_strlen($this->EOL)); $p = mb_orig_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[] = mb_orig_substr($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 (mb_orig_strlen($this->buf) > 512) { Daemon::$process->log('IRCClientConnection error: buffer overflow.'); $this->finish(); } }
/** * Wrapper for mbstring-overloaded strlen(). * * @param string $body * @return int */ private function _strlen($body) { return function_exists('mb_orig_strlen') ? mb_orig_strlen($body) : strlen($body); }
/** * Constructor * @return void */ protected function __construct($file, $target, $included = false) { $this->file = $file; $this->target = $target; $this->revision = ++Object::$lastRevision; $this->data = file_get_contents($file); if (substr($this->data, 0, 2) === '#!') { if (!is_executable($file)) { $this->raiseError('Shebang (#!) detected in the first line, but file hasn\'t +x mode.'); return; } $this->data = shell_exec($file); } $this->data = str_replace("\r", '', $this->data); $this->length = mb_orig_strlen($this->data); $this->state[] = [static::T_ALL, $this->target]; $this->tokens = [static::T_COMMENT => function ($c) { if ($c === "\n") { array_pop($this->state); } }, static::T_STRING_DOUBLE => function ($q) { $str = ''; ++$this->p; for (; $this->p < $this->length; ++$this->p) { $c = $this->getCurrentChar(); if ($c === $q) { ++$this->p; break; } elseif ($c === '\\') { next: $n = $this->getNextChar(); if ($n === $q) { $str .= $q; ++$this->p; } elseif (ctype_digit($n)) { $def = $n; ++$this->p; for (; $this->p < min($this->length, $this->p + 2); ++$this->p) { $n = $this->getNextChar(); if (!ctype_digit($n)) { break; } $def .= $n; } $str .= chr((int) $def); } elseif ($n === 'x' || $n === 'X') { $def = $n; ++$this->p; for (; $this->p < min($this->length, $this->p + 2); ++$this->p) { $n = $this->getNextChar(); if (!ctype_xdigit($n)) { break; } $def .= $n; } $str .= chr((int) hexdec($def)); } else { $str .= $c; } } else { $str .= $c; } } if ($this->p >= $this->length) { $this->raiseError('Unexpected End-Of-File.'); } return $str; }, static::T_STRING => function ($q) { $str = ''; ++$this->p; for (; $this->p < $this->length; ++$this->p) { $c = $this->getCurrentChar(); if ($c === $q) { ++$this->p; break; } elseif ($c === '\\') { if ($this->getNextChar() === $q) { $str .= $q; ++$this->p; } else { $str .= $c; } } else { $str .= $c; } } if ($this->p >= $this->length) { $this->raiseError('Unexpected End-Of-File.'); } return $str; }, static::T_ALL => function ($c) { if (ctype_space($c)) { } elseif ($c === '#') { $this->state[] = [static::T_COMMENT]; } elseif ($c === '}') { if (sizeof($this->state) > 1) { $this->purgeScope($this->getCurrentScope()); array_pop($this->state); } else { $this->raiseError('Unexpected \'}\''); } } elseif (ctype_alnum($c) || $c === '\\') { $elements = ['']; $elTypes = [null]; $i = 0; $tokenType = 0; $newLineDetected = null; for (; $this->p < $this->length; ++$this->p) { $prePoint = [$this->line, $this->col - 1]; $c = $this->getCurrentChar(); if (ctype_space($c) || $c === '=' || $c === ',') { if ($c === "\n") { $newLineDetected = $prePoint; } if ($elTypes[$i] !== null) { ++$i; $elTypes[$i] = null; } } elseif ($c === '\'') { if ($elTypes[$i] !== null) { $this->raiseError('Unexpected T_STRING.'); } $string = $this->token(static::T_STRING, $c); --$this->p; if ($elTypes[$i] === null) { $elements[$i] = $string; $elTypes[$i] = static::T_STRING; } } elseif ($c === '"') { if ($elTypes[$i] !== null) { $this->raiseError('Unexpected T_STRING_DOUBLE.'); } $string = $this->token(static::T_STRING_DOUBLE, $c); --$this->p; if ($elTypes[$i] === null) { $elements[$i] = $string; $elTypes[$i] = static::T_STRING_DOUBLE; } } elseif ($c === '}') { $this->raiseError('Unexpected \'}\' instead of \';\' or \'{\''); } elseif ($c === ';') { if ($newLineDetected) { $this->raiseError('Unexpected new-line instead of \';\'', 'notice', $newLineDetected[0], $newLineDetected[1]); } $tokenType = static::T_VAR; break; } elseif ($c === '{') { $tokenType = static::T_BLOCK; break; } else { if ($elTypes[$i] === static::T_STRING) { $this->raiseError('Unexpected T_CVALUE.'); } else { if (!isset($elements[$i])) { $elements[$i] = ''; } $elements[$i] .= $c; $elTypes[$i] = static::T_CVALUE; } } } foreach ($elTypes as $k => $v) { if (static::T_CVALUE === $v) { if (ctype_digit($elements[$k])) { $elements[$k] = (int) $elements[$k]; } elseif (is_numeric($elements[$k])) { $elements[$k] = (double) $elements[$k]; } else { $l = strtolower($elements[$k]); if ($l === 'true' || $l === 'on') { $elements[$k] = true; } elseif ($l === 'false' || $l === 'off') { $elements[$k] = false; } elseif ($l === 'null') { $elements[$k] = null; } } } } if ($tokenType === 0) { $this->raiseError('Expected \';\' or \'{\''); } elseif ($tokenType === static::T_VAR) { $name = str_replace('-', '', strtolower($elements[0])); if (sizeof($elements) > 2) { $value = array_slice($elements, 1); } else { $value = isset($elements[1]) ? $elements[1] : null; } $scope = $this->getCurrentScope(); if ($name === 'include') { if (!is_array($value)) { $value = [$value]; } foreach ($value as $path) { if (substr($path, 0, 1) !== '/') { $path = 'conf/' . $path; } $files = glob($path); if ($files) { foreach ($files as $fn) { try { static::parse($fn, $scope, true); } catch (InfiniteRecursion $e) { $this->raiseError('Cannot include \'' . $fn . '\' as a part of itself, it may cause an infinite recursion.'); } } } } } else { if (sizeof($elements) === 1) { $value = true; $elements[1] = true; $elTypes[1] = static::T_CVALUE; } elseif ($value === null) { $value = null; $elements[1] = null; $elTypes[1] = static::T_CVALUE; } if (isset($scope->{$name})) { if ($scope->{$name}->source !== 'cmdline') { if ($elTypes[1] === static::T_CVALUE && is_string($value)) { $scope->{$name}->pushHumanValue($value); } else { $scope->{$name}->pushValue($value); } $scope->{$name}->source = 'config'; $scope->{$name}->revision = $this->revision; } } elseif ($scope instanceof Section) { $scope->{$name} = new Generic(); $scope->{$name}->source = 'config'; $scope->{$name}->revision = $this->revision; $scope->{$name}->pushValue($value); $scope->{$name}->setValueType($value); } else { $this->raiseError('Unrecognized parameter \'' . $name . '\''); } } } elseif ($tokenType === static::T_BLOCK) { $scope = $this->getCurrentScope(); $sectionName = implode('-', $elements); $sectionName = strtr($sectionName, '-. ', ':::'); if (!isset($scope->{$sectionName})) { $scope->{$sectionName} = new Section(); } $scope->{$sectionName}->source = 'config'; $scope->{$sectionName}->revision = $this->revision; $this->state[] = [static::T_ALL, $scope->{$sectionName}]; } } else { $this->raiseError('Unexpected char \'' . Debug::exportBytes($c) . '\''); } }]; for (; $this->p < $this->length; ++$this->p) { $c = $this->getCurrentChar(); $e = end($this->state); $this->token($e[0], $c); } if (!$included) { $this->purgeScope($this->target); } if (Daemon::$config->verbosetty->value) { Daemon::log('Loaded config file: ' . escapeshellarg($file)); } }