Rewrite lib and install to use new database and have better syntax

This commit is contained in:
Sky Johnson 2024-12-11 21:05:50 -06:00
parent 743c3cd6c4
commit ce06aecf84
6 changed files with 919 additions and 884 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.installed
database.db

View File

@ -1,11 +0,0 @@
<?php // config.php :: Low-level app/database variables.
$dbsettings = Array(
"server" => "localhost", // MySQL server name. (Default: localhost)
"user" => "", // MySQL username.
"pass" => "", // MySQL password.
"name" => "", // MySQL database name.
"prefix" => "dk", // Prefix for table names. (Default: dk)
"secretword" => ""); // Secret word used when hashing information for cookies.
?>

View File

@ -1,32 +0,0 @@
<?php // cookies.php :: Handles cookies. (Mmm, tasty!)
function checkcookies() {
include('config.php');
$row = false;
if (isset($_COOKIE["dkgame"])) {
// COOKIE FORMAT:
// {ID} {USERNAME} {PASSWORDHASH} {REMEMBERME}
$theuser = explode(" ",$_COOKIE["dkgame"]);
$query = doquery("SELECT * FROM {{table}} WHERE username='$theuser[1]'", "users");
if (mysql_num_rows($query) != 1) { die("Invalid cookie data (Error 1). Please clear cookies and log in again."); }
$row = mysql_fetch_array($query);
if ($row["id"] != $theuser[0]) { die("Invalid cookie data (Error 2). Please clear cookies and log in again."); }
if (md5($row["password"] . "--" . $dbsettings["secretword"]) !== $theuser[2]) { die("Invalid cookie data (Error 3). Please clear cookies and log in again."); }
// If we've gotten this far, cookie should be valid, so write a new one.
$newcookie = implode(" ",$theuser);
if ($theuser[3] == 1) { $expiretime = time()+31536000; } else { $expiretime = 0; }
setcookie ("dkgame", $newcookie, $expiretime, "/", "", 0);
$onlinequery = doquery("UPDATE {{table}} SET onlinetime=NOW() WHERE id='$theuser[0]' LIMIT 1", "users");
}
return $row;
}
?>

71
database.php Normal file
View File

@ -0,0 +1,71 @@
<?php
/**
* An extension to the SQLite3 class to add our own logging and binding semantics!
*/
class Database extends SQLite3
{
public int $count = 0;
public array $log = [];
public float $query_time = 0;
public function __construct(string $db_path)
{
parent::__construct($db_path);
parent::exec('PRAGMA cache_size = 32000');
parent::exec('PRAGMA journal_mode = WAL');
parent::exec('PRAGMA temp_store = MEMORY');
}
public function query(string $query, array $params = []): SQLite3Result|false
{
$p = strpos($query, '?') !== false;
$stmt = $this->prepare($query);
foreach ($params ?? [] as $k => $v) $stmt->bindValue($p ? $k + 1 : $k, $v, $this->getSQLiteType($v));
$start = microtime(true);
$r = $stmt->execute();
$this->log($query, microtime(true) - $start);
return $r;
}
public function exec(string $query): bool
{
$start = microtime(true);
$r = parent::exec($query);
$this->log($query, microtime(true) - $start);
return $r;
}
public function exists(string $table, string $column, mixed $value, bool $case_insensitive = true): bool
{
if ($case_insensitive) {
$query = "SELECT 1 FROM $table WHERE $column = :v COLLATE NOCASE LIMIT 1";
} else {
$query = "SELECT 1 FROM $table WHERE $column = :v LIMIT 1";
}
$result = $this->query($query, [':v' => $value]);
return $result->fetchArray(SQLITE3_NUM) !== false;
}
private function log(string $query, float $time_taken): void
{
$this->count++;
$this->query_time += $time_taken;
$this->log[] = [$query, $time_taken];
}
private function getSQLiteType(mixed $value): int
{
return match (true) {
is_int($value) => SQLITE3_INTEGER,
is_float($value) => SQLITE3_FLOAT,
is_null($value) => SQLITE3_NULL,
default => SQLITE3_TEXT
};
}
}

136
lib.php
View File

