Compare commits

..

7 Commits

66 changed files with 998 additions and 478 deletions

View File

@ -62,26 +62,30 @@ function donothing()
function primary() function primary()
{ {
if (isset($_POST["submit"])) { if (isset($_POST["submit"])) {
$errors = []; $form = validate($_POST, [
'gamename' => ['alphanum-spaces', 'length:1-20'],
'gamesize' => ['int', 'min:5'],
'class1name' => ['alpha-spaces', 'length:1-18'],
'class2name' => ['alpha-spaces', 'length:1-18'],
'class3name' => ['alpha-spaces', 'length:1-18'],
'gameopen' => ['bool'],
'verifyemail' => ['bool'],
'shownews' => ['bool'],
'showonline' => ['bool'],
'showbabble' => ['bool']
]);
$gn = trim($_POST['gamename'] ?? 'Dragon Knight'); if ($form['valid']) {
$gs = (int) trim($_POST['gamesize'] ?? 250); $form = $form['data'];
$c1n = trim($_POST['class1name'] ?? 'Mage'); if (($form['gamesize'] % 5) != 0) exit('Map size must be divisible by five.');
$c2n = trim($_POST['class2name'] ?? 'Warrior');
$c3n = trim($_POST['class3name'] ?? 'Paladin');
if (empty($gn)) $errors[] = "Game name is required.";
if (!is_int($gs) || !($gs > 0) || ($gs % 5) != 0) $errors[] = "Map size must be a number greater than 0 and divisible by five.";
if (empty($c1n) || empty($c2n) || empty($c3n)) $errors[] = "Class names are required.";
if (count($errors) === 0) {
db()->query('UPDATE control SET gamename=?, gamesize=?, class1name=?, class2name=?, class3name=?, gameopen=?, verifyemail=?, gameurl=?, adminemail=?, shownews=?, showonline=?, showbabble=? WHERE id=1;', [ db()->query('UPDATE control SET gamename=?, gamesize=?, class1name=?, class2name=?, class3name=?, gameopen=?, verifyemail=?, gameurl=?, adminemail=?, shownews=?, showonline=?, showbabble=? WHERE id=1;', [
$gn, $gs, $c1n, $c2n, $c3n, $_POST['gameopen'] ?? 1, $_POST['verifyemail'] ?? 1, $_POST['gameurl'] ?? '', $_POST['adminemail'] ?? '', $_POST['shownews'] ?? 1, $_POST['showonline'] ?? 1, $_POST['showbabble'] ?? 1 $form['gamename'], $form['gamesize'], $form['class1name'], $form['class1name'], $form['class1name'], $form['gameopen'], $form['verifyemail'], $form['gameurl'], $form['adminemail'], $form['shownews'], $form['showonline'], $form['showbabble']
]); ]);
admindisplay("Settings updated.", "Main Settings"); admindisplay("Settings updated.", "Main Settings");
} else { } else {
$errorlist = implode('<br>', $errors); $errorlist = ul_from_validate_errors($form['errors']);
admindisplay("<b>Errors:</b><br><div style=\"color:red;\">$errorlist</div><br>Please go back and try again.", "Main Settings"); admindisplay("<b>Errors:</b><br><div style=\"color:red;\">$errorlist</div><br>Please go back and try again.", "Main Settings");
} }
} }
@ -95,7 +99,7 @@ function primary()
<table width="90%"> <table width="90%">
<tr><td width="20%"><span class="highlight">Game Open:</span></td><td><select name="gameopen"><option value="1" {{open1select}}>Open</option><option value="0" {{open0select}}>Closed</option></select><br><span class="small">Close the game if you are upgrading or working on settings and don't want to cause odd errors for end-users. Closing the game will completely halt all activity.</span></td></tr> <tr><td width="20%"><span class="highlight">Game Open:</span></td><td><select name="gameopen"><option value="1" {{open1select}}>Open</option><option value="0" {{open0select}}>Closed</option></select><br><span class="small">Close the game if you are upgrading or working on settings and don't want to cause odd errors for end-users. Closing the game will completely halt all activity.</span></td></tr>
<tr><td width="20%">Game Name:</td><td><input type="text" name="gamename" value="{{gamename}}" /><br><span class="small">Default is "Dragon Knight". Change this if you want to change to call your game something different.</span></td></tr> <tr><td width="20%">Game Name:</td><td><input type="text" name="gamename" value="{{gamename}}" /><br><span class="small">Default is "Dragon Knight". Change this if you want to change to call your game something different.</span></td></tr>
<tr><td width="20%">Game URL:</td><td><input type="text" name="gameurl" value="{{gameurl}}" /><br><span class="small">Please specify the full URL to your game installation ("http://www.server.com/dkpath/index.php"). This gets used in the registration email sent to users. If you leave this field blank or incorrect, users may not be able to register correctly.</span></td></tr> <tr><td width="20%">Game URL:</td><td><input type="text" name="gameurl" value="{{gameurl}}" /><br><span class="small">Please specify the full URL to your game installation ("https://www.dragonknight.com/"). This gets used in the registration email sent to users. If you leave this field blank or incorrect, users may not be able to register correctly.</span></td></tr>
<tr><td width="20%">Admin Email:</td><td><input type="text" name="adminemail" value="{{adminemail}}" /><br><span class="small">Please specify your email address. This gets used when the game has to send an email to users.</span></td></tr> <tr><td width="20%">Admin Email:</td><td><input type="text" name="adminemail" value="{{adminemail}}" /><br><span class="small">Please specify your email address. This gets used when the game has to send an email to users.</span></td></tr>
<tr><td width="20%">Map Size:</td><td><input type="text" name="gamesize" value="{{gamesize}}" /><br><span class="small">Default is 250. This is the size of each map quadrant. Note that monster levels increase every 5 spaces, so you should ensure that you have at least (map size / 5) monster levels total, otherwise there will be parts of the map without any monsters, or some monsters won't ever get used. Ex: with a map size of 250, you should have 50 monster levels total.</span></td></tr> <tr><td width="20%">Map Size:</td><td><input type="text" name="gamesize" value="{{gamesize}}" /><br><span class="small">Default is 250. This is the size of each map quadrant. Note that monster levels increase every 5 spaces, so you should ensure that you have at least (map size / 5) monster levels total, otherwise there will be parts of the map without any monsters, or some monsters won't ever get used. Ex: with a map size of 250, you should have 50 monster levels total.</span></td></tr>
<tr><td width="20%">Email Verification:</td><td><select name="verifyemail"><option value="0" {{selectverify0}}>Disabled</option><option value="1" {{selectverify1}}>Enabled</option></select><br><span class="small">Make users verify their email address for added security.</span></td></tr> <tr><td width="20%">Email Verification:</td><td><select name="verifyemail"><option value="0" {{selectverify0}}>Disabled</option><option value="1" {{selectverify1}}>Enabled</option></select><br><span class="small">Make users verify their email address for added security.</span></td></tr>

181
public/css/dk.css Normal file
View File

@ -0,0 +1,181 @@
:root {
--font-size: 12px;
}
html {
font-size: var(--font-size);
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
body {
background-image: url('/img/background.jpg');
}
div#game-container {
max-width: 1280px;
margin: 0 auto;
padding: 1rem;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: solid 2px black;
padding-bottom: 0.5rem;
}
main {
width: 100%;
display: flex;
margin-bottom: 0.5rem;
}
main > section {
padding: 4px;
}
main > section > section:not(:last-child) {
margin-bottom: 2rem;
}
main section#left {
width: 180px;
border-right: solid 2px black;
}
main section#middle {
flex-grow: 1;
}
main section#right {
width: 180px;
border-left: solid 2px black;
}
footer {
display: flex;
justify-content: space-around;
border: solid 1px black;
background-color: #eeeeee;
font-size: 0.8rem;
padding: 0.5rem;
}
table {
border-style: none;
padding: 0px;
font-size: var(--font-size);
}
td {
border-style: none;
padding: 3px;
vertical-align: top;
}
td.top {
border-bottom: solid 2px black;
}
td.left {
width: 180px;
border-right: solid 2px black;
}
td.right {
width: 180px;
border-left: solid 2px black;
}
a {
color: #663300;
text-decoration: none;
font-weight: bold;
}
a:hover {
color: #330000;
}
.small {
font: 10px verdana;
}
.highlight {
color: red;
}
.light {
color: #999999;
}
.title {
border: solid 1px black;
background-color: #eeeeee;
font-weight: bold;
padding: 5px;
font-size: 1.2rem;
font-family: 'Times New Roman', Times, serif;
}
.copyright {
border: solid 1px black;
background-color: #eeeeee;
font: 10px verdana;
}
.move-compass {
width: 128px;
height: 128px;
display: flex;
flex-direction: column;
background-image: url('/img/compass.webp');
margin: 0.5rem auto;
}
.move-compass div.mid {
display: flex;
}
.move-compass button {
background-color: transparent;
border: none;
color: transparent; /* Hide the text */
background-size: cover; /* Ensure the background image fills the button */
cursor: pointer;
}
.move-compass button:hover {
background-color: rgba(225, 16, 16, 0.5);
}
.move-compass button.north {
width: 128px;
height: 40px;
}
.move-compass button.west {
width: 63px;
height: 50px;
}
.move-compass button.east {
width: 63px;
height: 50px;
}
.move-compass button.south {
width: 128px;
height: 38px;
}
div.town-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
div.town-content div.options, div.town-content div.news {
grid-column: span 2;
}

View File

@ -85,13 +85,22 @@ function reply()
{ {
global $userrow; global $userrow;
$p = $_POST['parent'] ?? 0; $form = validate($_POST, [
$t = trim($_POST['title'] ?? ''); 'title' => ['length:2-30', 'alphanum-spaces'],
$c = trim($_POST['content'] ?? ''); 'content' => []
]);
db()->query('INSERT INTO forum (author, title, content, parent) VALUES (?, ?, ?, ?);', [$userrow['username'], $t, $c, $p]); if (!$form['valid']) {
db()->query('UPDATE forum SET newpostdate=CURRENT_TIMESTAMP, replies=replies + 1 WHERE id=?;', [$p]); exit(ul_from_validate_errors($form['errors']));
redirect("forum.php?do=thread:$p:0"); }
$form = $form['data'];
db()->query('INSERT INTO forum (author, title, content, parent) VALUES (?, ?, ?, ?);', [
$userrow['username'], $form['title'], $form['content'], $form['parent']
]);
db()->query('UPDATE forum SET newpostdate=CURRENT_TIMESTAMP, replies=replies + 1 WHERE id=?;', [$form['parent']]);
redirect("forum.php?do=thread:{$form['parent']}:0");
} }
function newthread() function newthread()
@ -99,10 +108,19 @@ function newthread()
global $userrow; global $userrow;
if (isset($_POST["submit"])) { if (isset($_POST["submit"])) {
extract($_POST); $form = validate($_POST, [
$t = trim($_POST['title'] ?? ''); 'title' => ['length:2-30', 'alphanum-spaces'],
$c = trim($_POST['content'] ?? ''); 'content' => []
db()->query('INSERT INTO forum (author, title, content) VALUES (?, ?, ?);', [$userrow['username'], $t, $c]); ]);
if (!$form['valid']) {
exit(ul_from_validate_errors($form['errors']));
}
$form = $form['data'];
db()->query('INSERT INTO forum (author, title, content) VALUES (?, ?, ?);', [
$userrow['username'], $form['title'], $form['content']
]);
redirect('forum.php'); redirect('forum.php');
} }

View File

@ -16,7 +16,7 @@ if (!in_array($page, ['main', 'items', 'levels', 'monsters', 'spells'])) $page =
<title><?= $controlrow["gamename"] ?> Help</title> <title><?= $controlrow["gamename"] ?> Help</title>
<style type="text/css"> <style type="text/css">
body { body {
background-image: url('images/background.jpg'); background-image: url('/img/background.jpg');
color: black; color: black;
font: 11px verdana; font: 11px verdana;
} }
@ -78,7 +78,7 @@ if (!in_array($page, ['main', 'items', 'levels', 'monsters', 'spells'])) $page =
<body> <body>
<a name="top"></a> <a name="top"></a>
<h1><?= $controlrow["gamename"] ?> Help</h1> <h1><?= $controlrow["gamename"] ?> Help</h1>
[ <a href="/index.php">Return to the game</a> ] [ <a href="/">Return to the game</a> ]
<br><br><hr> <br><br><hr>
@ -300,7 +300,7 @@ if (!in_array($page, ['main', 'items', 'levels', 'monsters', 'spells'])) $page =
</ul> </ul>
Apologies and lots of happy naked love to anyone I forgot. <br><br> Apologies and lots of happy naked love to anyone I forgot. <br><br>
And of course, thanks to <b>you</b> for playing my game! <br><br> And of course, thanks to <b>you</b> for playing my game! <br><br>
<a href="/index.php?do=ninja">NINJA!</a> <br><br> <a href="/ninja">NINJA!</a> <br><br>
[ <a href="#top">Top</a> ] [ <a href="#top">Top</a> ]
<br><br><hr><br> <br><br><hr><br>
@ -342,7 +342,7 @@ if (!in_array($page, ['main', 'items', 'levels', 'monsters', 'spells'])) $page =
$bigspecial = '<span class="light">None</span>'; $bigspecial = '<span class="light">None</span>';
} }
echo "<tr><td width=\"5%\"><img src=\"images/icon_$image.gif\" alt=\"$image\"></td><td width=\"30%\">".$item["name"]."</td><td width=\"20%\">".$item["buycost"]." Gold</td><td width=\"20%\">".$item["attribute"]." $power Power</td><td width=\"25%\">$bigspecial</td></tr>\n"; echo "<tr><td width=\"5%\"><img src=\"/img/icon_$image.gif\" alt=\"$image\"></td><td width=\"30%\">".$item["name"]."</td><td width=\"20%\">".$item["buycost"]." Gold</td><td width=\"20%\">".$item["attribute"]." $power Power</td><td width=\"25%\">$bigspecial</td></tr>\n";
} }
?> ?>
</table> </table>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 527 B

After

Width:  |  Height:  |  Size: 527 B

View File

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 575 B

View File

Before

