Remove a bunch of trailing whitespace.

This commit is contained in:
Greg Sarjeant 2025-06-17 22:08:50 -04:00
parent 93bfe14d4f
commit a3a6471ced
29 changed files with 131 additions and 131 deletions

View File

@ -39,7 +39,7 @@ RewriteCond %{REQUEST_URI} !^/css/custom/
RewriteRule ^css/tkr\.css$ public/css/tkr.css [L]
# 404 all other static files (images, js, fonts, etc.)
# so those requests don't hit the PHP app
# so those requests don't hit the PHP app
# (this is to reduce load on the PHP app from bots and scanners)
RewriteRule \.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$ - [R=404,L]

View File

@ -19,7 +19,7 @@ A lightweight, HTML-only status feed for self-hosted personal websites. Written
* PHP 8.2+ with the PDO and PDO_SQLITE extensions
* The PDO and PDO_SQLITE extensions are usually included by default
* This might work with earlier PHP versions, but I've only tested 8.2
## Installation
1. Download the latest tkr archive from https://subcultureofone.org/files/tkr/tkr.0.6.0.zip

View File

@ -18,12 +18,12 @@ define('DB_FILE', DATA_DIR . '/tkr.sqlite');
// Define an exception for validation errors
class SetupException extends Exception {
private $setupIssue;
public function __construct(string $message, string $setupIssue = '', int $code = 0, Throwable $previous = null) {
parent::__construct($message, $code, $previous);
$this->setupIssue = $setupIssue;
}
public function getSetupIssue(): string {
return $this->setupIssue;
}

View File

@ -39,7 +39,7 @@ RewriteCond %{REQUEST_URI} !^/css/custom/
RewriteRule ^css/tkr\.css$ public/css/tkr.css [L]
# 404 all other static files (images, js, fonts, etc.)
# so those requests don't hit the PHP app
# so those requests don't hit the PHP app
# (this is to reduce load on the PHP app from bots and scanners)
RewriteRule \.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$ - [R=404,L]

View File

@ -9,13 +9,13 @@
# Replace localhost with your subdomain, e.g. tkr.my-domain.com
ServerName localhost
DocumentRoot /var/www/tkr/public
# Security headers
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# Block access to sensitive directories
<Directory "/var/www/tkr/storage">
Require all denied
@ -44,7 +44,7 @@
Alias /css/tkr.css /var/www/tkr/public/css/tkr.css
# 404 all non-css static files (images, js, fonts, etc.)
# so those requests don't hit the PHP app
# so those requests don't hit the PHP app
# (this is to reduce load on the PHP app from bots and scanners)
<LocationMatch "\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$">
<RequireAll>
@ -69,7 +69,7 @@
RewriteCond %{REQUEST_URI} !^/css/custom/
RewriteRule ^css/tkr\.css$ css/tkr.css [L]
# Everything else to front controller
# Everything else to front controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L]

View File

@ -24,13 +24,13 @@
# Replace with the actual paths to your cert and key
SSLCertificateFile /etc/letsencrypt/live/tkr.my-domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/tkr.my-domain.com/privkey.pem
# Security headers
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# Block access to sensitive directories
<Directory "/var/www/tkr/storage">
Require all denied
@ -59,7 +59,7 @@
Alias /css/tkr.css /var/www/tkr/public/css/tkr.css
# 404 all non-css static files (images, js, fonts, etc.)
# so those requests don't hit the PHP app
# so those requests don't hit the PHP app
# (this is to reduce load on the PHP app from bots and scanners)
<LocationMatch "\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$">
<RequireAll>
@ -84,7 +84,7 @@
RewriteCond %{REQUEST_URI} !^/css/custom/
RewriteRule ^css/tkr\.css$ css/tkr.css [L]
# Everything else to front controller
# Everything else to front controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L]

View File

@ -9,18 +9,18 @@
# Replace localhost with your subdomain, e.g. tkr.my-domain.com
ServerName localhost
DocumentRoot /var/www/html
# Security headers
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# tkr Application at /tkr
# NOTE: If you change the directory name,
# remember to update all instances of /var/www/tkr in this file to match
# remember to update all instances of /var/www/tkr in this file to match
Alias /tkr /var/www/tkr/public
# Block access to sensitive TKR directories
<Directory "/var/www/tkr/storage">
Require all denied
@ -34,28 +34,28 @@
<Directory "/var/www/tkr/config">
Require all denied
</Directory>
# 404 all non-css static files in /tkr (images, js, fonts, etc.)
# so those requests don't hit the PHP app
# so those requests don't hit the PHP app
# (this is to reduce load on the PHP app from bots and scanners)
<LocationMatch "^/tkr/.*\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$">
<RequireAll>
Require all denied
</RequireAll>
</LocationMatch>
# tkr application directory
<Directory "/var/www/tkr/public">
Options -Indexes
AllowOverride None
Require all granted
RewriteEngine On
# Block direct PHP access
RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC]
RewriteRule ^.*$ - [R=404,L]
# Serve the one static file that exists: css/tkr.css
# (Pass requests to css/custom/ through to the PHP app)
RewriteCond %{REQUEST_URI} !^/tkr/css/custom/
@ -66,7 +66,7 @@
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L]
</Directory>
# Error and access logs
ErrorLog ${APACHE_LOG_DIR}/my-domain_error.log
CustomLog ${APACHE_LOG_DIR}/my-domain_access.log combined

View File

@ -17,7 +17,7 @@
# Replace localhost with your subdomain, e.g. tkr.my-domain.com
ServerName localhost
DocumentRoot /var/www/html
# SSL Configuration
SSLEngine on
@ -25,18 +25,18 @@
# Replace with the actual paths to your cert and key
SSLCertificateFile /etc/letsencrypt/live/my-domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/my-domain.com/privkey.pem
# Security headers
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# tkr Application at /tkr
# NOTE: If you change the directory name,
# remember to update all instances of /var/www/tkr in this file to match
# remember to update all instances of /var/www/tkr in this file to match
Alias /tkr /var/www/tkr/public
# Block access to sensitive TKR directories
<Directory "/var/www/tkr/storage">
Require all denied
@ -50,28 +50,28 @@
<Directory "/var/www/tkr/config">
Require all denied
</Directory>
# 404 all non-css static files in /tkr (images, js, fonts, etc.)
# so those requests don't hit the PHP app
# so those requests don't hit the PHP app
# (this is to reduce load on the PHP app from bots and scanners)
<LocationMatch "^/tkr/.*\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$">
<RequireAll>
Require all denied
</RequireAll>
</LocationMatch>
# tkr application directory
<Directory "/var/www/tkr/public">
Options -Indexes
AllowOverride None
Require all granted
RewriteEngine On
# Block direct PHP access
RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC]
RewriteRule ^.*$ - [R=404,L]
# Serve the one static file that exists: css/tkr.css
# (Pass requests to css/custom/ through to the PHP app)
RewriteCond %{REQUEST_URI} !^/tkr/css/custom/
@ -82,7 +82,7 @@
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L]
</Directory>
# Error and access logs
ErrorLog ${APACHE_LOG_DIR}/my-domain_error.log
CustomLog ${APACHE_LOG_DIR}/my-domain_access.log combined

View File

