public function run() { $captcha = new \WakePHP\Utils\CaptchaDraw(); $captcha->setText($this->args[1]); $captcha->show($file = tempnam(sys_get_temp_dir(), 'php')); $this->parent->captcha->uploadImage($this->args[0], file_get_contents($file), function ($lastError) { Daemon::log(Debug::dump($lastError)); $this->sendResult(true); }); }
public function perform() { $str = Request::getString($_REQUEST['str']); $size = Request::getInteger($_REQUEST['size']); $rounds = Request::getInteger($_REQUEST['rounds']); if (!$rounds) { $rounds = 24; } $salt = '$512=24'; $hash = Crypt::hash($str, $salt); $hex = trim(str_replace('\\x', ' ', Debug::exportBytes(base64_decode($hash), true))); $this->req->setResult(['stringWithSalt' => $str . $salt, 'base64' => $hash, 'salt' => $salt, 'hex' => $hex, 'rounds' => 24]); }
/** * Returns string of pseudo random characters * @param integer $len Length of desired string * @param string $chars String of allowed characters * @param callable $cb Callback * @param integer $pri Priority of EIO operation * @param boolean $hang If true, we shall use /dev/random instead of /dev/urandom and it may cause a delay * @return string */ public static function randomString($len = null, $chars = null, $cb = null, $pri = 0, $hang = false) { if ($len === null) { $len = 64; } if ($chars === null) { $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.'; } if ($cb === null) { Daemon::log('[CODE WARN] \\PHPDaemon\\Utils\\Crypt::randomString: non-callback way is not secure.' . ' Please rewrite your code with callback function in third argument' . PHP_EOL . Debug::backtrace()); $r = ''; $m = strlen($chars) - 1; for ($i = 0; $i < $len; ++$i) { $r .= $chars[mt_rand(0, $m)]; } return $r; } $charsLen = strlen($chars); $mask = static::getMinimalBitMask($charsLen - 1); $iterLimit = max($len, $len * 64); static::randomInts(2 * $len, function ($ints) use($cb, $chars, $charsLen, $len, $mask, &$iterLimit) { if ($ints === false) { call_user_func($cb, false); return; } $r = ''; for ($i = 0, $s = sizeof($ints); $i < $s; ++$i) { // This is wasteful, but RNGs are fast and doing otherwise adds complexity and bias $c = $ints[$i] & $mask; // Only use the random number if it is in range, otherwise try another (next iteration) if ($c < $charsLen) { $r .= static::stringIdx($chars, $c); } // Guarantee termination if (--$iterLimit <= 0) { return false; } } $d = $len - strlen($r); if ($d > 0) { static::randomString($d, $chars, function ($r2) use($r, $cb) { call_user_func($cb, $r . $r2); }); return; } call_user_func($cb, $r); }, $pri, $hang); }
public function redirect() { if (!$this->checkReferer($this->appInstance->config->domain->value)) { $this->req->setResult(['error' => 'Wrong referer']); return; } $code = Request::getString($_GET['code']); if ($code === '') { Daemon::log('Authentication failed'); $this->req->status(401); $this->req->setResult(['error' => 'Authenticaion failed']); return; } $this->appInstance->httpclient->get($get = ['https://api.vk.com/oauth/access_token', 'client_id' => $this->cmp->config->vk_app_key->value, 'redirect_uri' => HTTPClient::buildUrl([$this->req->getBaseUrl() . '/component/Account/ExternalAuthRedirect/json', 'agent' => 'VK', 'backurl' => $this->getBackurl(true)]), 'client_secret' => $this->cmp->config->vk_app_secret->value, 'code' => $code], function ($conn, $success) use(&$get) { if (!$success) { $this->req->status(400); $this->req->setResult(['error' => 'request declined']); return; } Daemon::log(Debug::dump($get)); Daemon::log(Debug::dump($conn->body)); $response = json_decode(rtrim($conn->body), true); $user_id = isset($response['user_id']) ? (int) $response['user_id'] : 0; $access_token = Request::getString($response['access_token']); if ($user_id === 0 || $access_token === '') { $this->req->status(403); $this->req->setResult(['error' => 'no access token or user id']); return; } $this->appInstance->httpclient->get(['https://api.vk.com/method/users.get', 'uids' => $user_id, 'fields' => 'screen_name', 'access_token' => $access_token], function ($conn, $success) use($user_id) { $response = json_decode($conn->body, true); if (!$success || !is_array($response) || empty($user_id)) { $this->req->redirectTo($this->req->getBaseUrl(), false); $this->req->setResult(['error' => 'Unrecognized response']); return; } $data = []; if (isset($response['screen_name'])) { $data['username'] = Request::getString($response['screen_name']); } $this->req->components->account->acceptUserAuthentication('VK', $user_id, $data, [$this, 'finalRedirect']); }); }); }
public static function checkJob($req, $invalidate = true) { $token = Request::getString($req->attrs->request['captcha_token']); $text = Request::getString($req->attrs->request['captcha_text']); return function ($jobname, $job) use($token, $text, $req, $invalidate) { Daemon::log(Debug::dump([$token, $text, $invalidate])); if ($token === '') { $job->setResult($jobname, ['captcha' => 'need']); return; } $req->appInstance->captcha->check($token, $text, $invalidate, function ($result) use($jobname, $job) { $errors = []; if ($result !== 'ok') { $errors['captcha'] = $result; } $job->setResult($jobname, $errors); }); }; }
public function updateAllServers() { gc_collect_cycles(); $app = $this; $amount = 1000 - sizeof($this->jobMap); \PHPDaemon\Core\Daemon::log('amount: ' . $amount); if ($amount <= 0) { return; } $this->servers->find(function ($cursor) use($app, $amount) { if (isset($cursor->items[0]['$err'])) { \PHPDaemon\Core\Daemon::log(\PHPDaemon\Core\Debug::dump($cursor->items)); return; } foreach ($cursor->items as $server) { $app->updateServer($server); } $cursor->destroy(); }, ['where' => ['$or' => [['atime' => ['$lte' => time() - 30], 'latency' => ['$ne' => false]], ['atime' => ['$lte' => time() - 120], 'latency' => false], ['atime' => null]]], 'limit' => -max($amount, 100), 'sort' => ['atime' => 1]]); }
public function setResult($result = null, $multi = false) { if ($this->dataType === 'json') { try { $this->header('Content-Type: text/json'); } catch (RequestHeadersAlreadySent $e) { } $this->out(json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . ($multi ? "\n" : '')); } elseif ($this->dataType === 'jsonp') { try { $this->header('Content-Type: text/plain'); } catch (RequestHeadersAlreadySent $e) { } $this->out(json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . ($multi ? "\n" : '')); } elseif ($this->dataType === 'xml') { $converter = new Array2XML(); $converter->setRootName($this->xmlRootName); try { $this->header('Content-Type: text/xml'); } catch (RequestHeadersAlreadySent $e) { } $this->out($converter->convert($result)); } elseif ($this->dataType === 'bson') { try { $this->header('Content-Type: application/octet-stream'); } catch (RequestHeadersAlreadySent $e) { } $this->out(bson_encode($result)); } elseif ($this->dataType === 'dump') { try { $this->header('Content-Type: text/plain'); } catch (RequestHeadersAlreadySent $e) { } $this->out(Debug::dump($result)); } else { $this->header('Content-Type: application/x-javascript'); $this->out(json_encode(['errmsg' => 'Unsupported data-type.'])); } if (!$multi) { $this->finish(); } }
public function run() { Daemon::log(Debug::dump($this->args)); $this->sendResult(call_user_func_array('mail', $this->args)); }
/** * Called when socket is bound * @return boolean Success */ protected function onBound() { if (!$this->ev) { Daemon::log(get_class($this) . '::' . __METHOD__ . ': Couldn\'t set event on bound socket: ' . Debug::dump($this->fd)); return false; } return true; }
/** * Shutdown this worker * @param boolean Hard? If hard, we shouldn't wait for graceful shutdown of the running applications. * @return boolean|null Ready? */ protected function shutdown($hard = false) { $error = error_get_last(); if ($error) { if ($error['type'] === E_ERROR) { Daemon::log('W#' . $this->pid . ' crashed by error \'' . $error['message'] . '\' at ' . $error['file'] . ':' . $error['line']); } } if (Daemon::$config->logevents->value) { $this->log('event shutdown(' . ($hard ? 'HARD' : '') . ') invoked.'); } if (Daemon::$config->throwexceptiononshutdown->value) { throw new \Exception('event shutdown'); } @ob_flush(); if ($this->terminated === true) { if ($hard) { exit(0); } return; } $this->terminated = true; if ($hard) { $this->setState(Daemon::WSTATE_SHUTDOWN); exit(0); } $this->reloadReady = $this->appInstancesReloadReady(); if ($this->reload && $this->graceful) { $this->reloadReady = $this->reloadReady && microtime(TRUE) > $this->reloadTime; } if (Daemon::$config->logevents->value) { $this->log('reloadReady = ' . Debug::dump($this->reloadReady)); } Timer::remove('breakMainLoopCheck'); Timer::add(function ($event) { $self = Daemon::$process; $self->reloadReady = $self->appInstancesReloadReady(); if ($self->reload === TRUE) { $self->reloadReady = $self->reloadReady && microtime(TRUE) > $self->reloadTime; } if (!$self->reloadReady) { $event->timeout(); } else { $self->eventBase->exit(); } }, 1000000.0, 'checkReloadReady'); while (!$this->reloadReady) { $this->eventBase->loop(); } FileSystem::waitAllEvents(); // ensure that all I/O events completed before suicide exit(0); // R.I.P. }
/** * Parse length-value structure * @param string &$p Data * @param integer $l Number of length bytes * @param boolean $nul Nul-terminated? Default is false * @param boolean $lrev Length is little endian? * @return string */ public static function getLV(&$p, $l = 1, $nul = false, $lrev = false) { $s = static::b2i(binarySubstr($p, 0, $l), !!$lrev); $p = binarySubstr($p, $l); if ($s === 0) { return ''; } $r = ''; if (strlen($p) < $s) { echo "getLV error: buf length (" . strlen($p) . "): " . Debug::exportBytes($p) . ", must be >= string length (" . $s . ")\n"; } elseif ($nul) { if ($p[$s - 1] !== "") { echo "getLV error: Wrong end of NUL-string (" . Debug::exportBytes($p[$s - 1]) . "), len " . $s . "\n"; } else { $d = $s - 1; if ($d < 0) { $d = 0; } $r = binarySubstr($p, 0, $d); $p = binarySubstr($p, $s); } } else { $r = binarySubstr($p, 0, $s); $p = binarySubstr($p, $s); } return $r; }
function D(...$args) { \PHPDaemon\Core\Daemon::log(\PHPDaemon\Core\Debug::dump(...$args)); //\PHPDaemon\Core\Daemon::log(\PHPDaemon\Core\Debug::backtrace()); }
/** * 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(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::parse_str($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 - 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 } } } }
public function perform() { $this->cmp->onAuth(function ($result) { if (!in_array('Superusers', $this->req->account['aclgroups'], true)) { $this->req->setResult(['success' => false, 'goLoginPage' => true]); return; } static $fields = ['email' => 1, 'username' => 1, 'regdate' => 1, 'ip' => 1, 'firstname' => 1, 'lastname' => 1, 'location' => 1, 'aclgroups' => 1, '_id' => 1]; $fieldNames = array_keys($fields); $field = function ($n) use($fieldNames) { if (!isset($fieldNames[$n])) { return null; } return $fieldNames[$n]; }; $action = Request::getString($_REQUEST['action']); if ($action === 'EditColumn') { $column = $field(Request::getInteger($_REQUEST['column'])); if ($column === null) { $this->req->setResult(['success' => false, 'error' => 'Column not found.']); return; } /** @noinspection PhpIllegalArrayKeyTypeInspection */ $this->req->appInstance->accounts->getAccount()->condSetId(Request::getString($_REQUEST['id']))->attr($column, $value = Request::getString($_REQUEST['value']))->save(function ($o) use($value) { Daemon::log(Debug::dump($o->lastError())); if ($o->lastError(true)) { $this->req->setResult(['success' => true, 'value' => $value]); } else { $this->req->setResult(['success' => false, 'error' => 'Account not found.']); } }); return; } $where = []; $sort = []; $sortDir = []; foreach ($_REQUEST as $k => $value) { list($type, $index) = explode('_', $k . '_'); if ($type === 'iSortCol') { /** @noinspection PhpIllegalArrayKeyTypeInspection */ $sort[$field($value)] = Request::getString($_REQUEST['sSortDir_' . $index]) == 'asc' ? 1 : -1; } } unset($sort[null]); $offset = Request::getInteger($_REQUEST['iDisplayStart']); $limit = Request::getInteger($_REQUEST['iDisplayLength']); $job = $this->req->job = new ComplexJob(function ($job) { $this->req->setResult(['success' => true, 'sEcho' => (int) Request::getString($_REQUEST['sEcho']), 'iTotalRecords' => $job->results['countTotal'], 'iTotalDisplayRecords' => $job->results['countFiltered'], 'aaData' => $job->results['find']]); }); $job('countTotal', function ($jobname, $job) { $this->req->appInstance->accounts->countAccount(function ($o, $n) use($job, $jobname) { /** @var ComplexJob $job */ $job->setResult($jobname, $n); }); }); $job('countFiltered', function ($jobname, $job) use($where, $limit) { /** @var ComplexJob $job */ /** @var WakePHPRequest $job->req */ $this->req->appInstance->accounts->countAccount(function ($o, $n) use($job, $jobname, $where) { /** @var ComplexJob $job */ $job->setResult($jobname, $n); }, $where); }); $job('find', function ($jobname, $job) use($where, $sort, $fields, $fieldNames, $field, $offset, $limit) { $this->req->appInstance->accounts->findAccounts(function ($cursor) use($jobname, $job, $fieldNames, $offset, $limit) { /** @var Cursor $cursor */ /** @var ComplexJob $job */ $accounts = []; foreach ($cursor as $item) { $account = []; foreach ($fieldNames as $k) { if (!isset($item[$k])) { $val = null; } else { $val = $item[$k]; if ($k === 'regdate') { $val = $val != 0 ? date('r', $val) : ''; } elseif ($k === '_id') { $val = (string) $val; } else { if ($k === 'aclgroups') { $val = (string) implode(', ', $val); } $val = htmlspecialchars($val); } } $account[] = $val; } $accounts[] = $account; } $cursor->destroy(); $job->setResult($jobname, $accounts); }, ['fields' => $fields, 'sort' => $sort, 'offset' => $offset, 'limit' => -abs($limit)]); }); $job(); }); }
/** * @param $names * @param callable $cb */ public function check($token, $text, $invalidate = true, $cb) { $e = static::decodeToken($token); if ($e === false) { call_user_func($cb, 'badToken'); return; } list($id, $rnd) = $e; $this->captcha->findOne(function ($t) use($cb, $id, $text, $invalidate) { if (!$t) { call_user_func($cb, 'expired'); return; } Daemon::log(Debug::dump([$invalidate])); if (!$invalidate) { if (strtolower($t['text']) === strtolower($text)) { call_user_func($cb, 'ok'); return; } } $this->captcha->remove(['_id' => new \MongoId($id)], function ($lastError) use($t, $text, $cb) { if ($lastError['n'] !== 1) { call_user_func($cb, 'expired'); return; } if (strtolower($t['text']) !== strtolower($text)) { call_user_func($cb, 'incorrect'); return; } call_user_func($cb, 'ok'); }); }, ['where' => ['_id' => $id, 'rnd' => $rnd, 'ctime' => ['$gt' => time() - 3600]]]); }
/** * 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 = 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 right quote, no thing in quotes, just empty string if ($c === $q) { ++$this->p; break; } elseif ($c === '\\') { next: $n = $this->getNextChar(); if ($n === $q) { //if letter $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 === '\\') { //special for \ 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) { // just like it name purge scope $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; } //todo ??? 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); //todo ???? --$this->p; //why not use key-value map 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]); } /* State: variable definition block */ $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; /* Value defined by constant (keyword) or number*/ $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)); } }
/** * Initializes slave session. * @param object Object. * @param \MongoTimestamp $point * @return void */ public function initSlave($point) { $this->db->{'local.oplog.$main'}->find(function ($cursor) { $this->cursor = $cursor; $cursor->state = 1; $cursor->lastOpId = NULL; foreach ($cursor->items as $k => &$item) { if (\PHPDaemon\Core\Daemon::$config->logevents->value) { \PHPDaemon\Core\Daemon::log(get_class($this) . ': caught oplog-record with ts = (' . \PHPDaemon\Core\Debug::dump($item['ts']) . ')'); } $cursor->lastOpId = $item['ts']; if ($item['op'] === 'i') { $this->cacheObject($item['o']); } elseif ($item['op'] === 'd') { $this->deleteObject($item['o']); } elseif ($item['op'] === 'u') { if (isset($item['b']) && $item['b'] === FALSE) { $item['o']['_id'] = $item['o2']['_id']; $this->cacheObject($item['o']); } else { $cursor->appInstance->{$item['ns']}->findOne(function ($item) { $this->cacheObject($item); }, ['where' => ['_id' => $item['o2']['_id']]]); } } unset($cursor->items[$k]); } }, ['tailable' => TRUE, 'sort' => ['$natural' => 1], 'snapshot' => 1, 'where' => ['ts' => ['$gt' => $point], '$exists' => ['_key' => TRUE]], 'parse_oplog' => TRUE]); }
/** * @param string $prop * @return void */ public function __unset($prop) { Daemon::log('[CODE WARN] Unsetting property ' . json_encode($prop) . ' in object of class ' . get_class($this) . PHP_EOL . Debug::backtrace()); unset($this->{$prop}); }
public function debug($point = null) { $msg = "\n--------------------------\n"; $msg .= "TYPE: " . get_class($this) . "\n"; $msg .= "NEW: " . ($this->new ? 'YES' : 'NO') . "\n"; $msg .= "POINT: " . Debug::dump($point) . "\n"; $msg .= "COND: " . Debug::dump($this->cond) . "\n"; $msg .= "OBJ: " . Debug::dump($this->obj) . "\n"; $msg .= "UPDATE: " . Debug::dump($this->update) . "\n"; $msg .= "lastError: " . Debug::dump($this->lastError) . "\n"; $msg .= "--------------------------"; Daemon::log($msg); return $this; }
/** * Parse length-value structure * @param string &$p Data * @param integer $l Number of length bytes * @param boolean $nul Nul-terminated? Default is false * @param boolean $lrev Length is little endian? * @return string */ public static function getLV(&$p, $l = 1, $nul = false, $lrev = false) { $s = static::b2i(mb_orig_substr($p, 0, $l), !!$lrev); $p = mb_orig_substr($p, $l); if ($s === 0) { return ''; } $r = ''; if (mb_orig_strlen($p) < $s) { Daemon::log('getLV error: buf length (' . mb_orig_strlen($p) . '): ' . Debug::exportBytes($p) . ', must be >= string length (' . $s . ")\n"); } elseif ($nul) { $lastByte = mb_orig_substr($p, -1); if ($lastByte !== "") { Daemon: log('getLV error: Wrong end of NUL-string (' . Debug::exportBytes($lastByte) . '), len ' . $s . "\n"); } else { $d = $s - 1; if ($d < 0) { $d = 0; } $r = mb_orig_substr($p, 0, $d); $p = mb_orig_substr($p, $s); } } else { $r = mb_orig_substr($p, 0, $s); $p = mb_orig_substr($p, $s); } return $r; }
/** * Stop the workers * @param $n - integer - number of workers to stop * @return boolean - success */ protected function stopWorkers($n = 1) { Daemon::log('--' . $n . '-- ' . Debug::backtrace() . '-----'); $n = (int) $n; $i = 0; foreach ($this->workers->threads as &$w) { if ($i >= $n) { break; } if ($w->shutdown) { continue; } if ($w->reloaded) { continue; } $w->stop(); ++$i; } $this->lastMpmActionTs = microtime(true); return true; }
/** * Send message to log. * @param mixed ...$args Arguments * @return string message */ public static function log() { $args = func_get_args(); if (sizeof($args) == 1) { $msg = is_scalar($args[0]) ? $args[0] : Debug::dump($args[0]); } else { $msg = Debug::dump($args); } $mt = explode(' ', microtime()); //$msg = substr($msg, 0, 1024) . Debug::backtrace(); if (is_resource(STDERR)) { fwrite(STDERR, '[PHPD] ' . $msg . "\n"); } $msg = str_replace("", $msg, date(strtr(Daemon::$config->logformat->value, ['%msg%' => "", '\\u' => '\\u', 'u' => sprintf('%06d', $mt[0] * 1000000)]))) . "\n"; if (Daemon::$logpointerAsync) { Daemon::$logpointerAsync->write($msg); } elseif (Daemon::$logpointer) { fwrite(Daemon::$logpointer, $msg); } }
protected function onPacket() { $this->result = $this->ptr; if (!$this->subscribed) { $this->resultType = !$this->resultTypeStack->isEmpty() ? $this->resultTypeStack->shift() : static::RESULT_TYPE_DEFAULT; if ($this->resultType === static::RESULT_TYPE_ARGSVALS) { $this->args = !$this->argsStack->isEmpty() ? $this->argsStack->shift() : []; } $this->onResponse->executeOne($this); goto clean; } elseif ($this->result[0] === 'message') { $t =& $this->subscribeCb; } elseif ($this->result[0] === 'pmessage') { $t =& $this->psubscribeCb; } else { $this->resultType = !$this->resultTypeStack->isEmpty() ? $this->resultTypeStack->shift() : static::RESULT_TYPE_DEFAULT; if ($this->resultType === static::RESULT_TYPE_ARGSVALS) { $this->args = !$this->argsStack->isEmpty() ? $this->argsStack->shift() : []; } $this->onResponse->executeOne($this); goto clean; } if (isset($t[$this->result[1]])) { $this->resultType = static::RESULT_TYPE_MESSAGE; $this->channel = $this->result[1]; $this->msg = $this->result[2]; foreach ($t[$this->result[1]] as $cb) { if (is_callable($cb)) { call_user_func($cb, $this); } } } elseif ($this->pool->config->logpubsubracecondition->value) { Daemon::log('[Redis client]' . ': PUB/SUB race condition at channel ' . Debug::json($this->result[1])); } clean: $this->args = null; $this->result = null; $this->channel = null; $this->msg = null; $this->error = false; $this->pos = 0; $this->resultType = static::RESULT_TYPE_DEFAULT; $this->assocData = null; if (!isset($t)) { $this->checkFree(); } }