Initial import
This commit is contained in:
commit
b884f28569
21 changed files with 1217 additions and 0 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
* text=auto
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/.debug
|
||||||
|
/config/config.ini
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "lib/index"]
|
||||||
|
path = lib/index
|
||||||
|
url = https://github.com/flashwave/index.git
|
1
lib/index
Submodule
1
lib/index
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 8a5423fea397e2f2adca0b9f46d1e5c21fd13c44
|
46
mince.php
Normal file
46
mince.php
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
namespace Mince;
|
||||||
|
|
||||||
|
use Index\Autoloader;
|
||||||
|
use Index\Environment;
|
||||||
|
use Index\Data\ConnectionFailedException;
|
||||||
|
use Index\Data\DbTools;
|
||||||
|
|
||||||
|
define('MCR_STARTUP', microtime(true));
|
||||||
|
define('MCR_ROOT', __DIR__);
|
||||||
|
define('MCR_DEBUG', is_file(MCR_ROOT . '/.debug'));
|
||||||
|
define('MCR_DIR_SRC', MCR_ROOT . '/src');
|
||||||
|
define('MCR_DIR_LIB', MCR_ROOT . '/lib');
|
||||||
|
define('MCR_DIR_PUB', MCR_ROOT . '/public');
|
||||||
|
define('MCR_DIR_PRV', MCR_ROOT . '/private');
|
||||||
|
define('MCR_DIR_CFG', MCR_ROOT . '/config');
|
||||||
|
|
||||||
|
require_once MCR_DIR_LIB . '/index/index.php';
|
||||||
|
|
||||||
|
Autoloader::addNamespace(__NAMESPACE__, MCR_DIR_SRC);
|
||||||
|
Environment::setDebug(MCR_DEBUG);
|
||||||
|
|
||||||
|
$config = parse_ini_file(MCR_DIR_CFG . '/config.ini');
|
||||||
|
if($config === false)
|
||||||
|
die('Config sux.');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$db = DbTools::create($config['dsn']);
|
||||||
|
} catch(ConnectionFailedException $ex) {
|
||||||
|
echo '<h3>Unable to connect to database</h3>';
|
||||||
|
die($ex->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
Remote::setUrl($config['remote_url']);
|
||||||
|
Remote::setSecret($config['remote_secret']);
|
||||||
|
|
||||||
|
if(empty($_COOKIE['mc_random'])) {
|
||||||
|
$sVerification = Utils::generatePassKey(32);
|
||||||
|
setcookie('mc_random', $sVerification, strtotime('1 day'), '/', $_SERVER['HTTP_HOST']);
|
||||||
|
} else
|
||||||
|
$sVerification = (string)filter_input(INPUT_COOKIE, 'mc_random');
|
||||||
|
|
||||||
|
$sVerification = hash('sha256', $sVerification);
|
||||||
|
|
||||||
|
// replace this with id.flashii.net shit
|
||||||
|
$userInfo = ChatAuth::attempt($db, $config['chat_endpoint'], $config['chat_secret'], (string)filter_input(INPUT_COOKIE, 'msz_auth'));
|
BIN
public/assets/bg_main.png
Normal file
BIN
public/assets/bg_main.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 434 B |
BIN
public/assets/bg_top.png
Normal file
BIN
public/assets/bg_top.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
BIN
public/assets/dirt-x4.png
Normal file
BIN
public/assets/dirt-x4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
BIN
public/assets/minecraft.eot
Normal file
BIN
public/assets/minecraft.eot
Normal file
Binary file not shown.
347
public/assets/minecraft.svg
Normal file
347
public/assets/minecraft.svg
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||||
|
<svg>
|
||||||
|
<metadata>
|
||||||
|
Created by FontForge 20090622 at Sun Nov 12 10:48:06 2017
|
||||||
|
By ffonts
|
||||||
|
Copyright \(c\) 2017 by Jacob Debono.
|
||||||
|
</metadata>
|
||||||
|
<defs>
|
||||||
|
<font id="Minecraft-Regular" horiz-adv-x="600" >
|
||||||
|
<font-face
|
||||||
|
font-family="Minecraft"
|
||||||
|
font-weight="400"
|
||||||
|
font-stretch="normal"
|
||||||
|
units-per-em="1000"
|
||||||
|
panose-1="0 0 5 0 0 0 0 0 0 0"
|
||||||
|
ascent="800"
|
||||||
|
descent="-200"
|
||||||
|
x-height="500"
|
||||||
|
cap-height="700"
|
||||||
|
bbox="0 -200 800 700"
|
||||||
|
underline-thickness="50"
|
||||||
|
underline-position="-50"
|
||||||
|
unicode-range="U+0020-U+2666"
|
||||||
|
/>
|
||||||
|
<missing-glyph horiz-adv-x="100"
|
||||||
|
/>
|
||||||
|
<glyph glyph-name=".notdef" horiz-adv-x="100"
|
||||||
|
/>
|
||||||
|
<glyph glyph-name="A" unicode="A"
|
||||||
|
d="M100 600v100h300v-100h-300zM400 600h100v-600h-100v400h-300v-400h-100v600h100v-100h300v100z" />
|
||||||
|
<glyph glyph-name="Adieresis" unicode="Ä"
|
||||||
|
d="M0 700h100v-100h-100v100zM500 700v-100h-100v100h100zM400 600v-100h-300v100h300zM400 400v100h100v-500h-100v300h-300v-300h-100v500h100v-100h300z" />
|
||||||
|
<glyph glyph-name="Aring" unicode="Å"
|
||||||
|
d="M300 700v-100h-100v100h100zM100 400v100h300v-100h-300zM400 400h100v-400h-100v200h-300v-200h-100v400h100v-100h300v100z" />
|
||||||
|
<glyph glyph-name="AE" unicode="Æ"
|
||||||
|
d="M300 600v-100h100v-100h-100v-300h200v-100h-300v400h-100v-400h-100v600h100v-100h100v100h-100v100h400v-100h-200z" />
|
||||||
|
<glyph glyph-name="B" unicode="B"
|
||||||
|
d="M400 500v-100h-300v-300h300v-100h-400v700h400v-100h-300v-100h300zM500 500h-100v100h100v-100zM400 400h100v-300h-100v300z" />
|
||||||
|
<glyph glyph-name="C" unicode="C"
|
||||||
|
d="M400 700v-100h-300v100h300zM0 600h100v-500h-100v500zM500 500h-100v100h100v-100zM500 200v-100h-100v100h100zM100 0v100h300v-100h-300z" />
|
||||||
|
<glyph glyph-name="Ccedilla" unicode="Ç"
|
||||||
|
d="M400 700v-100h-300v100h300zM0 600h100v-500h-100v500zM500 500h-100v100h100v-100zM500 200v-100h-100v100h100zM100 0v100h300v-100h-300zM500 -100h-100v100h100v-100zM200 -100h200v-100h-200v100z" />
|
||||||
|
<glyph glyph-name="D" unicode="D"
|
||||||
|
d="M400 100v-100h-400v700h400v-100h-300v-500h300zM400 600h100v-500h-100v500z" />
|
||||||
|
<glyph glyph-name="E" unicode="E"
|
||||||
|
d="M100 600v-100h200v-100h-200v-300h400v-100h-500v700h500v-100h-400z" />
|
||||||
|
<glyph glyph-name="F" unicode="F"
|
||||||
|
d="M500 700v-100h-400v-100h200v-100h-200v-400h-100v700h500z" />
|
||||||
|
<glyph glyph-name="G" unicode="G"
|
||||||
|
d="M100 600v100h400v-100h-400zM100 100h-100v500h100v-500zM500 100h-100v300h-100v100h200v-400zM100 0v100h300v-100h-300z" />
|
||||||
|
<glyph glyph-name="H" unicode="H"
|
||||||
|
d="M400 700h100v-700h-100v400h-300v-400h-100v700h100v-200h300v200z" />
|
||||||
|
<glyph glyph-name="I" unicode="I" horiz-adv-x="400"
|
||||||
|
d="M200 100h100v-100h-300v100h100v500h-100v100h300v-100h-100v-500z" />
|
||||||
|
<glyph glyph-name="J" unicode="J"
|
||||||
|
d="M400 700h100v-600h-100v600zM0 200h100v-100h-100v100zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="K" unicode="K"
|
||||||
|
d="M300 500v-100h-200v-400h-100v700h100v-200h200zM500 700v-100h-100v100h100zM400 600v-100h-100v100h100zM400 300h-100v100h100v-100zM400 300h100v-300h-100v300z" />
|
||||||
|
<glyph glyph-name="L" unicode="L"
|
||||||
|
d="M500 100v-100h-500v700h100v-600h400z" />
|
||||||
|
<glyph glyph-name="M" unicode="M"
|
||||||
|
d="M100 600h100v-100h-100v-500h-100v700h100v-100zM400 700h100v-700h-100v500h-100v100h100v100zM200 400v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="N" unicode="N"
|
||||||
|
d="M100 600h100v-100h-100v-500h-100v700h100v-100zM400 700h100v-700h-100v300h-100v100h100v300zM200 500h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="Ntilde" unicode="Ñ"
|
||||||
|
d="M500 700v-100h-500v100h500zM100 400h100v-100h-100v-300h-100v500h100v-100zM400 500h100v-500h-100v100h-100v100h100v300zM200 300h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="O" unicode="O"
|
||||||
|
d="M100 600v100h300v-100h-300zM100 100h-100v500h100v-500zM400 600h100v-500h-100v500zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="Oslash" unicode="Ø"
|
||||||
|
d="M100 600v100h300v-100h-300zM200 200h-100v-100h-100v500h100v-300h100v-100zM400 600h100v-500h-100v300h-100v100h100v100zM200 300v100h100v-100h-100zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="P" unicode="P"
|
||||||
|
d="M400 500v-100h-300v-400h-100v700h400v-100h-300v-100h300zM400 600h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="Q" unicode="Q"
|
||||||
|
d="M100 600v100h300v-100h-300zM100 100h-100v500h100v-500zM400 600h100v-400h-100v400zM300 100v100h100v-100h-100zM100 100h200v-100h-200v100zM500 0h-100v100h100v-100z" />
|
||||||
|
<glyph glyph-name="R" unicode="R"
|
||||||
|
d="M400 500v-100h-300v-400h-100v700h400v-100h-300v-100h300zM500 500h-100v100h100v-100zM400 400h100v-400h-100v400z" />
|
||||||
|
<glyph glyph-name="S" unicode="S"
|
||||||
|
d="M100 600v100h400v-100h-400zM0 600h100v-100h-100v100zM100 400v100h300v-100h-300zM400 400h100v-300h-100v300zM0 200h100v-100h-100v100zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="T" unicode="T"
|
||||||
|
d="M500 700v-100h-200v-600h-100v600h-200v100h500z" />
|
||||||
|
<glyph glyph-name="U" unicode="U"
|
||||||
|
d="M100 100h-100v600h100v-600zM400 700h100v-600h-100v600zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="Udieresis" unicode="Ü"
|
||||||
|
d="M100 700v-100h-100v100h100zM400 700h100v-100h-100v100zM100 100h-100v400h100v-400zM400 500h100v-400h-100v400zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="V" unicode="V"
|
||||||
|
d="M100 300h-100v400h100v-400zM400 700h100v-400h-100v400zM200 300v-200h-100v200h100zM300 300h100v-200h-100v200zM200 0v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="W" unicode="W"
|
||||||
|
d="M100 200h100v-100h-100v-100h-100v700h100v-500zM400 700h100v-700h-100v100h-100v100h100v500zM200 300h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="X" unicode="X"
|
||||||
|
d="M0 700h100v-100h-100v100zM500 700v-100h-100v100h100zM100 600h100v-100h-100v100zM400 600v-100h-100v100h100zM200 500h100v-100h-100v100zM100 300v100h100v-100h-100zM400 300h-100v100h100v-100zM0 300h100v-300h-100v300zM400 300h100v-300h-100v300z" />
|
||||||
|
<glyph glyph-name="Y" unicode="Y"
|
||||||
|
d="M0 700h100v-100h-100v100zM400 700h100v-100h-100v100zM100 600h100v-100h-100v100zM300 500v100h100v-100h-100zM200 500h100v-500h-100v500z" />
|
||||||
|
<glyph glyph-name="Z" unicode="Z"
|
||||||
|
d="M500 700v-200h-100v100h-400v100h500zM300 400v100h100v-100h-100zM200 300v100h100v-100h-100zM100 200v100h100v-100h-100zM0 200h100v-100h400v-100h-500v200z" />
|
||||||
|
<glyph glyph-name="a" unicode="a"
|
||||||
|
d="M400 500v-100h-300v100h300zM400 400h100v-400h-400v100h300v100h-300v100h300v100zM0 200h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="aacute" unicode="á"
|
||||||
|
d="M500 700v-100h-200v100h200zM400 500v-100h-300v100h300zM400 300v100h100v-400h-400v100h300v100h-300v100h300zM0 200h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="acircumflex" unicode="â"
|
||||||
|
d="M100 600v100h300v-100h-300zM0 600h100v-100h-100v100zM500 500h-100v100h100v-100zM400 500v-100h-300v100h300zM400 300v100h100v-400h-400v100h300v100h-300v100h300zM0 200h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="agrave" unicode="à"
|
||||||
|
d="M200 600h-200v100h200v-100zM400 500v-100h-300v100h300zM400 400h100v-400h-400v100h300v100h-300v100h300v100zM0 200h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="aring" unicode="å"
|
||||||
|
d="M300 700v-100h-100v100h100zM400 500v-100h-300v100h300zM400 400h100v-400h-400v100h300v100h-300v100h300v100zM0 200h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="ae" unicode="æ"
|
||||||
|
d="M100 500h100v-100h-100v100zM400 500v-100h-100v100h100zM400 200h-100v-100h200v-100h-400v100h100v100h-100v100h100v100h100v-100h100v-100zM500 300h-100v100h100v-100zM0 200h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="b" unicode="b"
|
||||||
|
d="M400 100v-100h-400v700h100v-300h100v-100h-100v-200h300zM400 400h-200v100h200v-100zM400 400h100v-300h-100v300z" />
|
||||||
|
<glyph glyph-name="c" unicode="c"
|
||||||
|
d="M400 500v-100h-300v100h300zM0 400h100v-300h-100v300zM500 300h-100v100h100v-100zM500 200v-100h-100v100h100zM100 0v100h300v-100h-300z" />
|
||||||
|
<glyph glyph-name="ccedilla" unicode="ç"
|
||||||
|
d="M400 500v-100h-300v100h300zM0 400h100v-300h-100v300zM500 300h-100v100h100v-100zM500 200v-100h-100v100h100zM100 0v100h300v-100h-300zM500 -100h-100v100h100v-100zM200 -100h200v-100h-200v100z" />
|
||||||
|
<glyph glyph-name="d" unicode="d"
|
||||||
|
d="M400 700h100v-700h-400v100h300v200h-100v100h100v300zM300 400h-200v100h200v-100zM100 100h-100v300h100v-300z" />
|
||||||
|
<glyph glyph-name="e" unicode="e"
|
||||||
|
d="M100 400v100h300v-100h-300zM400 400h100v-200h-400v-100h-100v300h100v-100h300v100zM100 0v100h400v-100h-400z" />
|
||||||
|
<glyph glyph-name="ecircumflex" unicode="ê"
|
||||||
|
d="M100 600v100h300v-100h-300zM0 600h100v-100h-100v100zM500 500h-100v100h100v-100zM400 500v-100h-300v100h300zM400 300v100h100v-200h-400v-100h-100v300h100v-100h300zM100 0v100h400v-100h-400z" />
|
||||||
|
<glyph glyph-name="edieresis" unicode="ë"
|
||||||
|
d="M200 700v-100h-100v100h100zM400 700v-100h-100v100h100zM100 400v100h300v-100h-300zM400 400h100v-200h-400v-100h-100v300h100v-100h300v100zM100 0v100h400v-100h-400z" />
|
||||||
|
<glyph glyph-name="f" unicode="f" horiz-adv-x="500"
|
||||||
|
d="M400 600h-200v100h200v-100zM100 600h100v-100h200v-100h-200v-400h-100v400h-100v100h100v100z" />
|
||||||
|
<glyph glyph-name="g" unicode="g"
|
||||||
|
d="M500 500v-500h-100v100h-300v100h300v200h-300v100h400zM100 400v-200h-100v200h100zM400 0v-100h-400v100h400z" />
|
||||||
|
<glyph glyph-name="h" unicode="h"
|
||||||
|
d="M100 400h100v-100h-100v-300h-100v700h100v-300zM400 500v-100h-200v100h200zM400 400h100v-400h-100v400z" />
|
||||||
|
<glyph glyph-name="i" unicode="i" horiz-adv-x="200"
|
||||||
|
d="M0 700h100v-100h-100v100zM0 500h100v-500h-100v500z" />
|
||||||
|
<glyph glyph-name="iacute" unicode="í" horiz-adv-x="300"
|
||||||
|
d="M200 700v-100h-200v100h200zM0 500h100v-500h-100v500z" />
|
||||||
|
<glyph glyph-name="icircumflex" unicode="î" horiz-adv-x="400"
|
||||||
|
d="M100 700v-100h-100v100h100zM200 700h100v-100h-100v100zM100 500h100v-500h-100v500z" />
|
||||||
|
<glyph glyph-name="j" unicode="j"
|
||||||
|
d="M400 700h100v-100h-100v100zM400 500h100v-500h-100v500zM0 100h100v-100h-100v100zM400 0v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="k" unicode="k" horiz-adv-x="500"
|
||||||
|
d="M100 300h100v-100h-100v-200h-100v700h100v-400zM400 500v-100h-100v100h100zM300 400v-100h-100v100h100zM300 100h-100v100h100v-100zM400 0h-100v100h100v-100z" />
|
||||||
|
<glyph glyph-name="l" unicode="l" horiz-adv-x="300"
|
||||||
|
d="M100 100h-100v600h100v-600zM100 100h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="m" unicode="m"
|
||||||
|
d="M200 500v-100h-100v-400h-100v500h200zM300 500h100v-100h-100v100zM200 400h100v-200h-100v200zM400 400h100v-400h-100v400z" />
|
||||||
|
<glyph glyph-name="n" unicode="n"
|
||||||
|
d="M400 500v-100h-300v-400h-100v500h400zM400 400h100v-400h-100v400z" />
|
||||||
|
<glyph glyph-name="ntilde" unicode="ñ"
|
||||||
|
d="M500 700v-100h-500v100h500zM400 500v-100h-300v-400h-100v500h400zM400 400h100v-400h-100v400z" />
|
||||||
|
<glyph glyph-name="o" unicode="o"
|
||||||
|
d="M100 400v100h300v-100h-300zM100 100h-100v300h100v-300zM400 400h100v-300h-100v300zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="oacute" unicode="ó"
|
||||||
|
d="M500 700v-100h-200v100h200zM100 400v100h300v-100h-300zM100 100h-100v300h100v-300zM400 400h100v-300h-100v300zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="ocircumflex" unicode="ô"
|
||||||
|
d="M100 600v100h300v-100h-300zM0 600h100v-100h-100v100zM500 500h-100v100h100v-100zM400 500v-100h-300v100h300zM100 100h-100v300h100v-300zM400 400h100v-300h-100v300zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="odieresis" unicode="ö"
|
||||||
|
d="M200 700v-100h-100v100h100zM400 700v-100h-100v100h100zM100 400v100h300v-100h-300zM100 100h-100v300h100v-300zM400 400h100v-300h-100v300zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="ograve" unicode="ò"
|
||||||
|
d="M200 600h-200v100h200v-100zM100 400v100h300v-100h-300zM100 100h-100v300h100v-300zM400 400h100v-300h-100v300zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="oslash" unicode="ø"
|
||||||
|
d="M400 400h100v-300h-100v200h-100v100h-200v100h300v-100zM200 100h200v-100h-100v-100h-100v100h-100v100h-100v300h100v-200h100v-100zM200 200v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="p" unicode="p"
|
||||||
|
d="M400 200v-100h-300v-200h-100v600h100v-100h100v-100h-100v-100h300zM400 400h-200v100h200v-100zM400 400h100v-200h-100v200z" />
|
||||||
|
<glyph glyph-name="q" unicode="q"
|
||||||
|
d="M400 500h100v-600h-100v200h-300v100h300v100h-100v100h100v100zM300 400h-200v100h200v-100zM100 400v-200h-100v200h100z" />
|
||||||
|
<glyph glyph-name="r" unicode="r"
|
||||||
|
d="M100 500v-100h100v-100h-100v-300h-100v500h100zM400 500v-100h-200v100h200zM400 400h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="s" unicode="s"
|
||||||
|
d="M100 400v100h400v-100h-400zM0 400h100v-100h-100v100zM100 200v100h300v-100h-300zM500 100h-100v100h100v-100zM400 100v-100h-400v100h400z" />
|
||||||
|
<glyph glyph-name="t" unicode="t" horiz-adv-x="400"
|
||||||
|
d="M200 100h-100v300h-100v100h100v200h100v-200h100v-100h-100v-300zM300 0h-100v100h100v-100z" />
|
||||||
|
<glyph glyph-name="u" unicode="u"
|
||||||
|
d="M100 100h-100v400h100v-400zM400 500h100v-500h-400v100h300v400z" />
|
||||||
|
<glyph glyph-name="uacute" unicode="ú"
|
||||||
|
d="M500 700v-100h-200v100h200zM100 100h-100v400h100v-400zM400 500h100v-500h-400v100h300v400z" />
|
||||||
|
<glyph glyph-name="ucircumflex" unicode="û"
|
||||||
|
d="M400 700v-100h-300v100h300zM0 500v100h100v-100h-100zM400 600h100v-100h-100v100zM100 100h-100v300h100v-300zM400 400h100v-400h-400v100h300v300z" />
|
||||||
|
<glyph glyph-name="udieresis" unicode="ü"
|
||||||
|
d="M200 700v-100h-100v100h100zM400 700v-100h-100v100h100zM100 100h-100v400h100v-400zM400 500h100v-500h-400v100h300v400z" />
|
||||||
|
<glyph glyph-name="ugrave" unicode="ù"
|
||||||
|
d="M200 600h-200v100h200v-100zM100 100h-100v400h100v-400zM400 500h100v-500h-400v100h300v400z" />
|
||||||
|
<glyph glyph-name="v" unicode="v"
|
||||||
|
d="M100 200h-100v300h100v-300zM400 500h100v-300h-100v300zM100 200h100v-100h-100v100zM300 100v100h100v-100h-100zM200 0v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="w" unicode="w"
|
||||||
|
d="M100 100h-100v400h100v-400zM400 500h100v-500h-400v100h100v200h100v-200h100v400z" />
|
||||||
|
<glyph glyph-name="x" unicode="x"
|
||||||
|
d="M0 400v100h100v-100h-100zM400 400v100h100v-100h-100zM100 300v100h100v-100h-100zM300 300v100h100v-100h-100zM200 200v100h100v-100h-100zM100 100v100h100v-100h-100zM300 100v100h100v-100h-100zM0 0v100h100v-100h-100zM400 0v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="y" unicode="y"
|
||||||
|
d="M100 200h-100v300h100v-300zM400 500h100v-500h-100v100h-300v100h300v300zM400 0v-100h-400v100h400z" />
|
||||||
|
<glyph glyph-name="ydieresis" unicode="ÿ"
|
||||||
|
d="M200 700v-100h-100v100h100zM400 700v-100h-100v100h100zM100 200h-100v300h100v-300zM400 500h100v-500h-100v100h-300v100h300v300zM400 0v-100h-400v100h400z" />
|
||||||
|
<glyph glyph-name="z" unicode="z"
|
||||||
|
d="M400 400v-100h-100v100h-300v100h500v-100h-100zM300 300v-100h-100v100h100zM100 200h100v-100h300v-100h-500v100h100v100z" />
|
||||||
|
<glyph glyph-name="uni03A9" unicode="Ω"
|
||||||
|
d="M400 700v-100h-300v100h300zM0 600h100v-400h-100v400zM400 600h100v-400h-100v400zM0 100h100v100h100v-200h-200v100zM300 200h100v-100h100v-100h-200v200z" />
|
||||||
|
<glyph glyph-name="zero" unicode="0"
|
||||||
|
d="M100 600v100h300v-100h-300zM200 200h-100v-100h-100v500h100v-300h100v-100zM400 600h100v-500h-100v300h-100v100h100v100zM200 300v100h100v-100h-100zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="one" unicode="1"
|
||||||
|
d="M500 100v-100h-500v100h200v400h-100v100h100v100h100v-600h200z" />
|
||||||
|
<glyph glyph-name="two" unicode="2"
|
||||||
|
d="M400 700v-100h-300v100h300zM0 500v100h100v-100h-100zM400 600h100v-200h-100v200zM200 400h200v-100h-200v100zM100 200v100h100v-100h-100zM0 200h100v-100h300v100h100v-200h-500v200z" />
|
||||||
|
<glyph glyph-name="three" unicode="3"
|
||||||
|
d="M400 700v-100h-300v100h300zM0 500v100h100v-100h-100zM400 600h100v-200h-100v200zM200 400h200v-100h-200v100zM400 100v200h100v-200h-100zM0 200h100v-100h-100v100zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="four" unicode="4"
|
||||||
|
d="M500 700v-700h-100v200h-400v200h100v-100h300v300h-100v100h200zM300 600v-100h-100v100h100zM200 500v-100h-100v100h100z" />
|
||||||
|
<glyph glyph-name="five" unicode="5"
|
||||||
|
d="M100 600v-100h300v-100h-400v300h500v-100h-400zM400 400h100v-300h-100v300zM0 200h100v-100h-100v100zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="six" unicode="6"
|
||||||
|
d="M400 600h-200v100h200v-100zM200 600v-100h-100v100h100zM100 300v-200h-100v400h100v-100h300v-100h-300zM400 300h100v-200h-100v200zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="seven" unicode="7"
|
||||||
|
d="M500 700v-300h-100v200h-300v-100h-100v200h500zM300 300v100h100v-100h-100zM200 300h100v-300h-100v300z" />
|
||||||
|
<glyph glyph-name="eight" unicode="8"
|
||||||
|
d="M100 600v100h300v-100h-300zM100 600v-200h-100v200h100zM400 600h100v-200h-100v200zM400 400v-100h-300v100h300zM100 300v-200h-100v200h100zM400 100v200h100v-200h-100zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="nine" unicode="9"
|
||||||
|
d="M100 600v100h300v-100h-300zM100 600v-200h-100v200h100zM400 600h100v-400h-100v100h-300v100h300v200zM300 100v100h100v-100h-100zM100 100h200v-100h-200v100z" />
|
||||||
|
<glyph glyph-name="period" unicode="." horiz-adv-x="200"
|
||||||
|
d="M0 200h100v-200h-100v200z" />
|
||||||
|
<glyph glyph-name="comma" unicode="," horiz-adv-x="200"
|
||||||
|
d="M0 200h100v-300h-100v300z" />
|
||||||
|
<glyph glyph-name="colon" unicode=":" horiz-adv-x="200"
|
||||||
|
d="M0 600h100v-200h-100v200zM0 200h100v-200h-100v200z" />
|
||||||
|
<glyph glyph-name="semicolon" unicode=";" horiz-adv-x="200"
|
||||||
|
d="M0 600h100v-200h-100v200zM0 200h100v-300h-100v300z" />
|
||||||
|
<glyph glyph-name="exclam" unicode="!" horiz-adv-x="200"
|
||||||
|
d="M0 700h100v-500h-100v500zM0 0v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="exclamdown" unicode="¡" horiz-adv-x="200"
|
||||||
|
d="M0 600h100v-100h-100v100zM0 400h100v-400h-100v400z" />
|
||||||
|
<glyph glyph-name="question" unicode="?"
|
||||||
|
d="M400 700v-100h-300v100h300zM0 500v100h100v-100h-100zM400 600h100v-200h-100v200zM300 300v100h100v-100h-100zM200 200v100h100v-100h-100zM200 0v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="questiondown" unicode="¿"
|
||||||
|
d="M300 700v-100h-100v100h100zM300 500v-100h-100v100h100zM200 400v-100h-100v100h100zM100 300v-200h-100v200h100zM400 200h100v-100h-100v100zM400 100v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="periodcentered" unicode="·" horiz-adv-x="300"
|
||||||
|
d="M200 400v-200h-200v200h200z" />
|
||||||
|
<glyph glyph-name="bullet" unicode="•" horiz-adv-x="300"
|
||||||
|
d="M200 400v-200h-200v200h200z" />
|
||||||
|
<glyph glyph-name="asterisk" unicode="*" horiz-adv-x="500"
|
||||||
|
d="M0 500h100v-100h-100v100zM400 500v-100h-100v100h100zM300 400v-100h-200v100h200zM0 200v100h100v-100h-100zM400 200h-100v100h100v-100z" />
|
||||||
|
<glyph glyph-name="numbersign" unicode="#"
|
||||||
|
d="M500 400h-100v-100h100v-100h-100v-200h-100v200h-100v-200h-100v200h-100v100h100v100h-100v100h100v200h100v-200h100v200h100v-200h100v-100zM300 300v100h-100v-100h100z" />
|
||||||
|
<glyph glyph-name="slash" unicode="/"
|
||||||
|
d="M400 700h100v-100h-100v100zM300 600h100v-200h-100v200zM200 300v100h100v-100h-100zM100 300h100v-200h-100v200zM0 0v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="backslash" unicode="\"
|
||||||
|
d="M0 700h100v-100h-100v100zM200 600v-200h-100v200h100zM200 400h100v-100h-100v100zM400 300v-200h-100v200h100zM400 100h100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="parenleft" unicode="(" horiz-adv-x="500"
|
||||||
|
d="M400 600h-200v100h200v-100zM200 600v-100h-100v100h100zM100 200h-100v300h100v-300zM200 100h-100v100h100v-100zM200 0v100h200v-100h-200z" />
|
||||||
|
<glyph glyph-name="parenright" unicode=")" horiz-adv-x="500"
|
||||||
|
d="M200 700v-100h-200v100h200zM200 600h100v-100h-100v100zM300 500h100v-300h-100v300zM200 100v100h100v-100h-100zM0 100h200v-100h-200v100z" />
|
||||||
|
<glyph glyph-name="braceleft" unicode="{" horiz-adv-x="500"
|
||||||
|
d="M400 600h-200v100h200v-100zM200 400h-100v200h100v-200zM0 400h100v-100h-100v100zM100 100v200h100v-200h-100zM200 0v100h200v-100h-200z" />
|
||||||
|
<glyph glyph-name="braceright" unicode="}" horiz-adv-x="500"
|
||||||
|
d="M200 700v-100h-200v100h200zM300 600v-200h-100v200h100zM300 400h100v-100h-100v100zM200 300h100v-200h-100v200zM0 100h200v-100h-200v100z" />
|
||||||
|
<glyph glyph-name="bracketleft" unicode="[" horiz-adv-x="400"
|
||||||
|
d="M100 100h200v-100h-300v700h300v-100h-200v-500z" />
|
||||||
|
<glyph glyph-name="bracketright" unicode="]" horiz-adv-x="400"
|
||||||
|
d="M300 700v-700h-300v100h200v500h-200v100h300z" />
|
||||||
|
<glyph glyph-name="hyphen" unicode="-"
|
||||||
|
d="M500 400v-100h-500v100h500z" />
|
||||||
|
<glyph glyph-name="uni00AD" unicode="­" horiz-adv-x="300"
|
||||||
|
d="M200 400v-100h-200v100h200z" />
|
||||||
|
<glyph glyph-name="emdash" unicode="—"
|
||||||
|
d="M500 400v-100h-500v100h500z" />
|
||||||
|
<glyph glyph-name="underscore" unicode="_"
|
||||||
|
d="M500 0v-100h-500v100h500z" />
|
||||||
|
<glyph glyph-name="guillemotleft" unicode="«"
|
||||||
|
d="M200 400v100h100v-100h-100zM400 400v100h100v-100h-100zM100 300v100h100v-100h-100zM300 300v100h100v-100h-100zM0 200v100h100v-100h-100zM200 200v100h100v-100h-100zM100 100v100h100v-100h-100zM300 100v100h100v-100h-100zM200 0v100h100v-100h-100zM400 0v100
|
||||||
|
h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="guillemotright" unicode="»"
|
||||||
|
d="M0 400v100h100v-100h-100zM200 400v100h100v-100h-100zM100 300v100h100v-100h-100zM300 300v100h100v-100h-100zM200 200v100h100v-100h-100zM400 200v100h100v-100h-100zM100 100v100h100v-100h-100zM300 100v100h100v-100h-100zM0 0v100h100v-100h-100zM200 0v100h100
|
||||||
|
v-100h-100z" />
|
||||||
|
<glyph glyph-name="quotedbl" unicode=""" horiz-adv-x="500"
|
||||||
|
d="M200 700v-200h-100v200h100zM300 700h100v-200h-100v200zM0 400v100h100v-100h-100zM200 400v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="quotesingle" unicode="'" horiz-adv-x="300"
|
||||||
|
d="M100 700h100v-200h-100v200zM0 400v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="space" unicode=" " horiz-adv-x="400"
|
||||||
|
/>
|
||||||
|
<glyph glyph-name="cent" unicode="¢" horiz-adv-x="500"
|
||||||
|
d="M100 300v100h100v100h100v-100h100v-100h-300zM0 300h100v-100h-100v100zM200 100h-100v100h300v-100h-100v-100h-100v100z" />
|
||||||
|
<glyph glyph-name="currency" unicode="¤" horiz-adv-x="400"
|
||||||
|
d="M0 400v100h100v-100h-100zM200 400v100h100v-100h-100zM100 300v100h100v-100h-100zM0 200v100h100v-100h-100zM200 200v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="dollar" unicode="$"
|
||||||
|
d="M100 500v100h100v100h100v-100h200v-100h-400zM0 500h100v-100h-100v100zM100 300v100h300v-100h-300zM500 200h-100v100h100v-100zM400 200v-100h-100v-100h-100v100h-200v100h400z" />
|
||||||
|
<glyph glyph-name="florin" unicode="ƒ"
|
||||||
|
d="M300 700h100v-100h-100v100zM200 600h100v-200h100v-100h-100v-200h-100v200h-100v100h100v200zM400 600h100v-100h-100v100zM0 200h100v-100h-100v100zM100 0v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="sterling" unicode="£"
|
||||||
|
d="M400 700v-100h-200v100h200zM100 600h100v-200h200v-100h-200v-200h300v-100h-500v100h100v200h-100v100h100v200zM500 500h-100v100h100v-100z" />
|
||||||
|
<glyph glyph-name="plus" unicode="+"
|
||||||
|
d="M500 400v-100h-200v-200h-100v200h-200v100h200v200h100v-200h200z" />
|
||||||
|
<glyph glyph-name="divide" unicode="÷"
|
||||||
|
d="M300 600v-100h-100v100h100zM500 400v-100h-500v100h500zM200 100v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="equal" unicode="="
|
||||||
|
d="M500 500v-100h-500v100h500zM500 200v-100h-500v100h500z" />
|
||||||
|
<glyph glyph-name="greater" unicode=">" horiz-adv-x="500"
|
||||||
|
d="M0 600v100h100v-100h-100zM100 500v100h100v-100h-100zM200 400v100h100v-100h-100zM300 300v100h100v-100h-100zM200 200v100h100v-100h-100zM100 100v100h100v-100h-100zM0 0v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="less" unicode="<" horiz-adv-x="500"
|
||||||
|
d="M300 600v100h100v-100h-100zM200 500v100h100v-100h-100zM100 400v100h100v-100h-100zM0 300v100h100v-100h-100zM100 200v100h100v-100h-100zM200 100v100h100v-100h-100zM300 0v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="plusminus" unicode="±"
|
||||||
|
d="M500 500v-100h-200v-200h-100v200h-200v100h200v200h100v-200h200zM500 100v-100h-500v100h500z" />
|
||||||
|
<glyph glyph-name="approxequal" unicode="≈" horiz-adv-x="800"
|
||||||
|
d="M700 600v-100h-100v-100h-300v100h-100v-100h-200v100h100v100h300v-100h100v100h200zM500 300h200v-100h-100v-100h-300v100h-100v-100h-200v100h100v100h300v-100h100v100z" />
|
||||||
|
<glyph glyph-name="asciitilde" unicode="~" horiz-adv-x="700"
|
||||||
|
d="M300 700v-100h-200v100h200zM500 700h100v-100h-100v100zM0 500v100h100v-100h-100zM300 600h200v-100h-200v100z" />
|
||||||
|
<glyph glyph-name="logicalnot" unicode="¬"
|
||||||
|
d="M500 300v-200h-100v100h-400v100h500z" />
|
||||||
|
<glyph glyph-name="infinity" unicode="∞" horiz-adv-x="800"
|
||||||
|
d="M300 400h-200v100h200v-100zM600 400h-200v100h200v-100zM100 400v-200h-100v200h100zM400 400v-200h-100v200h100zM600 400h100v-200h-100v200zM100 200h200v-100h-200v100zM400 200h200v-100h-200v100z" />
|
||||||
|
<glyph glyph-name="summation" unicode="∑"
|
||||||
|
d="M500 700v-200h-100v100h-300v-100h-100v200h500zM200 400h-100v100h100v-100zM300 300h-100v100h100v-100zM100 200v100h100v-100h-100zM0 200h100v-100h300v100h100v-200h-500v200z" />
|
||||||
|
<glyph glyph-name="radical" unicode="√" horiz-adv-x="900"
|
||||||
|
d="M800 700v-100h-200v-600h-300v100h-100v100h-100v100h-100v100h300v-200h100v500h400z" />
|
||||||
|
<glyph glyph-name="percent" unicode="%"
|
||||||
|
d="M100 500h-100v200h100v-200zM400 700h100v-100h-100v100zM300 600h100v-200h-100v200zM200 300v100h100v-100h-100zM100 300h100v-200h-100v200zM400 200h100v-200h-100v200zM0 0v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="smileface" unicode="☺" horiz-adv-x="900"
|
||||||
|
d="M100 600v100h600v-100h-600zM100 0h-100v600h100v-600zM700 600h100v-600h-100v600zM300 500v-100h-100v100h100zM500 400v100h100v-100h-100zM600 300v-100h-100v-100h-200v100h-100v100h400zM700 0v-100h-600v100h600z" />
|
||||||
|
<glyph glyph-name="invsmileface" unicode="☻" horiz-adv-x="900"
|
||||||
|
d="M700 600h100v-600h-100v-100h-600v100h-100v600h100v100h600v-100zM200 500v-100h100v100h-100zM600 400v100h-100v-100h100zM600 200v100h-400v-100h100v-100h200v100h100z" />
|
||||||
|
<glyph glyph-name="sun" unicode="☼" horiz-adv-x="900"
|
||||||
|
d="M0 700h100v-100h-100v100zM500 500h100v-100h200v-200h-200v-100h-100v-200h-200v200h-100v100h-200v200h200v100h100v200h200v-200zM800 700v-100h-100v100h100zM100 600h100v-100h-100v100zM700 600v-100h-100v100h100zM500 400h-200v-200h200v200zM100 0v100h100v-100
|
||||||
|
h-100zM700 0h-100v100h100v-100zM0 -100v100h100v-100h-100zM800 -100h-100v100h100v-100z" />
|
||||||
|
<glyph glyph-name="female" unicode="♀"
|
||||||
|
d="M100 600v100h300v-100h-300zM100 300h-100v300h100v-300zM400 600h100v-300h-100v300zM400 300v-100h-100v-100h100v-100h-100v-100h-100v100h-100v100h100v100h-100v100h300z" />
|
||||||
|
<glyph glyph-name="male" unicode="♂" horiz-adv-x="800"
|
||||||
|
d="M700 700v-300h-100v100h-100v100h-100v100h300zM400 400v100h100v-100h-100zM400 400v-100h-300v100h300zM100 0h-100v300h100v-300zM400 300h100v-300h-100v300zM400 0v-100h-300v100h300z" />
|
||||||
|
<glyph glyph-name="spade" unicode="♠" horiz-adv-x="800"
|
||||||
|
d="M600 300h100v-100h-100v-100h-100v-100h100v-100h-500v100h100v100h-100v100h-100v100h100v100h100v100h100v200h100v-200h100v-100h100v-100z" />
|
||||||
|
<glyph glyph-name="club" unicode="♣" horiz-adv-x="800"
|
||||||
|
d="M700 400v-200h-100v-100h-100v-100h100v-100h-500v100h100v100h-100v100h-100v200h200v100h-100v100h100v100h300v-100h100v-100h-100v-100h200z" />
|
||||||
|
<glyph glyph-name="heart" unicode="♥" horiz-adv-x="800"
|
||||||
|
d="M600 600h100v-300h-100v-100h-100v-100h-100v-100h-100v100h-100v100h-100v100h-100v300h100v100h200v-100h100v100h200v-100z" />
|
||||||
|
<glyph glyph-name="diamond" unicode="♦" horiz-adv-x="800"
|
||||||
|
d="M600 400h100v-100h-100v-100h-100v-100h-100v-100h-100v100h-100v100h-100v100h-100v100h100v100h100v100h100v100h100v-100h100v-100h100v-100z" />
|
||||||
|
<glyph glyph-name="at" unicode="@" horiz-adv-x="700"
|
||||||
|
d="M500 700v-100h-400v100h400zM0 600h100v-500h-100v500zM500 600h100v-400h-400v300h200v-200h100v300zM100 0v100h400v-100h-400z" />
|
||||||
|
<glyph glyph-name="ampersand" unicode="&"
|
||||||
|
d="M300 700v-100h-100v100h100zM100 600h100v-100h-100v100zM400 500h-100v100h100v-100zM400 300v-200h-100v100h-100v100h-100v100h100v100h100v-200h100zM500 400v-100h-100v100h100zM100 300v-200h-100v200h100zM100 100h200v-100h-200v100zM500 0h-100v100h100v-100z
|
||||||
|
" />
|
||||||
|
<glyph glyph-name="paragraph" unicode="¶" horiz-adv-x="700"
|
||||||
|
d="M600 700v-700h-100v600h-100v-600h-100v300h-200v100h200v200h-200v100h500zM100 600v-200h-100v200h100z" />
|
||||||
|
<glyph glyph-name="section" unicode="§"
|
||||||
|
d="M100 600v100h400v-100h-400zM0 600h100v-100h-100v100zM100 400v100h300v-100h-300zM0 400h100v-100h-100v100zM500 300h-100v100h100v-100zM400 300v-100h-300v100h300zM500 100h-100v100h100v-100zM400 100v-100h-400v100h400z" />
|
||||||
|
<glyph glyph-name="registered" unicode="®" horiz-adv-x="700"
|
||||||
|
d="M200 400h-100v100h400v-100h-100v-100h-100v-100h-100v200zM400 200v-100h100v-100h-400v100h-100v300h100v-200h100v-100h100v100h100zM500 400h100v-300h-100v300z" />
|
||||||
|
<glyph glyph-name="bar" unicode="|" horiz-adv-x="200"
|
||||||
|
d="M0 700h100v-300h-100v300zM0 300h100v-300h-100v300z" />
|
||||||
|
<glyph glyph-name="asciicircum" unicode="^"
|
||||||
|
d="M200 600v100h100v-100h-100zM100 500v100h100v-100h-100zM300 500v100h100v-100h-100zM0 400v100h100v-100h-100zM400 400v100h100v-100h-100z" />
|
||||||
|
<glyph glyph-name="house" unicode="⌂"
|
||||||
|
d="M300 500v-100h-100v100h100zM200 400v-100h-100v100h100zM400 300h-100v100h100v-100zM400 300h100v-300h-500v300h100v-200h300v200z" />
|
||||||
|
<glyph glyph-name="cedilla" unicode="¸" horiz-adv-x="400"
|
||||||
|
d="M200 0h100v-100h-100v100zM0 -100h200v-100h-200v100z" />
|
||||||
|
</font>
|
||||||
|
</defs></svg>
|
After Width: | Height: | Size: 28 KiB |
BIN
public/assets/minecraft.woff
Normal file
BIN
public/assets/minecraft.woff
Normal file
Binary file not shown.
BIN
public/assets/weblogo.png
Normal file
BIN
public/assets/weblogo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 151 KiB |
244
public/index.php
Normal file
244
public/index.php
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
<?php
|
||||||
|
namespace Mince;
|
||||||
|
|
||||||
|
use Index\Performance\Timings;
|
||||||
|
use Index\Data\DbType;
|
||||||
|
use Index\Http\HttpFx;
|
||||||
|
use Mince\HTML;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../mince.php';
|
||||||
|
|
||||||
|
$timing = new Timings;
|
||||||
|
|
||||||
|
$router = new HttpFx;
|
||||||
|
|
||||||
|
$timing->lap('httpfx', 'HttpFx Created');
|
||||||
|
|
||||||
|
$loginUrl = $config['login_url'];
|
||||||
|
|
||||||
|
$router->setDefaultErrorHandler(function($response, $request, $code, $text) use ($loginUrl, $userInfo) {
|
||||||
|
$body = HTML::getHeader($userInfo, $loginUrl, sprintf('%03d %s', $code, $text));
|
||||||
|
$body .= '<div class="error">';
|
||||||
|
$body .= sprintf(' <h2>HTTP %03d</h2>', $code);
|
||||||
|
$body .= sprintf(' <p>%s</p>', $text);
|
||||||
|
$body .= '</div>';
|
||||||
|
$body .= HTML::getFooter();
|
||||||
|
$response->setContent($body);
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->use('/', function($response) use ($timing) {
|
||||||
|
$response->setPoweredBy('Mince+Index');
|
||||||
|
$response->setServerTiming($timing);
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->get('/index.php', function($response) {
|
||||||
|
$response->redirect('/', true);
|
||||||
|
});
|
||||||
|
$router->get('/map.php', function($response) {
|
||||||
|
$response->redirect('/maps/survival', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->get('/', function($response, $request) use ($db, $loginUrl, $userInfo, $sVerification) {
|
||||||
|
$name = (string)$request->getParam('name');
|
||||||
|
$error = (string)$request->getParam('error');
|
||||||
|
|
||||||
|
if(!empty($error) && ctype_lower($error)) {
|
||||||
|
$errors = [
|
||||||
|
'request' => ['Invalid request type.', 'Try to reload the page and try again.'],
|
||||||
|
'verify' => ['Request verification failed.', 'Try to reload the page and try again.'],
|
||||||
|
'itainthappenin' => ['Haha', 'No'],
|
||||||
|
'short' => ['Invalid username', 'The provided name is too short.'],
|
||||||
|
'long' => ['Invalid username', 'The provided name is too long.'],
|
||||||
|
'invalid' => ['Invalid username', 'The provided name contains invalid characters.'],
|
||||||
|
'conflict' => ['Username conflict', 'This username is already whitelisted with someone, contact flashwave if this is unexpected.'],
|
||||||
|
'connect' => ['Failed to connect to the server', 'The server is probably offline, pope flashwave if this is not expected.'],
|
||||||
|
'not-listed' => ['You have not been whitelisted yet', 'Add yourself to the whitelist before trying to remove yourself from it.'],
|
||||||
|
];
|
||||||
|
|
||||||
|
if(array_key_exists($error, $errors)) {
|
||||||
|
$mErrorTitle = $errors[$error][0];
|
||||||
|
$mErrorComment = $errors[$error][1];
|
||||||
|
} else {
|
||||||
|
$mErrorTitle = 'Unexpected response from server';
|
||||||
|
$mErrorComment = $error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = HTML::getHeader($userInfo, $loginUrl);
|
||||||
|
|
||||||
|
if(!empty($mErrorTitle)) {
|
||||||
|
$body .= '<div class="error">';
|
||||||
|
$body .= sprintf(' <h2>%s</h2>', $mErrorTitle);
|
||||||
|
$body .= sprintf(' <p>%s</p>', $mErrorComment ?? 'No further details provided.');
|
||||||
|
$body .= '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if($userInfo->success) {
|
||||||
|
if($userInfo->mc_whitelisted < 1) {
|
||||||
|
$body .= '<div class="whitelist">';
|
||||||
|
$body .= ' <h2>Add to Whitelist</h2>';
|
||||||
|
$body .= ' <p>This will give you access to the server.</p>';
|
||||||
|
$body .= ' <form method="post" action="/whitelist/add">';
|
||||||
|
$body .= sprintf(' <input type="hidden" name="boob" value="%s"/>', $sVerification);
|
||||||
|
$body .= ' <label>';
|
||||||
|
$body .= ' <div class="label-header">Username</div>';
|
||||||
|
$body .= sprintf(' <div class="label-input"><input type="text" name="name" value="%s" /></div>', htmlspecialchars($name));
|
||||||
|
$body .= ' </label>';
|
||||||
|
$body .= ' <input type="submit" value="Add me to the Whitelist"/>';
|
||||||
|
$body .= ' </form>';
|
||||||
|
$body .= '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$body .= '<div class="details">';
|
||||||
|
$body .= ' <h2>Server address</h2>';
|
||||||
|
$body .= ' <p style="color: red;">Down currently because I don\'t have the resources to run multiple games at once yet.</p>';
|
||||||
|
//$body .= ' <pre><code>mc.flashii.net</code></pre>';
|
||||||
|
//$body .= ' <p>An SRV record is used, so no port needs to be specified.</p>';
|
||||||
|
$body .= ' <p>We recommend you use <a href="https://multimc.org/" target="_blank" rel="noopener">MultiMC</a>/<a href="https://polymc.org/" target="_blank" rel="noopener">PolyMC</a> for easy version and mod management and <a href="https://adoptium.net/">Adoptium Java 17</a> to actually be able to launch the game. Other launchers work completely fine though.</p>';
|
||||||
|
$body .= '</div>';
|
||||||
|
|
||||||
|
$body .= '<div class="bedrock">';
|
||||||
|
$body .= ' <h2>Bedrock versions</h2>';
|
||||||
|
$body .= ' <p>Through the black magic bestowed upon us by <a href="https://geysermc.org/" target="_blank" rel="noopener">GeyserMC</a> it\'s possible to play on the server through any of the updated Bedrock versions of Minecraft.</p>';
|
||||||
|
$body .= ' <p>This should allow you to play on the server from a phone, a tablet or a console, provided you also have an account for the original version of the game.</p>';
|
||||||
|
$body .= ' <p>You will need to link your Minecraft and Bedrock accounts, you can do this by connecting to <code>link.geysermc.org</code> in both versions of the game and following the on-screen instructions.</p>';
|
||||||
|
$body .= ' <p>Unfortunately, the Bedrock versions of the game don\'t support SRV records, so you\'ll have to join with a different address:</p>';
|
||||||
|
//$body .= ' <pre><code>mcb.flashii.net:19132</code></pre>';
|
||||||
|
$body .= ' <p style="color: red;">Also down, lol!</p>';
|
||||||
|
$body .= '</div>';
|
||||||
|
|
||||||
|
if($userInfo->mc_whitelisted > 0) {
|
||||||
|
$body .= '<div class="unwhitelist">';
|
||||||
|
$body .= ' <h2>Remove from Whitelist</h2>';
|
||||||
|
$body .= ' <p>This will revoke your access to the server.</p>';
|
||||||
|
$body .= sprintf(' <p>You are currently whitelisted as <b>%s</b> on <b>%s</b>.</p>', $userInfo->mc_username, date('Y-m-d H:i:s T', $userInfo->mc_whitelisted));
|
||||||
|
$body .= ' <form method="post" action="/whitelist/remove">';
|
||||||
|
$body .= sprintf(' <input type="hidden" name="boob" value="%s"/>', $sVerification);
|
||||||
|
$body .= ' <input type="submit" value="Remove me from the whitelist"/>';
|
||||||
|
$body .= ' </form>';
|
||||||
|
$body .= '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$body .= '<div class="bedrock">';
|
||||||
|
$body .= ' <h2>All Of Fabric 5 (1.3.0)</h2>';
|
||||||
|
$body .= ' <pre><code>aof.flashii.net</code></pre>';
|
||||||
|
$body .= ' <p>An SRV record is used, so no port needs to be specified.</p>';
|
||||||
|
$body .= ' <p>There\'s a pack for <a href="https://multimc.org/" target="_blank" rel="noopener">MultiMC</a>/<a href="https://polymc.org/" target="_blank" rel="noopener">PolyMC</a> somewhere and you\'ll probably need <a href="https://adoptium.net/">Adoptium Java 17</a> to actually be able to launch the game. Other launchers work completely fine though, probably.</p>';
|
||||||
|
$body .= ' <p>This server doesn\'t currently use a whitelist, so you don\'t have to worry about that.</p>';
|
||||||
|
$body .= '</div>';
|
||||||
|
} else {
|
||||||
|
$body .= '<div class="loggedout">';
|
||||||
|
$body .= ' <h2>You must be logged in to use this website!</h2>';
|
||||||
|
$body .= ' <p>This website allows you to whitelist yourself on our Minecraft server, for which you need to be logged in.</p>';
|
||||||
|
$body .= ' <p>So it doesn\'t make sense to display the details either.</p>';
|
||||||
|
$body .= '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$body .= '<div class="rules">';
|
||||||
|
$body .= ' <h2>Rules</h2>';
|
||||||
|
$body .= ' <p>1. Observe <a href="https://flashii.net/info/rules">Global Rules</a>.</p>';
|
||||||
|
$body .= ' <p>2. Don\'t be an asshole.</p>';
|
||||||
|
$body .= ' <p>3. Don\'t flood.</p>';
|
||||||
|
$body .= '</div>';
|
||||||
|
|
||||||
|
$body .= HTML::getFooter();
|
||||||
|
|
||||||
|
return $body;
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->get('/maps', function($response) {
|
||||||
|
$response->redirect('/maps/survival');
|
||||||
|
});
|
||||||
|
$router->get('/maps/survival', function($response) use ($loginUrl, $userInfo) {
|
||||||
|
$body = HTML::getHeader($userInfo, $loginUrl);
|
||||||
|
|
||||||
|
$body .= '<div style="text-align: center">';
|
||||||
|
$body .= ' <iframe src="//mc-survival-map.mikoto.best/" width="854" height="480" allow="fullscreen" allowfullscreen style="border-width: 0;"></iframe>';
|
||||||
|
$body .= '</div>';
|
||||||
|
|
||||||
|
$body .= HTML::getFooter();
|
||||||
|
|
||||||
|
return $body;
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->use('/whitelist', function($response, $request) use ($sVerification) {
|
||||||
|
if(!$request->isFormContent()) {
|
||||||
|
$response->redirect('/?error=request');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = $request->getContent();
|
||||||
|
|
||||||
|
if(!$body->hasParam('boob') || !hash_equals($sVerification, (string)$body->getParam('boob'))) {
|
||||||
|
$response->redirect('/?error=verify');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->post('/whitelist/add', function($response, $request) use ($db, $userInfo) {
|
||||||
|
if($userInfo->user_id == 45) {
|
||||||
|
$response->redirect('/?error=itainthappenin');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = $request->getContent();
|
||||||
|
$name = (string)$body->getParam('name');
|
||||||
|
$resp = Whitelist::add($db, $userInfo, $name);
|
||||||
|
|
||||||
|
if($resp === '')
|
||||||
|
$response->redirect('/');
|
||||||
|
else {
|
||||||
|
if($resp === 'invalid')
|
||||||
|
$name = '';
|
||||||
|
$response->redirect("/?error={$resp}&name={$name}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->post('/whitelist/remove', function($response) use ($db, $userInfo) {
|
||||||
|
$resp = Whitelist::remove($db, $userInfo);
|
||||||
|
|
||||||
|
if($resp === '')
|
||||||
|
$response->redirect('/');
|
||||||
|
else
|
||||||
|
$response->redirect("/?error={$resp}");
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->get('/status', function($response) {
|
||||||
|
$response->redirect('/status/survival');
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->get('/status/survival', function() {
|
||||||
|
return '<!doctype html>todo: make something here';
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->get('/status/survival.json', function() {
|
||||||
|
return ServerQuery::create('mc.flashii.net')->stats();
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->get('/status/survival.png', function($response) {
|
||||||
|
$stats = ServerQuery::create('mc.flashii.net')->stats();
|
||||||
|
|
||||||
|
$image = new \Imagick;
|
||||||
|
$image->newImage(100, 100, 'black', 'png');
|
||||||
|
|
||||||
|
$draw = new \ImagickDraw;
|
||||||
|
$draw->setFillColor('white');
|
||||||
|
|
||||||
|
$image->annotateImage($draw, 10, 10, 0, $stats->motd);
|
||||||
|
|
||||||
|
$response->setContentType('image/png');
|
||||||
|
$response->setContent((string)$image);
|
||||||
|
|
||||||
|
$image->destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->get('/errors/:code', function($res, $req, $code) {
|
||||||
|
$code = intval($code);
|
||||||
|
if($code < 100 || $code >= 600)
|
||||||
|
$code = 400;
|
||||||
|
return $code;
|
||||||
|
});
|
||||||
|
|
||||||
|
$timing->lap('routes');
|
||||||
|
|
||||||
|
$router->dispatch();
|
157
public/mince.css
Normal file
157
public/mince.css
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
outline-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, a:active, a:visited {
|
||||||
|
color: #aaf;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
.wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: #111 url('/assets/bg_main.png');
|
||||||
|
color: #e0d0d0;
|
||||||
|
font: 13px/1.4 'Helvetica Neue', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background: #211710 url('/assets/bg_top.png');
|
||||||
|
height: 48px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.header-inner {
|
||||||
|
max-width: 1000px;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.header-fat {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
.header-logo {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
.header-logo img {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.header-user {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
color: #444;
|
||||||
|
height: 26px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
max-width: 1000px;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-top: 1em;
|
||||||
|
padding: 20px 0 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.details p {
|
||||||
|
margin: .2em 0;
|
||||||
|
}
|
||||||
|
.details pre {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #f33;
|
||||||
|
}
|
||||||
|
|
||||||
|
.whitelist {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.whitelist input[type="submit"] {
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: 1px solid #2a2;
|
||||||
|
background-color: #252;
|
||||||
|
color: #cfc;
|
||||||
|
transition: background-color .2s;
|
||||||
|
}
|
||||||
|
.whitelist input[type="submit"]:hover,
|
||||||
|
.whitelist input[type="submit"]:focus {
|
||||||
|
background-color: #272;
|
||||||
|
}
|
||||||
|
.whitelist input[type="submit"]:active {
|
||||||
|
background-color: #232;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unwhitelist {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.unwhitelist input[type="submit"] {
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: 1px solid #a22;
|
||||||
|
background-color: #522;
|
||||||
|
color: #fcc;
|
||||||
|
transition: background-color .2s;
|
||||||
|
}
|
||||||
|
.unwhitelist input[type="submit"]:hover,
|
||||||
|
.unwhitelist input[type="submit"]:focus {
|
||||||
|
background-color: #722;
|
||||||
|
}
|
||||||
|
.unwhitelist input[type="submit"]:active {
|
||||||
|
background-color: #322;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
margin-top: 1em;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
label .label-header {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 10px;
|
||||||
|
color: #AAA;
|
||||||
|
}
|
||||||
|
label .label-input input {
|
||||||
|
padding: 2px;
|
||||||
|
display: block;
|
||||||
|
font-size: 18px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
max-width: 300px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rules {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bedrock {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.bedrock pre {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
.bedrock p {
|
||||||
|
margin: .2em 0;
|
||||||
|
}
|
76
src/ChatAuth.php
Normal file
76
src/ChatAuth.php
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
namespace Mince;
|
||||||
|
|
||||||
|
use stdClass;
|
||||||
|
use Index\Data\IDbConnection;
|
||||||
|
|
||||||
|
final class ChatAuth {
|
||||||
|
public static function attempt(IDbConnection $db, string $endPoint, string $secret, string $cookie): object {
|
||||||
|
if(!empty($cookie)) {
|
||||||
|
$decoded = str_pad(base64_decode(str_pad(strtr($cookie, '-_', '+/'), strlen($cookie) % 4, '=', STR_PAD_RIGHT)), 37, "\0");
|
||||||
|
$unpacked = unpack('Cversion/Nuser/H*token', $decoded);
|
||||||
|
|
||||||
|
if(isset($unpacked['version']) && $unpacked['version'] === 1
|
||||||
|
&& isset($unpacked['user']) && $unpacked['user'] > 0) {
|
||||||
|
$loginRequest = [
|
||||||
|
'user_id' => $unpacked['user'],
|
||||||
|
'token' => 'SESS:' . $cookie,
|
||||||
|
'ip' => $_SERVER['REMOTE_ADDR'],
|
||||||
|
];
|
||||||
|
$loginSignature = hash_hmac('sha256', implode('#', $loginRequest), $secret);
|
||||||
|
|
||||||
|
$login = curl_init($endPoint);
|
||||||
|
curl_setopt_array($login, [
|
||||||
|
CURLOPT_AUTOREFERER => false,
|
||||||
|
CURLOPT_FAILONERROR => false,
|
||||||
|
CURLOPT_FOLLOWLOCATION => true,
|
||||||
|
CURLOPT_HEADER => false,
|
||||||
|
CURLOPT_POST => true,
|
||||||
|
CURLOPT_POSTFIELDS => json_encode($loginRequest),
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLOPT_TCP_FASTOPEN => true,
|
||||||
|
CURLOPT_CONNECTTIMEOUT => 2,
|
||||||
|
CURLOPT_MAXREDIRS => 2,
|
||||||
|
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
|
||||||
|
CURLOPT_TIMEOUT => 5,
|
||||||
|
CURLOPT_USERAGENT => 'mc.flashii.net',
|
||||||
|
CURLOPT_HTTPHEADER => [
|
||||||
|
'Content-Type: application/json',
|
||||||
|
'X-SharpChat-Signature: ' . $loginSignature,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$userInfo = json_decode(curl_exec($login));
|
||||||
|
curl_close($login);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(empty($userInfo->success)) {
|
||||||
|
$userInfo = new stdClass;
|
||||||
|
$userInfo->success = false;
|
||||||
|
$userInfo->user_id = 0;
|
||||||
|
$userInfo->username = 'Anonymous';
|
||||||
|
$userInfo->colour_raw = 0x40000000;
|
||||||
|
$userInfo->rank = 0;
|
||||||
|
$userInfo->hierarchy = 0;
|
||||||
|
$userInfo->is_silenced = '1970-01-01T00:00:00+00:00';
|
||||||
|
$userInfo->perms = 0;
|
||||||
|
$userInfo->mc_username = null;
|
||||||
|
$userInfo->mc_whitelisted = 0;
|
||||||
|
} else {
|
||||||
|
$getWhitelist = $db->prepare('SELECT `minecraft_username`, UNIX_TIMESTAMP(`whitelist_added`) AS `whitelist_added` FROM `whitelist_2022` WHERE `flashii_id` = ?');
|
||||||
|
$getWhitelist->addParameter(1, $userInfo->user_id);
|
||||||
|
$getWhitelist->execute();
|
||||||
|
$whitelist = $getWhitelist->getResult();
|
||||||
|
|
||||||
|
if($whitelist->next()) {
|
||||||
|
$userInfo->mc_username = $whitelist->getString(0);
|
||||||
|
$userInfo->mc_whitelisted = $whitelist->getInteger(1);
|
||||||
|
} else {
|
||||||
|
$userInfo->mc_username = null;
|
||||||
|
$userInfo->mc_whitelisted = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $userInfo;
|
||||||
|
}
|
||||||
|
}
|
48
src/HTML.php
Normal file
48
src/HTML.php
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
namespace Mince;
|
||||||
|
|
||||||
|
final class HTML {
|
||||||
|
public static function getHeader(object $userInfo, string $loginUrl, string $title = 'Flashii Minecraft Server'): string {
|
||||||
|
if($userInfo->success) {
|
||||||
|
$userBar = 'Logged in as ' . $userInfo->username;
|
||||||
|
} else {
|
||||||
|
$userBar = '<a href="' . $loginUrl . '">Log in</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return <<<HTML
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>{$title}</title>
|
||||||
|
<link href="/mince.css" type="text/css" rel="stylesheet"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="wrapper">
|
||||||
|
<nav class="header">
|
||||||
|
<div class="header-inner">
|
||||||
|
<div class="header-logo">
|
||||||
|
<a href="/"><img src="/assets/weblogo.png" alt="Flashii Minecraft"/></a>
|
||||||
|
</div>
|
||||||
|
<div class="header-fat"></div>
|
||||||
|
<div class="header-user">
|
||||||
|
{$userBar}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="content">
|
||||||
|
HTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getFooter(): string {
|
||||||
|
return <<<HTML
|
||||||
|
</div>
|
||||||
|
<footer class="footer">
|
||||||
|
<a href="https://flash.moe">Flashwave</a> 2022 | Site design "borrowed" from pre-Microsoft Mojang | "Minecraft" is a trademark of Mojang
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
HTML;
|
||||||
|
}
|
||||||
|
}
|
45
src/Remote.php
Normal file
45
src/Remote.php
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
namespace Mince;
|
||||||
|
|
||||||
|
final class Remote {
|
||||||
|
private static string $url = '';
|
||||||
|
private static string $secret = '';
|
||||||
|
|
||||||
|
public static function setUrl(string $url): void {
|
||||||
|
self::$url = $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function setSecret(string $secret): void {
|
||||||
|
self::$secret = $secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function call(string $mode, string $name): string {
|
||||||
|
$time = (string)floor(time() / 120);
|
||||||
|
$sign = hash_hmac('sha256', "{$time}#{$mode}#{$name}", self::$secret, true);
|
||||||
|
|
||||||
|
$request = curl_init(self::$url);
|
||||||
|
curl_setopt_array($request, [
|
||||||
|
CURLOPT_AUTOREFERER => false,
|
||||||
|
CURLOPT_FAILONERROR => false,
|
||||||
|
CURLOPT_FOLLOWLOCATION => true,
|
||||||
|
CURLOPT_HEADER => false,
|
||||||
|
CURLOPT_POST => true,
|
||||||
|
CURLOPT_POSTFIELDS => [
|
||||||
|
'm' => $mode,
|
||||||
|
's' => $sign,
|
||||||
|
'n' => $name,
|
||||||
|
],
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLOPT_TCP_FASTOPEN => true,
|
||||||
|
CURLOPT_CONNECTTIMEOUT => 2,
|
||||||
|
CURLOPT_MAXREDIRS => 2,
|
||||||
|
CURLOPT_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
|
||||||
|
CURLOPT_TIMEOUT => 5,
|
||||||
|
CURLOPT_USERAGENT => 'mc.flashii.net',
|
||||||
|
]);
|
||||||
|
$response = curl_exec($request);
|
||||||
|
curl_close($request);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
166
src/ServerQuery.php
Normal file
166
src/ServerQuery.php
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
<?php
|
||||||
|
namespace Mince;
|
||||||
|
|
||||||
|
use stdClass;
|
||||||
|
use RuntimeException;
|
||||||
|
use Socket;
|
||||||
|
use Index\AString;
|
||||||
|
use Index\Net\EndPoint;
|
||||||
|
use Index\Net\IPAddress;
|
||||||
|
use Index\Net\IPEndPoint;
|
||||||
|
use Index\Net\DnsEndPoint;
|
||||||
|
|
||||||
|
class ServerQuery { // rewrite this to use https://wiki.vg/Server_List_Ping query is kinda useless
|
||||||
|
public const PORT = 25565;
|
||||||
|
|
||||||
|
private string $addr;
|
||||||
|
private int $port;
|
||||||
|
private Socket $socket;
|
||||||
|
private int $sessionId;
|
||||||
|
private int $challengeToken = 0;
|
||||||
|
|
||||||
|
public function __construct(IPAddress $addr, int $port) {
|
||||||
|
$this->addr = (string)$addr;
|
||||||
|
$this->port = $port;
|
||||||
|
$this->sessionId = random_int(0, 0x7FFFFFFF) & 0x0F0F0F0F;
|
||||||
|
$this->socket = socket_create($addr->isV6() ? AF_INET6 : AF_INET, SOCK_DGRAM, SOL_UDP);
|
||||||
|
$this->handshake();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
socket_close($this->socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handshake(): void {
|
||||||
|
$response = $this->send(9);
|
||||||
|
$length = strlen($response);
|
||||||
|
$token = '';
|
||||||
|
|
||||||
|
for($i = 0; $i < $length; ++$i) {
|
||||||
|
$char = $response[$i];
|
||||||
|
if($char === "\0")
|
||||||
|
break;
|
||||||
|
$token .= $char;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->challengeToken = intval($token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stats(): object {
|
||||||
|
$response = $this->send(0, pack('N', $this->challengeToken));
|
||||||
|
|
||||||
|
$offset = 0;
|
||||||
|
$data = new stdClass;
|
||||||
|
|
||||||
|
$data->motd = self::readString($response, $offset);
|
||||||
|
$data->gametype = self::readString($response, $offset);
|
||||||
|
$data->map = self::readString($response, $offset);
|
||||||
|
$data->numplayers = self::readString($response, $offset);
|
||||||
|
$data->maxplayers = self::readString($response, $offset);
|
||||||
|
$data->hostport = unpack('v', substr($response, $offset, 2))[1];
|
||||||
|
$offset += 2;
|
||||||
|
$data->hostip = self::readString($response, $offset);
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function readString(string $source, int &$offset): string {
|
||||||
|
$length = strlen($source);
|
||||||
|
$string = '';
|
||||||
|
|
||||||
|
for(; $offset < $length; ++$offset) {
|
||||||
|
$char = $source[$offset];
|
||||||
|
if($char === "\0")
|
||||||
|
break;
|
||||||
|
$string .= $char;
|
||||||
|
}
|
||||||
|
|
||||||
|
++$offset;
|
||||||
|
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function send(int $type, string $payload = ''): string {
|
||||||
|
$payload = "\xFE\xFD" . pack('CN', $type, $this->sessionId) . $payload;
|
||||||
|
socket_sendto($this->socket, $payload, strlen($payload), 0, $this->addr, $this->port);
|
||||||
|
socket_recv($this->socket, $response, 1024, MSG_WAITALL);
|
||||||
|
|
||||||
|
$data = unpack('Ctype/Nsession', $response);
|
||||||
|
|
||||||
|
if($data['type'] !== $type)
|
||||||
|
throw new RuntimeException('Type does not match.');
|
||||||
|
if($data['session'] !== $this->sessionId)
|
||||||
|
throw new RuntimeException('Session id does not match.');
|
||||||
|
|
||||||
|
return substr($response, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function create(AString|string $endPoint): ServerQuery {
|
||||||
|
$endPoint = AString::cast($endPoint);
|
||||||
|
$firstChar = $endPoint[0];
|
||||||
|
|
||||||
|
if($firstChar === '[') { // IPv6
|
||||||
|
if($endPoint->contains(']:'))
|
||||||
|
$endPoint = IPEndPoint::parse($endPoint);
|
||||||
|
else
|
||||||
|
$endPoint = new IPEndPoint(IPAddress::parse($endPoint->trim('[]')), self::PORT);
|
||||||
|
|
||||||
|
return new ServerQuery($endPoint->getAddress(), $endPoint->getPort());
|
||||||
|
} elseif(is_numeric($firstChar)) { // IPv4
|
||||||
|
if($endPoint->contains(':'))
|
||||||
|
$endPoint = IPEndPoint::parse($endPoint);
|
||||||
|
else
|
||||||
|
$endPoint = new IPEndPoint(IPAddress::parse($endPoint), self::PORT);
|
||||||
|
|
||||||
|
return new ServerQuery($endPoint->getAddress(), $endPoint->getPort());
|
||||||
|
} else { // DNS
|
||||||
|
if($endPoint->contains(':'))
|
||||||
|
$endPoint = DnsEndPoint::parse($endPoint);
|
||||||
|
else {
|
||||||
|
$endPoint = new DnsEndPoint($endPoint, self::PORT);
|
||||||
|
|
||||||
|
$records = dns_get_record('_minecraft._tcp.' . (string)$endPoint->getHost(), DNS_SRV);
|
||||||
|
|
||||||
|
if(!empty($records)) {
|
||||||
|
usort($records, function($a, $b) {
|
||||||
|
$priority = $a['pri'] <=> $b['pri'];
|
||||||
|
if($priority !== 0)
|
||||||
|
return $priority;
|
||||||
|
$weight = $a['weight'] <=> $b['weight'];
|
||||||
|
if($weight !== 0)
|
||||||
|
return $priority;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach($records as $record) {
|
||||||
|
try {
|
||||||
|
return ServerQuery::create($record['target'] . ':' . $record['port']);
|
||||||
|
} catch(Exception $ex) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$records = dns_get_record((string)$endPoint->getHost(), DNS_A);
|
||||||
|
|
||||||
|
if(!empty($records)) {
|
||||||
|
foreach($records as $record) {
|
||||||
|
try {
|
||||||
|
return new ServerQuery(IPAddress::parse($record['ip']), $endPoint->getPort());
|
||||||
|
} catch(Exception $ex) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$records = dns_get_record((string)$endPoint->getHost(), DNS_AAAA);
|
||||||
|
|
||||||
|
if(!empty($records)) {
|
||||||
|
foreach($records as $record) {
|
||||||
|
try {
|
||||||
|
return new ServerQuery(IPAddress::parse($record['ipv6']), $endPoint->getPort());
|
||||||
|
} catch(Exception $ex) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException('Failed to connect.');
|
||||||
|
}
|
||||||
|
}
|
14
src/Utils.php
Normal file
14
src/Utils.php
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
namespace Mince;
|
||||||
|
|
||||||
|
final class Utils {
|
||||||
|
private const CHARS = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789';
|
||||||
|
|
||||||
|
public static function generatePassKey(int $length): string {
|
||||||
|
$keyChars = strlen(self::CHARS) - 1;
|
||||||
|
$bytes = str_repeat("\0", $length);
|
||||||
|
for($i = 0; $i < $length; ++$i)
|
||||||
|
$bytes[$i] = self::CHARS[random_int(0, $keyChars)];
|
||||||
|
return $bytes;
|
||||||
|
}
|
||||||
|
}
|
67
src/Whitelist.php
Normal file
67
src/Whitelist.php
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
namespace Mince;
|
||||||
|
|
||||||
|
use Index\Data\IDbConnection;
|
||||||
|
use Index\Data\DbType;
|
||||||
|
|
||||||
|
final class Whitelist {
|
||||||
|
public static function add(IDbConnection $db, object $userInfo, string $userName): string {
|
||||||
|
$length = strlen($userName);
|
||||||
|
if($length < 3)
|
||||||
|
return 'short';
|
||||||
|
if($length > 16)
|
||||||
|
return 'long';
|
||||||
|
if(!preg_match('#^([a-zA-Z0-9_]{3,16})$#', $userName))
|
||||||
|
return 'invalid';
|
||||||
|
|
||||||
|
$dupeCheck = $db->prepare('SELECT COUNT(`flashii_id`) > 0 FROM `whitelist_2022` WHERE `minecraft_username` = ?');
|
||||||
|
$dupeCheck->addParameter(1, $userName, DbType::STRING);
|
||||||
|
$dupeCheck->execute();
|
||||||
|
$dupeResult = $dupeCheck->getResult();
|
||||||
|
|
||||||
|
if(!$dupeResult->next())
|
||||||
|
return 'dupefail';
|
||||||
|
if($dupeResult->getInteger(0))
|
||||||
|
return 'conflict';
|
||||||
|
|
||||||
|
if(!empty($userInfo->mc_whitelisted) || !empty($userInfo->mc_username)) {
|
||||||
|
$resp = self::remove($db, $userInfo);
|
||||||
|
if($resp !== '')
|
||||||
|
return $resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
$resp = Remote::call('wl:add', $userName);
|
||||||
|
|
||||||
|
if($resp !== 'success')
|
||||||
|
return $resp;
|
||||||
|
|
||||||
|
$insert = $db->prepare('INSERT INTO `whitelist_2022` (`flashii_id`, `minecraft_username`) VALUES (?, ?)');
|
||||||
|
$insert->addParameter(1, $userInfo->user_id);
|
||||||
|
$insert->addParameter(2, $userName, DbType::STRING);
|
||||||
|
$insert->execute();
|
||||||
|
|
||||||
|
$userInfo->mc_username = $userName;
|
||||||
|
$userInfo->mc_whitelisted = time();
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function remove(IDbConnection $db, object $userInfo): string {
|
||||||
|
if(empty($userInfo->mc_whitelisted) || empty($userInfo->mc_username))
|
||||||
|
return 'not-listed';
|
||||||
|
|
||||||
|
$resp = Remote::call('wl:remove', $userInfo->mc_username);
|
||||||
|
|
||||||
|
if($resp !== 'success')
|
||||||
|
return $resp;
|
||||||
|
|
||||||
|
$delete = $db->prepare('DELETE FROM `whitelist_2022` WHERE `flashii_id` = ?');
|
||||||
|
$delete->addParameter(1, $userInfo->user_id);
|
||||||
|
$delete->execute();
|
||||||
|
|
||||||
|
$userInfo->mc_username = null;
|
||||||
|
$userInfo->mc_whitelisted = 0;
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue