Updated JS stuffs.

This commit is contained in:
flash 2025-03-20 21:49:41 +00:00
parent 1363bf5bca
commit 452eeb22d6
Signed by: flash
GPG key ID: 2C9C2C574D47FE3E
21 changed files with 267 additions and 412 deletions

View file

@ -1,108 +0,0 @@
const fs = require('fs');
const path = require('path');
const readline = require('readline');
const utils = require('./utils.js');
exports.process = async function(root, options) {
const macroPrefix = options.prefix || '#';
const entryPoint = options.entry || '';
root = fs.realpathSync(root);
const included = [];
const processFile = async function(fileName) {
const fullPath = path.join(root, fileName);
if(included.includes(fullPath))
return '';
included.push(fullPath);
if(!fullPath.startsWith(root))
return '/* *** INVALID PATH: ' + fullPath + ' */';
if(!fs.existsSync(fullPath))
return '/* *** FILE NOT FOUND: ' + fullPath + ' */';
const lines = readline.createInterface({
input: fs.createReadStream(fullPath),
crlfDelay: Infinity,
});
let output = '';
let lastWasEmpty = false;
if(options.showPath)
output += "/* *** PATH: " + fullPath + " */\n";
for await(const line of lines) {
const lineTrimmed = utils.trim(line);
if(lineTrimmed === '')
continue;
if(line.startsWith(macroPrefix)) {
const args = lineTrimmed.split(' ');
const macro = utils.trim(utils.trimStart(args.shift(), macroPrefix));
switch(macro) {
case 'comment':
break;
case 'include': {
const includePath = utils.trimEnd(args.join(' '), ';');
output += utils.trim(await processFile(includePath));
output += "\n";
break;
}
case 'buildvars':
if(typeof options.buildVars === 'object') {
const bvTarget = options.buildVarsTarget || 'window';
const bvProps = [];
for(const bvName in options.buildVars)
bvProps.push(`${bvName}: { value: ${JSON.stringify(options.buildVars[bvName])} }`);
if(Object.keys(bvProps).length > 0)
output += `Object.defineProperties(${bvTarget}, { ${bvProps.join(', ')} });\n`;
}
break;
default:
output += line;
output += "\n";
break;
}
} else {
output += line;
output += "\n";
}
}
return output;
};
return await processFile(entryPoint);
};
exports.housekeep = function(assetsPath) {
const files = fs.readdirSync(assetsPath).map(fileName => {
const stats = fs.statSync(path.join(assetsPath, fileName));
return {
name: fileName,
lastMod: stats.mtimeMs,
};
}).sort((a, b) => b.lastMod - a.lastMod).map(info => info.name);
const regex = /^(.+)[\-\.]([a-f0-9]+)\.(.+)$/i;
const counts = {};
for(const fileName of files) {
const match = fileName.match(regex);
if(match) {
const name = match[1] + '-' + match[3];
counts[name] = (counts[name] || 0) + 1;
if(counts[name] > 5)
fs.unlinkSync(path.join(assetsPath, fileName));
} else console.log(`Encountered file name in assets folder with unexpected format: ${fileName}`);
}
};

24
assets/makai.js/csrf.js Normal file
View file

@ -0,0 +1,24 @@
#include html.js
const $csrf = (() => {
let elem;
const getElement = () => {
if(elem === undefined)
elem = $query('meta[name="csrf-token"]');
return elem;
};
return {
get token() {
return getElement()?.content ?? '';
},
set token(token) {
if(typeof token !== 'string')
throw 'token must be a string';
const elem = getElement();
if(elem instanceof HTMLMetaElement)
elem.content = token;
},
};
})();

View file

