/** * Prepares the request body * @return void */ public function postPrepare() { if (!$this->attrs->server['REQUEST_METHOD_POST']) { return; } if (isset($this->attrs->server['REQUEST_PREPARED_UPLOADS']) && $this->attrs->server['REQUEST_PREPARED_UPLOADS'] === 'nginx') { if (isset($this->attrs->server['REQUEST_PREPARED_UPLOADS_URL_PREFIX'])) { $URLprefix = $this->attrs->server['REQUEST_PREPARED_UPLOADS_URL_PREFIX']; $l = mb_orig_strlen($URLprefix); foreach (['PHP_SELF', 'REQUEST_URI', 'SCRIPT_NAME', 'DOCUMENT_URI'] as $k) { if (!isset($this->attrs->server[$k])) { continue; } if (strncmp($this->attrs->server[$k], $URLprefix, $l) === 0) { $this->attrs->server[$k] = substr($this->attrs->server[$k], $l - 1); } } } $prefix = 'file.'; $prefixlen = mb_orig_strlen($prefix); foreach ($this->attrs->post as $k => $v) { if (strncmp($k, $prefix, $prefixlen) === 0) { $e = explode('.', substr($k, $prefixlen)); if (!isset($e[1])) { $e = ['file', $e[0]]; } if (!isset($this->attrs->files[$e[0]])) { $this->attrs->files[$e[0]] = ['error' => UPLOAD_ERR_OK]; } $this->attrs->files[$e[0]][$e[1]] = $v; unset($this->attrs->post[$k]); } } $uploadTmp = $this->getUploadTempDir(); foreach ($this->attrs->files as $k => &$file) { if (!isset($file['tmp_name']) || !isset($file['name']) || !ctype_digit(basename($file['tmp_name'])) || mb_orig_strpos(pathinfo($file['tmp_name'], PATHINFO_DIRNAME), $uploadTmp) !== 0) { unset($this->attrs->files[$k]); continue; } FileSystem::open($file['tmp_name'], 'c+!', function ($fp) use(&$file) { if (!$fp) { return; } $file['fp'] = $fp; }); } unset($file); } if (isset($this->attrs->server['REQUEST_BODY_FILE']) && $this->upstream->pool->config->autoreadbodyfile->value) { $this->readBodyFile(); } }
/** * Open logs. * @return void */ public static function openLogs() { if (Daemon::$config->logging->value) { Daemon::$logpointer = fopen(Daemon::$config->logstorage->value, 'a'); if (isset(Daemon::$config->group->value)) { chgrp(Daemon::$config->logstorage->value, Daemon::$config->group->value); // @TODO: rewrite to async I/O } if (isset(Daemon::$config->user->value)) { chown(Daemon::$config->logstorage->value, Daemon::$config->user->value); // @TODO: rewrite to async I/O } if (Daemon::$process instanceof Thread\Worker && FileSystem::$supported) { FileSystem::open(Daemon::$config->logstorage->value, 'a!', function ($file) { Daemon::$logpointerAsync = $file; if (!$file) { return; } }); } } else { Daemon::$logpointer = null; Daemon::$logpointerAsync = null; } }
/** * Process HTTP headers * @return boolean Success */ protected function httpProcessHeaders() { $this->req->attrs->paramsDone = true; if (isset($this->req->attrs->server['HTTP_CONNECTION']) && preg_match('~(?:^|\\W)Upgrade(?:\\W|$)~i', $this->req->attrs->server['HTTP_CONNECTION']) && isset($this->req->attrs->server['HTTP_UPGRADE']) && strtolower($this->req->attrs->server['HTTP_UPGRADE']) === 'websocket') { if ($this->pool->WS) { $this->pool->WS->inheritFromRequest($this->req, $this); } return false; } $this->req = Daemon::$appResolver->getRequest($this->req, $this, isset($this->pool->config->responder->value) ? $this->pool->config->responder->value : null); if ($this->req instanceof \stdClass) { $this->endRequest($this->req, 0, 0); return false; } else { if ($this->pool->config->sendfile->value && (!$this->pool->config->sendfileonlybycommand->value || isset($this->req->attrs->server['USE_SENDFILE'])) && !isset($this->req->attrs->server['DONT_USE_SENDFILE'])) { $req = $this->req; FileSystem::tempnam($this->pool->config->sendfiledir->value, $this->pool->config->sendfileprefix->value, function ($fn) use($req) { FileSystem::open($fn, 'wb', function ($file) use($req) { $req->sendfp = $file; }); $req->header('X-Sendfile: ' . $fn); }); } $this->req->callInit(); } return true; }
/** * Returns string of pseudo random bytes * @param integer $len Length of desired string * @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 integer */ public static function randomBytes($len, $cb, $pri = 0, $hang = false) { FileSystem::open('/dev/' . ($hang ? '' : 'u') . 'random', 'r', function ($file) use($len, $cb, $pri) { if (!$file) { call_user_func($cb, false); return; } $file->read($len, 0, function ($file, $data) use($cb) { call_user_func($cb, $data); }, $pri); }, null, $pri); }
/** * Reads session data * @param string $sid Session ID * @param callable $cb Callback * @return void */ public function sessionRead($sid, $cb = null) { FileSystem::open(FileSystem::genRndTempnamPrefix(session_save_path(), $this->sessionPrefix) . basename($sid), 'r+!', function ($fp) use($cb) { if (!$fp) { call_user_func($cb, false); return; } $fp->readAll(function ($fp, $data) use($cb) { $this->sessionFp = $fp; call_user_func($cb, $data); }); }); }
/** * Obtain exclusive temporary file * @param string $dir Directory * @param string $prefix Prefix * @param callable $cb Callback (File) * @return resource */ public static function tempnam($dir, $prefix, $cb) { $cb = CallbackWrapper::forceWrap($cb); if (!FileSystem::$supported) { FileSystem::open(tempnam($dir, $prefix), 'w!', $cb); } $tries = 0; static::tempnamHandler($dir, $prefix, $cb, $tries); }
/** * Returns string of pseudo random bytes * @param integer $len Length of desired string * @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 integer */ public static function randomBytes($len, $cb, $pri = 0, $hang = false) { $cb = CallbackWrapper::wrap($cb); FileSystem::open('/dev/' . ($hang ? '' : 'u') . 'random', 'r', function ($file) use($len, $cb, $pri) { if (!$file) { $cb(false); return; } $file->read($len, 0, function ($file, $data) use($cb) { $cb($data); }, $pri); }, null, $pri); }