starting farting

This commit is contained in:
2025-11-03 15:09:59 +03:00
parent d454c29ee9
commit 677384c153
22 changed files with 1369 additions and 95 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "damper.mjs"]
path = damper.mjs
url = https://git.svoboda.works/mirzaev/damper.mjs

View File

@@ -27,7 +27,10 @@
"mirzaev/baza": "^3.3",
"twig/twig": "^3.2",
"twig/extra-bundle": "^3.7",
"twig/intl-extra": "^3.10"
"twig/intl-extra": "^3.10",
"mirzaev/languages": "^1.0",
"mirzaev/currencies": "^1.0",
"svoboda/time": "^1.0"
},
"autoload": {
"psr-4": {

1
damper.mjs Submodule

Submodule damper.mjs added at 81d208b964

View File

@@ -1,10 +1,5 @@
#!/bin/bash
if [ -d author/project ]; then
mv author/project author/site
fi
if [ -d author ]; then
mv author zharko
fi
#!/bin/fish
if not test -L zharko/site/system/public/js/modules/damper.mjs
ln -s ../../../../../../damper.mjs/damper.mjs zharko/site/system/public/js/modules/damper.mjs;
end

View File

@@ -0,0 +1,120 @@
<?php
declare(strict_types=1);
namespace zharko\site\controllers;
// Files of the project
use zharko\site\controllers\core;
// Framework for PHP
use mirzaev\minimal\http\enumerations\content,
mirzaev\minimal\http\enumerations\method,
mirzaev\minimal\http\enumerations\status;
// Library for languages support
use mirzaev\languages\language;
/**
* Account
*
* @package zharko\site\controllers
*
* @param array $errors Registry of errors
*
* @method null index() Main page
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class account extends core
{
/**
* Errors
*
* @var array $errors Registry of errors
*/
protected array $errors = [
'system' => [],
'account' => []
];
/**
* Registration page
*
* @param string|null $mail Mail
* @param string|null $password Password
*
* @return null
*/
public function registration(
?string $mail = null,
?string $password = null
): null {
if ($this->request->method === method::put) {
// PUT (creating the account)
if (str_contains($this->request->headers['accept'] ?? '', content::json->value)) {
// Request for JSON response
// Filtering the mail value
preg_match('/([^@\r\n]+)@([^@\r\n\.]+)\.([^@\r\n\.]+)/u', 'vova@mail.ru', $matches);
$mail = $matches[1] . '@' . $matches[2] . '.' . $matches[3];
unset($matches);
// Filtering the password value
preg_match_all('/[^a-fA-F0-9]+/Uu', $password, $password_restricted);
if (empty($mail)) {
// Mail is empty
} else if (empty($password)) {
// Password is empty
} else if (!empty($password_restricted)) {
// Pasword has restricted symbols
} else {
// All parameters validated
// Creating the account
$this->model->write(mail: $mail, password: $password, errors: $this->errors['account']);
// Exit (success)
return null;
}
// Exit (fail)
return null;
}
} else if ($this->request->method === method::get) {
// GET (sending the HTML-document for registration)
if (str_contains($this->request->headers['accept'] ?? '', content::html->value)) {
// Request for HTML response
// Render page
$page = $this->view->render('pages/account/registration.html');
// Sending response
$this->response
->start()
->clean()
->sse()
->write($page)
->validate($this->request)
?->body()
->end();
// Deinitializing rendered page
unset($page);
// Exit (success)
return null;
}
}
// Exit (fail)
return null;
}
}

View File

@@ -7,8 +7,8 @@ namespace zharko\site\controllers;
// Files of the project
use zharko\site\views\templater,
zharko\site\models\core as models,
zharko\site\models\account,
zharko\site\models\enumerations\language;
zharko\site\models\session,
zharko\site\models\account;
// Framework for PHP
use mirzaev\minimal\core as minimal,
@@ -16,6 +16,9 @@ use mirzaev\minimal\core as minimal,
mirzaev\minimal\http\response,
mirzaev\minimal\http\enumerations\status;
// Library for languages support
use mirzaev\languages\language;
/**
* Controllers core
*
@@ -30,10 +33,16 @@ use mirzaev\minimal\core as minimal,
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
* @author zharko <mail@domain.zone>
*/
class core extends controller
{
/**
* Session
*
* @var session $session Session
*/
protected session $session;
/**
* Account
*

View File

@@ -22,7 +22,6 @@ use mirzaev\minimal\http\enumerations\content,
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
* @author zharko <mail@domain.zone>
*/
final class index extends core
{

View File

@@ -5,7 +5,20 @@ declare(strict_types=1);
namespace zharko\site\models;
// Files of the project
use zharko\site\models\core
use zharko\site\models\core;
// Library for languages
use mirzaev\languages\language;
// Baza database
use mirzaev\baza\database,
mirzaev\baza\column,
mirzaev\baza\record,
mirzaev\baza\enumerations\encoding,
mirzaev\baza\enumerations\type;
// Svoboda time
use svoboda\time\statement as svoboda;
// Built-in libraries
use Exception as exception,
@@ -28,7 +41,7 @@ class account extends core
*
* @var string database Path to the database file
*/
protected string $file = DATABASES . DIRECTORY_SEPARATOR . 'account.baza';
protected string $file = DATABASES . DIRECTORY_SEPARATOR . 'accounts.baza';
/**
* Database
@@ -66,6 +79,52 @@ class account extends core
->connect($this->file);
}
/**
* Write
*
* Create the account record in the database
*
* @return int|false The record identifier, if created
*/
public function write(
string $domain = '',
string $name = '',
string $mail = '',
string $password = '',
language $language = language::en,
&$errors = []
): int|false {
// Initializing the identifier
$identifier = $this->database->count() + 1;
// Calculating the current timestamp
$timestamp = svoboda::timestamp();
// Initializing the record
$record = $this->database->record(
$identifier,
$domain,
$name,
$mail,
$password,
'',
'',
$language->value,
1,
1,
0,
0,
$timestamp,
$timestamp
);
// Creating the record in the database
$created = $this->database->write($record);
// Exit (success)
return $created ? $identifier : false;
}
/**
* Authorization
*
@@ -88,16 +147,16 @@ class account extends core
// Found the account record
if (
$account->name_first !== $telegram->getFirstName() ||
$account->name_second !== $telegram->getLastName() ||
$account->domain !== $telegram->getUsername()
$account->name_first !== $telegram->getFirstName() ||
$account->name_second !== $telegram->getLastName() ||
$account->domain !== $telegram->getUsername()
) {
// The telegram account was updated
// Updating the account in the database
$updated = $this->database->read(
filter: fn(record $record) => $record->identifier_telegram === $telegram->getId(),
update: function (record &$record) use ($telegram){
update: function (record &$record) use ($telegram) {
// Writing new values into the record
$record->name_first = $telegram->getFirstName();
$record->name_second = $telegram->getLastName();
@@ -151,4 +210,3 @@ class account extends core
}
}
}

View File

@@ -1,62 +0,0 @@
<?php
declare(strict_types=1);
namespace zharko\site\models\enumerations;
/**
* Language
*
* Types of languages by ISO 639-1 standart
*
* @package zharko\site\models\enumerations
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
* @author zharko <mail@domain.zone>
*/
enum language
{
case en;
case ru;
/**
* Label
*
* Initialize label of the language
*
* @param language|null language Language into which to translate
*
* @return string Translated label of the language
*/
public function label(?language $language = language::en): string
{
// Exit (success)
return match ($this) {
language::en => match ($language) {
language::en => 'English',
language::ru => 'Английский'
},
language::ru => match ($language) {
language::en => 'Russian',
language::ru => 'Русский'
}
};
}
/**
* Flag
*
* Initialize the flag emoji of the language
*
* @return string The flag emoji of the language
*/
public function flag(): string
{
// Exit (success)
return match ($this) {
language::en => '🇺🇸',
language::ru => '🇷🇺'
};
}
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace zharko\site\models\enumerations;
/**
* Types of session verification
*
* @package zharko\site\models\enumerations
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
enum session
{
case blake2b;
case blake2b_or_address;
}

View File

@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace zharko\site\models\middlewares;
// Files of the project
use zharko\site\models\core,
zharko\site\models\account as model;
// Framework for PHP
use mirzaev\minimal\route,
mirzaev\minimal\controller,
mirzaev\minimal\middleware;
// Built-in libraries
use Exception as exception,
RuntimeException as exception_runtime;
/**
* Account middleware
*
* @package zharko\site\models\middlewares
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class account extends middleware
{
/**
* Authentication
*
* @return void
*/
public function authentication(callable $next, controller $controller): void
{
// Authorizing the account
$controller->account = account::authorization() ?? null;
// Exit (success)
$next();
}
}

View File

@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
namespace zharko\site\models\middlewares;
// Files of the project
use zharko\site\models\core,
zharko\site\models\session as model;
// Framework for PHP
use mirzaev\minimal\route,
mirzaev\minimal\controller,
mirzaev\minimal\middleware;
// Baza database
use mirzaev\baza\database,
mirzaev\baza\column,
mirzaev\baza\record,
mirzaev\baza\enumerations\encoding,
mirzaev\baza\enumerations\type;
// Built-in libraries
use Exception as exception,
RuntimeException as exception_runtime;
/**
* Session middleware
*
* @package zharko\site\models\middlewares
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class session extends middleware
{
/**
* Middleware
*
* @return void
*/
public function middleware(callable $next, controller $controller): void
{
// Initializing the session
$session = model::read();
if ($session instanceof session) {
// Found the session
}
// Exit (success)
$next();
}
}

View File

@@ -0,0 +1,169 @@
<?php
declare(strict_types=1);
namespace zharko\site\models;
// Files of the project
use zharko\site\models\core,
zharko\site\models\enumerations\session as verification;
// Library for languages
use mirzaev\languages\language;
// Baza database
use mirzaev\baza\database,
mirzaev\baza\column,
mirzaev\baza\record,
mirzaev\baza\enumerations\encoding,
mirzaev\baza\enumerations\type;
// Svoboda time
use svoboda\time\statement as svoboda;
// Built-in libraries
use Exception as exception,
RuntimeException as exception_runtime;
/**
* Session model
*
* @package zharko\site\models
*
* @method void __construct() Constructor
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class session extends core
{
/**
* File
*
* @var string database Path to the database file
*/
protected string $file = DATABASES . DIRECTORY_SEPARATOR . 'sessions.baza';
/**
* Database
*
* @var database $database The database
*/
public protected(set) database $database;
/**
* Type
*
* @var varification Type of the session verification
*/
final public const verification VERIFICATION = verification::blake2b;
/**
* Timer
*
* @var int The number of seconds after which the session is deactivated
*/
final public const int TIMER = 604800;
/**
* Constructor
*
* @return void
*/
public function __construct()
{
// Initializing the database
$this->database = new database()
->encoding(encoding::utf8)
->columns(
new column('identifier', type::integer_unsigned),
new column('expires', type::integer_unsigned),
new column('address', type::string, ['length' => 128]),
new column('x-forwarded-for', type::string, ['length' => 128]),
new column('referer', type::string, ['length' => 128]),
new column('useragent', type::string, ['length' => 256]),
new column('updated', type::integer_unsigned),
new column('created', type::integer_unsigned)
)
->connect($this->file);
}
/**
* Write
*
* Create the session record in the database
*
* @return int|false The record identifier, if created
*/
public function write(
string $address = '',
string $x_forwarded_for = '',
string $referer = '',
string $useragent = '',
&$errors = []
): int|false {
// Initializing the identifier
$identifier = $this->database->count() + 1;
// Calculating the current timestamp
$timestamp = svoboda::timestamp();
// Initializing the record
$record = $this->database->record(
$identifier,
$timestamp + static::TIMER,
$address,
$x_forwarded_for,
$referer,
$useragent,
$timestamp,
$timestamp
);
// Creating the record in the database
$created = $this->database->write($record);
// Exit (success)
return $created ? $identifier : false;
}
/**
* Read
*
* Read the session record from the database
*
* @return int|false The record identifier, if created
*/
public function read(
string $address = '',
string $x_forwarded_for = '',
string $referer = '',
string $useragent = '',
&$errors = []
): int|false {
// Initializing the identifier
$identifier = $this->database->count() + 1;
// Calculating the current timestamp
$timestamp = svoboda::timestamp();
// Initializing the record
$record = $this->database->record(
$identifier,
$timestamp + static::TIMER,
$address,
$x_forwarded_for,
$referer,
$useragent,
$timestamp,
$timestamp
);
// Creating the record in the database
$created = $this->database->write($record);
// Exit (success)
return $created ? $identifier : false;
}
}

View File

@@ -4,6 +4,9 @@ declare(strict_types=1);
namespace zharko\site;
// Files of the project
use zharko\site\models\middlewares\session;
// Framework for PHP
use mirzaev\minimal\core,
mirzaev\minimal\route,
@@ -48,15 +51,12 @@ $core = new core(namespace: __NAMESPACE__);
// Initializing routes
$core->router
->write('/', new route('index', 'index'), 'GET')
->write('/account/registration', new route('account', 'registration'), ['GET', 'PUT'])
;
// Writing the global middleware
$core->router->middleware(new middleware(function(callable $next, controller $controller) {
// Authorizing the account
$controller->account = account::authorization() ?? null;
$next();
}));
$core->router->middleware(new session);
/* $core->router->middleware(new account); */
// Processing the request
$core->start();

View File

@@ -0,0 +1,404 @@
/**
* @name Core
*
* @description
* Core of the project
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class core {
// Domain
static domain = window.location.hostname;
// Language
static language = "en";
// Theme
static theme = window.getComputedStyle(document.getElementById('theme'));
// Window
static window;
// The "loading" element
static loading = document.getElementById("loading");
// The <header> element
static header = document.body.getElementsByTagName("header")[0];
// The <aside> element
static aside = document.body.getElementsByTagName("aside")[0];
// The <menu> element
static menu = document.getElementById("menu");
// The <main> element
static main = document.body.getElementsByTagName("main")[0];
// The <footer> element
static footer = document.body.getElementsByTagName("footer")[0];
/**
* Request
*
* @param {string} uri
* @param {string} body
* @param {string} method POST, GET...
* @param {object} headers
* @param {string} type Format of response (json, text...)
*
* @return {Promise}
*/
static async request(
uri = "/",
body,
method = "GET",
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
},
type = "json",
) {
return await fetch(encodeURI(uri), { method, headers, body })
.then((response) => type === null || response[type]());
}
/**
* @name Modules
*
* @method connect(modules) Connect modules
*
* @return {Array} List of initialized modules
*/
static modules() {
return Object.keys(this).filter((module) =>
this[module]?.type === "module"
);
}
/**
* @name Buffer
*/
static buffer = class buffer {
/**
* @name Write to buffers
*
* @description
* Write to buffers (interface)
*
* @param {string} name Name of the parameter
* @param {string} value Value of the parameter (it can be JSON)
*
* @return {bool} Execution completed with an error?
*/
static write(name, value) {
core.modules.connect("damper").then(
() => {
// Imported the damper module
// Execute under damper
this.write.damper(name, value);
},
() => {
// Not imported the damper module
// Execute
this.write.system(name, value);
},
);
// Exit (success)
return false;
}
};
/**
* Сгенерировать окно выбора действия
*
* @param {string} title Верхний колонтинул
* @param {string} text Основное содержимое окна
* @param {string} left Содержимое левой кнопки
* @param {object} left_css Перечисление CSS-классов левой кнопки (массив)
* @param {function} left_click Действие после нажатия на левую кнопку
* @param {string} right Содержимое правой кнопки
* @param {object} right_css Перечисление CSS-классов правой кнопки (массив)
* @param {function} right_click Действие после нажатия на правую кнопку
*
* @return {void}
*/
/* static choose = core.damper(
(
title = "Выбор действия",
text = "",
left = "Да",
left_css = ["grass"],
left_click = () => {},
right = "Нет",
right_css = ["clay"],
right_click = () => {},
) => {
// Инициализация оболочки всплывающего окна
this.popup_body.wrap = document.createElement("div");
this.popup_body.wrap.setAttribute("id", "popup");
// Инициализация всплывающего окна
const popup = document.createElement("section");
popup.classList.add("list", "small");
// Инициализация заголовка всплывающего окна
const title_h3 = document.createElement("h3");
title_h3.classList.add("unselectable");
title_h3.innerText = title;
// Инициализация оболочки с основной информацией
const main = document.createElement("section");
main.classList.add("main");
// Инициализация колонки
const column = document.createElement("div");
column.classList.add("column");
// Инициализация текста
const text_p = document.createElement("p");
text_p.innerText = text;
// Инициализация строки
const row = document.createElement("div");
row.classList.add("row", "buttons");
// Инициализация левой кнопки
const left_button = document.createElement("button");
left_button.classList.add(...left_css);
left_button.innerText = left;
left_button.addEventListener("click", left_click);
// Инициализация правой кнопки
const right_button = document.createElement("button");
right_button.classList.add(...right_css);
right_button.innerText = right;
right_button.addEventListener("click", right_click);
// Инициализация окна с ошибками
this.popup_body.errors = document.createElement("section");
this.popup_body.errors.classList.add(
"errors",
"window",
"list",
"calculated",
"hidden",
);
this.popup_body.errors.setAttribute("data-errors", true);
// Инициализация элемента-тела (оболочки) окна с ошибками
const errors = document.createElement("section");
errors.classList.add("body");
// Инициализация элемента-списка ошибок
const dl = document.createElement("dl");
// Инициализация активного всплывающего окна
const old = document.getElementById("popup");
if (old instanceof HTMLElement) {
// Найдено активное окно
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.buttons);
// Сброс блокировки
this.freeze = false;
// Удаление активного окна
old.remove();
}
// Запись в документ
popup.appendChild(title_h3);
column.appendChild(text_p);
row.appendChild(left_button);
row.appendChild(right_button);
column.appendChild(row);
main.appendChild(column);
popup.appendChild(main);
this.popup_body.wrap.appendChild(popup);
document.body.appendChild(this.popup_body.wrap);
errors.appendChild(dl);
this.popup_body.errors.appendChild(errors);
this.popup_body.wrap.appendChild(this.popup_body.errors);
// Инициализация ширины окна с ошибками
this.popup_body.errors.style.setProperty(
"--calculated-width",
popup.offsetWidth + "px",
);
// Инициализация переменных для окна с ошибками (12 - это значение gap из div#popup)
function top(errors) {
errors.style.setProperty("transition", "0s");
errors.style.setProperty(
"--top",
popup.offsetTop + popup.offsetHeight + 12 + "px",
);
setTimeout(() => errors.style.removeProperty("transition"), 100);
}
top(this.popup_body.errors);
const resize = new ResizeObserver(() => top(this.popup_body.errors));
resize.observe(this.popup_body.wrap);
// Инициализация функции закрытия всплывающего окна
const click = () => {
// Блокировка
if (this.freeze) return;
// Удаление всплывающего окна
this.popup_body.wrap.remove();
// Удаление статуса активной строки
row.removeAttribute("data-selected");
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.buttons);
// Сброс блокировки
this.freeze = false;
};
// Инициализация функции добавления функции закрытия всплывающего окна
const enable = () =>
this.popup_body.wrap.addEventListener("click", click);
// Инициализация функции удаления функции закрытия всплывающего окна
const disable = () =>
this.popup_body.wrap.removeEventListener("click", click);
// Первичная активация функции удаления всплывающего окна
enable();
// Добавление функции удаления всплывающего окна по событиям
popup.addEventListener("mouseenter", disable);
popup.addEventListener("mouseleave", enable);
// Добавление функции удаления всплывающего окна по кнопкам
left_button.addEventListener("click", click);
right_button.addEventListener("click", click);
// Фокусировка
right_button.focus();
},
300,
); */
}
Object.assign(
core.modules,
{
/**
* @name Connect modules
*
* @param {Array|string} modules Names of modules or name of the module
*
* @return {Prommise}
*/
async connect(modules) {
// Normalisation required argiments
if (typeof modules === "string") modules = [modules];
if (modules instanceof Array) {
// Received and validated required arguments
// Initializing the registry of loaded modules
const loaded = [];
for (const module of modules) {
// Iterating over modules
// Downloading, importing and writing the module into a core property and into registry of loaded modules
core[module] =
loaded[module] =
await (await import(`./modules/${module}.mjs`)).default;
}
// Exit (success)
return loaded;
}
},
},
);
core.modules.connect("damper").then(() => {
// Imported the damper module
Object.assign(
core.buffer.write,
{
/**
* @name Write to buffers
*
* @description
* Write to buffers (damper)
*
* @param {string} name Name of the parameter
* @param {string} value Value of the parameter (it can be JSON)
* @param {bool} force Ignore the damper? (false)
*
* @return {Promise}
*/
damper: core.damper(
(...variables) => core.buffer.write.system(...variables),
300,
2,
),
},
);
});
/**
* @name Write to buffers
*
* @description
* Write to buffers (system)
*
* @param {string} name Name of the parameter
* @param {string} value Value of the parameter (it can be JSON)
*
* @return {Promise}
*/
Object.assign(
core.buffer.write,
{
system(
name,
value,
resolve = () => {},
reject = () => {},
) {
try {
core.modules.connect("session").then(() => {
// Imported the session module
// Write to the session buffer
core.session.buffer?.write(name, value);
});
core.modules.connect("account").then(() => {
// Imported the account module
// Write to the account buffer
core.account.buffer?.write(name, value);
});
// Exit (success)
resolve();
} catch (e) {
// Exit (fail)
reject(e);
}
},
},
);