@ -1,28 +1,18 @@
<?php // lib.php :: Common functions used throughout the program.
<?php
require_once __DIR__ . '/database.php';
$starttime = getmicrotime();
$numqueries = 0;
$version = "1.1.11";
$build = "";
function opendb() { // Open database connection.
include('config.php');
extract($dbsettings);
$link = mysql_connect($server, $user, $pass) or die(mysql_error());
mysql_select_db($name) or die(mysql_error());
return $link;
}
function doquery($query, $table) { // Something of a tiny little database abstraction layer.
include('config.php');
global $numqueries;
$sqlquery = mysql_query(str_replace("{{table}}", $dbsettings["prefix"] . "_" . $table, $query)) or die(mysql_error());
$numqueries++;
return $sqlquery;
/**
* Open/get SQLite database connection.
*/
function db(): Database
{
return $GLOBALS['database'] ??= new Database(__DIR__ . '/database.db');
}
function gettemplate($templatename) { // SQL query for the template.
@ -83,49 +73,33 @@ function admindisplay($content, $title) { // Finalize page and output to browser
global $numqueries, $userrow, $controlrow, $starttime, $version, $build;
if (!isset($controlrow)) {
$controlquery = doquery("SELECT * FROM {{table}} WHERE id='1' LIMIT 1", "control");
$controlrow = mysql_fetch_array($controlquery);
$query = db()->query('SELECT * FROM control WHERE id=1 LIMIT 1;');
$controlrow = $query->fetchArray(SQLITE3_ASSOC);
}
$template = gettemplate("admin");
// Make page tags for XHTML validation.
$xml = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
. "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\">\n"
. "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
$finalarray = array(
"title"=>$title,
$page = parsetemplate(gettemplate("admin"), [
"title"=>$title,
"content"=>$content,
"totaltime"=>round(getmicrotime() - $starttime, 4),
"numqueries"=>$numqueries,
"version"=>$version,
"build"=>$build);
$page = parsetemplate($template, $finalarray);
$page = $xml . $page;
"build"=>$build
]);
if ($controlrow["compression"] == 1) { ob_start("ob_gzhandler"); }
echo $page;
die();
echo "<html>\n" . $page;
exit;
}
function display($content, $title, $topnav=true, $leftnav=true, $rightnav=true, $badstart=false) { // Finalize page and output to browser.
global $numqueries, $userrow, $controlrow, $version, $build;
if (!isset($controlrow)) {
$controlquery = doquery("SELECT * FROM {{table}} WHERE id='1' LIMIT 1", "control");
$controlrow = mysql_fetch_array($controlquery);
$query = db()->query('SELECT * FROM control WHERE id=1 LIMIT 1;');
$controlrow = $query->fetchArray(SQLITE3_ASSOC);
}
if ($badstart == false) { global $starttime; } else { $starttime = $badstart; }
// Make page tags for XHTML validation.
$xml = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
. "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\">\n"
. "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
$template = gettemplate("primary");
if ($rightnav == true) { $rightnav = gettemplate("rightnav"); } else { $rightnav = ""; }
if ($leftnav == true) { $leftnav = gettemplate("leftnav"); } else { $leftnav = ""; }
if ($topnav == true) {
@ -137,14 +111,14 @@ function display($content, $title, $topnav=true, $leftnav=true, $rightnav=true,
if (isset($userrow)) {
// Get userrow again, in case something has been updated.
$userquery = doquery("SELECT * FROM {{table}} WHERE id='".$userrow["id"]."' LIMIT 1", "users");
$userquery = db()->query('SELECT * FROM users WHERE id = ? LIMIT 1;', [$userrow['id']]);
unset($userrow);
$userrow = mysql_fetch_array($userquery);
$userrow = $userquery->fetchArray(SQLITE3_ASSOC);
// Current town name.
if ($userrow["currentaction"] == "In Town") {
$townquery = doquery("SELECT * FROM {{table}} WHERE latitude='".$userrow["latitude"]."' AND longitude='".$userrow["longitude"]."' LIMIT 1", "towns");
$townrow = mysql_fetch_array($townquery);
$townquery = db()->query('SELECT * FROM towns WHERE latitude = ? AND longitude = ? LIMIT 1;', [$userrow["latitude"], $userrow["longitude"]]);
$townrow = $townquery->fetchArray(SQLITE3_ASSOC);
$userrow["currenttown"] = "Welcome to <b>".$townrow["name"]."</b>.<br /><br />";
} else {
$userrow["currenttown"] = "";
@ -188,10 +162,10 @@ function display($content, $title, $topnav=true, $leftnav=true, $rightnav=true,
if ($userrow["currenthp"] <= ($userrow["maxhp"]/5)) { $userrow["currenthp"] = "<blink><span class=\"highlight\"><b>*".$userrow["currenthp"]."*</b></span></blink>"; }
if ($userrow["currentmp"] <= ($userrow["maxmp"]/5)) { $userrow["currentmp"] = "<blink><span class=\"highlight\"><b>*".$userrow["currentmp"]."*</b></span></blink>"; }
$spellquery = doquery("SELECT id,name,type FROM {{table}}","spells");
$spellquery = db()->query('SELECT id, name, type FROM spells;');
$userspells = explode(",",$userrow["spells"]);
$userrow["magiclist"] = "";
while ($spellrow = mysql_fetch_array($spellquery)) {
foreach ($spellquery->fetchArray(SQLITE3_ASSOC) as $spellrow) {
$spell = false;
foreach($userspells as $a => $b) {
if ($b == $spellrow["id"] && $spellrow["type"] == 1) { $spell = true; }
@ -204,9 +178,9 @@ function display($content, $title, $topnav=true, $leftnav=true, $rightnav=true,
// Travel To list.
$townslist = explode(",",$userrow["towns"]);
$townquery2 = doquery("SELECT * FROM {{table}} ORDER BY id", "towns");
$townquery2 = db()->query('SELECT * FROM towns ORDER BY id;');
$userrow["townslist"] = "";
while ($townrow2 = mysql_fetch_array($townquery2)) {
foreach ($townquery2->fetchArray(SQLITE3_ASSOC) as $townrow2) {
$town = false;
foreach($townslist as $a => $b) {
if ($b == $townrow2["id"]) { $town = true; }
@ -215,29 +189,59 @@ function display($content, $title, $topnav=true, $leftnav=true, $rightnav=true,
$userrow["townslist"] .= "<a href=\"index.php?do=gotown:".$townrow2["id"]."\">".$townrow2["name"]."</a><br />\n";
}
}
} else {
$userrow = array();
$userrow = [];
}
$finalarray = array(
"dkgamename"=>$controlrow["gamename"],
$page = parsetemplate(gettemplate("primary"), [
"dkgamename"=>$controlrow["gamename"],
"title"=>$title,
"content"=>$content,
"rightnav"=>parsetemplate($rightnav,$userrow),
"leftnav"=>parsetemplate($leftnav,$userrow),
"topnav"=>$topnav,
"totaltime"=>round(getmicrotime() - $starttime, 4),
"totaltime"=>round(microtime(true) - $starttime, 4),
"numqueries"=>$numqueries,
"version"=>$version,
"build"=>$build);
$page = parsetemplate($template, $finalarray);
$page = $xml . $page;
if ($controlrow["compression"] == 1) { ob_start("ob_gzhandler"); }
echo $page;
die();
"build"=>$build
]);
echo "<html>\n" . $page;
exit;
}
?>
function checkcookies()
{
$row = false;
if (isset($_COOKIE["dkgame"])) {
// COOKIE FORMAT:
// {ID} {USERNAME} {PASSWORDHASH} {REMEMBERME}
$theuser = explode(" ",$_COOKIE["dkgame"]);
$query = db()->query('SELECT * FROM users WHERE id = ?, username = ?, password = ? LIMIT 1;', [$theuser[0], $theuser[1], $theuser[2]]);
if ($query === false) {
set_cookie('dkgame', '', -3600);
die("Invalid cookie data. Please log in again.");
}
$row = $query->fetchArray(SQLITE3_ASSOC);
set_cookie('dkgame', implode(" ", $theuser), (int) $theuser[3] === 1 ? time() + 31536000 : 0);
db()->exec('UPDATE users SET onlinetime = CURRENT_TIMESTAMP WHERE id = ? LIMIT 1;', [$theuser[0]]);
}
return $row;
}
/**
* Set a cookie with secure and HTTP-only flags.
*/
function set_cookie($name, $value, $expires)
{
setcookie($name, $value, [
'expires' => $expires,
'path' => '/',
'domain' => '', // Defaults to the current domain
'secure' => true, // Ensure the cookie is only sent over HTTPS
'httponly' => true, // Prevent access to cookie via JavaScript
'samesite' => 'Strict' // Enforce SameSite=Strict
]);
}

File diff suppressed because it is too large Load Diff