/** * When inserting a new reply, make sure the protected meta data is set correctly. * * We can't use WP_JSON_Posts::add_meta() here because the required meta is deemed * protected by @see is_protected_meta(). * * @see WP_JSON_Posts::insert_post() * @see WP_JSON_Posts::add_meta() */ public function add_protected_meta($post, $data, $update) { if (!$update && $this->type == $post['post_type']) { // Forum meta $reply_meta = array('author_ip' => bbp_current_author_ip(), 'forum_id' => bbp_get_topic_forum_id($post['post_parent']), 'topic_id' => $post['post_parent']); // Insert reply meta foreach ($reply_meta as $meta_key => $meta_value) { update_post_meta($post['ID'], '_bbp_' . $meta_key, $meta_value); } // Update the topic $topic_id = bbp_get_reply_topic_id($post['ID']); if (!empty($topic_id)) { bbp_update_topic($topic_id); } } }
/** * Handle all the extra meta stuff from posting a new topic * * @param int $topic_id Optional. Topic id * @param int $forum_id Optional. Forum id * @param bool|array $anonymous_data Optional logged-out user data. * @param int $author_id Author id * @param bool $is_edit Optional. Is the post being edited? Defaults to false. * @uses bbp_get_topic_id() To get the topic id * @uses bbp_get_forum_id() To get the forum id * @uses bbp_get_current_user_id() To get the current user id * @yses bbp_get_topic_forum_id() To get the topic forum id * @uses update_post_meta() To update the topic metas * @uses set_transient() To update the flood check transient for the ip * @uses bbp_update_user_last_posted() To update the users last posted time * @uses bbp_is_subscriptions_active() To check if the subscriptions feature is * activated or not * @uses bbp_is_user_subscribed() To check if the user is subscribed * @uses bbp_remove_user_subscription() To remove the user's subscription * @uses bbp_add_user_subscription() To add the user's subscription * @uses bbp_update_topic_forum_id() To update the topic's forum id * @uses bbp_update_topic_topic_id() To update the topic's topic id * @uses bbp_update_topic_last_reply_id() To update the last reply id topic meta * @uses bbp_update_topic_last_active_id() To update the topic last active id * @uses bbp_update_topic_last_active_time() To update the last active topic meta * @uses bbp_update_topic_reply_count() To update the topic reply count * @uses bbp_update_topic_reply_count_hidden() To udpate the topic hidden reply count * @uses bbp_update_topic_voice_count() To update the topic voice count * @uses bbp_update_topic_walker() To udpate the topic's ancestors */ function bbp_update_topic($topic_id = 0, $forum_id = 0, $anonymous_data = false, $author_id = 0, $is_edit = false) { // Validate the ID's passed from 'bbp_new_topic' action $topic_id = bbp_get_topic_id($topic_id); $forum_id = bbp_get_forum_id($forum_id); // Bail if there is no topic if (empty($topic_id)) { return; } // Check author_id if (empty($author_id)) { $author_id = bbp_get_current_user_id(); } // Check forum_id if (empty($forum_id)) { $forum_id = bbp_get_topic_forum_id($topic_id); } // If anonymous post, store name, email, website and ip in post_meta. // It expects anonymous_data to be sanitized. // Check bbp_filter_anonymous_post_data() for sanitization. if (!empty($anonymous_data) && is_array($anonymous_data)) { // Parse arguments against default values $r = bbp_parse_args($anonymous_data, array('bbp_anonymous_name' => '', 'bbp_anonymous_email' => '', 'bbp_anonymous_website' => ''), 'update_topic'); // Update all anonymous metas foreach ($r as $anon_key => $anon_value) { update_post_meta($topic_id, '_' . $anon_key, (string) $anon_value, false); } // Set transient for throttle check (only on new, not edit) if (empty($is_edit)) { set_transient('_bbp_' . bbp_current_author_ip() . '_last_posted', time()); } } else { if (empty($is_edit) && !current_user_can('throttle')) { bbp_update_user_last_posted($author_id); } } // Handle Subscription Checkbox if (bbp_is_subscriptions_active() && !empty($author_id)) { $subscribed = bbp_is_user_subscribed($author_id, $topic_id); $subscheck = !empty($_POST['bbp_topic_subscription']) && 'bbp_subscribe' === $_POST['bbp_topic_subscription'] ? true : false; // Subscribed and unsubscribing if (true === $subscribed && false === $subscheck) { bbp_remove_user_subscription($author_id, $topic_id); // Subscribing } elseif (false === $subscribed && true === $subscheck) { bbp_add_user_subscription($author_id, $topic_id); } } // Forum topic meta bbp_update_topic_forum_id($topic_id, $forum_id); bbp_update_topic_topic_id($topic_id, $topic_id); // Update associated topic values if this is a new topic if (empty($is_edit)) { // Update poster IP if not editing update_post_meta($topic_id, '_bbp_author_ip', bbp_current_author_ip(), false); // Last active time $last_active = current_time('mysql'); // Reply topic meta bbp_update_topic_last_reply_id($topic_id, 0); bbp_update_topic_last_active_id($topic_id, $topic_id); bbp_update_topic_last_active_time($topic_id, $last_active); bbp_update_topic_reply_count($topic_id, 0); bbp_update_topic_reply_count_hidden($topic_id, 0); bbp_update_topic_voice_count($topic_id); // Walk up ancestors and do the dirty work bbp_update_topic_walker($topic_id, $last_active, $forum_id, 0, false); } }
/** * Checks topics and replies against the discussion blacklist of blocked keys * * @since 2.0.0 bbPress (r3446) * * @param array $anonymous_data Anonymous user data * @param int $author_id Topic or reply author ID * @param string $title The title of the content * @param string $content The content being posted * @uses bbp_is_user_keymaster() Allow keymasters to bypass blacklist * @uses bbp_current_author_ip() To get current user IP address * @uses bbp_current_author_ua() To get current user agent * @return bool True if test is passed, false if fail */ function bbp_check_for_blacklist($anonymous_data = false, $author_id = 0, $title = '', $content = '') { // Allow for blacklist check to be skipped if (apply_filters('bbp_bypass_check_for_blacklist', false, $anonymous_data, $author_id, $title, $content)) { return true; } // Bail if keymaster is author if (!empty($author_id) && bbp_is_user_keymaster($author_id)) { return true; } /** Blacklist *************************************************************/ /** * Filters the bbPress blacklist keys. * * @since 2.6.0 bbPress (r6050) * * @param string $blacklist List of blacklist keys. One per new line. */ $blacklist = apply_filters('bbp_blacklist_keys', trim(get_option('blacklist_keys'))); // Bail if blacklist is empty if (empty($blacklist)) { return true; } /** User Data *************************************************************/ // Define local variable $_post = array(); // Map anonymous user data if (!empty($anonymous_data)) { $_post['author'] = $anonymous_data['bbp_anonymous_name']; $_post['email'] = $anonymous_data['bbp_anonymous_email']; $_post['url'] = $anonymous_data['bbp_anonymous_website']; // Map current user data } elseif (!empty($author_id)) { // Get author data $user = get_userdata($author_id); // If data exists, map it if (!empty($user)) { $_post['author'] = $user->display_name; $_post['email'] = $user->user_email; $_post['url'] = $user->user_url; } } // Current user IP and user agent $_post['user_ip'] = bbp_current_author_ip(); $_post['user_ua'] = bbp_current_author_ua(); // Post title and content $_post['title'] = $title; $_post['content'] = $content; // Ensure HTML tags are not being used to bypass the blacklist. $_post['comment_without_html'] = wp_strip_all_tags($content); /** Words *****************************************************************/ // Get words separated by new lines $words = explode("\n", $blacklist); // Loop through words foreach ((array) $words as $word) { // Trim the whitespace from the word $word = trim($word); // Skip empty lines if (empty($word)) { continue; } // Do some escaping magic so that '#' chars in the // spam words don't break things: $word = preg_quote($word, '#'); $pattern = "#{$word}#i"; // Loop through post data foreach ($_post as $post_data) { // Check each user data for current word if (preg_match($pattern, $post_data)) { // Post does not pass return false; } } } // Check passed successfully return true; }
/** * @group canonical * @covers ::bbp_create_initial_content */ public function test_bbp_create_initial_content() { $category_id = $this->factory->forum->create(array('forum_meta' => array('_bbp_forum_type' => 'category', '_bbp_status' => 'open'))); bbp_create_initial_content(array('forum_parent' => $category_id)); $forum_id = bbp_forum_query_subforum_ids($category_id); $forum_id = (int) $forum_id[0]; $topic_id = bbp_get_forum_last_topic_id($forum_id); $reply_id = bbp_get_forum_last_reply_id($forum_id); // Forum post $this->assertSame('General', bbp_get_forum_title($forum_id)); $this->assertSame('General chit-chat', bbp_get_forum_content($forum_id)); $this->assertSame('open', bbp_get_forum_status($forum_id)); $this->assertTrue(bbp_is_forum_public($forum_id)); $this->assertSame($category_id, bbp_get_forum_parent_id($forum_id)); // Topic post $this->assertSame($forum_id, bbp_get_topic_forum_id($topic_id)); $this->assertSame('Hello World!', bbp_get_topic_title($topic_id)); remove_all_filters('bbp_get_topic_content'); $topic_content = "I am the first topic in your new forums."; $this->assertSame($topic_content, bbp_get_topic_content($topic_id)); $this->assertSame('publish', bbp_get_topic_status($topic_id)); $this->assertTrue(bbp_is_topic_published($topic_id)); // Reply post $this->assertSame($forum_id, bbp_get_reply_forum_id($reply_id)); $this->assertSame('Reply To: Hello World!', bbp_get_reply_title($reply_id)); $this->assertSame($reply_id, bbp_get_reply_title_fallback($reply_id)); remove_all_filters('bbp_get_reply_content'); $reply_content = "Oh, and this is what a reply looks like."; $this->assertSame($reply_content, bbp_get_reply_content($reply_id)); $this->assertSame('publish', bbp_get_reply_status($reply_id)); $this->assertTrue(bbp_is_reply_published($reply_id)); // Category meta $this->assertSame(1, bbp_get_forum_subforum_count($category_id, true)); $this->assertSame(0, bbp_get_forum_topic_count($category_id, false, true)); $this->assertSame(0, bbp_get_forum_topic_count_hidden($category_id, true)); $this->assertSame(0, bbp_get_forum_reply_count($category_id, false, true)); $this->assertSame(1, bbp_get_forum_topic_count($category_id, true, true)); $this->assertSame(1, bbp_get_forum_reply_count($category_id, true, true)); $this->assertSame(0, bbp_get_forum_post_count($category_id, false, true)); $this->assertSame(2, bbp_get_forum_post_count($category_id, true, true)); $this->assertSame($topic_id, bbp_get_forum_last_topic_id($category_id)); $this->assertSame('Hello World!', bbp_get_forum_last_topic_title($category_id)); $this->assertSame($reply_id, bbp_get_forum_last_reply_id($category_id)); $this->assertSame('Reply To: Hello World!', bbp_get_forum_last_reply_title($category_id)); $this->assertSame($reply_id, bbp_get_forum_last_active_id($category_id)); $this->assertSame('1 day, 16 hours ago', bbp_get_forum_last_active_time($category_id)); // Forum meta $this->assertSame(0, bbp_get_forum_subforum_count($forum_id, true)); $this->assertSame(1, bbp_get_forum_topic_count($forum_id, false, true)); $this->assertSame(0, bbp_get_forum_topic_count_hidden($forum_id, true)); $this->assertSame(1, bbp_get_forum_reply_count($forum_id, false, true)); $this->assertSame(1, bbp_get_forum_topic_count($forum_id, true, true)); $this->assertSame(1, bbp_get_forum_reply_count($forum_id, true, true)); $this->assertSame(2, bbp_get_forum_post_count($forum_id, false, true)); $this->assertSame(2, bbp_get_forum_post_count($forum_id, true, true)); $this->assertSame($topic_id, bbp_get_forum_last_topic_id($forum_id)); $this->assertSame('Hello World!', bbp_get_forum_last_topic_title($forum_id)); $this->assertSame($reply_id, bbp_get_forum_last_reply_id($forum_id)); $this->assertSame('Reply To: Hello World!', bbp_get_forum_last_reply_title($forum_id)); $this->assertSame($reply_id, bbp_get_forum_last_active_id($forum_id)); $this->assertSame('1 day, 16 hours ago', bbp_get_forum_last_active_time($forum_id)); // Topic meta $this->assertSame('127.0.0.1', bbp_current_author_ip($topic_id)); $this->assertSame($forum_id, bbp_get_topic_forum_id($topic_id)); $this->assertSame(1, bbp_get_topic_voice_count($topic_id, true)); $this->assertSame(1, bbp_get_topic_reply_count($topic_id, true)); $this->assertSame(0, bbp_get_topic_reply_count_hidden($topic_id, true)); $this->assertSame($reply_id, bbp_get_topic_last_reply_id($topic_id)); $this->assertSame($reply_id, bbp_get_topic_last_active_id($topic_id)); $this->assertSame('1 day, 16 hours ago', bbp_get_topic_last_active_time($topic_id)); // Reply Meta $this->assertSame('127.0.0.1', bbp_current_author_ip($reply_id)); $this->assertSame($forum_id, bbp_get_reply_forum_id($reply_id)); $this->assertSame($topic_id, bbp_get_reply_topic_id($reply_id)); }
/** * Submit a post for spamming or hamming * * @since bbPress (r3277) * * @param int $post_id * * @global WP_Query $wpdb * @global string $akismet_api_host * @global string $akismet_api_port * @global object $current_user * @global object $current_site * * @uses current_filter() To get the reply_id * @uses get_post() To get the post object * @uses get_the_author_meta() To get the author meta * @uses get_post_meta() To get the post meta * @uses bbp_get_user_profile_url() To get a user's profile url * @uses get_permalink() To get the permalink of the post_parent * @uses akismet_get_user_roles() To get the role(s) of the post_author * @uses bbp_current_author_ip() To get the IP address of the current user * @uses BBP_Akismet::maybe_spam() To submit the post as ham or spam * @uses update_post_meta() To update the post meta with some Akismet data * @uses do_action() To call the 'bbp_akismet_submit_spam_post' and 'bbp_akismet_submit_ham_post' hooks * * @return array Array of existing topic terms */ public function submit_post($post_id = 0) { global $current_user, $current_site; // Innocent until proven guilty $request_type = 'ham'; $current_filter = current_filter(); // Check this filter and adjust the $request_type accordingly switch ($current_filter) { // Mysterious, and straight from the can case 'bbp_spammed_topic': case 'bbp_spammed_reply': $request_type = 'spam'; break; // Honey-glazed, a straight off the bone // Honey-glazed, a straight off the bone case 'bbp_unspammed_topic': case 'bbp_unspammed_reply': $request_type = 'ham'; break; // Possibly poison... // Possibly poison... default: return; } // Setup some variables $post_id = (int) $post_id; // Make sure we have a post $_post = get_post($post_id); // Bail if get_post() fails if (empty($_post)) { return; } // Bail if we're spamming, but the post_status isn't spam if ('spam' == $request_type && bbp_get_spam_status_id() != $_post->post_status) { return; } // Set some default post_data $post_data = array('comment_approved' => $_post->post_status, 'comment_author' => $_post->post_author ? get_the_author_meta('display_name', $_post->post_author) : get_post_meta($post_id, '_bbp_anonymous_name', true), 'comment_author_email' => $_post->post_author ? get_the_author_meta('email', $_post->post_author) : get_post_meta($post_id, '_bbp_anonymous_email', true), 'comment_author_url' => $_post->post_author ? bbp_get_user_profile_url($_post->post_author) : get_post_meta($post_id, '_bbp_anonymous_website', true), 'comment_content' => $_post->post_content, 'comment_date' => $_post->post_date, 'comment_ID' => $post_id, 'comment_post_ID' => $_post->post_parent, 'comment_type' => $_post->post_type, 'permalink' => get_permalink($post_id), 'user_ID' => $_post->post_author, 'user_ip' => get_post_meta($post_id, '_bbp_author_ip', true), 'user_role' => akismet_get_user_roles($_post->post_author)); // Use the original version stored in post_meta if available $as_submitted = get_post_meta($post_id, '_bbp_akismet_as_submitted', true); if ($as_submitted && is_array($as_submitted) && isset($as_submitted['comment_content'])) { $post_data = array_merge($post_data, $as_submitted); } // Add the reporter IP address $post_data['reporter_ip'] = bbp_current_author_ip(); // Add some reporter info if (is_object($current_user)) { $post_data['reporter'] = $current_user->user_login; } // Add the current site domain if (is_object($current_site)) { $post_data['site_domain'] = $current_site->domain; } // Place your slide beneath the microscope $post_data = $this->maybe_spam($post_data, 'submit', $request_type); // Manual user action if (isset($post_data['reporter'])) { // What kind of action switch ($request_type) { // Spammy case 'spam': $this->update_post_history($post_id, sprintf(__('%1$s reported this %2$s as spam', 'bbpress'), $post_data['reporter'], $post_data['comment_type']), 'report-spam'); update_post_meta($post_id, '_bbp_akismet_user_result', 'true'); update_post_meta($post_id, '_bbp_akismet_user', $post_data['reporter']); break; // Hammy // Hammy case 'ham': $this->update_post_history($post_id, sprintf(__('%1$s reported this %2$s as not spam', 'bbpress'), $post_data['reporter'], $post_data['comment_type']), 'report-ham'); update_post_meta($post_id, '_bbp_akismet_user_result', 'false'); update_post_meta($post_id, '_bbp_akismet_user', $post_data['reporter']); // @todo Topic term revision history break; // Possible other actions // Possible other actions default: break; } } do_action('bbp_akismet_submit_' . $request_type . '_post', $post_id, $post_data['bbp_akismet_result']); }
/** * When inserting a new topic, make sure the protected meta data is set correctly. * * We can't use WP_JSON_Posts::add_meta() here because the required meta is deemed * protected by @see is_protected_meta(). * * @see WP_JSON_Posts::insert_post() * @see WP_JSON_Posts::add_meta() */ public function add_protected_meta($post, $data, $update) { if (!$update && $this->type == $post['post_type']) { $topic_meta = array('author_ip' => bbp_current_author_ip(), 'forum_id' => $post['post_parent'], 'topic_id' => $post['ID'], 'voice_count' => 1, 'reply_count' => 0, 'reply_count_hidden' => 0, 'last_reply_id' => 0, 'last_active_id' => $post['ID'], 'last_active_time' => get_post_field('post_date', $post['ID'], 'db')); // Insert topic meta foreach ($topic_meta as $meta_key => $meta_value) { update_post_meta($post['ID'], '_bbp_' . $meta_key, $meta_value); } // Update the forum if (!empty($post['post_parent'])) { bbp_update_forum(array('forum_id' => $forum_id)); } } }
/** * Checks topics and replies against the discussion blacklist of blocked keys * * @since bbPress (r3446) * * @param array $anonymous_data Anonymous user data * @param int $author_id Topic or reply author ID * @param string $title The title of the content * @param string $content The content being posted * @uses is_super_admin() Allow super admins to bypass blacklist * @uses bbp_current_author_ip() To get current user IP address * @uses bbp_current_author_ua() To get current user agent * @return bool True if test is passed, false if fail */ function bbp_check_for_blacklist($anonymous_data = false, $author_id = 0, $title = '', $content = '') { // Bail if super admin is author if (is_super_admin($author_id)) { return true; } // Define local variable $_post = array(); /** Blacklist *************************************************************/ // Get the moderation keys $blacklist = trim(get_option('blacklist_keys')); // Bail if blacklist is empty if (empty($blacklist)) { return true; } /** User Data *************************************************************/ // Map anonymous user data if (!empty($anonymous_data)) { $_post['author'] = $anonymous_data['bbp_anonymous_name']; $_post['email'] = $anonymous_data['bbp_anonymous_email']; $_post['url'] = $anonymous_data['bbp_anonymous_website']; // Map current user data } elseif (!empty($author_id)) { // Get author data $user = get_userdata($author_id); // If data exists, map it if (!empty($user)) { $_post['author'] = $user->display_name; $_post['email'] = $user->user_email; $_post['url'] = $user->user_url; } } // Current user IP and user agent $_post['user_ip'] = bbp_current_author_ip(); $_post['user_ua'] = bbp_current_author_ua(); // Post title and content $_post['title'] = $title; $_post['content'] = $content; /** Words *****************************************************************/ // Get words separated by new lines $words = explode("\n", $blacklist); // Loop through words foreach ((array) $words as $word) { // Trim the whitespace from the word $word = trim($word); // Skip empty lines if (empty($word)) { continue; } // Do some escaping magic so that '#' chars in the // spam words don't break things: $word = preg_quote($word, '#'); $pattern = "#{$word}#i"; // Loop through post data foreach ($_post as $post_data) { // Check each user data for current word if (preg_match($pattern, $post_data)) { // Post does not pass return false; } } } // Check passed successfully return true; }