View File

@@ -0,0 +1 @@
var MD5 = function(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r<d.length;r++)_=d.charCodeAt(r),f+=m.charAt(_>>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<<m%32;return _}function V(d){for(var _="",m=0;m<32*d.length;m+=8)_+=String.fromCharCode(d[m>>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n<d.length;n+=16){var h=m,t=f,g=r,e=i;f=md5_ii(f=md5_ii(f=md5_ii(f=md5_ii(f=md5_hh(f=md5_hh(f=md5_hh(f=md5_hh(f=md5_gg(f=md5_gg(f=md5_gg(f=md5_gg(f=md5_ff(f=md5_ff(f=md5_ff(f=md5_ff(f,r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+0],7,-680876936),f,r,d[n+1],12,-389564586),m,f,d[n+2],17,606105819),i,m,d[n+3],22,-1044525330),r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+4],7,-176418897),f,r,d[n+5],12,1200080426),m,f,d[n+6],17,-1473231341),i,m,d[n+7],22,-45705983),r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+8],7,1770035416),f,r,d[n+9],12,-1958414417),m,f,d[n+10],17,-42063),i,m,d[n+11],22,-1990404162),r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+12],7,1804603682),f,r,d[n+13],12,-40341101),m,f,d[n+14],17,-1502002290),i,m,d[n+15],22,1236535329),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+1],5,-165796510),f,r,d[n+6],9,-1069501632),m,f,d[n+11],14,643717713),i,m,d[n+0],20,-373897302),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+5],5,-701558691),f,r,d[n+10],9,38016083),m,f,d[n+15],14,-660478335),i,m,d[n+4],20,-405537848),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+9],5,568446438),f,r,d[n+14],9,-1019803690),m,f,d[n+3],14,-187363961),i,m,d[n+8],20,1163531501),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+13],5,-1444681467),f,r,d[n+2],9,-51403784),m,f,d[n+7],14,1735328473),i,m,d[n+12],20,-1926607734),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+5],4,-378558),f,r,d[n+8],11,-2022574463),m,f,d[n+11],16,1839030562),i,m,d[n+14],23,-35309556),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+1],4,-1530992060),f,r,d[n+4],11,1272893353),m,f,d[n+7],16,-155497632),i,m,d[n+10],23,-1094730640),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+13],4,681279174),f,r,d[n+0],11,-358537222),m,f,d[n+3],16,-722521979),i,m,d[n+6],23,76029189),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+9],4,-640364487),f,r,d[n+12],11,-421815835),m,f,d[n+15],16,530742520),i,m,d[n+2],23,-995338651),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+0],6,-198630844),f,r,d[n+7],10,1126891415),m,f,d[n+14],15,-1416354905),i,m,d[n+5],21,-57434055),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+12],6,1700485571),f,r,d[n+3],10,-1894986606),m,f,d[n+10],15,-1051523),i,m,d[n+1],21,-2054922799),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+8],6,1873313359),f,r,d[n+15],10,-30611744),m,f,d[n+6],15,-1560198380),i,m,d[n+13],21,1309151649),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+4],6,-145523070),f,r,d[n+11],10,-1120210379),m,f,d[n+2],15,718787259),i,m,d[n+9],21,-343485551),m=safe_add(m,h),f=safe_add(f,t),r=safe_add(r,g),i=safe_add(i,e)}return Array(m,f,r,i)}function md5_cmn(d,_,m,f,r,i){return safe_add(bit_rol(safe_add(safe_add(_,d),safe_add(f,i)),r),m)}function md5_ff(d,_,m,f,r,i,n){return md5_cmn(_&m|~_&f,d,_,r,i,n)}function md5_gg(d,_,m,f,r,i,n){return md5_cmn(_&f|m&~f,d,_,r,i,n)}function md5_hh(d,_,m,f,r,i,n){return md5_cmn(_^m^f,d,_,r,i,n)}function md5_ii(d,_,m,f,r,i,n){return md5_cmn(m^(_|~f),d,_,r,i,n)}function safe_add(d,_){var m=(65535&d)+(65535&_);return(d>>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_}

View File

@@ -0,0 +1 @@
../../../../../../damper.mjs/damper.mjs

View File

@@ -0,0 +1,280 @@
"use strict";
/**
* @name Loader
*
* @description
* Implements actions with loading and rendering content
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
export default class loader {
/**
* @name Type of the program
*/
static type = "module";
/**
* @name Actial URI
*/
static uri;
/**
* @name Load
*
* @param {string} uri
* @param {string} body
*
* @return {Promise}
*/
static async load(uri = "/", body, back = false) {
if (typeof uri === "string") {
// Received and validated uri
return await core
.request(
uri,
body,
"GET",
{
"Content-Type": "application/x-www-form-urlencoded",
Accept: "application/json",
},
"json",
)
.then((json) => {
if (json) {
// Received a JSON-response
if (
json.errors !== null &&
typeof json.errors === "object" &&
json.errors.length > 0
) {
// Fail (received errors)
// Exit (fail)
reject(json);
} else {
// Success (not received errors)
if (back) {
// Requested to go back
// Writing actual URI
this.uri = history.state?.previous;
// Deletimg from the browser history
history.back();
} else {
// Requested to go forward
// Writing to the browser history
history.pushState(
{ previous: this.uri },
json.title ?? uri,
uri,
);
// Writing actual URI
this.uri = uri;
}
/**
* The <title>
*
* The title of the page
*/
if (
typeof json.title === "string" &&
json.title.length > 0
) {
// Received text for the <title> of the page
// Search for the <title> element (document.title)
const title = document.getElementsByTagName("title")[0];
if (title instanceof HTMLElement) {
// Found the <title> element
// Writing into the <title> element
title.innerText = json.title;
} else {
// Not found the <title> element
// Initialize the <title> element
const title = document.createElement("title");
// Inititalize the <head> element (document.head)
const head = document.getElementsByTagName("head")[0];
if (head instanceof HTMLElement) {
// Found the <head> element
// Writing the <title> element into the <head> element
head.appendChild(title);
}
// Writing title into the <title> element
title.innerText = json.title;
}
}
/**
* The <header> element
*/
if (
typeof json.header === "string" &&
json.header.length > 0
) {
// Received and validated the header HTML-code
if (core.header instanceof HTMLElement) {
// Found the <header> element
// Writing into the <header> element
core.header.outerHTML = json.header;
// Reinitializing the parameter with the <header> element
core.header = document.getElementsByTagName("header")[0];
} else {
// Not found the <header> element
// Initialize the <header> element
core.header = document.createElement("header");
// Inititalize the <body> element (document.body)
const body = document.getElementsByTagName("body")[0];
if (body instanceof HTMLElement) {
// Found the <body> element
if (core.main instanceof HTMLElement) {
// Found the <main> element
// Writing the <header> element before the <main> element
body.insertBefore(core.header, core.main);
} else if (core.footer instanceof HTMLElement) {
// Fount the <footer> element
// Writing the <header> element before the <footer> element
body.insertBefore(core.header, core.footer);
} else {
// Not found the <main> element and the <footer> element
// Search for the last <section> element inside the <body> element
const section = document.body.querySelector(
"body > section:last-of-type",
);
if (section instanceof HTMLElement) {
// Found the last <section> element inside the <body> element
// Writing the <header> element after the last <section> element inside the <body> element
body.insertBefore(
core.header,
section.nextElementSibling,
);
} else {
// Not found section elements <section> inside the <body> element
// Writing the <header> element into the <body> element
body.appendChild(core.header);
}
}
// Writing into the <header> element
core.header.outerHTML = json.header;
// Reinitializing the parameter with the <header> element
core.header = document.getElementsByTagName("header")[0];
}
}
}
/**
* The <main> element
*
* The main content of the page
*/
if (typeof json.main === "string" && json.main.length > 0) {
// Received and validated the <main> HTML-code
if (core.main instanceof HTMLElement) {
// Found the <main> element
// Writing into the <main> element
core.main.outerHTML = json.main;
// Reinitializing the parameter with the <main> element
core.main = document.getElementsByTagName("main")[0];
} else {
// Not found the <main> element
// Initialize the <main> element
core.main = document.createElement("main");
// Inititalize the <body> element (document.body)
const body = document.getElementsByTagName("body")[0];
if (body instanceof HTMLElement) {
// Found the <body> element
if (core.header instanceof HTMLElement) {
// Found the <header> element
// Writing the <main> element after the <header> element
body.insertBefore(
core.main,
core.header.nextElementSibling,
);
} else if (core.footer instanceof HTMLElement) {
// Fount the <footer> element
// Writing the <main> element before the <footer> element
body.insertBefore(core.main, core.footer);
} else {
// Not found the <header> element and the <footer> element
// Search for the last <section> element inside the <body> element
const section = document.body.querySelector(
"body > section:last-of-type",
);
if (section instanceof HTMLElement) {
// Found the last <section> element inside the <body> element
// Writing the <main> element after the last <section> element inside the <body> element
body.insertBefore(
core.main,
section.nextElementSibling,
);
} else {
// Not found section elements <section> inside the <body> element
// Writing the <main> element into the <body> element
body.appendChild(core.main);
}
}
// Writing into the <main> element
core.main.outerHTML = json.main;
// Reinitializing the parameter with the <main> element
core.main = document.getElementsByTagName("main")[0];
}
}
}
// Exit (success)
return json;
}
}
});
}
}
}
// Connecting to the core
if (!core.loader) core.loader = loader;

