From 5ad15a478de70c92012e08d4b52ed38b9b424497 Mon Sep 17 00:00:00 2001 From: Greg Sarjeant <1686767+gsarjeant@users.noreply.github.com> Date: Tue, 27 May 2025 19:58:49 -0400 Subject: [PATCH] Add setup.php. Add lib dir. Move functions to lib dir. --- tkr/bootstrap.php | 83 +++++++++++++++++++++++++ tkr/config.php | 12 ---- tkr/create_db.php | 56 ----------------- tkr/lib/config.php | 25 ++++++++ tkr/{ => lib}/session.php | 0 tkr/{stream_ticks.php => lib/ticks.php} | 45 ++++++++++++-- tkr/public/index.php | 54 ++++++++-------- tkr/public/login.php | 15 +++-- tkr/public/logout.php | 9 +-- tkr/public/save_tick.php | 40 ++++-------- tkr/public/setup.php | 72 +++++++++++++++++++++ tkr/{db => storage}/.gitkeep | 0 tkr/ticks/.gitkeep | 0 13 files changed, 277 insertions(+), 134 deletions(-) create mode 100644 tkr/bootstrap.php delete mode 100644 tkr/config.php delete mode 100644 tkr/create_db.php create mode 100644 tkr/lib/config.php rename tkr/{ => lib}/session.php (100%) rename tkr/{stream_ticks.php => lib/ticks.php} (52%) create mode 100644 tkr/public/setup.php rename tkr/{db => storage}/.gitkeep (100%) delete mode 100644 tkr/ticks/.gitkeep diff --git a/tkr/bootstrap.php b/tkr/bootstrap.php new file mode 100644 index 0000000..454de86 --- /dev/null +++ b/tkr/bootstrap.php @@ -0,0 +1,83 @@ +exec("CREATE TABLE IF NOT EXISTS user ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL, + display_name TEXT NOT NULL, + password_hash TEXT NOT NULL + )"); + + $db->exec("CREATE TABLE IF NOT EXISTS settings ( + id INTEGER PRIMARY KEY, + site_title TEXT NOT NULL, + site_description TEXT NULL, + base_path TEXT NOT NULL, + items_per_page INTEGER NOT NULL + )"); + + // See if there's any data in the tables + $user_count = (int) $db->query("SELECT COUNT(*) FROM user")->fetchColumn(); + $settings_count = (int) $db->query("SELECT COUNT(*) FROM settings")->fetchColumn(); + + // If either table has no records and we aren't on setup.php, redirect to setup.php + if ($user_count === 0 || $settings_count === 0){ + if (basename($_SERVER['PHP_SELF']) !== 'setup.php'){ + header('Location: setup.php'); + exit; + } + } else { + // If setup is complete and we are on setup.php, redirect to index.php. + if (basename($_SERVER['PHP_SELF']) === 'setup.php'){ + header('Location: index.php'); + exit; + } + }; +} + +function get_db(): PDO { + verify_data_dir(DATA_DIR, true); + + try { + $db = new PDO("sqlite:" . DB_FILE); + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); + } catch (PDOException $e) { + die("Database connection failed: " . $e->getMessage()); + } + + return $db; +} diff --git a/tkr/config.php b/tkr/config.php deleted file mode 100644 index ff8df93..0000000 --- a/tkr/config.php +++ /dev/null @@ -1,12 +0,0 @@ -setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); -} catch (PDOException $e) { - die("Database connection failed: " . $e->getMessage()); -} diff --git a/tkr/create_db.php b/tkr/create_db.php deleted file mode 100644 index d9569f6..0000000 --- a/tkr/create_db.php +++ /dev/null @@ -1,56 +0,0 @@ -setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); -} catch (PDOException $e) { - die("Could not connect to DB: " . $e->getMessage() . "\n"); -} - -$pdo->exec("CREATE TABLE IF NOT EXISTS user ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT UNIQUE NOT NULL, - password_hash TEXT NOT NULL -)"); - -$username = prompt("Enter username: "); -$password = promptSilent("Enter password: "); -$confirm = promptSilent("Confirm password: "); - -if ($password !== $confirm) { - die("Error: Passwords do not match.\n"); -} - -$passwordHash = password_hash($password, PASSWORD_DEFAULT); - -try { - $stmt = $pdo->prepare("INSERT INTO user(username, password_hash) VALUES (?, ?)"); - $stmt->execute([$username, $passwordHash]); - echo "User '$username' created successfully.\n"; -} catch (PDOException $e) { - echo "Failed to create user: " . $e->getMessage() . "\n"; -} diff --git a/tkr/lib/config.php b/tkr/lib/config.php new file mode 100644 index 0000000..012c885 --- /dev/null +++ b/tkr/lib/config.php @@ -0,0 +1,25 @@ +query("SELECT site_title, site_description, base_path, items_per_page FROM settings WHERE id=1"); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $c = new self(); + if ($row) { + $c->siteTitle = $row['site_title']; + $c->siteDescription = $row['site_description']; + $c->basePath = $row['base_path']; + $c->itemsPerPage = (int) $row['items_per_page']; + } + return $c; + } +} \ No newline at end of file diff --git a/tkr/session.php b/tkr/lib/session.php similarity index 100% rename from tkr/session.php rename to tkr/lib/session.php diff --git a/tkr/stream_ticks.php b/tkr/lib/ticks.php similarity index 52% rename from tkr/stream_ticks.php rename to tkr/lib/ticks.php index 2a3f525..d7b8886 100644 --- a/tkr/stream_ticks.php +++ b/tkr/lib/ticks.php @@ -1,8 +1,45 @@ "\'()]+)~i', + fn($matches) => '' . $matches[1] . '', + $safe + ); + + return $safe; +} + +function save_tick(string $tick): void { + // build the tick path and filename from the current time + $date = new DateTime(); + + $year = $date->format('Y'); + $month = $date->format('m'); + $day = $date->format('d'); + $time = $date->format('H:i:s'); + + // build the full path to the tick file + $dir = TICKS_DIR . "/$year/$month"; + $filename = "$dir/$day.txt"; + + // create the directory if it doesn't exist + if (!is_dir($dir)) { + mkdir($dir, 0770, true); + } + + // write the tick to the file (the file will be created if it doesn't exist) + $content = $time . "|" . $tick . "\n"; + file_put_contents($filename, $content, FILE_APPEND); +} + +function stream_ticks(int $limit, int $offset = 0): Generator { + $tick_files = glob(TICKS_DIR . '/*/*/*.txt'); usort($tick_files, fn($a, $b) => strcmp($b, $a)); // sort filenames in reverse chronological order $count = 0; diff --git a/tkr/public/index.php b/tkr/public/index.php index f3858fe..26379f2 100644 --- a/tkr/public/index.php +++ b/tkr/public/index.php @@ -1,21 +1,24 @@ itemsPerPage; $offset = ($page - 1) * $limit; -$ticks = iterator_to_array(stream_ticks($tickLocation, $limit, $offset)); +$ticks = iterator_to_array(stream_ticks($limit, $offset)); ?> - My ticker + <?= $config->siteTitle ?> -

Welcome! Here's what's ticking.

+

siteDescription ?>

- - + +
- +
-

Login

+

Login

-
- - - - - -
-

Logout

+
+ + + + + +
+

Logout

+
diff --git a/tkr/public/login.php b/tkr/public/login.php index c3c4d25..0f6ddd4 100644 --- a/tkr/public/login.php +++ b/tkr/public/login.php @@ -1,8 +1,10 @@ prepare("SELECT id, username, password_hash FROM user WHERE username = ?"); + $db = get_db(); + $stmt = $db->prepare("SELECT id, username, password_hash FROM user WHERE username = ?"); $stmt->execute([$username]); $user = $stmt->fetch(); @@ -22,7 +25,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { session_regenerate_id(true); $_SESSION['user_id'] = $user['id']; $_SESSION['username'] = $user['username']; - header('Location: ' . $basePath . '/'); + header('Location: ' . $config->basePath); exit; } else { $error = 'Invalid username or password'; @@ -40,7 +43,7 @@ $csrf_token = generateCsrfToken();

-
+

diff --git a/tkr/public/logout.php b/tkr/public/logout.php index 1ffad8e..474f8dc 100644 --- a/tkr/public/logout.php +++ b/tkr/public/logout.php @@ -1,11 +1,12 @@ basePath); exit; \ No newline at end of file diff --git a/tkr/public/save_tick.php b/tkr/public/save_tick.php index d25bb67..9e718e3 100644 --- a/tkr/public/save_tick.php +++ b/tkr/public/save_tick.php @@ -1,44 +1,30 @@ format('Y'); -$month = $date->format('m'); -$day = $date->format('d'); -$time = $date->format('H:i:s'); - -// build the full path to the tick file -$dir = "$tickLocation/$year/$month"; -$filename = "$dir/$day.txt"; - -// create the directory if it doesn't exist -if (!is_dir($dir)) { - mkdir($dir, 0770, true); -} - -// write the tick to the file (the file will be created if it doesn't exist) -$content = $time . "|" . $tick . "\n"; -file_put_contents($filename, $content, FILE_APPEND); +// save the tick +save_tick($_POST['tick']); // go back to the index and show the latest tick -header('Location: index.php'); +header('Location: ' . $config->basePath); exit; \ No newline at end of file diff --git a/tkr/public/setup.php b/tkr/public/setup.php new file mode 100644 index 0000000..479f91b --- /dev/null +++ b/tkr/public/setup.php @@ -0,0 +1,72 @@ +:"|\\*]*$#', $base_path)) { + $errors[] = "Base path must look like a valid URL path (e.g. / or /tkr/)."; + } + if ($items_per_page < 1 || $items_per_page > 50) { + $errors[] = "Items per page must be a number between 1 and 50."; + } + + if (empty($errors)) { + $hash = password_hash($password, PASSWORD_DEFAULT); + + $stmt = $db->prepare("INSERT INTO user (username, display_name, password_hash) VALUES (?, ?, ?)"); + $stmt->execute([$username, $display_name, $hash]); + + $stmt = $db->prepare("INSERT INTO settings (id, site_title, site_description, base_path, items_per_page) VALUES (1, ?, ?, ?, ?)"); + $stmt->execute([$site_title, $site_description, $base_path, $items_per_page]); + + header("Location: index.php"); + exit; + } +} + +?> + +

Let’s Set Up Your tkr

+ +

User settings

+
+
+
+

+

Site settings

+
+
+
+
+
+ +
diff --git a/tkr/db/.gitkeep b/tkr/storage/.gitkeep similarity index 100% rename from tkr/db/.gitkeep rename to tkr/storage/.gitkeep diff --git a/tkr/ticks/.gitkeep b/tkr/ticks/.gitkeep deleted file mode 100644 index e69de29..0000000