Width:  |  Height:  |  Size: 561 B

After

Width:  |  Height:  |  Size: 561 B

View File

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 402 B

View File

Before

Width:  |  Height:  |  Size: 551 B

After

Width:  |  Height:  |  Size: 551 B

View File

Before

Width:  |  Height:  |  Size: 486 B

After

Width:  |  Height:  |  Size: 486 B

View File

Before

Width:  |  Height:  |  Size: 474 B

After

Width:  |  Height:  |  Size: 474 B

View File

Before

Width:  |  Height:  |  Size: 500 B

After

Width:  |  Height:  |  Size: 500 B

View File

Before

Width:  |  Height:  |  Size: 523 B

After

Width:  |  Height:  |  Size: 523 B

View File

Before

Width:  |  Height:  |  Size: 565 B

After

Width:  |  Height:  |  Size: 565 B

View File

Before

Width:  |  Height:  |  Size: 469 B

After

Width:  |  Height:  |  Size: 469 B

View File

Before

Width:  |  Height:  |  Size: 469 B

After

Width:  |  Height:  |  Size: 469 B

View File

Before

Width:  |  Height:  |  Size: 461 B

After

Width:  |  Height:  |  Size: 461 B

BIN
public/img/compass.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 147 B

After

Width:  |  Height:  |  Size: 147 B

View File

Before

Width:  |  Height:  |  Size: 121 B

After

Width:  |  Height:  |  Size: 121 B

View File

Before

Width:  |  Height:  |  Size: 112 B

After

Width:  |  Height:  |  Size: 112 B

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1005 B

After

Width:  |  Height:  |  Size: 1005 B

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -3,6 +3,7 @@
// index.php :: Primary program script, evil alien overlord, you decide. // index.php :: Primary program script, evil alien overlord, you decide.
require_once '../src/lib.php'; require_once '../src/lib.php';
require_once '../src/router.php';
if (!file_exists('../.installed')) redirect('install.php'); if (!file_exists('../.installed')) redirect('install.php');
@ -41,31 +42,64 @@ require_once '../src/explore.php';
require_once '../src/fight.php'; require_once '../src/fight.php';
require_once '../src/heal.php'; require_once '../src/heal.php';
$do = explode(':', $_GET['do'] ?? ''); $r = new Router;
match ($do[0]) {
'inn' => inn(), $r->get('/', function() {
'buy' => buy(), global $userrow;
'buy2' => buy2($do[1]),
'buy3' => buy3($do[1]), if ($userrow["currentaction"] == "In Town") {
// 'sell' => sell(), $page = dotown();
'maps' => maps(), $title = "In Town";
'maps2' => maps2($do[1]), } elseif ($userrow["currentaction"] == "Exploring") {
'maps3' => maps3($do[1]), $page = doexplore();
'gotown' => travelto($do[1]), $title = "Exploring";
'move' => move(), } elseif ($userrow["currentaction"] == "Fighting") {
'fight' => fight(), redirect('/fight');
'victory' => victory(), }
'drop' => drop(),
'dead' => dead(), display($page, $title);
'verify' => header("Location: users.php?do=verify"), });
'spell' => healspells($do[1]),
'showchar' => showchar(), $r->get('/ninja', function() {
'onlinechar' => onlinechar($do[1]), exit('NINJA! 🥷');
'showmap' => showmap(), });
'babblebox' => babblebox(),
'ninja' => ninja(), $r->get('/inn', 'inn');
default => donothing() $r->post('/inn', 'inn');
}; $r->get('/buy', 'buy');
$r->get('/buy2/:id', 'buy2');
$r->post('/buy3/:id', 'buy3');
// $r->get('/sell', 'sell');
$r->get('/maps', 'maps');
$r->get('/maps2/:id', 'maps2');
$r->post('/maps3/:id', 'maps3');
$r->get('/gotown/:id', 'travelto');
$r->post('/move', 'move');
$r->get('/fight', 'fight');
$r->post('/fight', 'fight');
$r->get('/victory', 'victory');
$r->get('/drop', 'drop');
$r->post('/drop', 'drop');
$r->get('/dead', 'dead');
$r->get('/verify', function() {
redirect('users.php?do=verify');
});
$r->get('/spell/:id', 'healspells');
$r->get('/showchar', 'showchar');
$r->get('/onlinechar/:id', 'onlinechar');
$r->get('/showmap', 'showmap');
$r->get('/babblebox', 'babblebox');
$r->post('/babblebox', 'babblebox');
// [code, handler, params, middleware]
$l = $r->lookup($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
if ($l['code'] !== 200) exit($l['code']);
if (!empty($l['middleware'])) foreach ($l['middleware'] as $middleware) $middleware();
$l['handler'](...$l['params'] ?? []);
function donothing() function donothing()
{ {
@ -78,7 +112,7 @@ function donothing()
$page = doexplore(); $page = doexplore();
$title = "Exploring"; $title = "Exploring";
} elseif ($userrow["currentaction"] == "Fighting") { } elseif ($userrow["currentaction"] == "Fighting") {
redirect('index.php?do=fight'); redirect('/fight');
} }
display($page, $title); display($page, $title);
@ -101,9 +135,8 @@ function dotown()
// News box. Grab latest news entry and display it. Something a little more graceful coming soon maybe. // News box. Grab latest news entry and display it. Something a little more graceful coming soon maybe.
if ($controlrow["shownews"] == 1) { if ($controlrow["shownews"] == 1) {
$newsrow = db()->query('SELECT * FROM news ORDER BY id DESC LIMIT 1;')->fetchArray(SQLITE3_ASSOC); $newsrow = db()->query('SELECT * FROM news ORDER BY id DESC LIMIT 1;')->fetchArray(SQLITE3_ASSOC);
$townrow["news"] = "<table width=\"95%\"><tr><td class=\"title\">Latest News</td></tr><tr><td>\n"; $townrow["news"] = '<div class="title">Latest News</div>';
$townrow["news"] .= "<span class=\"light\">[".prettydate($newsrow["postdate"])."]</span><br>".nl2br($newsrow["content"]); $townrow["news"] .= "<span class=\"light\">[".prettydate($newsrow["postdate"])."]</span><br>".nl2br($newsrow["content"]);
$townrow["news"] .= "</td></tr></table>\n";
} }
// Who's Online. Currently just members. Guests maybe later. // Who's Online. Currently just members. Guests maybe later.
@ -115,25 +148,21 @@ function dotown()
while ($onlinerow = $onlinequery->fetchArray(SQLITE3_ASSOC)) { while ($onlinerow = $onlinequery->fetchArray(SQLITE3_ASSOC)) {
$online_count++; $online_count++;
$online_rows[] = "<a href=\"index.php?do=onlinechar:".$onlinerow["id"]."\">".$onlinerow["username"]."</a>"; $online_rows[] = "<a href=\"/onlinechar/{$onlinerow["id"]}\">".$onlinerow["username"]."</a>";
} }
$townrow["whosonline"] = "<table width=\"95%\"><tr><td class=\"title\">Who's Online</td></tr><tr><td>\n"; $townrow["whosonline"] = '<div class="title">Who\'s Online</div>';
$townrow["whosonline"] .= "There are <b>$online_count</b> user(s) online within the last 10 minutes: "; $townrow["whosonline"] .= "There are <b>$online_count</b> user(s) online within the last 10 minutes: ";
$townrow["whosonline"] .= rtrim(implode(', ', $online_rows), ', '); $townrow["whosonline"] .= rtrim(implode(', ', $online_rows), ', ');
$townrow["whosonline"] .= "</td></tr></table>\n";
} }
if ($controlrow["showbabble"] == 1) { if ($controlrow["showbabble"] == 1) {
$townrow["babblebox"] = <<<HTML $townrow["babblebox"] = <<<HTML
<table width="95%"> <div class="title">Babble Box</div>
<tr><td class="title">Babble Box</td></tr> <iframe src="/babblebox" name="sbox" width="100%" height="250" frameborder="0" id="bbox">
<tr><td> Your browser does not support inline frames! The Babble Box will not be available until you upgrade to
<iframe src="index.php?do=babblebox" name="sbox" width="100%" height="250" frameborder="0" id="bbox"> a newer <a href="http://www.mozilla.org" target="_new">browser</a>.
Your browser does not support inline frames! The Babble Box will not be available until you upgrade to a newer <a href="http://www.mozilla.org" target="_new">browser</a>. </iframe>
</iframe>
</td></tr>
</table>
HTML; HTML;
} }
@ -148,7 +177,7 @@ function doexplore()
{ {
return <<<HTML return <<<HTML
<table width="100%"> <table width="100%">
<tr><td class="title"><img src="images/title_exploring.gif" alt="Exploring" /></td></tr> <tr><td class="title"><img src="/img/title_exploring.gif" alt="Exploring" /></td></tr>
<tr><td> <tr><td>
You are exploring the map, and nothing has happened. Continue exploring using the direction buttons or the Travel To menus. You are exploring the map, and nothing has happened. Continue exploring using the direction buttons or the Travel To menus.
</td></tr> </td></tr>
@ -227,7 +256,7 @@ function onlinechar($id)
function showmap() function showmap()
{ {
$array = ["content" => "<center><img src=\"images/map.gif\" alt=\"Map\" /></center>", "title" => "Map"]; $array = ["content" => "<center><img src=\"/img/map.gif\" alt=\"Map\" /></center>", "title" => "Map"];
echo parsetemplate("<html>\n" . gettemplate("minimal"), $array); echo parsetemplate("<html>\n" . gettemplate("minimal"), $array);
} }
@ -240,18 +269,16 @@ function babblebox()
if (!empty($safecontent)) { if (!empty($safecontent)) {
db()->query('INSERT INTO babble (posttime, author, babble) VALUES (CURRENT_TIMESTAMP, ?, ?);', [$userrow['username'], $safecontent]); db()->query('INSERT INTO babble (posttime, author, babble) VALUES (CURRENT_TIMESTAMP, ?, ?);', [$userrow['username'], $safecontent]);
} }
redirect('index.php?do=babblebox'); redirect('/babblebox');
} }
$babblebox = ["content" => ""]; $babblebox['content'] = '';
$bg = 1; $query = db()->query('SELECT * FROM babble ORDER BY id DESC LIMIT 40;');
$query = db()->query('SELECT * FROM babble ORDER BY id DESC LIMIT 20;');
while ($babblerow = $query->fetchArray(SQLITE3_ASSOC)) { while ($babblerow = $query->fetchArray(SQLITE3_ASSOC)) {
if ($bg == 1) { $new = "<div style=\"width:98%; background-color:#eeeeee;\">[<b>".$babblerow["author"]."</b>] ".$babblerow["babble"]."</div>\n"; $bg = 2; } $new = "<div class=\"message\">[<b>{$babblerow["author"]}</b>] {$babblerow["babble"]}</div>\n";
else { $new = "<div style=\"width:98%; background-color:#ffffff;\">[<b>".$babblerow["author"]."</b>] ".stripslashes($babblerow["babble"])."</div>\n"; $bg = 1; }
$babblebox["content"] = $new . $babblebox["content"]; $babblebox["content"] = $new . $babblebox["content"];
} }
$babblebox["content"] .= "<center><form action=\"index.php?do=babblebox\" method=\"post\"><input type=\"text\" name=\"babble\" size=\"15\" maxlength=\"120\" /><br><input type=\"submit\" name=\"submit\" value=\"Babble\" /> <input type=\"reset\" name=\"reset\" value=\"Clear\" /></form></center>"; $babblebox["content"] .= '<form action="/babblebox" method="post" style="margin-top: 1rem;"><input type="text" name="babble" maxlength="255" style="width: 100%;"><br><input type="submit" name="submit" value="Babble"><input type="reset" name="reset" value="Clear"></form>';
echo parsetemplate("<html>\n" . gettemplate("babblebox"), $babblebox); echo parsetemplate("<html>\n" . gettemplate("babblebox"), $babblebox);
} }

View File