View File

@@ -0,0 +1,144 @@
/**
* @name Registration
*
* @description
* Account registration
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class registration {
/**
* @name Request (interface)
*
* @description
* Send the account data for registration
*
* @param {string} mail Mail
* @param {string} password Password
* @param {bool} force Ignore the damper? (false)
*
* @return {bool} Did the processing complete without errors?
*/
static request(mail, password, force = false) {
core.modules.connect("damper").then(
() => {
// Imported the damper module
// Processing under damper
this.request.damper(mail, password, force);
},
() => {
// Not imported the damper module
// Processing
this.request.system(mail, password);
},
);
// Exit (success)
return true;
}
}
core.modules.connect("damper").then(() => {
// Imported the damper module
Object.assign(
registration.request,
{
/**
* @name Registration (damper)
*
* @description
* Send the account data for registration
*
* @memberof registration.request
*
* @param {string} mail Mail
* @param {string} password Password
* @param {bool} [force=false] Ignore the damper?
*
* @return {Promise}
*/
damper: core.damper(
(...variables) => registration.request.system(...variables),
300,
3,
),
},
);
});
Object.assign(
registration.request,
{
/**
* @name Request (system)
*
* @description
* Send the account data for registration
*
* @param {string} mail Mail
* @param {string} password Password
*
* @return {Promise}
*/
async system(
mail,
password,
resolve = () => {},
reject = () => {},
) {
try {
// Declaring the query row
let query = "";
// Generating the query row
if (typeof mail === "string") {
query += "&mail=" + mail;
}
if (typeof password === "string") {
query += "&password=" + MD5(unescape(encodeURIComponent(password)));
}
// Sending request to the server
return await core.request(
"/account/registration",
query,
"PUT",
).then(
(json) => {
if (json) {
// Received a JSON-response
if (
json.errors !== null &&
typeof json.errors === "object" &&
json.errors.length > 0
) {
// Fail (received errors)
// Exit (fail)
reject(json);
} else {
// Success (not received errors)
alert('Вы зарегистрировались');
window.location.href = '/';
// Exit (success)
resolve(json);
}
}
},
() => reject(),
);
} catch (e) {
// Exit (fail)
reject(e);
}
},
},
);

