Compare commits

..

2 Commits

Author SHA1 Message Date
ecb5c59eb7 Major changes, see source 2025-08-05 08:20:13 -06:00
eafc2588dc Forking from BootstrapSQLiteBlog 2025-07-24 08:37:22 -06:00
33 changed files with 3112 additions and 1 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
* text=auto

View File

@ -1,2 +1,3 @@
# PlainSQLiteBlog
# BootstrapSQLiteBlog
A blogging plugin for the php-webapp-framwork. Clone to the "plugins/" directory to use.

View File

@ -0,0 +1,8 @@
CREATE table if not exists links (
id integer primary key auto_increment,
label text not null,
url text not null,
icon text not null,
position text not null,
visibility text null,
sort integer not null default 0)

View File

@ -0,0 +1,9 @@
CREATE table if not exists posts (
id integer primary key auto_increment,
username text not null,
content text not null,
location text not null,
visibility text null,
created timestamp not null default current_timestamp,
updated timestamp not null default current_timestamp,
sort integer not null default 0)

View File

@ -0,0 +1,5 @@
CREATE table if not exists sessions (
id integer primary key auto_increment,
username text not null,
token text not null,
expires timestamp null)

View File

@ -0,0 +1,4 @@
CREATE table if not exists settings (
id integer primary key auto_increment,
setting text not null,
value text null)

View File

@ -0,0 +1,7 @@
CREATE table if not exists users (
id integer primary key auto_increment,
username text not null,
hash text not null,
can_post integer not null default 0,
is_admin integer not null default 0,
created timestamp not null default current_timestamp)

View File

@ -0,0 +1,4 @@
SELECT *
from posts
where
id = last_insert_id()

View File

@ -0,0 +1,8 @@
CREATE table if not exists links (
id integer primary key autoincrement,
label text not null,
url text not null,
icon text not null,
position text not null,
visibility text null,
sort integer not null default 0)

View File

@ -0,0 +1,9 @@
CREATE table if not exists posts (
id integer primary key autoincrement,
username text not null,
content text not null,
location text not null,
visibility text null,
created timestamp not null default current_timestamp,
updated timestamp not null default current_timestamp,
sort integer not null default 0)

View File

@ -0,0 +1,5 @@
CREATE table if not exists sessions (
id integer primary key autoincrement,
username text not null,
token text not null,
expires timestamp null)

View File

@ -0,0 +1,4 @@
CREATE table if not exists settings (
id integer primary key autoincrement,
setting text not null,
value text null)

View File

@ -0,0 +1,7 @@
CREATE table if not exists users (
id integer primary key autoincrement,
username text not null,
hash text not null,
can_post integer not null default 0,
is_admin integer not null default 0,
created timestamp not null default current_timestamp)

View File

@ -0,0 +1,4 @@
SELECT *
from posts
where
rowid = last_insert_rowid()

22
footer.php Normal file
View File

@ -0,0 +1,22 @@
<?php
$strDefaults =
"---
Copyright ©
* [Website Home](/)
* [Post](/post)
* [CSS](/edit/css)";
$strDefaults = preg_replace("/[ ]{4,}/", "", $strDefaults);
$strContent = Settings::get("footer", $strDefaults, true);
?>
<?php if (strlen($strContent) > 0): ?>
<div class="footer-content">
<?php
$varParsedown = new Parsedown();
echo $varParsedown->text($strContent);
?>
</div>
<?php endif; ?>

29
head.php Normal file
View File

