Compare commits
2 Commits
bf40752d9e
...
ecb5c59eb7
Author | SHA1 | Date | |
---|---|---|---|
ecb5c59eb7 | |||
eafc2588dc |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
* text=auto
|
@ -1,2 +1,3 @@
|
||||
# PlainSQLiteBlog
|
||||
# BootstrapSQLiteBlog
|
||||
|
||||
A blogging plugin for the php-webapp-framwork. Clone to the "plugins/" directory to use.
|
8
db/mysql/create_links_table.sql
Normal file
8
db/mysql/create_links_table.sql
Normal 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)
|
9
db/mysql/create_posts_table.sql
Normal file
9
db/mysql/create_posts_table.sql
Normal 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)
|
5
db/mysql/create_sessions_table.sql
Normal file
5
db/mysql/create_sessions_table.sql
Normal 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)
|
4
db/mysql/create_settings_table.sql
Normal file
4
db/mysql/create_settings_table.sql
Normal file
@ -0,0 +1,4 @@
|
||||
CREATE table if not exists settings (
|
||||
id integer primary key auto_increment,
|
||||
setting text not null,
|
||||
value text null)
|
7
db/mysql/create_users_table.sql
Normal file
7
db/mysql/create_users_table.sql
Normal 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)
|
4
db/mysql/get_last_post.sql
Normal file
4
db/mysql/get_last_post.sql
Normal file
@ -0,0 +1,4 @@
|
||||
SELECT *
|
||||
from posts
|
||||
where
|
||||
id = last_insert_id()
|
8
db/sqlite/create_links_table.sql
Normal file
8
db/sqlite/create_links_table.sql
Normal 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)
|
9
db/sqlite/create_posts_table.sql
Normal file
9
db/sqlite/create_posts_table.sql
Normal 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)
|
5
db/sqlite/create_sessions_table.sql
Normal file
5
db/sqlite/create_sessions_table.sql
Normal 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)
|
4
db/sqlite/create_settings_table.sql
Normal file
4
db/sqlite/create_settings_table.sql
Normal file
@ -0,0 +1,4 @@
|
||||
CREATE table if not exists settings (
|
||||
id integer primary key autoincrement,
|
||||
setting text not null,
|
||||
value text null)
|
7
db/sqlite/create_users_table.sql
Normal file
7
db/sqlite/create_users_table.sql
Normal 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)
|
4
db/sqlite/get_last_post.sql
Normal file
4
db/sqlite/get_last_post.sql
Normal file
@ -0,0 +1,4 @@
|
||||
SELECT *
|
||||
from posts
|
||||
where
|
||||
rowid = last_insert_rowid()
|
22
footer.php
Normal file
22
footer.php
Normal 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
29
head.php
Normal 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
20
header.php
Normal 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
24
init.php
Normal 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
69
lib/PageRender.php
Normal 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
1994
lib/Parsedown.php
Normal file
File diff suppressed because it is too large
Load Diff
55
lib/PostRender.php
Normal file
55
lib/PostRender.php
Normal 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> ·
|
||||
<a href="<?= $r["location"]; ?>">Related</a>
|
||||
|
||||
<?php
|
||||
$intOwnership =
|
||||
UserAuth::has("is_admin") ||
|
||||
$varUser["username"] == $r["username"];
|
||||
?>
|
||||
|
||||
<?php if ($intOwnership): ?>
|
||||
· <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
62
lib/Settings.php
Normal 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
110
lib/UserAuth.php
Normal 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
17
pages/directory.php
Normal 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>— <?= $intPostCount !== 1? "{$intPostCount} posts": "{$intPostCount} post"; ?></small></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
59
pages/edit.php
Normal file
59
pages/edit.php
Normal 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
82
pages/find.php
Normal 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
48
pages/index.php
Normal 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
146
pages/post.php
Normal 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
65
pages/upload.php
Normal 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
49
pages/user/index.php
Normal 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
83
pages/user/register.php
Normal 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
72
pages/user/signin.php
Normal 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
29
pages/user/signout.php
Normal 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");
|
||||
?>
|
Loading…
Reference in New Issue
Block a user