@ -10,7 +10,7 @@ server {
# replace localhost with your subdomain
# e.g. tkr.my-domain.com
server_name localhost;
root /var/www/tkr/public;
index index.php;
@ -63,7 +63,7 @@ server {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php;
include fastcgi_params;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param QUERY_STRING $query_string;
@ -73,7 +73,7 @@ server {
# (these are bots and scanners)
location ~ ^/.+\.php$ {
return 404;
}
}
# forward other requests to the fallback block,
# which sends them to php-fpm for handling
@ -88,7 +88,7 @@ server {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php;
include fastcgi_params;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param QUERY_STRING $query_string;

View File

@ -17,7 +17,7 @@ server {
# Replace with the actual paths to your cert and key
ssl_certificate /etc/letsencrypt/live/tkr.my-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tkr.my-domain.com/privkey.pem;
root /var/www/tkr/public;
index index.php;
@ -61,7 +61,7 @@ server {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php;
include fastcgi_params;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param QUERY_STRING $query_string;
@ -71,7 +71,7 @@ server {
# (these are bots and scanners)
location ~ ^/.+\.php$ {
return 404;
}
}
# forward other requests to the fallback block,
# which sends them to php-fpm for handling
@ -86,7 +86,7 @@ server {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php;
include fastcgi_params;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param QUERY_STRING $query_string;

View File

@ -12,7 +12,7 @@ server {
# replace localhost with your subdomain
# e.g. tkr.my-domain.com
server_name localhost;
root /var/www/html;
index index.html;
@ -65,7 +65,7 @@ server {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php;
include fastcgi_params;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param QUERY_STRING $query_string;
@ -75,7 +75,7 @@ server {
# (these are bots and scanners)
location ~ ^/tkr/.+\.php$ {
return 404;
}
}
# forward other requests to the fallback block,
# which sends them to php-fpm for handling
@ -87,7 +87,7 @@ server {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php;
include fastcgi_params;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param QUERY_STRING $query_string;

View File

@ -8,11 +8,11 @@
server {
listen 443 ssl;
listen [::]:443 ssl;
# Replace localhost with your domain
# e.g. my-domain.com
server_name localhost;
root /var/www/html;
index index.html;
@ -56,7 +56,7 @@ server {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php;
include fastcgi_params;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param QUERY_STRING $query_string;
@ -66,7 +66,7 @@ server {
# (these are bots and scanners)
location ~ ^/tkr/.+\.php$ {
return 404;
}
}
# forward other requests to the fallback block,
# which sends them to php-fpm for handling
@ -78,7 +78,7 @@ server {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php;
include fastcgi_params;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param QUERY_STRING $query_string;

View File

@ -8,7 +8,7 @@
--color-primary-light: #bae6fd;
--color-primary-lighter: #ebf8ff;
--color-primary-lightest: #f0f9ff;
/* Text colors */
--color-text-primary: #374151;
--color-text-secondary: #1e40af;
@ -16,25 +16,25 @@
--color-text-muted: gray;
--color-text-black: black;
--color-text-dark: #333;
/* Background colors */
--color-bg-body: whitesmoke;
--color-bg-white: white;
--color-bg-light: #fefefe;
--color-bg-file: #f8fafc;
/* Border colors */
--color-border-light: #e5e7eb;
--color-border-medium: #d1d5db;
--color-border-file: #cbd5e0;
/* State colors */
--color-required: #dc2626;
--color-hover-light: #dbeafe;
--color-hover-medium: #bfdbfe;
--color-emoji-bg: #ddeeff;
--color-emoji-border: #339;
/* Shadow colors */
--shadow-primary: rgba(66, 153, 225, 0.1);
--shadow-primary-strong: rgba(66, 153, 225, 0.3);
@ -108,9 +108,9 @@ h1.site-description {
width: auto;
}
input[type="text"],
input[type="number"],
input[type="password"],
input[type="text"],
input[type="number"],
input[type="password"],
textarea,
select {
width: 100%;
@ -124,9 +124,9 @@ select {
box-sizing: border-box;
}
input[type="text"]:focus,
input[type="number"]:focus,
input[type="password"]:focus,
input[type="text"]:focus,
input[type="number"]:focus,
input[type="password"]:focus,
textarea:focus,
select:focus {
outline: none;
@ -205,14 +205,14 @@ label.description {
.navbar {
overflow: visible;
background: var(--color-bg-white);
background: var(--color-bg-white);
display: flex;
align-items: center;
}
.navbar a {
font-size: 16px;
color: var(--color-text-secondary);
color: var(--color-text-secondary);
text-align: center;
padding: 14px 16px;
text-decoration: none;
@ -229,9 +229,9 @@ label.description {
box-shadow: 0 0 0 2px var(--shadow-primary);
}
/*
/*
Using details/summary tags to build dropdowm nmenus.
They have to be clicked open and closed, but they allow
They have to be clicked open and closed, but they allow
me to have semantically appropriate pure HTML dropdowms
that work on mobile devices.
*/
@ -241,7 +241,7 @@ label.description {
}
.dropdown summary.dropbtn {
font-size: 16px;
font-size: 16px;
border: none;
border-radius: 0px;
outline: none;
@ -424,13 +424,13 @@ label.description {
/* Styling for flash messages */
.flash-messages {
background: var(--color-bg-white);
background: var(--color-bg-white);
margin-top: 10px;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 10px var(--shadow-primary);
}
.flash-message {
padding: 12px 16px;
margin: 5px 0;
@ -462,7 +462,7 @@ label.description {
border-left-color: var(--color-flash-info-border-left);
color: var(--color-flash-info);
}
.fieldset-items {
margin-bottom: 14px;
display: grid;
@ -532,7 +532,7 @@ label.description {
}
.tick-time {
color: var(--color-text-muted);
color: var(--color-text-muted);
font-size: 0.8em;
margin-bottom: 0.4em;
}
@ -543,9 +543,9 @@ label.description {
display: block;
}
.tick-pagination a {
margin: 0 5px;
text-decoration: none;
.tick-pagination a {
margin: 0 5px;
text-decoration: none;
}
.emoji-option input {
@ -616,7 +616,7 @@ label.description {
box-shadow: 0 0 0 2px var(--shadow-primary);
}
/*
/*
Responsive layout - adjusts from 1 to 2 columns based on screen width
- min-width makes the mobile (stacked) view the default
- 600px covers most mobile devices in portrait mode
@ -633,7 +633,7 @@ label.description {
padding-top: 10px;
margin-bottom: 0;
}
.home-container {
grid-template-columns: 1fr 2fr;
grid-gap: 2em;
@ -646,7 +646,7 @@ label.description {
gap: 16px;
align-items: start;
}
.file-info {
grid-column: 2;
}
@ -654,7 +654,7 @@ label.description {
.navbar {
flex-wrap: wrap;
}
.dropdown-menu {
position: fixed;
left: 1em;

View File

@ -51,13 +51,13 @@ class AdminController extends Controller {
// handle form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$errors = [];
// UserModel profile
$username = trim($_POST['username'] ?? '');
$displayName = trim($_POST['display_name'] ?? '');
$about = trim($_POST['about'] ?? '');
$website = trim($_POST['website'] ?? '');
// Site settings
$siteTitle = trim($_POST['site_title']) ?? '';
$siteDescription = trim($_POST['site_description']) ?? '';
@ -68,7 +68,7 @@ class AdminController extends Controller {
// Password
$password = $_POST['password'] ?? '';
$confirmPassword = $_POST['confirm_password'] ?? '';
// Validate user profile
if (!$username) {
$errors[] = "Username is required.";
@ -87,7 +87,7 @@ class AdminController extends Controller {
$errors[] = "URL must start with http:// or https://.";
}
}
// Validate site settings
if (!$siteTitle) {
$errors[] = "Site title is required.";
@ -98,12 +98,12 @@ class AdminController extends Controller {
if ($itemsPerPage < 1 || $itemsPerPage > 50) {
$errors[] = "Items per page must be a number between 1 and 50.";
}
// If a password was sent, make sure it matches the confirmation
if ($password && !($password === $confirmPassword)){
$errors[] = "Passwords do not match";
}
// Validation complete
if (empty($errors)) {
// Update site settings
@ -112,21 +112,21 @@ class AdminController extends Controller {
$config->baseUrl = $baseUrl;
$config->basePath = $basePath;
$config->itemsPerPage = $itemsPerPage;
// Save site settings and reload config from database
// TODO - raise and handle exception on failure
$config = $config->save();
// Update user profile
$user->username = $username;
$user->displayName = $displayName;
$user->about = $about;
$user->website = $website;
// Save user profile and reload user from database
// TODO - raise and handle exception on failure
$user = $user->save();
// Update the password if one was sent
// TODO - raise and handle exception on failure
if($password){

View File

@ -19,13 +19,13 @@ class AuthController extends Controller {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
// TODO: move into user model
global $db;
$stmt = $db->prepare("SELECT id, username, password_hash FROM user WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password_hash'])) {
session_regenerate_id(true);
// TODO: move into session.php

View File

@ -24,5 +24,5 @@ class Controller {
extract($vars, EXTR_SKIP);
include $templatePath;
}
}
}

View File

@ -76,7 +76,7 @@ class CssController extends Controller {
http_response_code(400);
exit("Cannot delete default theme");
}
// Get the data for the selected CSS file
$cssId = $_POST['selectCssFile'];
$cssModel = new CssModel();
@ -87,7 +87,7 @@ class CssController extends Controller {
http_response_code(400);
exit("No entry found for css id $cssId");
}
// get the filename
$cssFilename = $cssRow["filename"];
@ -151,7 +151,7 @@ class CssController extends Controller {
// Validate file extension
$filename = $file['name'];
$fileExtension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if ($fileExtension !== 'css') {
throw new Exception('File must have a .css extension');
}
@ -186,7 +186,7 @@ class CssController extends Controller {
// Add upload to database
$cssModel = new CssModel();
$cssModel->save($safeFilename, $description);
// Set success flash message
Session::setFlashMessage('success', 'Theme uploaded as ' . $safeFilename);
@ -200,11 +200,11 @@ class CssController extends Controller {
private function validateCssContent($content) {
// Remove comments
$content = preg_replace('/\/\*.*?\*\//s', '', $content);
// Basic CSS validation - check for balanced braces
$openBraces = substr_count($content, '{');
$closeBraces = substr_count($content, '}');
if ($openBraces !== $closeBraces) {
throw new Exception('Invalid CSS: Unbalanced braces detected');
}
@ -261,7 +261,7 @@ class CssController extends Controller {
// Remove path information and dangerous characters
$fileName = basename($originalName);
$fileName = preg_replace('/[^a-zA-Z0-9._-]/', '_', $fileName);
return $fileName;
}

View File

@ -11,7 +11,7 @@
'config' => $config,
'moodPicker' => $moodPicker,
];
$this->render("mood.php", $vars);
}
@ -33,7 +33,7 @@
// set or clear the mood
$user->mood = $mood;
$user = $user->save();
// go back to the index and show the updated mood
header('Location: ' . $config->basePath);
exit;

View File

@ -4,7 +4,7 @@ class TickController extends Controller{
// every tick is identified by its timestamp
public function index(string $year, string $month, string $day, string $hour, string $minute, string $second){
$model = new TickModel();
$tick = $model->get($year, $month, $day, $hour, $minute, $second);
$tick = $model->get($year, $month, $day, $hour, $minute, $second);
$this->render('tick.php', $tick);
}
}

View File

@ -24,7 +24,7 @@ class Util {
},
$text
);
}
}
// For relative time display, compare the stored time to the current time
// and display it as "X seconds/minutes/hours/days etc." ago
@ -59,6 +59,6 @@ class Util {
[$year, $month, $day] = $dateParts;
[$hour, $minute, $second] = $timeParts;
return "$year/$month/$day/$hour/$minute/$second";
return "$year/$month/$day/$hour/$minute/$second";
}
}

View File

@ -36,11 +36,11 @@ class ConfigModel {
if (empty($this->cssId)) {
return null;
}
// Fetch filename from css table using cssId
$cssModel = new CssModel();
$cssRecord = $cssModel->getById($this->cssId);
return $cssRecord ? $cssRecord['filename'] : null;
}

View File

@ -20,7 +20,7 @@ class TickModel {
// split the path to the current file into the date components
$pathParts = explode('/', str_replace('\\', '/', $file));
// assign the different components to the appropriate part of the date
// assign the different components to the appropriate part of the date
$year = $pathParts[count($pathParts) - 3];
$month = $pathParts[count($pathParts) - 2];
$day = pathinfo($pathParts[count($pathParts) - 1], PATHINFO_FILENAME);
@ -75,18 +75,18 @@ class TickModel {
$content = $time . "|" . $tick . "\n";
file_put_contents($filename, $content, FILE_APPEND);
}
public static function get(string $y, string $m, string $d, string $H, string $i, string $s): array{
$tickTime = new DateTime("$y-$m-$d $H:$i:$s");
$timestamp = "$H:$i:$s";
$file = TICKS_DIR . "/$y/$m/$d.txt";
if (!file_exists($file)) {
http_response_code(404);
echo "Tick not found: $file.";
exit;
}
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (str_starts_with($line, $timestamp)) {

View File

@ -46,7 +46,7 @@ class UserModel {
// loading the password into memory
public function set_password(string $password): void {
global $db;
$hash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $db->prepare("UPDATE user SET password_hash=? WHERE id=1");
$stmt->execute([$hash]);

View File

@ -12,7 +12,7 @@ echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
<channel>
<title><?php echo Util::escape_xml($config->siteTitle . 'RSS Feed') ?></title>
<link><?php echo Util::escape_xml($config->baseUrl . $config->basePath)?></link>
<atom:link href="<?php echo Util::escape_xml($config->baseUrl . $config->basePath. 'feed/rss')?>"
<atom:link href="<?php echo Util::escape_xml($config->baseUrl . $config->basePath. 'feed/rss')?>"
rel="self"
type="application/rss+xml" />
<description><?php echo Util::escape_xml($config->siteDescription) ?></description>

View File

@ -18,11 +18,11 @@
<link rel="alternate"
type="application/rss+xml"
title="<?php echo Util::escape_html($config->siteTitle) ?> RSS Feed"
href="<?php echo Util::escape_html($config->baseUrl . $config->basePath)?>feed/rss/">
href="<?php echo Util::escape_html($config->baseUrl . $config->basePath)?>feed/rss/">
<link rel="alternate"
type="application/atom+xml"
title="<?php echo Util::escape_html($config->siteTitle) ?> Atom Feed"
href="<?php echo Util::escape_html($config->baseUrl . $config->basePath)?>feed/atom/">
href="<?php echo Util::escape_html($config->baseUrl . $config->basePath)?>feed/atom/">
</head>
<body>
<?php include TEMPLATES_DIR . '/partials/navbar.php'?>

View File

@ -4,7 +4,7 @@
<h1><?php if ($isSetup): ?>Setup<?php else: ?>Admin<?php endif; ?></h1>
<div>
<form
action="<?php echo $config->basePath . ($isSetup ? 'setup' : 'admin') ?>"
action="<?php echo $config->basePath . ($isSetup ? 'setup' : 'admin') ?>"
method="post">
<input type="hidden" name="csrf_token" value="<?= Util::escape_html($_SESSION['csrf_token']) ?>">
<fieldset>
@ -16,7 +16,7 @@
value="<?= Util::escape_html($user->username) ?>"
required>
<label>Display name <span class=required>*</span></label>
<input type="text"
<input type="text"
name="display_name"
value="<?= Util::escape_html($user->displayName) ?>"
required>
@ -36,7 +36,7 @@
<label>Title <span class=required>*</span></label>
<input type="text"
name="site_title"
value="<?= Util::escape_html($config->siteTitle) ?>"
value="<?= Util::escape_html($config->siteTitle) ?>"
required>
<label>Description <span class=required>*</span></label>
<input type="text"
@ -47,7 +47,7 @@
name="base_url"
value="<?= Util::escape_html($config->baseUrl) ?>"
required>
<label>Base path <span class=required>*</span></label>
<label>Base path <span class=required>*</span></label>
<input type="text"
name="base_path"
value="<?= Util::escape_html($config->basePath) ?>"
@ -62,7 +62,7 @@
<fieldset>
<legend>Change password</legend>
<div class="fieldset-items">
<label>New password
<label>New password
<?php if($isSetup): ?><span class=required>*</span><?php endif; ?>
</label>
<input type="password"

View File

@ -11,14 +11,14 @@
<select id="selectCssFile" name="selectCssFile" value=<?= $config->cssId ?>>
<option value="">Default</option>
<?php foreach ($customCss as $cssFile): ?>
<?php
<?php
if ($cssFile['id'] == $config->cssId){
$cssDescription = $cssFile['description'];
$selected = "selected";
}
?>
<option value=<?= $cssFile['id'] ?>
<option value=<?= $cssFile['id'] ?>
<?= isset($selected) ? $selected : ""?>>
<?=Util::escape_html($cssFile['filename'])?>
</option>
@ -40,9 +40,9 @@
<div class="fieldset-items">
<input type="hidden" name="csrf_token" value="<?= Util::escape_html($_SESSION['csrf_token']) ?>">
<label for="uploadCssFile">Select File to Upload</label>
<input type="file"
id="uploadCssFile"
name="uploadCssFile"
<input type="file"
id="uploadCssFile"
name="uploadCssFile"
accept=".css">
<div class="file-info">
<strong>File Requirements:</strong><br>
@ -51,8 +51,8 @@
Will be scanned for malicious content
</div>
<label for="description">Description (optional)</label>
<textarea id="description"
name="description"
<textarea id="description"
name="description"
placeholder="Describe this CSS file..."></textarea>
<div></div>
<button type="submit" name="action" value="upload">Upload CSS File</button>

View File

@ -31,9 +31,9 @@
<div class="fieldset-items">
<?php foreach ($emojiList as $emojiItem): ?>
<div class="emoji-checkbox-item">
<input type="checkbox"
id="delete_emoji_<?= Util::escape_html($emojiItem['id']) ?>"
name="delete_emoji_ids[]"
<input type="checkbox"
id="delete_emoji_<?= Util::escape_html($emojiItem['id']) ?>"
name="delete_emoji_ids[]"
value="<?= Util::escape_html($emojiItem['id']) ?>">
<label for="delete_emoji_<?= Util::escape_html($emojiItem['id']) ?>">
<span class="emoji-display"><?= Util::escape_html($emojiItem['emoji']) ?></span>

View File

@ -34,7 +34,7 @@
<input type="hidden" name="csrf_token" value="<?= Util::escape_html($_SESSION['csrf_token']) ?>">
<textarea name="tick"
placeholder="What's ticking?"
minlength="1"
minlength="1"
maxlength="200"
rows="3"></textarea>
<button type="submit" class="submit-btn">Tick</button>