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]); }
/** * 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; }
/** * 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 } } } }
/** * 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)); } }
/** * 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; }