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