@ -2,7 +2,7 @@
require_once '../src/lib.php'; require_once '../src/lib.php';
if (file_exists('../.installed')) redirect('index.php'); if (file_exists('../.installed')) redirect('/');
$page = $_GET['page'] ?? 1; $page = $_GET['page'] ?? 1;
match ((int) $page) { match ((int) $page) {
@ -657,11 +657,11 @@ function third()
Now you must create an administrator account so you can use the control panel. Fill out the form below to create your account. You will be able to customize the class names through the control panel once your admin account is created.<br><br> Now you must create an administrator account so you can use the control panel. Fill out the form below to create your account. You will be able to customize the class names through the control panel once your admin account is created.<br><br>
<form action="install.php?page=4" method="post"> <form action="install.php?page=4" method="post">
<table width="50%"> <table width="50%">
<tr><td width="20%" style="vertical-align:top;">Username:</td><td><input type="text" name="username" size="30" maxlength="30" /><br><br><br></td></tr> <tr><td width="20%" style="vertical-align:top;">Username:</td><td><input type="text" name="username" /><br><br><br></td></tr>
<tr><td style="vertical-align:top;">Password:</td><td><input type="password" name="password1" size="30" maxlength="30" /></td></tr> <tr><td style="vertical-align:top;">Password:</td><td><input type="password" name="password" /></td></tr>
<tr><td style="vertical-align:top;">Verify Password:</td><td><input type="password" name="password2" size="30" maxlength="30" /><br><br><br></td></tr> <tr><td style="vertical-align:top;">Verify Password:</td><td><input type="password" name="confirm_password" /><br><br><br></td></tr>
<tr><td style="vertical-align:top;">Email Address:</td><td><input type="text" name="email1" size="30" maxlength="100" /></td></tr> <tr><td style="vertical-align:top;">Email Address:</td><td><input type="text" name="email" /></td></tr>
<tr><td style="vertical-align:top;">Verify Email:</td><td><input type="text" name="email2" size="30" maxlength="100" /><br><br><br></td></tr> <tr><td style="vertical-align:top;">Verify Email:</td><td><input type="text" name="confirm_email" /><br><br><br></td></tr>
<tr><td style="vertical-align:top;">Character Class:</td><td><select name="charclass"><option value="1">Mage</option><option value="2">Warrior</option><option value="3">Paladin</option></select></td></tr> <tr><td style="vertical-align:top;">Character Class:</td><td><select name="charclass"><option value="1">Mage</option><option value="2">Warrior</option><option value="3">Paladin</option></select></td></tr>
<tr><td colspan="2"><input type="submit" name="submit" value="Submit" /> <input type="reset" name="reset" value="Reset" /></td></tr> <tr><td colspan="2"><input type="submit" name="submit" value="Submit" /> <input type="reset" name="reset" value="Reset" /></td></tr>
</table> </table>
@ -676,48 +676,22 @@ function third()
*/ */
function fourth() function fourth()
{ {
$u = trim($_POST['username'] ??= ''); $form = validate($_POST, [
$e = trim($_POST['email1'] ??= ''); 'username' => ['length:3-18', 'alpha-spaces'],
$ec = trim($_POST['email2'] ??= ''); 'email' => ['email'],
$p = $_POST['password1'] ??= ''; 'confirm_email' => ['confirm'],
$pc = $_POST['password2'] ??= ''; 'password' => ['length:6-255'],
'confirm_password' => ['confirm']
]);
$errors = []; if (!$form['valid']) exit(ul_from_validate_errors($form['errors']));
if (empty($u) || strlen($u) < 3 || strlen($u) > 18 || !ctype_alnum(str_replace(' ', '', $u))) {
$errors[] = 'Username is required and must be between 3 and 18 characters long and contain only
alphanumeric characters and spaces.';
}
if (empty($e) || strlen($e) > 255 || !filter_var($e, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Email is required must be a valid email address.';
}
if ($e !== $ec) {
$errors[] = 'Verify Email must match.';
}
if (empty($p) || strlen($p) < 6) {
$errors[] = 'Password is required and must be at least 6 characters long.';
}
if ($pc !== $p) {
$errors[] = 'Verify Password must match.';
}
if (!empty($errors)) {
echo "<ul>";
foreach ($errors as $error) echo "<li>$error</li>";
echo "</ul>";
exit;
}
$form = $form['data'];
if (db()->query( if (db()->query(
"INSERT INTO users (username, password, email, verify, charclass, authlevel) VALUES (?, ?, ?, 1, ?, 1)", "INSERT INTO users (username, password, email, verify, charclass, authlevel) VALUES (?, ?, ?, 1, ?, 1)",
[$u, password_hash($p, PASSWORD_ARGON2ID), $e, $_POST['charclass']] [$form['username'], password_hash($form['password'], PASSWORD_ARGON2ID), $form['email'], $form['charclass']]
) === false) { ) === false) {
echo "Failed to create user."; exit("Failed to create user.");
exit;
} }
file_put_contents('../.installed', date('Y-m-d H:i:s')); file_put_contents('../.installed', date('Y-m-d H:i:s'));
@ -731,7 +705,7 @@ function fourth()
<b>Dragon Knight Installation: Page Four</b><br><br> <b>Dragon Knight Installation: Page Four</b><br><br>
Your admin account was created successfully. Installation is complete.<br><br> Your admin account was created successfully. Installation is complete.<br><br>
Be sure to delete install.php from your Dragon Knight directory for security purposes.<br><br> Be sure to delete install.php from your Dragon Knight directory for security purposes.<br><br>
You are now ready to <a href="index.php">play the game</a>. Note that you must log in through the public section before being allowed into the control panel. Once logged in, an "Admin" link will appear in the Functions box of the left sidebar panel.<br><br/> You are now ready to <a href="/">play the game</a>. Note that you must log in through the public section before being allowed into the control panel. Once logged in, an "Admin" link will appear in the Functions box of the left sidebar panel.<br><br/>
Thank you for using Dragon Knight!<br><br>-----<br><br> Thank you for using Dragon Knight!<br><br>-----<br><br>
<b>Optional:</b> Dragon Knight is a free product, and does not require registration of any sort. However, there is an <b>Optional:</b> Dragon Knight is a free product, and does not require registration of any sort. However, there is an
optional "call home" function in the installer, which notifies the author of your game installation. The ONLY information optional "call home" function in the installer, which notifies the author of your game installation. The ONLY information
@ -749,7 +723,7 @@ function fourth()
function fifth() function fifth()
{ {
if (mail("sky@sharkk.net", "Dragon Knight Call Home", $_SERVER["SERVER_NAME"].$_SERVER["PHP_SELF"]) !== true) { if (mail("sky@sharkk.net", "Dragon Knight Call Home", $_SERVER["SERVER_NAME"].$_SERVER["PHP_SELF"]) !== true) {
exit('Dragon Knight was unable to send your URL. Please go back and try again, or just continue on to <a href=\"index.php\">the game</a>.'); exit('Dragon Knight was unable to send your URL. Please go back and try again, or just continue on to <a href=\"/\">the game</a>.');
} }
echo <<<HTML echo <<<HTML
@ -760,7 +734,7 @@ function fifth()
<body> <body>
<b>Dragon Knight Installation: Page Five</b><br><br> <b>Dragon Knight Installation: Page Five</b><br><br>
Thank you for submitting your URL!<br><br> Thank you for submitting your URL!<br><br>
You are now ready to <a href="index.php">play the game</a>. Note that you must log in through the public section before being allowed into the control panel. Once logged in, an "Admin" link will appear in the Functions box of the left sidebar panel. You are now ready to <a href="/">play the game</a>. Note that you must log in through the public section before being allowed into the control panel. Once logged in, an "Admin" link will appear in the Functions box of the left sidebar panel.
</body> </body>
</html> </html>
HTML; HTML;

View File

@ -13,23 +13,33 @@ match ($_GET['do'] ?? 'login') {
function login() function login()
{ {
if (checkcookies() !== false) redirect('index.php'); if (checkcookies() !== false) redirect('/');
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$u = trim($_POST['username'] ?? ''); $form = validate($_POST, [
'username' => ['length:3-18', 'alpha-spaces'],
'password' => ['length:6-255'],
'remember' => ['bool']
]);
$query = db()->query('SELECT id, username, password FROM users WHERE username = ? LIMIT 1;', [$u]); if (!$form['valid']) {
if ($query === false) die("Invalid username or password. Please go back and try again."); exit(ul_from_validate_errors($form['errors']));
$row = $query->fetchArray(SQLITE3_ASSOC); }
if (!password_verify($_POST['password'] ?? '', $row['password'])) die("Invalid username or password. Please go back and try again.");
$expiretime = isset($_POST["rememberme"]) ? time() + 31536000 : 0; $form = $form['data'];
$rememberme = isset($_POST["rememberme"]) ? 1 : 0;
$query = db()->query('SELECT id, username, password FROM users WHERE username = ? COLLATE NOCASE LIMIT 1;', [$form['username']]);
$row = $query ? $query->fetchArray(SQLITE3_ASSOC) : false;
if ($row === false || !password_verify($_POST['password'] ?? '', $row['password']))
die("Invalid username or password. Please go back and try again.");
$expiretime = $form['remember'] ? time() + 31536000 : 0;
$rememberme = $form['remember'] ? 1 : 0;
$cookie = implode(' ', [$row['id'], $row['username'], $row['password'], $rememberme]); $cookie = implode(' ', [$row['id'], $row['username'], $row['password'], $rememberme]);
set_cookie("dkgame", $cookie, $expiretime); set_cookie("dkgame", $cookie, $expiretime);
header("Location: index.php"); redirect('/');
exit;
} }
$page = gettemplate("login"); $page = gettemplate("login");
@ -41,6 +51,5 @@ function login()
function logout() function logout()
{ {
set_cookie("dkgame", "", -3600); set_cookie("dkgame", "", -3600);
header("Location: login.php?do=login"); redirect('login.php?do=login');
die();
} }

View File

@ -24,61 +24,28 @@ function register()
global $controlrow; global $controlrow;
if (isset($_POST["submit"])) { if (isset($_POST["submit"])) {
$u = trim($_POST['username'] ?? ''); $form = validate($_POST, [
$e = trim($_POST['email1'] ?? ''); 'username' => ['length:3-18', 'alpha-spaces', 'unique:users,username'],
$e2 = trim($_POST['email2'] ?? ''); 'email' => ['email', 'unique:users,email'],
$p = $_POST['password1'] ?? ''; 'confirm_email' => ['confirm'],
$p2 = $_POST['password2'] ?? ''; 'password' => ['length:6-255'],
'confirm_password' => ['confirm'],
'charclass' => ['in:1,2,3']
]);
$errors = []; if (!$form['valid']) {
$err = ul_from_validate_errors($form['errors']);
// Process username.
if (empty($u) || strlen($u) < 3 || strlen($u) > 18 || !ctype_alnum(str_replace(' ', '', $u))) {
$errors[] = 'Username is required and must be between 3 and 18 characters long and contain only
alphanumeric characters and spaces.';
}
if (db()->exists('users', 'username', $u)) {
$errors[] = 'Username already taken. Try another.';
}
// Process email address.
if (empty($e) || strlen($e) > 255 || !filter_var($e, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Email is required must be a valid email address.';
}
if ($e !== $e2) {
$errors[] = 'Verify Email must match.';
}
if (db()->exists('users', 'email', $e)) {
$errors[] = 'Email already taken. Forgot your password?';
}
// Process password.
if (empty($p) || strlen($p) < 6) {
$errors[] = 'Password is required and must be at least 6 characters long.';
}
if ($p2 !== $p) {
$errors[] = 'Verify Password must match.';
}
$password = password_hash($p, PASSWORD_ARGON2ID);
if (count($errors) !== 0) {
$err = "<ul>";
foreach ($errors as $error) $err .= "<li>$error</li>";
$err .= "</ul>";
$page = "The following error(s) occurred when your account was being made:<br><span style=\"color:red;\">$err</span><br>Please go back and try again."; $page = "The following error(s) occurred when your account was being made:<br><span style=\"color:red;\">$err</span><br>Please go back and try again.";
} else { } else {
$form = $form['data'];
$password = password_hash($form['password'], PASSWORD_ARGON2ID);
$token = ($controlrow['verifyemail'] == true) ? token(8) : 'g2g'; $token = ($controlrow['verifyemail'] == true) ? token(8) : 'g2g';
db()->query('INSERT INTO users (verify, username, password, email, charclass) VALUES (?, ?, ?, ?, ?)', [ db()->query('INSERT INTO users (verify, username, password, email, charclass) VALUES (?, ?, ?, ?, ?)', [
$token, $u, $password, $e, $_POST['charclass'] ?? 1 $token, $form['username'], $password, $form['email'], $form['charclass']
]); ]);
if ($controlrow['verifyemail'] == true) { if ($controlrow['verifyemail'] == true) {
if (sendregmail($e, $token)) { if (sendregmail($form['email'], $token)) {
$page = "Your account was created successfully.<br><br>You should receive an Account Verification email shortly. You will need the verification code contained in that email before you are allowed to log in. Once you have received the email, please visit the <a href=\"users.php?do=verify\">Verification Page</a> to enter your code and start playing."; $page = "Your account was created successfully.<br><br>You should receive an Account Verification email shortly. You will need the verification code contained in that email before you are allowed to log in. Once you have received the email, please visit the <a href=\"users.php?do=verify\">Verification Page</a> to enter your code and start playing.";
} else { } else {
$page = "Your account was created successfully.<br><br>However, there was a problem sending your verification email. Please check with the game administrator to help resolve this problem."; $page = "Your account was created successfully.<br><br>However, there was a problem sending your verification email. Please check with the game administrator to help resolve this problem.";
@ -97,7 +64,6 @@ function register()
$page = parsetemplate(gettemplate("register"), $controlrow); $page = parsetemplate(gettemplate("register"), $controlrow);
} }
$topnav = "<a href=\"login.php?do=login\"><img src=\"images/button_login.gif\" alt=\"Log In\" border=\"0\" /></a><a href=\"users.php?do=register\"><img src=\"images/button_register.gif\" alt=\"Register\" border=\"0\" /></a><a href=\"help.php\"><img src=\"images/button_help.gif\" alt=\"Help\" border=\"0\" /></a>";
display($page, "Register", false, false, false); display($page, "Register", false, false, false);
} }
@ -116,7 +82,7 @@ function verify()
display("Your account was verified successfully.<br><br>You may now continue to the <a href=\"login.php?do=login\">Login Page</a> and start playing the game.<br><br>Thanks for playing!","Verify Email",false,false,false); display("Your account was verified successfully.<br><br>You may now continue to the <a href=\"login.php?do=login\">Login Page</a> and start playing the game.<br><br>Thanks for playing!","Verify Email",false,false,false);
} }
$topnav = "<a href=\"login.php?do=login\"><img src=\"images/button_login.gif\" alt=\"Log In\" border=\"0\" /></a><a href=\"users.php?do=register\"><img src=\"images/button_register.gif\" alt=\"Register\" border=\"0\" /></a><a href=\"help.php\"><img src=\"images/button_help.gif\" alt=\"Help\" border=\"0\" /></a>"; $topnav = "<a href=\"login.php?do=login\"><img src=\"/img/button_login.gif\" alt=\"Log In\" border=\"0\" /></a><a href=\"users.php?do=register\"><img src=\"/img/button_register.gif\" alt=\"Register\" border=\"0\" /></a><a href=\"help.php\"><img src=\"/img/button_help.gif\" alt=\"Help\" border=\"0\" /></a>";
display(gettemplate("verify"), "Verify Email", false, false, false); display(gettemplate("verify"), "Verify Email", false, false, false);
} }
@ -139,7 +105,7 @@ function lostpassword()
} }
} }
$topnav = "<a href=\"login.php?do=login\"><img src=\"images/button_login.gif\" alt=\"Log In\" border=\"0\" /></a><a href=\"users.php?do=register\"><img src=\"images/button_register.gif\" alt=\"Register\" border=\"0\" /></a><a href=\"help.php\"><img src=\"images/button_help.gif\" alt=\"Help\" border=\"0\" /></a>"; $topnav = "<a href=\"login.php?do=login\"><img src=\"/img/button_login.gif\" alt=\"Log In\" border=\"0\" /></a><a href=\"users.php?do=register\"><img src=\"/img/button_register.gif\" alt=\"Register\" border=\"0\" /></a><a href=\"help.php\"><img src=\"/img/button_help.gif\" alt=\"Help\" border=\"0\" /></a>";
display(gettemplate("lostpassword"), "Lost Password", false, false, false); display(gettemplate("lostpassword"), "Lost Password", false, false, false);
} }
@ -174,7 +140,7 @@ function changepassword()
display("Your password was changed successfully.<br><br>You have been logged out of the game to avoid errors.<br><br>Please <a href=\"login.php?do=login\">log back in</a> to continue playing.","Change Password",false,false,false); display("Your password was changed successfully.<br><br>You have been logged out of the game to avoid errors.<br><br>Please <a href=\"login.php?do=login\">log back in</a> to continue playing.","Change Password",false,false,false);
} }
$topnav = "<a href=\"login.php?do=login\"><img src=\"images/button_login.gif\" alt=\"Log In\" border=\"0\" /></a><a href=\"users.php?do=register\"><img src=\"images/button_register.gif\" alt=\"Register\" border=\"0\" /></a><a href=\"help.php\"><img src=\"images/button_help.gif\" alt=\"Help\" border=\"0\" /></a>"; $topnav = "<a href=\"login.php?do=login\"><img src=\"/img/button_login.gif\" alt=\"Log In\" border=\"0\" /></a><a href=\"users.php?do=register\"><img src=\"/img/button_register.gif\" alt=\"Register\" border=\"0\" /></a><a href=\"help.php\"><img src=\"/img/button_help.gif\" alt=\"Help\" border=\"0\" /></a>";
display(gettemplate("changepassword"), "Change Password", false, false, false); display(gettemplate("changepassword"), "Change Password", false, false, false);
} }