@ -0,0 +1,29 @@
<meta name="viewport" content="initial-scale=1, width=device-width" />
<style>
<?php
$strDefaults = "
/* Put in your custom CSS here: */
.header-content { margin-bottom: 3em; }
.footer-content { margin-top: 3em; }
html { background: #aaa; font-family: Georgia; }
body { max-width: 7in; margin: 0 auto; padding: 3em; background: #fff; }
hr { border: none; background: #aaa; min-height: 1px; }
textarea { width: 100%; min-width: 100%; max-width: 100%; min-height: 3in; margin-bottom: 0.5em; }
.message-danger { background: #f00; color: #fff; padding: 0.5em; }
.message-warning { background: #fd0; color: #000; padding: 0.5em; }
.message-success { background: #070; color: #fff; padding: 0.5em; }
.message-info { background: #0df; color: #000; padding: 0.5em; }
.post-container { margin-top: 3em; margin-bottom: 3em; }
.post-container > hr { border: 0; background: none; border-bottom: 2px dotted #aaa; margin-top: 3em; margin-bottom: 3em; }
.post img { max-width: 2in; }
table { margin-bottom: 1em; }
a[href], a[href]:visited { color: #07a; text-decoration: none; }
a[href]:hover { text-decoration: underline; }
";
$strDefaults = preg_replace("/[ ]{4,}/", "", $strDefaults);
$strContent = Settings::get("css", $strDefaults, true);
echo $strContent;
?>
</style>

20
header.php Normal file
View File

@ -0,0 +1,20 @@
<?php
$strDefaults =
"[Website Home](/) —
[Post](/post) ·
[CSS](/edit/css)
---";
$strDefaults = preg_replace("/[ ]{4,}/", "", $strDefaults);
$strContent = Settings::get("header", $strDefaults, true);
?>
<?php if (strlen($strContent) > 0): ?>
<div class="header-content">
<?php
$varParsedown = new Parsedown();
echo $varParsedown->text($strContent);
?>
</div>
<?php endif; ?>

24
init.php Normal file
View File

@ -0,0 +1,24 @@
<?php
global $c;
$strDBCSFile = "dbcs.txt";
$strDBCS = "sqlite:sqlite.db";
if (!file_exists($strDBCSFile))
file_put_contents($strDBCSFile, $strDBCS);
$strDBCS = trim(file_get_contents($strDBCSFile));
$c = new DatabaseConnection($strDBCS);
$intInitialize = 1;
if ($intInitialize == 1)
{
$c->query([
"create_users_table.sql",
"create_sessions_table.sql",
"create_links_table.sql",
"create_posts_table.sql",
"create_settings_table.sql"]);
}
?>

69
lib/PageRender.php Normal file
View File

@ -0,0 +1,69 @@
<?php
class PageRender
{
public static function message()
{
if (func_num_args() > 0)
{
Cookie::set("message", func_get_arg(0));
if (func_num_args() > 1)
Cookie::set("messageClass", func_get_arg(1));
return;
}
$strMessage = Cookie::get("message");
$strMessageClass = Cookie::get("messageClass");
if (!isset($strMessageClass) || $strMessageClass == null || strlen($strMessageClass) < 1)
$strMessageClass = "info";
?>
<?php if (isset($strMessage) && $strMessage !== null && strlen($strMessage) > 0): ?>
<p class="message message-<?= $strMessageClass; ?>">
<?= $strMessage; ?>
</p>
<?php endif; ?>
<?php
Cookie::set("message");
Cookie::set("messageClass");
}
public static function uploads()
{
$varUploads = [];
try
{
$varUploads = scandir("files");
if ($varUploads !== false)
{
$varUploads = array_diff($varUploads, [".", ".."]);
rsort($varUploads);
}
}
catch (Exception $x) {}
$varUploads = array_slice($varUploads, 0, 20);
?>
<div class="uploads">
<div>
<label>Uploads</label>
</div>
<ul>
<li><a href="/upload" target="_blank">Manage</a></li>
<?php foreach ($varUploads as $u): ?>
<li><a href="/files/<?= $u; ?>" target="_blank">/files/<?= $u; ?></a></li>
<?php endforeach; ?>
</ul>
</div>
<?php
}
}
?>

1994
lib/Parsedown.php Normal file

File diff suppressed because it is too large Load Diff

55
lib/PostRender.php Normal file
View File

@ -0,0 +1,55 @@
<?php
class PostRender
{
public static function rows($varRows)
{
$varUser = UserAuth::getUser();
$varParsedown = new Parsedown();
$intRenderedRows = 0;
?>
<div class="post-container">
<?php foreach ($varRows as $r): ?>
<?php if (!UserAuth::visible($r["visibility"])) continue; ?>
<?php if ($intRenderedRows > 0): ?>
<hr />
<?php endif; ?>
<div class="post">
<div class="post-body">
<?php echo $varParsedown->text($r["content"]); ?>
</div>
<div class="post-footer">
<div class="post-author">by <?= $r["username"]; ?></div>
<div class="post-date">on <?= $r["created"]; ?> UTC</div>
<div class="post-links">
<a href="/<?= $r["id"]; ?>">Permalink</a> &middot;
<a href="<?= $r["location"]; ?>">Related</a>
<?php
$intOwnership =
UserAuth::has("is_admin") ||
$varUser["username"] == $r["username"];
?>
<?php if ($intOwnership): ?>
&middot; <a href="/post/<?= $r["id"]; ?>">Edit</a>
<?php endif; ?>
</div>
</div>
</div>
<?php $intRenderedRows++; ?>
<?php endforeach; ?>
<?php if ($intRenderedRows < 1): ?>
<div>Sorry, there is nothing here to show.</div>
<?php endif; ?>
</div>
<?php
}
}
?>

62
lib/Settings.php Normal file
View File

@ -0,0 +1,62 @@
<?php
class Settings
{
private static $varValues = null;
public static function get($strSettingName=null, $strDefault="", $intSave=0)
{
global $c;
if (Settings::$varValues == null)
{
$varRows = $c->query("SELECT * from settings order by setting");
$varValues = [];
foreach ($varRows as $r)
$varValues[$r["setting"]] = $r["value"];
Settings::$varValues = $varValues;
}
if ($strSettingName == null)
return Settings::$varValues;
if (array_key_exists($strSettingName, Settings::$varValues))
return Settings::$varValues[$strSettingName];
if ($intSave)
Settings::set($strSettingName, $strDefault);
return $strDefault;
}
public static function set($strSettingName, $strValue)
{
Settings::$varValues = null;
global $c;
$varExisting = $c->query("
SELECT *
from settings
where
setting like ?
order by
id desc",
$strSettingName);
if (count($varExisting) !== 1)
{
$c->query("DELETE from settings where setting like ?", $strSettingName);
$c->query("INSERT into settings (setting, value) values (?, ?)", $strSettingName, $strValue);
}
$c->query(
"UPDATE settings
set
value = ?
where setting like ?",
$strValue,
$strSettingName);
}
}
?>

110
lib/UserAuth.php Normal file
View File

@ -0,0 +1,110 @@
<?php
class UserAuth
{
public static function getUser()
{
global $c;
try
{
$strToken = Cookie::get("token");
if ($strToken !== null)
if (strlen($strToken) > 0)
{
$varSessions = $c->query(
"SELECT *
from sessions as s
join users as u on u.username = s.username
where
s.token = ?
and (
s.expires is null
or s.expires > current_timestamp
)",
$strToken);
if (count($varSessions) == 1)
return $varSessions[0];
}
}
catch (Exception $x) {}
return null;
}
public static function has($strColumnName)
{
global $c;
$varUser = UserAuth::getUser();
if ($varUser == null)
return false;
if (array_key_exists($strColumnName, $varUser))
if (intval($varUser[$strColumnName]) > 0)
return true;
return false;
}
public static function require($strColumnName)
{
if (!UserAuth::has($strColumnName))
{
PageRender::message("You do not have permission to do that, please sign into an account that does.", "warning");
Respond::redirect("/user/signin");
}
}
public static function visible($strVisibility)
{
global $c;
if (UserAuth::has("is_admin"))
return true;
$varUser = UserAuth::getUser();
$strUsername = $varUser["username"] ?? null;
$varRegex = [
["/user/i", ($varUser == null)],
["/admin/i", (!UserAuth::has("is_admin"))],
];
// Support arrays with username and visibility keys:
if (is_array($strVisibility))
{
if (array_key_exists("username", $strVisibility))
if ($strVisibility["username"] == $strUsername)
return true;
if (!array_key_exists("visibility", $strVisibility))
return false;
$strVisibility = $strVisibility["visibility"];
}
if ($strVisibility == null)
$strVisibility = "";
// Handle hiding the post from non-admins:
if (preg_match("/^(admin|hid(e|den)|invisible|no(ne|body)|private)$/i", $strVisibility))
return false;
if (preg_match("/{$strUsername}/i", $strVisibility)) return true;
// Handle showing the post to everyone:
if (preg_match("/^(|(every|any)(body|one))|all|public)$/i", $strVisibility))
return true;
$intExit = 0;
foreach ($varRegex as $re)
if (preg_match($re[0], $strVisibility))
if ($re[1])
$intExit = 1;
if ($intExit == 1)
return false;
return true;
}
}
?>

17
pages/directory.php Normal file
View File

@ -0,0 +1,17 @@
<?php
global $c;
$varPostLocations = $c->query("SELECT distinct location from posts order by location");
?>
<div>
<label>Directory</label>
</div>
<ul>
<?php foreach ($varPostLocations as $i): ?>
<?php
$intPostCount = $c->query("SELECT count(*) as c from posts where location = ?", $i["location"])[0]["c"];
?>
<li><a href="<?= $i["location"]; ?>"><?= $i["location"]; ?></a> <small>&mdash; <?= $intPostCount !== 1? "{$intPostCount} posts": "{$intPostCount} post"; ?></small></li>
<?php endforeach; ?>
</ul>

59
pages/edit.php Normal file
View File

@ -0,0 +1,59 @@
<?php
global $c;
UserAuth::require("is_admin");
$varUser = UserAuth::getUser();
$strId = Request::getArg(0);
// if ($strId == null || strlen($strId) < 1)
// $strId = "none";
if (Request::posts("content"))
Settings::set($strId, Request::getPosted("content"));
$strContent = Settings::get($strId, "");
?>
<?php if ($strId == null || strlen($strId) < 1): ?>
<?php $varRows = Settings::get(); ?>
<div>
<label>Edit</label>
</div>
<ul>
<?php foreach ($varRows as $k => $v): ?>
<li><a href="/edit/<?= $k; ?>"><?= $k; ?></a></li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<style>
textarea {
font-family: monospace;
}
</style>
<form method="post">
<div>
<label><?= $strId; ?></label>
</div>
<div>
<textarea
class="form-control border-0 shadow-none"
name="content"
placeholder="Enter content here..."
oninput="fnResize(this);"
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"><?= $strContent; ?></textarea>
</div>
<div><input type="submit" value="Save" /></div>
</form>
<?php endif; ?>

82
pages/find.php Normal file
View File

@ -0,0 +1,82 @@
<?php
global $c;
$strPath = "/";
$strPath .= implode("/", Request::getPathParts());
$varPosts = [];
$strQuery = Request::getParam("q");
$strAuthor = Request::getParam("username");
$strId = Request::getParam("id");
$intHasQuery = $strQuery !== null && strlen($strQuery) > 0;
$intHasAuthor = $strAuthor !== null && strlen($strAuthor) > 0;
$intHasId = $strId !== null && strlen($strId) > 0;
if ($intHasQuery)
{
$strQuery = preg_replace("/[^A-Za-z0-9]/", "", $strQuery);
$varPosts = $c->query(
"SELECT *
from posts as p
where
content like concat('%', ?, '%')
order by
created desc",
$strQuery);
$i = 0;
for ($i = 0; $i < count($varPosts); $i++)
{
$varOld = $varPosts[$i];
$varOld["content"] = preg_replace("/({$strQuery})/i", "<mark>$1</mark>", $varOld["content"]);
$varPosts[$i] = $varOld;
}
}
if ($intHasAuthor)
{
$varPosts = $c->query(
"SELECT *
from posts as p
where
username like ?
order by
created desc",
$strAuthor);
}
if ($intHasId)
{
$varPosts = $c->query(
"SELECT *
from posts as p
where
id = ?
order by
created desc",
$strId);
}
?>
<?php if (!$intHasAuthor && !$intHasId): ?>
<form method="get">
<table>
<tbody>
<tr>
<td><label>Search</label></td>
<td><input type="text" name="q" value="<?= $strQuery; ?>" /></td>
<td>
<input type="submit" value="Go" />
</td>
</tr>
</tbody>
</table>
</form>
<?php endif; ?>
<?php if ($intHasQuery || $intHasAuthor || $intHasId): ?>
<?php PostRender::rows($varPosts); ?>
<?php endif; ?>

48
pages/index.php Normal file
View File

@ -0,0 +1,48 @@
<?php
global $c;
$strArg1 = substr(Request::getPath(), 1);
$varPosts = [];
// Get one post by its id:
if (preg_match("/^[0-9]{1,}$/", $strArg1))
{
$varPosts = $c->query(
"SELECT *
from posts as p
where
id = ?
order by
created desc",
intval($strArg1));
}
// Get many post by its author:
if (preg_match("/^\@[A-Za-z0-9]{1,}$/", $strArg1))
{
$strArg1 = substr($strArg1, 1);
$varPosts = $c->query(
"SELECT *
from posts as p
where
username like ?
order by
created desc",
$strArg1);
}
if (count($varPosts) < 1)
{
$varPosts = $c->query(
"SELECT *
from posts as p
where
location like ?
or location like '*'
order by
created desc",
Request::getPath());
}
?>
<?php PostRender::rows($varPosts); ?>

146
pages/post.php Normal file
View File

@ -0,0 +1,146 @@
<?php
global $c;
UserAuth::require("can_post");
$varUser = UserAuth::getUser();
$strId = Request::getArg(0);
$strContent = "";
$strLocation = Request::getParam("to") ?? "";
$strVisibility = "";
$strVerb = "Create";
if (strlen($strId) > 0)
{
$strVerb = "Edit";
$varRows = $c->query("SELECT * from posts where id = ?", $strId);
if (count($varRows) !== 1)
{
PageRender::message("Zero or more than one row returned", "danger");
Respond::redirect("/post");
}
$varRow = $varRows[0];
$strContent = $varRow["content"];
$strLocation = $varRow["location"];
$strVisibility = $varRow["visibility"];
if (!UserAuth::has("is_admin"))
if ($varUser["username"] !== $varRow["username"])
{
PageRender::message("You are not the author of that post.");
Respond::redirect("/post");
}
}
if (Request::posts("location", "content", "visibility"))
{
$strLocation = Request::getPosted("location");
$strContent = Request::getPosted("content");
$strVisibility = Request::getPosted("visibility");
if ($strId == null || strlen($strId) < 1)
{
$c->query(
"INSERT into posts (username, content, location, visibility)
values (?, ?, ?, ?)",
$varUser["username"],
$strContent,
$strLocation,
$strVisibility);
$strId = $c->query("get_last_post.sql")[0]["id"];
PageRender::message("Post created.", "success");
Respond::redirect("/{$strId}");
}
if (strlen($strContent) < 1)
{
$c->query("DELETE from posts where id = ?", $strId);
PageRender::message("Post deleted successfully.", "success");
Respond::redirect("/post");
}
$c->query(
"UPDATE posts
set
content = ?,
location = ?,
visibility = ?,
updated = current_timestamp
where
id = ?",
$strContent,
$strLocation,
$strVisibility,
$strId);
PageRender::message("Post saved.", "success");
Respond::redirect("/post/{$strId}");
}
?>
<?php PageRender::message(); ?>
<style>
textarea {
font-family: monospace;
}
</style>
<form method="post">
<div>
<div>
<label>Content</label>
</div>
<div>
<textarea
name="content"
placeholder="Enter markdown content here..."
><?= $strContent; ?></textarea>
</div>
</div>
<div>
<table>
<tbody>
<tr>
<td><label>Location</label></td>
<td>
<input
type="text"
name="location"
placeholder="/"
value="<?= $strLocation; ?>" />
</td>
</tr>
<tr>
<td><label>Visible To</label></td>
<td>
<input
type="text"
name="visibility"
placeholder="everyone"
value="<?= $strVisibility; ?>" />
</td>
</tr>
<tr>
<td></td>
<td>
<input
type="submit"
value="Go" />
</td>
</tr>
</tbody>
</table>
</div>
</form>
<?php PageRender::uploads(); ?>

65
pages/upload.php Normal file
View File

@ -0,0 +1,65 @@
<?php
UserAuth::require("is_admin");
if (isset($_FILES["file"]))
{
$varFile = $_FILES["file"];
try
{
$strUploadName = basename($varFile["name"]);
$strUploadName = preg_replace("/ /", "_", $strUploadName);
$strUploadName = preg_replace("/[^A-Za-z0-9_\-\.]/", "", $strUploadName);
$strTimestamp = date("YmdHis");
$strDestinationPath = "files/{$strTimestamp}_{$strUploadName}";
$intAllow = 0;
// Check file size (optional)
if ($varFile["size"] > 1024 * 1024 * 5)
throw new Exception("Upload exceeds maximum file size.");
if (file_exists($strDestinationPath))
throw new Exception("Destination file already exists.");
foreach (["/\.jpg$/", "/\.png$/"] as $strExtension)
if (preg_match_all($strExtension, $strDestinationPath))
$intAllow = 1;
if ($intAllow == 0)
throw new Exception("File type not allowed.");
$intResult = move_uploaded_file($varFile["tmp_name"], $strDestinationPath);
if (!$intResult)
throw new Exception("Problem uploading file.");
}
catch (Exception $x)
{
PageRender::message($x->getMessage(), "danger");
}
}
?>
<?php PageRender::message(); ?>
<form method="post" enctype="multipart/form-data">
<table>
<tbody>
<tr>
<td>File</td>
<td><input type="file" name="file" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Upload" /></td>
</tr>
</tbody>
</table>
</form>
<?php PageRender::uploads(); ?>

49
pages/user/index.php Normal file
View File

@ -0,0 +1,49 @@
<?php
global $c;
$strError = null;
if (UserAuth::getUser() == null)
Respond::redirect("/user/signin");
$varUser = UserAuth::getUser();
if ($varUser == null)
Respond::redirect("/");
try
{
if (Request::posts("user_name", "display_name"))
{
$strUsername = Request::getPosted("user_name");
$strDisplayName = Request::getPosted("display_name");
if (!preg_match("/^[A-Za-z0-9]{1,}$/", $strUsername))
throw new Exception("Username must be alphanumeric characters only");
$c->query(
"INSERT or replace into users (email, user_name, display_name)
select
?,
?,
?",
$varUser["email"],
$strUsername,
$strDisplayName);
PageRender::message("Profile updated", "success");
}
}
catch (Exception $x)
{
PageRender::message($x->getMessage(), "danger");
}
$strUsername = $varUser["username"];
PageRender::message("You are signed in as {$strUsername}.");
?>
<?php PageRender::message(); ?>
<ul>
<li><a href="/user/signout">Sign out</a></li>
</ul>

83
pages/user/register.php Normal file
View File

@ -0,0 +1,83 @@
<?php
global $c;
try
{
$intUserCount = $c->query("SELECT count(*) as c from users")[0]["c"];
if ($intUserCount < 1)
{
PageRender::message(
"Please create an administrator account.",
"warning");
}
if (Request::posts("username", "password", "repeat"))
{
$strUsername = Request::getPosted("username");
$strPassword = Request::getPosted("password");
$strRepeat = Request::getPosted("repeat");
if (!preg_match("/^[A-Za-z0-9]{1,}$/", $strUsername))
throw new Exception("Not a valid username");
if (Request::getPosted("password") !== Request::getPosted("repeat"))
throw new Exception("Passwords do not match");
if (strlen($strPassword) < 6)
throw new Exception("Password must be at least 6 characters");
$varUsers = $c->query("SELECT * from users where username like ?", $strUsername);
if (count($varUsers) > 0)
throw new Exception("Username in use");
$strHash = sha1($strPassword);
$c->query(
"INSERT into users (username, hash) values (?, ?)",
$strUsername,
$strHash);
$intUserCount = $c->query("SELECT count(*) as c from users")[0]["c"];
if ($intUserCount == 1)
$c->query("UPDATE users set can_post = 1, is_admin = 1");
PageRender::message("Registration was a success, please sign in to continue.");
Respond::redirect("/user/signin");
}
}
catch (Exception $x)
{
PageRender::message($x->getMessage(), "danger");
}
?>
<form method="post">
<table>
<tbody>
<tr>
<td><label>Username</label></td>
<td><input type="text" name="username" value="" /></td>
</tr>
<tr>
<td><label>Password</label></td>
<td><input type="password" name="password" value="" /></td>
</tr>
<tr>
<td><label>Repeat</label></td>
<td><input type="password" name="repeat" value="" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Go" /></td>
</tr>
</tbody>
</table>
</form>

72
pages/user/signin.php Normal file
View File

@ -0,0 +1,72 @@
<?php
global $c;
try
{
$intUserCount = $c->query("SELECT count(*) as c from users")[0]["c"];
if ($intUserCount < 1)
Respond::redirect("/user/register");
if (Request::posts("username", "password"))
{
$strUsername = Request::getPosted("username");
$strPassword = Request::getPosted("password");
$strHash = sha1($strPassword);
$varUsers = $c->query(
"SELECT *
from users
where
username like ?
and hash = ?",
$strUsername,
$strHash);
if (count($varUsers) !== 1)
throw new Exception("Zero or more than one user returned for credentials provided");
$strToken = sha1(microtime());
$c->query(
"INSERT into sessions (username, token) values (?, ?)",
$strUsername,
$strToken);
Cookie::set("token", $strToken);
PageRender::message(
"Successfully signed in",
"info");
Respond::redirect("/user");
}
}
catch (Exception $x)
{
PageRender::message($x->getMessage(), "danger");
}
?>
<?php PageRender::message(); ?>
<form method="post">
<table>
<tbody>
<tr>
<td><label>Username</label></td>
<td><input type="text" name="username" value="" /></td>
</tr>
<tr>
<td><label>Password</label></td>
<td><input type="password" name="password" value="" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Go" /></td>
</tr>
</tbody>
</table>
</form>

29
pages/user/signout.php Normal file
View File

@ -0,0 +1,29 @@
<?php
global $c;
$varUser = UserAuth::getUser();
if ($varUser !== null)
{
if (Request::getArg(0) == "all")
{
$c->query(
"UPDATE sessions
set
expires = current_timestamp
where username = ?",
$varUser["username"]);
}
else
{
$c->query(
"UPDATE sessions
set
expires = current_timestamp
where token = ?",
$varUser["token"]);
}
}
PageRender::message("You have successfully signed out");
Respond::redirect("/user/signin");
?>