PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/system/plugins/spamchecker/spamchecker.plugin.php

https://github.com/HabariMag/habarimag-old
PHP | 239 lines | 179 code | 19 blank | 41 comment | 20 complexity | a96f131b44e6f1273fcb80f6ad2b4f01 MD5 | raw file
Possible License(s): Apache-2.0
  1. <?php
  2. /**
  3. * SpamChecker Class
  4. *
  5. * This class implements first round spam checking.
  6. *
  7. **/
  8. class SpamChecker extends Plugin
  9. {
  10. /**
  11. * function act_comment_insert_before
  12. * This function is executed when the action "comment_insert_before"
  13. * is invoked from a Comment object.
  14. * The parent class, Plugin, handles registering the action
  15. * and hook name using the name of the function to determine
  16. * where it will be applied.
  17. * You can still register functions as hooks without using
  18. * this method, but boy, is it handy.
  19. * @param Comment The comment that will be processed before storing it in the database.
  20. **/
  21. function action_comment_insert_before ( $comment )
  22. {
  23. // This plugin ignores non-comments
  24. if ($comment->type != Comment::COMMENT) {
  25. return;
  26. }
  27. $spamcheck = array();
  28. // <script> is bad, mmmkay?
  29. $comment->content = InputFilter::filter($comment->content);
  30. // first, check the commenter's name
  31. // if it's only digits, then we can discard this comment
  32. if ( preg_match( "/^\d+$/", $comment->name ) ) {
  33. $comment->status = Comment::STATUS_SPAM;
  34. $spamcheck[] = _t('Commenters with numeric names are spammy.');
  35. }
  36. // now look at the comment text
  37. // if it's digits only, discard it
  38. $textonly = strip_tags( $comment->content );
  39. if ( preg_match( "/^\d+$/", $textonly ) ) {
  40. $comment->status = Comment::STATUS_SPAM;
  41. $spamcheck[] = _t('Comments that are only numeric are spammy.');
  42. }
  43. // is the content whitespaces only?
  44. if ( preg_match( "/\A\s+\z/", $textonly ) ) {
  45. $comment->status = Comment::STATUS_SPAM;
  46. $spamcheck[] = _t('Comments that are only whitespace characters are spammy.');
  47. }
  48. // is the content the single word "array"?
  49. if ( 'array' == strtolower( $textonly ) ) {
  50. $comment->status = Comment::STATUS_SPAM;
  51. $spamcheck[] = _t('Comments that are only "array" are spammy.');
  52. }
  53. // is the content the same as the name?
  54. if ( strtolower( $textonly ) == strtolower( $comment->name ) ) {
  55. $comment->status = Comment::STATUS_SPAM;
  56. $spamcheck[] = _t('Comments that consist of only the commenters name are spammy.');
  57. }
  58. // a lot of spam starts with "<strong>some text...</strong>"
  59. if ( preg_match( "#^<strong>[^.]+\.\.\.</strong>#", $comment->content ) )
  60. {
  61. $comment->status = Comment::STATUS_SPAM;
  62. $spamcheck[] = _t('Comments that start with strong text are spammy.');
  63. }
  64. // are there more than 3 URLs posted? If so, it's almost certainly spam
  65. if ( preg_match_all( "#https?://#", strtolower( $comment->content ), $matches, PREG_SET_ORDER ) > 3 ) {
  66. $comment->status = Comment::STATUS_SPAM;
  67. $spamcheck[] = _t('There is a 3 URL limit in comments.');
  68. }
  69. // are there more than 3 URLencoded characters in the content?
  70. if ( preg_match_all( "/%[0-9a-f]{2}/", strtolower( $comment->content ), $matches, PREG_SET_ORDER ) > 3 ) {
  71. $comment->status = Comment::STATUS_SPAM;
  72. $spamcheck[] = _t('There is a 3 URL-encoded character limit in comments.');
  73. }
  74. // Was the tcount high enough?
  75. /* // This only works with special javascript running on comment form
  76. if ( empty($handlervars['tcount']) || $handlervars['tcount'] < 10 ) {
  77. $comment->status = Comment::STATUS_SPAM;
  78. $spamcheck[] = _t('Commenter did not actually type content.');
  79. }
  80. */
  81. // We don't allow bbcode here, silly
  82. if ( stripos($comment->content, '[url=') !== false ) {
  83. $comment->status = Comment::STATUS_SPAM;
  84. $spamcheck[] = _t('We do not accept BBCode here.');
  85. }
  86. // Must have less than half link content
  87. $nonacontent = strip_tags(preg_replace('/<a.*?<\/a/i', '', $comment->content));
  88. $text_length = strlen( $textonly );
  89. if ( strlen($nonacontent) / ( $text_length == 0 ? 1 : $text_length) < 0.5 ) {
  90. $comment->status = Comment::STATUS_SPAM;
  91. $spamcheck[] = _t('Too much text that is a link compared to that which is not.');
  92. }
  93. // Only do db checks if it's not already spam
  94. if ($comment->status != Comment::STATUS_SPAM) {
  95. $spams = DB::get_value('SELECT count(*) FROM ' . DB::table('comments') . ' WHERE status = ? AND ip = ?', array(Comment::STATUS_SPAM, $comment->ip));
  96. // If you've already got two spams on your IP address, all you ever do is spam
  97. if ($spams > 1) {
  98. $comment->status = Comment::STATUS_SPAM;
  99. $spamcheck[] = sprintf(_t('Too many existing spams from this IP: %s'), long2ip($comment->ip));
  100. }
  101. }
  102. // Any commenter that takes longer than the session timeout is automatically moderated
  103. if (!isset($_SESSION['comments_allowed']) || ! in_array(Controller::get_var('ccode'), $_SESSION['comments_allowed'])) {
  104. $comment->status = Comment::STATUS_UNAPPROVED;
  105. $spamcheck[] = _t("The commenter's session timed out.");
  106. }
  107. if ( isset($comment->info->spamcheck) && is_array($comment->info->spamcheck)) {
  108. $comment->info->spamcheck = array_unique(array_merge($comment->info->spamcheck, $spamcheck));
  109. }
  110. else {
  111. $comment->info->spamcheck = $spamcheck;
  112. }
  113. // otherwise everything looks good
  114. // so continue processing the comment
  115. return;
  116. }
  117. /**
  118. * Add a rule to replace the existing rule for creating a comment post url
  119. *
  120. * @param array $rules The array of rewrite rules to route incoming URL requests to handlers
  121. * @return array The modified rules array
  122. */
  123. public function filter_rewrite_rules($rules)
  124. {
  125. $rules[] = new RewriteRule(array(
  126. 'name' => 'submit_feedback',
  127. 'parse_regex' => '/^(?P<id>([0-9]+))\/(?P<ccode>([0-9a-f]+))\/feedback[\/]{0,1}$/i',
  128. 'build_str' => '{$id}/{$ccode}/feedback',
  129. 'handler' => 'FeedbackHandler',
  130. 'action' => 'add_comment',
  131. 'priority' => 7,
  132. 'is_active' => 1,
  133. ));
  134. return $rules;
  135. }
  136. /**
  137. * Change some outgoing arguments supplied to rewrite rules during URL generation
  138. *
  139. * @param array $args The arguments passed to build a URL
  140. * @param string $rulename The name of the URL that is to be built
  141. * @return array The modified arguments
  142. */
  143. public function filter_rewrite_args($args, $rulename)
  144. {
  145. switch ($rulename) {
  146. case 'submit_feedback':
  147. $args['ccode'] = $this->get_code($args['id']);
  148. if ( !isset($_SESSION['comments_allowed'])) {
  149. $_SESSION['comments_allowed'] = array();
  150. }
  151. $_SESSION['comments_allowed'][] = $args['ccode'];
  152. // Only allow comments on the last 10 posts you look at
  153. $_SESSION['comments_allowed'] = array_slice($_SESSION['comments_allowed'], -10);
  154. break;
  155. }
  156. return $args;
  157. }
  158. /**
  159. * Ensure that the code assigned to this user for their commenting URL is genuine
  160. *
  161. * @param float $spam_rating The spamminess of the comment as detected by other plugins
  162. * @param Comment $comment The submitted comment object
  163. * @param array $handlervars An array of handlervars passed in via the comment submission URL
  164. * @return float The original spam rating
  165. */
  166. function filter_spam_filter( $spam_rating, $comment, $handlervars )
  167. {
  168. // This plugin ignores non-comments
  169. if ($comment->type != Comment::COMMENT) {
  170. return $spam_rating;
  171. }
  172. if (!$this->verify_code($handlervars['ccode'], $comment->post_id)) {
  173. ob_end_clean();
  174. header( 'HTTP/1.1 403 Forbidden', true, 403 );
  175. die('<h1>' . _t('The selected action is forbidden.') . '</h1>');
  176. }
  177. return $spam_rating;
  178. }
  179. /**
  180. * Get a 10-digit hex code that identifies the user submitting the comment
  181. * @param A post id to which the comment will be submitted
  182. * @param The IP address of the commenter
  183. * @return A 10-digit hex code
  184. **/
  185. public function get_code($post_id, $ip = '')
  186. {
  187. if ( $ip == '' ) {
  188. $ip = sprintf( "%u", ip2long( Utils::get_ip() ) );
  189. }
  190. $code = substr( md5( $post_id . Options::get( 'GUID' ) . 'more salt' . $ip ), 0, 10 );
  191. $code = Plugins::filter( 'comment_code', $code, $post_id, $ip );
  192. return $code;
  193. }
  194. /**
  195. * Verify a 10-digit hex code that identifies the user submitting the comment
  196. * @param A post id to which the comment has been submitted
  197. * @param The IP address of the commenter
  198. * @return True if the code is valid, false if not
  199. **/
  200. public function verify_code($suspect_code, $post_id, $ip = '')
  201. {
  202. $code = $this->get_code( $post_id, $ip );
  203. return ( $suspect_code == $code );
  204. }
  205. }
  206. ?>