torrentpier/library/ajax/posts.php
Roman Kelesidis 411a756085
Some security enhancements (#1505)
* Some security enhancements

* Update CHANGELOG.md
2024-06-12 13:12:25 +07:00

290 lines
13 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
if (!defined('IN_AJAX')) {
die(basename(__FILE__));
}
global $lang, $bb_cfg, $userdata, $wordCensor;
if (!isset($this->request['type'])) {
$this->ajax_die('empty type');
}
if (isset($this->request['post_id'])) {
$post_id = (int)$this->request['post_id'];
$post = DB()->fetch_row("SELECT t.*, f.*, p.*, pt.post_text
FROM " . BB_TOPICS . " t, " . BB_FORUMS . " f, " . BB_POSTS . " p, " . BB_POSTS_TEXT . " pt
WHERE p.post_id = $post_id
AND t.topic_id = p.topic_id
AND f.forum_id = t.forum_id
AND p.post_id = pt.post_id
LIMIT 1");
if (!$post) {
$this->ajax_die('not post');
}
$is_auth = auth(AUTH_ALL, $post['forum_id'], $userdata, $post);
if ($post['topic_status'] == TOPIC_LOCKED && !$is_auth['auth_mod']) {
$this->ajax_die($lang['TOPIC_LOCKED']);
}
} elseif (isset($this->request['topic_id'])) {
$topic_id = (int)$this->request['topic_id'];
$post = DB()->fetch_row("SELECT t.*, f.*
FROM " . BB_TOPICS . " t, " . BB_FORUMS . " f
WHERE t.topic_id = $topic_id
AND f.forum_id = t.forum_id
LIMIT 1");
if (!$post) {
$this->ajax_die($lang['INVALID_TOPIC_ID_DB']);
}
$is_auth = auth(AUTH_ALL, $post['forum_id'], $userdata, $post);
}
switch ($this->request['type']) {
case 'delete':
if ($post['post_id'] != $post['topic_first_post_id'] && $is_auth['auth_delete'] && ($is_auth['auth_mod'] || ($userdata['user_id'] == $post['poster_id'] && $post['topic_last_post_id'] == $post['post_id'] && $post['post_time'] + 3600 * 3 > TIMENOW))) {
if (empty($this->request['confirmed'])) {
$this->prompt_for_confirm($lang['CONFIRM_DELETE']);
}
\TorrentPier\Legacy\Admin\Common::post_delete($post_id);
// Update atom feed
update_atom('topic', (int)$this->request['topic_id']);
$this->response['hide'] = true;
$this->response['post_id'] = $post_id;
} else {
$this->ajax_die(sprintf($lang['SORRY_AUTH_DELETE'], strip_tags($is_auth['auth_delete_type'])));
}
break;
case 'reply':
if (bf($userdata['user_opt'], 'user_opt', 'dis_post')) {
$this->ajax_die($lang['RULES_REPLY_CANNOT']);
} elseif (!$is_auth['auth_reply']) {
$this->ajax_die(sprintf($lang['SORRY_AUTH_REPLY'], strip_tags($is_auth['auth_reply_type'])));
}
$quote_username = ($post['post_username'] != '') ? $post['post_username'] : get_username($post['poster_id']);
$message = "[quote=\"" . $quote_username . "\"][qpost=" . $post['post_id'] . "]" . $post['post_text'] . "[/quote]\r";
// hide user passkey
$message = preg_replace('#(?<=[\?&;]' . $bb_cfg['passkey_key'] . '=)[a-zA-Z0-9]#', 'passkey', $message);
// hide sid
$message = preg_replace('#(?<=[\?&;]sid=)[a-zA-Z0-9]#', 'sid', $message);
$message = $wordCensor->censorString($message);
if ($post['post_id'] == $post['topic_first_post_id']) {
$message = "[quote]" . $post['topic_title'] . "[/quote]\r";
}
if (mb_strlen($message, 'UTF-8') > 1000) {
$this->response['redirect'] = make_url(POSTING_URL . '?mode=quote&' . POST_POST_URL . '=' . $post_id);
}
$this->response['quote'] = true;
$this->response['message'] = $message;
break;
case 'view_message':
$message = (string)$this->request['message'];
if (!trim($message)) {
$this->ajax_die($lang['EMPTY_MESSAGE']);
}
$message = htmlCHR($message, false, ENT_NOQUOTES);
$this->response['message_html'] = bbcode2html($message);
$this->response['res_id'] = @$this->request['res_id'];
break;
case 'edit':
case 'editor':
if (bf($userdata['user_opt'], 'user_opt', 'dis_post_edit')) {
$this->ajax_die($lang['POST_EDIT_CANNOT']);
}
if ($post['poster_id'] != $userdata['user_id'] && !$is_auth['auth_mod']) {
$this->ajax_die($lang['EDIT_OWN_POSTS']);
}
if ((mb_strlen($post['post_text'], 'UTF-8') > 1000) || $post['post_attachment'] || ($post['topic_first_post_id'] == $post_id)) {
$this->response['redirect'] = make_url(POSTING_URL . '?mode=editpost&' . POST_POST_URL . '=' . $post_id);
} elseif ($this->request['type'] == 'editor') {
$text = (string)$this->request['text'];
$text = prepare_message($text);
if (mb_strlen($text) > 2) {
if ($text != $post['post_text']) {
if ($bb_cfg['max_smilies']) {
$count_smilies = substr_count(bbcode2html($text), '<img class="smile" src="' . $bb_cfg['smilies_path']);
if ($count_smilies > $bb_cfg['max_smilies']) {
$this->ajax_die(sprintf($lang['MAX_SMILIES_PER_POST'], $bb_cfg['max_smilies']));
}
}
DB()->query("UPDATE " . BB_POSTS_TEXT . " SET post_text = '" . DB()->escape($text) . "' WHERE post_id = $post_id LIMIT 1");
if ($post['topic_last_post_id'] != $post['post_id'] && $userdata['user_id'] == $post['poster_id']) {
DB()->query("UPDATE " . BB_POSTS . " SET post_edit_time = '" . TIMENOW . "', post_edit_count = post_edit_count + 1 WHERE post_id = $post_id LIMIT 1");
}
$s_text = str_replace('\n', "\n", $text);
$s_topic_title = str_replace('\n', "\n", $post['topic_title']);
add_search_words($post_id, stripslashes($s_text), stripslashes($s_topic_title));
update_post_html([
'post_id' => $post_id,
'post_text' => $text
]);
}
} else {
$this->ajax_die($lang['EMPTY_MESSAGE']);
}
// Update atom feed
update_atom('topic', (int)$this->request['topic_id']);
$this->response['html'] = bbcode2html($text);
} else {
$is_auth = auth(AUTH_ALL, $post['forum_id'], $userdata, $post);
if ($post['topic_status'] == TOPIC_LOCKED && !$is_auth['auth_mod']) {
$this->ajax_die($lang['TOPIC_LOCKED']);
} elseif (!$is_auth['auth_edit']) {
$this->ajax_die(sprintf($lang['SORRY_AUTH_EDIT'], strip_tags($is_auth['auth_edit_type'])));
}
$hidden_form = '<input type="hidden" name="mode" value="editpost" />';
$hidden_form .= '<input type="hidden" name="' . POST_POST_URL . '" value="' . $post_id . '" />';
$hidden_form .= '<input type="hidden" name="subject" value="' . $post['topic_title'] . '" />';
$this->response['text'] = '
<form action="' . POSTING_URL . '" method="post" name="post">
' . $hidden_form . '
<div class="buttons mrg_4">
<input type="button" value="B" name="codeB" title="' . $lang['BOLD'] . '" style="font-weight: bold;" />
<input type="button" value="i" name="codeI" title="' . $lang['ITALIC'] . '" style="font-style: italic;" />
<input type="button" value="u" name="codeU" title="' . $lang['UNDERLINE'] . '" style="text-decoration: underline;" />
<input type="button" value="s" name="codeS" title="' . $lang['STRIKEOUT'] . '" style="text-decoration: line-through;" />&nbsp;&nbsp;
<input type="button" value="' . $lang['QUOTE'] . '" name="codeQuote" title="' . $lang['QUOTE_TITLE'] . '" />
<input type="button" value="Img" name="codeImg" title="' . $lang['IMG_TITLE'] . '" />
<input type="button" value="' . $lang['URL'] . '" name="codeUrl" title="' . $lang['URL_TITLE'] . '" style="text-decoration: underline;" />&nbsp;
<input type="button" value="' . $lang['CODE'] . '" name="codeCode" title="' . $lang['CODE_TITLE'] . '" />
<input type="button" value="' . $lang['LIST'] . '" name="codeList" title="' . $lang['LIST_TITLE'] . '" />
<input type="button" value="1." name="codeOpt" title="' . $lang['LIST_ITEM'] . '" />&nbsp;
<input type="button" value="' . $lang['QUOTE_SEL'] . '" name="quoteselected" title="' . $lang['QUOTE_SELECTED'] . '" onclick="bbcode.onclickQuoteSel();" />&nbsp;
</div>
<textarea id="message-' . $post_id . '" class="editor mrg_4" name="message" rows="18" cols="92">' . $post['post_text'] . '</textarea>
<div class="mrg_4 tCenter">
<input title="Alt+Enter" name="preview" type="submit" value="' . $lang['PREVIEW'] . '">
<input type="button" onclick="edit_post(' . $post_id . ');" value="' . $lang['CANCEL'] . '">
<input type="button" onclick="edit_post(' . $post_id . ', \'editor\', $(\'#message-' . $post_id . '\').val()); return false;" class="bold" value="' . $lang['SUBMIT'] . '">
</div><hr>
<script type="text/javascript">
var bbcode = new BBCode("message-' . $post_id . '");
var ctrl = "ctrl";
bbcode.addTag("codeB", "b", null, "B", ctrl);
bbcode.addTag("codeI", "i", null, "I", ctrl);
bbcode.addTag("codeU", "u", null, "U", ctrl);
bbcode.addTag("codeS", "s", null, "S", ctrl);
bbcode.addTag("codeQuote", "quote", null, "Q", ctrl);
bbcode.addTag("codeImg", "img", null, "R", ctrl);
bbcode.addTag("codeUrl", "url", "/url", "W", ctrl);
bbcode.addTag("codeCode", "code", null, "K", ctrl);
bbcode.addTag("codeList", "list", null, "L", ctrl);
bbcode.addTag("codeOpt", "*", "", "0", ctrl);
</script>
</form>';
}
$this->response['post_id'] = $post_id;
break;
case 'add':
if (!isset($this->request['topic_id'])) {
$this->ajax_die($lang['INVALID_TOPIC_ID']);
}
if (bf($userdata['user_opt'], 'user_opt', 'dis_post')) {
$this->ajax_die($lang['RULES_REPLY_CANNOT']);
} elseif (!$is_auth['auth_reply']) {
$this->ajax_die(sprintf($lang['SORRY_AUTH_REPLY'], strip_tags($is_auth['auth_reply_type'])));
}
if ($post['topic_status'] == TOPIC_LOCKED && !$is_auth['auth_mod']) {
$this->ajax_die($lang['TOPIC_LOCKED']);
}
$message = (string)$this->request['message'];
$message = prepare_message($message);
// Flood control
$where_sql = IS_GUEST ? "p.poster_ip = '" . USER_IP . "'" : "p.poster_id = {$userdata['user_id']}";
$sql = "SELECT MAX(p.post_time) AS last_post_time FROM " . BB_POSTS . " p WHERE $where_sql";
if ($row = DB()->fetch_row($sql) and $row['last_post_time']) {
if ($userdata['user_level'] == USER) {
if ((TIMENOW - $row['last_post_time']) < $bb_cfg['flood_interval']) {
$this->ajax_die($lang['FLOOD_ERROR']);
}
}
}
// Double Post Control
if (!empty($row['last_post_time']) && !IS_AM) {
$sql = "
SELECT pt.post_text
FROM " . BB_POSTS . " p, " . BB_POSTS_TEXT . " pt
WHERE $where_sql
AND p.post_time = " . (int)$row['last_post_time'] . "
AND pt.post_id = p.post_id
LIMIT 1
";
if ($row = DB()->fetch_row($sql)) {
$last_msg = DB()->escape($row['post_text']);
if ($last_msg == $message) {
$this->ajax_die($lang['DOUBLE_POST_ERROR']);
}
}
}
if ($bb_cfg['max_smilies']) {
$count_smilies = substr_count(bbcode2html($message), '<img class="smile" src="' . $bb_cfg['smilies_path']);
if ($count_smilies > $bb_cfg['max_smilies']) {
$this->ajax_die(sprintf($lang['MAX_SMILIES_PER_POST'], $bb_cfg['max_smilies']));
}
}
DB()->sql_query("INSERT INTO " . BB_POSTS . " (topic_id, forum_id, poster_id, post_time, poster_ip) VALUES ($topic_id, " . $post['forum_id'] . ", " . $userdata['user_id'] . ", '" . TIMENOW . "', '" . USER_IP . "')");
$post_id = DB()->sql_nextid();
DB()->sql_query("INSERT INTO " . BB_POSTS_TEXT . " (post_id, post_text) VALUES ($post_id, '" . DB()->escape($message) . "')");
\TorrentPier\Legacy\Post::update_post_stats('reply', $post, $post['forum_id'], $topic_id, $post_id, $userdata['user_id']);
$s_message = str_replace('\n', "\n", $message);
$s_topic_title = str_replace('\n', "\n", $post['topic_title']);
add_search_words($post_id, stripslashes($s_message), stripslashes($s_topic_title));
update_post_html([
'post_id' => $post_id,
'post_text' => $message
]);
if ($bb_cfg['topic_notify_enabled']) {
$notify = !empty($this->request['notify']);
\TorrentPier\Legacy\Post::user_notification('reply', $post, $post['topic_title'], $post['forum_id'], $topic_id, $notify);
}
// Update atom feed
update_atom('topic', (int)$this->request['topic_id']);
$this->response['redirect'] = make_url(POST_URL . "$post_id#$post_id");
break;
default:
$this->ajax_die('empty type');
break;
}