View File

@ -6,14 +6,21 @@ function move()
{ {
global $userrow, $controlrow; global $userrow, $controlrow;
if ($userrow["currentaction"] == "Fighting") { header("Location: index.php?do=fight"); die(); } if ($userrow["currentaction"] == "Fighting") { redirect('/fight'); }
$latitude = $userrow["latitude"]; $latitude = $userrow["latitude"];
$longitude = $userrow["longitude"]; $longitude = $userrow["longitude"];
if (isset($_POST["north"])) { $latitude++; if ($latitude > $controlrow["gamesize"]) { $latitude = $controlrow["gamesize"]; } }
if (isset($_POST["south"])) { $latitude--; if ($latitude < ($controlrow["gamesize"]*-1)) { $latitude = ($controlrow["gamesize"]*-1); } } $form = validate($_POST, [
if (isset($_POST["east"])) { $longitude++; if ($longitude > $controlrow["gamesize"]) { $longitude = $controlrow["gamesize"]; } } 'direction' => ['in:north,west,east,south']
if (isset($_POST["west"])) { $longitude--; if ($longitude < ($controlrow["gamesize"]*-1)) { $longitude = ($controlrow["gamesize"]*-1); } } ]);
if (!$form['valid']) display(ul_from_validate_errors($form['errors']), 'Move Error');
$d = $form['data']['direction'];
if ($d === 'north') { $latitude++; if ($latitude > $controlrow["gamesize"]) { $latitude = $controlrow["gamesize"]; } }
if ($d === 'south') { $latitude--; if ($latitude < ($controlrow["gamesize"]*-1)) { $latitude = ($controlrow["gamesize"]*-1); } }
if ($d === 'east') { $longitude++; if ($longitude > $controlrow["gamesize"]) { $longitude = $controlrow["gamesize"]; } }
if ($d === 'west') { $longitude--; if ($longitude < ($controlrow["gamesize"]*-1)) { $longitude = ($controlrow["gamesize"]*-1); } }
$town = get_town_by_xy($longitude, $latitude); $town = get_town_by_xy($longitude, $latitude);
if ($town !== false) { if ($town !== false) {
@ -26,5 +33,5 @@ function move()
$action = $chancetofight === 1 ? "currentaction='Fighting', currentfight='1'," : "currentaction='Exploring',"; $action = $chancetofight === 1 ? "currentaction='Fighting', currentfight='1'," : "currentaction='Exploring',";
db()->query("UPDATE users SET $action latitude = ?, longitude = ?, dropcode = 0 WHERE id = ?;", [$latitude, $longitude, $userrow['id']]); db()->query("UPDATE users SET $action latitude = ?, longitude = ?, dropcode = 0 WHERE id = ?;", [$latitude, $longitude, $userrow['id']]);
header("Location: index.php"); redirect('/');
} }

View File

@ -57,7 +57,7 @@ function fight()
$pagearray["monsterturn"] = handleMonsterTurn($userrow, $monsterrow); $pagearray["monsterturn"] = handleMonsterTurn($userrow, $monsterrow);
db()->query("UPDATE users SET currentaction='Exploring' WHERE id=?;", [$userrow['id']]); db()->query("UPDATE users SET currentaction='Exploring' WHERE id=?;", [$userrow['id']]);
redirect('index.php'); redirect('/');
} }
} }
@ -97,7 +97,7 @@ function fight()
// Check for monster defeat // Check for monster defeat
if ($userrow["currentmonsterhp"] <= 0) { if ($userrow["currentmonsterhp"] <= 0) {
db()->query('UPDATE users SET currentmonsterhp=0 WHERE id=?;', [$userrow['id']]); db()->query('UPDATE users SET currentmonsterhp=0 WHERE id=?;', [$userrow['id']]);
redirect('index.php?do=victory'); redirect('/victory');
} }
// Monster's turn // Monster's turn
@ -134,7 +134,7 @@ function fight()
db()->query('UPDATE users SET currentmonsterhp=0, currenthp=?, currentmp=? WHERE id=?;', [ db()->query('UPDATE users SET currentmonsterhp=0, currenthp=?, currentmp=? WHERE id=?;', [
$userrow['currenthp'], $userrow['currentmp'], $userrow['id'] $userrow['currenthp'], $userrow['currentmp'], $userrow['id']
]); ]);
redirect('index.php?do=victory'); redirect('/victory');
} }
// Monster's turn // Monster's turn
@ -152,7 +152,7 @@ function fight()
if ($playerisdead != 1) { if ($playerisdead != 1) {
$pagearray["command"] = <<<HTML $pagearray["command"] = <<<HTML
Command?<br><br> Command?<br><br>
<form action="index.php?do=fight" method="post"> <form action="/fight" method="post">
<input type="submit" name="fight" value="Fight" /><br><br> <input type="submit" name="fight" value="Fight" /><br><br>
<select name="userspell"><option value="0">Choose One</option>$magiclist</select> <input type="submit" name="spell" value="Spell" /><br><br> <select name="userspell"><option value="0">Choose One</option>$magiclist</select> <input type="submit" name="spell" value="Spell" /><br><br>
<input type="submit" name="run" value="Run" /><br><br> <input type="submit" name="run" value="Run" /><br><br>
@ -183,7 +183,7 @@ function fight()
$userrow['id'] $userrow['id']
]); ]);
} else { } else {
$pagearray["command"] = "<b>You have died.</b><br><br>As a consequence, you've lost half of your gold. However, you have been given back a portion of your hit points to continue your journey.<br><br>You may now continue back to <a href=\"index.php\">town</a>, and we hope you fair better next time."; $pagearray["command"] = "<b>You have died.</b><br><br>As a consequence, you've lost half of your gold. However, you have been given back a portion of your hit points to continue your journey.<br><br>You may now continue back to <a href=\"/\">town</a>, and we hope you fair better next time.";
} }
// Finalize page and display it // Finalize page and display it
@ -194,8 +194,8 @@ function victory()
{ {
global $userrow; global $userrow;
if ($userrow["currentmonsterhp"] != 0) { header("Location: index.php?do=fight"); die(); } if ($userrow["currentmonsterhp"] != 0) redirect('/fight');
if ($userrow["currentfight"] == 0) { header("Location: index.php"); die(); } if ($userrow["currentfight"] == 0) redirect('/');
$monsterrow = get_monster($userrow['currentmonster']); $monsterrow = get_monster($userrow['currentmonster']);
@ -235,7 +235,7 @@ function victory()
$spelltext = "You have learned a new spell.<br>"; $spelltext = "You have learned a new spell.<br>";
} else { $spelltext = ""; $newspell=""; } } else { $spelltext = ""; $newspell=""; }
$page = "Congratulations. You have defeated the ".$monsterrow["name"].".<br>You gain $exp experience. $warnexp <br>You gain $gold gold. $warngold <br><br><b>You have gained a level!</b><br><br>You gain ".$levelrow[$userrow["charclass"]."_hp"]." hit points.<br>You gain ".$levelrow[$userrow["charclass"]."_mp"]." magic points.<br>You gain ".$levelrow[$userrow["charclass"]."_tp"]." travel points.<br>You gain ".$levelrow[$userrow["charclass"]."_strength"]." strength.<br>You gain ".$levelrow[$userrow["charclass"]."_dexterity"]." dexterity.<br>$spelltext<br>You can now continue <a href=\"index.php\">exploring</a>."; $page = "Congratulations. You have defeated the ".$monsterrow["name"].".<br>You gain $exp experience. $warnexp <br>You gain $gold gold. $warngold <br><br><b>You have gained a level!</b><br><br>You gain ".$levelrow[$userrow["charclass"]."_hp"]." hit points.<br>You gain ".$levelrow[$userrow["charclass"]."_mp"]." magic points.<br>You gain ".$levelrow[$userrow["charclass"]."_tp"]." travel points.<br>You gain ".$levelrow[$userrow["charclass"]."_strength"]." strength.<br>You gain ".$levelrow[$userrow["charclass"]."_dexterity"]." dexterity.<br>$spelltext<br>You can now continue <a href=\"/\">exploring</a>.";
$title = "Courage and Wit have served thee well!"; $title = "Courage and Wit have served thee well!";
$dropcode = ""; $dropcode = "";
} else { } else {
@ -253,10 +253,10 @@ function victory()
if (rand(1, 30) === 1) { if (rand(1, 30) === 1) {
$droprow = db()->query('SELECT * FROM drops WHERE mlevel <= ? ORDER BY RANDOM() LIMIT 1;', [$monsterrow['level']])->fetchArray(SQLITE3_ASSOC); $droprow = db()->query('SELECT * FROM drops WHERE mlevel <= ? ORDER BY RANDOM() LIMIT 1;', [$monsterrow['level']])->fetchArray(SQLITE3_ASSOC);
$dropcode = "dropcode='".$droprow["id"]."',"; $dropcode = "dropcode='".$droprow["id"]."',";
$page .= "This monster has dropped an item. <a href=\"index.php?do=drop\">Click here</a> to reveal and equip the item, or you may also move on and continue <a href=\"index.php\">exploring</a>."; $page .= "This monster has dropped an item. <a href=\"/drop\">Click here</a> to reveal and equip the item, or you may also move on and continue <a href=\"/\">exploring</a>.";
} else { } else {
$dropcode = ""; $dropcode = "";
$page .= "You can now continue <a href=\"index.php\">exploring</a>."; $page .= "You can now continue <a href=\"/\">exploring</a>.";
} }
$title = "Victory!"; $title = "Victory!";
@ -274,7 +274,7 @@ function drop()
{ {
global $userrow; global $userrow;
if ($userrow["dropcode"] == 0) redirect('index.php'); if ($userrow["dropcode"] == 0) redirect('/');
$droprow = get_drop($userrow['dropcode']); $droprow = get_drop($userrow['dropcode']);
@ -330,7 +330,7 @@ function drop()
]); ]);
} }
display("The item has been equipped. You can now continue <a href=\"index.php\">exploring</a>.", "Item Drop"); display("The item has been equipped. You can now continue <a href=\"/\">exploring</a>.", "Item Drop");
} }
$attributearray = array("maxhp"=>"Max HP", $attributearray = array("maxhp"=>"Max HP",
@ -357,8 +357,8 @@ function drop()
} }
$page .= "<br>Select an inventory slot from the list below to equip this item. If the inventory slot is already full, the old item will be discarded."; $page .= "<br>Select an inventory slot from the list below to equip this item. If the inventory slot is already full, the old item will be discarded.";
$page .= "<form action=\"index.php?do=drop\" method=\"post\"><select name=\"slot\"><option value=\"0\">Choose One</option><option value=\"1\">Slot 1: ".$userrow["slot1name"]."</option><option value=\"2\">Slot 2: ".$userrow["slot2name"]."</option><option value=\"3\">Slot 3: ".$userrow["slot3name"]."</option></select> <input type=\"submit\" name=\"submit\" value=\"Submit\" /></form>"; $page .= "<form action=\"/drop\" method=\"post\"><select name=\"slot\"><option value=\"0\">Choose One</option><option value=\"1\">Slot 1: ".$userrow["slot1name"]."</option><option value=\"2\">Slot 2: ".$userrow["slot2name"]."</option><option value=\"3\">Slot 3: ".$userrow["slot3name"]."</option></select> <input type=\"submit\" name=\"submit\" value=\"Submit\" /></form>";
$page .= "You may also choose to just continue <a href=\"index.php\">exploring</a> and give up this item."; $page .= "You may also choose to just continue <a href=\"/\">exploring</a> and give up this item.";
display($page, "Item Drop"); display($page, "Item Drop");
} }
@ -370,7 +370,7 @@ function dead()
<b>You have died.</b><br><br> <b>You have died.</b><br><br>
As a consequence, you've lost half of your gold. However, you have been given back a portion of your hit points As a consequence, you've lost half of your gold. However, you have been given back a portion of your hit points
to continue your journey.<br><br> to continue your journey.<br><br>
You may now continue back to <a href="index.php">town</a>, and we hope you fair better next time. You may now continue back to <a href="/">town</a>, and we hope you fair better next time.
HTML; HTML;
display($page, 'You Died'); display($page, 'You Died');
} }

View File

