execute_query("SELECT img, mime FROM queue WHERE id = ?", array($id))) {
$row = $getimg->fetch_assoc();
$img = $row['img'];
$mime = $row['mime'];
$getimg->close();
} else {
db_fail();
}
} else {
$image_file = save_uploaded_file();
if ($image_file) {
$img = fread(fopen($image_file, "r"), filesize($image_file));
$mime = get_mimetype($image_file);
}
}
// Column => value; the values are bound as query parameters
$fields = array(
'title' => $title,
'author' => $author,
'email' => $email,
'editor' => $editor,
);
if ($is_admin && isset($comments)) {
$fields['comments'] = $comments;
}
$fields['hidden'] = $hidden ? 1 : 0;
if ($remove_img && $story) {
$fields['story'] = $story;
$fields['mime'] = NULL;
$fields['img'] = NULL;
} else if (isset($img)) {
$fields['mime'] = $mime;
$fields['img'] = $img;
$fields['story'] = '';
} else {
$fields['story'] = $story;
}
if (!is_numeric($id) || $move)
$fields['date'] = $date;
$set = implode(', ', array_map(function ($column) { return "`$column` = ?"; }, array_keys($fields)));
$params = array_values($fields);
if (is_numeric($id) && !$move) {
$query = "UPDATE $table SET $set WHERE `id` = ? LIMIT 1";
$params[] = $id;
} else {
$query = "INSERT INTO $table SET $set";
}
//echo $query;
$result = $db->execute_query($query, $params) or db_fail();
if (is_numeric($id) && $move) {
$queue_id = $id;
}
// Get the (new) ID if we don't already have it.
if (!is_numeric($id) || $move) {
$query = "SELECT LAST_INSERT_ID();";
$getid = $db->query($query) or db_fail();
$row = $getid->fetch_row();
$id = $row[0];
}
// Delete the article in the queue if pushing live
if ($move && $queue_id) {
delete_story($queue_id, $move);
$queue = FALSE;
}
// Allow unprivileged user to view image on queue
if (!$is_admin && $action == 'submit')
$_SESSION['allow_queue_image'] = $id;
// A visitor's next story needs a new captcha
if (!$is_admin)
captcha_used();
// Prune filesystem
if ($image_file)
prune_images($image_file);
// email admin if added to the queue
if ($action == 'submit')
send_email($title, $author, $story);
return $id;
}
function delete_story($id, $move = FALSE) {
global $db, $is_admin, $queue;
// Only editors can delete stories
if (!$is_admin)
return '';
$queue = get_queue();
$table = which_table($move, 'delete');
$query = "DELETE FROM $table WHERE `id` = ? LIMIT 1";
//echo $query;
$result = $db->execute_query($query, array((int)$id)) or db_fail();
$message = '';
if (!$move)
$message = 'Article has been deleted.';
return $message;
}
function get_mimetype($image_file) {
$upload = getimagesize($image_file);
$mimetype = $upload ? $upload['mime'] : NULL;
return $mimetype;
}
function save_uploaded_file() {
// A new upload in this request
if (is_uploaded_file($_FILES['upload']['tmp_name'] ?? '')) {
return store_upload($_FILES['upload']['tmp_name']);
}
// An image uploaded at the preview step; the session knows which one
if (($_POST['uploaded'] ?? '') === 'pending') {
return pending_upload();
}
return FALSE;
}
function prune_images($image_file) {
// Delete the saved image, and anything older than $age.
// Only ever touch upload files inside the upload directory.
$age = 86400; // a day old
$dir = upload_dir();
if (dirname($image_file) === $dir && is_upload_name(basename($image_file))) {
@unlink($image_file);
}
unset($_SESSION['pending_upload']);
foreach (glob($dir . '/*') as $cleanup_file) {
if (is_upload_name(basename($cleanup_file)) &&
@filemtime($cleanup_file) < (time() - $age)) {
@unlink($cleanup_file);
}
}
}
/*
* Validate data
*
* Updates the global $validate array, with the key as the element name, and the value set to the error message.
*
*/
$validate = array();
function validate_data() {
global $validate, $is_admin;
// extract POST variables
$result = get_post_data(TRUE);
// assign their keys and values to the symbol table
extract($result[0], EXTR_OVERWRITE);
$upload_error = $_FILES['upload']['error'] ?? UPLOAD_ERR_NO_FILE;
$upload_tmp = $_FILES['upload']['tmp_name'] ?? '';
// Visitors must solve the captcha before a preview or a save
if (!$is_admin && !captcha_check()) {
$validate['captcha'] = 'Please complete the captcha.';
}
if (!$author) {
$validate['author'] = "You have not submitted an author.";
}
if (!$title) {
$validate['title'] = "You have not submitted a title.";
}
if ($remove_img && !$story) {
$validate['story'] = "You've tried to remove an image without replacing it with text.";
}
// 0 == no error; 4 == no file; all others are errors.
if ($upload_error > 0 &&
$upload_error !== 4) {
$validate['upload'] = 'There was an error uploading the file ('.$upload_error.')';
} else if ($upload_tmp) {
$upload = getimagesize($upload_tmp);
if (!$upload)
$validate['upload'] = htmlspecialchars($_FILES['upload']['name']) .
" wasn't an image file. Please go back.";
}
return TRUE;
}
function sanitise($story) {
if ($story) {
// No Javascript please!
$story = preg_replace("##si", "", $story);
// No comments please!
$story = preg_replace("##si", "", $story);
// Replace number ranges with n-dashes, in the text only (not in tags,
// where the digits can be part of a link or an attribute)
$parts = preg_split("#(<[^>]*>)#", $story, -1, PREG_SPLIT_DELIM_CAPTURE);
for ($i = 0; $i < count($parts); $i += 2)
$parts[$i] = preg_replace("#(\d)-+(?=\d)#", "$1–", $parts[$i]);
$story = implode('', $parts);
// Replace " -- " and "--" with m-dashes
$story = preg_replace("#(\s?)--(\s?)#si", "$1—$2", $story);
// Replace ellipses
$story = preg_replace("#(\w|\p{P}|>)\. ?\. ?\.(\s|\p{P})#si", "$1…$2", $story);
// External processing
include_once('../lib/smartypants.inc.php');
$story = SmartyPants($story);
#include_once('../lib/convert_entities.inc.php');
#$story = html_entity_decode_full($story); // Convert named entities to numeric entities
// Remove any unsafe markup; this must stay the last step
$story = purify_story($story);
}
return $story;
}
function send_email($title, $author, $story) {
include_once('../lib/convert_entities.inc.php');
$to = site_email('editor');
$subject = "New submission: $title";
$headers = 'From: x.x.x Queue <'.site_email('editor').'>'."\r\n";
$message = "Please review the queue. $author has sent the following new submission:\n\n";
if ($story) {
// Turn line and paragraph breaks into new lines before the tags are removed,
// and decode the entities last, so that a decoded "<" is not taken for a tag
$text = preg_replace(array("#
#i", "#