@ -1,111 +0,0 @@
const $t = document.createTextNode.bind(document);
const $er = (type, props, ...children) => $e({ tag: type, attrs: props, child: children });
const $e = function(info, attrs, child, created) {
info = info || {};
if(typeof info === 'string') {
info = {tag: info};
if(attrs)
info.attrs = attrs;
if(child)
info.child = child;
if(created)
info.created = created;
}
const elem = document.createElement(info.tag || 'div');
if(info.attrs) {
const attrs = info.attrs;
for(let key in attrs) {
const attr = attrs[key];
if(attr === undefined || attr === null)
continue;
switch(typeof attr) {
case 'function':
if(key.substring(0, 2) === 'on')
key = key.substring(2).toLowerCase();
elem.addEventListener(key, attr);
break;
case 'object':
if(attr instanceof Array) {
if(key === 'class')
key = 'classList';
const prop = elem[key];
let addFunc = null;
if(prop instanceof Array)
addFunc = prop.push.bind(prop);
else if(prop instanceof DOMTokenList)
addFunc = prop.add.bind(prop);
if(addFunc !== null) {
for(let j = 0; j < attr.length; ++j)
addFunc(attr[j]);
} else {
if(key === 'classList')
key = 'class';
elem.setAttribute(key, attr.toString());
}
} else {
for(const attrKey in attr)
elem[key][attrKey] = attr[attrKey];
}
break;
case 'boolean':
if(attr)
elem.setAttribute(key, '');
break;
default:
if(key === 'className')
key = 'class';
elem.setAttribute(key, attr.toString());
break;
}
}
}
if(info.child) {
let children = info.child;
if(!Array.isArray(children))
children = [children];
for(const child of children) {
switch(typeof child) {
case 'string':
elem.appendChild($t(child));
break;
case 'object':
if(child instanceof Element)
elem.appendChild(child);
else if(child.getElement) {
const childElem = child.getElement();
if(childElem instanceof Element)
elem.appendChild(childElem);
else
elem.appendChild($e(child));
} else
elem.appendChild($e(child));
break;
default:
elem.appendChild($t(child.toString()));
break;
}
}
}
if(info.created)
info.created(elem);
return elem;
};

View file

@ -1,13 +1,10 @@
#include elem.js
#include xhr.js
const MakaiSiteHeaderImages = function() { const MakaiSiteHeaderImages = function() {
const url = '/header-bgs.json'; const url = '/header-bgs.json';
let headers; let headers;
const all = async () => { const all = async () => {
if(!Array.isArray(headers)) if(!Array.isArray(headers))
headers = (await $x.get('/header-bgs.json')).json(); headers = (await $xhr.get('/header-bgs.json', { type: 'json' })).body;
return headers; return headers;
}; };
@ -59,18 +56,19 @@ const MakaiSiteHeader = function(element) {
if(t < 1) if(t < 1)
requestAnimationFrame(updateTransition); requestAnimationFrame(updateTransition);
else { else {
$r(prevImage); prevImage.remove();
resolve(); resolve();
} }
}; };
prevImage.style.zIndex = '2'; prevImage.style.zIndex = '2';
const nextImage = $e({ const nextImage = $element(
tag: 'img', 'img',
attrs: { {
alt: url, alt: url,
src: url, src: url,
style: { zIndex: '1' },
onerror: () => { onerror: () => {
prevImage.style.opacity = null; prevImage.style.opacity = null;
prevImage.style.zIndex = null; prevImage.style.zIndex = null;
@ -81,8 +79,7 @@ const MakaiSiteHeader = function(element) {
requestAnimationFrame(updateTransition); requestAnimationFrame(updateTransition);
}, },
}, },
style: { zIndex: '1' }, );
});
bgElem.appendChild(nextImage); bgElem.appendChild(nextImage);
}); });
}; };

View file

@ -105,7 +105,7 @@ const MakaiSideListElement = function(element) {
}; };
const clearBody = insertEmpty => { const clearBody = insertEmpty => {
$rc(bodyElem); $removeChildren(bodyElem);
insertEmptyElement(); insertEmptyElement();
}; };

139
assets/makai.js/html.js Normal file
View file

