Completed
Push — master ( e8a235...f9b8a1 )
by Stephanie
04:14
created

FrmAntiSpam::_is_regexp_spam()   C

Complexity

Conditions 12
Paths 36

Size

Total Lines 86
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 47
nc 36
nop 1
dl 0
loc 86
rs 5.034
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
if ( ! defined( 'ABSPATH' ) ) {
4
	die( 'You are not allowed to call this page directly.' );
5
}
6
7
class FrmAntiSpam {
8
9
	private static function is_spam( $comment ) {
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
Unused Code introduced by
The parameter $comment is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
10
		$response = array( 'spam' => false );
11
12
		/* Check if logged in */
13
		if ( is_user_logged_in() ) {
14
		    return $response;
15
		}
16
17
		/* Honeypot */
18
		if ( ! empty($_POST['ab_spam__hidden_field']) ) {
19
			$response['reason'] = 'css';
20
			return $response;
21
		}
22
23
		if ( empty( $ip ) ) {
0 ignored issues
show
Bug introduced by
The variable $ip seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
24
			$response['reason'] = 'empty';
25
			return $response;
26
		}
27
28
		/* Action time */
29
		if ( $options['time_check'] && self::_is_shortest_time() ) {
0 ignored issues
show
Bug introduced by
The variable $options does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
30
			$response['reason'] = 'time';
31
			return $response;
32
		}
33
34
		/* BBCode Spam */
35
		if ( $options['bbcode_check'] && self::_is_bbcode_spam($body) ) {
0 ignored issues
show
Bug introduced by
The variable $body does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
36
			$response['reason'] = 'bbcode';
37
			return $response;
38
		}
39
40
		if ( $options['advanced_check'] && self::_is_fake_ip($ip) ) {
41
			$response['reason'] = 'server';
42
			return $response;
43
		}
44
45
		/* Regexp for Spam */
46
		if ( $options['regexp_check'] ) {
47
			$is_spam = self::_is_regexp_spam( array(
48
				'ip'	 => $ip,
49
				'host'	 => parse_url($url, PHP_URL_HOST),
0 ignored issues
show
Bug introduced by
The variable $url does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
50
				'body'	 => $body,
51
				'email'	 => $email,
0 ignored issues
show
Bug introduced by
The variable $email does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
52
				'author' => $author,
0 ignored issues
show
Bug introduced by
The variable $author does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
53
			) );
54
			if ( $is_spam ) {
55
				$response['reason'] = 'regexp';
56
				return $response;
57
			}
58
		}
59
60
		/* DNSBL Spam */
61
		if ( $options['dnsbl_check'] && self::_is_dnsbl_spam( $ip ) ) {
62
			$response['reason'] = 'dnsbl';
63
			return $response;
64
		}
65
	}
66
67
	/**
68
	* Check for form submission time
69
	*
70
	* @return  boolean    TRUE if the action time is less than 5 seconds
71
	*/
72
73
	private static function _is_shortest_time() {
74
		$too_short = false;
75
		$start_time = FrmAppHelper::get_post_param( 'ab_init_time', 0, 'absint' );
76
77
		if ( $start_time ) {
78
			// Compare time values
79
			$min_seconds = apply_filters( 'frm_spam_time_limit', 5 );
80
			$total_time = time() - $start_time;
81
			if ( $total_time < $min_seconds ) {
82
				$too_short = true;
83
			}
84
		}
85
86
		return $too_short;
87
	}
88
89
	private static function _is_bbcode_spam( $body ) {
90
		return (bool) preg_match( '/\[url[=\]].*\[\/url\]/is', $body );
91
	}
92
	
93
	private static function _is_fake_ip( $client_ip, $client_host = false ) {
94
		/* Remote Host */
95
		$host_by_ip = gethostbyaddr( $client_ip );
96
97
		/* IPv6 */
98
		if ( self::_is_ipv6( $client_ip ) ) {
99
			return $client_ip != $host_by_ip;
100
		}
101
102
		/* IPv4 */
103
		if ( empty( $client_host ) ) {
104
			$ip_by_host = gethostbyname( $host_by_ip );
105
106
			if ( $ip_by_host === $host_by_ip ) {
107
				return false;
108
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
109
110
		} else {
111
			/* IPv4 / API */
112
			if ( $host_by_ip === $client_ip ) {
113
				return true;
114
			}
115
116
			$ip_by_host = gethostbyname($client_host);
117
		}
118
119
		if ( strpos( $client_ip, self::_cut_ip($ip_by_host) ) === false ) {
120
			return true;
121
		}
122
123
		return false;
124
	}
125
126
	/**
127
	* Check for an IPv6 address
128
	*
129
	* @param   string   $ip  IP to validate
130
	* @return  boolean       TRUE if IPv6
131
	*/
132
133
	private static function _is_ipv6( $ip ) {
134
		if ( function_exists('filter_var') ) {
135
			return filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) !== false;
136
		} else {
137
			return ! self::_is_ipv4( $ip );
0 ignored issues
show
Bug introduced by
The method _is_ipv4() does not seem to exist on object<FrmAntiSpam>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
138
		}
139
	}
140
141
	private static function _cut_ip( $ip, $cut_end = true ) {
142
		$separator = ( self::_is_ipv4($ip) ? '.' : ':' );
0 ignored issues
show
Bug introduced by
The method _is_ipv4() does not seem to exist on object<FrmAntiSpam>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
143
		$part = ( $cut_end ? strrchr( $ip, $separator) : strstr( $ip, $separator) );
144
145
		return str_replace( $part, '', $ip );
146
	}
147
148
	private static function _is_regexp_spam( $comment ) {
149
		/* Felder */
150
		$fields = array(
151
			'ip',
152
			'host',
153
			'body',
154
			'email',
155
			'author'
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
156
		);
157
158
		/* Regexp */
159
		$patterns = array(
160
			0 => array(
161
				'host'	=> '^(www\.)?\d+\w+\.com$',
162
				'body'	=> '^\w+\s\d+$',
163
				'email'	=> '@gmail.com$'
0 ignored issues
show
introduced by
Each line in an array declaration must end in a comma
Loading history...
164
			),
165
			1 => array(
166
				'body'	=> '\<\!.+?mfunc.+?\>'
0 ignored issues
show
introduced by
Each line in an array declaration must end in a comma
Loading history...
167
			)
168
		);
169
170
		/* Spammy author */
171
		if ( $quoted_author = preg_quote($comment['author'], '/') ) {
172
			$patterns[] = array(
173
				'body' => sprintf(
174
					'<a.+?>%s<\/a>$',
175
					$quoted_author
176
				)
177
			);
178
			$patterns[] = array(
179
				'body' => sprintf(
180
					'%s https?:.+?$',
181
					$quoted_author
182
				)
183
			);
184
			$patterns[] = array(
185
				'email'	 => '@gmail.com$',
186
				'author' => '^[a-z0-9-\.]+\.[a-z]{2,6}$',
187
				'host'	 => sprintf(
188
					'^%s$',
189
					$quoted_author
190
				)
191
			);
192
		}
193
194
		/* Hook */
195
		$patterns = apply_filters(
196
			'antispam_bee_patterns',
197
			$patterns
198
		);
199
200
		if ( ! $patterns ) {
201
			return false;
202
		}
203
204
		foreach ($patterns as $pattern) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
205
			$hits = array();
206
207
			foreach ($pattern as $field => $regexp) {
0 ignored issues
show
introduced by
No space after opening parenthesis is prohibited
Loading history...
introduced by
No space before closing parenthesis is prohibited
Loading history...
208
				/* Empty value? */
209
				if ( empty($field) OR !in_array($field, $fields) OR empty($regexp) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
210
					continue;
211
				}
212
213
				/* Ignore non utf-8 chars */
214
				$comment[$field] = ( function_exists('iconv') ? iconv('utf-8', 'utf-8//TRANSLIT', $comment[$field]) : $comment[$field] );
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
215
216
				/* Empty value? */
217
				if ( empty($comment[$field]) ) {
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
218
					continue;
219
				}
220
221
				/* Perform regex */
222
				if ( @preg_match('/' .$regexp. '/isu', $comment[$field]) ) {
0 ignored issues
show
Coding Style introduced by
Silencing errors is discouraged
Loading history...
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
223
					$hits[$field] = true;
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
224
				}
225
			}
226
227
			if ( count($hits) === count($pattern) ) {
228
				return true;
229
			}
230
		}
231
232
		return false;
233
	}
234
235
	private static function _is_dnsbl_spam( $ip ) {
236
		/* Start request */
237
		$response = wp_safe_remote_request(
238
			esc_url_raw(
239
				sprintf( 'http://www.stopforumspam.com/api?ip=%s&f=json', $ip ),
240
				'http'
241
			)
242
		);
243
244
		/* Response error? */
245
		if ( is_wp_error( $response ) ) {
246
			return false;
247
		}
248
249
		/* Get JSON */
250
		$json = wp_remote_retrieve_body( $response );
251
252
		/* Decode JSON */
253
		$result = json_decode( $json );
254
255
		/* Empty data */
256
		if ( empty( $result->success ) ) {
257
			return false;
258
		}
259
260
		/* Return status */
261
		return (bool) $result->ip->appears;
262
	}	
263
}
264