Passed
Push — patch_1-1-9 ( 70f5ab...f2626d )
by Spuds
21:21 queued 15:06
created

bb2_insert()   C

Complexity

Conditions 14
Paths 97

Size

Total Lines 72
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 14
eloc 38
c 1
b 0
f 0
nc 97
nop 3
dl 0
loc 72
rs 6.2666

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
/**
4
 * This Plugin file contains all the functions that allow for ElkArte to interface
5
 * with Bad Behavior.  Bad Behavior is
6
 * Copyright (C) 2005,2006,2007,2008,2009,2010,2011,2012 Michael Hampton
7
 * License: LGPLv3
8
 *
9
 * @name      ElkArte Forum
10
 * @copyright ElkArte Forum contributors
11
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
12
 *
13
 * @version 1.1.9
14
 *
15
 */
16
17
// This die was left on purpose, because BB is special
18
if (!defined('ELK'))
19
{
20
	die('No access...');
21
}
22
23
define('BB2_CWD', dirname(__FILE__));
24
25
// Calls inward to Bad Behavior itself.
26
require_once(BB2_CWD . '/bad-behavior/core.inc.php');
27
28
/**
29
 * Return current time in the format preferred by your database.
30
 *
31
 * @return string
32
 */
33
function bb2_db_date()
34
{
35
	return time();
36
}
37
38
/**
39
 * Return affected rows from most recent query.
40
 *
41
 * @return int
42
 */
43
function bb2_db_affected_rows()
44
{
45
	$db = database();
46
47
	return $db->affected_rows();
48
}
49
50
/**
51
 * Escape a string for database usage
52
 *
53
 * @param string $string
54
 * @return string
55
 */
56
function bb2_db_escape($string)
57
{
58
	$db = database();
59
60
	return $db->escape_string($string);
61
}
62
63
/**
64
 * Return the number of rows in a particular query.
65
 *
66
 * @param object $result
67
 * @return int
68
 */