@ -24,5 +24,5 @@ function healspells($id)
db()->query('UPDATE users SET currenthp=?, currentmp=? WHERE id=?;', [$newhp, $newmp, $userrow['id']]); db()->query('UPDATE users SET currenthp=?, currentmp=? WHERE id=?;', [$newhp, $newmp, $userrow['id']]);
display("You have cast the ".$spellrow["name"]." spell, and gained ".$spellrow["attribute"]." Hit Points. You can now continue <a href=\"index.php\">exploring</a>.", "Healing Spell"); display("You have cast the ".$spellrow["name"]." spell, and gained ".$spellrow["attribute"]." Hit Points. You can now continue <a href=\"/\">exploring</a>.", "Healing Spell");
} }

View File

@ -2,8 +2,8 @@
require_once __DIR__ . '/database.php'; require_once __DIR__ . '/database.php';
define('VERSION', '1.1.11'); define('VERSION', '1.2.3');
define('BUILD', ''); define('BUILD', 'Reawaken');
define('START', microtime(true)); define('START', microtime(true));
/** /**
@ -106,9 +106,9 @@ function display($content, $title, $topnav=true, $leftnav=true, $rightnav=true,
if ($rightnav == true) { $rightnav = gettemplate("rightnav"); } else { $rightnav = ""; } if ($rightnav == true) { $rightnav = gettemplate("rightnav"); } else { $rightnav = ""; }
if ($leftnav == true) { $leftnav = gettemplate("leftnav"); } else { $leftnav = ""; } if ($leftnav == true) { $leftnav = gettemplate("leftnav"); } else { $leftnav = ""; }
if ($topnav == true) { if ($topnav == true) {
$topnav = "<a href=\"login.php?do=logout\"><img src=\"images/button_logout.gif\" alt=\"Log Out\" title=\"Log Out\" border=\"0\" /></a> <a href=\"help.php\"><img src=\"images/button_help.gif\" alt=\"Help\" title=\"Help\" border=\"0\" /></a>"; $topnav = "<a href=\"login.php?do=logout\"><img src=\"/img/button_logout.gif\" alt=\"Log Out\" title=\"Log Out\" border=\"0\" /></a> <a href=\"help.php\"><img src=\"/img/button_help.gif\" alt=\"Help\" title=\"Help\" border=\"0\" /></a>";
} else { } else {
$topnav = "<a href=\"login.php?do=login\"><img src=\"images/button_login.gif\" alt=\"Log In\" title=\"Log In\" border=\"0\" /></a> <a href=\"users.php?do=register\"><img src=\"images/button_register.gif\" alt=\"Register\" title=\"Register\" border=\"0\" /></a> <a href=\"help.php\"><img src=\"images/button_help.gif\" alt=\"Help\" title=\"Help\" border=\"0\" /></a>"; $topnav = "<a href=\"login.php?do=login\"><img src=\"/img/button_login.gif\" alt=\"Log In\" title=\"Log In\" border=\"0\" /></a> <a href=\"users.php?do=register\"><img src=\"/img/button_register.gif\" alt=\"Register\" title=\"Register\" border=\"0\" /></a> <a href=\"help.php\"><img src=\"/img/button_help.gif\" alt=\"Help\" title=\"Help\" border=\"0\" /></a>";
} }
if (isset($userrow)) { if (isset($userrow)) {
@ -142,19 +142,19 @@ function display($content, $title, $topnav=true, $leftnav=true, $rightnav=true,
$stattp = ceil($userrow["currenttp"] / $userrow["maxtp"] * 100); $stattp = ceil($userrow["currenttp"] / $userrow["maxtp"] * 100);
$stattable = "<table width=\"100\"><tr><td width=\"33%\">\n"; $stattable = "<table width=\"100\"><tr><td width=\"33%\">\n";
$stattable .= "<table cellspacing=\"0\" cellpadding=\"0\"><tr><td style=\"padding:0px; width:15px; height:100px; border:solid 1px black; vertical-align:bottom;\">\n"; $stattable .= "<table cellspacing=\"0\" cellpadding=\"0\"><tr><td style=\"padding:0px; width:15px; height:100px; border:solid 1px black; vertical-align:bottom;\">\n";
if ($stathp >= 66) { $stattable .= "<div style=\"padding:0px; height:".$stathp."px; border-top:solid 1px black; background-image:url(images/bars_green.gif);\"><img src=\"images/bars_green.gif\" alt=\"\" /></div>"; } if ($stathp >= 66) { $stattable .= "<div style=\"padding:0px; height:".$stathp."px; border-top:solid 1px black; background-image:url(/img/bars_green.gif);\"><img src=\"/img/bars_green.gif\" alt=\"\" /></div>"; }
if ($stathp < 66 && $stathp >= 33) { $stattable .= "<div style=\"padding:0px; height:".$stathp."px; border-top:solid 1px black; background-image:url(images/bars_yellow.gif);\"><img src=\"images/bars_yellow.gif\" alt=\"\" /></div>"; } if ($stathp < 66 && $stathp >= 33) { $stattable .= "<div style=\"padding:0px; height:".$stathp."px; border-top:solid 1px black; background-image:url(/img/bars_yellow.gif);\"><img src=\"/img/bars_yellow.gif\" alt=\"\" /></div>"; }
if ($stathp < 33) { $stattable .= "<div style=\"padding:0px; height:".$stathp."px; border-top:solid 1px black; background-image:url(images/bars_red.gif);\"><img src=\"images/bars_red.gif\" alt=\"\" /></div>"; } if ($stathp < 33) { $stattable .= "<div style=\"padding:0px; height:".$stathp."px; border-top:solid 1px black; background-image:url(/img/bars_red.gif);\"><img src=\"/img/bars_red.gif\" alt=\"\" /></div>"; }
$stattable .= "</td></tr></table></td><td width=\"33%\">\n"; $stattable .= "</td></tr></table></td><td width=\"33%\">\n";
$stattable .= "<table cellspacing=\"0\" cellpadding=\"0\"><tr><td style=\"padding:0px; width:15px; height:100px; border:solid 1px black; vertical-align:bottom;\">\n"; $stattable .= "<table cellspacing=\"0\" cellpadding=\"0\"><tr><td style=\"padding:0px; width:15px; height:100px; border:solid 1px black; vertical-align:bottom;\">\n";
if ($statmp >= 66) { $stattable .= "<div style=\"padding:0px; height:".$statmp."px; border-top:solid 1px black; background-image:url(images/bars_green.gif);\"><img src=\"images/bars_green.gif\" alt=\"\" /></div>"; } if ($statmp >= 66) { $stattable .= "<div style=\"padding:0px; height:".$statmp."px; border-top:solid 1px black; background-image:url(/img/bars_green.gif);\"><img src=\"/img/bars_green.gif\" alt=\"\" /></div>"; }
if ($statmp < 66 && $statmp >= 33) { $stattable .= "<div style=\"padding:0px; height:".$statmp."px; border-top:solid 1px black; background-image:url(images/bars_yellow.gif);\"><img src=\"images/bars_yellow.gif\" alt=\"\" /></div>"; } if ($statmp < 66 && $statmp >= 33) { $stattable .= "<div style=\"padding:0px; height:".$statmp."px; border-top:solid 1px black; background-image:url(/img/bars_yellow.gif);\"><img src=\"/img/bars_yellow.gif\" alt=\"\" /></div>"; }
if ($statmp < 33) { $stattable .= "<div style=\"padding:0px; height:".$statmp."px; border-top:solid 1px black; background-image:url(images/bars_red.gif);\"><img src=\"images/bars_red.gif\" alt=\"\" /></div>"; } if ($statmp < 33) { $stattable .= "<div style=\"padding:0px; height:".$statmp."px; border-top:solid 1px black; background-image:url(/img/bars_red.gif);\"><img src=\"/img/bars_red.gif\" alt=\"\" /></div>"; }
$stattable .= "</td></tr></table></td><td width=\"33%\">\n"; $stattable .= "</td></tr></table></td><td width=\"33%\">\n";
$stattable .= "<table cellspacing=\"0\" cellpadding=\"0\"><tr><td style=\"padding:0px; width:15px; height:100px; border:solid 1px black; vertical-align:bottom;\">\n"; $stattable .= "<table cellspacing=\"0\" cellpadding=\"0\"><tr><td style=\"padding:0px; width:15px; height:100px; border:solid 1px black; vertical-align:bottom;\">\n";
if ($stattp >= 66) { $stattable .= "<div style=\"padding:0px; height:".$stattp."px; border-top:solid 1px black; background-image:url(images/bars_green.gif);\"><img src=\"images/bars_green.gif\" alt=\"\" /></div>"; } if ($stattp >= 66) { $stattable .= "<div style=\"padding:0px; height:".$stattp."px; border-top:solid 1px black; background-image:url(/img/bars_green.gif);\"><img src=\"/img/bars_green.gif\" alt=\"\" /></div>"; }
if ($stattp < 66 && $stattp >= 33) { $stattable .= "<div style=\"padding:0px; height:".$stattp."px; border-top:solid 1px black; background-image:url(images/bars_yellow.gif);\"><img src=\"images/bars_yellow.gif\" alt=\"\" /></div>"; } if ($stattp < 66 && $stattp >= 33) { $stattable .= "<div style=\"padding:0px; height:".$stattp."px; border-top:solid 1px black; background-image:url(/img/bars_yellow.gif);\"><img src=\"/img/bars_yellow.gif\" alt=\"\" /></div>"; }
if ($stattp < 33) { $stattable .= "<div style=\"padding:0px; height:".$stattp."px; border-top:solid 1px black; background-image:url(images/bars_red.gif);\"><img src=\"images/bars_red.gif\" alt=\"\" /></div>"; } if ($stattp < 33) { $stattable .= "<div style=\"padding:0px; height:".$stattp."px; border-top:solid 1px black; background-image:url(/img/bars_red.gif);\"><img src=\"/img/bars_red.gif\" alt=\"\" /></div>"; }
$stattable .= "</td></tr></table></td>\n"; $stattable .= "</td></tr></table></td>\n";
$stattable .= "</tr><tr><td>HP</td><td>MP</td><td>TP</td></tr></table>\n"; $stattable .= "</tr><tr><td>HP</td><td>MP</td><td>TP</td></tr></table>\n";
$userrow["statbars"] = $stattable; $userrow["statbars"] = $stattable;
@ -172,7 +172,7 @@ function display($content, $title, $topnav=true, $leftnav=true, $rightnav=true,
if ($b == $spellrow["id"] && $spellrow["type"] == 1) { $spell = true; } if ($b == $spellrow["id"] && $spellrow["type"] == 1) { $spell = true; }
} }
if ($spell == true) { if ($spell == true) {
$userrow["magiclist"] .= "<a href=\"index.php?do=spell:".$spellrow["id"]."\">".$spellrow["name"]."</a><br>"; $userrow["magiclist"] .= "<a href=\"/spell/{$spellrow["id"]}\">".$spellrow["name"]."</a><br>";
} }
} }
if ($userrow["magiclist"] == "") { $userrow["magiclist"] = "None"; } if ($userrow["magiclist"] == "") { $userrow["magiclist"] = "None"; }
@ -187,7 +187,7 @@ function display($content, $title, $topnav=true, $leftnav=true, $rightnav=true,
if ($b == $townrow2["id"]) { $town = true; } if ($b == $townrow2["id"]) { $town = true; }
} }
if ($town == true) { if ($town == true) {
$userrow["townslist"] .= "<a href=\"index.php?do=gotown:".$townrow2["id"]."\">".$townrow2["name"]."</a><br>\n"; $userrow["townslist"] .= "<a href=\"/gotown/{$townrow2["id"]}\">".$townrow2["name"]."</a><br>\n";
} }
} }
} else { } else {
@ -343,3 +343,186 @@ function token($length = 32): string
{ {
return bin2hex(random_bytes($length)); return bin2hex(random_bytes($length));
} }
/**
* Validate any given array of data against rules. Returns [valid, data, error]. Data contains the trimmed
* values from the input array. Note: all fields with rules are assumed to be required, unless the optional
* rule is used.
*
* Example: ['required', 'no-trim', 'length:5-20', 'alphanum-spaces']
*/
function validate(array $input_data, array $rules): array
{
$data = [];
$errors = [];
foreach ($rules as $field => $field_rules) {
$value = $input_data[$field] ?? null;
$field_name = ucfirst(str_replace('_', ' ', $field));
$is_required = true;
$default_value = null;
if (in_array('optional', $field_rules)) {
$is_required = false;
}
foreach ($field_rules as $rule) {
if (strpos($rule, 'default:') === 0) {
$default_value = substr($rule, 8);
break;
}
}
if (($value === null || $value === '') && $default_value !== null) {
$value = $default_value;
}
if (($value === null || $value === '') && !$is_required) continue;
if ($is_required && ($value === null || $value === '')) {
$errors[$field][] = "{$field_name} is required.";
continue;
}
if (!in_array('no-trim', $field_rules)) {
$value = trim($value);
}
$data[$field] = $value;
foreach ($field_rules as $rule) {
// Parse rule and arguments
if (strpos($rule, ':') !== false) {
list($rule_name, $rule_args) = explode(':', $rule, 2);
} else {
$rule_name = $rule;
$rule_args = null;
}
if ($rule_name === 'optional') continue;
switch ($rule_name) {
case 'bool':
if (!isset($input_data[$field]) || empty($value)) {
$value = false;
} else {
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
if ($value === null) {
$errors[$field][] = "{$field_name} must be a valid boolean value.";
}
}
break;
case 'length':
list($min, $max) = explode('-', $rule_args);
$len = strlen((string)$value);
if ($len < $min || $len > $max) {
$errors[$field][] = "{$field_name} must be between {$min} and {$max} characters.";
}
break;
case 'alphanum':
if (!preg_match('/^[a-zA-Z0-9]+$/', $value)) {
$errors[$field][] = "{$field_name} must contain only letters and numbers.";
}
break;
case 'alpha':
if (!preg_match('/^[a-zA-Z]+$/', $value)) {
$errors[$field][] = "{$field_name} must contain only letters and numbers.";
}
break;
case 'alphanum-spaces':
if (!preg_match('/^[a-zA-Z0-9\s_]+$/', $value)) {
$errors[$field][] = "{$field_name} must contain only letters, numbers, spaces, and underscores.";
}
break;
case 'alpha-spaces':
if (!preg_match('/^[a-zA-Z\s_]+$/', $value)) {
$errors[$field][] = "{$field_name} must contain only letters, numbers, spaces, and underscores.";
}
break;
case 'email':
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
$errors[$field][] = "{$field_name} must be a valid email address.";
}
break;
case 'int':
if (!filter_var($value, FILTER_VALIDATE_INT)) {
$errors[$field][] = "{$field_name} must be an integer.";
}
break;
case 'min':
if ($value < $rule_args) {
$errors[$field][] = "{$field_name} must be at least {$rule_args}.";
}
break;
case 'max':
if ($value > $rule_args) {
$errors[$field][] = "{$field_name} must be no more than {$rule_args}.";
}
break;
case 'regex':
if (!preg_match($rule_args, $value)) {
$errors[$field][] = "{$field_name} does not match the required pattern.";
}
break;
case 'in':
$options = explode(',', $rule_args);
if (!in_array($value, $options)) {
$errors[$field][] = "{$field_name} must be one of: " . implode(', ', $options);
}
break;
case 'confirm':
$field_to_confirm = substr($field, 8);
$confirm_value = $data[$field_to_confirm] ?? '';
$confirm_field_name = ucfirst(str_replace('_', ' ', $field_to_confirm));
if ($value !== $confirm_value) {
$errors[$field][] = "{$field_name} must match {$confirm_field_name}.";
}
break;
case 'unique':
list($table, $column) = explode(',', $rule_args, 2);
if (db()->exists($table, $column, $value)) {
$errors[$field][] = "{$field_name} must be unique.";
}
break;
}
}
}
foreach ($input_data as $field => $value) {
if (!isset($data[$field])) $data[$field] = trim($value);
}
return [
'valid' => empty($errors),
'data' => $data,
'errors' => $errors
];
}
/**
* Generates a ul list from `validate()`'s errors.
*/
function ul_from_validate_errors(array $errors): string
{
$string = '<ul>';
foreach ($errors as $field => $errors) {
$string .= '<li>';
foreach ($errors as $error) $string .= $error;
$string .= '</li>';
}
return $string . '</ul>';
}

