1246 lines
53 KiB
PHP
1246 lines
53 KiB
PHP
<?php
|
|
# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
|
|
# All rights reserved. See LICENSE file for licensing details
|
|
|
|
if (IN_serendipity !== true) {
|
|
die ("Don't hack!");
|
|
}
|
|
|
|
/**
|
|
* Check if a comment token (from comment notification email) is valid for a given comment id.
|
|
*
|
|
* @param string The Token
|
|
* @param int The comment id
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
function serendipity_checkCommentToken($token, $cid) {
|
|
global $serendipity;
|
|
|
|
$goodtoken = false;
|
|
if ($serendipity['useCommentTokens']) {
|
|
// Delete any comment tokens older than 1 week.
|
|
serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}options
|
|
WHERE okey LIKE 'comment_%' AND name < " . (time() - 604800) );
|
|
// Get the token for this comment id
|
|
$tokencheck = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}options
|
|
WHERE okey = 'comment_" . (int)$cid . "' LIMIT 1", true, 'assoc');
|
|
// Verify it against the passed key
|
|
if (is_array($tokencheck)) {
|
|
if ($tokencheck['value'] == $token) {
|
|
$goodtoken = true; // use this to bypass security checks later
|
|
// if using tokens, delete this comment from that list no matter how we got here
|
|
serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}options
|
|
WHERE okey = 'comment_" . (int)$cid . "'");
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return $goodtoken;
|
|
}
|
|
|
|
/**
|
|
* Check if a comment token was submitted to the serendipity main framework.
|
|
* This function can kill the workflow completely, if moderation was wanted.
|
|
*
|
|
* @param string The current base URI
|
|
* @access public
|
|
* @return null
|
|
*/
|
|
function serendipity_checkCommentTokenModeration($uri) {
|
|
global $serendipity;
|
|
|
|
// token based comment moderation starts here
|
|
if ($serendipity['useCommentTokens'] === true && preg_match(PAT_DELETE, $uri, $res)) {
|
|
$return_msg = "Error.\n";
|
|
$tokenparse = explode("_",$res[1]);
|
|
// check that we got a 32 char token
|
|
if (is_array($tokenparse)) {
|
|
if (strlen($tokenparse[2]) == 32) {
|
|
if ($tokenparse[0] == 'comment') {
|
|
if (serendipity_deleteComment($res[2], $res[3], 'comments', $tokenparse[2])) {
|
|
$return_msg = sprintf (COMMENT_DELETED, $res[2])."\n";
|
|
} else {
|
|
$return_msg = sprintf (COMMENT_NOTOKENMATCH, $res[2])."\n";
|
|
}
|
|
} elseif ($tokenparse[0] == 'trackback') {
|
|
if (serendipity_deleteComment($res[2], $res[3], 'trackbacks', $tokenparse[2])) {
|
|
$return_msg = sprintf (TRACKBACK_DELETED, $res[2])."\n";
|
|
} else {
|
|
$return_msg = sprintf (TRACKBACK_NOTOKENMATCH, $res[2])."\n";
|
|
}
|
|
}
|
|
} else {
|
|
$return_msg = sprintf (BADTOKEN)."\n";
|
|
}
|
|
header('Content-Type: text/plain; charset='. LANG_CHARSET);
|
|
die($return_msg);
|
|
}
|
|
}
|
|
if ($serendipity['useCommentTokens'] === true && preg_match(PAT_APPROVE, $uri, $res)) {
|
|
$return_msg = "Error.\n";
|
|
$tokenparse = explode("_",$res[1]);
|
|
// check that we got a 32 char token
|
|
if (is_array($tokenparse)) {
|
|
if (strlen($tokenparse[2]) == 32) {
|
|
if ($tokenparse[0] == 'comment') {
|
|
if (serendipity_approveComment($res[2], $res[3], false, false, $tokenparse[2])) {
|
|
$return_msg = sprintf (COMMENT_APPROVED, $res[2])."\n";
|
|
} else {
|
|
$return_msg = sprintf (COMMENT_NOTOKENMATCH, $res[2])."\n";
|
|
}
|
|
} elseif ($tokenparse[0] == 'trackback') {
|
|
if (serendipity_approveComment($res[2], $res[3], false, false, $tokenparse[2])) {
|
|
$return_msg = sprintf (TRACKBACK_APPROVED, $res[2])."\n";
|
|
} else {
|
|
$return_msg = sprintf (TRACKBACK_NOTOKENMATCH, $res[2])."\n";
|
|
}
|
|
}
|
|
} else {
|
|
$return_msg = sprintf (BADTOKEN)."\n";
|
|
}
|
|
header('Content-Type: text/plain; charset='. LANG_CHARSET);
|
|
die($return_msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Store the personal details of a commenting user in a cookie (or delete that cookie)
|
|
*
|
|
* @access public
|
|
* @return null
|
|
*/
|
|
function serendipity_rememberComment() {
|
|
global $serendipity;
|
|
|
|
if (isset($serendipity['POST']['remember'])) {
|
|
serendipity_rememberCommentDetails(
|
|
array(
|
|
'url' => $serendipity['POST']['url'],
|
|
'name' => $serendipity['POST']['name'],
|
|
'email' => $serendipity['POST']['email'],
|
|
'remember' => 'checked="checked"'
|
|
)
|
|
);
|
|
} elseif (isset($serendipity['POST']['comment'])) {
|
|
serendipity_forgetCommentDetails(array('url', 'name', 'email', 'remember'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Store all options of an array within a permanent cookie
|
|
*
|
|
* @access public
|
|
* @param array input array
|
|
* @return null
|
|
*/
|
|
function serendipity_rememberCommentDetails($details) {
|
|
global $serendipity;
|
|
|
|
foreach ($details as $n => $v) {
|
|
serendipity_setCookie($n, $v);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Purge stored options from a permanent cookie
|
|
*
|
|
* LONG
|
|
*
|
|
* @access public
|
|
* @param array Array of key names that shall be deleted inside cookies
|
|
* @return null
|
|
*/
|
|
function serendipity_forgetCommentDetails($keys) {
|
|
global $serendipity;
|
|
if (!$serendipity['COOKIE']) {
|
|
return;
|
|
}
|
|
|
|
foreach ($keys AS $n) {
|
|
serendipity_deleteCookie($n);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Display the Comment form for entries
|
|
*
|
|
* @access public
|
|
* @param int The EntryID to show the commentform for
|
|
* @param string The URL that acts as the target of the HTML Form
|
|
* @param array Array of existing comments to this entry
|
|
* @param array Array of personal details data (i.e. from Cookie or POST input)
|
|
* @param boolean Toggle whether to show extended options of the comment form
|
|
* @param boolean Toggle whether comments to this entry are allowed
|
|
* @param array The data of the entry that the comment is referring to
|
|
* @return null
|
|
*/
|
|
function serendipity_displayCommentForm($id, $url = '', $comments = NULL, $data = NULL, $showToolbar = true, $moderate_comments = true, $entry = null) {
|
|
global $serendipity;
|
|
|
|
if ($comments == NULL) {
|
|
if (empty($id)) {
|
|
$comments = array();
|
|
} else {
|
|
$comments = serendipity_fetchComments($id);
|
|
}
|
|
}
|
|
|
|
$commentform_data = array(
|
|
'commentform_action' => $url,
|
|
'commentform_id' => (int)$id,
|
|
'commentform_name' => isset($data['name']) ? serendipity_specialchars($data['name']) : (isset($serendipity['COOKIE']['name']) ? serendipity_specialchars($serendipity['COOKIE']['name']) : ''),
|
|
'commentform_email' => isset($data['email']) ? serendipity_specialchars($data['email']) : (isset($serendipity['COOKIE']['email']) ? serendipity_specialchars($serendipity['COOKIE']['email']) : ''),
|
|
'commentform_url' => isset($data['url']) ? serendipity_specialchars($data['url']) : (isset($serendipity['COOKIE']['url']) ? serendipity_specialchars($serendipity['COOKIE']['url']) : ''),
|
|
'commentform_remember' => isset($data['remember']) ? 'checked="checked"' : (isset($serendipity['COOKIE']['remember']) ? 'checked="checked"' : ''),
|
|
'commentform_replyTo' => serendipity_generateCommentList($id, $comments, ((isset($data['replyTo']) && ($data['replyTo'])) ? $data['replyTo'] : 0)),
|
|
'commentform_subscribe' => isset($data['subscribe']) ? 'checked="checked"' : '',
|
|
'commentform_data' => isset($data['comment']) ? serendipity_specialchars($data['comment']) : '',
|
|
'is_commentform_showToolbar' => $showToolbar,
|
|
'is_allowSubscriptions' => (serendipity_db_bool($serendipity['allowSubscriptions']) || $serendipity['allowSubscriptions'] === 'fulltext' ? true : false),
|
|
'is_moderate_comments' => $moderate_comments,
|
|
'commentform_entry' => $entry
|
|
);
|
|
|
|
$serendipity['smarty']->assign($commentform_data);
|
|
|
|
serendipity_smarty_fetch('COMMENTFORM', 'commentform.tpl');
|
|
}
|
|
|
|
/**
|
|
* Fetch an array of comments to a specific entry id
|
|
*
|
|
* @access public
|
|
* @param int The Entry ID to fetch comments for
|
|
* @param int How many comments to fetch (empty: all)
|
|
* @param string How shall comments be ordered (ASC|DESC)
|
|
* @param boolean Shall non-approved comments be displayed?
|
|
* @param string Comment type to fetch
|
|
* @return array The SQL result of comments
|
|
*/
|
|
function serendipity_fetchComments($id, $limit = null, $order = '', $showAll = false, $type = 'NORMAL', $where = '') {
|
|
global $serendipity;
|
|
$and = '';
|
|
|
|
if (!empty($limit)) {
|
|
$limit = serendipity_db_limit_sql($limit);
|
|
} else {
|
|
$limit = '';
|
|
}
|
|
|
|
if ($type == 'comments' || empty($type)) {
|
|
$type = 'NORMAL';
|
|
} elseif ($type == 'trackbacks') {
|
|
$type = 'TRACKBACK';
|
|
} elseif ($type == 'pingbacks') {
|
|
$type = 'PINGBACK';
|
|
} elseif ($type == 'comments_and_trackbacks') {
|
|
$type = '%';
|
|
}
|
|
|
|
if (!empty($id)) {
|
|
$and .= " AND co.entry_id = '" . (int)$id ."'";
|
|
}
|
|
|
|
if (!$showAll) {
|
|
$and .= ' AND co.status = \'approved\'';
|
|
}
|
|
|
|
$and .= $where;
|
|
|
|
if ($serendipity['dbType'] == 'postgres' ||
|
|
$serendipity['dbType'] == 'pdo-postgres') {
|
|
$group = '';
|
|
$distinct = 'DISTINCT';
|
|
} else {
|
|
$group = 'GROUP BY co.id';
|
|
$distinct = '';
|
|
}
|
|
|
|
$query = "SELECT $distinct
|
|
co.id,
|
|
co.entry_id, co.timestamp, co.title AS ctitle, co.email, co.url, co.ip, co.body, co.type, co.subscribed,
|
|
co.author,
|
|
e.title,
|
|
e.timestamp AS entrytimestamp,
|
|
e.id AS entryid,
|
|
e.authorid,
|
|
e.author as entryauthor,
|
|
co.id AS commentid,
|
|
co.parent_id AS parent_id,
|
|
co.status
|
|
FROM
|
|
{$serendipity['dbPrefix']}comments AS co
|
|
LEFT JOIN {$serendipity['dbPrefix']}entries AS e ON (co.entry_id = e.id)
|
|
WHERE co.type LIKE '" . $type . "' AND co.entry_id > 0 $and
|
|
$group
|
|
ORDER BY
|
|
" . (empty($order) ? 'co.id' : $order) . "
|
|
$limit";
|
|
$comments = serendipity_db_query($query, false, 'assoc');
|
|
|
|
if (!is_array($comments)) {
|
|
$comments = array();
|
|
}
|
|
|
|
$addData = array('id' => $id, 'limit' => $limit, 'order' => $order, 'showAll' => $showAll, 'type' => $type, 'where' => $where);
|
|
serendipity_plugin_api::hook_event('fetchcomments', $comments, $addData);
|
|
|
|
return $comments;
|
|
}
|
|
|
|
/**
|
|
* Create a HTML SELECT dropdown field which represents all hierarchical comments
|
|
*
|
|
* @access public
|
|
* @param int The entry ID to show comments for
|
|
* @param array The existing comments for this entry
|
|
* @param int The ID of the comment that is being referred to (last selection)
|
|
* @param int The parent ID of the last comment [for recursive usage]
|
|
* @param int The current nesting/hierarchy level [for recursive usage]
|
|
* @param string The HTML indention string that gets prepended to a comment [for recursive usage]
|
|
* @return string The HTML SELECT code
|
|
*/
|
|
function serendipity_generateCommentList($id, $comments = NULL, $selected = 0, $parent = 0, $level = 0, $indent = '') {
|
|
global $serendipity;
|
|
|
|
if (!is_array($comments)) {
|
|
if (empty($id)) {
|
|
$comments = array();
|
|
} else {
|
|
$comments = serendipity_fetchComments($id);
|
|
}
|
|
}
|
|
|
|
$retval = $parent ? '' : '<select id="serendipity_replyTo" onchange="' . (!empty($serendipity['plugindata']['onchange']) ? $serendipity['plugindata']['onchange'] : '') . '" name="serendipity[replyTo]"><option value="0">[ ' . TOP_LEVEL . ' ]</option>';
|
|
|
|
$i = 0;
|
|
foreach ($comments as $comment) {
|
|
if ($comment['parent_id'] == $parent) {
|
|
$i++;
|
|
$retval .= '<option value="' . $comment['id'] . '"'. ($selected == $comment['id'] || (isset($serendipity['POST']['replyTo']) && $comment['id'] == $serendipity['POST']['replyTo']) ? ' selected="selected"' : '') .'>' . str_repeat(' ', $level * 2) . '#' . $indent . $i . ': ' . (empty($comment['author']) ? ANONYMOUS : serendipity_specialchars($comment['author'])) . ' ' . ON . ' ' . serendipity_mb('ucfirst', serendipity_strftime(DATE_FORMAT_SHORT, $comment['timestamp'])) . "</option>\n";
|
|
$retval .= serendipity_generateCommentList($id, $comments, $selected, $comment['id'], $level + 1, $indent . $i . '.');
|
|
}
|
|
}
|
|
$retval .= $parent ? '' : '</select>';
|
|
|
|
return $retval;
|
|
}
|
|
|
|
/**
|
|
* Print a list of comments to an entry
|
|
*
|
|
* @access public
|
|
* @param array The list of comments to display
|
|
* @param int The parentID of a comment to show. Can contain the constant for VIEWMODE_THREADED/LINEAR. [recursive usage]
|
|
* @param int The current nesting depth of a comment [recursive usage]
|
|
* @param string A string repesenting the actual comment (1.1.2.1)
|
|
* @return string The HTML construct of all comments
|
|
*/
|
|
function serendipity_printComments($comments, $parentid = 0, $depth = 0, $trace = null, $smarty_block = 'COMMENTS', $smarty_file = 'comments.tpl') {
|
|
global $serendipity;
|
|
static $_smartyComments;
|
|
|
|
/* - $_smartyComments holds the ending smarty array.
|
|
- $depth is the current depth of the recurrence.
|
|
- $i is the position in the current depth. */
|
|
|
|
if ($parentid === VIEWMODE_THREADED) {
|
|
$parentid = 0;
|
|
}
|
|
|
|
/* Wait a second, we just got attacked by a call with level 0,
|
|
this must mean we've started over */
|
|
if ( $depth == 0 ) {
|
|
$_smartyComments = array();
|
|
}
|
|
|
|
$formToken = serendipity_setFormToken('url');
|
|
$i = 0;
|
|
foreach ($comments as $comment) {
|
|
if ($parentid === VIEWMODE_LINEAR || !isset($comment['parent_id']) || $comment['parent_id'] == $parentid) {
|
|
$i++;
|
|
|
|
$comment['comment'] = (is_string($comment['body']) ? serendipity_specialchars(strip_tags($comment['body'])) : '');
|
|
$comment['url'] = (is_string($comment['url']) ? strip_tags($comment['url']) : '');
|
|
$comment['link_delete'] = $serendipity['baseURL'] . 'comment.php?serendipity[delete]=' . $comment['id'] . '&serendipity[entry]=' . $comment['entry_id'] . '&serendipity[type]=comments&' . $formToken;
|
|
|
|
/* Fix invalid cases in protocoll part */
|
|
if (!empty($comment['url'])) {
|
|
$comment['url'] = preg_replace('@^http://@i','http://', $comment['url']);
|
|
$comment['url'] = preg_replace('@^https://@i','https://', $comment['url']);
|
|
}
|
|
/* Fix fucked links */
|
|
if (!empty($comment['url']) && substr($comment['url'], 0, 7) != 'http://' && substr($comment['url'], 0, 8) != 'https://') {
|
|
$comment['url'] = 'http://' . $comment['url'];
|
|
}
|
|
|
|
if (!empty($comment['url'])) {
|
|
if (!@parse_url($comment['url'])) {
|
|
$comment['url'] = '';
|
|
}
|
|
$comment['url'] = serendipity_specialchars($comment['url'], ENT_QUOTES);
|
|
}
|
|
|
|
$addData = array('from' => 'functions_entries:printComments');
|
|
serendipity_plugin_api::hook_event('frontend_display', $comment, $addData);
|
|
|
|
if (isset($comment['no_email']) && $comment['no_email']) {
|
|
$comment['email'] = false;
|
|
} elseif (!empty($comment['email'])) {
|
|
$comment['clear_email'] = $comment['email'];
|
|
$comment['email'] = serendipity_specialchars(str_replace('@', '[at]', $comment['email']));
|
|
}
|
|
|
|
$comment['body'] = $comment['comment'];
|
|
$comment['pos'] = $i;
|
|
$comment['trace'] = $trace . $i;
|
|
$comment['depth'] = $depth;
|
|
$comment['author'] = serendipity_specialchars($comment['author']);
|
|
if (isset($comment['title'])) {
|
|
$comment['title'] = serendipity_specialchars($comment['title']);
|
|
}
|
|
|
|
if (serendipity_userLoggedIn()) {
|
|
if ($comment['subscribed'] == 'true') {
|
|
if ($comment['status'] == 'approved') {
|
|
$comment['body'] .= '<div class="serendipity_subscription_on"><em>' . ACTIVE_COMMENT_SUBSCRIPTION . '</em></div>';
|
|
} else {
|
|
$comment['body'] .= '<div class="serendipity_subscription_pending"><em>' . PENDING_COMMENT_SUBSCRIPTION . '</em></div>';
|
|
}
|
|
} else {
|
|
#$comment['body'] .= '<div class="serendipity_subscription_off"><em>' . NO_COMMENT_SUBSCRIPTION . '</em></div>';
|
|
}
|
|
}
|
|
|
|
$_smartyComments[] = $comment;
|
|
if ($comment['id'] && $parentid !== VIEWMODE_LINEAR ) {
|
|
serendipity_printComments($comments, $comment['id'], ($depth+1), ($trace . $i . '.'), $smarty_block, $smarty_file);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* We are inside a recusive child, and we need to break out */
|
|
if ($depth !== 0) {
|
|
return true;
|
|
}
|
|
|
|
$serendipity['smarty']->assignByRef($smarty_block == 'COMMENTS' ? 'comments' : 'trackbacks', $_smartyComments);
|
|
unset($_smartyComments);
|
|
|
|
return serendipity_smarty_fetch($smarty_block, $smarty_file);
|
|
}
|
|
|
|
/**
|
|
* Fetches and prints a listing of comments by author
|
|
*/
|
|
function serendipity_printCommentsByAuthor() {
|
|
global $serendipity;
|
|
|
|
$type = serendipity_db_escape_string($serendipity['GET']['commentMode']);
|
|
|
|
if ($type == 'comments' || empty($type)) {
|
|
$type = 'NORMAL';
|
|
} elseif ($type == 'trackbacks') {
|
|
$type = 'TRACKBACK';
|
|
} elseif ($type == 'comments_and_trackbacks') {
|
|
$type = '%';
|
|
}
|
|
|
|
if (!empty($serendipity['GET']['viewCommentAuthor'])) {
|
|
$sql_where = " AND co.author = '" . serendipity_db_escape_string($serendipity['GET']['viewCommentAuthor']) . "'";
|
|
$group_by = "GROUP BY co.author";
|
|
} else {
|
|
$sql_where = " AND 1"; // Required fake 'where' condition
|
|
$group_by = "";
|
|
}
|
|
|
|
if (!empty($serendipity['GET']['commentStartTime'])) {
|
|
$sql_where .= " AND co.timestamp >= " . (int)$serendipity['GET']['commentStartTime'];
|
|
}
|
|
|
|
if (!empty($serendipity['GET']['commentEndTime'])) {
|
|
$sql_where .= " AND co.timestamp <= " . (int)$serendipity['GET']['commentEndTime'];
|
|
}
|
|
|
|
if (empty($serendipity['GET']['page'])) {
|
|
$serendipity['GET']['page'] = 1;
|
|
}
|
|
$sql_limit = $serendipity['fetchLimit'] * ($serendipity['GET']['page']-1) . ',' . $serendipity['fetchLimit'];
|
|
$c = serendipity_fetchComments(null, $sql_limit, 'co.entry_id DESC, co.id ASC', false, $type, $sql_where);
|
|
|
|
$entry_comments = array();
|
|
foreach($c as $i => $comment) {
|
|
if (!isset($entry_comments[$comment['entry_id']])) {
|
|
$comment['link'] = serendipity_archiveURL($comment['entry_id'], $comment['title'], 'serendipityHTTPPath', true, array('timestamp' => $comment['entrytimestamp']));
|
|
$entry_comments[$comment['entry_id']] = $comment;
|
|
}
|
|
$entry_comments[$comment['entry_id']]['comments'][] = $comment;
|
|
}
|
|
|
|
foreach($entry_comments AS $entry_id => $_data) {
|
|
$entry_comments[$entry_id]['tpl_comments'] = serendipity_printComments($_data['comments'], VIEWMODE_LINEAR, 0, null, 'COMMENTS', 'comments.tpl');
|
|
}
|
|
|
|
$serendipity['smarty']->assignByRef('comments_by_authors', $entry_comments);
|
|
|
|
if (!empty($id)) {
|
|
$and .= " AND co.entry_id = '" . (int)$id ."'";
|
|
}
|
|
|
|
if (!$showAll) {
|
|
$and .= ' AND co.status = \'approved\'';
|
|
}
|
|
|
|
$fc = "SELECT count(co.id) AS counter
|
|
FROM {$serendipity['dbPrefix']}comments AS co
|
|
WHERE co.entry_id > 0
|
|
AND co.type LIKE '" . $type . "'
|
|
AND co.status = 'approved' " . $sql_where . " "
|
|
. $group_by;
|
|
$cc = serendipity_db_query($fc, true, 'assoc');
|
|
if (!isset($cc['counter'])) {
|
|
$totalComments = 0;
|
|
} else {
|
|
$totalComments = $cc['counter'];
|
|
}
|
|
serendipity_printEntryFooter('', $totalComments);
|
|
|
|
serendipity_smarty_fetch('ENTRIES', 'comments_by_author.tpl');
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Delete a specific comment
|
|
*
|
|
* @access public
|
|
* @param int The ID of the comment to delete
|
|
* @param int The ID of the entry the comment belongs to [safety]
|
|
* @param string The type of a comment (comments/trackback)
|
|
* @param string The 32 character token [if using token based moderation]
|
|
* @return boolean Return whether the action was successful)
|
|
*/
|
|
function serendipity_deleteComment($id, $entry_id, $type='comments', $token=false) {
|
|
global $serendipity;
|
|
|
|
$id = (int)$id;
|
|
$entry_id = (int)$entry_id;
|
|
if ($id < 1 OR $entry_id < 1) {
|
|
return false;
|
|
}
|
|
|
|
$goodtoken = serendipity_checkCommentToken($token, $id);
|
|
|
|
if ($_SESSION['serendipityAuthedUser'] === true || $goodtoken) {
|
|
|
|
$admin = '';
|
|
if (!$goodtoken && !serendipity_checkPermission('adminEntriesMaintainOthers')) {
|
|
$admin = " AND authorid = " . (int)$_SESSION['serendipityAuthorid'];
|
|
|
|
// Load articles author id and check it
|
|
$sql = serendipity_db_query("SELECT authorid FROM {$serendipity['dbPrefix']}entries
|
|
WHERE id = ". $entry_id, true);
|
|
if ($sql['authorid'] != $serendipity['authorid']) {
|
|
return false; // wrong user having no adminEntriesMaintainOthers right
|
|
}
|
|
|
|
}
|
|
|
|
/* We have to figure out if the comment we are about to delete, is awaiting approval,
|
|
if so - we should *not* subtract it from the entries table */
|
|
$sql = serendipity_db_query("SELECT type, status, parent_id, body FROM {$serendipity['dbPrefix']}comments
|
|
WHERE entry_id = ". $entry_id ."
|
|
AND id = ". $id, true);
|
|
|
|
|
|
/* Check to see if the comment has children
|
|
* if it does, don't delete, but replace with "*(COMMENT DELETED)*"
|
|
to delete a tree, delete children first */
|
|
$has_parent = serendipity_db_query("SELECT count(id) AS count
|
|
FROM {$serendipity['dbPrefix']}comments
|
|
WHERE parent_id = ". $id . "
|
|
LIMIT 1", true);
|
|
|
|
if (is_array($has_parent) && isset($has_parent['count']) && $has_parent['count'] > 0 && $sql['body'] != 'COMMENT_DELETED') {
|
|
// Comment has childs, so don't delete it.
|
|
serendipity_db_query("UPDATE {$serendipity['dbPrefix']}comments
|
|
SET body = 'COMMENT_DELETED'
|
|
WHERE id = " . $id);
|
|
} else {
|
|
// Comment has no childs or had already been deleted., it can be safely removed.
|
|
serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}comments
|
|
WHERE entry_id = ". $entry_id ."
|
|
AND id = ". $id);
|
|
|
|
if (is_array($sql) && $sql['status'] !== 'pending') {
|
|
if (!empty($sql['type']) && $sql['type'] != 'NORMAL') {
|
|
$type = 'trackbacks';
|
|
} else {
|
|
$type = 'comments';
|
|
}
|
|
serendipity_db_query("UPDATE {$serendipity['dbPrefix']}entries SET $type = $type-1 WHERE id = ". $entry_id ." AND $type > 0 $admin");
|
|
}
|
|
|
|
serendipity_db_query("UPDATE {$serendipity['dbPrefix']}comments SET parent_id = " . (int)$sql['parent_id'] . " WHERE parent_id = " . $id);
|
|
}
|
|
|
|
$addData = array('cid' => $id, 'entry_id' => $entry_id);
|
|
serendipity_plugin_api::hook_event('backend_deletecomment', $sql, $addData);
|
|
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Toggle whether an entry allows comments
|
|
*
|
|
* @access public
|
|
* @param int The ID of the entry where the switch shall be toggled
|
|
* @param string Whether the entry shall be opened or closed for comments
|
|
* @return null
|
|
*/
|
|
function serendipity_allowCommentsToggle($entry_id, $switch = 'disable') {
|
|
global $serendipity;
|
|
|
|
if ($_SESSION['serendipityAuthedUser'] === true) {
|
|
$admin = '';
|
|
if (!serendipity_checkPermission('adminEntriesMaintainOthers')) {
|
|
$admin = " AND authorid = " . (int)$_SESSION['serendipityAuthorid'];
|
|
}
|
|
|
|
$query = "UPDATE {$serendipity['dbPrefix']}entries SET allow_comments = '" . ($switch == 'disable' ? 'false' : 'true') . "' WHERE id = '". (int)$entry_id ."' $admin";
|
|
serendipity_db_query($query);
|
|
if (serendipity_isResponseClean($_SERVER['HTTP_REFERER'])) {
|
|
header('Status: 302 Found');
|
|
header('Location: '. $_SERVER['HTTP_REFERER']);
|
|
exit;
|
|
}
|
|
} else {
|
|
die('What are you up to? You need to be an admin to close comments');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Approve a comment
|
|
*
|
|
* LONG
|
|
*
|
|
* @access public
|
|
* @param int The ID of the comment to approve
|
|
* @param int The ID of the entry a comment belongs to
|
|
* @param boolean Whether to force approving a comment despite of its current status
|
|
* @param boolean If set to true, a comment will be moderated instead of approved.
|
|
* @param string The 32 character token [if using token based moderation]
|
|
* @return boolean Success or failure
|
|
*/
|
|
function serendipity_approveComment($cid, $entry_id, $force = false, $moderate = false, $token = false) {
|
|
global $serendipity;
|
|
|
|
$goodtoken = serendipity_checkCommentToken($token, $cid);
|
|
|
|
/* Get data about the comment, we need this query because this function can be called from anywhere */
|
|
/* This also makes sure we are either the author of the comment, or a USERLEVEL_ADMIN */
|
|
$sql = "SELECT c.*, e.title, a.email as authoremail, a.mail_comments, e.timestamp AS entry_timestamp, e.last_modified AS entry_last_modified, e.authorid AS entry_authorid
|
|
FROM {$serendipity['dbPrefix']}comments c
|
|
LEFT JOIN {$serendipity['dbPrefix']}entries e ON (e.id = c.entry_id)
|
|
LEFT JOIN {$serendipity['dbPrefix']}authors a ON (e.authorid = a.authorid)
|
|
WHERE c.id = '". (int)$cid ."'
|
|
". ((!serendipity_checkPermission('adminEntriesMaintainOthers') && $force !== true && !$goodtoken) ? "AND e.authorid = '". (int)$serendipity['authorid'] ."'" : '') ."
|
|
". (($force === true) ? "" : "AND status = 'pending'");
|
|
$rs = serendipity_db_query($sql, true);
|
|
|
|
// Check for adminEntriesMaintainOthers
|
|
if (!$force && !$goodtoken && $rs['entry_authorid'] != $serendipity['authorid'] && !serendipity_checkPermission('adminEntriesMaintainOthers')) {
|
|
return false; // wrong user having no adminEntriesMaintainOthers right
|
|
}
|
|
|
|
$flip = false;
|
|
if ($moderate === 'flip') {
|
|
$flip = true;
|
|
|
|
if ($rs['status'] == 'pending') {
|
|
$sql = "UPDATE {$serendipity['dbPrefix']}comments SET status = 'approved' WHERE id = ". (int)$cid;
|
|
$moderate = false;
|
|
} else {
|
|
$sql = "UPDATE {$serendipity['dbPrefix']}comments SET status = 'pending' WHERE id = ". (int)$cid;
|
|
$moderate = true;
|
|
}
|
|
} elseif ($moderate) {
|
|
$sql = "UPDATE {$serendipity['dbPrefix']}comments SET status = 'pending' WHERE id = ". (int)$cid;
|
|
} else {
|
|
$sql = "UPDATE {$serendipity['dbPrefix']}comments SET status = 'approved' WHERE id = ". (int)$cid;
|
|
}
|
|
serendipity_db_query($sql);
|
|
|
|
$field = ($rs['type'] == 'NORMAL' ? 'comments' : 'trackbacks');
|
|
// Check when the entry was published. If it is older than max_last_modified allows, the last_modified date of that entry
|
|
// will not be pushed. With this we make sure that an RSS feed will not be updated on a client's reader and marked as new
|
|
// only because someone made an comment to an old entry.
|
|
if ($rs['entry_timestamp'] > time() - $serendipity['max_last_modified']) {
|
|
$lm = time();
|
|
} else {
|
|
$lm = (int)$rs['entry_last_modified'];
|
|
}
|
|
|
|
$counter_comments = serendipity_db_query("SELECT count(id) AS counter
|
|
FROM {$serendipity['dbPrefix']}comments
|
|
WHERE status = 'approved'
|
|
AND type = 'NORMAL'
|
|
AND entry_id = " . (int)$entry_id . "
|
|
GROUP BY entry_id", true);
|
|
|
|
$counter_tb = serendipity_db_query("SELECT count(id) AS counter
|
|
FROM {$serendipity['dbPrefix']}comments
|
|
WHERE status = 'approved'
|
|
AND (type = 'TRACKBACK' or type = 'PINGBACK')
|
|
AND entry_id = " . (int)$entry_id . "
|
|
GROUP BY entry_id", true);
|
|
|
|
$query = "UPDATE {$serendipity['dbPrefix']}entries
|
|
SET comments = " . (int)$counter_comments['counter'] . ",
|
|
trackbacks = " . (int)$counter_tb['counter'] . ",
|
|
last_modified = ". $lm ."
|
|
WHERE id = ". (int)$entry_id;
|
|
serendipity_db_query($query);
|
|
|
|
/* It's already approved, don't spam people */
|
|
if ( $rs === false ) {
|
|
return false;
|
|
}
|
|
|
|
if (!$moderate) {
|
|
if ($serendipity['allowSubscriptions'] === 'fulltext') {
|
|
serendipity_mailSubscribers($entry_id, $rs['author'], $rs['email'], $rs['title'], $rs['authoremail'], $cid, $rs['body']);
|
|
} elseif (serendipity_db_bool($serendipity['allowSubscriptions'])) {
|
|
serendipity_mailSubscribers($entry_id, $rs['author'], $rs['email'], $rs['title'], $rs['authoremail'], $cid);
|
|
}
|
|
|
|
serendipity_plugin_api::hook_event('backend_approvecomment', $rs);
|
|
}
|
|
|
|
if ($flip) {
|
|
if ($moderate) return -1; // comment set to pending
|
|
if (!$moderate) return 1; // comment set to approved
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Confirm a mail authentication request
|
|
*
|
|
* @access public
|
|
* @param int The ID of a comment
|
|
* @param string The confirmation hash
|
|
* @return boolean
|
|
*/
|
|
function serendipity_confirmMail($cid, $hash) {
|
|
global $serendipity;
|
|
|
|
$q = "SELECT c.entry_id, e.title, e.timestamp, e.id
|
|
FROM {$serendipity['dbPrefix']}comments AS c
|
|
JOIN {$serendipity['dbPrefix']}entries AS e
|
|
ON (e.id = c.entry_id)
|
|
WHERE c.status = 'confirm" . serendipity_db_escape_string($hash) . "'
|
|
AND c.id = '" . (int)$cid . "'";
|
|
$confirm = serendipity_db_query($q, true);
|
|
|
|
if ($confirm['entry_id'] > 0) {
|
|
serendipity_db_query("UPDATE {$serendipity['dbPrefix']}options
|
|
SET okey = 'mail_confirm'
|
|
WHERE okey = 'mail_confirm" . serendipity_db_escape_string($hash) . "'");
|
|
|
|
serendipity_db_query("UPDATE {$serendipity['dbPrefix']}comments
|
|
SET status = 'pending'
|
|
WHERE status = 'confirm" . serendipity_db_escape_string($hash) . "'
|
|
AND id = '" . (int)$cid . "'");
|
|
|
|
// TODO?
|
|
/* if (serendipity_db_bool($confirm['mail_comments'])) {
|
|
serendipity_sendComment($cid, $row['email'], $name, $email, $url, $id, $row['title'], $comments, $type, serendipity_db_bool($ca['moderate_comments']));
|
|
}
|
|
*/
|
|
|
|
serendipity_approveComment($cid, $confirm['entry_id'], true);
|
|
return $confirm;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Store the comment made by a visitor in the database
|
|
*
|
|
* @access public
|
|
* @param int The ID of an entry
|
|
* @param array An array that holds the input data from the visitor
|
|
* @param string The type of a comment (normal/trackback)
|
|
* @param string Where did a comment come from? (internal|trackback|plugin)
|
|
* @param string Additional plugin data (spamblock plugin etc.)
|
|
* @return boolean Returns true if the comment could be added
|
|
*/
|
|
function serendipity_insertComment($id, $commentInfo, $type = 'NORMAL', $source = 'internal', $ca = array()) {
|
|
global $serendipity;
|
|
|
|
if (!empty($ca['status'])) {
|
|
$commentInfo['status'] = $ca['status'];
|
|
}
|
|
|
|
if ($serendipity['serendipityAuthedUser']) {
|
|
$authorReply = true;
|
|
$authorEmail = $serendipity['serendipityEmail'];
|
|
}
|
|
|
|
$title = serendipity_db_escape_string(isset($commentInfo['title']) ? $commentInfo['title'] : '');
|
|
$comments = $commentInfo['comment'];
|
|
$ip = serendipity_db_escape_string(isset($commentInfo['ip']) ? $commentInfo['ip'] : $_SERVER['REMOTE_ADDR']);
|
|
$commentsFixed = serendipity_db_escape_string($commentInfo['comment']);
|
|
$name = serendipity_db_escape_string($commentInfo['name']);
|
|
$url = serendipity_db_escape_string($commentInfo['url']);
|
|
$email = serendipity_db_escape_string($commentInfo['email']);
|
|
$parentid = (isset($commentInfo['parent_id']) && is_numeric($commentInfo['parent_id'])) ? $commentInfo['parent_id'] : 0;
|
|
$status = serendipity_db_escape_string(isset($commentInfo['status']) ? $commentInfo['status'] : (serendipity_db_bool($ca['moderate_comments']) ? 'pending' : 'approved'));
|
|
$t = serendipity_db_escape_string(isset($commentInfo['time']) ? $commentInfo['time'] : time());
|
|
$referer = substr((isset($_SESSION['HTTP_REFERER']) ? serendipity_db_escape_string($_SESSION['HTTP_REFERER']) : ''), 0, 200);
|
|
|
|
$query = "SELECT a.email, e.title, a.mail_comments, a.mail_trackbacks
|
|
FROM {$serendipity['dbPrefix']}entries AS e
|
|
LEFT OUTER JOIN {$serendipity['dbPrefix']}authors AS a
|
|
ON a.authorid = e.authorid
|
|
WHERE e.id = '". (int)$id ."'
|
|
AND e.isdraft = 'false'";
|
|
if (!serendipity_db_bool($serendipity['showFutureEntries'])) {
|
|
$query .= " AND e.timestamp <= " . serendipity_db_time();
|
|
}
|
|
|
|
$row = serendipity_db_query($query, true); // Get info on author/entry
|
|
if (!is_array($row) || empty($id)) {
|
|
// No associated entry found.
|
|
if ($GLOBALS['tb_logging']) {
|
|
$fp = fopen('trackback2.log', 'a');
|
|
fwrite($fp, '[' . date('d.m.Y H:i') . '] entry reference not found: ' . $query . "\n");
|
|
fclose($fp);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
$send_optin = false;
|
|
if (isset($commentInfo['subscribe'])) {
|
|
if (!isset($serendipity['allowSubscriptionsOptIn']) || $serendipity['allowSubscriptionsOptIn']) {
|
|
$subscribe = 'false';
|
|
$send_optin = true;
|
|
} else {
|
|
$subscribe = 'true';
|
|
}
|
|
} else {
|
|
$subscribe = 'false';
|
|
}
|
|
|
|
$dbhash = md5(uniqid(rand(), true));
|
|
|
|
if ($status == 'confirm') {
|
|
$dbstatus = 'confirm' . $dbhash;
|
|
} elseif ($status == 'confirm1') {
|
|
$auth = serendipity_db_query("SELECT *
|
|
FROM {$serendipity['dbPrefix']}options
|
|
WHERE okey = 'mail_confirm'
|
|
AND name = '" . $email . "'
|
|
AND value = '" . $name . "'", true);
|
|
if (!is_array($auth)) {
|
|
serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}options (okey, name, value)
|
|
VALUES ('mail_confirm{$dbhash}', '{$email}', '{$name}')");
|
|
$dbstatus = 'confirm' . $dbhash;
|
|
} else {
|
|
$serendipity['csuccess'] = 'true';
|
|
$status = $dbstatus = 'approved';
|
|
}
|
|
} else {
|
|
$dbstatus = $status;
|
|
}
|
|
|
|
$query = "INSERT INTO {$serendipity['dbPrefix']}comments (entry_id, parent_id, ip, author, email, url, body, type, timestamp, title, subscribed, status, referer)";
|
|
$query .= " VALUES ('". (int)$id ."', '$parentid', '$ip', '$name', '$email', '$url', '$commentsFixed', '$type', '$t', '$title', '$subscribe', '$dbstatus', '$referer')";
|
|
|
|
if ($GLOBALS['tb_logging']) {
|
|
$fp = fopen('trackback2.log', 'a');
|
|
fwrite($fp, '[' . date('d.m.Y H:i') . '] SQL: ' . $query . "\n");
|
|
}
|
|
|
|
serendipity_db_query($query);
|
|
$cid = serendipity_db_insert_id('comments', 'id');
|
|
|
|
// Send mail to the author if he chose to receive these mails, or if the comment is awaiting moderation
|
|
if ($status != 'confirm' && (serendipity_db_bool($ca['moderate_comments'])
|
|
|| ($type == 'NORMAL' && serendipity_db_bool($row['mail_comments']))
|
|
|| (($type == 'TRACKBACK' || $type == 'PINGBACK') && serendipity_db_bool($row['mail_trackbacks'])))) {
|
|
if (! ($authorReply && $authorEmail == $row['email'])) {
|
|
serendipity_sendComment($cid, $row['email'], $name, $email, $url, $id, $row['title'], $comments, $type, serendipity_db_bool($ca['moderate_comments']), $referer);
|
|
}
|
|
}
|
|
|
|
// Approve with force, if moderation is disabled
|
|
if ($GLOBALS['tb_logging']) {
|
|
fwrite($fp, '[' . date('d.m.Y H:i') . '] status: ' . $status . ', moderate: ' . $ca['moderate_comments'] . "\n");
|
|
}
|
|
|
|
if ($status != 'confirm' && (empty($ca['moderate_comments']) || serendipity_db_bool($ca['moderate_comments']) == false)) {
|
|
if ($GLOBALS['tb_logging']) {
|
|
fwrite($fp, '[' . date('d.m.Y H:i') . '] Approving...' . "\n");
|
|
}
|
|
serendipity_approveComment($cid, $id, true);
|
|
} elseif ($GLOBALS['tb_logging']) {
|
|
fwrite($fp, '[' . date('d.m.Y H:i') . '] No need to approve...' . "\n");
|
|
}
|
|
|
|
if ($status == 'confirm') {
|
|
$subject = sprintf(NEW_COMMENT_TO_SUBSCRIBED_ENTRY, $row['title']);
|
|
$message = sprintf(CONFIRMATION_MAIL_ALWAYS,
|
|
$name,
|
|
$row['title'],
|
|
$commentsFixed,
|
|
$serendipity['baseURL'] . 'comment.php?c=' . $cid . '&hash=' . $dbhash);
|
|
|
|
serendipity_sendMail($email, $subject, $message, $serendipity['blogMail']);
|
|
} elseif ($status == 'confirm1') {
|
|
$subject = sprintf(NEW_COMMENT_TO_SUBSCRIBED_ENTRY, $row['title']);
|
|
$message = sprintf(CONFIRMATION_MAIL_ONCE,
|
|
$name,
|
|
$row['title'],
|
|
$commentsFixed,
|
|
$serendipity['baseURL'] . 'comment.php?c=' . $cid . '&hash=' . $dbhash);
|
|
|
|
serendipity_sendMail($email, $subject, $message, $serendipity['blogMail']);
|
|
}
|
|
|
|
if ($send_optin) {
|
|
$dupe_check = serendipity_db_query("SELECT count(entry_id) AS counter
|
|
FROM {$serendipity['dbPrefix']}comments
|
|
WHERE entry_id = " . (int)$id . "
|
|
AND email = '$email'
|
|
AND subscribed = 'true'", true);
|
|
if (!is_array($dupe_check) || $dupe_check['counter'] < 1) {
|
|
serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}options (okey, name, value)
|
|
VALUES ('commentsub_{$dbhash}', '" . time() . "', '{$cid}')");
|
|
|
|
$subject = sprintf(NEW_COMMENT_TO_SUBSCRIBED_ENTRY, $row['title']);
|
|
$message = sprintf(CONFIRMATION_MAIL_SUBSCRIPTION,
|
|
$name,
|
|
$row['title'],
|
|
serendipity_archiveURL($id, $row['title'], 'baseURL'),
|
|
$serendipity['baseURL'] . 'comment.php?optin=' . $dbhash);
|
|
|
|
serendipity_sendMail($email, $subject, $message, $serendipity['blogMail']);
|
|
}
|
|
}
|
|
|
|
serendipity_purgeEntry($id, $t);
|
|
|
|
if ($GLOBALS['tb_logging']) {
|
|
fclose($fp);
|
|
}
|
|
|
|
return $cid;
|
|
}
|
|
|
|
/**
|
|
* Confirm a comment subscription
|
|
*
|
|
* @access public
|
|
* @param string The confirmation hash
|
|
* @return boolean
|
|
*/
|
|
function serendipity_commentSubscriptionConfirm($hash) {
|
|
global $serendipity;
|
|
|
|
// Delete possible current cookie. Also delete any confirmation hashs that smell like 3-week-old, dead fish.
|
|
if (stristr($serendipity['dbType'], 'sqlite')) {
|
|
$cast = "name";
|
|
} else {
|
|
// Adds explicits casting for mysql, postgresql and others.
|
|
$cast = "cast(name as integer)";
|
|
}
|
|
|
|
serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}options
|
|
WHERE okey LIKE 'commentsub_%' AND $cast < " . (time() - 1814400) . ")");
|
|
|
|
$hashinfo = serendipity_db_query("SELECT value
|
|
FROM {$serendipity['dbPrefix']}options
|
|
WHERE okey = 'commentsub_" . serendipity_db_escape_string($hash) . "'", true);
|
|
if (is_array($hashinfo) && $hashinfo['value'] > 0) {
|
|
$cid = (int)$hashinfo['value'];
|
|
serendipity_db_query("UPDATE {$serendipity['dbPrefix']}comments
|
|
SET subscribed = 'true'
|
|
WHERE id = $cid");
|
|
|
|
serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}options
|
|
WHERE okey = 'commentsub_" . serendipity_db_escape_string($hash) . "'");
|
|
|
|
return $cid;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save a comment made by a visitor
|
|
*
|
|
* @access public
|
|
* @param int The ID of an entry
|
|
* @param array An array that holds the input data from the visitor
|
|
* @param string The type of a comment (normal/trackback)
|
|
* @param string Where did a comment come from? (internal|trackback|plugin)
|
|
* @return boolean Returns true if the comment could be added
|
|
*/
|
|
function serendipity_saveComment($id, $commentInfo, $type = 'NORMAL', $source = 'internal') {
|
|
global $serendipity;
|
|
|
|
$query = "SELECT id, allow_comments, moderate_comments, last_modified, timestamp, title FROM {$serendipity['dbPrefix']}entries WHERE id = '". (int)$id ."'";
|
|
$ca = serendipity_db_query($query, true);
|
|
|
|
$commentInfo['type'] = $type;
|
|
$commentInfo['source'] = $source;
|
|
|
|
// Secure email addresses, only one [first] allowed to not mail to multiple recipients
|
|
$mailparts = explode(',', $commentInfo['email']);
|
|
$commentInfo['email'] = trim($mailparts[0]);
|
|
|
|
serendipity_plugin_api::hook_event('frontend_saveComment', $ca, $commentInfo);
|
|
if (!is_array($ca) || serendipity_db_bool($ca['allow_comments'])) {
|
|
if ($GLOBALS['tb_logging']) {
|
|
$fp = fopen('trackback2.log', 'a');
|
|
fwrite($fp, '[' . date('d.m.Y H:i') . '] insert comment into DB' . "\n");
|
|
fclose($fp);
|
|
}
|
|
|
|
$commentInfo['comment_cid'] = serendipity_insertComment($id, $commentInfo, $type, $source, $ca);
|
|
$commentInfo['comment_id'] = $id;
|
|
serendipity_plugin_api::hook_event('frontend_saveComment_finish', $ca, $commentInfo);
|
|
return true;
|
|
} else {
|
|
if ($GLOBALS['tb_logging']) {
|
|
$fp = fopen('trackback2.log', 'a');
|
|
fwrite($fp, '[' . date('d.m.Y H:i') . '] discarding comment from DB' . "\n");
|
|
fclose($fp);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send a mail to all subscribers of an entry about a new comment
|
|
*
|
|
* @access public
|
|
* @param int The ID of the entry where a new comment has been made
|
|
* @param string The name of the latest poster to an entry
|
|
* @param string The email addre ssof the latest poster to an entry
|
|
* @param string The title of the entry
|
|
* @param string The mail address used to send emails from
|
|
* @param int The ID of the comment that has been made
|
|
* @param string The body of the comment that has been made
|
|
* @return null
|
|
*/
|
|
function serendipity_mailSubscribers($entry_id, $poster, $posterMail, $title, $fromEmail = 'none@example.com', $cid = null, $body = null) {
|
|
global $serendipity;
|
|
|
|
$entryURI = serendipity_archiveURL($entry_id, $title, 'baseURL') . ($cid > 0 ? '#c' . $cid : '');
|
|
$subject = sprintf(NEW_COMMENT_TO_SUBSCRIBED_ENTRY, $title);
|
|
|
|
$pgsql_insert = '';
|
|
$mysql_insert = '';
|
|
if ($serendipity['dbType'] == 'postgres' ||
|
|
$serendipity['dbType'] == 'pdo-postgres') {
|
|
$pgsql_insert = 'DISTINCT ON (email)';
|
|
} else {
|
|
$mysql_insert = 'GROUP BY email';
|
|
}
|
|
|
|
$sql = "SELECT $pgsql_insert author, email, type
|
|
FROM {$serendipity['dbPrefix']}comments
|
|
WHERE entry_id = '". (int)$entry_id ."'
|
|
AND email <> '" . serendipity_db_escape_string($posterMail) . "'
|
|
AND email <> ''
|
|
AND subscribed = 'true' $mysql_insert";
|
|
$subscribers = serendipity_db_query($sql);
|
|
|
|
if (!is_array($subscribers)) {
|
|
return;
|
|
}
|
|
|
|
foreach ($subscribers as $subscriber) {
|
|
if ($subscriber['type'] == 'TRACKBACK') {
|
|
$text = sprintf(
|
|
SUBSCRIPTION_TRACKBACK_MAIL,
|
|
|
|
$subscriber['author'],
|
|
$serendipity['blogTitle'],
|
|
$title,
|
|
$poster,
|
|
($body ? "\n\n" . $body . "\n" : '') . $entryURI,
|
|
serendipity_rewriteURL('unsubscribe/' . urlencode($subscriber['email']) . '/' . (int)$entry_id, 'baseURL')
|
|
);
|
|
} else {
|
|
$text = sprintf(
|
|
SUBSCRIPTION_MAIL,
|
|
|
|
$subscriber['author'],
|
|
$serendipity['blogTitle'],
|
|
$title,
|
|
$poster,
|
|
($body ? "\n\n" . $body . "\n" : '') . $entryURI,
|
|
serendipity_rewriteURL('unsubscribe/' . urlencode($subscriber['email']) . '/' . (int)$entry_id, 'baseURL')
|
|
);
|
|
}
|
|
|
|
serendipity_sendMail($subscriber['email'], $subject, $text, $fromEmail);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cancel a subscription to an entry
|
|
*
|
|
* @access public
|
|
* @param string E-Mail address to cancel subscription
|
|
* @param int The entry ID to unsubscribe from
|
|
* @return int Return number of unsubscriptions
|
|
*/
|
|
function serendipity_cancelSubscription($email, $entry_id) {
|
|
global $serendipity;
|
|
$sql = "UPDATE {$serendipity['dbPrefix']}comments
|
|
SET subscribed = 'false'
|
|
WHERE entry_id = '". (int)$entry_id ."'
|
|
AND email = '" . serendipity_db_escape_string($email) . "'";
|
|
serendipity_db_query($sql);
|
|
|
|
return serendipity_db_affected_rows();
|
|
}
|
|
|
|
/**
|
|
* Send a comment notice to the admin/author of an entry
|
|
*
|
|
* @access public
|
|
* @param int ID of the comment that has been made
|
|
* @param string Author's email address to send the mail to
|
|
* @param string The name of the sender
|
|
* @param string The URL of the sender
|
|
* @param int The ID of the entry that has been commented
|
|
* @param string The title of the entry that has been commented
|
|
* @param string The text of the comment
|
|
* @param string The type of the comment (normal|trackback)
|
|
* @param boolean Toggle Whether comments to this entry need approval
|
|
* @return boolean Return success of sending the mails
|
|
*/
|
|
function serendipity_sendComment($comment_id, $to, $fromName, $fromEmail, $fromUrl, $id, $title, $comment, $type = 'NORMAL', $moderate_comment = false, $referer = '') {
|
|
global $serendipity;
|
|
|
|
if (empty($fromName)) {
|
|
$fromName = ANONYMOUS;
|
|
}
|
|
|
|
$entryURI = serendipity_archiveURL($id, $title, 'baseURL');
|
|
$path = ($type == 'TRACKBACK' || $type == 'PINGBACK') ? 'trackback' : 'comment';
|
|
|
|
// Check for using Tokens
|
|
if ($serendipity['useCommentTokens']) {
|
|
$token = serendipity_generateCToken($comment_id);
|
|
$path = $path . "_token_" . $token;
|
|
|
|
}
|
|
|
|
$deleteURI = serendipity_rewriteURL(PATH_DELETE . '/'. $path .'/' . $comment_id . '/' . $id . '-' . serendipity_makeFilename($title) . '.html', 'baseURL');
|
|
$approveURI = serendipity_rewriteURL(PATH_APPROVE . '/'. $path .'/' . $comment_id . '/' . $id . '-' . serendipity_makeFilename($title) . '.html', 'baseURL');
|
|
|
|
$eventData = array( 'comment_id' => $comment_id,
|
|
'entry_id' => $id,
|
|
'entryURI' => $entryURI,
|
|
'path' => $path,
|
|
'deleteURI' => $deleteURI,
|
|
'approveURI' => $approveURI,
|
|
'moderate_comment' => $moderate_comment,
|
|
'action_more' => array());
|
|
serendipity_plugin_api::hook_event('backend_sendcomment', $eventData);
|
|
|
|
$action_more = '';
|
|
foreach($eventData['action_more'] as $action) {
|
|
$action_more .= "\n" . str_repeat(' ', 3) . $action;
|
|
}
|
|
|
|
if ($type == 'TRACKBACK' || $type == 'PINGBACK') {
|
|
|
|
/******************* TRACKBACKS *******************/
|
|
$subject = ($moderate_comment ? '[' . REQUIRES_REVIEW . '] ' : '') . NEW_TRACKBACK_TO . ' ' . $title;
|
|
$text = sprintf(A_NEW_TRACKBACK_BLAHBLAH, $title)
|
|
. "\n"
|
|
. "\n" . REQUIRES_REVIEW . ': ' . (($moderate_comment) ? YES : NO) . (isset($serendipity['moderate_reason']) ? ' (' . $serendipity['moderate_reason'] . ')' : '')
|
|
. "\n" . LINK_TO_ENTRY . ': ' . $entryURI
|
|
. "\n" . WEBLOG . ': ' . stripslashes($fromName)
|
|
. "\n" . LINK_TO_REMOTE_ENTRY . ': ' . $fromUrl
|
|
. "\n"
|
|
. "\n" . EXCERPT . ':'
|
|
. "\n" . strip_tags($comment)
|
|
. "\n"
|
|
. "\n" . '----'
|
|
. "\n" . YOU_HAVE_THESE_OPTIONS
|
|
. (($moderate_comment) ? "\n" . str_repeat(' ', 2) . THIS_TRACKBACK_NEEDS_REVIEW : '')
|
|
. "\n" . str_repeat(' ', 3) . str_pad(VIEW_ENTRY, 15) . ' -- '. $entryURI
|
|
. "\n" . str_repeat(' ', 3) . str_pad(DELETE_TRACKBACK, 15) . ' -- '. $deleteURI
|
|
. (($moderate_comment) ? "\n" . str_repeat(' ', 3) . str_pad(APPROVE_TRACKBACK, 15) . ' -- '. $approveURI : '')
|
|
. $action_more;
|
|
|
|
} else {
|
|
|
|
/******************* COMMENTS *********************/
|
|
$subject = ($moderate_comment ? '[' . REQUIRES_REVIEW . '] ' : '') . NEW_COMMENT_TO . ' ' . $title;
|
|
$text = sprintf(A_NEW_COMMENT_BLAHBLAH, $serendipity['blogTitle'], $title)
|
|
. "\n" . LINK_TO_ENTRY . ': ' . $entryURI
|
|
. "\n"
|
|
. "\n" . REQUIRES_REVIEW . ': ' . (($moderate_comment) ? YES : NO) . (isset($serendipity['moderate_reason']) ? ' (' . $serendipity['moderate_reason'] . ')' : '')
|
|
. "\n" . IP_ADDRESS . ': ' . $_SERVER['REMOTE_ADDR']
|
|
. "\n" . NAME . ': ' . $fromName
|
|
. "\n" . EMAIL . ': ' . $fromEmail
|
|
. "\n" . HOMEPAGE . ': ' . $fromUrl
|
|
. "\n" . REFERER . ': ' . $referer
|
|
. "\n"
|
|
. "\n" . COMMENTS . ': '
|
|
. "\n" . strip_tags($comment)
|
|
. "\n"
|
|
. "\n" . '----'
|
|
. "\n" . YOU_HAVE_THESE_OPTIONS
|
|
. (($moderate_comment) ? "\n" . str_repeat(' ', 2) . THIS_COMMENT_NEEDS_REVIEW : '')
|
|
. "\n" . str_repeat(' ', 3) . str_pad(VIEW_COMMENT, 15) . ' -- '. $entryURI .'#c'. $comment_id
|
|
. "\n" . str_repeat(' ', 3) . str_pad(DELETE_COMMENT, 15) . ' -- '. $deleteURI
|
|
. (($moderate_comment) ? "\n" . str_repeat(' ', 3) . str_pad(APPROVE_COMMENT, 15) . ' -- '. $approveURI : '')
|
|
. $action_more;
|
|
}
|
|
|
|
return serendipity_sendMail($to, $subject, $text, $fromEmail, null, $fromName);
|
|
}
|
|
|
|
/**
|
|
* Generates a token for E-Mail moderation of comments
|
|
* and stores it in the database
|
|
*
|
|
* @access public
|
|
* @param int ID of the comment to generate the token for
|
|
* @return string The generated token
|
|
*/
|
|
function serendipity_generateCToken($cid) {
|
|
|
|
global $serendipity;
|
|
|
|
$ctoken = md5(uniqid(rand(),1));
|
|
|
|
//Delete any comment tokens older than 1 week.
|
|
serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}options
|
|
WHERE okey LIKE 'comment_%' AND name < " . (time() - 604800) );
|
|
|
|
// Issue new comment moderation hash
|
|
serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}options (name, value, okey)
|
|
VALUES ('" . time() . "', '" . $ctoken . "', 'comment_" . $cid ."')");
|
|
return $ctoken;
|
|
|
|
} |