69
function bb2_db_num_rows($result)
70
{
71
	$db = database();
72
73
	return $db->num_rows($result);
0 ignored issues
show
Bug introduced by
$result of type object is incompatible with the type resource expected by parameter $result of Database::num_rows(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
	return $db->num_rows(/** @scrutinizer ignore-type */ $result);
Loading history...
74
}
75
76
/**
77
 * Run a query and return the results, if any.
78
 * Should return FALSE if an error occurred.
79
 * Bad Behavior will use the return value here in other callbacks.
80
 *
81
 * @param string $query
82
 * @return bool or int
83
 */
84
function bb2_db_query($query)
85
{
86
	global $modSettings;
87
88
	$db = database();
89
90
	// First fix the horrors caused by bb's support of only mysql
91
	// ok they are right its my horror :P
92
	if (strpos($query, 'DATE_SUB') !== false)
93
	{
94
		if (!empty($modSettings['badbehavior_logging']))
95
			$query = 'DELETE FROM {db_prefix}log_badbehavior WHERE date < ' . (bb2_db_date() - 7 * 86400);
96
		else
97
			return true;
98
	}
99
100
	if (strpos($query, 'OPTIMIZE TABLE') !== false)
101
		return true;
102
	elseif (strpos($query, '@@session.wait_timeout') !== false)
103
		return true;
104
	elseif (empty($query))
105
		return true;
106
107
	// Run the query, return success, failure or the actual results
108
	$result = $db->query('', $query, array());
109
110
	if (!$result)
111
		return false;
112
	elseif ($result === true)
113
		return (bb2_db_affected_rows() !== 0);
114
	elseif (bb2_db_num_rows($result) === 0)
115
		return false;
116
117
	return bb2_db_rows($result);
0 ignored issues
show
Bug Best Practice introduced by
The expression return bb2_db_rows($result) returns the type array<mixed,mixed> which is incompatible with the documented return type boolean.
Loading history...
118
}
119
120
/**
121
 * Return all rows in a particular query.
122
 * Should contain an array of all rows generated by calling mysql_fetch_assoc()
123
 * or equivalent and appending the result of each call to an array.
124
 *
125
 * @param object $result
126
 * @return mixed[] associate array of query results
127
 */
128
function bb2_db_rows($result)
129
{
130
	$db = database();
131
132
	$temp = array();
133
	while ($row = $db->fetch_assoc($result))
0 ignored issues
show
Bug introduced by
$result of type object is incompatible with the type resource expected by parameter $request of Database::fetch_assoc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

133
	while ($row = $db->fetch_assoc(/** @scrutinizer ignore-type */ $result))
Loading history...
134
		$temp[] = $row;
135
	$db->free_result($result);
0 ignored issues
show
Bug introduced by
$result of type object is incompatible with the type resource expected by parameter $result of Database::free_result(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

135
	$db->free_result(/** @scrutinizer ignore-type */ $result);
Loading history...
136
137
	return $temp;
138
}
139
140
/**
141
 * Return emergency contact email address.
142
 *
143
 * @return string (email address)
144
 */
145
function bb2_email()
146
{
147
	global $webmaster_email;
148
149
	return $webmaster_email;
150
}
151
152
/**
153
 * Create the query for inserting a record in to the database.
154
 * This is the main logging function for logging and verbose levels.
155
 *
156
 * @param array $settings
157
 * @param array $package
158
 * @param string $key
159
 * @return string
160
 */
161
function bb2_insert($settings, $package, $key)
162
{
163
	global $user_info;
164
165
	// Logging not enabled
166
	if (!$settings['logging'])
167
		return '';
168
169
	// Clean the data that bb sent us
170
	$ip = bb2_db_escape(substr($package['ip'], 0, 19));
171
	$date = (int) bb2_db_date();
172
	$request_method = bb2_db_escape($package['request_method']);
173
	$request_uri = bb2_db_escape(substr($package['request_uri'], 0, 254));
174
	$server_protocol = bb2_db_escape($package['server_protocol']);
175
	$user_agent = bb2_db_escape($package['user_agent']);
176
	$member_id = !empty($user_info['id']) ? (int) $user_info['id'] : 0;
177
	$session = !empty($_SESSION['session_value']) ? bb2_db_escape((string) $_SESSION['session_value']) : '';
178
179
	// Prepare the headers etc for db insertion
180
	// We are passed at least
181
	//	Host, User-Agent, Accept, Accept-Language, Accept-Encoding, DNT, Connection, Referer, Cookie, Authorization
182
	$headers = '';
183
	$length = 0;
184
	$skip = array('User-Agent', 'Accept-Encoding', 'DNT', 'X-Wap-Profile');
185
	foreach ($package['headers'] as $h => $v)
186
	{
187
		$v = trim($v);
188
		if ($v !== '' && !in_array($h, $skip))
189
		{
190
			// Make sure this header it will fit in the db, if not move on to the next
191
			// @todo increase the db space to 512 or convert to text?
192
			$check = $length + strlen($h) + strlen($v) + 2;
193
			if ($check < 254)
194
			{
195
				$headers .= bb2_db_escape("$h: $v\n");
196
				$length = $check;
197
			}
198
		}
199
	}
200
201
	$request_entity = '';
202
	if (!strcasecmp($request_method, "POST"))
203
	{
204
		foreach ($package['request_entity'] as $h => $v)
205
		{
206
			if (is_array($v))
207
				$v = bb2_multi_implode($v, ' | ', true);
208
209
			$v = trim($v);
210
			if ($v !== '')
211
				$request_entity .= bb2_db_escape("$h: $v\n");
212
		}
213
214
		// Only such much space in this column, so brutally cut it
215
		$request_entity = trim($request_entity);
216
		$request_entity = bb2_db_escape(substr($request_entity, 0, 254));
217
	}
218
219
	// Make it safe for the db
220
	foreach (array('ip', 'date', 'request_method', 'request_uri', 'server_protocol', 'headers', 'user_agent', 'request_entity', 'key', 'member_id', 'session') as $id)
221
	{
222
		$$id = trim($$id);
223
		while (preg_match('~[\'\\\\]$~', substr($$id, -1)) === 1)
224
			$$id = trim(substr($$id, 0, -1));
225
226
		$$id = str_replace("'", '_', $$id);
227
	}
228
229
	// Add it
230
	return "INSERT INTO {db_prefix}log_badbehavior
231
		(ip, date, request_method, request_uri, server_protocol, http_headers, user_agent, request_entity, valid, id_member, session) VALUES
232
		(\"$ip\", \"$date\", \"$request_method\", \"$request_uri\", \"$server_protocol\", \"$headers\", \"$user_agent\", \"$request_entity\", \"$key\", \"$member_id\" , \"$session\")";
233
}
234
235
/**
236
 * Implode that is multi dimensional array aware
237
 *
238
 * - Recursively calls itself to return a single string from a multi dimensional
239
 * array
240
 *
241
 * @param mixed[] $array array to recursively implode
242
 * @param string $glue value that glues elements together
243
 * @param bool $trim_all trim ALL whitespace from string
244
 *
245
 * @return string
246
 */
247
function bb2_multi_implode($array, $glue = ',', $trim_all = false)
248
{
249
	if (!is_array($array))
0 ignored issues
show
introduced by
The condition is_array($array) is always true.
Loading history...
250
		$array = array($array);
251
252
	foreach ($array as $key => $value)
253
	{
254
		if (is_array($value))
255
			$array[$key] = bb2_multi_implode($value, $glue, $trim_all);
256
	}
257
258
	if ($trim_all)
259
		$array = array_map('trim', $array);
260
261
	return implode($glue, $array);
262
}
263
264
/**
265
 * Retrieve whitelist
266
 *
267
 * @todo
268
 * @return type
269
 */
270
function bb2_read_whitelist()
271
{
272
	global $modSettings;
273
274
	// Current whitelist data
275
	$whitelist = array('badbehavior_ip_wl', 'badbehavior_useragent_wl', 'badbehavior_url_wl');
276
	foreach ($whitelist as $list)
277
	{
278
		$whitelist[$list] = array();
279
		if (!empty($modSettings[$list]))
280
		{
281
			$whitelist[$list] = Util::unserialize($modSettings[$list]);
282
			$whitelist[$list] = array_filter($whitelist[$list]);
0 ignored issues
show
Bug introduced by
$whitelist[$list] of type string is incompatible with the type array expected by parameter $array of array_filter(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

282
			$whitelist[$list] = array_filter(/** @scrutinizer ignore-type */ $whitelist[$list]);
Loading history...
283
		}
284
	}
285
286
	// Nothing in the whitelist
287
	if (empty($whitelist['badbehavior_ip_wl']) && empty($whitelist['badbehavior_useragent_wl']) && empty($whitelist['badbehavior_url_wl']))
288
		return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type type.
Loading history...
289
290
	// Build up the whitelist array so badbehavior can use it
291
	return array_merge(
0 ignored issues
show
Bug Best Practice introduced by
The expression return array_merge(array...havior_useragent_wl'])) returns the type array which is incompatible with the documented return type type.
Loading history...
292
		array('ip' => $whitelist['badbehavior_ip_wl']),
293
		array('url' => $whitelist['badbehavior_url_wl']),
294
		array('useragent' => $whitelist['badbehavior_useragent_wl'])
295
	);
296
}
297
298
/**
299
 * Retrieve bad behavior settings from database and supply them to
300
 * bad behavior so it knows to not behave badly
301
 *
302
 * @return mixed[]
303
 */
304
function bb2_read_settings()
305
{
306
	global $modSettings;
307
308
	$badbehavior_reverse_proxy = !empty($modSettings['badbehavior_reverse_proxy']);
309
310
	// Make sure that the proxy addresses are split into an array, and if it's empty - make sure reverse proxy is disabled
311
	if (!empty($modSettings['badbehavior_reverse_proxy_addresses']))
312
		$badbehavior_reverse_proxy_addresses = explode('|', trim($modSettings['badbehavior_reverse_proxy_addresses']));
313
	else
314
	{
315
		$badbehavior_reverse_proxy_addresses = array();
316
		$badbehavior_reverse_proxy = false;
317
	}
318
319
	// If they supplied a http:BL API Key lets see if it looks correct before we use it
320
	$invalid_badbehavior_httpbl_key = empty($modSettings['badbehavior_httpbl_key']) || (!empty($modSettings['badbehavior_httpbl_key']) && (strlen($modSettings['badbehavior_httpbl_key']) !== 12 || !ctype_lower($modSettings['badbehavior_httpbl_key'])));
321
322
	// Return the settings so BadBehavior can use them
323
	return array(
324
		'log_table' => '{db_prefix}log_badbehavior',
325
		'strict' => !empty($modSettings['badbehavior_strict']),
326
		'verbose' => !empty($modSettings['badbehavior_verbose']),
327
		'logging' => !empty($modSettings['badbehavior_logging']),
328
		'httpbl_key' => $invalid_badbehavior_httpbl_key ? '' : $modSettings['badbehavior_httpbl_key'],
329
		'httpbl_threat' => $modSettings['badbehavior_httpbl_threat'],
330
		'httpbl_maxage' => $modSettings['badbehavior_httpbl_maxage'],
331
		'eu_cookie' => !empty($modSettings['badbehavior_eucookie']),
332
		'offsite_forms' => !empty($modSettings['badbehavior_offsite_forms']),
333
		'reverse_proxy' => $badbehavior_reverse_proxy,
334
		'reverse_proxy_header' => $modSettings['badbehavior_reverse_proxy_header'],
335
		'reverse_proxy_addresses' => $badbehavior_reverse_proxy_addresses
336
	);
337
}
338
339
/**
340
 * Insert this into the <head> section of your HTML through a template call
341
 * or whatever is appropriate. This is optional we'll fall back to cookies
342
 * if you don't use it.
343
 */
344
function bb2_insert_head()
345
{
346
	global $bb2_javascript;
347
348
	// Prepare it so we can use addInlineJavascript by removing the script tags hats its pre wrapped in
349
	$temp = str_replace('<script type="text/javascript">' . "\n" . '<!--' . "\n", '', $bb2_javascript);
350
	$temp = str_replace('// --></script>', '', $temp);
351
352
	return "\n" . trim($temp);
353
}
354
355
/**
356
 * Display Statistics (default off)
357
 * Enabling this option will return a string to add a blurb to your site footer
358
 * advertising Bad Behavior’s presence and the number of recently blocked requests.
359
 *
360
 * This option is not available or has no effect when logging is not in use.
361
 *
362
 * @param bool $force
363
 */
364
function bb2_insert_stats($force = false)
365
{
366
	global $txt;
367
368
	$settings = bb2_read_settings();
369
370
	if ($force || $settings['display_stats'])
371
	{
372
		// Get the blocked count for the last 7 days ... cache this as well
373
		if (!Cache::instance()->getVar($bb2_blocked, 'bb2_blocked', 900))
374
		{
375
			$bb2_blocked = bb2_db_query('SELECT COUNT(*) FROM {db_prefix}log_badbehavior WHERE valid NOT LIKE "00000000"');
376
			Cache::instance()->put('bb2_blocked', $bb2_blocked, 900);
377
		}
378
379
		if ($bb2_blocked !== false)
380
			return sprintf($txt['badbehavior_blocked'], $bb2_blocked[0]['COUNT(*)']);
381
	}
382
}
383
384
/**
385
 * Return the top-level relative path of wherever we are (for cookies)
386
 *
387
 * @return string
388
 */
389
function bb2_relative_path()
390
{
391
	global $boardurl;
392
393
	return $boardurl;
394
}
395