@ -0,0 +1,139 @@
const $id = document.getElementById.bind(document);
const $query = document.querySelector.bind(document);
const $queryAll = document.querySelectorAll.bind(document);
const $text = document.createTextNode.bind(document);
const $insertBefore = function(target, element) {
target.parentNode.insertBefore(element, target);
};
const $appendChild = function(element, child) {
switch(typeof child) {
case 'undefined':
break;
case 'string':
element.appendChild($text(child));
break;
case 'function':
$appendChild(element, child());
break;
case 'object':
if(child === null)
break;
if(child instanceof Node)
element.appendChild(child);
else if(child?.element instanceof Node)
element.appendChild(child.element);
else if(typeof child?.toString === 'function')
element.appendChild($text(child.toString()));
break;
default:
element.appendChild($text(child.toString()));
break;
}
};
const $appendChildren = function(element, ...children) {
for(const child of children)
$appendChild(element, child);
};
const $removeChildren = function(element) {
while(element.lastChild)
element.removeChild(element.lastChild);
};
const $fragment = function(props, ...children) {
const fragment = document.createDocumentFragment();
$appendChildren(fragment, ...children);
return fragment;
};
const $element = function(type, props, ...children) {
if(typeof type === 'function')
return new type(props ?? {}, ...children);
const element = document.createElement(type ?? 'div');
if(props)
for(let key in props) {
const prop = props[key];
if(prop === undefined || prop === null)
continue;
switch(typeof prop) {
case 'function':
if(key.substring(0, 2) === 'on')
key = key.substring(2).toLowerCase();
element.addEventListener(key, prop);
break;
case 'object':
if(prop instanceof Array) {
if(key === 'class')
key = 'classList';
const attr = element[key];
let addFunc = null;
if(attr instanceof Array)
addFunc = attr.push.bind(attr);
else if(attr instanceof DOMTokenList)
addFunc = attr.add.bind(attr);
if(addFunc !== null) {
for(let j = 0; j < prop.length; ++j)
addFunc(prop[j]);
} else {
if(key === 'classList')
key = 'class';
element.setAttribute(key, prop.toString());
}
} else {
if(key === 'class' || key === 'className')
key = 'classList';
let setFunc = null;
if(element[key] instanceof DOMTokenList)
setFunc = (ak, av) => { if(av) element[key].add(ak); };
else if(element[key] instanceof CSSStyleDeclaration)
setFunc = (ak, av) => {
if(ak.includes('-'))
element[key].setProperty(ak, av);
else
element[key][ak] = av;
};
else
setFunc = (ak, av) => { element[key][ak] = av; };
for(const attrKey in prop) {
const attrValue = prop[attrKey];
if(attrValue)
setFunc(attrKey, attrValue);
}
}
break;
case 'boolean':
if(prop)
element.setAttribute(key, '');
break;
default:
if(key === 'className')
key = 'class';
element.setAttribute(key, prop.toString());
break;
}
}
$appendChildren(element, ...children);
return element;
};

View file

@ -1,11 +1,14 @@
#include elem.js #include csrf.js
#include html.js
#include xhr.js
#include elems/head.js #include elems/head.js
#include np/init.js #include np/init.js
#include tools/ascii.js #include tools/ascii.js
#include tools/whois.js #include tools/whois.js
const makai = (() => { const makai = (() => {
const header = new MakaiSiteHeader($q('.js-header')); const header = new MakaiSiteHeader($query('.js-header'));
const runIfPathStartsWith = (prefix, func, ...args) => { const runIfPathStartsWith = (prefix, func, ...args) => {
if(location.pathname === prefix || location.pathname.startsWith(`${prefix}/`)) if(location.pathname === prefix || location.pathname.startsWith(`${prefix}/`))

View file

@ -1,5 +1,3 @@
#include xhr.js
const MakaiNowPlaying = function(userName) { const MakaiNowPlaying = function(userName) {
const noCoverUrl = 'https://lastfm.freetls.fastly.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png'; const noCoverUrl = 'https://lastfm.freetls.fastly.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png';
const fetchTarget = `https://now.flash.moe/get.php?u=${userName}`; const fetchTarget = `https://now.flash.moe/get.php?u=${userName}`;
@ -31,15 +29,14 @@ const MakaiNowPlaying = function(userName) {
return { return {
fetch: async () => { fetch: async () => {
const result = await $x.get(fetchTarget); const { status, body } = await $xhr.get(fetchTarget, { type: 'json' });
if(result.status !== 200) if(status !== 200)
throw `http ${result.status}`; throw `http ${status}`;
let info = result.json(); if(body.length < 1)
if(info.length < 1)
throw 'no data'; throw 'no data';
return format(info[0]); return format(body[0]);
}, },
}; };
}; };

View file

@ -1,9 +1,8 @@
#include utility.js
#include np/client.js #include np/client.js
#include np/element.jsx #include np/element.jsx
const MakaiNowPlayingInit = siteHeader => { const MakaiNowPlayingInit = siteHeader => {
const target = $q('.js-np-target'); const target = $query('.js-np-target');
if(!(target instanceof Element)) if(!(target instanceof Element))
return; return;
@ -13,7 +12,7 @@ const MakaiNowPlayingInit = siteHeader => {
const client = new MakaiNowPlaying(userName); const client = new MakaiNowPlaying(userName);
const element = new MakaiNowPlayingElement; const element = new MakaiNowPlayingElement;
$rp(target, element.element); target.replaceWith(element.element);
const update = () => { const update = () => {
client.fetch().then(result => { client.fetch().then(result => {

View file

@ -1,8 +1,6 @@
#include utility.js
const MakaiASCII = () => { const MakaiASCII = () => {
const chars = $qa('.js-ascii-char'); const chars = $queryAll('.js-ascii-char');
const search = $q('.js-ascii-search'); const search = $query('.js-ascii-search');
const charsFilter = (filter) => { const charsFilter = (filter) => {
if(!filter) { if(!filter) {

View file

@ -1,17 +1,15 @@
#include utility.js
#include xhr.js
#include elems/sidelist.jsx #include elems/sidelist.jsx
const MakaiWHOIS = () => { const MakaiWHOIS = () => {
let locked = false; let locked = false;
const input = $q('.js-whois-input'); const input = $query('.js-whois-input');
const submit = $q('.js-whois-submit'); const submit = $query('.js-whois-submit');
const result = $q('.js-whois-body'); const result = $query('.js-whois-body');
const tabs = $q('.js-whois-tabs'); const tabs = $query('.js-whois-tabs');
const historic = []; const historic = [];
const history = (() => { const history = (() => {
const element = $q('.js-whois-sidelist'); const element = $query('.js-whois-sidelist');
if(element instanceof Element) if(element instanceof Element)
return new MakaiSideListElement(element); return new MakaiSideListElement(element);
})(); })();
@ -40,18 +38,17 @@ const MakaiWHOIS = () => {
if(!lock()) if(!lock())
return; return;
$x.post('/tools/whois/lookup', {}, { _csrfp: $csrfp.get(), target: target }).then(output => { $xhr.post('/tools/whois/lookup', { type: 'json' }, { _csrfp: $csrf.token, target: target }).then(output => {
let headers = output.headers(); if(output.headers.has('x-csrfp'))
if(headers.has('x-csrfp')) $csrf.token = output.headers.get('x-csrfp');
$csrfp.set(headers.get('x-csrfp'));
let resp = output.json(); let resp = output.body;
if(resp.error) if(resp.error)
alert(resp.text); alert(resp.text);
let count = 0; let count = 0;
$rc(tabs); $removeChildren(tabs);
if(resp.result && Array.isArray(resp.result.responses) && resp.result.responses.length > 0) { if(resp.result && Array.isArray(resp.result.responses) && resp.result.responses.length > 0) {
if(!historic.includes(resp.result.target)) { if(!historic.includes(resp.result.target)) {
@ -60,16 +57,16 @@ const MakaiWHOIS = () => {
} }
for(const response of resp.result.responses) { for(const response of resp.result.responses) {
const tab = $e({tag: 'a'}); const tab = $element('a');
const tabHeader = $e(); const tabHeader = $element();
const tabServer = $e(); const tabServer = $element();
tab.href = 'javascript:;'; tab.href = 'javascript:;';
tab.className = 'whois-result-tab'; tab.className = 'whois-result-tab';
if(count === 0) tab.className += ' whois-result-tab-active'; if(count === 0) tab.className += ' whois-result-tab-active';
tab.onclick = () => { tab.onclick = () => {
const active = $q('.whois-result-tab-active'); const active = $query('.whois-result-tab-active');
if(active) active.classList.remove('whois-result-tab-active'); if(active) active.classList.remove('whois-result-tab-active');
tab.classList.add('whois-result-tab-active'); tab.classList.add('whois-result-tab-active');
result.textContent = response.lines.join("\r\n").trim(); result.textContent = response.lines.join("\r\n").trim();

View file

@ -1,65 +0,0 @@
const $i = document.getElementById.bind(document);
const $c = document.getElementsByClassName.bind(document);
const $q = document.querySelector.bind(document);
const $qa = document.querySelectorAll.bind(document);
const $r = function(element) {
if(element && element.parentNode)
element.parentNode.removeChild(element);
};
const $ri = function(name) {
$r($i(name));
};
const $ib = function(ref, elem) {
ref.parentNode.insertBefore(elem, ref);
};
const $rc = function(element) {
while(element.lastChild)
element.removeChild(element.lastChild);
};
const $rp = function(target, replace) {
$ib(target, replace);
$r(target);
};
const $ar = function(array, index) {
array.splice(index, 1);
};
const $ari = function(array, item) {
let index;
while(array.length > 0 && (index = array.indexOf(item)) >= 0)
$ar(array, index);
};
const $arf = function(array, predicate) {
let index;
while(array.length > 0 && (index = array.findIndex(predicate)) >= 0)
$ar(array, index);
};
const $as = function(array) {
if(array.length < 2)
return;
for(let i = array.length - 1; i > 0; --i) {
let j = Math.floor(Math.random() * (i + 1)),
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
};
const $csrfp = (function() {
const elem = $q('meta[name="csrfp-token"]');
return {
get: () => elem?.content ?? '',
set: token => {
if(elem != null)
elem.content = token?.toString() ?? '';
},
};
})();

View file

@ -1,15 +1,24 @@
const $x = (function() { #include csrf.js
const $xhr = (function() {
const send = function(method, url, options, body) { const send = function(method, url, options, body) {
options ??= {}; if(options === undefined)
options = {};
else if(typeof options !== 'object')
throw 'options must be undefined or an object';
Object.freeze(options);
const xhr = new XMLHttpRequest; const xhr = new XMLHttpRequest;
const requestHeadersRaw = options?.headers ?? {};
const requestHeaders = new Map; const requestHeaders = new Map;
if(typeof requestHeadersRaw === 'object') if('headers' in options && typeof options.headers === 'object')
for(const name in requestHeadersRaw) for(const name in options.headers)
if(requestHeadersRaw.hasOwnProperty(name)) if(options.headers.hasOwnProperty(name))
requestHeaders.set(name.toLowerCase(), requestHeadersRaw[name]); requestHeaders.set(name.toLowerCase(), options.headers[name]);
if(options.csrf)
requestHeaders.set('x-csrf-token', $csrf.token);
if(typeof options.download === 'function') { if(typeof options.download === 'function') {
xhr.onloadstart = ev => options.download(ev); xhr.onloadstart = ev => options.download(ev);
@ -29,6 +38,9 @@ const $x = (function() {
if(typeof options.timeout === 'number') if(typeof options.timeout === 'number')
xhr.timeout = options.timeout; xhr.timeout = options.timeout;
if(typeof options.type === 'string')
xhr.responseType = options.type;
if(typeof options.abort === 'function') if(typeof options.abort === 'function')
options.abort(() => xhr.abort()); options.abort(() => xhr.abort());
@ -39,7 +51,7 @@ const $x = (function() {
if(body instanceof URLSearchParams) { if(body instanceof URLSearchParams) {
requestHeaders.set('content-type', 'application/x-www-form-urlencoded'); requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
} else if(body instanceof FormData) { } else if(body instanceof FormData) {
requestHeaders.set('content-type', 'multipart/form-data'); // content-type is implicitly set
} else if(body instanceof Blob || body instanceof ArrayBuffer || body instanceof DataView) { } else if(body instanceof Blob || body instanceof ArrayBuffer || body instanceof DataView) {
if(!requestHeaders.has('content-type')) if(!requestHeaders.has('content-type'))
requestHeaders.set('content-type', 'application/octet-stream'); requestHeaders.set('content-type', 'application/octet-stream');
@ -54,30 +66,33 @@ const $x = (function() {
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let responseHeaders = undefined; xhr.onload = ev => {
const headers = (headersString => {
const headers = new Map;
xhr.onload = ev => resolve({ const raw = headersString.trim().split(/[\r\n]+/);
status: xhr.status,
body: () => xhr.responseText,
json: () => JSON.parse(xhr.responseText),
headers: () => {
if(responseHeaders !== undefined)
return responseHeaders;
responseHeaders = new Map;
const raw = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/);
for(const name in raw) for(const name in raw)
if(raw.hasOwnProperty(name)) { if(raw.hasOwnProperty(name)) {
const parts = raw[name].split(': '); const parts = raw[name].split(': ');
responseHeaders.set(parts.shift(), parts.join(': ')); headers.set(parts.shift(), parts.join(': '));
} }
return responseHeaders; return headers;
}, })(xhr.getAllResponseHeaders());
xhr: xhr,
ev: ev, if(headers.has('x-csrf-token'))
}); $csrf.token = headers.get('x-csrf-token');
resolve({
get ev() { return ev; },
get xhr() { return xhr; },
get status() { return xhr.status; },
get headers() { return headers; },
get body() { return xhr.response; },
get text() { return xhr.responseText; },
});
};
xhr.onerror = ev => reject({ xhr.onerror = ev => reject({
xhr: xhr, xhr: xhr,

View file

@ -1,35 +0,0 @@
const crypto = require('crypto');
exports.strtr = (str, replacements) => str.toString().replace(
/{([^}]+)}/g, (match, key) => replacements[key] || match
);
const trim = function(str, chars, flags) {
if(chars === undefined)
chars = " \n\r\t\v\0";
let start = 0,
end = str.length;
if(flags & 0x01)
while(start < end && chars.indexOf(str[start]) >= 0)
++start;
if(flags & 0x02)
while(end > start && chars.indexOf(str[end - 1]) >= 0)
--end;
return (start > 0 || end < str.length)
? str.substring(start, end)
: str;
};
exports.trimStart = (str, chars) => trim(str, chars, 0x01);
exports.trimEnd = (str, chars) => trim(str, chars, 0x02);
exports.trim = (str, chars) => trim(str, chars, 0x03);
exports.shortHash = function(text) {
const hash = crypto.createHash('sha256');
hash.update(text);
return hash.digest('hex').substring(0, 8);
};

View file

@ -11,7 +11,9 @@ const fs = require('fs');
public: pathJoin(__dirname, 'public'), public: pathJoin(__dirname, 'public'),
debug: isDebug, debug: isDebug,
swc: { swc: {
es: 'es2020', es: 'es2021',
jsx: '$element',
jsxf: '$fragment',
}, },
}; };

View file

@ -1,6 +1,7 @@
<?php <?php
namespace Makai; namespace Makai;
use Index\Http\HttpResponseBuilder;
use Index\Http\Routing\{RouteHandler,RouteHandlerCommon}; use Index\Http\Routing\{RouteHandler,RouteHandlerCommon};
use Index\Http\Routing\Routes\ExactRoute; use Index\Http\Routing\Routes\ExactRoute;
use Index\Templating\TplEnvironment; use Index\Templating\TplEnvironment;
@ -17,7 +18,7 @@ class DeveloperRoutes implements RouteHandler {
) {} ) {}
#[ExactRoute('GET', '/')] #[ExactRoute('GET', '/')]
public function getIndex($response, $request) { public function getIndex() {
$projectInfos = $this->projects->getProjects( $projectInfos = $this->projects->getProjects(
featuredOnly: true, featuredOnly: true,
deleted: false, deleted: false,
@ -54,12 +55,12 @@ class DeveloperRoutes implements RouteHandler {
} }
#[ExactRoute('GET', '/tools')] #[ExactRoute('GET', '/tools')]
public function temporaryRedirect($response): void { public function temporaryRedirect(HttpResponseBuilder $response): void {
$response->redirect('/'); $response->redirect('/');
} }
#[ExactRoute('GET', '/contact')] #[ExactRoute('GET', '/contact')]
public function permanentRedirect($response): void { public function permanentRedirect(HttpResponseBuilder $response): void {
$response->redirect('/', true); $response->redirect('/', true);
} }
} }

View file

@ -2,6 +2,7 @@
namespace Makai\SSHKeys; namespace Makai\SSHKeys;
use DateTimeInterface; use DateTimeInterface;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{RouteHandler,RouteHandlerCommon}; use Index\Http\Routing\{RouteHandler,RouteHandlerCommon};
use Index\Http\Routing\Routes\ExactRoute; use Index\Http\Routing\Routes\ExactRoute;
@ -13,7 +14,7 @@ class SSHKeysRoutes implements RouteHandler {
) {} ) {}
#[ExactRoute('GET', '/ssh_keys')] #[ExactRoute('GET', '/ssh_keys')]
public function getSshKeys($response, $request): array|string { public function getSshKeys(HttpResponseBuilder $response, HttpRequest $request): array|string {
$minLevel = (int)$request->getParam('l', FILTER_SANITIZE_NUMBER_INT); $minLevel = (int)$request->getParam('l', FILTER_SANITIZE_NUMBER_INT);
$includeComment = $request->hasParam('c'); $includeComment = $request->hasParam('c');
$json = $request->hasParam('j'); $json = $request->hasParam('j');
@ -47,7 +48,7 @@ class SSHKeysRoutes implements RouteHandler {
} }
#[ExactRoute('GET', '/authorized_keys')] #[ExactRoute('GET', '/authorized_keys')]
public function getAuthorisedKeys($response, $request): string { public function getAuthorisedKeys(HttpResponseBuilder $response): string {
$response->setTypePlain(); $response->setTypePlain();
$body = ''; $body = '';
@ -59,7 +60,7 @@ class SSHKeysRoutes implements RouteHandler {
} }
#[ExactRoute('GET', '/git_keys_ro')] #[ExactRoute('GET', '/git_keys_ro')]
public function getGitKeysReadOnly($response, $request): string { public function getGitKeysReadOnly(HttpResponseBuilder $response): string {
$response->setTypePlain(); $response->setTypePlain();
$body = ''; $body = '';
@ -71,7 +72,7 @@ class SSHKeysRoutes implements RouteHandler {
} }
#[ExactRoute('GET', '/git_keys_rw')] #[ExactRoute('GET', '/git_keys_rw')]
public function getGitKeysReadWrite($response, $request): string { public function getGitKeysReadWrite(HttpResponseBuilder $response): string {
$response->setTypePlain(); $response->setTypePlain();
$body = ''; $body = '';
@ -83,7 +84,7 @@ class SSHKeysRoutes implements RouteHandler {
} }
#[ExactRoute('GET', '/ssh.php')] #[ExactRoute('GET', '/ssh.php')]
public function getSshPhp($response, $request): void { public function getSshPhp(HttpResponseBuilder $response, HttpRequest $request): void {
$query = []; $query = [];
$minLevel = (int)$request->getParam('l', FILTER_SANITIZE_NUMBER_INT); $minLevel = (int)$request->getParam('l', FILTER_SANITIZE_NUMBER_INT);

View file

@ -1,6 +1,7 @@
<?php <?php
namespace Makai\Tools\Ascii; namespace Makai\Tools\Ascii;
use Index\Http\HttpResponseBuilder;
use Index\Http\Routing\{RouteHandler,RouteHandlerCommon}; use Index\Http\Routing\{RouteHandler,RouteHandlerCommon};
use Index\Http\Routing\Routes\ExactRoute; use Index\Http\Routing\Routes\ExactRoute;
use Index\Templating\TplEnvironment; use Index\Templating\TplEnvironment;
@ -13,7 +14,7 @@ class AsciiRoutes implements RouteHandler {
) {} ) {}
#[ExactRoute('GET', '/tools/ascii')] #[ExactRoute('GET', '/tools/ascii')]
public function getAsciiTable($response, $request): string { public function getAsciiTable(HttpResponseBuilder $response): string {
return $this->templating->render('tools/ascii/index', [ return $this->templating->render('tools/ascii/index', [
'chars' => AsciiCharacter::all(), 'chars' => AsciiCharacter::all(),
]); ]);
@ -21,7 +22,7 @@ class AsciiRoutes implements RouteHandler {
#[ExactRoute('GET', '/ascii')] #[ExactRoute('GET', '/ascii')]
#[ExactRoute('GET', '/ascii.php')] #[ExactRoute('GET', '/ascii.php')]
public function getAsciiPHP($response, $request): void { public function getAsciiPHP(HttpResponseBuilder $response): void {
$response->redirect('/tools/ascii', true); $response->redirect('/tools/ascii', true);
} }
} }

View file

@ -2,6 +2,7 @@
namespace Makai\Tools; namespace Makai\Tools;
use Index\XString; use Index\XString;
use Index\Http\{HttpRequest,HttpResponseBuilder};
use Index\Http\Routing\{RouteHandler,RouteHandlerCommon}; use Index\Http\Routing\{RouteHandler,RouteHandlerCommon};
use Index\Http\Routing\Routes\ExactRoute; use Index\Http\Routing\Routes\ExactRoute;
@ -9,7 +10,7 @@ class ToolsRoutes implements RouteHandler {
use RouteHandlerCommon; use RouteHandlerCommon;
#[ExactRoute('GET', '/tools/random')] #[ExactRoute('GET', '/tools/random')]
public function getRandomString($response, $request): string { public function getRandomString(HttpResponseBuilder $response, HttpRequest $request): string {
$response->setTypePlain(); $response->setTypePlain();
$length = (int)$request->getParam('length', FILTER_SANITIZE_NUMBER_INT); $length = (int)$request->getParam('length', FILTER_SANITIZE_NUMBER_INT);
@ -27,7 +28,7 @@ class ToolsRoutes implements RouteHandler {
#[ExactRoute('GET', '/tools/hajime-hash')] #[ExactRoute('GET', '/tools/hajime-hash')]
#[ExactRoute('GET', '/tools/hidoi-hash')] #[ExactRoute('GET', '/tools/hidoi-hash')]
public function getHajimeHash($response, $request): string { public function getHajimeHash(HttpResponseBuilder $response, HttpRequest $request): string {
$response->setTypePlain(); $response->setTypePlain();
if(!$request->hasParam('text')) if(!$request->hasParam('text'))
return 'text param is empty'; return 'text param is empty';
@ -37,7 +38,7 @@ class ToolsRoutes implements RouteHandler {
#[ExactRoute('GET', '/key.php')] #[ExactRoute('GET', '/key.php')]
#[ExactRoute('GET', '/rngstr')] #[ExactRoute('GET', '/rngstr')]
public function getRedirect($response, $request): void { public function getRedirect(HttpResponseBuilder $response, HttpRequest $request): void {
$url = '/tools/random'; $url = '/tools/random';
$length = (int)$request->getParam('length', FILTER_SANITIZE_NUMBER_INT); $length = (int)$request->getParam('length', FILTER_SANITIZE_NUMBER_INT);

View file

@ -4,7 +4,10 @@ namespace Makai\Tools\Whois;
use Exception; use Exception;
use Memcached; use Memcached;
use Index\Cache\CacheBackends; use Index\Cache\CacheBackends;
use Index\Http\HttpResponseBuilder;
use Index\Http\Content\FormContent;
use Index\Http\Routing\{RouteHandler,RouteHandlerCommon}; use Index\Http\Routing\{RouteHandler,RouteHandlerCommon};
use Index\Http\Routing\Processors\Before;
use Index\Http\Routing\Routes\ExactRoute; use Index\Http\Routing\Routes\ExactRoute;
use Index\Templating\TplEnvironment; use Index\Templating\TplEnvironment;
use Makai\CSRFPContainer; use Makai\CSRFPContainer;
@ -23,17 +26,13 @@ class WhoisRoutes implements RouteHandler {
} }
#[ExactRoute('GET', '/whois')] #[ExactRoute('GET', '/whois')]
public function getWhoisPHP($response, $request): void { public function getWhoisPHP(HttpResponseBuilder $response): void {
$response->redirect('/tools/whois', true); $response->redirect('/tools/whois', true);
} }
#[ExactRoute('POST', '/tools/whois/lookup')] #[ExactRoute('POST', '/tools/whois/lookup')]
public function postLookup($response, $request) { #[Before('input:urlencoded')]
if(!$request->isFormContent()) public function postLookup(HttpResponseBuilder $response, FormContent $content) {
return 400;
$content = $request->getContent();
if(!$this->csrfp->verifyToken((string)$content->getParam('_csrfp'))) if(!$this->csrfp->verifyToken((string)$content->getParam('_csrfp')))
return [ return [
'error' => true, 'error' => true,

View file

@ -4,7 +4,7 @@
<meta charset="{{ master_charset|default('utf-8') }}"> <meta charset="{{ master_charset|default('utf-8') }}">
{% if master_title is defined and master_title is not empty %}<title>{{ master_title }}</title>{% endif %} {% if master_title is defined and master_title is not empty %}<title>{{ master_title }}</title>{% endif %}
{% block master_head %}{% endblock %} {% block master_head %}{% endblock %}
{% if csrfp_available() %}<meta name="csrfp-token" content="{{ csrfp_token() }}">{% endif %} {% if csrfp_available() %}<meta name="csrf-token" content="{{ csrfp_token() }}">{% endif %}
</head> </head>
<body> <body>
{% block master_body %}{% endblock %} {% block master_body %}{% endblock %}