/** * Completely rebuild the counters for a particular thread (useful if they become out of sync) * * @param int The thread ID */ function rebuild_thread_counters($tid) { global $db; $thread = get_thread($tid); $count = array(); $query = $db->simple_select("posts", "COUNT(pid) AS replies", "tid='{$tid}' AND pid!='{$thread['firstpost']}' AND visible='1'"); $count['replies'] = $db->fetch_field($query, "replies"); // Unapproved posts $query = $db->simple_select("posts", "COUNT(pid) AS unapprovedposts", "tid='{$tid}' AND pid != '{$thread['firstpost']}' AND visible='0'"); $count['unapprovedposts'] = $db->fetch_field($query, "unapprovedposts"); // Soft deleted posts $query = $db->simple_select("posts", "COUNT(pid) AS deletedposts", "tid='{$tid}' AND pid != '{$thread['firstpost']}' AND visible='-1'"); $count['deletedposts'] = $db->fetch_field($query, "deletedposts"); // Attachment count $query = $db->query("\n\t\t\tSELECT COUNT(aid) AS attachment_count\n\t\t\tFROM " . TABLE_PREFIX . "attachments a\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "posts p ON (a.pid=p.pid)\n\t\t\tWHERE p.tid='{$tid}' AND a.visible=1\n\t"); $count['attachmentcount'] = $db->fetch_field($query, "attachment_count"); update_thread_counters($tid, $count); update_thread_data($tid); }
function akismet_admin() { global $mybb, $db, $page, $lang; if ($page->active_action != "akismet") { return; } $page->add_breadcrumb_item($lang->akismet); if ($mybb->input['delete_all'] && $mybb->request_method == "post") { // User clicked no if ($mybb->input['no']) { admin_redirect("index.php?module=forum-akismet"); } if ($mybb->request_method == "post") { // Delete the template $db->delete_query("posts", "visible = '-4'"); // Log admin action log_admin_action(); flash_message($lang->success_deleted_spam, 'success'); admin_redirect("index.php?module=forum-akismet"); } else { $page->output_confirm_action("index.php?module=forum-akismet&delete_all=1", $lang->confirm_spam_deletion); } } if ($mybb->input['unmark'] && $mybb->request_method == "post") { $unmark = $mybb->input['akismet']; if (empty($unmark)) { flash_message($lang->error_unmark, 'error'); admin_redirect("index.php?module=forum-akismet"); } $posts_in = ''; $comma = ''; foreach ($unmark as $key => $val) { $posts_in .= $comma . intval($key); $comma = ','; } $query = $db->simple_select("posts", "pid, tid", "pid IN ({$posts_in}) AND replyto = '0'"); while ($post = $db->fetch_array($query)) { $threadp[] = $post['tid']; } if (!is_array($threadp)) { $threadp = array(); } $thread_list = implode(',', $threadp); $query = $db->query("\r\n\t\t\tSELECT p.tid, f.usepostcounts, p.uid, p.fid, p.dateline, p.replyto, t.lastpost, t.lastposter, t.lastposteruid, t.subject\r\n\t\t\tFROM " . TABLE_PREFIX . "posts p\r\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "threads t ON (t.tid=p.tid)\r\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "forums f ON (f.fid=p.fid)\r\n\t\t\tWHERE p.pid IN ({$posts_in}) AND p.visible = '-4'\r\n\t\t"); while ($post = $db->fetch_array($query)) { // Fetch the last post for this forum $query2 = $db->query("\r\n\t\t\t\tSELECT tid, lastpost, lastposter, lastposteruid, subject\r\n\t\t\t\tFROM " . TABLE_PREFIX . "threads\r\n\t\t\t\tWHERE fid='{$post['fid']}' AND visible='1' AND closed NOT LIKE 'moved|%'\r\n\t\t\t\tORDER BY lastpost DESC\r\n\t\t\t\tLIMIT 0, 1\r\n\t\t\t"); $lastpost = $db->fetch_array($query2); if ($post['lastpost'] > $lastpost['lastpost']) { $lastpost['lastpost'] = $post['lastpost']; $lastpost['lastposter'] = $post['lastposter']; $lastpost['lastposteruid'] = $post['lastposteruid']; $lastpost['subject'] = $post['subject']; $lastpost['tid'] = $post['tid']; } $update_count = array("lastpost" => intval($lastpost['lastpost']), "lastposter" => $db->escape_string($lastpost['lastposter']), "lastposteruid" => intval($lastpost['lastposteruid']), "lastposttid" => intval($lastpost['tid']), "lastpostsubject" => $db->escape_string($lastpost['subject'])); $db->update_query("forums", $update_count, "fid='{$post['fid']}'"); $query2 = $db->query("\r\n\t\t\t\tSELECT u.uid, u.username, p.username AS postusername, p.dateline\r\n\t\t\t\tFROM " . TABLE_PREFIX . "posts p\r\n\t\t\t\tLEFT JOIN " . TABLE_PREFIX . "users u ON (u.uid=p.uid)\r\n\t\t\t\tWHERE p.tid='{$post['tid']}' AND p.visible='1' OR p.pid = '{$post['pid']}'\r\n\t\t\t\tORDER BY p.dateline DESC\r\n\t\t\t\tLIMIT 1"); $lastpost = $db->fetch_array($query2); $query2 = $db->query("\r\n\t\t\t\tSELECT u.uid, u.username, p.username AS postusername, p.dateline\r\n\t\t\t\tFROM " . TABLE_PREFIX . "posts p\r\n\t\t\t\tLEFT JOIN " . TABLE_PREFIX . "users u ON (u.uid=p.uid)\r\n\t\t\t\tWHERE p.tid='{$post['tid']}'\r\n\t\t\t\tORDER BY p.dateline ASC\r\n\t\t\t\tLIMIT 0,1\r\n\t\t\t"); $firstpost = $db->fetch_array($query2); if (!$firstpost['username']) { $firstpost['username'] = $firstpost['postusername']; } if (!$lastpost['username']) { $lastpost['username'] = $lastpost['postusername']; } if (!$lastpost['dateline']) { $lastpost['username'] = $firstpost['username']; $lastpost['uid'] = $firstpost['uid']; $lastpost['dateline'] = $firstpost['dateline']; } $lastpost['username'] = $db->escape_string($lastpost['username']); $firstpost['username'] = $db->escape_string($firstpost['username']); $query2 = $db->simple_select("users", "akismetstopped", "uid='{$post['uid']}'"); $akismetstopped = $db->fetch_field($query2, "akismetstopped") - 1; if ($akismetstopped < 0) { $akismetstopped = 0; } $db->update_query("users", array('akismetstopped' => $akismetstopped), "uid='{$post['uid']}'"); $update_array = array('username' => $firstpost['username'], 'uid' => intval($firstpost['uid']), 'lastpost' => intval($lastpost['dateline']), 'lastposter' => $lastpost['username'], 'lastposteruid' => intval($lastpost['uid'])); $db->update_query("threads", $update_array, "tid='{$post['tid']}'"); if ($post['usepostcounts'] != 0) { $db->write_query("UPDATE " . TABLE_PREFIX . "users SET postnum=postnum+1 WHERE uid = '{$post['uid']}'"); } $newthreads = $newreplies = 0; if ($post['replyto'] == 0) { ++$newthreads; } else { ++$newreplies; } update_thread_counters($post['tid'], array('replies' => '+' . $newreplies)); update_forum_counters($post['fid'], array('threads' => '+' . $newthreads, 'posts' => '+1')); } $approve = array("visible" => 1); if ($thread_list) { $db->update_query("threads", $approve, "tid IN ({$thread_list})"); } $db->update_query("posts", $approve, "pid IN ({$posts_in})"); // Log admin action log_admin_action(); flash_message($lang->success_unmarked, 'success'); admin_redirect("index.php?module=forum-akismet"); } if ($mybb->input['delete'] && $mybb->request_method == "post") { $deletepost = $mybb->input['akismet']; if (empty($deletepost)) { flash_message($lang->error_deletepost, 'error'); admin_redirect("index.php?module=forum-akismet"); } $posts_in = ''; $comma = ''; foreach ($deletepost as $key => $val) { $posts_in .= $comma . intval($key); $comma = ','; } $query = $db->simple_select("posts", "pid, tid", "pid IN ({$posts_in}) AND replyto = '0'"); while ($post = $db->fetch_array($query)) { $threadp[$post['pid']] = $post['tid']; } if (!is_array($threadp)) { $threadp = array(); } require_once MYBB_ROOT . "inc/functions_upload.php"; foreach ($deletepost as $pid => $val) { if (array_key_exists($pid, $threadp)) { $db->delete_query("posts", "pid IN ({$posts_in})"); $db->delete_query("attachments", "pid IN ({$posts_in})"); // Get thread info $query = $db->simple_select("threads", "poll", "tid='" . $threadp[$pid] . "'"); $poll = $db->fetch_field($query, 'poll'); // Delete threads, redirects, favorites, polls, and poll votes $db->delete_query("threads", "tid='" . $threadp[$pid] . "'"); $db->delete_query("threads", "closed='moved|" . $threadp[$pid] . "'"); $db->delete_query("threadsubscriptions", "tid='" . $threadp[$pid] . "'"); $db->delete_query("polls", "tid='" . $threadp[$pid] . "'"); $db->delete_query("pollvotes", "pid='{$poll}'"); } // Remove attachments remove_attachments($pid); // Delete the post $db->delete_query("posts", "pid='{$pid}'"); } // Log admin action log_admin_action(); flash_message($lang->success_spam_deleted, 'success'); admin_redirect("index.php?module=forum-akismet"); } if (!$mybb->input['action']) { require MYBB_ROOT . "inc/class_parser.php"; $parser = new postParser(); $page->output_header($lang->akismet); $form = new Form("index.php?module=forum-akismet", "post"); $table = new Table(); $table->construct_header($form->generate_check_box("checkall", 1, '', array('class' => 'checkall')), array('width' => '5%')); $table->construct_header("Title / Username / Post", array('class' => 'align_center')); $mybb->input['page'] = intval($mybb->input['page']); if ($mybb->input['page'] > 0) { $start = $mybb->input['page'] * 20; } else { $start = 0; } $query = $db->simple_select("posts", "COUNT(pid) as spam", "visible = '-4'"); $total_rows = $db->fetch_field($query, 'spam'); if ($start > $total_rows) { $start = $total_rows - 20; } if ($start < 0) { $start = 0; } $query = $db->simple_select("posts", "*", "visible = '-4'", array('limit_start' => $start, 'limit' => '20', 'order_by' => 'dateline', 'order_dir' => 'desc')); while ($post = $db->fetch_array($query)) { if ($post['uid'] != 0) { $username = "******"../" . str_replace("{uid}", $post['uid'], PROFILE_URL) . "\" target=\"_blank\">" . format_name($post['username'], $post['usergroup'], $post['displaygroup']) . "</a>"; } else { $username = $post['username']; } $table->construct_cell($form->generate_check_box("akismet[{$post['pid']}]", 1, '')); $table->construct_cell("<span style=\"float: right;\">{$lang->username} {$username}</span> <span style=\"float: left;\">{$lang->title}: " . htmlspecialchars_uni($post['subject']) . " <strong>(" . my_date($mybb->settings['dateformat'], $post['dateline']) . ", " . my_date($mybb->settings['timeformat'], $post['dateline']) . ")</strong></span>"); $table->construct_row(); $parser_options = array("allow_html" => 0, "allow_mycode" => 0, "allow_smilies" => 0, "allow_imgcode" => 0, "me_username" => $post['username'], "filter_badwords" => 1); $post['message'] = $parser->parse_message($post['message'], $parser_options); $table->construct_cell($post['message'], array("colspan" => 2)); $table->construct_row(); } $num_rows = $table->num_rows(); if ($num_rows == 0) { $table->construct_cell($lang->no_spam_found, array("class" => "align_center", "colspan" => 2)); $table->construct_row(); } $table->output($lang->detected_spam_messages); echo "<br />" . draw_admin_pagination($mybb->input['page'], 20, $total_rows, "index.php?module=forum-akismet&page={page}"); $buttons[] = $form->generate_submit_button($lang->unmark_selected, array('name' => 'unmark')); $buttons[] = $form->generate_submit_button($lang->deleted_selected, array('name' => 'delete')); if ($num_rows > 0) { $buttons[] = $form->generate_submit_button($lang->delete_all, array('name' => 'delete_all', 'onclick' => "return confirm('{$lang->confirm_spam_deletion}');")); } $form->output_submit_wrapper($buttons); $form->end(); $page->output_footer(); } exit; }
/** * Insert a thread into the database. * * @return array Array of new thread details, tid and visibility. */ function insert_thread() { global $db, $mybb, $plugins, $cache, $lang; // Yes, validating is required. if (!$this->get_validated()) { die("The thread needs to be validated before inserting it into the DB."); } if (count($this->get_errors()) > 0) { die("The thread is not valid."); } $thread =& $this->data; // Fetch the forum this thread is being made in $forum = get_forum($thread['fid']); // This thread is being saved as a draft. if ($thread['savedraft']) { $visible = -2; } else { $forumpermissions = forum_permissions($thread['fid'], $thread['uid']); // Decide on the visibility of this post. if ($forumpermissions['modthreads'] == 1 && !is_moderator($thread['fid'], "", $thread['uid'])) { $visible = 0; } else { $visible = 1; } // Are posts from this user being moderated? Change visibility if ($mybb->user['uid'] == $thread['uid'] && $mybb->user['moderateposts'] == 1) { $visible = 0; } } // Have a post ID but not a thread ID - fetch thread ID if (!empty($thread['pid']) && !$thread['tid']) { $query = $db->simple_select("posts", "tid", "pid='{$thread['pid']}"); $thread['tid'] = $db->fetch_field($query, "tid"); } if (isset($thread['pid']) && $thread['pid'] > 0) { $query = $db->simple_select("posts", "pid", "pid='{$thread['pid']}' AND uid='{$thread['uid']}' AND visible='-2'"); $draft_check = $db->fetch_field($query, "pid"); } else { $draft_check = false; } // Are we updating a post which is already a draft? Perhaps changing it into a visible post? if ($draft_check) { $this->thread_insert_data = array("subject" => $db->escape_string($thread['subject']), "icon" => (int) $thread['icon'], "username" => $db->escape_string($thread['username']), "dateline" => (int) $thread['dateline'], "lastpost" => (int) $thread['dateline'], "lastposter" => $db->escape_string($thread['username']), "visible" => $visible); $plugins->run_hooks("datahandler_post_insert_thread", $this); $db->update_query("threads", $this->thread_insert_data, "tid='{$thread['tid']}'"); $this->post_insert_data = array("subject" => $db->escape_string($thread['subject']), "icon" => (int) $thread['icon'], "username" => $db->escape_string($thread['username']), "dateline" => (int) $thread['dateline'], "message" => $db->escape_string($thread['message']), "ipaddress" => $db->escape_binary(my_inet_pton(get_ip())), "includesig" => $thread['options']['signature'], "smilieoff" => $thread['options']['disablesmilies'], "visible" => $visible); $plugins->run_hooks("datahandler_post_insert_thread_post", $this); $db->update_query("posts", $this->post_insert_data, "pid='{$thread['pid']}'"); $this->tid = $thread['tid']; $this->pid = $thread['pid']; } else { $this->thread_insert_data = array("fid" => $thread['fid'], "subject" => $db->escape_string($thread['subject']), "prefix" => (int) $thread['prefix'], "icon" => (int) $thread['icon'], "uid" => $thread['uid'], "username" => $db->escape_string($thread['username']), "dateline" => (int) $thread['dateline'], "lastpost" => (int) $thread['dateline'], "lastposter" => $db->escape_string($thread['username']), "views" => 0, "replies" => 0, "visible" => $visible, "notes" => ''); $plugins->run_hooks("datahandler_post_insert_thread", $this); $this->tid = $db->insert_query("threads", $this->thread_insert_data); $this->post_insert_data = array("tid" => $this->tid, "fid" => $thread['fid'], "subject" => $db->escape_string($thread['subject']), "icon" => (int) $thread['icon'], "uid" => $thread['uid'], "username" => $db->escape_string($thread['username']), "dateline" => (int) $thread['dateline'], "message" => $db->escape_string($thread['message']), "ipaddress" => $db->escape_binary(my_inet_pton(get_ip())), "includesig" => $thread['options']['signature'], "smilieoff" => $thread['options']['disablesmilies'], "visible" => $visible); $plugins->run_hooks("datahandler_post_insert_thread_post", $this); $this->pid = $db->insert_query("posts", $this->post_insert_data); // Now that we have the post id for this first post, update the threads table. $firstpostup = array("firstpost" => $this->pid); $db->update_query("threads", $firstpostup, "tid='{$this->tid}'"); } // If we're not saving a draft there are some things we need to check now if (!$thread['savedraft']) { if ($thread['options']['subscriptionmethod'] != "" && $thread['uid'] > 0) { switch ($thread['options']['subscriptionmethod']) { case "pm": $notification = 2; break; case "email": $notification = 1; break; default: $notification = 0; } require_once MYBB_ROOT . "inc/functions_user.php"; add_subscribed_thread($this->tid, $notification, $thread['uid']); } // Perform any selected moderation tools. if (is_moderator($thread['fid'], "", $thread['uid']) && is_array($thread['modoptions'])) { $lang->load($this->language_file, true); $modoptions = $thread['modoptions']; $modlogdata['fid'] = $thread['fid']; if (isset($thread['tid'])) { $modlogdata['tid'] = $thread['tid']; } $modoptions_update = array(); // Close the thread. if (!empty($modoptions['closethread'])) { $modoptions_update['closed'] = 1; log_moderator_action($modlogdata, $lang->thread_closed); } // Stick the thread. if (!empty($modoptions['stickthread'])) { $modoptions_update['sticky'] = 1; log_moderator_action($modlogdata, $lang->thread_stuck); } // Execute moderation options. if ($modoptions_update) { $db->update_query('threads', $modoptions_update, "tid='{$this->tid}'"); } } if ($visible == 1) { // If we have a registered user then update their post count and last post times. if ($thread['uid'] > 0) { $user = get_user($thread['uid']); $update_query = array(); // Only update the lastpost column of the user if the date of the thread is newer than their last post. if ($thread['dateline'] > $user['lastpost']) { // Yes this has a single quote within a double quote. It's not a bug. $update_query['lastpost'] = "'{$thread['dateline']}'"; } // Update the post count if this forum allows post counts to be tracked if ($forum['usepostcounts'] != 0) { $update_query['postnum'] = "postnum+1"; } if ($forum['usethreadcounts'] != 0) { $update_query['threadnum'] = 'threadnum+1'; } // Only update the table if we need to. if (!empty($update_query)) { $db->update_query("users", $update_query, "uid='{$thread['uid']}'", 1, true); } } if (!isset($forum['lastpost'])) { $forum['lastpost'] = 0; } $done_users = array(); // Queue up any forum subscription notices to users who are subscribed to this forum. $excerpt = my_substr($thread['message'], 0, $mybb->settings['subscribeexcerpt']) . $lang->emailbit_viewthread; // Parse badwords require_once MYBB_ROOT . "inc/class_parser.php"; $parser = new postParser(); $excerpt = $parser->parse_badwords($excerpt); $query = $db->query("\n\t\t\t\t\tSELECT u.username, u.email, u.uid, u.language, u.loginkey, u.salt, u.regdate\n\t\t\t\t\tFROM " . TABLE_PREFIX . "forumsubscriptions fs\n\t\t\t\t\tLEFT JOIN " . TABLE_PREFIX . "users u ON (u.uid=fs.uid)\n\t\t\t\t\tLEFT JOIN " . TABLE_PREFIX . "usergroups g ON (g.gid=u.usergroup)\n\t\t\t\t\tWHERE fs.fid='" . (int) $thread['fid'] . "'\n\t\t\t\t\tAND fs.uid != '" . (int) $thread['uid'] . "'\n\t\t\t\t\tAND u.lastactive > '{$forum['lastpost']}'\n\t\t\t\t\tAND g.isbannedgroup != 1\n\t\t\t\t"); while ($subscribedmember = $db->fetch_array($query)) { if ($done_users[$subscribedmember['uid']]) { continue; } $done_users[$subscribedmember['uid']] = 1; $forumpermissions = forum_permissions($thread['fid'], $subscribedmember['uid']); if ($forumpermissions['canview'] == 0 || $forumpermissions['canviewthreads'] == 0) { continue; } if (!is_moderator($thread['fid'], "", $subscribedmember['uid']) && $forumpermissions['canonlyviewownthreads'] == 1) { // In a 'view own only' forum and not a moderator continue; } // Determine the language pack we'll be using to send this email in and load it if it isn't already. if ($subscribedmember['language'] != '' && $lang->language_exists($subscribedmember['language'])) { $uselang = $subscribedmember['language']; } else { if ($mybb->settings['bblanguage']) { $uselang = $mybb->settings['bblanguage']; } else { $uselang = "english"; } } if ($uselang == $mybb->settings['bblanguage']) { $emailsubject = $lang->emailsubject_forumsubscription; $emailmessage = $lang->email_forumsubscription; } else { if (!isset($langcache[$uselang]['emailsubject_forumsubscription'])) { $userlang = new MyLanguage(); $userlang->set_path(MYBB_ROOT . "inc/languages"); $userlang->set_language($uselang); $userlang->load("messages"); $langcache[$uselang]['emailsubject_forumsubscription'] = $userlang->emailsubject_forumsubscription; $langcache[$uselang]['email_forumsubscription'] = $userlang->email_forumsubscription; unset($userlang); } $emailsubject = $langcache[$uselang]['emailsubject_forumsubscription']; $emailmessage = $langcache[$uselang]['email_forumsubscription']; } $emailsubject = $lang->sprintf($emailsubject, $forum['name']); $post_code = md5($subscribedmember['loginkey'] . $subscribedmember['salt'] . $subscribedmember['regdate']); $emailmessage = $lang->sprintf($emailmessage, $subscribedmember['username'], $thread['username'], $forum['name'], $mybb->settings['bbname'], $thread['subject'], $excerpt, $mybb->settings['bburl'], get_thread_link($this->tid), $thread['fid'], $post_code); $new_email = array("mailto" => $db->escape_string($subscribedmember['email']), "mailfrom" => '', "subject" => $db->escape_string($emailsubject), "message" => $db->escape_string($emailmessage), "headers" => ''); $db->insert_query("mailqueue", $new_email); unset($userlang); $queued_email = 1; } // Have one or more emails been queued? Update the queue count if (isset($queued_email) && $queued_email == 1) { $cache->update_mailqueue(); } } } // Assign any uploaded attachments with the specific posthash to the newly created post. if ($thread['posthash']) { $thread['posthash'] = $db->escape_string($thread['posthash']); $attachmentassign = array("pid" => $this->pid, "posthash" => ''); $db->update_query("attachments", $attachmentassign, "posthash='{$thread['posthash']}' AND pid='0'"); } if ($visible == 1) { update_last_post($this->tid); update_forum_counters($thread['fid'], array("threads" => "+1", "posts" => "+1")); update_forum_lastpost($thread['fid']); } else { if ($visible == 0) { update_forum_counters($thread['fid'], array("unapprovedthreads" => "+1", "unapprovedposts" => "+1")); } } $query = $db->simple_select("attachments", "COUNT(aid) AS attachmentcount", "pid='{$this->pid}' AND visible='1'"); $attachmentcount = $db->fetch_field($query, "attachmentcount"); if ($attachmentcount > 0) { update_thread_counters($this->tid, array("attachmentcount" => "+{$attachmentcount}")); } // Return the post's pid and whether or not it is visible. $this->return_values = array("pid" => $this->pid, "tid" => $this->tid, "visible" => $visible); $plugins->run_hooks("datahandler_post_insert_thread_end", $this); return $this->return_values; }
/** * Upload an attachment in to the file system * * @param array $attachment Attachment data (as fed by PHPs $_FILE) * @param boolean $update_attachment Whether or not we are updating a current attachment or inserting a new one * @return array Array of attachment data if successful, otherwise array of error data */ function upload_attachment($attachment, $update_attachment = false) { global $mybb, $db, $theme, $templates, $posthash, $pid, $tid, $forum, $mybb, $lang, $plugins, $cache; $posthash = $db->escape_string($mybb->get_input('posthash')); $pid = (int) $pid; if (isset($attachment['error']) && $attachment['error'] != 0) { $ret['error'] = $lang->error_uploadfailed . $lang->error_uploadfailed_detail; switch ($attachment['error']) { case 1: // UPLOAD_ERR_INI_SIZE $ret['error'] .= $lang->error_uploadfailed_php1; break; case 2: // UPLOAD_ERR_FORM_SIZE $ret['error'] .= $lang->error_uploadfailed_php2; break; case 3: // UPLOAD_ERR_PARTIAL $ret['error'] .= $lang->error_uploadfailed_php3; break; case 4: // UPLOAD_ERR_NO_FILE $ret['error'] .= $lang->error_uploadfailed_php4; break; case 6: // UPLOAD_ERR_NO_TMP_DIR $ret['error'] .= $lang->error_uploadfailed_php6; break; case 7: // UPLOAD_ERR_CANT_WRITE $ret['error'] .= $lang->error_uploadfailed_php7; break; default: $ret['error'] .= $lang->sprintf($lang->error_uploadfailed_phpx, $attachment['error']); break; } return $ret; } if (!is_uploaded_file($attachment['tmp_name']) || empty($attachment['tmp_name'])) { $ret['error'] = $lang->error_uploadfailed . $lang->error_uploadfailed_php4; return $ret; } $attachtypes = $cache->read('attachtypes'); $attachment = $plugins->run_hooks("upload_attachment_start", $attachment); $ext = get_extension($attachment['name']); // Check if we have a valid extension if (!isset($attachtypes[$ext])) { $ret['error'] = $lang->error_attachtype; return $ret; } else { $attachtype = $attachtypes[$ext]; } // Check the size if ($attachment['size'] > $attachtype['maxsize'] * 1024 && $attachtype['maxsize'] != "") { $ret['error'] = $lang->sprintf($lang->error_attachsize, $attachtype['maxsize']); return $ret; } // Double check attachment space usage if ($mybb->usergroup['attachquota'] > 0) { $query = $db->simple_select("attachments", "SUM(filesize) AS ausage", "uid='" . $mybb->user['uid'] . "'"); $usage = $db->fetch_array($query); $usage = $usage['ausage'] + $attachment['size']; if ($usage > $mybb->usergroup['attachquota'] * 1024) { $friendlyquota = get_friendly_size($mybb->usergroup['attachquota'] * 1024); $ret['error'] = $lang->sprintf($lang->error_reachedattachquota, $friendlyquota); return $ret; } } // Gather forum permissions $forumpermissions = forum_permissions($forum['fid']); // Check if an attachment with this name is already in the post if ($pid != 0) { $uploaded_query = "pid='{$pid}'"; } else { $uploaded_query = "posthash='{$posthash}'"; } $query = $db->simple_select("attachments", "*", "filename='" . $db->escape_string($attachment['name']) . "' AND " . $uploaded_query); $prevattach = $db->fetch_array($query); if ($prevattach['aid'] && $update_attachment == false) { if (!$mybb->usergroup['caneditattachments'] && !$forumpermissions['caneditattachments']) { $ret['error'] = $lang->error_alreadyuploaded_perm; return $ret; } $ret['error'] = $lang->error_alreadyuploaded; return $ret; } // Check to see how many attachments exist for this post already if ($mybb->settings['maxattachments'] > 0 && $update_attachment == false) { $query = $db->simple_select("attachments", "COUNT(aid) AS numattachs", $uploaded_query); $attachcount = $db->fetch_field($query, "numattachs"); if ($attachcount >= $mybb->settings['maxattachments']) { $ret['error'] = $lang->sprintf($lang->error_maxattachpost, $mybb->settings['maxattachments']); return $ret; } } $month_dir = ''; if ($mybb->safemode == false) { // Check if the attachment directory (YYYYMM) exists, if not, create it $month_dir = gmdate("Ym"); if (!@is_dir($mybb->settings['uploadspath'] . "/" . $month_dir)) { @mkdir($mybb->settings['uploadspath'] . "/" . $month_dir); // Still doesn't exist - oh well, throw it in the main directory if (!@is_dir($mybb->settings['uploadspath'] . "/" . $month_dir)) { $month_dir = ''; } } } // All seems to be good, lets move the attachment! $filename = "post_" . $mybb->user['uid'] . "_" . TIME_NOW . "_" . md5(random_str()) . ".attach"; $file = upload_file($attachment, $mybb->settings['uploadspath'] . "/" . $month_dir, $filename); // Failed to create the attachment in the monthly directory, just throw it in the main directory if (!empty($file['error']) && $month_dir) { $file = upload_file($attachment, $mybb->settings['uploadspath'] . '/', $filename); } elseif ($month_dir) { $filename = $month_dir . "/" . $filename; } if (!empty($file['error'])) { $ret['error'] = $lang->error_uploadfailed . $lang->error_uploadfailed_detail; switch ($file['error']) { case 1: $ret['error'] .= $lang->error_uploadfailed_nothingtomove; break; case 2: $ret['error'] .= $lang->error_uploadfailed_movefailed; break; } return $ret; } // Lets just double check that it exists if (!file_exists($mybb->settings['uploadspath'] . "/" . $filename)) { $ret['error'] = $lang->error_uploadfailed . $lang->error_uploadfailed_detail . $lang->error_uploadfailed_lost; return $ret; } // Generate the array for the insert_query $attacharray = array("pid" => $pid, "posthash" => $posthash, "uid" => $mybb->user['uid'], "filename" => $db->escape_string($file['original_filename']), "filetype" => $db->escape_string($file['type']), "filesize" => (int) $file['size'], "attachname" => $filename, "downloads" => 0, "dateuploaded" => TIME_NOW); // If we're uploading an image, check the MIME type compared to the image type and attempt to generate a thumbnail if ($ext == "gif" || $ext == "png" || $ext == "jpg" || $ext == "jpeg" || $ext == "jpe") { // Check a list of known MIME types to establish what kind of image we're uploading switch (my_strtolower($file['type'])) { case "image/gif": $img_type = 1; break; case "image/jpeg": case "image/x-jpg": case "image/x-jpeg": case "image/pjpeg": case "image/jpg": $img_type = 2; break; case "image/png": case "image/x-png": $img_type = 3; break; default: $img_type = 0; } $supported_mimes = array(); foreach ($attachtypes as $attachtype) { if (!empty($attachtype['mimetype'])) { $supported_mimes[] = $attachtype['mimetype']; } } // Check if the uploaded file type matches the correct image type (returned by getimagesize) $img_dimensions = @getimagesize($mybb->settings['uploadspath'] . "/" . $filename); $mime = ""; $file_path = $mybb->settings['uploadspath'] . "/" . $filename; if (function_exists("finfo_open")) { $file_info = finfo_open(FILEINFO_MIME); list($mime, ) = explode(';', finfo_file($file_info, MYBB_ROOT . $file_path), 1); finfo_close($file_info); } else { if (function_exists("mime_content_type")) { $mime = mime_content_type(MYBB_ROOT . $file_path); } } if (!is_array($img_dimensions) || $img_dimensions[2] != $img_type && !in_array($mime, $supported_mimes)) { delete_uploaded_file($mybb->settings['uploadspath'] . "/" . $filename); $ret['error'] = $lang->error_uploadfailed; return $ret; } require_once MYBB_ROOT . "inc/functions_image.php"; $thumbname = str_replace(".attach", "_thumb.{$ext}", $filename); $attacharray = $plugins->run_hooks("upload_attachment_thumb_start", $attacharray); $thumbnail = generate_thumbnail($mybb->settings['uploadspath'] . "/" . $filename, $mybb->settings['uploadspath'], $thumbname, $mybb->settings['attachthumbh'], $mybb->settings['attachthumbw']); if ($thumbnail['filename']) { $attacharray['thumbnail'] = $thumbnail['filename']; } elseif ($thumbnail['code'] == 4) { $attacharray['thumbnail'] = "SMALL"; } } if ($forumpermissions['modattachments'] == 1 && !is_moderator($forum['fid'], "canapproveunapproveattachs")) { $attacharray['visible'] = 0; } else { $attacharray['visible'] = 1; } $attacharray = $plugins->run_hooks("upload_attachment_do_insert", $attacharray); if ($prevattach['aid'] && $update_attachment == true) { unset($attacharray['downloads']); // Keep our download count if we're updating an attachment $db->update_query("attachments", $attacharray, "aid='" . $db->escape_string($prevattach['aid']) . "'"); // Remove old attachment file // Check if this attachment is referenced in any other posts. If it isn't, then we are safe to delete the actual file. $query = $db->simple_select("attachments", "COUNT(aid) as numreferences", "attachname='" . $db->escape_string($prevattach['attachname']) . "'"); if ($db->fetch_field($query, "numreferences") == 0) { delete_uploaded_file($mybb->settings['uploadspath'] . "/" . $prevattach['attachname']); if ($prevattach['thumbnail']) { delete_uploaded_file($mybb->settings['uploadspath'] . "/" . $prevattach['thumbnail']); } $date_directory = explode('/', $prevattach['attachname']); if (@is_dir($mybb->settings['uploadspath'] . "/" . $date_directory[0])) { delete_upload_directory($mybb->settings['uploadspath'] . "/" . $date_directory[0]); } } $aid = $prevattach['aid']; } else { $aid = $db->insert_query("attachments", $attacharray); if ($pid) { update_thread_counters($tid, array("attachmentcount" => "+1")); } } $ret['aid'] = $aid; return $ret; }
/** * Completely rebuild the counters for a particular thread (useful if they become out of sync) * * @param int The thread ID * @param array Optional thread array so we don't have to query it */ function rebuild_thread_counters($tid) { global $db; if (!$thread['tid']) { $thread = get_thread($tid); } $query = $db->simple_select("posts", "COUNT(*) AS replies", "tid='{$tid}' AND pid!='{$thread['firstpost']}' AND visible='1'"); $count['replies'] = $db->fetch_field($query, "replies"); if ($count['replies'] < 0) { $count['replies'] = 0; } // Unapproved posts $query = $db->simple_select("posts", "COUNT(pid) AS totunposts", "tid='{$tid}' AND pid != '{$thread['firstpost']}' AND visible='0'"); $count['unapprovedposts'] = $db->fetch_field($query, "totunposts"); if (!$count['unapprovedposts']) { $count['unapprovedposts'] = 0; } // Attachment count $query = $db->query("\n\t\t\tSELECT COUNT(aid) AS attachment_count\n\t\t\tFROM " . TABLE_PREFIX . "attachments a\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "posts p ON (a.pid=p.pid)\n\t\t\tWHERE p.tid='{$tid}'\n\t"); $count['attachmentcount'] = $db->fetch_field($query, "attachment_count"); if (!$count['attachmentcount']) { $count['attachmentcount'] = 0; } update_thread_counters($tid, $count); }
function save_raw_post_func($xmlrpc_params) { global $db, $lang, $theme, $plugins, $mybb, $session, $settings, $cache, $time, $mybbgroups; $lang->load("editpost"); $input = Tapatalk_Input::filterXmlInput(array('post_id' => Tapatalk_Input::INT, 'post_title' => Tapatalk_Input::STRING, 'post_content' => Tapatalk_Input::STRING, 'return_html' => Tapatalk_Input::INT, 'attachment_id_array' => Tapatalk_Input::RAW, 'group_id' => Tapatalk_Input::STRING, 'editreason' => Tapatalk_Input::STRING), $xmlrpc_params); $parser = new postParser(); // No permission for guests if (!$mybb->user['uid']) { return tt_no_permission(); } // Get post info $pid = $input['post_id']; $query = $db->simple_select("posts", "*", "pid='{$pid}'"); $post = $db->fetch_array($query); if (empty($input['post_title'])) { $input['post_title'] = $post['subject']; } if (!$post['pid']) { return xmlrespfalse($lang->error_invalidpost); } // Get thread info $tid = $post['tid']; $thread = get_thread($tid); if (!$thread['tid']) { return xmlrespfalse($lang->error_invalidthread); } $thread['subject'] = htmlspecialchars_uni($thread['subject']); // Get forum info $fid = $post['fid']; $forum = get_forum($fid); if (!$forum || $forum['type'] != "f") { return xmlrespfalse($lang->error_closedinvalidforum); } if ($forum['open'] == 0 || $mybb->user['suspendposting'] == 1) { return tt_no_permission(); } $forumpermissions = forum_permissions($fid); if (!is_moderator($fid, "caneditposts")) { if ($thread['closed'] == 1) { return xmlrespfalse($lang->redirect_threadclosed); } if ($forumpermissions['caneditposts'] == 0) { return tt_no_permission(); } if ($mybb->user['uid'] != $post['uid']) { return tt_no_permission(); } // Edit time limit $time = TIME_NOW; if ($mybb->settings['edittimelimit'] != 0 && $post['dateline'] < $time - $mybb->settings['edittimelimit'] * 60) { $lang->edit_time_limit = $lang->sprintf($lang->edit_time_limit, $mybb->settings['edittimelimit']); return xmlrespfalse($lang->edit_time_limit); } } // Check if this forum is password protected and we have a valid password tt_check_forum_password($forum['fid']); // Set up posthandler. require_once MYBB_ROOT . "inc/datahandlers/post.php"; $posthandler = new PostDataHandler("update"); $posthandler->action = "post"; // Set the post data that came from the input to the $post array. $post = array("pid" => $pid, "subject" => $input['post_title'], "uid" => $mybb->user['uid'], "username" => $mybb->user['username'], "edit_uid" => $mybb->user['uid'], "message" => $input['post_content']); if (version_compare($mybb->version, '1.8.0', '>=') && !empty($input['editreason'])) { $post["editreason"] = $input['editreason']; } // get subscription status $query = $db->simple_select("threadsubscriptions", 'notification', "uid='" . intval($mybb->user['uid']) . "' AND tid='" . intval($tid) . "'"); $substatus = $db->fetch_array($query); // Set up the post options from the input. $post['options'] = array("signature" => 1, "subscriptionmethod" => isset($substatus['notification']) ? $substatus['notification'] == 1 ? 'instant' : 'none' : '', "disablesmilies" => 0); $posthandler->set_data($post); // Now let the post handler do all the hard work. if (!$posthandler->validate_post()) { $post_errors = $posthandler->get_friendly_errors(); return xmlrespfalse(implode(" :: ", $post_errors)); } else { $postinfo = $posthandler->update_post(); $visible = $postinfo['visible']; $first_post = $postinfo['first_post']; // Help keep our attachments table clean. $db->delete_query("attachments", "filename='' OR filesize<1"); if ($visible == 0 && $first_post && !is_moderator($fid, "", $mybb->user['uid'])) { $state = 1; } else { if ($visible == 0 && !is_moderator($fid, "", $mybb->user['uid'])) { $state = 1; } else { $state = 0; } } } $pid = intval($pid); if (!empty($input['group_id_esc'])) { $db->update_query("attachments", array("pid" => $pid), "posthash='{$input['group_id_esc']}'"); } // update thread attachment account if (count($input['attachment_id_array']) > 0) { update_thread_counters($tid, array("attachmentcount" => "+" . count($input['attachment_id_array']))); } $post = get_post($pid); $parser_options = array(); $parser_options['allow_html'] = false; $parser_options['allow_mycode'] = true; $parser_options['allow_smilies'] = false; $parser_options['allow_imgcode'] = true; $parser_options['allow_videocode'] = true; $parser_options['nl2br'] = (bool) $input['return_html']; $parser_options['filter_badwords'] = 1; if (!$post['username']) { $post['username'] = $lang->guest; } if ($post['userusername']) { $parser_options['me_username'] = $post['userusername']; } else { $parser_options['me_username'] = $post['username']; } $post['message'] = $parser->parse_message($post['message'], $parser_options); $post['subject'] = $parser->parse_badwords($post['subject']); $result = new xmlrpcval(array('result' => new xmlrpcval(true, 'boolean'), 'result_text' => new xmlrpcval('', 'base64'), 'state' => new xmlrpcval($state, 'int'), 'post_title' => new xmlrpcval($post['subject'], 'base64'), 'post_content' => new xmlrpcval(process_post($post['message'], $input['return_html']), 'base64')), 'struct'); return new xmlrpcresp($result); }
/** * Restore multiple posts * * @param array $pids PIDs * @return boolean */ function restore_posts($pids) { global $db, $cache, $plugins; $num_posts = 0; if (empty($pids)) { return false; } // Make sure we only have valid values $pids = array_map('intval', $pids); $pid_list = implode(',', $pids); $pids = $threads_to_update = array(); // Make visible $update = array("visible" => 1); // We have three cases we deal with in these code segments: // 1) We're approving specific restored posts // 1.1) if the thread is deleted // 1.2) if the thread is restored // 2) We're restoring the firstpost of the thread, therefore restoring the thread itself // 3) We're doing both 1 and 2 $query = $db->query("\n\t\t\tSELECT p.tid\n\t\t\tFROM " . TABLE_PREFIX . "posts p\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "threads t ON (t.tid=p.tid)\n\t\t\tWHERE p.pid IN ({$pid_list}) AND p.visible = '-1' AND t.firstpost = p.pid AND t.visible = -1\n\t\t"); while ($post = $db->fetch_array($query)) { // This is the first post in the thread so we're approving the whole thread. $threads_to_update[] = $post['tid']; } if (!empty($threads_to_update)) { $this->restore_threads($threads_to_update); } $thread_counters = $forum_counters = $user_counters = array(); $query = $db->query("\n\t\t\tSELECT p.pid, p.tid, f.fid, f.usepostcounts, p.uid, t.visible AS threadvisible\n\t\t\tFROM " . TABLE_PREFIX . "posts p\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "threads t ON (t.tid=p.tid)\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "forums f ON (f.fid=p.fid)\n\t\t\tWHERE p.pid IN ({$pid_list}) AND p.visible = '-1' AND t.firstpost != p.pid\n\t\t"); while ($post = $db->fetch_array($query)) { $pids[] = $post['pid']; if (!isset($thread_counters[$post['tid']])) { $thread_counters[$post['tid']] = array('replies' => 0); } ++$thread_counters[$post['tid']]['replies']; // If the thread of this post is deleted then we've already taken into account this counter as implied. // Updating it again would cause it to double count if ($post['threadvisible'] == 1) { if (!isset($forum_counters[$post['fid']])) { $forum_counters[$post['fid']] = array('num_posts' => 0); } ++$forum_counters[$post['fid']]['num_posts']; } // If post counts enabled in this forum and the thread is approved, add 1 if ($post['usepostcounts'] != 0 && $post['threadvisible'] == 1) { if (!isset($user_counters[$post['uid']])) { $user_counters[$post['uid']] = 0; } ++$user_counters[$post['uid']]; } } if (empty($pids) && empty($threads_to_update)) { return false; } if (!empty($pids)) { $where = "pid IN (" . implode(',', $pids) . ")"; $db->update_query("posts", $update, $where); } $plugins->run_hooks("class_moderation_restore_posts", $pids); if (is_array($thread_counters)) { foreach ($thread_counters as $tid => $counters) { $counters_update = array("deletedposts" => "-" . $counters['replies'], "replies" => "+" . $counters['replies']); update_thread_counters($tid, $counters_update); update_last_post($tid); } } if (is_array($forum_counters)) { foreach ($forum_counters as $fid => $counters) { $updated_forum_stats = array('posts' => "+{$counters['num_posts']}", 'deletedposts' => "-{$counters['num_posts']}"); update_forum_counters($fid, $updated_forum_stats); update_forum_lastpost($fid); } } if (!empty($user_counters)) { foreach ($user_counters as $uid => $counter) { update_user_counters($uid, array('postnum' => "+{$counter}")); } } return true; }
} } if ($mybb->input['attachmentaid'] && isset($mybb->input['attachmentact']) && $mybb->input['action'] == "do_editpost" && $mybb->request_method == "post") { // Verify incoming POST request verify_post_check($mybb->input['my_post_key']); $mybb->input['attachmentaid'] = intval($mybb->input['attachmentaid']); if ($mybb->input['attachmentact'] == "remove") { remove_attachment($pid, "", $mybb->input['attachmentaid']); } elseif ($mybb->input['attachmentact'] == "approve" && is_moderator($fid, 'caneditposts')) { $update_sql = array("visible" => 1); $db->update_query("attachments", $update_sql, "aid='{$mybb->input['attachmentaid']}'"); update_thread_counters($post['tid'], array('attachmentcount' => "+1")); } elseif ($mybb->input['attachmentact'] == "unapprove" && is_moderator($fid, 'caneditposts')) { $update_sql = array("visible" => 0); $db->update_query("attachments", $update_sql, "aid='{$mybb->input['attachmentaid']}'"); update_thread_counters($post['tid'], array('attachmentcount' => "-1")); } if (!$mybb->input['submit']) { $mybb->input['action'] = "editpost"; } } if ($mybb->input['action'] == "deletepost" && $mybb->request_method == "post") { // Verify incoming POST request verify_post_check($mybb->input['my_post_key']); $plugins->run_hooks("editpost_deletepost"); if ($mybb->input['delete'] == 1) { $query = $db->simple_select("posts", "pid", "tid='{$tid}'", array("limit" => 1, "order_by" => "dateline", "order_dir" => "asc")); $firstcheck = $db->fetch_array($query); if ($firstcheck['pid'] == $pid) { $firstpost = 1; } else {
/** * Unapprove multiple posts * * @param array PIDs * @return boolean true */ function unapprove_posts($pids) { global $db, $cache; // Make sure we only have valid values $pids = array_map('intval', $pids); $pid_list = implode(',', $pids); $pids = $threads_to_update = array(); // Make invisible $approve = array("visible" => 0); // We have three cases we deal with in these code segments: // 1) We're unapproving specific approved posts // 1.1) if the thread is approved // 1.2) if the thread is unapproved // 2) We're unapproving the firstpost of the thread, therefore unapproving the thread itself // 3) We're doing both 1 and 2 $query = $db->query("\n\t\t\tSELECT p.tid\n\t\t\tFROM " . TABLE_PREFIX . "posts p\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "threads t ON (t.tid=p.tid)\n\t\t\tWHERE p.pid IN ({$pid_list}) AND p.visible = '1' AND t.firstpost = p.pid AND t.visible = 1\n\t\t"); while ($post = $db->fetch_array($query)) { // This is the first post in the thread so we're unapproving the whole thread. $threads_to_update[] = $post['tid']; } if (!empty($threads_to_update)) { $this->unapprove_threads($threads_to_update); } $thread_counters = array(); $forum_counters = array(); $query = $db->query("\n\t\t\tSELECT p.pid, p.tid, f.fid, f.usepostcounts, p.uid, t.visible AS threadvisible\n\t\t\tFROM " . TABLE_PREFIX . "posts p\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "threads t ON (t.tid=p.tid)\n\t\t\tLEFT JOIN " . TABLE_PREFIX . "forums f ON (f.fid=p.fid)\n\t\t\tWHERE p.pid IN ({$pid_list}) AND p.visible = '1' AND t.firstpost != p.pid\n\t\t"); while ($post = $db->fetch_array($query)) { $pids[] = $post['pid']; ++$thread_counters[$post['tid']]['unapprovedposts']; ++$thread_counters[$post['tid']]['replies']; // If the thread of this post is unapproved then we've already taken into account this counter as implied. // Updating it again would cause it to double count if ($post['threadvisible'] != 0) { ++$forum_counters[$post['fid']]['num_posts']; } // If post counts enabled in this forum and the thread is approved, subtract 1 if ($post['usepostcounts'] != 0 && $post['threadvisible'] == 1) { $db->update_query("users", array("postnum" => "postnum-1"), "uid='{$post['uid']}'", 1, true); } } if (empty($pids) && empty($threads_to_update)) { return false; } if (!empty($pids)) { $where = "pid IN (" . implode(',', $pids) . ")"; $db->update_query("posts", $approve, $where); } if (is_array($thread_counters)) { foreach ($thread_counters as $tid => $counters) { $counters_update = array("unapprovedposts" => "+" . $counters['unapprovedposts'], "replies" => "-" . $counters['replies']); update_thread_counters($tid, $counters_update); update_thread_data($tid); } } if (is_array($forum_counters)) { foreach ($forum_counters as $fid => $counters) { $updated_forum_stats = array("posts" => "-{$counters['num_posts']}", "unapprovedposts" => "+{$counters['num_posts']}", "threads" => "-{$counters['num_threads']}", "unapprovedthreads" => "+{$counters['num_threads']}"); update_forum_counters($fid, $updated_forum_stats); } } return true; }
/** * Updates a post that is already in the database. * */ function update_post() { global $db, $mybb, $plugins; // Yes, validating is required. if ($this->get_validated() != true) { die("The post needs to be validated before inserting it into the DB."); } if (count($this->get_errors()) > 0) { die("The post is not valid."); } $post =& $this->data; $post['pid'] = intval($post['pid']); $existing_post = get_post($post['pid']); $post['tid'] = $existing_post['tid']; $post['fid'] = $existing_post['fid']; $forum = get_forum($post['fid']); // Decide on the visibility of this post. if (isset($post['visible']) && $post['visible'] != $existing_post['visible']) { if ($forum['mod_edit_posts'] == 1 && !is_moderator($post['fid'], "", $post['uid'])) { if ($existing_post['visible'] == 1) { update_thread_data($existing_post['tid']); update_thread_counters($existing_post['tid'], array('replies' => '-1', 'unapprovedposts' => '+1')); update_forum_counters($existing_post['fid'], array('unapprovedthreads' => '+1', 'unapprovedposts' => '+1')); // Subtract from the users post count // Update the post count if this forum allows post counts to be tracked if ($forum['usepostcounts'] != 0) { $db->write_query("UPDATE " . TABLE_PREFIX . "users SET postnum=postnum-1 WHERE uid='{$existing_post['uid']}'"); } } $visible = 0; } else { if ($existing_post['visible'] == 0) { update_thread_data($existing_post['tid']); update_thread_counters($existing_post['tid'], array('replies' => '+1', 'unapprovedposts' => '-1')); update_forum_counters($existing_post['fid'], array('unapprovedthreads' => '-1', 'unapprovedposts' => '-1')); // Update the post count if this forum allows post counts to be tracked if ($forum['usepostcounts'] != 0) { $db->write_query("UPDATE " . TABLE_PREFIX . "users SET postnum=postnum+1 WHERE uid='{$existing_post['uid']}'"); } } $visible = 1; } } else { $visible = 0; if ($forum['mod_edit_posts'] != 1 || is_moderator($post['fid'], "", $post['uid'])) { $visible = 1; } } // Check if this is the first post in a thread. $options = array("order_by" => "dateline", "order_dir" => "asc", "limit_start" => 0, "limit" => 1); $query = $db->simple_select("posts", "pid", "tid='" . intval($post['tid']) . "'", $options); $first_post_check = $db->fetch_array($query); if ($first_post_check['pid'] == $post['pid']) { $first_post = true; } else { $first_post = false; } if ($existing_post['visible'] == 0) { $visible = 0; } // Update the thread details that might have been changed first. if ($first_post) { $this->tid = $post['tid']; $this->thread_update_data['visible'] = $visible; if (isset($post['prefix'])) { $this->thread_update_data['prefix'] = intval($post['prefix']); } if (isset($post['subject'])) { $this->thread_update_data['subject'] = $db->escape_string($post['subject']); } if (isset($post['icon'])) { $this->thread_update_data['icon'] = intval($post['icon']); } if (count($this->thread_update_data) > 0) { $plugins->run_hooks("datahandler_post_update_thread", $this); $db->update_query("threads", $this->thread_update_data, "tid='" . intval($post['tid']) . "'"); } } // Prepare array for post updating. $this->pid = $post['pid']; if (isset($post['subject'])) { $this->post_update_data['subject'] = $db->escape_string($post['subject']); } if (isset($post['message'])) { $this->post_update_data['message'] = $db->escape_string($post['message']); } if (isset($post['icon'])) { $this->post_update_data['icon'] = intval($post['icon']); } if (isset($post['options'])) { if (isset($post['options']['disablesmilies'])) { $this->post_update_data['smilieoff'] = $db->escape_string($post['options']['disablesmilies']); } if (isset($post['options']['signature'])) { $this->post_update_data['includesig'] = $db->escape_string($post['options']['signature']); } } // If we need to show the edited by, let's do so. if ($mybb->settings['showeditedby'] == 1 && !is_moderator($post['fid'], "caneditposts", $post['edit_uid']) || $mybb->settings['showeditedbyadmin'] == 1 && is_moderator($post['fid'], "caneditposts", $post['edit_uid'])) { $this->post_update_data['edituid'] = intval($post['edit_uid']); $this->post_update_data['edittime'] = TIME_NOW; } $this->post_update_data['visible'] = $visible; $plugins->run_hooks("datahandler_post_update", $this); $db->update_query("posts", $this->post_update_data, "pid='" . intval($post['pid']) . "'"); // Automatic subscription to the thread if ($post['options']['subscriptionmethod'] != "" && $post['uid'] > 0) { switch ($post['options']['subscriptionmethod']) { case "instant": $notification = 1; break; default: $notification = 0; } require_once MYBB_ROOT . "inc/functions_user.php"; add_subscribed_thread($post['tid'], $notification, $post['uid']); } else { $db->delete_query("threadsubscriptions", "uid='" . intval($post['uid']) . "' AND tid='" . intval($post['tid']) . "'"); } update_forum_lastpost($post['fid']); return array('visible' => $visible, 'first_post' => $first_post); }
function reply_post_func($xmlrpc_params) { global $db, $lang, $theme, $plugins, $mybb, $session, $settings, $cache, $time, $mybbgroups, $tid, $pid, $visible, $thread, $post; $input = Tapatalk_Input::filterXmlInput(array('forum_id' => Tapatalk_Input::INT, 'topic_id' => Tapatalk_Input::INT, 'subject' => Tapatalk_Input::STRING, 'text_body' => Tapatalk_Input::STRING, 'attachment_id_array' => Tapatalk_Input::RAW, 'group_id' => Tapatalk_Input::STRING, 'return_html' => Tapatalk_Input::INT), $xmlrpc_params); $lang->load("newreply"); $parser = new Tapatalk_Parser(); $tid = $input['topic_id']; $options = array("limit" => 1); $query = $db->simple_select("threads", "*", "tid='" . $tid . "'"); if ($db->num_rows($query) == 0) { return xmlrespfalse($lang->error_invalidthread); } $thread = $db->fetch_array($query); $fid = $thread['fid']; // Get forum info $forum = get_forum($fid); if (!$forum) { return xmlrespfalse($lang->error_invalidforum); } $forumpermissions = forum_permissions($fid); if ($thread['visible'] == 0 && !is_moderator($fid) || $thread['visible'] < 0) { return xmlrespfalse($lang->error_invalidthread); } if ($forum['open'] == 0 || $forum['type'] != "f") { return xmlrespfalse($lang->error_closedinvalidforum); } if ($mybb->user['uid'] < 1 || $forumpermissions['canview'] == 0 || $forumpermissions['canpostreplys'] == 0 || $mybb->user['suspendposting'] == 1) { return tt_no_permission(); } if ($forumpermissions['canonlyviewthreads'] == 1 && $thread['uid'] != $mybb->user['uid']) { return tt_no_permission(); } tt_check_forum_password($forum['fid']); // Check to see if the thread is closed, and if the user is a mod. if (!is_moderator($fid, "caneditposts")) { if ($thread['closed'] == 1) { return xmlrespfalse($lang->redirect_threadclosed); } } // Is the currently logged in user a moderator of this forum? if (is_moderator($fid)) { $ismod = true; } else { $ismod = false; } if (!empty($input['group_id'])) { $posthash = $input['group_id']; } else { $posthash = md5($thread['tid'] . $mybb->user['uid'] . random_str()); } if ($mybb->settings['maxposts'] > 0 && $mybb->usergroup['cancp'] != 1) { $daycut = TIME_NOW - 60 * 60 * 24; $query = $db->simple_select("posts", "COUNT(*) AS posts_today", "uid='{$mybb->user['uid']}' AND visible='1' AND dateline>{$daycut}"); $post_count = $db->fetch_field($query, "posts_today"); if ($post_count >= $mybb->settings['maxposts']) { $lang->error_maxposts = $lang->sprintf($lang->error_maxposts, $mybb->settings['maxposts']); return xmlrespfalse($lang->error_maxposts); } } $username = $mybb->user['username']; $uid = $mybb->user['uid']; $user_check = "p.uid='{$uid}'"; if (version_compare($mybb->version, '1.8.0', '<')) { $query = $db->simple_select("posts p", "p.pid, p.visible", "{$user_check} AND p.tid='{$thread['tid']}' AND p.subject='" . $db->escape_string($mybb->input['subject']) . "' AND p.message='" . $db->escape_string($mybb->input['message']) . "' AND p.posthash='" . $db->escape_string($mybb->input['posthash']) . "' AND p.visible != '-2'"); } else { $query = $db->simple_select("posts p", "p.pid, p.visible", "{$user_check} AND p.tid='{$thread['tid']}' AND p.subject='" . $db->escape_string($mybb->get_input('subject')) . "' AND p.message='" . $db->escape_string($mybb->get_input('message')) . "' AND p.visible != '-2' AND p.dateline>" . (TIME_NOW - 600)); } $duplicate_check = $db->fetch_field($query, "pid"); if ($duplicate_check) { return xmlrespfalse($lang->error_post_already_submitted); } require_once MYBB_ROOT . "inc/datahandlers/post.php"; $posthandler = new PostDataHandler("insert"); $post = array("tid" => $input['topic_id'], "replyto" => 0, "fid" => $thread['fid'], "subject" => $input['subject'], "icon" => 0, "uid" => $uid, "username" => $username, "message" => $input['text_body'], "ipaddress" => get_ip(), "posthash" => $posthash); if ($mybb->input['pid']) { $post['pid'] = $mybb->input['pid']; } $post['savedraft'] = 0; // Set up the post options from the input. $post['options'] = array("signature" => 1, "subscriptionmethod" => $mybb->user['subscriptionmethod'] == 0 ? '' : $mybb->user['subscriptionmethod'], "disablesmilies" => 0); $post['modoptions']['stickthread'] = $thread['sticky']; $post['modoptions']['closethread'] = $thread['closed']; $posthandler->set_data($post); // Now let the post handler do all the hard work. $valid_post = $posthandler->validate_post(); $post_errors = array(); // Fetch friendly error messages if this is an invalid post if (!$valid_post) { $post_errors = $posthandler->get_friendly_errors(); } // Mark thread as read require_once MYBB_ROOT . "inc/functions_indicators.php"; mark_thread_read($tid, $fid); // One or more errors returned, fetch error list and throw to newreply page if (count($post_errors) > 0) { return xmlrespfalse(implode(" :: ", $post_errors)); } else { $postinfo = $posthandler->insert_post(); $pid = $postinfo['pid']; $visible = $postinfo['visible']; tapatalk_push_reply(); tapatalk_push_quote(); tapatalk_push_tag(); // Deciding the fate if ($visible == -2) { $state = 1; } elseif ($visible == 1) { $state = 0; } else { $state = 1; } } $pid = intval($pid); if (!empty($input['group_id_esc'])) { $db->update_query("attachments", array("pid" => $pid), "posthash='{$input['group_id_esc']}'"); } // update thread attachment account if (count($input['attachment_id_array']) > 0) { update_thread_counters($tid, array("attachmentcount" => "+" . count($input['attachment_id_array']))); } $post = get_post($pid); $parser_options = array(); $parser_options['allow_html'] = false; $parser_options['allow_mycode'] = true; $parser_options['allow_smilies'] = false; $parser_options['allow_imgcode'] = true; $parser_options['allow_videocode'] = true; $parser_options['nl2br'] = (bool) $input['return_html']; $parser_options['filter_badwords'] = 1; if (!$post['username']) { $post['username'] = $lang->guest; } if ($post['userusername']) { $parser_options['me_username'] = $post['userusername']; } else { $parser_options['me_username'] = $post['username']; } $post['message'] = post_bbcode_clean($post['message']); $post['message'] = $parser->parse_message($post['message'], $parser_options); global $attachcache; $attachcache = array(); if ($thread['attachmentcount'] > 0) { // Now lets fetch all of the attachments for these posts. $query = $db->simple_select("attachments", "*", "pid='{$pid}'"); while ($attachment = $db->fetch_array($query)) { $attachcache[$attachment['pid']][$attachment['aid']] = $attachment; } } $attachment_list = process_post_attachments($post['pid'], $post); $can_delete = 0; if ($mybb->user['uid'] == $post['uid']) { if ($forumpermissions['candeletethreads'] == 1 && $postcounter == 1) { $can_delete = 1; } else { if ($forumpermissions['candeleteposts'] == 1 && $postcounter != 1) { $can_delete = 1; } } } $can_delete = (is_moderator($fid, "candeleteposts") || $can_delete == 1) && $mybb->user['uid'] != 0; $result = new xmlrpcval(array('result' => new xmlrpcval(true, 'boolean'), 'result_text' => new xmlrpcval('', 'base64'), 'post_id' => new xmlrpcval($postinfo['pid'], 'string'), 'state' => new xmlrpcval($state, 'int'), 'post_author_id' => new xmlrpcval($mybb->user['uid'], 'string'), 'post_author_name' => new xmlrpcval(basic_clean($mybb->user['username']), 'base64'), 'icon_url' => new xmlrpcval(absolute_url($mybb->user['avatar']), 'string'), 'post_content' => new xmlrpcval(process_post($post['message'], $input['return_html']), 'base64'), 'can_edit' => new xmlrpcval(is_moderator($fid, "caneditposts") || $thread['closed'] == 0 && $forumpermissions['caneditposts'] == 1, 'boolean'), 'can_delete' => new xmlrpcval($can_delete, 'boolean'), 'post_time' => new xmlrpcval(mobiquo_iso8601_encode(TIME_NOW), 'dateTime.iso8601'), 'timestamp' => new xmlrpcval(TIME_NOW, 'string'), 'attachments' => new xmlrpcval($attachment_list, 'array')), 'struct'); return new xmlrpcresp($result); }
/** * Merge one thread into another * * @param int Thread that will be merged into destination * @param int Destination thread * @param string New thread subject * @return boolean true */ function merge_threads($mergetid, $tid, $subject) { global $db, $mybb, $mergethread, $thread, $plugins; $mergetid = intval($mergetid); $tid = intval($tid); if (!isset($mergethread['tid']) || $mergethread['tid'] != $mergetid) { $query = $db->simple_select("threads", "*", "tid='{$mergetid}'"); $mergethread = $db->fetch_array($query); } if (!isset($thread['tid']) || $thread['tid'] != $tid) { $query = $db->simple_select("threads", "*", "tid='{$tid}'"); $thread = $db->fetch_array($query); } $pollsql = ''; if ($mergethread['poll']) { $pollsql['poll'] = $mergethread['poll']; $sqlarray = array("tid" => $tid); $db->update_query("polls", $sqlarray, "tid='" . intval($mergethread['tid']) . "'"); } else { $query = $db->simple_select("threads", "*", "poll='{$mergethread['poll']}' AND tid != '{$mergetid}'"); $pollcheck = $db->fetch_array($query); if (!$pollcheck['poll']) { $db->delete_query("polls", "pid='{$mergethread['poll']}'"); $db->delete_query("pollvotes", "pid='{$mergethread['poll']}'"); } } $subject = $db->escape_string($subject); $sqlarray = array("tid" => $tid, "fid" => $thread['fid'], "replyto" => 0); $db->update_query("posts", $sqlarray, "tid='{$mergetid}'"); $pollsql['subject'] = $subject; $db->update_query("threads", $pollsql, "tid='{$tid}'"); $sqlarray = array("closed" => "moved|{$tid}"); $db->update_query("threads", $sqlarray, "closed='moved|{$mergetid}'"); $sqlarray = array("tid" => $tid); $db->update_query("threadsubscriptions", $sqlarray, "tid='{$mergetid}'"); update_first_post($tid); $arguments = array("mergetid" => $mergetid, "tid" => $tid, "subject" => $subject); $plugins->run_hooks("class_moderation_merge_threads", $arguments); $this->delete_thread($mergetid); $updated_stats = array("replies" => '+' . ($mergethread['replies'] + 1), "unapprovedposts" => "+{$mergethread['unapprovedposts']}", "attachmentcount" => "+{$mergethread['attachmentcount']}"); update_thread_counters($tid, $updated_stats); // Thread is not in current forum if ($mergethread['fid'] != $thread['fid']) { // If new thread is unapproved, implied counter comes in to effect if ($thread['visible'] == 0) { $updated_stats = array("unapprovedposts" => '+' . ($mergethread['replies'] + $mergethread['unapprovedposts'])); } else { $updated_stats = array("posts" => '+' . ($mergethread['replies'] + 1), "unapprovedposts" => "+{$mergethread['unapprovedposts']}"); } update_forum_counters($thread['fid'], $updated_stats); } return true; }
/** * Upload an attachment in to the file system * * @param array Attachment data (as fed by PHPs $_FILE) * @return array Array of attachment data if successful, otherwise array of error data */ function upload_attachment($attachment) { global $db, $theme, $templates, $posthash, $pid, $tid, $forum, $mybb, $lang, $plugins, $cache; $posthash = $db->escape_string($mybb->input['posthash']); if (isset($attachment['error']) && $attachment['error'] != 0) { $ret['error'] = $lang->error_uploadfailed . $lang->error_uploadfailed_detail; switch ($attachment['error']) { case 1: // UPLOAD_ERR_INI_SIZE $ret['error'] .= $lang->error_uploadfailed_php1; break; case 2: // UPLOAD_ERR_FORM_SIZE $ret['error'] .= $lang->error_uploadfailed_php2; break; case 3: // UPLOAD_ERR_PARTIAL $ret['error'] .= $lang->error_uploadfailed_php3; break; case 4: // UPLOAD_ERR_NO_FILE $ret['error'] .= $lang->error_uploadfailed_php4; break; case 6: // UPLOAD_ERR_NO_TMP_DIR $ret['error'] .= $lang->error_uploadfailed_php6; break; case 7: // UPLOAD_ERR_CANT_WRITE $ret['error'] .= $lang->error_uploadfailed_php7; break; default: $ret['error'] .= $lang->sprintf($lang->error_uploadfailed_phpx, $attachment['error']); break; } return $ret; } if (!is_uploaded_file($attachment['tmp_name']) || empty($attachment['tmp_name'])) { $ret['error'] = $lang->error_uploadfailed . $lang->error_uploadfailed_php4; return $ret; } $ext = get_extension($attachment['name']); // Check if we have a valid extension $query = $db->simple_select("attachtypes", "*", "extension='" . $db->escape_string($ext) . "'"); $attachtype = $db->fetch_array($query); if (!$attachtype['atid']) { $ret['error'] = $lang->error_attachtype; return $ret; } // Check the size if ($attachment['size'] > $attachtype['maxsize'] * 1024 && $attachtype['maxsize'] != "") { $ret['error'] = $lang->sprintf($lang->error_attachsize, $attachtype['maxsize']); return $ret; } // Double check attachment space usage if ($mybb->usergroup['attachquota'] > 0) { $query = $db->simple_select("attachments", "SUM(filesize) AS ausage", "uid='" . $mybb->user['uid'] . "'"); $usage = $db->fetch_array($query); $usage = $usage['ausage'] + $attachment['size']; if ($usage > $mybb->usergroup['attachquota'] * 1024) { $friendlyquota = get_friendly_size($mybb->usergroup['attachquota'] * 1024); $ret['error'] = $lang->sprintf($lang->error_reachedattachquota, $friendlyquota); return $ret; } } // Check if an attachment with this name is already in the post $query = $db->simple_select("attachments", "*", "filename='" . $db->escape_string($attachment['name']) . "' AND (posthash='{$posthash}' OR (pid='" . intval($pid) . "' AND pid!='0'))"); $prevattach = $db->fetch_array($query); if ($prevattach['aid']) { $ret['error'] = $lang->error_alreadyuploaded; return $ret; } // Check if the attachment directory (YYYYMM) exists, if not, create it $month_dir = gmdate("Ym"); if (!@is_dir($mybb->settings['uploadspath'] . "/" . $month_dir)) { @mkdir($mybb->settings['uploadspath'] . "/" . $month_dir); // Still doesn't exist - oh well, throw it in the main directory if (!@is_dir($mybb->settings['uploadspath'] . "/" . $month_dir)) { $month_dir = ''; } } // If safe_mode is enabled, don't attempt to use the monthly directories as it won't work if (ini_get('safe_mode') == 1 || strtolower(ini_get('safe_mode')) == 'on') { $month_dir = ''; } // All seems to be good, lets move the attachment! $filename = "post_" . $mybb->user['uid'] . "_" . TIME_NOW . "_" . md5(random_str()) . ".attach"; $file = upload_file($attachment, $mybb->settings['uploadspath'] . "/" . $month_dir, $filename); // Failed to create the attachment in the monthly directory, just throw it in the main directory if ($file['error'] && $month_dir) { $file = upload_file($attachment, $mybb->settings['uploadspath'] . '/', $filename); } if ($month_dir) { $filename = $month_dir . "/" . $filename; } if ($file['error']) { $ret['error'] = $lang->error_uploadfailed . $lang->error_uploadfailed_detail; switch ($file['error']) { case 1: $ret['error'] .= $lang->error_uploadfailed_nothingtomove; break; case 2: $ret['error'] .= $lang->error_uploadfailed_movefailed; break; } return $ret; } // Lets just double check that it exists if (!file_exists($mybb->settings['uploadspath'] . "/" . $filename)) { $ret['error'] = $lang->error_uploadfailed . $lang->error_uploadfailed_detail . $lang->error_uploadfailed_lost; return $ret; } // Generate the array for the insert_query $attacharray = array("pid" => intval($pid), "posthash" => $posthash, "uid" => $mybb->user['uid'], "filename" => $db->escape_string($file['original_filename']), "filetype" => $db->escape_string($file['type']), "filesize" => intval($file['size']), "attachname" => $filename, "downloads" => 0, "dateuploaded" => TIME_NOW); // If we're uploading an image, check the MIME type compared to the image type and attempt to generate a thumbnail if ($ext == "gif" || $ext == "png" || $ext == "jpg" || $ext == "jpeg" || $ext == "jpe") { // Check a list of known MIME types to establish what kind of image we're uploading switch (my_strtolower($file['type'])) { case "image/gif": $img_type = 1; break; case "image/jpeg": case "image/x-jpg": case "image/x-jpeg": case "image/pjpeg": case "image/jpg": $img_type = 2; break; case "image/png": case "image/x-png": $img_type = 3; break; default: $img_type = 0; } $supported_mimes = array(); $attachtypes = $cache->read("attachtypes"); foreach ($attachtypes as $attachtype) { if (!empty($attachtype['mimetype'])) { $supported_mimes[] = $attachtype['mimetype']; } } // Check if the uploaded file type matches the correct image type (returned by getimagesize) $img_dimensions = @getimagesize($mybb->settings['uploadspath'] . "/" . $filename); if (!is_array($img_dimensions) || $img_dimensions[2] != $img_type && !in_array(mime_content_type($filename), $supported_mimes)) { @unlink($mybb->settings['uploadspath'] . "/" . $filename); $ret['error'] = $lang->error_uploadfailed; return $ret; } require_once MYBB_ROOT . "inc/functions_image.php"; $thumbname = str_replace(".attach", "_thumb.{$ext}", $filename); $thumbnail = generate_thumbnail($mybb->settings['uploadspath'] . "/" . $filename, $mybb->settings['uploadspath'], $thumbname, $mybb->settings['attachthumbh'], $mybb->settings['attachthumbw']); if ($thumbnail['filename']) { $attacharray['thumbnail'] = $thumbnail['filename']; } elseif ($thumbnail['code'] == 4) { $attacharray['thumbnail'] = "SMALL"; } } if ($forum['modattachments'] == 1 && !is_moderator($forum['fid'], "", $mybb->user['uid'])) { $attacharray['visible'] = 0; } else { $attacharray['visible'] = 1; } $plugins->run_hooks_by_ref("upload_attachment_do_insert", $attacharray); $aid = $db->insert_query("attachments", $attacharray); if ($tid) { update_thread_counters($tid, array("attachmentcount" => "+1")); } $ret['aid'] = $aid; return $ret; }