From 8491a6daa0327d47a1cf46e8380d880f3ce69fd3 Mon Sep 17 00:00:00 2001 From: flooxik Date: Sat, 24 Oct 2026 16:53:46 +0300 Subject: [PATCH] =?UTF-8?q?v0.5.1:=20=D0=9F=D0=B5=D1=80=D0=B2=D0=B0=D1=8F?= =?UTF-8?q?=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 + api.php | 424 ++++++++++++++++++++++++ icons/apple-touch-icon.png | Bin 0 -> 9315 bytes icons/favicon-32.png | Bin 0 -> 6840 bytes icons/favicon.svg | 10 + icons/icon-192.png | Bin 0 -> 9476 bytes icons/icon-512.png | Bin 0 -> 15629 bytes icons/maskable-192.png | Bin 0 -> 8351 bytes icons/maskable-512.png | Bin 0 -> 12440 bytes index.html | 641 +++++++++++++++++++++++++++++++++++++ manifest.webmanifest | 14 + 11 files changed, 1095 insertions(+) create mode 100644 .gitignore create mode 100644 api.php create mode 100644 icons/apple-touch-icon.png create mode 100644 icons/favicon-32.png create mode 100644 icons/favicon.svg create mode 100644 icons/icon-192.png create mode 100644 icons/icon-512.png create mode 100644 icons/maskable-192.png create mode 100644 icons/maskable-512.png create mode 100644 index.html create mode 100644 manifest.webmanifest diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e8a044d --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/* +!/.gitignore +!/index.html +!/api.php +!/manifest.webmanifest +!/icons/ diff --git a/api.php b/api.php new file mode 100644 index 0000000..b25d132 --- /dev/null +++ b/api.php @@ -0,0 +1,424 @@ +getCode() ?: 400) : 500); + echo json_encode(['error' => $e instanceof ApiError ? $e->getMessage() : 'Ошибка сервера (подробности в логе PHP)'], JSON_UNESCAPED_UNICODE); +}); + +function out($d, int $c = 200): void { http_response_code($c); echo json_encode($d, JSON_UNESCAPED_UNICODE); exit; } +function rd(string $f, $def) { $p = D . $f; if (!is_file($p)) return $def; $j = json_decode((string)file_get_contents($p), true); return $j === null ? $def : $j; } +function wr(string $f, $d): void { + $p = D . $f; $t = $p . '.tmp'; + file_put_contents($t, json_encode($d, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); + rename($t, $p); +} +function str($v, int $max): string { return is_scalar($v) ? mb_substr(trim((string)$v), 0, $max) : ''; } +function new_id(string $p = ''): string { return $p . bin2hex(random_bytes(5)); } + +function load_ref(): array { + $r = rd('ref.json', []); + if (!isset($r['dicts'])) { + $r = ['dicts' => [ + ['id' => 'cats', 'name' => 'Категории', 'values' => array_values($r['cats'] ?? ['Категория 1', 'Категория 2', 'Категория 3'])], + ['id' => 'locs', 'name' => 'Расположения', 'values' => array_values($r['locs'] ?? ['Склад', 'Дом', 'Воронеж'])], + ], 'columns' => []]; + } + $r['columns'] = $r['columns'] ?? []; + if (dict_idx($r, 'ltypes') < 0) $r['dicts'][] = ['id' => 'ltypes', 'name' => 'Типы списков', 'values' => LIST_TYPES]; + return $r; +} +function std_cols(): array { + return [ + ['id' => 'name', 'name' => 'Название', 'type' => 'text', 'dict' => null], + ['id' => 'qty', 'name' => 'Кол-во', 'type' => 'number', 'dict' => null], + ['id' => 'cat', 'name' => 'Категория', 'type' => 'select', 'dict' => 'cats'], + ['id' => 'loc', 'name' => 'Расположение', 'type' => 'select', 'dict' => 'locs'], + ]; +} +function cols_map(array $ref): array { + $m = []; + foreach (array_merge(std_cols(), $ref['columns']) as $c) $m[$c['id']] = $c; + return $m; +} +function ltypes(array $ref): array { $i = dict_idx($ref, 'ltypes'); return $i < 0 ? LIST_TYPES : $ref['dicts'][$i]['values']; } +function ref_values(array $ref, string $id): array { $i = dict_idx($ref, $id); return $i < 0 ? [] : $ref['dicts'][$i]['values']; } +function dict_idx(array $ref, string $id): int { + foreach ($ref['dicts'] as $i => $d) if ($d['id'] === $id) return $i; + return -1; +} + +function norm_list(array $l): array { + if (!isset($l['kind'])) { + $l['kind'] = 'standard'; + $l['cols'] = STD_IDS; + $l['ltype'] = (($l['type'] ?? '') === 'box') ? 'Коробка' : ''; + $items = []; + foreach ($l['items'] ?? [] as $it) { + $items[] = ['id' => (string)($it['id'] ?? new_id()), 'v' => [ + 'name' => (string)($it['name'] ?? ''), 'qty' => (string)($it['qty'] ?? ''), + 'cat' => (string)($it['cat'] ?? ''), 'loc' => (string)($it['loc'] ?? '')]]; + } + $l['items'] = $items; + unset($l['type']); + } + $l['ltype'] = $l['ltype'] ?? ''; + return $l; +} +function load_lists(): array { return array_map('norm_list', rd('lists.json', [])); } +function list_idx(array $lists, string $id): int { + foreach ($lists as $i => $l) if ($l['id'] === $id) return $i; + return -1; +} +function same_cols(array $a, array $b): bool { + $a = $a['cols']; $b = $b['cols']; sort($a); sort($b); + return $a === $b; +} + +function map_items(array $items, array $dst, array $ref): array { + $out = []; + foreach ($items as $it) { + $v = []; + foreach ($dst['cols'] as $c) $v[$c] = (string)($it['v'][$c] ?? ''); + if ($dst['kind'] === 'standard') { + if ($v['name'] === '') $v['name'] = 'Без названия'; + if ($v['cat'] === '') $v['cat'] = (string)(ref_values($ref, 'cats')[0] ?? ''); + if ($v['loc'] === '') $v['loc'] = (string)(ref_values($ref, 'locs')[0] ?? ''); + } + $out[] = ['id' => new_id(), 'v' => $v]; + } + return $out; +} +function clean_val(array $col, $v, array $ref): string { + $v = is_scalar($v) ? trim((string)$v) : ''; + switch ($col['type']) { + case 'text': + return mb_substr($v, 0, 200); + case 'number': + if ($v === '') return ''; + if (!is_numeric($v) || strlen($v) > 20) fail('«' . $col['name'] . '»: нужно число'); + return $v; + case 'date': + if ($v === '') return ''; + if (!preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $v, $m) || !checkdate((int)$m[2], (int)$m[3], (int)$m[1])) fail('«' . $col['name'] . '»: неверная дата'); + return $v; + case 'check': + return ($v === '1' || $v === 'true') ? '1' : ''; + case 'select': + if ($v === '') return ''; + $di = dict_idx($ref, (string)$col['dict']); + if ($di < 0 || !in_array($v, $ref['dicts'][$di]['values'], true)) fail('«' . $col['name'] . '»: значения «' . mb_substr($v, 0, 40) . '» нет в справочнике'); + return $v; + } + return ''; +} +function clean_row($raw, array $cols, array $cm, array $ref, string $kind): array { + $raw = is_array($raw) ? $raw : []; + $v = []; $any = false; + foreach ($cols as $c) { + $v[$c] = clean_val($cm[$c], $raw[$c] ?? '', $ref); + if ($v[$c] !== '') $any = true; + } + if ($kind === 'standard') { + if ($v['name'] === '') fail('У предмета должно быть название'); + if ($v['cat'] === '' || $v['loc'] === '') fail('Укажите категорию и расположение'); + } elseif (!$any) fail('Строка пустая'); + return $v; +} +function clean_list(array $l, array $ref, ?array $old): array { + $id = (string)($l['id'] ?? ''); + if (!preg_match('/^[a-z0-9]{3,20}$/', $id)) fail('Некорректный список'); + $cm = cols_map($ref); + $lt = str($l['ltype'] ?? '', 60); + $oldLt = $old ? (string)($old['ltype'] ?? '') : ''; + $ltype = ($lt === '' || in_array($lt, ltypes($ref), true) || $lt === $oldLt) ? $lt : $oldLt; + if ($old) { + $kind = $old['kind']; $cols = $old['cols']; + } else { + $kind = (($l['kind'] ?? '') === 'custom') ? 'custom' : 'standard'; + if ($kind === 'standard') $cols = STD_IDS; + else { + $cols = array_values(array_unique(array_map('strval', (array)($l['cols'] ?? [])))); + if (!$cols || count($cols) > 12) fail('Выберите от 1 до 12 колонок'); + foreach ($cols as $c) if (!isset($cm[$c])) fail('Неизвестная колонка'); + } + } + $src = $l['items'] ?? null; + if (!is_array($src) || count($src) > 5000) fail('Некорректный список предметов'); + $items = []; + foreach ($src as $it) { + $iid = substr(preg_replace('/[^a-z0-9]/', '', strtolower((string)($it['id'] ?? ''))), 0, 20); + $items[] = ['id' => $iid !== '' ? $iid : new_id(), 'v' => clean_row($it['v'] ?? [], $cols, $cm, $ref, $kind)]; + } + return ['id' => $id, 'name' => str($l['name'] ?? '', 100) ?: 'Список', 'kind' => $kind, 'ltype' => $ltype, + 'cols' => $cols, 'final' => !empty($l['final']), 'items' => $items]; +} + +function touch_presence(string $u): void { + $pr = rd('presence.json', []); $now = time(); + if (($pr[$u] ?? 0) > $now - 15) return; + $pr[$u] = $now; + foreach ($pr as $k => $t) if ($t < $now - 86400) unset($pr[$k]); + wr('presence.json', $pr); +} + +function session_info(): array { + return ['user' => ['login' => $_SESSION['u'], 'role' => $_SESSION['role']], 'csrf' => $_SESSION['csrf'], 'mustChange' => !empty($_SESSION['must'])]; +} + +session_name('inv'); +session_set_cookie_params(['httponly' => true, 'samesite' => 'Strict', 'secure' => !empty($_SERVER['HTTPS'])]); +session_start(); + +if ($_SERVER['REQUEST_METHOD'] !== 'POST') out(['error' => 'POST only'], 405); +$in = json_decode((string)file_get_contents('php://input'), true) ?: []; +$a = (string)($in['a'] ?? ''); + +$lock = fopen(D . '.lock', 'c'); flock($lock, LOCK_EX); + +if ($a === 'login') { + $login = mb_strtolower(str($in['login'] ?? '', 50)); + $ip = $_SERVER['REMOTE_ADDR'] ?? '?'; + $buckets = [[hash('sha256', "$ip|$login"), 5], [hash('sha256', $ip), 20]]; + $at = rd('attempts.json', []); $now = time(); + foreach ($at as $k => $v) if (($v['t'] ?? 0) < $now - 3600 && ($v['until'] ?? 0) < $now) unset($at[$k]); + foreach ($buckets as [$k]) if (($at[$k]['until'] ?? 0) > $now) { wr('attempts.json', $at); out(['error' => 'Слишком много попыток. Подождите несколько минут.'], 429); } + $users = rd('users.json', ['users' => []]); $u = null; $ui = -1; + foreach ($users['users'] as $i => $x) if ($x['login'] === $login) { $u = $x; $ui = $i; } + $pw = (string)($in['password'] ?? ''); + $ok = password_verify($pw, $u['hash'] ?? password_hash('dummy', PASSWORD_DEFAULT)) && $u !== null; + if (!$ok) { + foreach ($buckets as [$k, $lim]) { + $n = ($at[$k]['n'] ?? 0) + 1; + $at[$k] = ['n' => $n, 't' => $now, 'until' => $n >= $lim ? $now + 600 : 0]; + if ($n >= $lim) $at[$k]['n'] = 0; + } + wr('attempts.json', $at); usleep(500000); + out(['error' => 'Неверный логин или пароль'], 401); + } + foreach ($buckets as [$k]) unset($at[$k]); + wr('attempts.json', $at); + if (password_needs_rehash($u['hash'], PASSWORD_DEFAULT)) { $users['users'][$ui]['hash'] = password_hash($pw, PASSWORD_DEFAULT); wr('users.json', $users); } + session_regenerate_id(true); + $_SESSION = ['u' => $u['login'], 'role' => $u['role'], 'csrf' => bin2hex(random_bytes(16)), 'must' => !empty($u['must_change'])]; + touch_presence($u['login']); + out(session_info()); +} + +if (empty($_SESSION['u'])) out(['error' => 'auth'], 401); +touch_presence((string)$_SESSION['u']); +if ($a === 'me') out(session_info()); +if (!hash_equals($_SESSION['csrf'], (string)($_SERVER['HTTP_X_CSRF'] ?? ''))) out(['error' => 'CSRF'], 403); +$admin = $_SESSION['role'] === 'admin'; +if (!empty($_SESSION['must']) && !in_array($a, ['logout', 'passwd'], true)) fail('Сначала смените пароль', 403); +$ref = load_ref(); + +switch ($a) { +case 'ping': + out(['ok' => true]); + +case 'logout': + $pr = rd('presence.json', []); unset($pr[$_SESSION['u']]); wr('presence.json', $pr); + $_SESSION = []; session_destroy(); out(['ok' => true]); + +case 'passwd': + $users = rd('users.json', ['users' => []]); + $new = (string)($in['new'] ?? ''); + $oldPw = (string)($in['old'] ?? ''); + if (mb_strlen($new) < 8) fail('Новый пароль — не короче 8 символов'); + if ($new === $oldPw) fail('Новый пароль должен отличаться от текущего'); + foreach ($users['users'] as $i => $x) if ($x['login'] === $_SESSION['u']) { + if (!password_verify($oldPw, $x['hash'])) fail('Неверный текущий пароль', 403); + $users['users'][$i]['hash'] = password_hash($new, PASSWORD_DEFAULT); + unset($users['users'][$i]['must_change']); + wr('users.json', $users); $_SESSION['must'] = false; out(['ok' => true]); + } + fail('Пользователь не найден', 404); + +case 'state': + $r = ['ref' => $ref, 'std' => std_cols(), 'listTypes' => ltypes($ref)]; + if (!$admin) $r['lists'] = load_lists(); + out($r); + +case 'users': + if (!$admin) fail('forbidden', 403); + $pr = rd('presence.json', []); $now = time(); $res = []; + foreach (rd('users.json', ['users' => []])['users'] as $x) + $res[] = ['login' => $x['login'], 'role' => $x['role'] ?? 'user', 'online' => ($pr[$x['login']] ?? 0) > $now - ONLINE_SEC]; + out(['users' => $res]); + +case 'user_add': + if (!$admin) fail('forbidden', 403); + $nl = mb_strtolower(str($in['login'] ?? '', 30)); $np = (string)($in['password'] ?? ''); + if (!preg_match('/^[a-z0-9_.-]{2,30}$/', $nl)) fail('Логин: 2–30 символов, латинские буквы, цифры и знаки _ . -'); + if (mb_strlen($np) < 8) fail('Пароль — не короче 8 символов'); + $users = rd('users.json', ['users' => []]); + foreach ($users['users'] as $x) if ($x['login'] === $nl) fail('Такой логин уже есть'); + if (count($users['users']) >= 50) fail('Слишком много пользователей'); + $users['users'][] = ['login' => $nl, 'role' => 'user', 'hash' => password_hash($np, PASSWORD_DEFAULT)]; + wr('users.json', $users); out(['ok' => true]); + +case 'list_save': + if ($admin) fail('forbidden', 403); + $lists = load_lists(); + $id = (string)($in['list']['id'] ?? ''); + $i = list_idx($lists, $id); + $new = clean_list((array)($in['list'] ?? []), $ref, $i >= 0 ? $lists[$i] : null); + if ($i >= 0) $lists[$i] = $new; else array_unshift($lists, $new); + wr('lists.json', $lists); out(['ok' => true, 'list' => $new]); + +case 'list_delete': + if ($admin) fail('forbidden', 403); + wr('lists.json', array_values(array_filter(load_lists(), fn($x) => $x['id'] !== ($in['id'] ?? '')))); + out(['ok' => true]); + +case 'transfer': + if ($admin) fail('forbidden', 403); + $lists = load_lists(); + $si = list_idx($lists, (string)($in['from'] ?? '')); + if ($si < 0) fail('Исходный список не найден', 404); + $ids = array_map('strval', (array)($in['ids'] ?? [])); + $picked = array_values(array_filter($lists[$si]['items'], fn($it) => in_array($it['id'], $ids, true))); + if (!$picked) fail('Не выбрано ни одного предмета'); + $copy = fn() => array_map(fn($it) => ['id' => new_id(), 'v' => $it['v']], $picked); + $move = !empty($in['move']); + if ($move && !empty($lists[$si]['final'])) fail('Исходный список закрыт итогом — перенос с удалением невозможен'); + $to = (array)($in['to'] ?? []); + if (isset($to['existing'])) { + $ti = list_idx($lists, (string)$to['existing']); + if ($ti < 0 || $ti === $si) fail('Список назначения не найден', 404); + if (!empty($lists[$ti]['final'])) fail('Список назначения закрыт итогом'); + if (!in_array('name', $lists[$si]['cols'], true) || !in_array('name', $lists[$ti]['cols'], true)) fail('В обоих списках должна быть колонка «Название»'); + if (!same_cols($lists[$si], $lists[$ti]) && empty($in['confirm'])) fail('Колонки списков отличаются, нужно подтверждение'); + if (count($lists[$ti]['items']) + count($picked) > 5000) fail('Слишком много предметов в списке'); + $lists[$ti]['items'] = array_merge($lists[$ti]['items'], map_items($picked, $lists[$ti], $ref)); + $target = $lists[$ti]['id']; + } else { + $name = str($to['name'] ?? '', 100); + $lt = (string)($to['ltype'] ?? ''); + if ($name === '') fail('Укажите название списка'); + if (!in_array($lt, ltypes($ref), true)) fail('Выберите тип списка'); + $nl = ['id' => new_id('l'), 'name' => $name, 'kind' => $lists[$si]['kind'], 'ltype' => $lt, + 'cols' => $lists[$si]['cols'], 'final' => false, 'items' => $copy()]; + array_unshift($lists, $nl); $si++; + $target = $nl['id']; + } + if ($move) { + $lists[$si]['items'] = array_values(array_filter($lists[$si]['items'], fn($it) => !in_array($it['id'], $ids, true))); + } + wr('lists.json', $lists); + out(['ok' => true, 'target' => $target, 'lists' => $lists]); + +case 'dict_op': + if (!$admin) fail('forbidden', 403); + $op = (string)($in['op'] ?? ''); $did = (string)($in['id'] ?? ''); + $v = str($in['value'] ?? '', 60); $old = (string)($in['old'] ?? ''); + if ($op === 'add_dict') { + if ($v === '') fail('Введите название справочника'); + foreach ($ref['dicts'] as $d) if (mb_strtolower($d['name']) === mb_strtolower($v)) fail('Справочник с таким названием уже есть'); + if (count($ref['dicts']) >= 50) fail('Слишком много справочников'); + $ref['dicts'][] = ['id' => new_id('d'), 'name' => $v, 'values' => []]; + wr('ref.json', $ref); out(['ref' => $ref]); + } + $di = dict_idx($ref, $did); + if ($di < 0) fail('Справочник не найден', 404); + $vals = $ref['dicts'][$di]['values']; + $core = in_array($did, ['cats', 'locs', 'ltypes'], true); + $usedCols = array_keys(array_filter(cols_map($ref), fn($c) => $c['type'] === 'select' && $c['dict'] === $did)); + $lists = load_lists(); + switch ($op) { + case 'rename_dict': + if ($v === '') fail('Введите название'); + foreach ($ref['dicts'] as $d) if ($d['id'] !== $did && mb_strtolower($d['name']) === mb_strtolower($v)) fail('Справочник с таким названием уже есть'); + $ref['dicts'][$di]['name'] = $v; break; + case 'delete_dict': + if ($core) fail('Встроенный справочник удалить нельзя'); + if ($usedCols) fail('Справочник используется в колонках — сначала удалите или измените их'); + array_splice($ref['dicts'], $di, 1); break; + case 'add_value': + if ($v === '' || in_array($v, $vals, true)) fail('Пустое или повторяющееся значение'); + $ref['dicts'][$di]['values'][] = $v; break; + case 'rename_value': + $i = array_search($old, $vals, true); + if ($i === false || $v === '' || ($v !== $old && in_array($v, $vals, true))) fail('Пустое или повторяющееся значение'); + $ref['dicts'][$di]['values'][$i] = $v; + foreach ($lists as &$l) foreach ($l['items'] as &$it) foreach ($usedCols as $c) if (($it['v'][$c] ?? null) === $old) $it['v'][$c] = $v; + unset($l, $it); + if ($did === 'ltypes') foreach ($lists as &$l) if (($l['ltype'] ?? '') === $old) $l['ltype'] = $v; + unset($l); wr('lists.json', $lists); break; + case 'delete_value': + $i = array_search($old, $vals, true); + if ($i === false) fail('Не найдено', 404); + if ($core && count($vals) < 2) fail('Нельзя удалить последнее значение'); + if ($did === 'ltypes') foreach ($lists as $l) if (($l['ltype'] ?? '') === $old) fail("Тип «{$old}» назначен спискам (например, «{$l['name']}»). Сначала смените им тип."); + foreach ($lists as $l) foreach ($l['items'] as $it) foreach ($usedCols as $c) if (($it['v'][$c] ?? null) === $old) fail("«{$old}» используется в предметах"); + array_splice($ref['dicts'][$di]['values'], (int)$i, 1); break; + default: fail('op'); + } + wr('ref.json', $ref); out(['ref' => $ref]); + +case 'col_op': + if (!$admin) fail('forbidden', 403); + $op = (string)($in['op'] ?? ''); $cid = (string)($in['id'] ?? ''); + $name = str($in['name'] ?? '', 60); $type = (string)($in['type'] ?? ''); $dict = $in['dict'] ?? null; + $lists = load_lists(); + $usedIn = function (string $id) use ($lists) { return array_values(array_map(fn($l) => $l['name'], array_filter($lists, fn($l) => in_array($id, $l['cols'], true)))); }; + $checkName = function () use ($ref, $name, $cid) { + if ($name === '') fail('Введите название колонки'); + foreach (cols_map($ref) as $c) if ($c['id'] !== $cid && mb_strtolower($c['name']) === mb_strtolower($name)) fail('Колонка с таким названием уже есть'); + }; + $checkType = function () use ($ref, $type, &$dict) { + if (!in_array($type, COL_TYPES, true)) fail('Неверный тип колонки'); + if ($type === 'select') { if ((string)$dict === 'ltypes' || dict_idx($ref, (string)$dict) < 0) fail('Выберите справочник для списка'); $dict = (string)$dict; } + else $dict = null; + }; + if ($op === 'add') { + $checkName(); $checkType(); + if (count($ref['columns']) >= 50) fail('Слишком много колонок'); + $ref['columns'][] = ['id' => new_id('c'), 'name' => $name, 'type' => $type, 'dict' => $dict]; + } else { + $ci = -1; foreach ($ref['columns'] as $i => $c) if ($c['id'] === $cid) $ci = $i; + if ($ci < 0) fail('Колонка не найдена', 404); + if ($op === 'update') { + $checkName(); + $c = $ref['columns'][$ci]; + $dict = $dict === '' ? null : $dict; + if ($type !== $c['type'] || ($type === 'select' && (string)$dict !== (string)$c['dict'])) { + if ($u = $usedIn($cid)) fail('Тип колонки нельзя менять: она уже используется в списках (' . implode(', ', array_slice($u, 0, 3)) . ')'); + $checkType(); + $ref['columns'][$ci]['type'] = $type; $ref['columns'][$ci]['dict'] = $dict; + } + $ref['columns'][$ci]['name'] = $name; + } elseif ($op === 'delete') { + if ($u = $usedIn($cid)) fail('Колонка используется в списках: ' . implode(', ', array_slice($u, 0, 3))); + array_splice($ref['columns'], $ci, 1); + } else fail('op'); + } + wr('ref.json', $ref); out(['ref' => $ref]); + +default: fail('unknown'); +} diff --git a/icons/apple-touch-icon.png b/icons/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9fa5b8e35311446508fa5199866118a8eecb873d GIT binary patch literal 9315 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 B4OjpG literal 0 HcmV?d00001 diff --git a/icons/favicon.svg b/icons/favicon.svg new file mode 100644 index 0000000..05decc0 --- /dev/null +++ b/icons/favicon.svg @@ -0,0 +1,10 @@ +AAAWgmp1bWIAAAAeanVtZGMycGEAEQAQgAAAqgA4m3EDYzJwYQAAABZcanVtYgAAAEdqdW1kYzJtYQARABCAAACqADibcQN1cm46YzJwYTplMjA2MjUxMy03MmI2LTQ0NTUtODY5ZC0xNjBlOTIzNTQ2YTgAAAADl2p1bWIAAAApanVtZGMyYXMAEQAQgAAAqgA4m3EDYzJwYS5hc3NlcnRpb25zAAAAALxqdW1iAAAARGp1bWRjYm9yABEAEIAAAKoAOJtxE2MycGEuaW5ncmVkaWVudC52MwAAAAAYYzJzaJdrAJ9pjMJgmDwhoEK922sAAABwY2JvcqNpZGM6Zm9ybWF0bWltYWdlL3N2Zyt4bWxqaW5zdGFuY2VJRHgseG1wOmlpZDo3YTY2ODQ4My03ZTdiLTQ4ZDQtYmIxYy03YmNiMmZmZjQyYWZscmVsYXRpb25zaGlwaHBhcmVudE9mAAAB4mp1bWIAAABBanVtZGNib3IAEQAQgAAAqgA4m3ETYzJwYS5hY3Rpb25zLnYyAAAAABhjMnNo9AqJugjLK9Tv/YAI1ABNiwAAAZljYm9yomdhY3Rpb25zgqJmYWN0aW9ua2MycGEub3BlbmVkanBhcmFtZXRlcnOha2luZ3JlZGllbnRzgaJjdXJseC1zZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmluZ3JlZGllbnQudjNkaGFzaFggCHVhv9Wa+acWK2oozzvNikmNwIltospBqVgUpTLKYSqkZmFjdGlvbngdY29tLmFudGhyb3BpYy5jbGF1ZGUucHJvdmlkZWRqcGFyYW1ldGVyc6F4H2NvbS5hbnRocm9waWMub3JpZ2luLWNvbmZpZGVuY2VndW5rbm93bmtkZXNjcmlwdGlvbnhmQ2xhdWRlIHByb3ZpZGVkIHRoaXMgZmlsZSBhdCB0aGUgcmVxdWVzdCBvZiBhIHVzZXIgYW5kIG1heSBoYXZlIGNyZWF0ZWQgb3IgbW9kaWZpZWQgdGhlIGZpbGUgY29udGVudHMubXNvZnR3YXJlQWdlbnShZG5hbWVmQ2xhdWRlcmFsbEFjdGlvbnNJbmNsdWRlZPUAAADIanVtYgAAAEBqdW1kY2JvcgARABCAAACqADibcRNjMnBhLmhhc2guZGF0YQAAAAAYYzJzaEfup5O1mG+ZNM6zR6v68J4AAACAY2JvcqVjYWxnZnNoYTI1NmNwYWRNAAAAAAAAAAAAAAAAAGRoYXNoWCAq9XrR10PKA1R/sEMn0TuNePa93vZiF5gt00g7qOhVzmRuYW1lbmp1bWJmIG1hbmlmZXN0amV4Y2x1c2lvbnOBomVzdGFydBiiZmxlbmd0aBkeBAAAAj5qdW1iAAAAJ2p1bWRjMmNsABEAEIAAAKoAOJtxA2MycGEuY2xhaW0udjIAAAACD2Nib3KlY2FsZ2ZzaGEyNTZpc2lnbmF0dXJleE1zZWxmI2p1bWJmPS9jMnBhL3VybjpjMnBhOmUyMDYyNTEzLTcyYjYtNDQ1NS04NjlkLTE2MGU5MjM1NDZhOC9jMnBhLnNpZ25hdHVyZWppbnN0YW5jZUlEeCx4bXA6aWlkOmY3ZDdiZWRjLTdjMmQtNGYzNy04MmEyLTBjY2VhOGQ5MzMxZHJjcmVhdGVkX2Fzc2VydGlvbnODomN1cmx4LXNlbGYjanVtYmY9YzJwYS5hc3NlcnRpb25zL2MycGEuaW5ncmVkaWVudC52M2RoYXNoWCAIdWG/1Zr5pxYraijPO82KSY3AiW2iykGpWBSlMsphKqJjdXJseCpzZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmFjdGlvbnMudjJkaGFzaFgg5kL1Q39WQLzUai1hYfRLmWUxowBTRxqDhxvbY9ISIAaiY3VybHgpc2VsZiNqdW1iZj1jMnBhLmFzc2VydGlvbnMvYzJwYS5oYXNoLmRhdGFkaGFzaFgg6Qfv+m1sS8HxvFyILudyNEAEc8MDNPI9sgYGcc4kdI10Y2xhaW1fZ2VuZXJhdG9yX2luZm+jZG5hbWVvQW50aHJvcGljIEZpbGVzZ3ZlcnNpb25lMS4wLjBrc3BlY1ZlcnNpb25lMi40LjAAABA4anVtYgAAAChqdW1kYzJjcwARABCAAACqADibcQNjMnBhLnNpZ25hdHVyZQAAABAIY2JvctKEWQISogEmGCFZAgowggIGMIIBjaADAgECAhRA5aAK7sI50L64g/oGQgU9Z1UTADAKBggqhkjOPQQDAzBJMRcwFQYDVQQKEw5BbnRocm9waWMsIFBCQzEuMCwGA1UEAxMlQW50aHJvcGljIENvbnRlbnQgQ3JlZGVudGlhbHMgUm9vdCBDQTAeFw0yNjA4MDcxODQzNTZaFw0yODA4MDYxOTQzNTZaMEQxFzAVBgNVBAoTDkFudGhyb3BpYywgUEJDMSkwJwYDVQQDEyBBbnRocm9waWMgQ2xhdWRlIENvbnRlbnQgU2lnbmluZzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJh6CmvLUBgFFNU0vUKlOVtE6djd17L5SuwX0LemFisBM3dkd/3cyjxFA3Qo5S46fX0/ihY0VZ7mfb9KF703t5OjWDBWMA4GA1UdDwEB/wQEAwIHgDAVBgNVHSUEDjAMBgorBgEEAYPoXgIBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUzlHiBIFOZFsj+OPEz5o+nMHXXMIwCgYIKoZIzj0EAwMDZwAwZAIwMXMdFJ4BetLLVY7ORuE9noqbbAZOZn/aArXyTwFAZfKrPzxF2vPoJNf1+UCdg1XGAjBwX1zd9WGqYkqmL5SFqw1QySjr1zJfpJM9+1rdDwSPLMOPOjKuiXjoU/pUUeG9RwmhY3BhZFkNngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPZYQIdmEe5b8rZbxQ1LPQEfhfOCO+Px9LYOVg09a9dHkJk561Gm9KQrXaR5p0joKg/Y/XEsOlYKe+2y0ysxBLajkTg= + + + + + + + + + diff --git a/icons/icon-192.png b/icons/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..0fff29d6b091e43c88877a76dc2174081ce1bf2d GIT binary patch literal 9476 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
;l*0dxG_vC=2H-IO%mJ#qgLvjjjb$+xRq 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 + + +inventorEZ + + + + + + + + +
inventorEZ
+ +
+
+
+
+ + + diff --git a/manifest.webmanifest b/manifest.webmanifest new file mode 100644 index 0000000..752d7a4 --- /dev/null +++ b/manifest.webmanifest @@ -0,0 +1,14 @@ +{ + "name": "inventorEZ", + "short_name": "inventorEZ", + "start_url": "./", + "display": "standalone", + "background_color": "#f6efdf", + "theme_color": "#f6efdf", + "icons": [ + {"src": "icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any"}, + {"src": "icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any"}, + {"src": "icons/maskable-192.png", "sizes": "192x192", "type": "image/png", "purpose": "maskable"}, + {"src": "icons/maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable"} + ] +}