Initial commit
This commit is contained in:
commit
8489054f25
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>404 - Page Not Found</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>404 - Page Not Found</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<?php $logged_in = $_COOKIE["checkin"] ?? null; ?>
|
||||
|
||||
<?php if ( $logged_in && $logged_in == "waiting for expiry" ): ?>
|
||||
|
||||
<nav class="admin-bar">
|
||||
<ul>
|
||||
<li><a href="/admin.php">Admin Area</a>
|
||||
<li><a href="/logout.php">Log Out</a>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<?php endif; ?>
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
$logged_in = $_COOKIE["checkin"] ?? null;
|
||||
if ( !$logged_in || $logged_in != "waiting for expiry" ) {
|
||||
header("Location: /blog_log.php");
|
||||
die();
|
||||
}
|
||||
$post_success = $_GET["success"] ?? null;
|
||||
|
||||
// Get the file list
|
||||
$files = array_values( array_diff( scandir( "./posts" ), array('..', '.')));
|
||||
rsort($files);
|
||||
include_once "common.php";
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Administration</title>
|
||||
<style>
|
||||
header, main{width:90%;max-width:900px;margin:2em auto}
|
||||
hr.small-divider{width:25%;margin: 2em auto}
|
||||
textarea{width:100%;height:50vh}
|
||||
input[type=text]{width:100%}
|
||||
.logout{position:absolute;top:0;right:2em;padding:0.5em;border: 1px solid black}
|
||||
table{width:100%}
|
||||
.error{background:darkred;color:pink}
|
||||
ul.inline li{display:inline-block; margin:0}
|
||||
ul.inline li:not(:last-child)::after{content: ' | '}
|
||||
ul.list-style-none{list-style:none;margin:0;padding:0}
|
||||
.post-list tbody tr:nth-child(odd){background-color: #DDD}
|
||||
td{padding-left:1em}
|
||||
details {border: 1px solid #aaa;border-radius: 4px;padding: 0.5em 0.5em 0}
|
||||
summary {font-weight: bold;margin: -0.5em -0.5em 0;padding: 0.5em}
|
||||
details[open] summary {border-bottom: 1px solid #aaa;margin-bottom: 0.5em}
|
||||
thead{background: #333;color:#EEE}
|
||||
</style>
|
||||
</head>
|
||||
<body class="admin">
|
||||
<header>
|
||||
<h1>Website Admin</h1>
|
||||
<a href="/logout.php" class="logout">Log Out</a>
|
||||
</header>
|
||||
<main>
|
||||
<?php if ( $post_success === "0" ): ?>
|
||||
<div class="error">
|
||||
<h2>Error</h2>
|
||||
<p>There was a server error preventing your update from succeeding. Please check with your server admin to resolve the issue.</p>
|
||||
</div>
|
||||
<?php elseif ( $post_success === "1" ): ?>
|
||||
<p>New post successfully added!</p>
|
||||
<?php endif; ?>
|
||||
<form action="/new-post.php" method="post">
|
||||
<h2>New Post</h2>
|
||||
<p>
|
||||
<label>Title: <input type="text" name="post_title"></label>
|
||||
</p>
|
||||
<p>
|
||||
<label>Post (markdown):<br><textarea name="post_body" required></textarea>
|
||||
</p>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
<hr class="small-divider">
|
||||
<details class="post-list" open>
|
||||
<summary>Posts</summary>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Post Title</th>
|
||||
<th>Post Date</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach( $files as $f ) {
|
||||
$parts = split_filename( $f );
|
||||
$link = make_post_link( $f );
|
||||
$out = <<<HTML
|
||||
<tr>
|
||||
<td>$link</td>
|
||||
<td>{$parts["time"]}</td>
|
||||
<td>
|
||||
<ul class="inline list-style-none">
|
||||
<li>Edit</li>
|
||||
<li><a href="delete_post.php?f=%s">Delete</a></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
HTML;
|
||||
printf( $out, $parts["raw"] );
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><?php echo $page_title; ?></title>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1><?php echo $site_name; ?></h1>
|
||||
</header>
|
||||
<main>
|
||||
<form action="/new-post.php">
|
||||
<h2>New Post</h2>
|
||||
<label>Title: <input type="text" name="post_title"></label>
|
||||
<label>Post (markdown):<br><textarea name="post_body"></textarea>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
<hr class="small-divider">
|
||||
<details>
|
||||
<summary>Posts</summary>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Post Title</th>
|
||||
<th>Post Date</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
<hr>
|
||||
<form action="/new-post.php">
|
||||
<h2>New Page</h2>
|
||||
<label>Page Name <input type="text" name="page_name"></label>
|
||||
<label>Add to menu? <input type="checkbox" name="page_in_menu"></label>
|
||||
<label>Post (markdown):<br><textarea name="page_body"></textarea>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
<hr class="small-divider">
|
||||
<details>
|
||||
<summary>Pages</summary>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Page URL</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
const PW_FILE = "./blog_pass_hash.txt";
|
||||
$invalid = false;
|
||||
$logged_in = $_COOKIE["checkin"] ?? null;
|
||||
if ( $logged_in && $logged_in == "waiting for expiry" ) {
|
||||
header("Location: /admin.php");
|
||||
die();
|
||||
}
|
||||
$secret = $_POST["secret"] ?? null;
|
||||
if ( $secret ) {
|
||||
$secret = hash( "sha256", $secret );
|
||||
if ( $secret ) {
|
||||
$current = file_get_contents( PW_FILE );
|
||||
if ( $current) {
|
||||
if ( $secret == $current ) {
|
||||
setcookie("checkin", "waiting for expiry", time()+60*60*24*30, "/", "", false, true);
|
||||
header("Location: /admin.php");
|
||||
die();
|
||||
} else {
|
||||
$invalid = true;
|
||||
}
|
||||
} else {
|
||||
$success = file_put_contents( PW_FILE, $secret );
|
||||
if ( !$success ) die( "Internal server error" );
|
||||
setcookie("checkin", "waiting for expiry", time()+60*60*24*30, "/", "", false, true);
|
||||
header("Location: /admin.php");
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>A secret opens the door</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<?php if ( $invalid ): ?>
|
||||
<p id="error-message">
|
||||
An invalid secret was whispered.
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<form action="/blog_log.php" method="post">
|
||||
<label>Whisper a secret… <input type="password" name="secret" <?php echo $invalid ? 'aria-describedby="error-message"' : ''; ?>></label>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
function make_post_link( $a ) {
|
||||
$parts = split_filename( $a );
|
||||
return sprintf(
|
||||
'<a href="post.php?f=%s">%s</a>',
|
||||
$parts["encoded"],
|
||||
$parts["title"]
|
||||
);
|
||||
}
|
||||
|
||||
function title_from_filename( $fn ) {
|
||||
$fn = str_replace( ".md", "", $fn );
|
||||
$fn = urldecode( $fn );
|
||||
return $fn;
|
||||
}
|
||||
|
||||
function make_date_from_stamp( $ts ) {
|
||||
// Expects "time" from split_filename
|
||||
$date = date( "m/d/y", (int)$ts );
|
||||
return $date;
|
||||
}
|
||||
|
||||
function split_filename( $fn ) {
|
||||
$parts = explode( "_", $fn, 2);
|
||||
$out = [];
|
||||
$out["time"] = make_date_from_stamp( $parts[0] );
|
||||
$out["title"] = title_from_filename( $parts[1] );
|
||||
$out["raw"] = urlencode( $fn );
|
||||
$out["encoded"] = $fn;
|
||||
return $out;
|
||||
}
|
||||
|
||||
function read_post( $fn_raw ) {
|
||||
// Expects "raw" from split_filename
|
||||
$path = "posts/" . $fn_raw;
|
||||
$data = file_get_contents( $path );
|
||||
return $data;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This will appear in the header and title
|
||||
* for much of the site.
|
||||
*/
|
||||
const SITE_NAME = "My Website";
|
||||
|
||||
/*
|
||||
* Raw HTML, no markdown. Introductory content
|
||||
* goes here. It will appear on the index.php
|
||||
* page at the top (above the posts).
|
||||
*/
|
||||
const TOP_BLURB = <<<HTML
|
||||
HTML;
|
||||
|
||||
/*
|
||||
* Raw HTML, no markdown. Content for after
|
||||
* main body goes here. It will appear on the
|
||||
* index.php page at the bottom (below the posts).
|
||||
*/
|
||||
const FOOT_BLURB = <<<HTML
|
||||
HTML;
|
||||
|
||||
/*
|
||||
* If truthy, will replace the default
|
||||
* site header. It will automatically be
|
||||
* placed inside a <header> element.
|
||||
*/
|
||||
const SITE_HEADER = false;
|
||||
|
||||
/*
|
||||
* If truthy, will replace the default
|
||||
* site footer. It will automatically be
|
||||
* placed inside a <footer> element.
|
||||
*/
|
||||
const SITE_FOOTER = false;
|
||||
|
||||
/*
|
||||
* Change the base language of your site here.
|
||||
*/
|
||||
const LANG = "en";
|
|
@ -0,0 +1,21 @@
|
|||
nav.admin-bar{
|
||||
position: absolute;
|
||||
right: 2em;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
nav.admin-bar ul{list-style:none;display:inline-block;padding:0;margin:0}
|
||||
nav.admin-bar ul li{
|
||||
display:inline-block;
|
||||
padding:0.5em;
|
||||
background-color:#333;
|
||||
color: #EEE;
|
||||
margin: 0 5px;
|
||||
border-radius: 0 0 10px 10px;
|
||||
box-shadow: 3px 3px 5px silver;
|
||||
}
|
||||
nav.admin-bar :any-link {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
header{padding:1em 0}
|
||||
header h1{font-size: 1.2rem;border-bottom:3px solid #333;display:inline-block}
|
||||
header h1 a{text-decoration: none; color: inherit}
|
||||
.article-head{margin-bottom:4em;padding:1em 0;border-bottom:1px dashed #333}
|
||||
.article-head h1, .article-head .date{display:inline-block}
|
||||
.article-head .date{margin-left:2em;font-style:italic}
|
||||
|
||||
blockquote{border-left:3px solid #333;padding-left:1em}
|
||||
pre{border:1px dotted #333;background-color:#333;color:white;border-radius:10px;padding:1em;margin:2em 0}
|
||||
|
||||
body.post{color:#444;font-family:sans-serif;padding-left:2em}
|
||||
body.post main h1,
|
||||
body.post main h2,
|
||||
body.post main h3,
|
||||
body.post main h4,
|
||||
body.post main h5,
|
||||
body.post main h6{font-family:serif}
|
||||
body.post main{max-width:900px}
|
||||
body.post main p
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
// Get the file list
|
||||
$files = array_values( array_diff( scandir( "./posts" ), array('..', '.')));
|
||||
rsort($files);
|
||||
include_once "common.php";
|
||||
include_once "config.php";
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><?php echo SITE_NAME; ?></title>
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<link rel="stylesheet" href="/css/admin-bar.css">
|
||||
</head>
|
||||
<body class="index">
|
||||
<?php include_once "admin-bar-partial.php"; ?>
|
||||
<header>
|
||||
<?php if ( SITE_HEADER ): ?>
|
||||
<?php echo SITE_HEADER; ?>
|
||||
<?php else: ?>
|
||||
<h1><a href="/"><?php echo SITE_NAME; ?></a></h1>
|
||||
<?php endif; ?>
|
||||
</header>
|
||||
<main>
|
||||
<?php
|
||||
echo TOP_BLURB;
|
||||
if ( count( $files ) > 0 ) {
|
||||
echo "<ul>";
|
||||
foreach( $files as $f ) {
|
||||
$link = make_post_link( $f );
|
||||
echo "<li>$link</li>";
|
||||
}
|
||||
echo "</ul>";
|
||||
}
|
||||
?>
|
||||
</main>
|
||||
<?php if (FOOT_BLURB) echo FOOT_BLURB; ?>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
$logged_in = $_COOKIE["checkin"] ?? null;
|
||||
if ( $logged_in && $logged_in == "waiting for expiry" ) {
|
||||
setcookie("checkin", "", time() - 3600);
|
||||
}
|
||||
header("Location: /blog_log.php");
|
||||
die();
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
// Bounce if not logged in
|
||||
$logged_in = $_COOKIE["checkin"] ?? null;
|
||||
if ( !$logged_in || $logged_in != "waiting for expiry" ) {
|
||||
header("Location: /blog_log.php");
|
||||
die();
|
||||
}
|
||||
|
||||
$ts = time();
|
||||
$title = isset( $_POST["post_title"] ) ? trim( $_POST["post_title"] ) : null;
|
||||
$body = isset( $_POST["post_body"] ) ? trim( $_POST["post_body"] ) : null;
|
||||
|
||||
// Bounce if requirements are not met for the post
|
||||
if ( !$title || !$body || $title == "" || $body == "" ) {
|
||||
header("Location: /blog_log.php?success=0");
|
||||
die();
|
||||
}
|
||||
|
||||
// Try to write the file
|
||||
$success = file_put_contents( "./posts/" . $ts . "_" . urlencode( $title ) . ".md", $body );
|
||||
if ( $success ) {
|
||||
// Yay! Redirect to admin
|
||||
header("Location: /admin.php?success=1");
|
||||
die();
|
||||
} else {
|
||||
header("Location: /admin.php?success=0");
|
||||
die();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
include_once "common.php";
|
||||
include_once "config.php";
|
||||
$f = $_GET["f"] ?? null;
|
||||
if ( !$f ) {
|
||||
header("Location: 404.php");
|
||||
die();
|
||||
}
|
||||
$parts = split_filename( $f );
|
||||
$data = read_post( $parts["raw"] );
|
||||
if ( !$data ) {
|
||||
header("Location: 404.php");
|
||||
die();
|
||||
}
|
||||
include_once "parsedown.php";
|
||||
$html = Parsedown::instance()->text( $data );
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><?php echo $parts["title"]; ?></title>
|
||||
<link rel="stylesheet" href="/css/style.css">
|
||||
<link rel="stylesheet" href="/css/admin-bar.css">
|
||||
</head>
|
||||
<body class="post">
|
||||
<?php include_once "admin-bar-partial.php"; ?>
|
||||
<header>
|
||||
<?php if ( SITE_HEADER ): ?>
|
||||
<?php echo SITE_HEADER; ?>
|
||||
<?php else: ?>
|
||||
<h1><a href="/"><?php echo SITE_NAME; ?></a></h1>
|
||||
<?php endif; ?>
|
||||
</header>
|
||||
<main>
|
||||
<div class="article-head">
|
||||
<h1><?php echo $parts["title"]; ?></h1>
|
||||
<p class="date"><?php echo $parts["time"]; ?></p>
|
||||
</div>
|
||||
<div class="article-body">
|
||||
<?php echo $html; ?>
|
||||
</div>
|
||||
</main>
|
||||
<?php if ( SITE_FOOTER ): ?>
|
||||
<footer>
|
||||
<?php echo SITE_FOOTER; ?>
|
||||
</footer>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue