diff options
Diffstat (limited to 'localwebsite')
31 files changed, 0 insertions, 2369 deletions
diff --git a/localwebsite/classes/MyOpenWrtUtils.php b/localwebsite/classes/MyOpenWrtUtils.php deleted file mode 100644 index c140fa1..0000000 --- a/localwebsite/classes/MyOpenWrtUtils.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php - -class MyOpenWrtUtils { - - // public static function getRoutingTable(?string $table = null): array { - // $arguments = ['route-show']; - // if ($table) - // $arguments[] = $table; - // - // return self::toList(self::run($arguments)); - // } - // - // public static function getRoutingRules(): array { - // return self::toList(self::run(['rule-show'])); - // } - // - // public static function ipsetList(string $set_name): array { - // return self::toList(self::run(['ipset-list', $set_name])); - // } - - public static function ipsetListAll(): array { - global $config; - - $args = ['ipset-list-all']; - $args = array_merge($args, array_keys($config['modems'])); - - $lines = self::toList(self::run($args)); - - $sets = []; - $cur_set = null; - foreach ($lines as $line) { - if (startsWith($line, '>')) { - $cur_set = substr($line, 1); - if (!isset($sets[$cur_set])) - $sets[$cur_set] = []; - continue; - } - - if (is_null($cur_set)) { - debugError(__METHOD__.': cur_set is not set'); - continue; - } - - $sets[$cur_set][] = $line; - } - - return $sets; - } - - public static function ipsetAdd(string $set_name, string $ip) { - return self::run(['ipset-add', $set_name, $ip]); - } - - public static function ipsetDel(string $set_name, string $ip) { - return self::run(['ipset-del', $set_name, $ip]); - } - - public static function getDHCPLeases(): array { - $list = self::toList(self::run(['dhcp-leases'])); - $list = array_map('self::toDHCPLease', $list); - return $list; - } - - public static function setUpstream(string $ip) { - return self::run(['homekit-set-default-upstream', $ip]); - } - - public static function getDefaultRoute() { - return self::run(['get-default-route']); - } - - - // - // http functions - // - - private static function run(array $arguments) { - $url = self::getLink($arguments); - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - $body = curl_exec($ch); - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - if ($code != 200) - throw new Exception(__METHOD__.': http code '.$code); - - curl_close($ch); - return trim($body); - } - - private static function getLink($arguments) { - global $config; - - $url = 'http://'.$config['openwrt_ip'].'/cgi-bin/luci/command/cfg099944'; - if (!empty($arguments)) { - $arguments = array_map(function($arg) { - $arg = str_replace('/', '_', $arg); - return urlencode($arg); - }, $arguments); - $arguments = implode('%20', $arguments); - - $url .= '/'; - $url .= $arguments; - } - - return $url; - } - - - // - // parsing functions - // - - private static function toList(string $s): array { - if ($s == '') - return []; - return explode("\n", $s); - } - - private static function toDHCPLease(string $s): array { - $words = explode(' ', $s); - $time = array_shift($words); - $mac = array_shift($words); - $ip = array_shift($words); - array_pop($words); - $hostname = trim(implode(' ', $words)); - if (!$hostname || $hostname == '*') - $hostname = '?'; - return [ - 'time' => $time, - 'time_s' => date('d M, H:i:s', $time), - 'mac' => $mac, - 'ip' => $ip, - 'hostname' => $hostname - ]; - } - -} diff --git a/localwebsite/classes/MySimpleSocketClient.php b/localwebsite/classes/MySimpleSocketClient.php deleted file mode 100644 index e59efba..0000000 --- a/localwebsite/classes/MySimpleSocketClient.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -class MySimpleSocketClient { - - protected $sock; - - public function __construct(string $host, int $port) - { - if (($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) - throw new Exception("socket_create() failed: ".$this->getSocketError()); - - $this->sock = $socket; - - if ((socket_connect($socket, $host, $port)) === false) - throw new Exception("socket_connect() failed: ".$this->getSocketError()); - } - - public function __destruct() - { - $this->close(); - } - - /** - * @throws Exception - */ - public function send(string $data) - { - $data .= "\r\n"; - $remained = strlen($data); - - while ($remained > 0) { - $result = socket_write($this->sock, $data); - if ($result === false) - throw new Exception(__METHOD__ . ": socket_write() failed: ".$this->getSocketError()); - - $remained -= $result; - if ($remained > 0) - $data = substr($data, $result); - } - } - - /** - * @throws Exception - */ - public function recv() - { - $recv_buf = ''; - $buf = ''; - - while (true) { - $result = socket_recv($this->sock, $recv_buf, 1024, 0); - if ($result === false) - throw new Exception(__METHOD__ . ": socket_recv() failed: " . $this->getSocketError()); - - // peer disconnected - if ($result === 0) - break; - - $buf .= $recv_buf; - if (endsWith($buf, "\r\n")) - break; - } - - return trim($buf); - } - - /** - * Close connection. - */ - public function close() - { - if (!$this->sock) - return; - - socket_close($this->sock); - $this->sock = null; - } - - /** - * @return string - */ - protected function getSocketError(): string - { - $sle_args = []; - if ($this->sock !== null) - $sle_args[] = $this->sock; - return socket_strerror(socket_last_error(...$sle_args)); - } - -}
\ No newline at end of file diff --git a/localwebsite/classes/TemphumdClient.php b/localwebsite/classes/TemphumdClient.php deleted file mode 100644 index 07e5a3e..0000000 --- a/localwebsite/classes/TemphumdClient.php +++ /dev/null @@ -1,41 +0,0 @@ -<?php - -class TemphumdClient extends MySimpleSocketClient { - - public string $name; - public float $temp; - public float $humidity; - public ?int $flags; - - /** - * @throws Exception - */ - public function __construct(string $host, int $port, string $name, ?int $flags = null) { - parent::__construct($host, $port); - $this->name = $name; - $this->flags = $flags; - - socket_set_timeout($this->sock, 3); - } - - public function readSensor(): void { - $this->send('read'); - - $data = jsonDecode($this->recv()); - - $temp = round((float)$data['temp'], 3); - $hum = round((float)$data['humidity'], 3); - - $this->temp = $temp; - $this->humidity = $hum; - } - - public function hasTemperature(): bool { - return ($this->flags & config::TEMPHUMD_NO_TEMP) == 0; - } - - public function hasHumidity(): bool { - return ($this->flags & config::TEMPHUMD_NO_HUM) == 0; - } - -}
\ No newline at end of file diff --git a/localwebsite/classes/User.php b/localwebsite/classes/User.php deleted file mode 100644 index 9019082..0000000 --- a/localwebsite/classes/User.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -class User extends model { - - const DB_TABLE = 'users'; - - public int $id; - public string $username; - public string $password; - -} diff --git a/localwebsite/classes/auth.php b/localwebsite/classes/auth.php deleted file mode 100644 index a13843b..0000000 --- a/localwebsite/classes/auth.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -class auth { - - public static ?User $authorizedUser = null; - - const COOKIE_NAME = 'lws-auth'; - - public static function getToken(): ?string { - return $_COOKIE[self::COOKIE_NAME] ?? null; - } - - public static function setToken(string $token) { - setcookie_safe(self::COOKIE_NAME, $token); - } - - public static function resetToken() { - if (!headers_sent()) - unsetcookie(self::COOKIE_NAME); - } - - public static function id(bool $do_check = true): int { - if ($do_check) - self::check(); - - if (!self::$authorizedUser) - return 0; - - return self::$authorizedUser->id; - } - - public static function check(?string $pwhash = null): bool { - if (self::$authorizedUser !== null) - return true; - - // get auth token - if (!$pwhash) - $pwhash = self::getToken(); - - if (!is_string($pwhash)) - return false; - - // find session by given token - $user = users::getUserByPwhash($pwhash); - if (is_null($user)) { - self::resetToken(); - return false; - } - - self::$authorizedUser = $user; - - return true; - } - - public static function logout() { - self::resetToken(); - self::$authorizedUser = null; - } - -}
\ No newline at end of file diff --git a/localwebsite/classes/config.php b/localwebsite/classes/config.php deleted file mode 100644 index 927321e..0000000 --- a/localwebsite/classes/config.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php - -class config { - - const TEMPHUMD_NO_TEMP = 1 << 0; - const TEMPHUMD_NO_HUM = 1 << 1; - - public static function get(string $key) { - global $config; - return is_callable($config[$key]) ? $config[$key]() : $config[$key]; - } - -}
\ No newline at end of file diff --git a/localwebsite/classes/users.php b/localwebsite/classes/users.php deleted file mode 100644 index 1160dba..0000000 --- a/localwebsite/classes/users.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -class users { - - public static function add(string $username, string $password): int { - $db = getDB(); - $db->insert('users', [ - 'username' => $username, - 'password' => pwhash($password) - ]); - return $db->insertId(); - } - - public static function exists(string $username): bool { - $db = getDB(); - $count = (int)$db->querySingle("SELECT COUNT(*) FROM users WHERE username=?", $username); - return $count > 0; - } - - public static function validatePassword(string $username, string $password): bool { - $db = getDB(); - $row = $db->querySingleRow("SELECT * FROM users WHERE username=?", $username); - if (!$row) - return false; - - return $row['password'] == pwhash($password); - } - - public static function getUserByPwhash(string $pwhash): ?User { - $db = getDB(); - $data = $db->querySingleRow("SELECT * FROM users WHERE password=?", $pwhash); - return $data ? new User($data) : null; - } - - public static function setPassword(int $id, string $new_password) { - getDB()->exec("UPDATE users SET password=? WHERE id=?", pwhash($new_password), $id); - } - -}
\ No newline at end of file diff --git a/localwebsite/engine/debug.php b/localwebsite/engine/debug.php deleted file mode 100644 index b1b959f..0000000 --- a/localwebsite/engine/debug.php +++ /dev/null @@ -1,355 +0,0 @@ -<?php - -// require_once 'engine/mysql.php'; - -class debug { - - protected static $Types = [ - 1 => 'E_ERROR', - 2 => 'E_WARNING', - 4 => 'E_PARSE', - 8 => 'E_NOTICE', - 16 => 'E_CORE_ERROR', - 32 => 'E_CORE_WARNING', - 64 => 'E_COMPILE_ERROR', - 128 => 'E_COMPILE_WARNING', - 256 => 'E_USER_ERROR', - 512 => 'E_USER_WARNING', - 1024 => 'E_USER_NOTICE', - 2048 => 'E_STRICT', - 4096 => 'E_RECOVERABLE_ERROR', - 8192 => 'E_DEPRECATED', - 16384 => 'E_USER_DEPRECATED', - 32767 => 'E_ALL' - ]; - - const STORE_NONE = -1; - const STORE_MYSQL = 0; - const STORE_FILE = 1; - const STORE_BOTH = 2; - - private static $instance = null; - - protected $enabled = false; - protected $errCounter = 0; - protected $logCounter = 0; - protected $messagesStoreType = self::STORE_NONE; - protected $errorsStoreType = self::STORE_NONE; - protected $filter; - protected $reportRecursionLevel = 0; - protected $overridenDebugFile = null; - protected $silent = false; - protected $prefix; - - private function __construct($filter) { - $this->filter = $filter; - } - - public static function getInstance($filter = null) { - if (is_null(self::$instance)) { - self::$instance = new self($filter); - } - return self::$instance; - } - - public function enable() { - $self = $this; - - set_error_handler(function($no, $str, $file, $line) use ($self) { - if ($self->silent || !$self->enabled) { - return; - } - if ((is_callable($this->filter) && !($this->filter)($no, $file, $line, $str)) || !$self->canReport()) { - return; - } - $self->report(true, $str, $no, $file, $line); - }); - - append_shutdown_function(function() use ($self) { - if (!$self->enabled || !($error = error_get_last())) { - return; - } - if (is_callable($this->filter) - && !($this->filter)($error['type'], $error['file'], $error['line'], $error['message'])) { - return; - } - if (!$self->canReport()) { - return; - } - $self->report(true, $error['message'], $error['type'], $error['file'], $error['line']); - }); - - $this->enabled = true; - } - - public function disable() { - restore_error_handler(); - $this->enabled = false; - } - - public function report($is_error, $text, $errno = 0, $errfile = '', $errline = '') { - global $config; - - $this->reportRecursionLevel++; - - $logstarted = $this->errCounter > 0 || $this->logCounter > 0; - $num = $is_error ? $this->errCounter++ : $this->logCounter++; - $custom = $is_error && !$errno; - $ts = time(); - $exectime = exectime(); - $bt = backtrace(2); - - $store_file = (!$is_error && $this->checkMessagesStoreType(self::STORE_FILE)) - || ($is_error && $this->checkErrorsStoreType(self::STORE_FILE)); - - $store_mysql = (!$is_error && $this->checkMessagesStoreType(self::STORE_MYSQL)) - || ($is_error && $this->checkErrorsStoreType(self::STORE_MYSQL)); - - if ($this->prefix) - $text = $this->prefix.$text; - - // if ($store_mysql) { - // $db = getMySQL('local_logs', true); - // $data = [ - // 'ts' => $ts, - // 'num' => $num, - // 'time' => $exectime, - // 'custom' => intval($custom), - // 'errno' => $errno, - // 'file' => $errfile, - // 'line' => $errline, - // 'text' => $text, - // 'stacktrace' => $bt, - // 'is_cli' => PHP_SAPI == 'cli' ? 1 : 0, - // ]; - // if (PHP_SAPI == 'cli') { - // $data += [ - // 'ip' => '', - // 'ua' => '', - // 'url' => '', - // ]; - // } else { - // $data += [ - // 'ip' => ip2ulong($_SERVER['REMOTE_ADDR']), - // 'ua' => $_SERVER['HTTP_USER_AGENT'] ?? '', - // 'url' => $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'] - // ]; - // } - // $db->insert('backend_errors', $data); - // } - - if ($store_file) { - $title = PHP_SAPI == 'cli' ? 'cli' : $_SERVER['REQUEST_URI']; - $date = date('d/m/y H:i:s', $ts); - $exectime = (string)$exectime; - if (strlen($exectime) < 6) - $exectime .= str_repeat('0', 6 - strlen($exectime)); - - $buf = ""; - if (!$logstarted) { - $buf .= "\n<e fg=white bg=magenta style=fgbright,bold> {$title} </e><e fg=white bg=blue style=fgbright> {$date} </e>\n"; - } - $buf .= "<e fg=".($is_error ? 'red' : 'white').">".($is_error ? 'E' : 'I')."=<e style=bold>${num}</e> <e fg=cyan>{$exectime}</e> "; - if ($is_error && !$custom) { - $buf .= "<e fg=green>{$errfile}<e fg=white>:<e fg=green style=fgbright>{$errline}</e> (".self::errname($errno).") "; - } - $buf = stransi($buf); - - $buf .= $text; - $buf .= "\n"; - if ($is_error && $config['debug_backtrace']) { - $buf .= $bt."\n"; - } - - $debug_file = $this->getDebugFile(); - - $logdir = dirname($debug_file); - if (!file_exists($logdir)) { - mkdir($logdir); - setperm($logdir); - } - - $f = fopen($debug_file, 'a'); - if ($f) { - fwrite($f, $buf); - fclose($f); - } - } - - $this->reportRecursionLevel--; - } - - public function canReport() { - return $this->reportRecursionLevel < 2; - } - - public function setErrorsStoreType($errorsStoreType) { - $this->errorsStoreType = $errorsStoreType; - } - - public function setMessagesStoreType($messagesStoreType) { - $this->messagesStoreType = $messagesStoreType; - } - - public function checkMessagesStoreType($store_type) { - return $this->messagesStoreType == $store_type || $this->messagesStoreType == self::STORE_BOTH; - } - - public function checkErrorsStoreType($store_type) { - return $this->errorsStoreType == $store_type || $this->errorsStoreType == self::STORE_BOTH; - } - - public function overrideDebugFile($file) { - $this->overridenDebugFile = $file; - } - - protected function getDebugFile() { - global $config; - return is_null($this->overridenDebugFile) ? ROOT.'/'.$config['debug_file'] : $this->overridenDebugFile; - } - - public function setSilence($silent) { - $this->silent = $silent; - } - - public function setPrefix($prefix) { - $this->prefix = $prefix; - } - - public static function errname($errno) { - static $errors = null; - if (is_null($errors)) { - $errors = array_flip(array_slice(get_defined_constants(true)['Core'], 0, 15, true)); - } - return $errors[$errno]; - } - - public static function getTypes() { - return self::$Types; - } - -} - -class debug_measure { - - private $name; - private $time; - private $started = false; - - /** - * @param string $name - * @return $this - */ - public function start($name = null) { - if (is_null($name)) { - $name = strgen(3); - } - $this->name = $name; - $this->time = microtime(true); - $this->started = true; - return $this; - } - - /** - * @return float|string|null - */ - public function finish() { - if (!$this->started) { - debugLog("debug_measure::finish(): not started, name=".$this->name); - return null; - } - - $time = (microtime(true) - $this->time); - debugLog("MEASURE".($this->name != '' ? ' '.$this->name : '').": ".$time); - - $this->started = false; - return $time; - } - -} - -/** - * @param $var - * @return string - */ -function str_print_r($var) { - ob_start(); - print_r($var); - return trim(ob_get_clean()); -} - -/** - * @param $var - * @return string - */ -function str_var_dump($var) { - ob_start(); - var_dump($var); - return trim(ob_get_clean()); -} - -/** - * @param $args - * @param bool $all_dump - * @return string - */ -function str_vars($args, $all_dump = false) { - return implode(' ', array_map(function($a) use ($all_dump) { - if ($all_dump) { - return str_var_dump($a); - } - $type = gettype($a); - if ($type == 'string' || $type == 'integer' || $type == 'double') { - return $a; - } else if ($type == 'array' || $type == 'object') { - return str_print_r($a); - } else { - return str_var_dump($a); - } - }, $args)); -} - -/** - * @param int $shift - * @return string - */ -function backtrace($shift = 0) { - $bt = debug_backtrace(); - $lines = []; - foreach ($bt as $i => $t) { - if ($i < $shift) { - continue; - } - if (!isset($t['file'])) { - $lines[] = 'from ?'; - } else { - $lines[] = 'from '.$t['file'].':'.$t['line']; - } - } - return implode("\n", $lines); -} - -/** - * @param mixed ...$args - */ -function debugLog(...$args) { - global $config; - if (!$config['is_dev']) - return; - - debug::getInstance()->report(false, str_vars($args)); -} - -function debugLogOnProd(...$args) { - debug::getInstance()->report(false, str_vars($args)); -} - -/** - * @param mixed ...$args - */ -function debugError(...$args) { - $debug = debug::getInstance(); - if ($debug->canReport()) { - $debug->report(true, str_vars($args)); - } -} diff --git a/localwebsite/engine/model.php b/localwebsite/engine/model.php deleted file mode 100644 index 4dd981c..0000000 --- a/localwebsite/engine/model.php +++ /dev/null @@ -1,243 +0,0 @@ -<?php - -abstract class model { - - const DB_TABLE = null; - const DB_KEY = 'id'; - - const STRING = 0; - const INTEGER = 1; - const FLOAT = 2; - const ARRAY = 3; - const BOOLEAN = 4; - const JSON = 5; - const SERIALIZED = 6; - - protected static array $SpecCache = []; - - public static function create_instance(...$args) { - $cl = get_called_class(); - return new $cl(...$args); - } - - public function __construct(array $raw) { - if (!isset(self::$SpecCache[static::class])) { - list($fields, $model_name_map, $db_name_map) = static::get_spec(); - self::$SpecCache[static::class] = [ - 'fields' => $fields, - 'model_name_map' => $model_name_map, - 'db_name_map' => $db_name_map - ]; - } - - foreach (self::$SpecCache[static::class]['fields'] as $field) - $this->{$field['model_name']} = self::cast_to_type($field['type'], $raw[$field['db_name']]); - - if (is_null(static::DB_TABLE)) - trigger_error('class '.get_class($this).' doesn\'t have DB_TABLE defined'); - } - - /** - * @param $fields - * - * TODO: support adding or subtracting (SET value=value+1) - */ - public function edit($fields) { - $db = getDB(); - - $model_upd = []; - $db_upd = []; - - foreach ($fields as $name => $value) { - $index = self::$SpecCache[static::class]['db_name_map'][$name] ?? null; - if (is_null($index)) { - debugError(__METHOD__.': field `'.$name.'` not found in '.static::class); - continue; - } - - $field = self::$SpecCache[static::class]['fields'][$index]; - switch ($field['type']) { - case self::ARRAY: - if (is_array($value)) { - $db_upd[$name] = implode(',', $value); - $model_upd[$field['model_name']] = $value; - } else { - debugError(__METHOD__.': field `'.$name.'` is expected to be array. skipping.'); - } - break; - - case self::INTEGER: - $value = (int)$value; - $db_upd[$name] = $value; - $model_upd[$field['model_name']] = $value; - break; - - case self::FLOAT: - $value = (float)$value; - $db_upd[$name] = $value; - $model_upd[$field['model_name']] = $value; - break; - - case self::BOOLEAN: - $db_upd[$name] = $value ? 1 : 0; - $model_upd[$field['model_name']] = $value; - break; - - case self::JSON: - $db_upd[$name] = jsonEncode($value); - $model_upd[$field['model_name']] = $value; - break; - - case self::SERIALIZED: - $db_upd[$name] = serialize($value); - $model_upd[$field['model_name']] = $value; - break; - - default: - $value = (string)$value; - $db_upd[$name] = $value; - $model_upd[$field['model_name']] = $value; - break; - } - } - - if (!empty($db_upd) && !$db->update(static::DB_TABLE, $db_upd, static::DB_KEY."=?", $this->get_id())) { - debugError(__METHOD__.': failed to update database'); - return; - } - - if (!empty($model_upd)) { - foreach ($model_upd as $name => $value) - $this->{$name} = $value; - } - } - - public function get_id() { - return $this->{to_camel_case(static::DB_KEY)}; - } - - public function as_array(array $fields = [], array $custom_getters = []): array { - if (empty($fields)) - $fields = array_keys(static::$SpecCache[static::class]['db_name_map']); - - $array = []; - foreach ($fields as $field) { - if (isset($custom_getters[$field]) && is_callable($custom_getters[$field])) { - $array[$field] = $custom_getters[$field](); - } else { - $array[$field] = $this->{to_camel_case($field)}; - } - } - - return $array; - } - - protected static function cast_to_type(int $type, $value) { - switch ($type) { - case self::BOOLEAN: - return (bool)$value; - - case self::INTEGER: - return (int)$value; - - case self::FLOAT: - return (float)$value; - - case self::ARRAY: - return array_filter(explode(',', $value)); - - case self::JSON: - $val = jsonDecode($value); - if (!$val) - $val = null; - return $val; - - case self::SERIALIZED: - $val = unserialize($value); - if ($val === false) - $val = null; - return $val; - - default: - return (string)$value; - } - } - - protected static function get_spec(): array { - $rc = new ReflectionClass(static::class); - $props = $rc->getProperties(ReflectionProperty::IS_PUBLIC); - - $list = []; - $index = 0; - - $model_name_map = []; - $db_name_map = []; - - foreach ($props as $prop) { - if ($prop->isStatic()) - continue; - - $name = $prop->getName(); - if (startsWith($name, '_')) - continue; - - $type = $prop->getType(); - $phpdoc = $prop->getDocComment(); - - $mytype = null; - if (!$prop->hasType() && !$phpdoc) - $mytype = self::STRING; - else { - $typename = $type->getName(); - switch ($typename) { - case 'string': - $mytype = self::STRING; - break; - case 'int': - $mytype = self::INTEGER; - break; - case 'float': - $mytype = self::FLOAT; - break; - case 'array': - $mytype = self::ARRAY; - break; - case 'bool': - $mytype = self::BOOLEAN; - break; - } - - if ($phpdoc != '') { - $pos = strpos($phpdoc, '@'); - if ($pos === false) - continue; - - if (substr($phpdoc, $pos+1, 4) == 'json') - $mytype = self::JSON; - else if (substr($phpdoc, $pos+1, 5) == 'array') - $mytype = self::ARRAY; - else if (substr($phpdoc, $pos+1, 10) == 'serialized') - $mytype = self::SERIALIZED; - } - } - - if (is_null($mytype)) - debugError(__METHOD__.": ".$name." is still null in ".static::class); - - $dbname = from_camel_case($name); - $list[] = [ - 'type' => $mytype, - 'model_name' => $name, - 'db_name' => $dbname - ]; - - $model_name_map[$name] = $index; - $db_name_map[$dbname] = $index; - - $index++; - } - - return [$list, $model_name_map, $db_name_map]; - } - -} diff --git a/localwebsite/engine/request_handler.php b/localwebsite/engine/request_handler.php deleted file mode 100644 index 535e850..0000000 --- a/localwebsite/engine/request_handler.php +++ /dev/null @@ -1,142 +0,0 @@ -<?php - -abstract class request_handler { - - const GET = 'GET'; - const POST = 'POST'; - - private static array $AllowedInputTypes = ['i', 'f', 'b', 'e' /* enum */]; - - public function dispatch(string $act) { - $method = $_SERVER['REQUEST_METHOD'] == 'POST' ? 'POST' : 'GET'; - return $this->call_act($method, $act); - } - - protected function before_dispatch(string $method, string $act)/*: ?array*/ { - return null; - } - - protected function call_act(string $method, string $act, array $input = []) { - global $RouterInput; - - $notfound = !method_exists($this, $method.'_'.$act) || !((new ReflectionMethod($this, $method.'_'.$act))->isPublic()); - if ($notfound) - $this->method_not_found($method, $act); - - if (!empty($input)) { - foreach ($input as $k => $v) - $RouterInput[$k] = $v; - } - - $args = $this->before_dispatch($method, $act); - return call_user_func_array([$this, $method.'_'.$act], is_array($args) ? [$args] : []); - } - - abstract protected function method_not_found(string $method, string $act); - - protected function input(string $input, bool $as_assoc = false): array { - $input = preg_split('/,\s+?/', $input, null, PREG_SPLIT_NO_EMPTY); - - $ret = []; - foreach ($input as $var) { - list($type, $name, $enum_values, $enum_default) = self::parse_input_var($var); - - $value = param($name); - - switch ($type) { - case 'i': - if (is_null($value) && !is_null($enum_default)) { - $value = (int)$enum_default; - } else { - $value = (int)$value; - } - break; - - case 'f': - if (is_null($value) && !is_null($enum_default)) { - $value = (float)$enum_default; - } else { - $value = (float)$value; - } - break; - - case 'b': - if (is_null($value) && !is_null($enum_default)) { - $value = (bool)$enum_default; - } else { - $value = (bool)$value; - } - break; - - case 'e': - if (!in_array($value, $enum_values)) { - $value = !is_null($enum_default) ? $enum_default : ''; - } - break; - } - - if (!$as_assoc) { - $ret[] = $value; - } else { - $ret[$name] = $value; - } - } - - return $ret; - } - protected static function parse_input_var(string $var): array { - $type = null; - $name = null; - $enum_values = null; - $enum_default = null; - - $pos = strpos($var, ':'); - if ($pos !== false) { - $type = substr($var, 0, $pos); - $rest = substr($var, $pos+1); - - if (!in_array($type, self::$AllowedInputTypes)) { - trigger_error('request_handler::parse_input_var('.$var.'): unknown type '.$type); - $type = null; - } - - switch ($type) { - case 'e': - $br_from = strpos($rest, '('); - $br_to = strpos($rest, ')'); - - if ($br_from === false || $br_to === false) { - trigger_error('request_handler::parse_input_var('.$var.'): failed to parse enum values'); - $type = null; - $name = $rest; - break; - } - - $enum_values = array_map('trim', explode('|', trim(substr($rest, $br_from+1, $br_to-$br_from-1)))); - $name = trim(substr($rest, 0, $br_from)); - - if (!empty($enum_values)) foreach ($enum_values as $key => $val) { - if (substr($val, 0, 1) == '=') { - $enum_values[$key] = substr($val, 1); - $enum_default = $enum_values[$key]; - } - } - break; - - default: - if (($eq_pos = strpos($rest, '=')) !== false) { - $enum_default = substr($rest, $eq_pos+1); - $rest = substr($rest, 0, $eq_pos); - } - $name = trim($rest); - break; - } - } else { - $type = 's'; - $name = $var; - } - - return [$type, $name, $enum_values, $enum_default]; - } - -} diff --git a/localwebsite/engine/router.php b/localwebsite/engine/router.php deleted file mode 100644 index 5e966a9..0000000 --- a/localwebsite/engine/router.php +++ /dev/null @@ -1,199 +0,0 @@ -<?php - -class router { - - protected array $routes = [ - 'children' => [], - 're_children' => [] - ]; - - public function add($template, $value) { - if ($template == '') { - return; - } - - // expand {enum,erat,ions} - $templates = [[$template, $value]]; - if (preg_match_all('/\{([\w\d_\-,]+)\}/', $template, $matches)) { - foreach ($matches[1] as $match_index => $variants) { - $variants = explode(',', $variants); - $variants = array_map('trim', $variants); - $variants = array_filter($variants, function($s) { return $s != ''; }); - - for ($i = 0; $i < count($templates); ) { - list($template, $value) = $templates[$i]; - $new_templates = []; - foreach ($variants as $variant_index => $variant) { - $new_templates[] = [ - str_replace_once($matches[0][$match_index], $variant, $template), - str_replace('${'.($match_index+1).'}', $variant, $value) - ]; - } - array_splice($templates, $i, 1, $new_templates); - $i += count($new_templates); - } - } - } - - // process all generated routes - foreach ($templates as $template) { - list($template, $value) = $template; - - $start_pos = 0; - $parent = &$this->routes; - $template_len = strlen($template); - - while ($start_pos < $template_len) { - $slash_pos = strpos($template, '/', $start_pos); - if ($slash_pos !== false) { - $part = substr($template, $start_pos, $slash_pos-$start_pos+1); - $start_pos = $slash_pos+1; - } else { - $part = substr($template, $start_pos); - $start_pos = $template_len; - } - - $parent = &$this->_addRoute($parent, $part, - $start_pos < $template_len ? null : $value); - } - } - } - - protected function &_addRoute(&$parent, $part, $value = null) { - $par_pos = strpos($part, '('); - $is_regex = $par_pos !== false && ($par_pos == 0 || $part[$par_pos-1] != '\\'); - - $children_key = !$is_regex ? 'children' : 're_children'; - - if (isset($parent[$children_key][$part])) { - if (is_null($value)) { - $parent = &$parent[$children_key][$part]; - } else { - if (!isset($parent[$children_key][$part]['value'])) { - $parent[$children_key][$part]['value'] = $value; - } else { - trigger_error(__METHOD__.': route is already defined'); - } - } - return $parent; - } - - $child = [ - 'children' => [], - 're_children' => [] - ]; - if (!is_null($value)) { - $child['value'] = $value; - } - - $parent[$children_key][$part] = $child; - return $parent[$children_key][$part]; - } - - public function find($uri) { - if ($uri != '/' && $uri[0] == '/') { - $uri = substr($uri, 1); - } - $start_pos = 0; - $parent = &$this->routes; - $uri_len = strlen($uri); - $matches = []; - - while ($start_pos < $uri_len) { - $slash_pos = strpos($uri, '/', $start_pos); - if ($slash_pos !== false) { - $part = substr($uri, $start_pos, $slash_pos-$start_pos+1); - $start_pos = $slash_pos+1; - } else { - $part = substr($uri, $start_pos); - $start_pos = $uri_len; - } - - $found = false; - if (isset($parent['children'][$part])) { - $parent = &$parent['children'][$part]; - $found = true; - } else if (!empty($parent['re_children'])) { - foreach ($parent['re_children'] as $re => &$child) { - $exp = '#^'.$re.'$#'; - $re_result = preg_match($exp, $part, $match); - if ($re_result === false) { - debugError(__METHOD__.": regex $exp failed"); - continue; - } - - if ($re_result) { - if (count($match) > 1) { - $matches = array_merge($matches, array_slice($match, 1)); - } - $parent = &$child; - $found = true; - break; - } - } - } - - if (!$found) { - return false; - } - } - - if (!isset($parent['value'])) { - return false; - } - - $value = $parent['value']; - if (!empty($matches)) { - foreach ($matches as $i => $match) { - $needle = '$('.($i+1).')'; - $pos = strpos($value, $needle); - if ($pos !== false) { - $value = substr_replace($value, $match, $pos, strlen($needle)); - } - } - } - - return $value; - } - - public function load($routes) { - $this->routes = $routes; - } - - public function dump() { - return $this->routes; - } - -} - -function routerFind(router $router) { - $document_uri = $_SERVER['REQUEST_URI']; - if (($pos = strpos($document_uri, '?')) !== false) - $document_uri = substr($document_uri, 0, $pos); - $document_uri = urldecode($document_uri); - - $fixed_document_uri = preg_replace('#/+#', '/', $document_uri); - if ($fixed_document_uri != $document_uri && !is_xhr_request()) { - redirect($fixed_document_uri); - } else { - $document_uri = $fixed_document_uri; - } - - $route = $router->find($document_uri); - if ($route === false) - return false; - - $route = preg_split('/ +/', $route); - $handler = $route[0]; - $act = $route[1]; - $input = []; - if (count($route) > 2) { - for ($i = 2; $i < count($route); $i++) { - $var = $route[$i]; - list($k, $v) = explode('=', $var); - $input[trim($k)] = trim($v); - } - } - - return [$handler, $act, $input]; -}
\ No newline at end of file diff --git a/localwebsite/engine/tpl.php b/localwebsite/engine/tpl.php deleted file mode 100644 index 3d18c9a..0000000 --- a/localwebsite/engine/tpl.php +++ /dev/null @@ -1,520 +0,0 @@ -<?php - -abstract class base_tpl { - - public $twig; - protected $vars = []; - protected $global_vars = []; - protected $title = ''; - protected $title_modifiers = []; - protected $keywords = ''; - protected $description = ''; - protected $js = []; - protected $lang_keys = []; - protected $static = []; - protected $external_static = []; - protected $head = []; - protected $globals_applied = false; - protected $static_time; - - public function __construct($templates_dir, $cache_dir) { - global $config; - - // $cl = get_called_class(); - - $this->twig = self::twig_instance($templates_dir, $cache_dir, $config['is_dev']); - $this->static_time = time(); - } - - public static function twig_instance($templates_dir, $cache_dir, $auto_reload) { - // must specify a second argument ($rootPath) here - // otherwise it will be getcwd() and it's www-prod/htdocs/ for apache and www-prod/ for cli code - // this is bad for templates rebuilding - $twig_loader = new \Twig\Loader\FilesystemLoader($templates_dir, ROOT); - - $env_options = []; - if (!is_null($cache_dir)) { - $env_options += [ - 'cache' => $cache_dir, - 'auto_reload' => $auto_reload - ]; - } - - $twig = new \Twig\Environment($twig_loader, $env_options); - $twig->addExtension(new Twig_MyExtension); - - return $twig; - } - - public function render($template, array $vars = []) { - $this->apply_globals(); - return $this->do_render($template, array_merge($this->vars, $vars)); - } - - protected function do_render($template, $vars) { - global $config; - $s = ''; - try { - $s = $this->twig->render($template, $vars); - } catch (\Twig\Error\Error $e) { - $error = get_class($e).": failed to render"; - $source_ctx = $e->getSourceContext(); - if ($source_ctx) { - $path = $source_ctx->getPath(); - if (startsWith($path, ROOT)) - $path = substr($path, strlen(ROOT)+1); - $error .= " ".$source_ctx->getName()." (".$path.") at line ".$e->getTemplateLine(); - } - $error .= ": "; - $error .= $e->getMessage(); - debugError($error); - if ($config['is_dev']) - $s = $error."\n"; - } - return $s; - } - - public function set($arg1, $arg2 = null) { - if (is_array($arg1)) { - foreach ($arg1 as $key => $value) { - $this->vars[$key] = $value; - } - } elseif ($arg2 !== null) { - $this->vars[$arg1] = $arg2; - } - } - - public function is_set($key): bool { - return isset($this->vars[$key]); - } - - public function set_global($arg1, $arg2 = null) { - if (is_array($arg1)) { - foreach ($arg1 as $key => $value) { - $this->global_vars[$key] = $value; - } - } elseif ($arg2 !== null) { - $this->global_vars[$arg1] = $arg2; - } - } - - public function is_global_set($key): bool { - return isset($this->global_vars[$key]); - } - - public function get_global($key) { - return $this->is_global_set($key) ? $this->global_vars[$key] : null; - } - - public function apply_globals() { - if (!empty($this->global_vars) && !$this->globals_applied) { - foreach ($this->global_vars as $key => $value) - $this->twig->addGlobal($key, $value); - $this->globals_applied = true; - } - } - - /** - * @param string $title - */ - public function set_title($title) { - $this->title = $title; - } - - /** - * @return string - */ - public function get_title() { - $title = $this->title != '' ? $this->title : 'Домашний сайт'; - if (!empty($this->title_modifiers)) { - foreach ($this->title_modifiers as $modifier) { - $title = $modifier($title); - } - } - return $title; - } - - /** - * @param callable $callable - */ - public function add_page_title_modifier(callable $callable) { - if (!is_callable($callable)) { - trigger_error(__METHOD__.': argument is not callable'); - } else { - $this->title_modifiers[] = $callable; - } - } - - /** - * @param string $css_name - * @param null $extra - */ - public function add_static(string $name, $extra = null) { - global $config; - // $is_css = endsWith($name, '.css'); - $this->static[] = [$name, $extra]; - } - - public function add_external_static($type, $url) { - $this->external_static[] = ['type' => $type, 'url' => $url]; - } - - public function add_js($js) { - $this->js[] = $js; - } - - public function add_lang_keys(array $keys) { - $this->lang_keys = array_merge($this->lang_keys, $keys); - } - - public function add_head($html) { - $this->head[] = $html; - } - - public function get_head_html() { - global $config; - $lines = []; - $public_path = $config['static_public_path']; - foreach ($this->static as $val) { - list($name, $extra) = $val; - if (endsWith($name, '.js')) - $lines[] = self::js_link($public_path.'/'.$name, $config['static'][$name] ?? 1); - else - $lines[] = self::css_link($public_path.'/'.$name, $config['static'][$name] ?? 1, $extra); - } - if (!empty($this->external_static)) { - foreach ($this->external_static as $ext) { - if ($ext['type'] == 'js') - $lines[] = self::js_link($ext['url']); - else if ($ext['type'] == 'css') - $lines[] = self::css_link($ext['url']); - } - } - if (!empty($this->head)) { - $lines = array_merge($lines, $this->head); - } - return implode("\n", $lines); - } - - public static function js_link($name, $version = null): string { - if ($version !== null) - $name .= '?'.$version; - return '<script src="'.$name.'" type="text/javascript"></script>'; - } - - public static function css_link($name, $version = null, $extra = null) { - if ($version !== null) - $name .= '?'.$version; - $s = '<link'; - if (is_array($extra)) { - if (!empty($extra['id'])) - $s .= ' id="'.$extra['id'].'"'; - } - $s .= ' rel="stylesheet" type="text/css"'; - if (is_array($extra) && !empty($extra['media'])) - $s .= ' media="'.$extra['media'].'"'; - $s .= ' href="'.$name.'"'; - $s .= '>'; - return $s; - } - - public function get_lang_keys() { - global $lang; - $keys = []; - if (!empty($this->lang_keys)) { - foreach ($this->lang_keys as $key) - $keys[$key] = $lang[$key]; - } - return $keys; - } - - public function render_not_found() { - http_response_code(404); - if (!is_xhr_request()) { - $this->render_page('404.twig'); - } else { - ajax_error(['code' => 404]); - } - } - - /** - * @param null|string $reason - */ - public function render_forbidden($reason = null) { - http_response_code(403); - if (!is_xhr_request()) { - $this->set(['reason' => $reason]); - $this->render_page('403.twig'); - } else { - $data = ['code' => 403]; - if (!is_null($reason)) - $data['reason'] = $reason; - ajax_error($data); - } - } - - public function must_revalidate() { - header('Cache-Control: no-store, no-cache, must-revalidate'); - } - - abstract public function render_page($template); - -} - -class web_tpl extends base_tpl { - - protected $alternate = false; - - public function __construct() { - global $config; - $templates = $config['templates']['web']; - parent::__construct( - ROOT.'/'. $templates['root'], - $config['twig_cache'] - ? ROOT.'/'.$templates['cache'] - : null - ); - } - - public function set_alternate($alt) { - $this->alternate = $alt; - } - - public function render_page($template) { - echo $this->_render_header(); - echo $this->_render_body($template); - echo $this->_render_footer(); - exit; - } - - public function _render_header() { - global $config; - $this->apply_globals(); - - $vars = [ - 'title' => $this->get_title(), - 'keywords' => $this->keywords, - 'description' => $this->description, - 'alternate' => $this->alternate, - 'static' => $this->get_head_html(), - ]; - return $this->do_render('header.twig', $vars); - } - - public function _render_body($template) { - return $this->do_render($template, $this->vars); - } - - public function _render_footer() { - $exec_time = microtime(true) - START_TIME; - $exec_time = round($exec_time, 4); - - $footer_vars = [ - 'exec_time' => $exec_time, - 'js' => !empty($this->js) ? implode("\n", $this->js) : '', - ]; - return $this->do_render('footer.twig', $footer_vars); - } - -} - -class Twig_MyExtension extends \Twig\Extension\AbstractExtension { - - public function getFilters() { - global $lang; - - return array( - new \Twig\TwigFilter('lang', 'lang'), - - new \Twig\TwigFilter('lang', function($key, array $args = []) use (&$lang) { - array_walk($args, function(&$item, $key) { - $item = htmlescape($item); - }); - array_unshift($args, $key); - return call_user_func_array([$lang, 'get'], $args); - }, ['is_variadic' => true]), - - new \Twig\TwigFilter('plural', function($text, array $args = []) use (&$lang) { - array_unshift($args, $text); - return call_user_func_array([$lang, 'num'], $args); - }, ['is_variadic' => true]), - - new \Twig\TwigFilter('format_number', function($number, array $args = []) { - array_unshift($args, $number); - return call_user_func_array('formatNumber', $args); - }, ['is_variadic' => true]), - - new \Twig\TwigFilter('short_number', function($number, array $args = []) { - array_unshift($args, $number); - return call_user_func_array('shortNumber', $args); - }, ['is_variadic']), - - new \Twig\TwigFilter('format_time', function($ts, array $args = []) { - array_unshift($args, $ts); - return call_user_func_array('formatTime', $args); - }, ['is_variadic' => true]), - - new \Twig\TwigFilter('format_duration', function($seconds, array $args = []) { - array_unshift($args, $seconds); - return call_user_func_array('formatDuration', $args); - }, ['is_variadic' => true]), - ); - } - - public function getTokenParsers() { - return [new JsTagTokenParser()]; - } - - public function getName() { - return 'lang'; - } - -} - -// Based on https://stackoverflow.com/questions/26170727/how-to-create-a-twig-custom-tag-that-executes-a-callback -class JsTagTokenParser extends \Twig\TokenParser\AbstractTokenParser { - - public function parse(\Twig\Token $token) { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - - // recovers all inline parameters close to your tag name - $params = array_merge([], $this->getInlineParams($token)); - - $continue = true; - while ($continue) { - // create subtree until the decideJsTagFork() callback returns true - $body = $this->parser->subparse(array ($this, 'decideJsTagFork')); - - // I like to put a switch here, in case you need to add middle tags, such - // as: {% js %}, {% nextjs %}, {% endjs %}. - $tag = $stream->next()->getValue(); - switch ($tag) { - case 'endjs': - $continue = false; - break; - default: - throw new \Twig\Error\SyntaxError(sprintf('Unexpected end of template. Twig was looking for the following tags "endjs" to close the "mytag" block started at line %d)', $lineno), -1); - } - - // you want $body at the beginning of your arguments - array_unshift($params, $body); - - // if your endjs can also contains params, you can uncomment this line: - // $params = array_merge($params, $this->getInlineParams($token)); - // and comment this one: - $stream->expect(\Twig\Token::BLOCK_END_TYPE); - } - - return new JsTagNode(new \Twig\Node\Node($params), $lineno, $this->getTag()); - } - - /** - * Recovers all tag parameters until we find a BLOCK_END_TYPE ( %} ) - * - * @param \Twig\Token $token - * @return array - */ - protected function getInlineParams(\Twig\Token $token) { - $stream = $this->parser->getStream(); - $params = array (); - while (!$stream->test(\Twig\Token::BLOCK_END_TYPE)) { - $params[] = $this->parser->getExpressionParser()->parseExpression(); - } - $stream->expect(\Twig\Token::BLOCK_END_TYPE); - return $params; - } - - /** - * Callback called at each tag name when subparsing, must return - * true when the expected end tag is reached. - * - * @param \Twig\Token $token - * @return bool - */ - public function decideJsTagFork(\Twig\Token $token) { - return $token->test(['endjs']); - } - - /** - * Your tag name: if the parsed tag match the one you put here, your parse() - * method will be called. - * - * @return string - */ - public function getTag() { - return 'js'; - } - -} - -class JsTagNode extends \Twig\Node\Node { - - public function __construct($params, $lineno = 0, $tag = null) { - parent::__construct(['params' => $params], [], $lineno, $tag); - } - - public function compile(\Twig\Compiler $compiler) { - $count = count($this->getNode('params')); - - $compiler->addDebugInfo($this); - $compiler - ->write('global $__tpl;') - ->raw(PHP_EOL); - - for ($i = 0; ($i < $count); $i++) { - // argument is not an expression (such as, a \Twig\Node\Textbody) - // we should trick with output buffering to get a valid argument to pass - // to the functionToCall() function. - if (!($this->getNode('params')->getNode($i) instanceof \Twig\Node\Expression\AbstractExpression)) { - $compiler - ->write('ob_start();') - ->raw(PHP_EOL); - - $compiler - ->subcompile($this->getNode('params')->getNode($i)); - - $compiler - ->write('$js = ob_get_clean();') - ->raw(PHP_EOL); - } - } - - $compiler - ->write('$__tpl->add_js($js);') - ->raw(PHP_EOL) - ->write('unset($js);') - ->raw(PHP_EOL); - } - -} - - - -/** - * @param $data - */ -function ajax_ok($data) { - ajax_response(['response' => $data]); -} - -/** - * @param $error - * @param int $code - */ -function ajax_error($error, $code = 200) { - ajax_response(['error' => $error], $code); -} - -/** - * @param $data - * @param int $code - */ -function ajax_response($data, $code = 200) { - header('Cache-Control: no-cache, must-revalidate'); - header('Pragma: no-cache'); - header('Content-Type: application/json; charset=utf-8'); - http_response_code($code); - echo jsonEncode($data); - exit; -}
\ No newline at end of file diff --git a/localwebsite/handlers/AuthHandler.php b/localwebsite/handlers/AuthHandler.php deleted file mode 100644 index 971f850..0000000 --- a/localwebsite/handlers/AuthHandler.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -class AuthHandler extends RequestHandler { - - protected function before_dispatch(string $method, string $act) { - return null; - } - - public function GET_auth() { - list($error) = $this->input('error'); - $this->tpl->set(['error' => $error]); - $this->tpl->set_title('Авторизация'); - $this->tpl->render_page('auth.twig'); - } - - public function POST_auth() { - list($username, $password) = $this->input('username, password'); - - $result = users::validatePassword($username, $password); - if (!$result) { - debugError('invalid login attempt: '.$_SERVER['REMOTE_ADDR'].', '.$_SERVER['HTTP_USER_AGENT'].", username=$username, password=$password"); - redirect('/auth/?error='.urlencode('неверный логин или пароль')); - } - - auth::setToken(pwhash($password)); - redirect('/'); - } - - public function GET_deauth() { - if (auth::id()) - auth::logout(); - - redirect('/'); - } - -} diff --git a/localwebsite/handlers/FakeRequestHandler.php b/localwebsite/handlers/FakeRequestHandler.php deleted file mode 100644 index 09e03b8..0000000 --- a/localwebsite/handlers/FakeRequestHandler.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -class FakeRequestHandler extends RequestHandler { - - public function apacheNotFound() { - http_response_code(404); - $uri = htmlspecialchars($_SERVER['REQUEST_URI']); - echo <<<EOF -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> -<html><head> -<title>404 Not Found</title> -</head><body> -<h1>Not Found</h1> -<p>The requested URL {$uri} was not found on this server.</p> -</body></html> -EOF; - exit; - } - -}
\ No newline at end of file diff --git a/localwebsite/handlers/MiscHandler.php b/localwebsite/handlers/MiscHandler.php deleted file mode 100644 index 4e7291e..0000000 --- a/localwebsite/handlers/MiscHandler.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -class MiscHandler extends RequestHandler -{ - - public function GET_sensors_page() { - global $config; - - $clients = []; - foreach ($config['temphumd_servers'] as $key => $params) { - $cl = new TemphumdClient(...$params); - $clients[$key] = $cl; - - $cl->readSensor(); - } - - $this->tpl->set(['sensors' => $clients]); - $this->tpl->set_title('Датчики'); - $this->tpl->render_page('sensors.twig'); - } - - public function GET_cams_stat() { - global $config; - list($ip, $port) = explode(':', $config['ipcam_server_api_addr']); - $body = jsonDecode(file_get_contents('http://'.$ip.':'.$port.'/api/timestamp/all')); - - header('Content-Type: text/plain'); - $date_fmt = 'd.m.Y H:i:s'; - - foreach ($body['response'] as $cam => $data) { - $fix = date($date_fmt, $data['fix']); - $start = date($date_fmt, $data['motion_start']); - $motion = date($date_fmt, $data['motion']); - echo "$cam:\n motion: $motion\n"; - echo " motion_start: $start\n"; - echo " fix: $fix\n\n"; - } - } - -} diff --git a/localwebsite/handlers/ModemHandler.php b/localwebsite/handlers/ModemHandler.php deleted file mode 100644 index 94ad75b..0000000 --- a/localwebsite/handlers/ModemHandler.php +++ /dev/null @@ -1,130 +0,0 @@ -<?php - -use libphonenumber\NumberParseException; -use libphonenumber\PhoneNumberFormat; -use libphonenumber\PhoneNumberUtil; - -class ModemHandler extends RequestHandler -{ - - public function GET_routing_smallhome_page() { - global $config; - - list($error) = $this->input('error'); - $upstream = self::getCurrentUpstream(); - - $current_upstream = [ - 'key' => $upstream, - 'label' => $config['modems'][$upstream]['label'] - ]; - - $this->tpl->set([ - 'error' => $error, - 'current' => $current_upstream, - 'modems' => $config['modems'], - ]); - $this->tpl->set_title('Маршрутизация'); - $this->tpl->render_page('routing_page.twig'); - } - - public function GET_routing_smallhome_switch() { - global $config; - list($new_upstream) = $this->input('upstream'); - if (!isset($config['modems'][$new_upstream])) - redirect('/routing/?error='.urlencode('invalid upstream')); - - $current_upstream = self::getCurrentUpstream(); - if ($current_upstream != $new_upstream) { - if ($new_upstream == 'mts-il') - $new_upstream_ip = '192.168.88.1'; - else - $new_upstream_ip = $config['modems'][$new_upstream]['ip']; - MyOpenWrtUtils::setUpstream($new_upstream_ip); - } - - redirect('/routing/'); - } - - public function GET_routing_ipsets_page() { - list($error) = $this->input('error'); - - $ip_sets = MyOpenWrtUtils::ipsetListAll(); - $this->tpl->set([ - 'sets' => $ip_sets, - 'error' => $error - ]); - $this->tpl->set_title('Маршрутизация: IP sets'); - $this->tpl->render_page('routing_ipsets_page.twig'); - } - - public function GET_routing_ipsets_del() { - list($set, $ip) = $this->input('set, ip'); - self::validateIpsetsInput($set, $ip); - - $output = MyOpenWrtUtils::ipsetDel($set, $ip); - - $url = '/routing/ipsets/'; - if ($output != '') - $url .= '?error='.urlencode($output); - redirect($url); - } - - public function POST_routing_ipsets_add() { - list($set, $ip) = $this->input('set, ip'); - self::validateIpsetsInput($set, $ip); - - $output = MyOpenWrtUtils::ipsetAdd($set, $ip); - - $url = '/routing/ipsets/'; - if ($output != '') - $url .= '?error='.urlencode($output); - redirect($url); - } - - public function GET_routing_dhcp_page() { - $overrides = config::get('dhcp_hostname_overrides'); - $leases = MyOpenWrtUtils::getDHCPLeases(); - foreach ($leases as &$lease) { - if ($lease['hostname'] == '?' && array_key_exists($lease['mac'], $overrides)) - $lease['hostname'] = $overrides[$lease['mac']]; - } - $this->tpl->set([ - 'leases' => $leases - ]); - $this->tpl->set_title('Маршрутизация: DHCP'); - $this->tpl->render_page('routing_dhcp_page.twig'); - } - - protected static function getCurrentUpstream() { - global $config; - - $default_route = MyOpenWrtUtils::getDefaultRoute(); - if ($default_route == '192.168.88.1') - $default_route = $config['modems']['mts-il']['ip']; - $upstream = null; - foreach ($config['modems'] as $modem_name => $modem_data) { - if ($default_route == $modem_data['ip']) { - $upstream = $modem_name; - break; - } - } - if (is_null($upstream)) - $upstream = $config['routing_default']; - - return $upstream; - } - - protected static function validateIpsetsInput($set, $ip) { - global $config; - - if (!isset($config['modems'][$set])) - redirect('/routing/ipsets/?error='.urlencode('invalid set: '.$set)); - - if (($slashpos = strpos($ip, '/')) !== false) - $ip = substr($ip, 0, $slashpos); - - if (!filter_var($ip, FILTER_VALIDATE_IP)) - redirect('/routing/ipsets/?error='.urlencode('invalid ip/network: '.$ip)); - } - -} diff --git a/localwebsite/handlers/RequestHandler.php b/localwebsite/handlers/RequestHandler.php deleted file mode 100644 index 136a23e..0000000 --- a/localwebsite/handlers/RequestHandler.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -class RequestHandler extends request_handler { - - /** @var web_tpl*/ - protected $tpl; - - public function __construct() { - global $__tpl; - $__tpl = new web_tpl(); - $this->tpl = $__tpl; - - $this->tpl->add_static('bootstrap.min.css'); - $this->tpl->add_static('bootstrap.min.js'); - $this->tpl->add_static('polyfills.js'); - $this->tpl->add_static('app.js'); - $this->tpl->add_static('app.css'); - - if (auth::id()) { - $this->tpl->set_global([ - 'auth_user' => auth::$authorizedUser - ]); - } - } - - public function dispatch(string $act) { - global $config; - $this->tpl->set_global([ - '__dev' => $config['is_dev'], - ]); - return parent::dispatch($act); - } - - protected function method_not_found(string $method, string $act) - { - global $config; - - if ($act != '404' && $config['is_dev']) - debugError(get_called_class() . ": act {$method}_{$act} not found."); - - if (!is_xhr_request()) - $this->tpl->render_not_found(); - else - ajax_error('unknown act "'.$act.'"', 404); - - } - - protected function before_dispatch(string $method, string $act) { - if (config::get('auth_need') && !auth::id()) - redirect('/auth/'); - } -}
\ No newline at end of file diff --git a/localwebsite/htdocs/.htaccess b/localwebsite/htdocs/.htaccess deleted file mode 100644 index c18b135..0000000 --- a/localwebsite/htdocs/.htaccess +++ /dev/null @@ -1,6 +0,0 @@ -RewriteEngine on - -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteCond %{REQUEST_URI} !=/server-status -RewriteRule ^.*$ /index.php [L,QSA] diff --git a/localwebsite/htdocs/favicon.ico b/localwebsite/htdocs/favicon.ico Binary files differdeleted file mode 100644 index d5ff579..0000000 --- a/localwebsite/htdocs/favicon.ico +++ /dev/null diff --git a/localwebsite/htdocs/index.php b/localwebsite/htdocs/index.php deleted file mode 100644 index cd32132..0000000 --- a/localwebsite/htdocs/index.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -require_once __DIR__.'/../init.php'; - -$router = new router; - -$router->add('routing/', 'Modem routing_smallhome_page'); -$router->add('routing/switch-small-home/', 'Modem routing_smallhome_switch'); -$router->add('routing/{ipsets,dhcp}/', 'Modem routing_${1}_page'); -$router->add('routing/ipsets/{add,del}/', 'Modem routing_ipsets_${1}'); - -$router->add('sms/', 'Modem sms'); -// $router->add('modem/set.ajax', 'Modem ctl_set_ajax'); - -// inverter -$router->add('inverter/set-osp/', 'Inverter set_osp'); - -// misc -$router->add('/', 'Misc main'); -$router->add('sensors/', 'Misc sensors_page'); -$router->add('cams/', 'Misc cams'); -$router->add('cams/([\d,]+)/', 'Misc cams id=$(1)'); -$router->add('cams/stat/', 'Misc cams_stat'); -$router->add('debug/', 'Misc debug'); - -// auth -$router->add('auth/', 'Auth auth'); -$router->add('deauth/', 'Auth deauth'); - - -$route = routerFind($router); -if ($route === false) - (new FakeRequestHandler)->dispatch('404'); - -list($handler, $act, $RouterInput) = $route; - -$handler_class = $handler.'Handler'; -if (!class_exists($handler_class)) { - debugError('index.php: class '.$handler_class.' not found'); - (new FakeRequestHandler)->dispatch('404'); -} - -(new $handler_class)->dispatch($act); diff --git a/localwebsite/templates-web/404.twig b/localwebsite/templates-web/404.twig deleted file mode 100644 index e28f5c5..0000000 --- a/localwebsite/templates-web/404.twig +++ /dev/null @@ -1 +0,0 @@ -Page Not Found
\ No newline at end of file diff --git a/localwebsite/templates-web/auth.twig b/localwebsite/templates-web/auth.twig deleted file mode 100644 index a0107b3..0000000 --- a/localwebsite/templates-web/auth.twig +++ /dev/null @@ -1,24 +0,0 @@ -{% include 'bc.twig' with { - history: [ - {text: "Авторизация" } - ] -} %} - -{% if error %} - <div class="mt-4 alert alert-danger"><b>Ошибка:</b> {{ error }}</div> -{% endif %} - - -<form method="post" action="/auth/"> - <div class="mt-2"> - <input type="text" name="username" placeholder="Логин" class="form-control"> - </div> - - <div class="mt-2"> - <input type="password" name="password" placeholder="Пароль" class="form-control"> - </div> - - <div class="mt-2"> - <button type="submit" class="btn btn-outline-primary">Войти</button> - </div> -</form>
\ No newline at end of file diff --git a/localwebsite/templates-web/bc.twig b/localwebsite/templates-web/bc.twig deleted file mode 100644 index b74ad40..0000000 --- a/localwebsite/templates-web/bc.twig +++ /dev/null @@ -1,12 +0,0 @@ -<nav aria-label="breadcrumb"> - <ol class="breadcrumb"> - <li class="breadcrumb-item"><a href="/">Главная</a></li> - {% for item in history %} - <li class="breadcrumb-item"{% if loop.last %} aria-current="page"{% endif %}> - {% if item.link %}<a href="{{ item.link }}">{% endif %} - {{ item.html ? item.html|raw : item.text }} - {% if item.link %}</a>{% endif %} - </li> - {% endfor %} - </ol> -</nav>
\ No newline at end of file diff --git a/localwebsite/templates-web/footer.twig b/localwebsite/templates-web/footer.twig deleted file mode 100644 index 8739f80..0000000 --- a/localwebsite/templates-web/footer.twig +++ /dev/null @@ -1,8 +0,0 @@ -{% if js %} - <script>{{ js|raw }}</script> -{% endif %} - -</div> -</body> -</html> -<!-- generated in {{ exec_time}} -->
\ No newline at end of file diff --git a/localwebsite/templates-web/header.twig b/localwebsite/templates-web/header.twig deleted file mode 100644 index 1a866e1..0000000 --- a/localwebsite/templates-web/header.twig +++ /dev/null @@ -1,15 +0,0 @@ -<!doctype html> -<html> -<head> - <title>{{ title }}</title> - <meta http-equiv="content-type" content="text/html; charset=utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> - <script> - window.onerror = function(error) { - window.console && console.error(error); - } - </script> - {{ static|raw }} -</head> -<body> -<div class="container py-3">
\ No newline at end of file diff --git a/localwebsite/templates-web/index.twig b/localwebsite/templates-web/index.twig deleted file mode 100644 index b28a078..0000000 --- a/localwebsite/templates-web/index.twig +++ /dev/null @@ -1,35 +0,0 @@ -<div class="container py-4"> - <nav aria-label="breadcrumb"> - <ol class="breadcrumb"> - <li class="breadcrumb-item active" aria-current="page">Главная</li> - </ol> - </nav> - - {% if auth_user %} - <div class="mb-4 alert alert-secondary"> - Вы авторизованы как <b>{{ auth_user.username }}</b>. <a href="/deauth/">Выйти</a> - </div> - {% endif %} - - <h6>Интернет</h6> - <ul class="list-group list-group-flush"> - <li class="list-group-item"><a href="/modem/">Модемы</a></li> - <li class="list-group-item"><a href="/routing/">Маршрутизация</a></li> - <li class="list-group-item"><a href="/sms/">SMS-сообщения</a></li> - </ul> - - <h6 class="mt-4">Другое</h6> - <ul class="list-group list-group-flush"> - <li class="list-group-item"><a href="/inverter/">Инвертор</a> (<a href="/inverter/?alt=1">alt</a>, <a href="{{ grafana_inverter_url }}">Grafana</a>)</li> - <li class="list-group-item"><a href="/pump/">Насос</a> (<a href="/pump/?alt=1">alt</a>)</li> - <li class="list-group-item"><a href="/sensors/">Датчики</a> (<a href="{{ grafana_sensors_url }}">Grafana</a>)</li> - </ul> - - <h6 class="mt-4"><a href="/cams/"><b>Все камеры</b></a> (<a href="/cams/?high=1">HQ</a>)</h6> - <ul class="list-group list-group-flush"> - {% for id, name in cameras %} - <li class="list-group-item"><a href="/cams/{{ id }}/">{{ name }}</a> (<a href="/cams/{{ id }}/?high=1">HQ</a>)</li> - {% endfor %} - <li class="list-group-item"><a href="/cams/stat/">Статистика</a></li> - </ul> -</div> diff --git a/localwebsite/templates-web/routing_dhcp_page.twig b/localwebsite/templates-web/routing_dhcp_page.twig deleted file mode 100644 index 12b837e..0000000 --- a/localwebsite/templates-web/routing_dhcp_page.twig +++ /dev/null @@ -1,11 +0,0 @@ -{% include 'routing_header.twig' with { - selected_tab: 'dhcp' -} %} - -{% for lease in leases %} - <div class="mt-3"> - <b>{{ lease.hostname }}</b> <span class="text-secondary">(exp: {{ lease.time_s }})</span><br/> - {{ lease.ip }}<br> - <span class="text-secondary">{{ lease.mac }}</span> - </div> -{% endfor %}
\ No newline at end of file diff --git a/localwebsite/templates-web/routing_header.twig b/localwebsite/templates-web/routing_header.twig deleted file mode 100644 index 7d07d0a..0000000 --- a/localwebsite/templates-web/routing_header.twig +++ /dev/null @@ -1,23 +0,0 @@ -{% include 'bc.twig' with { - history: [ - {text: "Маршрутизация" } - ] -} %} - -{% set routing_tabs = [ - {tab: 'smallhome', url: '/routing/', label: 'Интернет'}, - {tab: 'ipsets', url: '/routing/ipsets/', label: 'Правила'}, - {tab: 'dhcp', url: '/routing/dhcp/', label: 'DHCP'} -] %} - -<nav> - <div class="nav nav-tabs" id="nav-tab"> - {% for tab in routing_tabs %} - <a href="{{ tab.url }}" class="text-decoration-none"><button class="nav-link{% if tab.tab == selected_tab %} active{% endif %}" type="button">{{ tab.label }}</button></a> - {% endfor %} - </div> -</nav> - -{% if error %} - <div class="mt-4 alert alert-danger"><b>Ошибка:</b> {{ error }}</div> -{% endif %} diff --git a/localwebsite/templates-web/routing_ipsets_page.twig b/localwebsite/templates-web/routing_ipsets_page.twig deleted file mode 100644 index 5996e68..0000000 --- a/localwebsite/templates-web/routing_ipsets_page.twig +++ /dev/null @@ -1,29 +0,0 @@ -{% include 'routing_header.twig' with { - selected_tab: 'ipsets' -} %} - -<div class="mt-2 text-secondary"> - Таблицы расположены в порядке применения правил iptables. -</div> - -{% for set, ips in sets %} - <h6 class="text-primary mt-4">{{ set }}</h6> - - {% if ips %} - {% for ip in ips %} - <div>{{ ip }} (<a href="/routing/ipsets/del/?set={{ set }}&ip={{ ip }}" onclick="return confirm('Подтвердите удаление {{ ip }} из {{ set }}.')">удалить</a>)</div> - {% endfor %} - {% else %} - <span class="text-secondary">Нет записей.</span> - {% endif %} - - <div style="max-width: 300px"> - <form method="post" action="/routing/ipsets/add/"> - <input type="hidden" name="set" value="{{ set }}"> - <div class="input-group mt-2"> - <input type="text" name="ip" placeholder="x.x.x.x/y" class="form-control"> - <button type="submit" class="btn btn-outline-primary">Добавить</button> - </div> - </form> - </div> -{% endfor %}
\ No newline at end of file diff --git a/localwebsite/templates-web/routing_page.twig b/localwebsite/templates-web/routing_page.twig deleted file mode 100644 index 90437fd..0000000 --- a/localwebsite/templates-web/routing_page.twig +++ /dev/null @@ -1,17 +0,0 @@ -{% include 'routing_header.twig' with { - selected_tab: 'smallhome' -} %} - -<div class="mt-3 mb-3"> - Текущий апстрим: <b>{{ current.label }}</b> -</div> - -{% for key, modem in modems %} - {% if key != current.key %} - <div class="pt-1 pb-2"> - <a href="/routing/switch-small-home/?upstream={{ key }}"> - <button type="button" class="btn btn-primary">Переключить на <b>{{ modem.label }}</b></button> - </a> - </div> - {% endif %} -{% endfor %}
\ No newline at end of file diff --git a/localwebsite/templates-web/sensors.twig b/localwebsite/templates-web/sensors.twig deleted file mode 100644 index 1005dc0..0000000 --- a/localwebsite/templates-web/sensors.twig +++ /dev/null @@ -1,15 +0,0 @@ -{% include 'bc.twig' with { - history: [ - {text: "Датчики" } - ] -} %} - -{% for key, sensor in sensors %} - <h6 class="text-primary{% if not loop.first %} mt-4{% endif %}">{{ sensor.name }}</h6> - {% if sensor.hasTemperature() %} - <span class="text-secondary">Температура:</span> <b>{{ sensor.temp }}</b> °C<br> - {% endif %} - {% if sensor.hasHumidity() %} - <span class="text-secondary">Влажность:</span> <b>{{ sensor.humidity }}</b>% - {% endif %} -{% endfor %} |