Author: Vasily Zorin (maintainer@daemon.io)
Inheritance: use trait PHPDaemon\Traits\ClassWatchdog, use trait PHPDaemon\Traits\StaticObjectWatchdog
 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);
     });
 }
Exemple #2
0
 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]);
 }
Exemple #3
0
 /**
  * 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);
 }
Exemple #4
0
 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']);
         });
     });
 }
Exemple #5
0
 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);
         });
     };
 }
Exemple #6
0
 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]]);
 }
Exemple #7
0
 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();
     }
 }
Exemple #8
0
 public function run()
 {
     Daemon::log(Debug::dump($this->args));
     $this->sendResult(call_user_func_array('mail', $this->args));
 }
Exemple #9
0
 /**
  * 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;
 }
Exemple #10
0
 /**
  * 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.
 }
Exemple #11
0
 /**
  * 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;
 }
Exemple #12
0
 function D(...$args)
 {
     \PHPDaemon\Core\Daemon::log(\PHPDaemon\Core\Debug::dump(...$args));
     //\PHPDaemon\Core\Daemon::log(\PHPDaemon\Core\Debug::backtrace());
 }
Exemple #13
0
 /**
  * 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
             }
         }
     }
 }
Exemple #14
0
 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();
     });
 }
Exemple #15
0
 /**
  * @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]]]);
 }
Exemple #16
0
 /**
  * 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));
     }
 }
Exemple #17
0
 /**
  * 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});
 }
Exemple #19
0
 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;
 }
Exemple #20
0
 /**
  * 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;
 }
Exemple #21
0
 /**
  * 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);
     }
 }
Exemple #23
0
 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();
     }
 }