/includes/extend/akismet.php

  1. <?php 
  2.  
  3. /** 
  4. * Main bbPress Akismet Class 
  5. * 
  6. * @package bbPress 
  7. * @subpackage Akismet 
  8. */ 
  9.  
  10. // Exit if accessed directly 
  11. if ( !defined( 'ABSPATH' ) ) exit; 
  12.  
  13. if ( !class_exists( 'BBP_Akismet' ) ) : 
  14. /** 
  15. * Loads Akismet extension 
  16. * 
  17. * @since bbPress (r3277) 
  18. * 
  19. * @package bbPress 
  20. * @subpackage Akismet 
  21. */ 
  22. class BBP_Akismet { 
  23.  
  24. /** 
  25. * The main bbPress Akismet loader 
  26. * 
  27. * @since bbPress (r3277) 
  28. * 
  29. * @uses add_filter() 
  30. */ 
  31. public function __construct() { 
  32. $this->setup_actions(); 
  33.  
  34. /** 
  35. * Setup the admin hooks 
  36. * 
  37. * @since bbPress (r3277) 
  38. * @access private 
  39. * 
  40. * @uses add_filter() To add various filters 
  41. * @uses add_action() To add various actions 
  42. */ 
  43. private function setup_actions() { 
  44.  
  45. // Prevent debug notices 
  46. $checks = array(); 
  47.  
  48. // bbPress functions to check for spam 
  49. $checks['check'] = array( 
  50. 'bbp_new_topic_pre_insert' => 1, // New topic check 
  51. 'bbp_new_reply_pre_insert' => 1, // New reply check 
  52. 'bbp_edit_topic_pre_insert' => 1, // Edit topic check 
  53. 'bbp_edit_reply_pre_insert' => 1 // Edit reply check 
  54. ); 
  55.  
  56. // bbPress functions for spam and ham submissions 
  57. $checks['submit'] = array( 
  58. 'bbp_spammed_topic' => 10, // Spammed topic 
  59. 'bbp_unspammed_topic' => 10, // Unspammed reply 
  60. 'bbp_spammed_reply' => 10, // Spammed reply 
  61. 'bbp_unspammed_reply' => 10, // Unspammed reply 
  62. ); 
  63.  
  64. // Add the checks 
  65. foreach ( $checks as $type => $functions ) 
  66. foreach ( $functions as $function => $priority ) 
  67. add_filter( $function, array( $this, $type . '_post' ), $priority ); 
  68.  
  69. // Update post meta 
  70. add_action( 'wp_insert_post', array( $this, 'update_post_meta' ), 10, 2 ); 
  71.  
  72. // Admin 
  73. if ( is_admin() ) { 
  74. add_action( 'add_meta_boxes', array( $this, 'add_metaboxes' ) ); 
  75.  
  76. /** 
  77. * Converts topic/reply data into Akismet comment checking format 
  78. * 
  79. * @since bbPress (r3277) 
  80. * 
  81. * @param string $post_data 
  82. * 
  83. * @uses get_userdata() To get the user data 
  84. * @uses bbp_filter_anonymous_user_data() To get anonymous user data 
  85. * @uses bbp_get_topic_permalink() To get the permalink of the topic 
  86. * @uses bbp_get_reply_url() To get the permalink of the reply 
  87. * @uses bbp_current_author_ip() To get the IP address of the current user 
  88. * @uses BBP_Akismet::maybe_spam() To check if post is spam 
  89. * @uses BBP_Akismet::get_user_roles() To get the role(s) of the current user 
  90. * @uses do_action() To call the 'bbp_akismet_spam_caught' hook 
  91. * @uses add_filter() To call the 'bbp_new_reply_pre_set_terms' hook 
  92. * 
  93. * @return array Array of post data 
  94. */ 
  95. public function check_post( $post_data ) { 
  96.  
  97. // Define local variables 
  98. $user_data = array(); 
  99. $post_permalink = ''; 
  100.  
  101. // Post is not published 
  102. if ( bbp_get_public_status_id() !== $post_data['post_status'] ) 
  103. return $post_data; 
  104.  
  105. // Cast the post_author to 0 if it's empty 
  106. if ( empty( $post_data['post_author'] ) ) 
  107. $post_data['post_author'] = 0; 
  108.  
  109. /** Author ************************************************************/ 
  110.  
  111. // Get user data 
  112. $userdata = get_userdata( $post_data['post_author'] ); 
  113. $anonymous_data = bbp_filter_anonymous_post_data(); 
  114.  
  115. // Author is anonymous 
  116. if ( !empty( $anonymous_data ) ) { 
  117. $user_data['name'] = $anonymous_data['bbp_anonymous_name']; 
  118. $user_data['email'] = $anonymous_data['bbp_anonymous_email']; 
  119. $user_data['website'] = $anonymous_data['bbp_anonymous_website']; 
  120.  
  121. // Author is logged in 
  122. } elseif ( !empty( $userdata ) ) { 
  123. $user_data['name'] = $userdata->display_name; 
  124. $user_data['email'] = $userdata->user_email; 
  125. $user_data['website'] = $userdata->user_url; 
  126.  
  127. // Missing author data, so set some empty strings 
  128. } else { 
  129. $user_data['name'] = ''; 
  130. $user_data['email'] = ''; 
  131. $user_data['website'] = ''; 
  132.  
  133. /** Post **************************************************************/ 
  134.  
  135. // Use post parent for permalink 
  136. if ( !empty( $post_data['post_parent'] ) ) 
  137. $post_permalink = get_permalink( $post_data['post_parent'] ); 
  138.  
  139. // Put post_data back into usable array 
  140. $_post = array( 
  141. 'comment_author' => $user_data['name'],  
  142. 'comment_author_email' => $user_data['email'],  
  143. 'comment_author_url' => $user_data['website'],  
  144. 'comment_content' => $post_data['post_content'],  
  145. 'comment_post_ID' => $post_data['post_parent'],  
  146. 'comment_type' => $post_data['post_type'],  
  147. 'permalink' => $post_permalink,  
  148. 'referrer' => $_SERVER['HTTP_REFERER'],  
  149. 'user_agent' => $_SERVER['HTTP_USER_AGENT'],  
  150. 'user_ID' => $post_data['post_author'],  
  151. 'user_ip' => bbp_current_author_ip(),  
  152. 'user_role' => $this->get_user_roles( $post_data['post_author'] ),  
  153. ); 
  154.  
  155. // Check the post_data 
  156. $_post = $this->maybe_spam( $_post ); 
  157.  
  158. // Get the result 
  159. $post_data['bbp_akismet_result'] = $_post['bbp_akismet_result']; 
  160. unset( $_post['bbp_akismet_result'] ); 
  161.  
  162. // Store the data as submitted 
  163. $post_data['bbp_post_as_submitted'] = $_post; 
  164.  
  165. // Allow post_data to be manipulated 
  166. do_action_ref_array( 'bbp_akismet_check_post', $post_data ); 
  167.  
  168. // Spam 
  169. if ( 'true' === $post_data['bbp_akismet_result'] ) { 
  170.  
  171. // Let plugins do their thing 
  172. do_action( 'bbp_akismet_spam_caught' ); 
  173.  
  174. // This is spam 
  175. $post_data['post_status'] = bbp_get_spam_status_id(); 
  176.  
  177. // We don't want your spam tags here 
  178. add_filter( 'bbp_new_reply_pre_set_terms', array( $this, 'filter_post_terms' ), 1, 3 ); 
  179.  
  180. // @todo Spam counter? 
  181.  
  182. // @todo Topic/reply moderation? No true/false response - 'pending' or 'draft' 
  183. // @todo Auto-delete old spam? 
  184.  
  185. // Log the last post 
  186. $this->last_post = $post_data; 
  187.  
  188. // Pass the data back to the filter 
  189. return $post_data; 
  190.  
  191. /** 
  192. * Submit a post for spamming or hamming 
  193. * 
  194. * @since bbPress (r3277) 
  195. * 
  196. * @param int $post_id 
  197. * 
  198. * @global WP_Query $wpdb 
  199. * @global string $akismet_api_host 
  200. * @global string $akismet_api_port 
  201. * @global object $current_user 
  202. * @global object $current_site 
  203. * 
  204. * @uses current_filter() To get the reply_id 
  205. * @uses get_post() To get the post object 
  206. * @uses get_the_author_meta() To get the author meta 
  207. * @uses get_post_meta() To get the post meta 
  208. * @uses bbp_get_user_profile_url() To get a user's profile url 
  209. * @uses get_permalink() To get the permalink of the post_parent 
  210. * @uses BBP_Akismet::get_user_roles() To get the role(s) of the post_author 
  211. * @uses bbp_current_author_ip() To get the IP address of the current user 
  212. * @uses BBP_Akismet::maybe_spam() To submit the post as ham or spam 
  213. * @uses update_post_meta() To update the post meta with some Akismet data 
  214. * @uses do_action() To call the 'bbp_akismet_submit_spam_post' and 'bbp_akismet_submit_ham_post' hooks 
  215. * 
  216. * @return array Array of existing topic terms 
  217. */ 
  218. public function submit_post( $post_id = 0 ) { 
  219. global $current_user, $current_site; 
  220.  
  221. // Innocent until proven guilty 
  222. $request_type = 'ham'; 
  223. $current_filter = current_filter(); 
  224.  
  225. // Check this filter and adjust the $request_type accordingly 
  226. switch ( $current_filter ) { 
  227.  
  228. // Mysterious, and straight from the can 
  229. case 'bbp_spammed_topic' : 
  230. case 'bbp_spammed_reply' : 
  231. $request_type = 'spam'; 
  232. break; 
  233.  
  234. // Honey-glazed, a straight off the bone 
  235. case 'bbp_unspammed_topic' : 
  236. case 'bbp_unspammed_reply' : 
  237. $request_type = 'ham'; 
  238. break; 
  239.  
  240. // Possibly poison... 
  241. default : 
  242. return; 
  243.  
  244. // Setup some variables 
  245. $post_id = (int) $post_id; 
  246.  
  247. // Make sure we have a post 
  248. $_post = get_post( $post_id ); 
  249.  
  250. // Bail if get_post() fails 
  251. if ( empty( $_post ) ) 
  252. return; 
  253.  
  254. // Bail if we're spamming, but the post_status isn't spam 
  255. if ( ( 'spam' === $request_type ) && ( bbp_get_spam_status_id() !== $_post->post_status ) ) 
  256. return; 
  257.  
  258. // Set some default post_data 
  259. $post_data = array( 
  260. 'comment_approved' => $_post->post_status,  
  261. 'comment_author' => $_post->post_author ? get_the_author_meta( 'display_name', $_post->post_author ) : get_post_meta( $post_id, '_bbp_anonymous_name', true ),  
  262. 'comment_author_email' => $_post->post_author ? get_the_author_meta( 'email', $_post->post_author ) : get_post_meta( $post_id, '_bbp_anonymous_email', true ),  
  263. 'comment_author_url' => $_post->post_author ? bbp_get_user_profile_url( $_post->post_author ) : get_post_meta( $post_id, '_bbp_anonymous_website', true ),  
  264. 'comment_content' => $_post->post_content,  
  265. 'comment_date' => $_post->post_date,  
  266. 'comment_ID' => $post_id,  
  267. 'comment_post_ID' => $_post->post_parent,  
  268. 'comment_type' => $_post->post_type,  
  269. 'permalink' => get_permalink( $post_id ),  
  270. 'user_ID' => $_post->post_author,  
  271. 'user_ip' => get_post_meta( $post_id, '_bbp_author_ip', true ),  
  272. 'user_role' => $this->get_user_roles( $_post->post_author ),  
  273. ); 
  274.  
  275. // Use the original version stored in post_meta if available 
  276. $as_submitted = get_post_meta( $post_id, '_bbp_akismet_as_submitted', true ); 
  277. if ( $as_submitted && is_array( $as_submitted ) && isset( $as_submitted['comment_content'] ) ) 
  278. $post_data = array_merge( $post_data, $as_submitted ); 
  279.  
  280. // Add the reporter IP address 
  281. $post_data['reporter_ip'] = bbp_current_author_ip(); 
  282.  
  283. // Add some reporter info 
  284. if ( is_object( $current_user ) ) 
  285. $post_data['reporter'] = $current_user->user_login; 
  286.  
  287. // Add the current site domain 
  288. if ( is_object( $current_site ) ) 
  289. $post_data['site_domain'] = $current_site->domain; 
  290.  
  291. // Place your slide beneath the microscope 
  292. $post_data = $this->maybe_spam( $post_data, 'submit', $request_type ); 
  293.  
  294. // Manual user action 
  295. if ( isset( $post_data['reporter'] ) ) { 
  296.  
  297. // What kind of action 
  298. switch ( $request_type ) { 
  299.  
  300. // Spammy 
  301. case 'spam' : 
  302. $this->update_post_history( $post_id, sprintf( esc_html__( '%1$s reported this %2$s as spam', 'bbpress' ), $post_data['reporter'], $post_data['comment_type'] ), 'report-spam' ); 
  303. update_post_meta( $post_id, '_bbp_akismet_user_result', 'true' ); 
  304. update_post_meta( $post_id, '_bbp_akismet_user', $post_data['reporter'] ); 
  305. break; 
  306.  
  307. // Hammy 
  308. case 'ham' : 
  309. $this->update_post_history( $post_id, sprintf( esc_html__( '%1$s reported this %2$s as not spam', 'bbpress' ), $post_data['reporter'], $post_data['comment_type'] ), 'report-ham' ); 
  310. update_post_meta( $post_id, '_bbp_akismet_user_result', 'false' ); 
  311. update_post_meta( $post_id, '_bbp_akismet_user', $post_data['reporter'] ); 
  312.  
  313. // @todo Topic term revision history 
  314. break; 
  315.  
  316. // Possible other actions 
  317. default : 
  318. break; 
  319.  
  320. do_action( 'bbp_akismet_submit_' . $request_type . '_post', $post_id, $post_data['bbp_akismet_result'] ); 
  321.  
  322. /** 
  323. * Ping Akismet service and check for spam/ham response 
  324. * 
  325. * @since bbPress (r3277) 
  326. * 
  327. * @param array $post_data 
  328. * @param string $check Accepts check|submit 
  329. * @param string $spam Accepts spam|ham 
  330. * 
  331. * @global string $akismet_api_host 
  332. * @global string $akismet_api_port 
  333. * 
  334. * @uses akismet_test_mode() To determine if Akismet is in test mode 
  335. * @uses akismet_http_post() To send data to the mothership for processing 
  336. * 
  337. * @return array Array of post data 
  338. */ 
  339. private function maybe_spam( $post_data, $check = 'check', $spam = 'spam' ) { 
  340. global $akismet_api_host, $akismet_api_port; 
  341.  
  342. // Define variables 
  343. $query_string = $path = $response = ''; 
  344.  
  345. // Populate post data 
  346. $post_data['blog'] = get_option( 'home' ); 
  347. $post_data['blog_charset'] = get_option( 'blog_charset' ); 
  348. $post_data['blog_lang'] = get_locale(); 
  349. $post_data['referrer'] = $_SERVER['HTTP_REFERER']; 
  350. $post_data['user_agent'] = $_SERVER['HTTP_USER_AGENT']; 
  351.  
  352. // Akismet Test Mode 
  353. if ( akismet_test_mode() ) 
  354. $post_data['is_test'] = 'true'; 
  355.  
  356. // Loop through _POST args and rekey strings 
  357. foreach ( $_POST as $key => $value ) 
  358. if ( is_string( $value ) ) 
  359. $post_data['POST_' . $key] = $value; 
  360.  
  361. // Keys to ignore 
  362. $ignore = array( 'HTTP_COOKIE', 'HTTP_COOKIE2', 'PHP_AUTH_PW' ); 
  363.  
  364. // Loop through _SERVER args and remove whitelisted keys 
  365. foreach ( $_SERVER as $key => $value ) { 
  366.  
  367. // Key should not be ignored 
  368. if ( !in_array( $key, $ignore ) && is_string( $value ) ) { 
  369. $post_data[$key] = $value; 
  370.  
  371. // Key should be ignored 
  372. } else { 
  373. $post_data[$key] = ''; 
  374.  
  375. // Ready... 
  376. foreach ( $post_data as $key => $data ) 
  377. $query_string .= $key . '=' . urlencode( stripslashes( $data ) ) . '&'; 
  378.  
  379. // Aim... 
  380. if ( 'check' === $check ) { 
  381. $path = '/1.1/comment-check'; 
  382. } elseif ( 'submit' === $check ) { 
  383. $path = '/1.1/submit-' . $spam; 
  384.  
  385. // Fire! 
  386. $response = $this->http_post( $query_string, $akismet_api_host, $path, $akismet_api_port ); 
  387.  
  388. // Check the high-speed cam 
  389. if ( !empty( $response[1] ) ) { 
  390. $post_data['bbp_akismet_result'] = $response[1]; 
  391. } else { 
  392. $post_data['bbp_akismet_result'] = esc_html__( 'No response', 'bbpress' ); 
  393.  
  394. // This is ham 
  395. return $post_data; 
  396.  
  397. /** 
  398. * Update post meta after a spam check 
  399. * 
  400. * @since bbPress (r3308) 
  401. * 
  402. * @param int $post_id 
  403. * @param object $_post 
  404. * 
  405. * @global object $this->last_post 
  406. * 
  407. * @uses get_post() To get the post object 
  408. * @uses get_userdata() To get the user data 
  409. * @uses bbp_filter_anonymous_user_data() To get anonymous user data 
  410. * @uses update_post_meta() To update post meta with Akismet data 
  411. * @uses BBP_Akismet::update_post_history() To update post Akismet history 
  412. */ 
  413. public function update_post_meta( $post_id = 0, $_post = false ) { 
  414.  
  415. // Define local variable(s) 
  416. $as_submitted = false; 
  417.  
  418. // Setup some variables 
  419. $post_id = (int) $post_id; 
  420.  
  421. // Ensure we have a post object 
  422. if ( empty( $_post ) ) 
  423. $_post = get_post( $post_id ); 
  424.  
  425. // Set up Akismet last post data 
  426. if ( !empty( $this->last_post ) ) 
  427. $as_submitted = $this->last_post['bbp_post_as_submitted']; 
  428.  
  429. // wp_insert_post() might be called in other contexts. Ensure this is 
  430. // the same topic/reply as was checked by BBP_Akismet::check_post() 
  431. if ( is_object( $_post ) && !empty( $this->last_post ) && is_array( $as_submitted ) ) { 
  432.  
  433. // Get user data 
  434. $userdata = get_userdata( $_post->post_author ); 
  435. $anonymous_data = bbp_filter_anonymous_post_data(); 
  436.  
  437. // More checks 
  438. if ( intval( $as_submitted['comment_post_ID'] ) === intval( $_post->post_parent ) 
  439. && $as_submitted['comment_author'] === ( $anonymous_data ? $anonymous_data['bbp_anonymous_name'] : $userdata->display_name ) 
  440. && $as_submitted['comment_author_email'] === ( $anonymous_data ? $anonymous_data['bbp_anonymous_email'] : $userdata->user_email ) 
  441. ) { 
  442.  
  443. // Normal result: true 
  444. if ( $this->last_post['bbp_akismet_result'] === 'true' ) { 
  445.  
  446. // Leave a trail so other's know what we did 
  447. update_post_meta( $post_id, '_bbp_akismet_result', 'true' ); 
  448. $this->update_post_history( $post_id, esc_html__( 'Akismet caught this post as spam', 'bbpress' ), 'check-spam' ); 
  449.  
  450. // If post_status isn't the spam status, as expected, leave a note 
  451. if ( bbp_get_spam_status_id() !== $_post->post_status ) { 
  452. $this->update_post_history( $post_id, sprintf( esc_html__( 'Post status was changed to %s', 'bbpress' ), $_post->post_status ), 'status-changed-' . $_post->post_status ); 
  453.  
  454. // Normal result: false 
  455. } elseif ( $this->last_post['bbp_akismet_result'] === 'false' ) { 
  456.  
  457. // Leave a trail so other's know what we did 
  458. update_post_meta( $post_id, '_bbp_akismet_result', 'false' ); 
  459. $this->update_post_history( $post_id, esc_html__( 'Akismet cleared this post as not spam', 'bbpress' ), 'check-ham' ); 
  460.  
  461. // If post_status is the spam status, which isn't expected, leave a note 
  462. if ( bbp_get_spam_status_id() === $_post->post_status ) { 
  463.  
  464. // @todo Use wp_blacklist_check() 
  465.  
  466. $this->update_post_history( $post_id, sprintf( esc_html__( 'Post status was changed to %s', 'bbpress' ), $_post->post_status ), 'status-changed-' . $_post->post_status ); 
  467.  
  468. // Abnormal result: error 
  469. } else { 
  470. // Leave a trail so other's know what we did 
  471. update_post_meta( $post_id, '_bbp_akismet_error', time() ); 
  472. $this->update_post_history( $post_id, sprintf( esc_html__( 'Akismet was unable to check this post (response: %s), will automatically retry again later.', 'bbpress' ), $this->last_post['bbp_akismet_result'] ), 'check-error' ); 
  473.  
  474. // Record the complete original data as submitted for checking 
  475. if ( isset( $this->last_post['bbp_post_as_submitted'] ) ) { 
  476. update_post_meta( $post_id, '_bbp_akismet_as_submitted', $this->last_post['bbp_post_as_submitted'] ); 
  477.  
  478. /** 
  479. * Update a post's Akismet history 
  480. * 
  481. * @since bbPress (r3308) 
  482. * 
  483. * @param int $post_id 
  484. * @param string $message 
  485. * @param string $event 
  486. * 
  487. * @uses wp_get_current_user() To get the current_user object 
  488. * @uses add_post_meta() Add Akismet post history 
  489. */ 
  490. private function update_post_history( $post_id = 0, $message = null, $event = null ) { 
  491.  
  492. // Define local variable(s) 
  493. $user = ''; 
  494.  
  495. // Get the current user 
  496. $current_user = wp_get_current_user(); 
  497.  
  498. // Get the user's login name if possible 
  499. if ( is_object( $current_user ) && isset( $current_user->user_login ) ) 
  500. $user = $current_user->user_login; 
  501.  
  502. // Setup the event to be saved 
  503. $event = array( 
  504. 'time' => akismet_microtime(),  
  505. 'message' => $message,  
  506. 'event' => $event,  
  507. 'user' => $user,  
  508. ); 
  509.  
  510. // Save the event data 
  511. add_post_meta( $post_id, '_bbp_akismet_history', $event ); 
  512.  
  513. /** 
  514. * Get a post's Akismet history 
  515. * 
  516. * @since bbPress (r3308) 
  517. * 
  518. * @param int $post_id 
  519. * 
  520. * @uses wp_get_current_user() To get the current_user object 
  521. * @uses get_post_meta() Get a post's Akismet history 
  522. * 
  523. * @return array Array of a post's Akismet history 
  524. */ 
  525. public function get_post_history( $post_id = 0 ) { 
  526.  
  527. // Retrieve any previous history 
  528. $history = get_post_meta( $post_id, '_bbp_akismet_history' ); 
  529.  
  530. // Sort it by the time recorded 
  531. usort( $history, 'akismet_cmp_time' ); 
  532.  
  533. return $history; 
  534.  
  535. /** 
  536. * Handle any terms submitted with a post flagged as spam 
  537. * 
  538. * @since bbPress (r3308) 
  539. * 
  540. * @param string $terms Comma-separated list of terms 
  541. * @param int $topic_id 
  542. * @param int $reply_id 
  543. * 
  544. * @uses bbp_get_reply_id() To get the reply_id 
  545. * @uses bbp_get_topic_id() To get the topic_id 
  546. * @uses wp_get_object_terms() To a post's current terms 
  547. * @uses update_post_meta() To add spam terms to post meta 
  548. * 
  549. * @return array Array of existing topic terms 
  550. */ 
  551. public function filter_post_terms( $terms = '', $topic_id = 0, $reply_id = 0 ) { 
  552.  
  553. // Validate the reply_id and topic_id 
  554. $reply_id = bbp_get_reply_id( $reply_id ); 
  555. $topic_id = bbp_get_topic_id( $topic_id ); 
  556.  
  557. // Get any pre-existing terms 
  558. $existing_terms = wp_get_object_terms( $topic_id, bbp_get_topic_tag_tax_id(), array( 'fields' => 'names' ) ); 
  559.  
  560. // Save the terms for later in case the reply gets hammed 
  561. if ( !empty( $terms ) ) 
  562. update_post_meta( $reply_id, '_bbp_akismet_spam_terms', $terms ); 
  563.  
  564. // Keep the topic tags the same for now 
  565. return $existing_terms; 
  566.  
  567. /** 
  568. * Submit data to Akismet service with unique bbPress User Agent 
  569. * 
  570. * This code is directly taken from the akismet_http_post() function and 
  571. * documented to bbPress 2.0 standard. 
  572. * 
  573. * @since bbPress (r3466) 
  574. * 
  575. * @param string $request The request we are sending 
  576. * @param string $host The host to send our request to 
  577. * @param string $path The path from the host 
  578. * @param string $port The port to use 
  579. * @param string $ip Optional Override $host with an IP address 
  580. * @uses bbp_get_version() To get the current bbPress version 
  581. * @return mixed WP_Error on error, array on success, empty on failure 
  582. */ 
  583. private function http_post( $request, $host, $path, $port = 80, $ip = '' ) { 
  584.  
  585. // Preload required variables 
  586. $bbp_version = bbp_get_version(); 
  587. $content_length = strlen( $request ); 
  588. $http_host = $host; 
  589. $blog_charset = get_option( 'blog_charset' ); 
  590. $response = ''; 
  591. $errno = null; 
  592. $errstr = null; 
  593.  
  594. // Untque User Agent 
  595. $akismet_ua = "bbPress/{$bbp_version} | "; 
  596. $akismet_ua .= 'Akismet/' . constant( 'AKISMET_VERSION' ); 
  597.  
  598. // Use specific IP (if provided) 
  599. if ( !empty( $ip ) && long2ip( ip2long( $ip ) ) ) 
  600. $http_host = $ip; 
  601.  
  602. // WP HTTP class is available 
  603. if ( function_exists( 'wp_remote_post' ) ) { 
  604.  
  605. // Setup the arguments 
  606. $http_args = array( 
  607. 'body' => $request,  
  608. 'headers' => array( 
  609. 'Content-Type' => 'application/x-www-form-urlencoded; charset=' . $blog_charset,  
  610. 'Host' => $host,  
  611. 'User-Agent' => $akismet_ua 
  612. ),  
  613. 'httpversion' => '1.0',  
  614. 'timeout' => 15 
  615. ); 
  616.  
  617. // Where we are sending our request 
  618. $akismet_url = 'http://' . $http_host . $path; 
  619.  
  620. // Send the request 
  621. $response = wp_remote_post( $akismet_url, $http_args ); 
  622.  
  623. // Bail if the response is an error 
  624. if ( is_wp_error( $response ) ) 
  625. return ''; 
  626.  
  627. // No errors so return response 
  628. return array( $response['headers'], $response['body'] ); 
  629.  
  630. // WP HTTP class is not available (Why not?) 
  631. } else { 
  632.  
  633. // Header info to use with our socket 
  634. $http_request = "POST {$path} HTTP/1.0\r\n"; 
  635. $http_request .= "Host: {$host}\r\n"; 
  636. $http_request .= "Content-Type: application/x-www-form-urlencoded; charset={$blog_charset}\r\n"; 
  637. $http_request .= "Content-Length: {$content_length}\r\n"; 
  638. $http_request .= "User-Agent: {$akismet_ua}\r\n"; 
  639. $http_request .= "\r\n"; 
  640. $http_request .= $request; 
  641.  
  642. // Open a socket connection 
  643. if ( false !== ( $fs = @fsockopen( $http_host, $port, $errno, $errstr, 10 ) ) ) { 
  644.  
  645. // Write our request to the pointer 
  646. fwrite( $fs, $http_request ); 
  647.  
  648. // Loop through pointer and compile a response 
  649. while ( !feof( $fs ) ) { 
  650. // One TCP-IP packet at a time 
  651. $response .= fgets( $fs, 1160 ); 
  652.  
  653. // Close our socket 
  654. fclose( $fs ); 
  655.  
  656. // Explode the response into usable data 
  657. $response = explode( "\r\n\r\n", $response, 2 ); 
  658.  
  659. // Return the response ('' if error/empty) 
  660. return $response; 
  661.  
  662. /** 
  663. * Return a user's roles on this site (including super_admin) 
  664. * 
  665. * @since bbPress (r4812) 
  666. * 
  667. * @param type $user_id 
  668. * @return boolean 
  669. */ 
  670. private function get_user_roles( $user_id = 0 ) { 
  671.  
  672. // Default return value 
  673. $roles = array(); 
  674.  
  675. // Bail if cannot query the user 
  676. if ( ! class_exists( 'WP_User' ) || empty( $user_id ) ) { 
  677. return false; 
  678.  
  679. // User ID 
  680. $user = new WP_User( $user_id ); 
  681. if ( isset( $user->roles ) ) { 
  682. $roles = (array) $user->roles; 
  683.  
  684. // Super admin 
  685. if ( is_multisite() && is_super_admin( $user_id ) ) { 
  686. $roles[] = 'super_admin'; 
  687.  
  688. return implode( ', ', $roles ); 
  689.  
  690. /** Admin *****************************************************************/ 
  691.  
  692. /** 
  693. * Add Aksimet History metaboxes to topics and replies 
  694. * 
  695. * @since bbPress (r5049) 
  696. */ 
  697. public function add_metaboxes() { 
  698.  
  699. // Topics 
  700. add_meta_box( 
  701. 'bbp_akismet_topic_history',  
  702. __( 'Akismet History', 'bbpress' ),  
  703. array( $this, 'history_metabox' ),  
  704. bbp_get_topic_post_type(),  
  705. 'normal',  
  706. 'core' 
  707. ); 
  708.  
  709. // Replies 
  710. add_meta_box( 
  711. 'bbp_akismet_reply_history',  
  712. __( 'Akismet History', 'bbpress' ),  
  713. array( $this, 'history_metabox' ),  
  714. bbp_get_reply_post_type(),  
  715. 'normal',  
  716. 'core' 
  717. ); 
  718.  
  719. /** 
  720. * Output for Akismet History metabox 
  721. * 
  722. * @since bbPress (r5049) 
  723. * 
  724. * @uses get_post_history() To get the Akismet history for the post 
  725. * @uses get_the_ID() To get the post ID 
  726. * @uses bbp_time_since() To get the human readable time 
  727. */ 
  728. public function history_metabox() { 
  729.  
  730. // Post ID 
  731. $history = $this->get_post_history( get_the_ID() ); ?> 
  732.  
  733. <div class="akismet-history" style="margin: 13px 0;"> 
  734.  
  735. <?php if ( !empty( $history ) ) : ?> 
  736.  
  737. <table> 
  738. <tbody> 
  739.  
  740. <?php foreach ( $history as $row ) : ?> 
  741.  
  742. <tr> 
  743. <td style="color: #999; text-align: right; white-space: nowrap;"> 
  744. <span title="<?php echo esc_attr( date( 'D d M Y @ h:i:m a', $row['time'] ) . ' GMT' ); ?>"> 
  745. <?php bbp_time_since( $row['time'], false, true ); ?> 
  746. </span> 
  747. </td> 
  748. <td style="padding-left: 5px;"> 
  749. <?php echo esc_html( $row['message'] ); ?> 
  750. </td> 
  751. </tr> 
  752.  
  753. <?php endforeach; ?> 
  754. </tbody> 
  755. </table> 
  756.  
  757. <?php else : ?> 
  758.  
  759. <p><?php esc_html_e( 'No recorded history. Akismet has not checked this post.', 'bbpress' ); ?></p> 
  760.  
  761. <?php endif; ?> 
  762.  
  763. </div> 
  764.  
  765. <?php 
  766. endif; 
.