View File

@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace zharko\site\views;
// Files of the project
use zharko\site\models\enumerations\language;
// Library for languages support
use mirzaev\languages\language;
// Framework for PHP
use mirzaev\minimal\controller;

View File

@@ -1,5 +1,13 @@
{% block js %}
{% for element in js %}
<script {% if element.src %}src="{{ element.src }}"{% endif %} {% if element.type %}type="{{ element.type }}"{% endif %}>{{ element.innerText }}</script>
{% endfor %}
<script src="/js/modules/damper.mjs" type="module"></script>
<script src="/js/core.js"></script>
<script src="/js/modules/loader.mjs" type="module"></script>
{% for element in js %}
<script
{% if element.src %}src="{{ element.src }}"{% endif %}
{% if element.type %}type="{{ element.type }}"{% endif %}>
{{ element.innerText }}
</script>
{% endfor %}
{% endblock %}

View File

@@ -0,0 +1,24 @@
{% extends "/themes/default/index.html" %}
{% block css %}
{% endblock %}
{% block main %}
<section id="registration">
<div>
<label for="registration_mail">{{ language == 'ru' ? 'Почта' : 'Mail' }}</label>
<input id="registration_mail" type="mail" required/>
</div>
<div>
<label for="registration_password">{{ language == 'ru' ? 'Пароль' : 'Password' }}</label>
<input id="registration_password" type="password" required/>
</div>
<button id="registration_send" onclick="registration.request(...[...document.querySelectorAll('main #registration :is(input:not([type=\'radio\']), input[type=\'radio\']:checked, textarea)')]?.map(element => element.value))">{{ language == 'ru' ? 'Зарегистрироваться' : 'Register' }}</button>
</section>
{% endblock %}
{% block js %}
<script src="/js/pages/account/registration.js"></script>
<script src="/js/libraries/md5.js"></script>
{% endblock %}