Rewrite lib and install to use new database and have better syntax
This commit is contained in:
parent
743c3cd6c4
commit
ce06aecf84
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
.installed
|
||||
database.db
|
11
config.php
11
config.php
|
@ -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.
|
||||
|
||||
?>
|
32
cookies.php
32
cookies.php
|
@ -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
71
database.php
Normal 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
|
||||
};
|
||||
}
|
||||
}
|
132
lib.php
132
lib.php
|
@ -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(
|
||||
$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(
|
||||
$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
|
||||
]);
|
||||
}
|
||||
|
|
1385
public/install.php
1385
public/install.php
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user