<?php
/*
* Copyright 2012 Douglas Robbins <hide@address.com>
*
* This file is part of Blite, a blogging application, available at
* <http://blite.ca/>.
*
* Blite is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
require('configure.php');
if (!$authuser) {
echo $lang['permdenied'];
exit;
}
$postid = '';
$page['error'] = '';
$page['lastpage'] = $cfg['home'];
if (!empty($_POST['postid']) && is_numeric($_POST['postid'])) {
$postid = $_POST['postid'];
}
if ($_SESSION['lastpage']) {
$page['lastpage'] = $_SESSION['lastpage'];
}
// Check the nonce.
if ($_POST) {
list($nonce, $noncestamp, $nonceerror) = verify_nonce('p_admin','The admin page expired.');
if ( !empty($nonceerror) ) {
echo $nonceerror;
exit;
}
}
// Retract a post.
if (!empty($_POST['retract']) && $postid) {
// Confirm the post exists; get the datestamp & categories.
$query_params = array ( 'postid' => 'int' );
$results = db_query("SELECT stamp,categories FROM posts WHERE id=?");
$post = db_getdata($results);
if ($post['stamp']) {
$year = date('Y', $post['stamp']);
$month = date ('n', $post['stamp']);
$catlist = explode(' ', $post['categories']);
foreach ($catlist as $catid) {
$query_params = array ( 'catid' => 'int' );
db_query("UPDATE categories SET postcount=postcount-1 WHERE id=?");
}
$query_params = array ( 'postid' => 'int' );
db_query("DELETE FROM categorized WHERE postid=?");
$query_params = array ( 'year' => 'int', 'month' => 'int' );
db_query("UPDATE archives SET postcount=postcount-1 WHERE year=? AND month=?");
$query_params = array ( 'postid' => 'int' );
db_query("UPDATE posts SET status='3' WHERE id=?");
$query_params = array( 'nonce' => 'txt', 'noncestamp' => 'int' );
db_query("INSERT INTO nonces (nonce, type, stamp) VALUES (?, 'p_admin', ?)");
rm_cache($cfg['datadir'] . '/cache/recent-posts');
rm_cache($cfg['datadir'] . '/cache/archives');
header("Location: " . $_SESSION['lastpage']);
exit;
}
}
// Publish a post.
elseif (!empty($_POST['publish']) && $postid) {
$query_params = array ( 'postid' => 'int' );
$results = db_query("SELECT categories FROM posts WHERE id=?");
$post = db_getdata($results);
if ($post['categories']) {
// Insert this post into categories and update categories counts
$catlist = explode(' ', $post['categories']);
foreach ($catlist as $catid) {
$query_params = array ( 'postid' => 'int', 'catid' => 'int' );
db_query("INSERT INTO categorized (postid, catid) VALUES (?, ?)");
$query_params = array ( 'catid' => 'int' );
db_query("UPDATE categories SET postcount=postcount+1 WHERE id=?");
}
// Update archives
$now = time();
$year = date('Y', $now);
$month = date ('n', $now);
$query_params = array ( 'year' => 'int', 'month' => 'int' );
$results = db_query("SELECT id FROM archives WHERE year=? AND month=?");
$row = db_getdata($results);
$archid = $row['id'];
if (!empty($archid)) {
// Update existing entry.
$query_params = array ( 'year' => 'int', 'month' => 'int' );
db_query("UPDATE archives SET postcount=postcount+1 WHERE year=? AND month=?");
}
else {
// Create new entry.
$query_params = array ( 'year' => 'int', 'month' => 'int' );
db_query("INSERT INTO archives (year, month, postcount) VALUES (?, ?, '1')");
$archid = $db->lastInsertRowID();
}
// Set this post as published
$archym = $year . '-' . $month;
$query_params = array (
'now' => 'int',
'archym' => 'txt',
'postid' => 'int'
);
db_query("UPDATE posts SET status='1', stamp=?, arch=? WHERE id=?");
$query_params = array( 'nonce' => 'txt', 'noncestamp' => 'int' );
db_query("INSERT INTO nonces (nonce, type, stamp) VALUES (?, 'p_admin', ?)");
rm_cache($cfg['datadir'] . '/cache/recent-posts');
rm_cache($cfg['datadir'] . '/cache/archives');
header("Location: ./?t=$postid");
exit;
}
}
// Save a post.
elseif (!empty($_POST['save']) || !empty($_POST['savedraft']) || !empty($_POST['saveretracted'])) {
$now = time();
$year = date('Y', $now);
$month = date ('n', $now);
$error = '';
$status = 1;
if (!empty($_POST['savedraft'])) {
$status = 2;
}
elseif (!empty($_POST['saveretracted'])) {
$status = 3;
}
$postbody = $_POST['postbody'];
$postbody = preg_replace("/\r\n|\r/", "\n", $postbody);
// Find and comment-out the excerpt marker.
if ( preg_match ("/\n--\n/", $postbody) ) {
$postbody = preg_replace("/\n--\n/", "\n<!-- -mark- -->\n", $postbody, 1);
}
$postbody = clean_blogpost($postbody, '2');
$posttitle = clean_blogpost($_POST['posttitle'], '1');
$newcat = clean_blogpost($_POST['newcat'], '1');
// Put the category checks into a stored array.
while (list ($key, $val) = each ($_POST)) {
if (substr($key, 0, 4) == 'cat-') {
$stored[$key] = $val;
}
}
if (empty($posttitle)) {
$error .= "<li>" . $lang['titlereq'] . "</li>\n";
}
if (empty($postbody)) {
$error .= "<li>" . $lang['textreq'] . "</li>\n";
}
if (empty($stored) && empty($_POST['newcat'])) {
$error .= "<li>" . $lang['catreq'] . "</li>\n";
}
if ($error) {
$page['error'] = "\n<div id='error_box'>\n<div class='error_title'>".$lang['errors']."</div>\n<ol>\n$error</ol>\n</div>\n";
}
else {
// Proceed to save data.
// Put category ids into space-separated format for storage in posts table.
foreach ($stored as $catid => $val) {
$categories .= "$val ";
}
$categories = trim($categories);
// Create a new category.
if ($_POST['newcat']) {
// If it exists, skip creation.
$query_params = array( 'newcat' => 'txt' );
$results = db_query("SELECT id FROM categories WHERE catname=?");
$cat = db_getdata($results);
if (empty($cat['id'])) {
$query_params = array( 'newcat' => 'txt' );
db_query("INSERT INTO categories (catname,postcount) VALUES (?,'0')");
$newcatid = $db->lastInsertRowID();
}
else {
$newcatid = $cat['id'];
}
$stored['cat-'.${newcatid}] = $newcatid;
$categories .= " $newcatid";
$categories = ltrim($categories);
}
if ($postid) {
// Editing an existing post.
// Get current category assignments for later comparison.
$query_params = array( 'postid' => 'int' );
$results = db_query("SELECT categories,stamp,status,arch FROM posts WHERE id=?");
$old = db_getdata($results);
$oldcategories = $old['categories'];
$oldstatus = $old['status'];
$arch = $old['arch'];
$stamp = $old['stamp'];
// If status is changing from draft to published, (a) set a new stamp, (b) update archives.
if ($oldstatus > 1 && $status == 1) {
$stamp = $now;
$arch = $year . '-' . $month;
// update archives.
$query_params = array( 'year' => 'int', 'month' => 'int' );
$results = db_query("SELECT id FROM archives WHERE year=? AND month=?");
$row = db_getdata($results);
$archid = $row['id'];
if ($archid) {
// Update existing entry.
$query_params = array( 'year' => 'int', 'month' => 'int' );
db_query("UPDATE archives SET postcount=postcount+1 WHERE year=? AND month=?");
}
else {
// Create new entry.
$query_params = array( 'year' => 'int', 'month' => 'int' );
db_query("INSERT INTO archives (year, month, postcount) VALUES (?, ?, '1')");
$archid = $db->lastInsertRowID();
}
}
// Or if we're re-saving a draft, update the timestamp.
elseif ( ($oldstatus == $status) && $status == '2' ) {
$stamp = $now;
}
// Update the posts table and delete all entries in categorized table.
$query_params = array (
'status' => 'int',
'stamp' => 'int',
'arch' => 'txt',
'categories' => 'txt',
'posttitle' => 'txt',
'postbody' => 'txt',
'postid' => 'int'
);
db_query("UPDATE posts SET status=?, stamp=?, arch=?, categories=?, title=?, body=? WHERE id=?");
$query_params = array( 'postid' => 'int' );
db_query("DELETE FROM categorized WHERE postid=?");
rm_cache($cfg['datadir'] . '/cache/excerpt-' . $postid);
}
else {
// Adding a new post.
// Create entry in posts table and get the new id.
$archym = $year . '-' . $month;
$query_params = array (
'now' => 'int',
'status' => 'int',
'archym' => 'txt',
'categories' => 'txt',
'posttitle' => 'txt',
'postbody' => 'txt'
);
db_query("INSERT INTO posts (stamp, status, arch, categories, title, body, comcount) VALUES (?, ?, ?, ?, ?, ?, '0')");
$postid = $db->lastInsertRowID();
// Update or create new entry in archives table.
if ($status == 1) {
$query_params = array( 'year' => 'int', 'month' => 'int' );
$results = db_query("SELECT id FROM archives WHERE year=? AND month=?");
$row = db_getdata($results);
$archid = $row['id'];
if (!empty($archid)) {
// Update existing entry.
$query_params = array( 'year' => 'int', 'month' => 'int' );
db_query("UPDATE archives SET postcount=postcount+1 WHERE year=? AND month=?");
}
else {
// Create new entry.
$query_params = array( 'year' => 'int', 'month' => 'int' );
db_query("INSERT INTO archives (year, month, postcount) VALUES (?, ?, '1')");
$archid = $db->lastInsertRowID();
}
}
}
if ($status == 1) {
// Create entries in categorized table. If a new post, increment postcount for categories.
foreach ($stored as $key => $catid) {
$query_params = array( 'postid' => 'int', 'catid' => 'int' );
db_query("INSERT INTO categorized (postid, catid) VALUES (?, ?)");
if ($oldstatus > 1 || !$_POST['postid']) {
$query_params = array( 'catid' => 'int' );
db_query("UPDATE categories SET postcount=postcount+1 WHERE id=?");
}
}
// Update postcounts in the categories table after (a) editing a post and changing categories or (b) changing status from draft to published..
if ( $postid && !empty($oldcategories) && ($oldcategories !== $categories) ) {
$oldlist = explode(' ', $oldcategories);
$newlist = explode(' ', $categories);
foreach ($oldlist as $catid) {
if (!in_array($catid, $newlist)) {
// Previous category removed.
$query_params = array( 'catid' => 'int' );
db_query("UPDATE categories SET postcount=postcount-1 WHERE id=?");
}
}
foreach ($newlist as $catid) {
if (!in_array($catid, $oldlist)) {
// New category added.
$query_params = array( 'catid' => 'int' );
db_query("UPDATE categories SET postcount=postcount+1 WHERE id=?");
}
}
}
}
$query_params = array( 'nonce' => 'txt', 'noncestamp' => 'int' );
db_query("INSERT INTO nonces (nonce, type, stamp) VALUES (?, 'p_admin', ?)");
rm_cache($cfg['datadir'] . '/cache/recent-posts');
rm_cache($cfg['datadir'] . '/cache/archives');
header("Location: " . $_SESSION['lastpage'] . '#post_' . $postid);
exit;
}
}
// Load data for editing a post.
elseif ($postid) {
$query_params = array( 'postid' => 'int' );
$results = db_query("SELECT title, status, categories, body FROM posts WHERE id=?");
$post = db_getdata($results);
if (stristr($post['categories'], ' ')) {
$list = explode(' ', $post['categories']);
foreach ($list as $catid) {
$stored['cat-'.$catid] = $catid;
}
}
else {
$stored['cat-'.$post['categories']] = $post['categories'];
}
$poststatus = $post['status'];
$posttitle = htmlspecialchars($post['title']);
$postbody = $post['body'];
// Decode any encoded <code> blocks.
if ( stristr($postbody, '<code>') ) {
$postbody = decode_code($postbody);
}
// Find and uncomment the excerpt marker.
if ( preg_match ("/\n<!-- -mark- -->\n/", $postbody) ) {
$postbody = preg_replace("/\n<!-- -mark- -->\n/", "\n--\n", $postbody, 1);
}
$postbody = htmlspecialchars($postbody);
}
// Build the category checks.
$query_params = '';
$results = db_query("SELECT categories.id, categories.catname FROM categories ORDER BY catname");
$catchecks = '';
while ($row = db_getdata($results)) {
$catid = $row['id'];
$catname = $row['catname'];
$chk = '';
if (!empty($stored['cat-'.$catid])) {
$chk = 'checked';
}
$catchecks .= "<div class='cat'><label><input type='checkbox' name='cat-$catid' value='$catid' $chk> $catname</label></div>\n";
}
$catchecks = "<div class='cattitle'>Categories</div>\n$catchecks";
// Build a nonce if one hasn't been passed from previous submission.
if ( empty($nonce) ) {
$noncestamp = time();
$nonce = sha1( $noncestamp . $_SERVER['REMOTE_ADDR'] . $cfg['noncesalt'] );
}
if (empty($posttitle)) {
$posttitle = '';
}
if (empty($postbody)) {
$postbody = '';
}
if (empty($newcat)) {
$newcat = '';
}
if (empty($poststatus)) {
$poststatus = '';
}
$page['cssfile'] = 'themes/' . $cfg['theme'] . '/admin.css';
$page['pagetitle'] = $lang['newpost'];
$page['infobar'] = "<div class='infobar'>" . $lang['newpost'] . "</div>";
$page['textlabel'] = $lang['text'];
$page['titlelabel'] = $lang['title'];
$page['posttitle'] = $posttitle;
$page['postbody'] = $postbody;
$page['newcat'] = $newcat;
$page['postid'] = $postid;
$page['nonce'] = $nonce;
$page['stamp'] = $noncestamp;
$page['savedraft'] = '';
$page['savelabel'] = $lang['save'];
if (!$postid || $poststatus == 2) {
$page['savelabel'] = $lang['savepublish'];
$page['savedraft'] = "<input type='submit' name='savedraft' value='" . $lang['savedraft'] . "'>";
}
elseif ($poststatus == 3) {
$page['savelabel'] = $lang['savepublish'];
$page['savedraft'] = "<input type='submit' name='saveretracted' value='" . $lang['saveretracted'] . "'>";
}
$page['categories'] = $catchecks;
$page['contentclass'] = 'post';
$page['navbottom'] = "<ul class='adminnav'><li><a href='./'>Home</a></li>\n$adminnav</ul>\n";
if ($postid) {
$page['pagetitle'] = $lang['editpost'];
$page['infobar'] = "<div class='infobar'>" . $lang['editpost'] . "</div>";
}
if (empty($error)) {
$page['onload'] = "onload='document.commentform.posttitle.focus();'";
}
else {
if (empty($posttitle)) {
$page['onload'] = "onload='document.commentform.posttitle.focus();'";
}
elseif (empty($postbody)) {
$page['onload'] = "onload='document.commentform.postbody.focus();'";
}
}
$subtemplate = file_get_contents('themes/' . $cfg['theme'] . '/templates/sub_post.tpl');
$template = file_get_contents('themes/' . $cfg['theme'] . '/templates/main.tpl');
$template = str_replace("#maincontent#", $subtemplate, $template);
foreach ($page as $key => $val) {
$template = str_replace("#${key}#",$val,$template);
}
echo $template;
exit;
function clean_blogpost($text, $type) {
if (get_magic_quotes_gpc()) {
$text = stripslashes($text);
}
if ($type == '1') {
$text = strip_tags($text);
}
elseif ($type == '2') {
// Apply htmlentities() within any <code> blocks.
if ( stristr($text, '<code>') ) {
$text = encode_code($text);
}
// Put the text through the PHP DOM.
if (extension_loaded('dom')) {
$text = dom_it($text);
}
// Isolate comments on their own line - INCL. THE EXCERPT MARKER.
// PHP DOM will sometimes collapse consecutive lines with html tags.
$text = str_replace("><!-- ", ">\n<!-- ", $text);
$text = str_replace(" --><", " -->\n<", $text);
// Tweaks for code readibility.
$text = pretty_code($text);
}
$text = trim($text);
return $text;
}
function pretty_code($text) {
// Add a newline after block-level closing tags.
$tags = array ( '/div', '/p', '/pre', '/ul', '/ol', '/li', 'br', 'hr' );
foreach ($tags as $tag) {
$text = str_replace('<'.$tag.'><', '<'.$tag.">\n<", $text);
}
// Add a newline after select block-level tags (removed by PHP DOM).
// These replacements should become RE's to allow for tag attributes.
$tags = array ( 'ul', 'ol' );
foreach ($tags as $tag) {
$text = str_replace('<'.$tag.'><', '<'.$tag.">\n<", $text);
}
return $text;
}
?>