183
src/router.php Normal file
View File

@ -0,0 +1,183 @@
<?php
/**
* A radix-trie based URI router. Seperates URIs into chunks, then turns those chunks into an efficiently parsed
* trie. Supports URI variables!
*/
class Router
{
/**
* List of valid HTTP verbs.
*/
private const VALID_METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
/**
* The tree of currently registered routes.
*/
private array $routes = [];
/**
* Store the last inserted node so we can register middleware and attributes to it.
*/
private array $last_inserted_node;
/**
* Add a route to the route tree. The route must be a URI path, and contain dynamic segments
* using a colon prefix. (:id, :slug, etc)
*
* Example:
* `$r->add($routes, 'GET', '/posts/:id', function($id) { echo "Viewing post $id"; });`
*/
public function add(string $method, string $route, callable $handler): Router
{
$this->validateMethod($method);
$this->validateRoute($route);
// Expand the route into segments and make dynamic segments into a common placeholder
$segments = array_map(function($segment) {
return str_starts_with($segment, ':') ? ':x' : $segment;
}, explode('/', trim($route, '/')));
// Push each segment into the routes array as a node, except if this is the root node
$node = &$this->routes;
foreach ($segments as $segment) {
// skip an empty segment, which allows us to register handlers for the root node
if ($segment === '') continue;
$node = &$node[$segment]; // build the node tree as we go
}
// Add the handler to the last node
$node[$method] = ['handler' => $handler, 'middleware' => []];
// Store a reference to the node so we can add middleware to it.
$this->last_inserted_node = &$node[$method];
return $this;
}
/**
* Perform a lookup in the route tree for a given method and URI. Returns an array with a result code,
* a handler if found, and any dynamic parameters. Codes are 200 for success, 404 for not found, and
* 405 for method not allowed.
*
* @return array ['code', 'handler', 'params']
*/
public function lookup(string $method, string $uri): array
{
// node is a reference to our current location in the node tree
$node = $this->routes;
// params will hold any dynamic segments we find
$params = [];
// if the URI is just a slash, we can return the handler for the root node
if ($uri === '/') {
return isset($node[$method])
? ['code' => 200, 'handler' => $node[$method]['handler']]
: ['code' => 405];
}
// We'll split up the URI into segments and traverse the node tree
foreach (explode('/', trim($uri, '/')) as $segment) {
// if there is a node for this segment, move to it
if (isset($node[$segment])) {
$node = $node[$segment];
continue;
}
// if there is a dynamic segment, move to it and store the value
if (isset($node[':x'])) {
$params[] = $segment;
$node = $node[':x'];
continue;
}
// if we can't find a node for this segment, return 404
return ['code' => 404];
}
// if we found a handler for the method, return it and any params. if not, return a 405
return isset($node[$method])
? ['code' => 200, 'handler' => $node[$method]['handler'], 'params' => $params ?? [], 'middleware' => $node[$method]['middleware']]
: ['code' => 405];
}
/**
* Add a middleware function to the last inserted node's stack.
*/
public function middleware(callable $middleware): Router
{
$this->last_inserted_node['middleware'][] = $middleware;
return $this;
}
/**
* Shorthand to register a GET route.
*/
public function get(string $route, callable $handler): Router
{
return $this->add('GET', $route, $handler);
}
/**
* Shorthand to register a POST route.
*/
public function post(string $route, callable $handler): Router
{
return $this->add('POST', $route, $handler);
}
/**
* Shorthand to register a PUT route.
*/
public function put(string $route, callable $handler): Router
{
return $this->add('PUT', $route, $handler);
}
/**
* Shorthand to register a DELETE route.
*/
public function delete(string $route, callable $handler): Router
{
return $this->add('DELETE', $route, $handler);
}
/**
* Shorthand to register a PATCH route.
*/
public function patch(string $route, callable $handler): Router
{
return $this->add('PATCH', $route, $handler);
}
/**
* Validate the given method against valid HTTP verbs.
*/
private function validateMethod(string $method): void
{
if (!in_array($method, self::VALID_METHODS)) {
throw new InvalidArgumentException("Invalid HTTP method: $method");
}
}
/**
* Validate that a new route follows expected formatting.
*/
private function validateRoute(string $route): void
{
if ($route === '') {
throw new InvalidArgumentException("Route cannot be empty");
}
// Ensure route starts with a slash
if (!str_starts_with($route, '/')) {
throw new InvalidArgumentException("Route must start with a '/'");
}
// Optional: Check for consecutive dynamic segments or invalid characters
if (preg_match('/(:x.*){2,}/', $route)) {
throw new InvalidArgumentException("Invalid route pattern: consecutive dynamic segments");
}
}
}

View File

@ -13,7 +13,7 @@ function inn()
if ($townrow === false) { display("Cheat attempt detected.<br><br>Get a life, loser.", "Error"); } if ($townrow === false) { display("Cheat attempt detected.<br><br>Get a life, loser.", "Error"); }
if ($userrow["gold"] < $townrow["innprice"]) { if ($userrow["gold"] < $townrow["innprice"]) {
display("You do not have enough gold to stay at this Inn tonight.<br><br>You may return to <a href=\"index.php\">town</a>, or use the direction buttons on the left to start exploring.", "Inn"); display("You do not have enough gold to stay at this Inn tonight.<br><br>You may return to <a href=\"/\">town</a>, or use the direction buttons on the left to start exploring.", "Inn");
} }
if (isset($_POST["submit"])) { if (isset($_POST["submit"])) {
@ -23,16 +23,16 @@ function inn()
[$newgold, $userrow['maxhp'], $userrow['maxmp'], $userrow['maxtp'], $userrow['id'] [$newgold, $userrow['maxhp'], $userrow['maxmp'], $userrow['maxtp'], $userrow['id']
]); ]);
$title = "Inn"; $title = "Inn";
$page = "You wake up feeling refreshed and ready for action.<br><br>You may return to <a href=\"index.php\">town</a>, or use the direction buttons on the left to start exploring."; $page = "You wake up feeling refreshed and ready for action.<br><br>You may return to <a href=\"/\">town</a>, or use the direction buttons on the left to start exploring.";
} elseif (isset($_POST["cancel"])) { } elseif (isset($_POST["cancel"])) {
redirect('index.php'); redirect('/');
} else { } else {
$title = "Inn"; $title = "Inn";
$page = <<<HTML $page = <<<HTML
Resting at the inn will refill your current HP, MP, and TP to their maximum levels.<br><br> Resting at the inn will refill your current HP, MP, and TP to their maximum levels.<br><br>
A night's sleep at this Inn will cost you <b>{$townrow["innprice"]} gold</b>. Is that ok?<br><br> A night's sleep at this Inn will cost you <b>{$townrow["innprice"]} gold</b>. Is that ok?<br><br>
<form action="index.php?do=inn" method="post"> <form action="/inn" method="post">
<input type="submit" name="submit" value="Yes" /> <input type="submit" name="cancel" value="No" /> <input type="submit" name="submit" value="Yes"> <input type="submit" name="cancel" value="No">
</form> </form>
HTML; HTML;
} }
@ -57,19 +57,19 @@ function buy()
$attrib = ($itemsrow["type"] == 1) ? "Attack Power:" : "Defense Power:"; $attrib = ($itemsrow["type"] == 1) ? "Attack Power:" : "Defense Power:";
$page .= "<tr><td width=\"4%\">"; $page .= "<tr><td width=\"4%\">";
$page .= match ($itemsrow["type"]) { $page .= match ($itemsrow["type"]) {
1 => '<img src="images/icon_weapon.gif" alt="weapon" /></td>', 1 => '<img src="/img/icon_weapon.gif" alt="weapon" /></td>',
2 => '<img src="images/icon_armor.gif" alt="armor" /></td>', 2 => '<img src="/img/icon_armor.gif" alt="armor" /></td>',
3 => '<img src="images/icon_shield.gif" alt="shield" /></td>' 3 => '<img src="/img/icon_shield.gif" alt="shield" /></td>'
}; };
if ($userrow["weaponid"] == $itemsrow["id"] || $userrow["armorid"] == $itemsrow["id"] || $userrow["shieldid"] == $itemsrow["id"]) { if ($userrow["weaponid"] == $itemsrow["id"] || $userrow["armorid"] == $itemsrow["id"] || $userrow["shieldid"] == $itemsrow["id"]) {
$page .= "<td width=\"32%\"><span class=\"light\">".$itemsrow["name"]."</span></td><td width=\"32%\"><span class=\"light\">$attrib ".$itemsrow["attribute"]."</span></td><td width=\"32%\"><span class=\"light\">Already purchased</span></td></tr>\n"; $page .= "<td width=\"32%\"><span class=\"light\">".$itemsrow["name"]."</span></td><td width=\"32%\"><span class=\"light\">$attrib ".$itemsrow["attribute"]."</span></td><td width=\"32%\"><span class=\"light\">Already purchased</span></td></tr>\n";
} else { } else {
if ($itemsrow["special"] != "X") { $specialdot = "<span class=\"highlight\">&#42;</span>"; } else { $specialdot = ""; } if ($itemsrow["special"] != "X") { $specialdot = "<span class=\"highlight\">&#42;</span>"; } else { $specialdot = ""; }
$page .= "<td width=\"32%\"><b><a href=\"index.php?do=buy2:".$itemsrow["id"]."\">".$itemsrow["name"]."</a>$specialdot</b></td><td width=\"32%\">$attrib <b>".$itemsrow["attribute"]."</b></td><td width=\"32%\">Price: <b>".$itemsrow["buycost"]." gold</b></td></tr>\n"; $page .= "<td width=\"32%\"><b><a href=\"/buy2/{$itemsrow["id"]}\">".$itemsrow["name"]."</a>$specialdot</b></td><td width=\"32%\">$attrib <b>".$itemsrow["attribute"]."</b></td><td width=\"32%\">Price: <b>".$itemsrow["buycost"]." gold</b></td></tr>\n";
} }
} }
$page .= "</table><br>\n"; $page .= "</table><br>\n";
$page .= "If you've changed your mind, you may also return back to <a href=\"index.php\">town</a>.\n"; $page .= "If you've changed your mind, you may also return back to <a href=\"/\">town</a>.\n";
$title = "Buy Items"; $title = "Buy Items";
display($page, $title); display($page, $title);
@ -90,7 +90,7 @@ function buy2($id)
$item = get_item($id); $item = get_item($id);
if ($userrow["gold"] < $item["buycost"]) { if ($userrow["gold"] < $item["buycost"]) {
display("You do not have enough gold to buy this item.<br><br>You may return to <a href=\"index.php\">town</a>, <a href=\"index.php?do=buy\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Items"); display("You do not have enough gold to buy this item.<br><br>You may return to <a href=\"/\">town</a>, <a href=\"/buy\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Items");
} }
$type_to_row_mapping = [1 => 'weaponid', 2 => 'armorid', 3 => 'shieldid']; $type_to_row_mapping = [1 => 'weaponid', 2 => 'armorid', 3 => 'shieldid'];
@ -98,9 +98,9 @@ function buy2($id)
if ($current_equipped_id != 0) { if ($current_equipped_id != 0) {
$item2 = get_item($current_equipped_id); $item2 = get_item($current_equipped_id);
$page = "If you are buying the ".$item["name"].", then I will buy your ".$item2["name"]." for ".ceil($item2["buycost"] / 2)." gold. Is that ok?<br><br><form action=\"index.php?do=buy3:$id\" method=\"post\"><input type=\"submit\" name=\"submit\" value=\"Yes\" /> <input type=\"submit\" name=\"cancel\" value=\"No\" /></form>"; $page = "If you are buying the ".$item["name"].", then I will buy your ".$item2["name"]." for ".ceil($item2["buycost"] / 2)." gold. Is that ok?<br><br><form action=\"/buy3/$id\" method=\"post\"><input type=\"submit\" name=\"submit\" value=\"Yes\" /> <input type=\"submit\" name=\"cancel\" value=\"No\" /></form>";
} else { } else {
$page = "You are buying the ".$item["name"].", is that ok?<br><br><form action=\"index.php?do=buy3:$id\" method=\"post\"><input type=\"submit\" name=\"submit\" value=\"Yes\" /> <input type=\"submit\" name=\"cancel\" value=\"No\" /></form>"; $page = "You are buying the ".$item["name"].", is that ok?<br><br><form action=\"/buy3/$id\" method=\"post\"><input type=\"submit\" name=\"submit\" value=\"Yes\" /> <input type=\"submit\" name=\"cancel\" value=\"No\" /></form>";
} }
display($page, "Buy Items"); display($page, "Buy Items");
@ -112,7 +112,7 @@ function buy2($id)
function buy3($id) function buy3($id)
{ {
if (isset($_POST["cancel"])) redirect('index.php'); if (isset($_POST["cancel"])) redirect('/');
global $userrow; global $userrow;
@ -124,7 +124,7 @@ function buy3($id)
$item = get_item($id); $item = get_item($id);
if ($userrow["gold"] < $item["buycost"]) { if ($userrow["gold"] < $item["buycost"]) {
display("You do not have enough gold to buy this item.<br><br>You may return to <a href=\"index.php\">town</a>, <a href=\"index.php?do=buy\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Items"); display("You do not have enough gold to buy this item.<br><br>You may return to <a href=\"/\">town</a>, <a href=\"/buy\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Items");
} }
$type_mapping = [ $type_mapping = [
@ -212,7 +212,7 @@ function buy3($id)
$stmt = db()->query("UPDATE users SET " . implode(", ", $updateFields) . " WHERE id = ?;", $updateValues); $stmt = db()->query("UPDATE users SET " . implode(", ", $updateFields) . " WHERE id = ?;", $updateValues);
if ($stmt === false) exit("Failed to purchase and equip $id. Go back and try again."); if ($stmt === false) exit("Failed to purchase and equip $id. Go back and try again.");
display("Thank you for purchasing this item.<br><br>You may return to <a href=\"index.php\">town</a>, <a href=\"index.php?do=buy\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Items"); display("Thank you for purchasing this item.<br><br>You may return to <a href=\"/\">town</a>, <a href=\"/buy\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Items");
} }
/** /**
@ -237,14 +237,14 @@ function maps()
foreach($mappedtowns as $b) if ($b == $townrow["id"]) $mapped = true; foreach($mappedtowns as $b) if ($b == $townrow["id"]) $mapped = true;
if ($mapped == false) { if ($mapped == false) {
$page .= "<tr><td width=\"25%\"><a href=\"index.php?do=maps2:".$townrow["id"]."\">".$townrow["name"]."</a></td><td width=\"25%\">Price: ".$townrow["mapprice"]." gold</td><td width=\"50%\" colspan=\"2\">Buy map to reveal details.</td></tr>\n"; $page .= "<tr><td width=\"25%\"><a href=\"/maps2/{$townrow["id"]}\">".$townrow["name"]."</a></td><td width=\"25%\">Price: ".$townrow["mapprice"]." gold</td><td width=\"50%\" colspan=\"2\">Buy map to reveal details.</td></tr>\n";
} else { } else {
$page .= "<tr><td width=\"25%\"><span class=\"light\">".$townrow["name"]."</span></td><td width=\"25%\"><span class=\"light\">Already mapped.</span></td><td width=\"35%\"><span class=\"light\">Location: $latitude $longitude</span></td><td width=\"15%\"><span class=\"light\">TP: ".$townrow["travelpoints"]."</span></td></tr>\n"; $page .= "<tr><td width=\"25%\"><span class=\"light\">".$townrow["name"]."</span></td><td width=\"25%\"><span class=\"light\">Already mapped.</span></td><td width=\"35%\"><span class=\"light\">Location: $latitude $longitude</span></td><td width=\"15%\"><span class=\"light\">TP: ".$townrow["travelpoints"]."</span></td></tr>\n";
} }
} }
$page .= "</table><br>\n"; $page .= "</table><br>\n";
$page .= "If you've changed your mind, you may also return back to <a href=\"index.php\">town</a>.\n"; $page .= "If you've changed your mind, you may also return back to <a href=\"/\">town</a>.\n";
display($page, "Buy Maps"); display($page, "Buy Maps");
} }
@ -259,10 +259,10 @@ function maps2($id)
$townrow = get_town_by_id($id); $townrow = get_town_by_id($id);
if ($userrow["gold"] < $townrow["mapprice"]) { if ($userrow["gold"] < $townrow["mapprice"]) {
display("You do not have enough gold to buy this map.<br><br>You may return to <a href=\"index.php\">town</a>, <a href=\"index.php?do=maps\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Maps"); display("You do not have enough gold to buy this map.<br><br>You may return to <a href=\"/\">town</a>, <a href=\"/maps\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Maps");
} }
$page = "You are buying the ".$townrow["name"]." map. Is that ok?<br><br><form action=\"index.php?do=maps3:$id\" method=\"post\"><input type=\"submit\" name=\"submit\" value=\"Yes\" /> <input type=\"submit\" name=\"cancel\" value=\"No\" /></form>"; $page = "You are buying the ".$townrow["name"]." map. Is that ok?<br><br><form action=\"/maps3/$id\" method=\"post\"><input type=\"submit\" name=\"submit\" value=\"Yes\" /> <input type=\"submit\" name=\"cancel\" value=\"No\" /></form>";
display($page, "Buy Maps"); display($page, "Buy Maps");
} }
@ -272,14 +272,14 @@ function maps2($id)
*/ */
function maps3($id) function maps3($id)
{ {
if (isset($_POST["cancel"])) redirect('index.php'); if (isset($_POST["cancel"])) redirect('/');
global $userrow; global $userrow;
$townrow = get_town_by_id($id); $townrow = get_town_by_id($id);
if ($userrow["gold"] < $townrow["mapprice"]) { if ($userrow["gold"] < $townrow["mapprice"]) {
display("You do not have enough gold to buy this map.<br><br>You may return to <a href=\"index.php\">town</a>, <a href=\"index.php?do=maps\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Maps"); display("You do not have enough gold to buy this map.<br><br>You may return to <a href=\"/\">town</a>, <a href=\"/maps\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Maps");
} }
$mappedtowns = $userrow["towns"].",$id"; $mappedtowns = $userrow["towns"].",$id";
@ -287,7 +287,7 @@ function maps3($id)
db()->query('UPDATE users SET towns=?, gold=? WHERE id=?;', [$mappedtowns, $newgold, $userrow['id']]); db()->query('UPDATE users SET towns=?, gold=? WHERE id=?;', [$mappedtowns, $newgold, $userrow['id']]);
display("Thank you for purchasing this map.<br><br>You may return to <a href=\"index.php\">town</a>, <a href=\"index.php?do=maps\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Maps"); display("Thank you for purchasing this map.<br><br>You may return to <a href=\"/\">town</a>, <a href=\"/maps\">store</a>, or use the direction buttons on the left to start exploring.", "Buy Maps");
} }
/** /**
@ -297,7 +297,7 @@ function travelto($id, bool $usepoints = true)
{ {
global $userrow; global $userrow;
if ($userrow["currentaction"] == "Fighting") redirect('index.php?do=fight'); if ($userrow["currentaction"] == "Fighting") redirect('/fight');
$townrow = get_town_by_id($id); $townrow = get_town_by_id($id);
@ -310,7 +310,7 @@ function travelto($id, bool $usepoints = true)
} }
if (($userrow["latitude"] == $townrow["latitude"]) && ($userrow["longitude"] == $townrow["longitude"])) { if (($userrow["latitude"] == $townrow["latitude"]) && ($userrow["longitude"] == $townrow["longitude"])) {
display("You are already in this town. <a href=\"index.php\">Click here</a> to return to the main town screen.", "Travel To"); display("You are already in this town. <a href=\"/\">Click here</a> to return to the main town screen.", "Travel To");
} }
$newtp = ($usepoints) ? $userrow["currenttp"] - $townrow["travelpoints"] : $userrow["currenttp"]; $newtp = ($usepoints) ? $userrow["currenttp"] - $townrow["travelpoints"] : $userrow["currenttp"];
@ -332,6 +332,6 @@ function travelto($id, bool $usepoints = true)
$newtp, $newlat, $newlon, $newid $newtp, $newlat, $newlon, $newid
]); ]);
$page = "You have travelled to ".$townrow["name"].". You may now <a href=\"index.php\">enter this town</a>."; $page = "You have travelled to ".$townrow["name"].". You may now <a href=\"/\">enter this town</a>.";
display($page, "Travel To"); display($page, "Travel To");
} }

View File

@ -54,7 +54,7 @@ a:hover {
<b><u>DK Administration</u></b><br><br> <b><u>DK Administration</u></b><br><br>
<b>Links:</b><br> <b>Links:</b><br>
<a href="admin.php">Admin Home</a><br> <a href="admin.php">Admin Home</a><br>
<a href="index.php">Game Home</a><br><br> <a href="/">Game Home</a><br><br>
<b>Primary Data:</b><br> <b>Primary Data:</b><br>
<a href="admin.php?do=main">Main Settings</a><br> <a href="admin.php?do=main">Main Settings</a><br>
<a href="admin.php?do=news">Add News Post</a><br> <a href="admin.php?do=news">Add News Post</a><br>

View File

@ -1,34 +1,44 @@
<?php <?php
$template = <<<THEVERYENDOFYOU $template = <<<HTML
<head> <head>
<title>shoutbox</title> <title>Babblebox</title>
<style type="text/css"> <style type="text/css">
body { body {
background-image: url(images/background.jpg); background-image: url(/img/background.jpg);
color: black; color: black;
font: 11px verdana; font: 11px verdana;
margins: 0px; margin: 0px;
padding: 0px; padding: 0px;
} }
div {
padding: 2px; div {
border: solid 1px black; padding: 2px;
margin: 2px; border: solid 1px black;
text-align: left; margin: 2px;
} text-align: left;
a { }
color: #663300;
text-decoration: none; a {
font-weight: bold; color: #663300;
} text-decoration: none;
a:hover { font-weight: bold;
color: #330000; }
}
</style> a:hover {
color: #330000;
}
div.message {
background-color: white;
}
div.message:nth-child(even) {
background-color: #eeeeee;
}
</style>
</head> </head>
<body onload="window.scrollTo(0,99999)"> <body onload="window.scrollTo(0,99999)">
{{content}} {{content}}
</body> </body>
</html> </html>
THEVERYENDOFYOU; HTML;
?>

View File

@ -1,7 +1,7 @@
<?php <?php
$template = <<<THEVERYENDOFYOU $template = <<<THEVERYENDOFYOU
<table width="100%"> <table width="100%">
<tr><td class="title"><img src="images/title_fighting.gif" alt="Fighting" /></td></tr> <tr><td class="title"><img src="/img/title_fighting.gif" alt="Fighting" /></td></tr>
<tr><td> <tr><td>
You are fighting a <b>{{monstername}}</b><br><br> You are fighting a <b>{{monstername}}</b><br><br>
{{monsterhp}} {{monsterhp}}

View File

@ -1,44 +1,35 @@
<?php <?php
$template = <<<HTML $template = <<<HTML
<table width="100%"> <section>
<tr><td class="title"><img src="images/button_location.gif" alt="Location" title="Location" /></td></tr> <div class="title"><img src="/img/button_location.gif" alt="Location" title="Location"></div>
<tr><td>
Currently: {{currentaction}}<br> Currently: {{currentaction}}<br>
Latitude: {{latitude}}<br> Latitude: {{latitude}}<br>
Longitude: {{longitude}}<br> Longitude: {{longitude}}<br>
<a href="javascript:openmappopup()">View Map</a><br><br> <a href="javascript:openmappopup()">View Map</a><br>
<form action="index.php?do=move" method="post"> <form action="/move" method="post" class="move-compass">
<center> <button type="submit" name="direction" value="north" class="north">North</button>
<input name="north" type="submit" value="North" /><br> <div class="mid">
<input name="west" type="submit" value="West" /><input name="east" type="submit" value="East" /><br> <button type="submit" name="direction" value="west" class="west">West</button>
<input name="south" type="submit" value="South" /> <button type="submit" name="direction" value="east" class="east">East</button>
</center> </div>
<button type="submit" name="direction" value="south" class="south">South</button>
</form> </form>
</td></tr> </section>
</table>
<br> <section>
<div class="title"><img src="/img/button_towns.gif" alt="Towns" title="Towns"></div>
<table width="100%">
<tr><td class="title"><img src="images/button_towns.gif" alt="Towns" title="Towns" /></td></tr>
<tr><td>
{{currenttown}} {{currenttown}}
Travel To:<br> Travel To:<br>
{{townslist}} {{townslist}}
</td></tr> </section>
</table>
<br> <section>
<div class="title"><img src="/img/button_functions.gif" alt="Functions" title="Functions"></div>
<table width="100%"> <a href="/">Home</a><br>
<tr><td class="title"><img src="images/button_functions.gif" alt="Functions" title="Functions" /></td></tr>
<tr><td>
<a href="/index.php">Home</a><br>
{{forumslink}} {{forumslink}}
{{adminlink}} {{adminlink}}
<a href="users.php?do=changepassword">Change Password</a><br> <a href="users.php?do=changepassword">Change Password</a><br>
<a href="login.php?do=logout">Log Out</a><br> <a href="login.php?do=logout">Log Out</a><br>
<a href="help.php">Help</a> <a href="help.php">Help</a>
</td></tr> </section>
</table>
HTML; HTML;

View File

@ -1,13 +1,35 @@
<?php <?php
$template = <<<THEVERYENDOFYOU
<form action="login.php?do=login" method="post"> $template = <<<HTML
<table width="75%"> <form action="login.php?do=login" method="post">
<tr><td width="30%">Username:</td><td><input type="text" size="30" name="username" /></td></tr> <table width="75%">
<tr><td>Password:</td><td><input type="password" size="30" name="password" /></td></tr> <tr>
<tr><td>Remember me?</td><td><input type="checkbox" name="rememberme" value="yes" /> Yes</td></tr> <td width="30%">Username:</td>
<tr><td colspan="2"><input type="submit" name="submit" value="Log In" /></td></tr> <td><input type="text" name="username"></td>
<tr><td colspan="2">Checking the "Remember Me" option will store your login information in a cookie so you don't have to enter it next time you get online.<br><br>Want to play? You gotta <a href="users.php?do=register">register your own character.</a><br><br>You may also <a href="users.php?do=changepassword">change your password</a>, or <a href="users.php?do=lostpassword">request a new one</a> if you've lost yours.</td></tr> </tr>
</table> <tr>
</form> <td>Password:</td>
THEVERYENDOFYOU; <td><input type="password" name="password"></td>
?> </tr>
<tr>
<td>Remember me?</td>
<td>
<input type="hidden" name="remember" value="0">
<input type="checkbox" name="remember" value="1">
</td>
</tr>
<tr>
<td colspan="2"><input type="submit" name="submit" value="Log In"></td>
</tr>
<tr>
<td colspan="2">
Checking the "Remember Me" option will store your login information in a cookie so you don't have
to enter it next time you get online.<br><br>Want to play? You gotta
<a href="users.php?do=register">register your own character.</a><br><br>You may also
<a href="users.php?do=changepassword">change your password</a>, or
<a href="users.php?do=lostpassword">request a new one</a> if you've lost yours.
</td>
</tr>
</table>
</form>
HTML;

View File

@ -4,7 +4,7 @@ $template = <<<THEVERYENDOFYOU
<title>{{title}}</title> <title>{{title}}</title>
<style type="text/css"> <style type="text/css">
body { body {
background-image: url(images/background.jpg); background-image: url(/img/background.jpg);
color: black; color: black;
font: 11px verdana; font: 11px verdana;
} }
@ -65,4 +65,4 @@ a:hover {
</center></body> </center></body>
</html> </html>
THEVERYENDOFYOU; THEVERYENDOFYOU;
?> ?>

View File

@ -1,9 +1,9 @@
<?php <?php
$template = <<<HTML $template = <<<HTML
Here is the character profile for <b>{{username}}</b>.<br><br> Here is the character profile for <b>{{username}}</b>.<br><br>
When you're finished, you may <a href="index.php">return to town</a>.<br><br> When you're finished, you may <a href="/">return to town</a>.<br><br>
<table width="200"> <table width="200">
<tr><td class="title"><img src="images/button_character.gif" alt="Character" title="Character" /></td></tr> <tr><td class="title"><img src="/img/button_character.gif" alt="Character" title="Character" /></td></tr>
<tr><td> <tr><td>
<b>{{username}}</b><br><br> <b>{{username}}</b><br><br>
@ -24,12 +24,12 @@ $template = <<<HTML
</table><br> </table><br>
<table width="200"> <table width="200">
<tr><td class="title"><img src="images/button_inventory.gif" alt="Inventory" title="Inventory" /></td></tr> <tr><td class="title"><img src="/img/button_inventory.gif" alt="Inventory" title="Inventory" /></td></tr>
<tr><td> <tr><td>
<table width="100%"> <table width="100%">
<tr><td><img src="images/icon_weapon.gif" alt="Weapon" title="Weapon" /></td><td width="100%">Weapon: {{weaponname}}</td></tr> <tr><td><img src="/img/icon_weapon.gif" alt="Weapon" title="Weapon" /></td><td width="100%">Weapon: {{weaponname}}</td></tr>
<tr><td><img src="images/icon_armor.gif" alt="Armor" title="Armor" /></td><td width="100%">Armor: {{armorname}}</td></tr> <tr><td><img src="/img/icon_armor.gif" alt="Armor" title="Armor" /></td><td width="100%">Armor: {{armorname}}</td></tr>
<tr><td><img src="images/icon_shield.gif" alt="Shield" title="Shield" /></td><td width="100%">Shield: {{shieldname}}</td></tr> <tr><td><img src="/img/icon_shield.gif" alt="Shield" title="Shield" /></td><td width="100%">Shield: {{shieldname}}</td></tr>
</table> </table>
Slot 1: {{slot1name}}<br> Slot 1: {{slot1name}}<br>
Slot 2: {{slot2name}}<br> Slot 2: {{slot2name}}<br>

View File

@ -1,90 +1,44 @@
<?php <?php
$template = <<<THEVERYENDOFYOU $template = <<<HTML
<!DOCTYPE html>
<html lang="en">
<head> <head>
<title>{{title}}</title> <meta charset="UTF-8">
<style type="text/css"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
body { <title>{{title}}</title>
background-image: url(images/background.jpg); <link rel="stylesheet" href="/css/dk.css">
color: black;
font: 11px verdana; <script>
} function opencharpopup(){
table { var popurl="/showchar"
border-style: none; winpops=window.open(popurl,"","width=210,height=500,scrollbars")
padding: 0px; }
font: 11px verdana; function openmappopup(){
} var popurl="/showmap"
td { winpops=window.open(popurl,"","width=520,height=520,scrollbars")
border-style: none; }
padding: 3px; </script>
vertical-align: top;
}
td.top {
border-bottom: solid 2px black;
}
td.left {
width: 180px;
border-right: solid 2px black;
}
td.right {
width: 180px;
border-left: solid 2px black;
}
a {
color: #663300;
text-decoration: none;
font-weight: bold;
}
a:hover {
color: #330000;
}
.small {
font: 10px verdana;
}
.highlight {
color: red;
}
.light {
color: #999999;
}
.title {
border: solid 1px black;
background-color: #eeeeee;
font-weight: bold;
padding: 5px;
margin: 3px;
}
.copyright {
border: solid 1px black;
background-color: #eeeeee;
font: 10px verdana;
}
</style>
<script>
function opencharpopup(){
var popurl="index.php?do=showchar"
winpops=window.open(popurl,"","width=210,height=500,scrollbars")
}
function openmappopup(){
var popurl="index.php?do=showmap"
winpops=window.open(popurl,"","width=520,height=520,scrollbars")
}
</script>
</head> </head>
<body><center> <body>
<table cellspacing="0" width="90%"><tr> <div id="game-container">
<td class="top" colspan="3"> <header>
<table width="100%"><tr><td><img src="images/logo.gif" alt="{{dkgamename}}" title="{{dkgamename}}" border="0" /></td><td style="text-align:right; vertical-align:middle;">{{topnav}}</td></tr></table> <img id="logo" src="/img/logo.gif" alt="{{dkgamename}}" title="{{dkgamename}}">
</td> <nav>{{topnav}}</nav>
</tr><tr> </header>
<td class="left">{{leftnav}}</td>
<td class="middle">{{content}}</td> <main>
<td class="right">{{rightnav}}</td> <section id="left">{{leftnav}}</section>
</tr> <section id="middle">{{content}}</section>
</table><br> <section id="right">{{rightnav}}</section>
<table class="copyright" width="90%"><tr> </main>
<td width="25%" align="center">Powered by <a href="http://dragon.se7enet.com/dev.php" target="_new">Dragon Knight</a></td><td width="25%" align="center">&copy; 2003-2006 by renderse7en</td><td width="25%" align="center">{{totaltime}} Seconds, {{numqueries}} Queries</td><td width="25%" align="center">Version {{version}} {{build}}</td>
</tr></table> <footer>
</center></body> <div>Powered by <a href="http://dragon.se7enet.com/dev.php" target="_new">Dragon Knight</a></div>
<div>&copy; 2024 Sharkk</div>
<div>{{totaltime}} Seconds, {{numqueries}} Queries</div>
<div>Version {{version}} {{build}}</div>
</footer>
</div>
</body>
</html> </html>
THEVERYENDOFYOU; HTML;
?>

View File

@ -1,39 +1,30 @@
<?php <?php
$template = <<<THEVERYENDOFYOU $template = <<<HTML
<table width="100%"> <section>
<tr><td class="title"><img src="images/button_character.gif" alt="Character" title="Character" /></td></tr> <div class="title"><img src="/img/button_character.gif" alt="Character" title="Character"></div>
<tr><td> <b>{{username}}</b><br>
<b>{{username}}</b><br> Level: {{level}}<br>
Level: {{level}}<br> Exp: {{experience}}<br>
Exp: {{experience}}<br> Gold: {{gold}}<br>
Gold: {{gold}}<br> HP: {{currenthp}}<br>
HP: {{currenthp}}<br> MP: {{currentmp}}<br>
MP: {{currentmp}}<br> TP: {{currenttp}}<br>
TP: {{currenttp}}<br> {{statbars}}<br>
{{statbars}}<br> <a href="javascript:opencharpopup()">Extended Stats</a>
<a href="javascript:opencharpopup()">Extended Stats</a> </section>
</td></tr>
</table><br>
<table width="100%"> <section>
<tr><td class="title"><img src="images/button_inventory.gif" alt="Inventory" title="Inventory" /></td></tr> <div class="title"><img src="/img/button_inventory.gif" alt="Inventory" title="Inventory"></div>
<tr><td> <img src="/img/icon_weapon.gif" alt="Weapon" title="Weapon"> Weapon: {{weaponname}}<br>
<table width="100%"> <img src="/img/icon_armor.gif" alt="Armor" title="Armor"> Armor: {{armorname}}<br>
<tr><td><img src="images/icon_weapon.gif" alt="Weapon" title="Weapon" /></td><td width="100%">Weapon: {{weaponname}}</td></tr> <img src="/img/icon_shield.gif" alt="Shield" title="Shield"> Shield: {{shieldname}}<br>
<tr><td><img src="images/icon_armor.gif" alt="Armor" title="Armor" /></td><td width="100%">Armor: {{armorname}}</td></tr> Slot 1: {{slot1name}}<br>
<tr><td><img src="images/icon_shield.gif" alt="Shield" title="Shield" /></td><td width="100%">Shield: {{shieldname}}</td></tr> Slot 2: {{slot2name}}<br>
</table> Slot 3: {{slot3name}}
Slot 1: {{slot1name}}<br> </section>
Slot 2: {{slot2name}}<br>
Slot 3: {{slot3name}}
</td></tr>
</table><br>
<table width="100%"> <section>
<tr><td class="title"><img src="images/button_fastspells.gif" alt="Fast Spells" title="Fast Spells" /></td></tr> <div class="title"><img src="/img/button_fastspells.gif" alt="Fast Spells" title="Fast Spells"></div>
<tr><td> {{magiclist}}
{{magiclist}} </section>
</td></tr> HTML;
</table><br>
THEVERYENDOFYOU;
?>

View File

@ -1,7 +1,7 @@
<?php <?php
$template = <<<THEVERYENDOFYOU $template = <<<THEVERYENDOFYOU
<table width="100%"> <table width="100%">
<tr><td class="title"><img src="images/button_character.gif" alt="Character" title="Character" /></td></tr> <tr><td class="title"><img src="/img/button_character.gif" alt="Character" title="Character" /></td></tr>
<tr><td> <tr><td>
<b>{{username}}</b><br><br> <b>{{username}}</b><br><br>
@ -23,12 +23,12 @@ Defense Power: {{defensepower}}<br>
</table><br> </table><br>
<table width="100%"> <table width="100%">
<tr><td class="title"><img src="images/button_inventory.gif" alt="Inventory" title="Inventory" /></td></tr> <tr><td class="title"><img src="/img/button_inventory.gif" alt="Inventory" title="Inventory" /></td></tr>
<tr><td> <tr><td>
<table width="100%"> <table width="100%">
<tr><td><img src="images/icon_weapon.gif" alt="Weapon" title="Weapon" /></td><td width="100%">Weapon: {{weaponname}}</td></tr> <tr><td><img src="/img/icon_weapon.gif" alt="Weapon" title="Weapon" /></td><td width="100%">Weapon: {{weaponname}}</td></tr>
<tr><td><img src="images/icon_armor.gif" alt="Armor" title="Armor" /></td><td width="100%">Armor: {{armorname}}</td></tr> <tr><td><img src="/img/icon_armor.gif" alt="Armor" title="Armor" /></td><td width="100%">Armor: {{armorname}}</td></tr>
<tr><td><img src="images/icon_shield.gif" alt="Shield" title="Shield" /></td><td width="100%">Shield: {{shieldname}}</td></tr> <tr><td><img src="/img/icon_shield.gif" alt="Shield" title="Shield" /></td><td width="100%">Shield: {{shieldname}}</td></tr>
</table> </table>
Slot 1: {{slot1name}}<br> Slot 1: {{slot1name}}<br>
Slot 2: {{slot2name}}<br> Slot 2: {{slot2name}}<br>
@ -37,7 +37,7 @@ Slot 3: {{slot3name}}
</table><br> </table><br>
<table width="100%"> <table width="100%">
<tr><td class="title"><img src="images/button_spells.gif" alt="Spells" title="Spells" /></td></tr> <tr><td class="title"><img src="/img/button_spells.gif" alt="Spells" title="Spells" /></td></tr>
<tr><td> <tr><td>
{{magiclist}} {{magiclist}}
</td></tr> </td></tr>

View File

@ -1,26 +1,26 @@
<?php <?php
$template = <<<THEVERYENDOFYOU $template = <<<HTML
<table width="100%"> <div class="town-content">
<tr><td class="title"><img src="images/town_{{id}}.gif" alt="Welcome to {{name}}" title="Welcome to {{name}}" /></td></tr> <div class="options">
<tr><td> <div class="title"><img src="/img/town_{{id}}.gif" alt="Welcome to {{name}}" title="Welcome to {{name}}"></div>
<b>Town Options:</b><br> <b>Town Options:</b><br>
<ul> <ul>
<li /><a href="index.php?do=inn">Rest at the Inn</a> <li><a href="/inn">Rest at the Inn</a></li>
<li /><a href="index.php?do=buy">Buy Weapons/Armor</a> <li><a href="/buy">Buy Weapons/Armor</a></li>
<li /><a href="index.php?do=maps">Buy Maps</a> <li><a href="/maps">Buy Maps</a></li>
</ul> </ul>
</td></tr> </div>
<tr><td><center>
{{news}} <div class="news">
<br> {{news}}
<table width="95%"> </div>
<tr><td width="50%">
{{whosonline}} <div class="whos-online">
</td><td> {{whosonline}}
{{babblebox}} </div>
</td></tr>
</table> <div class="babblebox">
</td></tr> {{babblebox}}
</table> </div>
THEVERYENDOFYOU; </div>
?> HTML;