|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* This file contains all the functions used for the ban center. |
|
5
|
|
|
* @todo refactor as controller-model |
|
6
|
|
|
* |
|
7
|
|
|
* Simple Machines Forum (SMF) |
|
8
|
|
|
* |
|
9
|
|
|
* @package SMF |
|
10
|
|
|
* @author Simple Machines http://www.simplemachines.org |
|
11
|
|
|
* @copyright 2017 Simple Machines and individual contributors |
|
12
|
|
|
* @license http://www.simplemachines.org/about/smf/license.php BSD |
|
13
|
|
|
* |
|
14
|
|
|
* @version 2.1 Beta 4 |
|
15
|
|
|
*/ |
|
16
|
|
|
|
|
17
|
|
|
if (!defined('SMF')) |
|
18
|
|
|
die('No direct access...'); |
|
19
|
|
|
|
|
20
|
|
|
/** |
|
21
|
|
|
* Ban center. The main entrance point for all ban center functions. |
|
22
|
|
|
* It is accesssed by ?action=admin;area=ban. |
|
23
|
|
|
* It choses a function based on the 'sa' parameter, like many others. |
|
24
|
|
|
* The default sub-action is BanList(). |
|
25
|
|
|
* It requires the ban_members permission. |
|
26
|
|
|
* It initializes the admin tabs. |
|
27
|
|
|
* |
|
28
|
|
|
* @uses ManageBans template. |
|
29
|
|
|
*/ |
|
30
|
|
|
function Ban() |
|
31
|
|
|
{ |
|
32
|
|
|
global $context, $txt, $scripturl; |
|
33
|
|
|
|
|
34
|
|
|
isAllowedTo('manage_bans'); |
|
35
|
|
|
|
|
36
|
|
|
loadTemplate('ManageBans'); |
|
37
|
|
|
|
|
38
|
|
|
$subActions = array( |
|
39
|
|
|
'add' => 'BanEdit', |
|
40
|
|
|
'browse' => 'BanBrowseTriggers', |
|
41
|
|
|
'edittrigger' => 'BanEditTrigger', |
|
42
|
|
|
'edit' => 'BanEdit', |
|
43
|
|
|
'list' => 'BanList', |
|
44
|
|
|
'log' => 'BanLog', |
|
45
|
|
|
); |
|
46
|
|
|
|
|
47
|
|
|
// Default the sub-action to 'view ban list'. |
|
48
|
|
|
$_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'list'; |
|
49
|
|
|
|
|
50
|
|
|
$context['page_title'] = $txt['ban_title']; |
|
51
|
|
|
$context['sub_action'] = $_REQUEST['sa']; |
|
52
|
|
|
|
|
53
|
|
|
// Tabs for browsing the different ban functions. |
|
54
|
|
|
$context[$context['admin_menu_name']]['tab_data'] = array( |
|
55
|
|
|
'title' => $txt['ban_title'], |
|
56
|
|
|
'help' => 'ban_members', |
|
57
|
|
|
'description' => $txt['ban_description'], |
|
58
|
|
|
'tabs' => array( |
|
59
|
|
|
'list' => array( |
|
60
|
|
|
'description' => $txt['ban_description'], |
|
61
|
|
|
'href' => $scripturl . '?action=admin;area=ban;sa=list', |
|
62
|
|
|
'is_selected' => $_REQUEST['sa'] == 'list' || $_REQUEST['sa'] == 'edit' || $_REQUEST['sa'] == 'edittrigger', |
|
63
|
|
|
), |
|
64
|
|
|
'add' => array( |
|
65
|
|
|
'description' => $txt['ban_description'], |
|
66
|
|
|
'href' => $scripturl . '?action=admin;area=ban;sa=add', |
|
67
|
|
|
'is_selected' => $_REQUEST['sa'] == 'add', |
|
68
|
|
|
), |
|
69
|
|
|
'browse' => array( |
|
70
|
|
|
'description' => $txt['ban_trigger_browse_description'], |
|
71
|
|
|
'href' => $scripturl . '?action=admin;area=ban;sa=browse', |
|
72
|
|
|
'is_selected' => $_REQUEST['sa'] == 'browse', |
|
73
|
|
|
), |
|
74
|
|
|
'log' => array( |
|
75
|
|
|
'description' => $txt['ban_log_description'], |
|
76
|
|
|
'href' => $scripturl . '?action=admin;area=ban;sa=log', |
|
77
|
|
|
'is_selected' => $_REQUEST['sa'] == 'log', |
|
78
|
|
|
'is_last' => true, |
|
79
|
|
|
), |
|
80
|
|
|
), |
|
81
|
|
|
); |
|
82
|
|
|
|
|
83
|
|
|
call_integration_hook('integrate_manage_bans', array(&$subActions)); |
|
84
|
|
|
|
|
85
|
|
|
// Call the right function for this sub-action. |
|
86
|
|
|
call_helper($subActions[$_REQUEST['sa']]); |
|
87
|
|
|
} |
|
88
|
|
|
|
|
89
|
|
|
/** |
|
90
|
|
|
* Shows a list of bans currently set. |
|
91
|
|
|
* It is accessed by ?action=admin;area=ban;sa=list. |
|
92
|
|
|
* It removes expired bans. |
|
93
|
|
|
* It allows sorting on different criteria. |
|
94
|
|
|
* It also handles removal of selected ban items. |
|
95
|
|
|
* |
|
96
|
|
|
* @uses the main ManageBans template. |
|
97
|
|
|
*/ |
|
98
|
|
|
function BanList() |
|
99
|
|
|
{ |
|
100
|
|
|
global $txt, $context, $scripturl; |
|
101
|
|
|
global $user_info, $sourcedir, $modSettings; |
|
102
|
|
|
|
|
103
|
|
|
// User pressed the 'remove selection button'. |
|
104
|
|
|
if (!empty($_POST['removeBans']) && !empty($_POST['remove']) && is_array($_POST['remove'])) |
|
105
|
|
|
{ |
|
106
|
|
|
checkSession(); |
|
107
|
|
|
|
|
108
|
|
|
// Make sure every entry is a proper integer. |
|
109
|
|
|
array_map('intval', $_POST['remove']); |
|
110
|
|
|
|
|
111
|
|
|
// Unban them all! |
|
112
|
|
|
removeBanGroups($_POST['remove']); |
|
113
|
|
|
removeBanTriggers($_POST['remove']); |
|
114
|
|
|
|
|
115
|
|
|
// No more caching this ban! |
|
116
|
|
|
updateSettings(array('banLastUpdated' => time())); |
|
117
|
|
|
|
|
118
|
|
|
// Some members might be unbanned now. Update the members table. |
|
119
|
|
|
updateBanMembers(); |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
// Create a date string so we don't overload them with date info. |
|
123
|
|
|
if (preg_match('~%[AaBbCcDdeGghjmuYy](?:[^%]*%[AaBbCcDdeGghjmuYy])*~', $user_info['time_format'], $matches) == 0 || empty($matches[0])) |
|
124
|
|
|
$context['ban_time_format'] = $user_info['time_format']; |
|
125
|
|
|
else |
|
126
|
|
|
$context['ban_time_format'] = $matches[0]; |
|
127
|
|
|
|
|
128
|
|
|
$listOptions = array( |
|
129
|
|
|
'id' => 'ban_list', |
|
130
|
|
|
'title' => $txt['ban_title'], |
|
131
|
|
|
'items_per_page' => $modSettings['defaultMaxListItems'], |
|
132
|
|
|
'base_href' => $scripturl . '?action=admin;area=ban;sa=list', |
|
133
|
|
|
'default_sort_col' => 'added', |
|
134
|
|
|
'default_sort_dir' => 'desc', |
|
135
|
|
|
'get_items' => array( |
|
136
|
|
|
'function' => 'list_getBans', |
|
137
|
|
|
), |
|
138
|
|
|
'get_count' => array( |
|
139
|
|
|
'function' => 'list_getNumBans', |
|
140
|
|
|
), |
|
141
|
|
|
'no_items_label' => $txt['ban_no_entries'], |
|
142
|
|
|
'columns' => array( |
|
143
|
|
|
'name' => array( |
|
144
|
|
|
'header' => array( |
|
145
|
|
|
'value' => $txt['ban_name'], |
|
146
|
|
|
), |
|
147
|
|
|
'data' => array( |
|
148
|
|
|
'db' => 'name', |
|
149
|
|
|
), |
|
150
|
|
|
'sort' => array( |
|
151
|
|
|
'default' => 'bg.name', |
|
152
|
|
|
'reverse' => 'bg.name DESC', |
|
153
|
|
|
), |
|
154
|
|
|
), |
|
155
|
|
|
'notes' => array( |
|
156
|
|
|
'header' => array( |
|
157
|
|
|
'value' => $txt['ban_notes'], |
|
158
|
|
|
), |
|
159
|
|
|
'data' => array( |
|
160
|
|
|
'db' => 'notes', |
|
161
|
|
|
'class' => 'smalltext', |
|
162
|
|
|
), |
|
163
|
|
|
'sort' => array( |
|
164
|
|
|
'default' => 'LENGTH(bg.notes) > 0 DESC, bg.notes', |
|
165
|
|
|
'reverse' => 'LENGTH(bg.notes) > 0, bg.notes DESC', |
|
166
|
|
|
), |
|
167
|
|
|
), |
|
168
|
|
|
'reason' => array( |
|
169
|
|
|
'header' => array( |
|
170
|
|
|
'value' => $txt['ban_reason'], |
|
171
|
|
|
), |
|
172
|
|
|
'data' => array( |
|
173
|
|
|
'db' => 'reason', |
|
174
|
|
|
'class' => 'smalltext', |
|
175
|
|
|
), |
|
176
|
|
|
'sort' => array( |
|
177
|
|
|
'default' => 'LENGTH(bg.reason) > 0 DESC, bg.reason', |
|
178
|
|
|
'reverse' => 'LENGTH(bg.reason) > 0, bg.reason DESC', |
|
179
|
|
|
), |
|
180
|
|
|
), |
|
181
|
|
|
'added' => array( |
|
182
|
|
|
'header' => array( |
|
183
|
|
|
'value' => $txt['ban_added'], |
|
184
|
|
|
), |
|
185
|
|
|
'data' => array( |
|
186
|
|
|
'function' => function($rowData) use ($context) |
|
187
|
|
|
{ |
|
188
|
|
|
return timeformat($rowData['ban_time'], empty($context['ban_time_format']) ? true : $context['ban_time_format']); |
|
189
|
|
|
}, |
|
190
|
|
|
), |
|
191
|
|
|
'sort' => array( |
|
192
|
|
|
'default' => 'bg.ban_time', |
|
193
|
|
|
'reverse' => 'bg.ban_time DESC', |
|
194
|
|
|
), |
|
195
|
|
|
), |
|
196
|
|
|
'expires' => array( |
|
197
|
|
|
'header' => array( |
|
198
|
|
|
'value' => $txt['ban_expires'], |
|
199
|
|
|
), |
|
200
|
|
|
'data' => array( |
|
201
|
|
|
'function' => function($rowData) use ($txt) |
|
202
|
|
|
{ |
|
203
|
|
|
// This ban never expires...whahaha. |
|
204
|
|
|
if ($rowData['expire_time'] === null) |
|
205
|
|
|
return $txt['never']; |
|
206
|
|
|
|
|
207
|
|
|
// This ban has already expired. |
|
208
|
|
|
elseif ($rowData['expire_time'] < time()) |
|
209
|
|
|
return sprintf('<span class="red">%1$s</span>', $txt['ban_expired']); |
|
210
|
|
|
|
|
211
|
|
|
// Still need to wait a few days for this ban to expire. |
|
212
|
|
|
else |
|
213
|
|
|
return sprintf('%1$d %2$s', ceil(($rowData['expire_time'] - time()) / (60 * 60 * 24)), $txt['ban_days']); |
|
214
|
|
|
}, |
|
215
|
|
|
), |
|
216
|
|
|
'sort' => array( |
|
217
|
|
|
'default' => 'COALESCE(bg.expire_time, 1=1) DESC, bg.expire_time DESC', |
|
218
|
|
|
'reverse' => 'COALESCE(bg.expire_time, 1=1), bg.expire_time', |
|
219
|
|
|
), |
|
220
|
|
|
), |
|
221
|
|
|
'num_triggers' => array( |
|
222
|
|
|
'header' => array( |
|
223
|
|
|
'value' => $txt['ban_triggers'], |
|
224
|
|
|
), |
|
225
|
|
|
'data' => array( |
|
226
|
|
|
'db' => 'num_triggers', |
|
227
|
|
|
), |
|
228
|
|
|
'sort' => array( |
|
229
|
|
|
'default' => 'num_triggers DESC', |
|
230
|
|
|
'reverse' => 'num_triggers', |
|
231
|
|
|
), |
|
232
|
|
|
), |
|
233
|
|
|
'actions' => array( |
|
234
|
|
|
'header' => array( |
|
235
|
|
|
'value' => $txt['ban_actions'], |
|
236
|
|
|
'class' => 'centercol', |
|
237
|
|
|
), |
|
238
|
|
|
'data' => array( |
|
239
|
|
|
'sprintf' => array( |
|
240
|
|
|
'format' => '<a href="' . $scripturl . '?action=admin;area=ban;sa=edit;bg=%1$d">' . $txt['modify'] . '</a>', |
|
241
|
|
|
'params' => array( |
|
242
|
|
|
'id_ban_group' => false, |
|
243
|
|
|
), |
|
244
|
|
|
), |
|
245
|
|
|
'class' => 'centercol', |
|
246
|
|
|
), |
|
247
|
|
|
), |
|
248
|
|
|
'check' => array( |
|
249
|
|
|
'header' => array( |
|
250
|
|
|
'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check">', |
|
251
|
|
|
'class' => 'centercol', |
|
252
|
|
|
), |
|
253
|
|
|
'data' => array( |
|
254
|
|
|
'sprintf' => array( |
|
255
|
|
|
'format' => '<input type="checkbox" name="remove[]" value="%1$d" class="input_check">', |
|
256
|
|
|
'params' => array( |
|
257
|
|
|
'id_ban_group' => false, |
|
258
|
|
|
), |
|
259
|
|
|
), |
|
260
|
|
|
'class' => 'centercol', |
|
261
|
|
|
), |
|
262
|
|
|
), |
|
263
|
|
|
), |
|
264
|
|
|
'form' => array( |
|
265
|
|
|
'href' => $scripturl . '?action=admin;area=ban;sa=list', |
|
266
|
|
|
), |
|
267
|
|
|
'additional_rows' => array( |
|
268
|
|
|
array( |
|
269
|
|
|
'position' => 'top_of_list', |
|
270
|
|
|
'value' => '<input type="submit" name="removeBans" value="' . $txt['ban_remove_selected'] . '" data-confirm="' . $txt['ban_remove_selected_confirm'] . '" class="button_submit you_sure">', |
|
271
|
|
|
), |
|
272
|
|
|
array( |
|
273
|
|
|
'position' => 'bottom_of_list', |
|
274
|
|
|
'value' => '<input type="submit" name="removeBans" value="' . $txt['ban_remove_selected'] . '" data-confirm="' . $txt['ban_remove_selected_confirm'] . '" class="button_submit you_sure">', |
|
275
|
|
|
), |
|
276
|
|
|
), |
|
277
|
|
|
); |
|
278
|
|
|
|
|
279
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
|
280
|
|
|
createList($listOptions); |
|
281
|
|
|
|
|
282
|
|
|
$context['sub_template'] = 'show_list'; |
|
283
|
|
|
$context['default_list'] = 'ban_list'; |
|
284
|
|
|
} |
|
285
|
|
|
|
|
286
|
|
|
/** |
|
287
|
|
|
* Get bans, what else? For the given options. |
|
288
|
|
|
* |
|
289
|
|
|
* @param int $start Which item to start with (for pagination purposes) |
|
290
|
|
|
* @param int $items_per_page How many items to show on each page |
|
291
|
|
|
* @param string $sort A string telling ORDER BY how to sort the results |
|
292
|
|
|
* @return array An array of information about the bans for the list |
|
293
|
|
|
*/ |
|
294
|
|
View Code Duplication |
function list_getBans($start, $items_per_page, $sort) |
|
|
|
|
|
|
295
|
|
|
{ |
|
296
|
|
|
global $smcFunc; |
|
297
|
|
|
|
|
298
|
|
|
$request = $smcFunc['db_query']('', ' |
|
299
|
|
|
SELECT bg.id_ban_group, bg.name, bg.ban_time, bg.expire_time, bg.reason, bg.notes, COUNT(bi.id_ban) AS num_triggers |
|
300
|
|
|
FROM {db_prefix}ban_groups AS bg |
|
301
|
|
|
LEFT JOIN {db_prefix}ban_items AS bi ON (bi.id_ban_group = bg.id_ban_group) |
|
302
|
|
|
GROUP BY bg.id_ban_group, bg.name, bg.ban_time, bg.expire_time, bg.reason, bg.notes |
|
303
|
|
|
ORDER BY {raw:sort} |
|
304
|
|
|
LIMIT {int:offset}, {int:limit}', |
|
305
|
|
|
array( |
|
306
|
|
|
'sort' => $sort, |
|
307
|
|
|
'offset' => $start, |
|
308
|
|
|
'limit' => $items_per_page, |
|
309
|
|
|
) |
|
310
|
|
|
); |
|
311
|
|
|
$bans = array(); |
|
312
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
313
|
|
|
$bans[] = $row; |
|
314
|
|
|
|
|
315
|
|
|
$smcFunc['db_free_result']($request); |
|
316
|
|
|
|
|
317
|
|
|
return $bans; |
|
318
|
|
|
} |
|
319
|
|
|
|
|
320
|
|
|
/** |
|
321
|
|
|
* Get the total number of ban from the ban group table |
|
322
|
|
|
* |
|
323
|
|
|
* @return int The total number of bans |
|
324
|
|
|
*/ |
|
325
|
|
|
function list_getNumBans() |
|
326
|
|
|
{ |
|
327
|
|
|
global $smcFunc; |
|
328
|
|
|
|
|
329
|
|
|
$request = $smcFunc['db_query']('', ' |
|
330
|
|
|
SELECT COUNT(*) AS num_bans |
|
331
|
|
|
FROM {db_prefix}ban_groups', |
|
332
|
|
|
array( |
|
333
|
|
|
) |
|
334
|
|
|
); |
|
335
|
|
|
list ($numBans) = $smcFunc['db_fetch_row']($request); |
|
336
|
|
|
$smcFunc['db_free_result']($request); |
|
337
|
|
|
|
|
338
|
|
|
return $numBans; |
|
339
|
|
|
} |
|
340
|
|
|
|
|
341
|
|
|
/** |
|
342
|
|
|
* This function is behind the screen for adding new bans and modifying existing ones. |
|
343
|
|
|
* Adding new bans: |
|
344
|
|
|
* - is accessed by ?action=admin;area=ban;sa=add. |
|
345
|
|
|
* - uses the ban_edit sub template of the ManageBans template. |
|
346
|
|
|
* Modifying existing bans: |
|
347
|
|
|
* - is accessed by ?action=admin;area=ban;sa=edit;bg=x |
|
348
|
|
|
* - uses the ban_edit sub template of the ManageBans template. |
|
349
|
|
|
* - shows a list of ban triggers for the specified ban. |
|
350
|
|
|
*/ |
|
351
|
|
|
function BanEdit() |
|
352
|
|
|
{ |
|
353
|
|
|
global $txt, $modSettings, $context, $scripturl, $smcFunc, $sourcedir; |
|
354
|
|
|
|
|
355
|
|
|
if ((isset($_POST['add_ban']) || isset($_POST['modify_ban']) || isset($_POST['remove_selection'])) && empty($context['ban_errors'])) |
|
356
|
|
|
BanEdit2(); |
|
357
|
|
|
|
|
358
|
|
|
$ban_group_id = isset($context['ban']['id']) ? $context['ban']['id'] : (isset($_REQUEST['bg']) ? (int) $_REQUEST['bg'] : 0); |
|
359
|
|
|
|
|
360
|
|
|
// Template needs this to show errors using javascript |
|
361
|
|
|
loadLanguage('Errors'); |
|
362
|
|
|
createToken('admin-bet'); |
|
363
|
|
|
$context['form_url'] = $scripturl . '?action=admin;area=ban;sa=edit'; |
|
364
|
|
|
|
|
365
|
|
|
if (!empty($context['ban_errors'])) |
|
366
|
|
|
{ |
|
367
|
|
|
foreach ($context['ban_errors'] as $error) |
|
|
|
|
|
|
368
|
|
|
$context['error_messages'][$error] = $txt[$error]; |
|
369
|
|
|
} |
|
370
|
|
|
else |
|
371
|
|
|
{ |
|
372
|
|
|
// If we're editing an existing ban, get it from the database. |
|
373
|
|
|
if (!empty($ban_group_id)) |
|
374
|
|
|
{ |
|
375
|
|
|
$context['ban_group_id'] = $ban_group_id; |
|
376
|
|
|
|
|
377
|
|
|
// We're going to want this for making our list. |
|
378
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
|
379
|
|
|
|
|
380
|
|
|
$listOptions = array( |
|
381
|
|
|
'id' => 'ban_items', |
|
382
|
|
|
'base_href' => $scripturl . '?action=admin;area=ban;sa=edit;bg=' . $ban_group_id, |
|
383
|
|
|
'no_items_label' => $txt['ban_no_triggers'], |
|
384
|
|
|
'items_per_page' => $modSettings['defaultMaxListItems'], |
|
385
|
|
|
'get_items' => array( |
|
386
|
|
|
'function' => 'list_getBanItems', |
|
387
|
|
|
'params' => array( |
|
388
|
|
|
'ban_group_id' => $ban_group_id, |
|
389
|
|
|
), |
|
390
|
|
|
), |
|
391
|
|
|
'get_count' => array( |
|
392
|
|
|
'function' => 'list_getNumBanItems', |
|
393
|
|
|
'params' => array( |
|
394
|
|
|
'ban_group_id' => $ban_group_id, |
|
395
|
|
|
), |
|
396
|
|
|
), |
|
397
|
|
|
'columns' => array( |
|
398
|
|
|
'type' => array( |
|
399
|
|
|
'header' => array( |
|
400
|
|
|
'value' => $txt['ban_banned_entity'], |
|
401
|
|
|
'style' => 'width: 60%;text-align: left;', |
|
402
|
|
|
), |
|
403
|
|
|
'data' => array( |
|
404
|
|
|
'function' => function($ban_item) use ($txt) |
|
405
|
|
|
{ |
|
406
|
|
|
if (in_array($ban_item['type'], array('ip', 'hostname', 'email'))) |
|
407
|
|
|
return '<strong>' . $txt[$ban_item['type']] . ':</strong> ' . $ban_item[$ban_item['type']]; |
|
408
|
|
|
elseif ($ban_item['type'] == 'user') |
|
409
|
|
|
return '<strong>' . $txt['username'] . ':</strong> ' . $ban_item['user']['link']; |
|
410
|
|
|
else |
|
411
|
|
|
return '<strong>' . $txt['unknown'] . ':</strong> ' . $ban_item['no_bantype_selected']; |
|
412
|
|
|
}, |
|
413
|
|
|
'style' => 'text-align: left;', |
|
414
|
|
|
), |
|
415
|
|
|
), |
|
416
|
|
|
'hits' => array( |
|
417
|
|
|
'header' => array( |
|
418
|
|
|
'value' => $txt['ban_hits'], |
|
419
|
|
|
'style' => 'width: 15%; text-align: center;', |
|
420
|
|
|
), |
|
421
|
|
|
'data' => array( |
|
422
|
|
|
'db' => 'hits', |
|
423
|
|
|
'style' => 'text-align: center;', |
|
424
|
|
|
), |
|
425
|
|
|
), |
|
426
|
|
|
'id' => array( |
|
427
|
|
|
'header' => array( |
|
428
|
|
|
'value' => $txt['ban_actions'], |
|
429
|
|
|
'style' => 'width: 15%; text-align: center;', |
|
430
|
|
|
), |
|
431
|
|
|
'data' => array( |
|
432
|
|
|
'function' => function($ban_item) use ($txt, $context, $scripturl) |
|
433
|
|
|
{ |
|
434
|
|
|
return '<a href="' . $scripturl . '?action=admin;area=ban;sa=edittrigger;bg=' . $context['ban_group_id'] . ';bi=' . $ban_item['id'] . '">' . $txt['ban_edit_trigger'] . '</a>'; |
|
435
|
|
|
}, |
|
436
|
|
|
'style' => 'text-align: center;', |
|
437
|
|
|
), |
|
438
|
|
|
), |
|
439
|
|
|
'checkboxes' => array( |
|
440
|
|
|
'header' => array( |
|
441
|
|
|
'value' => '<input type="checkbox" onclick="invertAll(this, this.form, \'ban_items\');" class="input_check">', |
|
442
|
|
|
'style' => 'width: 5%; text-align: center;', |
|
443
|
|
|
), |
|
444
|
|
|
'data' => array( |
|
445
|
|
|
'sprintf' => array( |
|
446
|
|
|
'format' => '<input type="checkbox" name="ban_items[]" value="%1$d" class="input_check">', |
|
447
|
|
|
'params' => array( |
|
448
|
|
|
'id' => false, |
|
449
|
|
|
), |
|
450
|
|
|
), |
|
451
|
|
|
'style' => 'text-align: center;', |
|
452
|
|
|
), |
|
453
|
|
|
), |
|
454
|
|
|
), |
|
455
|
|
|
'form' => array( |
|
456
|
|
|
'href' => $scripturl . '?action=admin;area=ban;sa=edit;bg=' . $ban_group_id, |
|
457
|
|
|
), |
|
458
|
|
|
'additional_rows' => array( |
|
459
|
|
|
array( |
|
460
|
|
|
'position' => 'above_table_headers', |
|
461
|
|
|
'value' => ' |
|
462
|
|
|
<input type="submit" name="remove_selection" value="' . $txt['ban_remove_selected_triggers'] . '" class="button_submit"> <a class="button_link" href="' . $scripturl . '?action=admin;area=ban;sa=edittrigger;bg=' . $ban_group_id . '">' . $txt['ban_add_trigger'] . '</a>', |
|
463
|
|
|
'style' => 'text-align: right;', |
|
464
|
|
|
), |
|
465
|
|
|
array( |
|
466
|
|
|
'position' => 'above_table_headers', |
|
467
|
|
|
'value' => ' |
|
468
|
|
|
<input type="hidden" name="bg" value="' . $ban_group_id . '"> |
|
469
|
|
|
<input type="hidden" name="' . $context['session_var'] . '" value="' . $context['session_id'] . '"> |
|
470
|
|
|
<input type="hidden" name="' . $context['admin-bet_token_var'] . '" value="' . $context['admin-bet_token'] . '">', |
|
471
|
|
|
), |
|
472
|
|
|
array( |
|
473
|
|
|
'position' => 'below_table_data', |
|
474
|
|
|
'value' => ' |
|
475
|
|
|
<input type="submit" name="remove_selection" value="' . $txt['ban_remove_selected_triggers'] . '" class="button_submit"> <a class="button_link" href="' . $scripturl . '?action=admin;area=ban;sa=edittrigger;bg=' . $ban_group_id . '">' . $txt['ban_add_trigger'] . '</a>', |
|
476
|
|
|
'style' => 'text-align: right;', |
|
477
|
|
|
), |
|
478
|
|
|
array( |
|
479
|
|
|
'position' => 'below_table_data', |
|
480
|
|
|
'value' => ' |
|
481
|
|
|
<input type="hidden" name="bg" value="' . $ban_group_id . '"> |
|
482
|
|
|
<input type="hidden" name="' . $context['session_var'] . '" value="' . $context['session_id'] . '"> |
|
483
|
|
|
<input type="hidden" name="' . $context['admin-bet_token_var'] . '" value="' . $context['admin-bet_token'] . '">', |
|
484
|
|
|
), |
|
485
|
|
|
), |
|
486
|
|
|
); |
|
487
|
|
|
createList($listOptions); |
|
488
|
|
|
} |
|
489
|
|
|
// Not an existing one, then it's probably a new one. |
|
490
|
|
|
else |
|
491
|
|
|
{ |
|
492
|
|
|
$context['ban'] = array( |
|
493
|
|
|
'id' => 0, |
|
494
|
|
|
'name' => '', |
|
495
|
|
|
'expiration' => array( |
|
496
|
|
|
'status' => 'never', |
|
497
|
|
|
'days' => 0 |
|
498
|
|
|
), |
|
499
|
|
|
'reason' => '', |
|
500
|
|
|
'notes' => '', |
|
501
|
|
|
'ban_days' => 0, |
|
502
|
|
|
'cannot' => array( |
|
503
|
|
|
'access' => true, |
|
504
|
|
|
'post' => false, |
|
505
|
|
|
'register' => false, |
|
506
|
|
|
'login' => false, |
|
507
|
|
|
), |
|
508
|
|
|
'is_new' => true, |
|
509
|
|
|
); |
|
510
|
|
|
$context['ban_suggestions'] = array( |
|
511
|
|
|
'main_ip' => '', |
|
512
|
|
|
'hostname' => '', |
|
513
|
|
|
'email' => '', |
|
514
|
|
|
'member' => array( |
|
515
|
|
|
'id' => 0, |
|
516
|
|
|
), |
|
517
|
|
|
); |
|
518
|
|
|
|
|
519
|
|
|
// Overwrite some of the default form values if a user ID was given. |
|
520
|
|
|
if (!empty($_REQUEST['u'])) |
|
521
|
|
|
{ |
|
522
|
|
|
$request = $smcFunc['db_query']('', ' |
|
523
|
|
|
SELECT id_member, real_name, member_ip, email_address |
|
524
|
|
|
FROM {db_prefix}members |
|
525
|
|
|
WHERE id_member = {int:current_user} |
|
526
|
|
|
LIMIT 1', |
|
527
|
|
|
array( |
|
528
|
|
|
'current_user' => (int) $_REQUEST['u'], |
|
529
|
|
|
) |
|
530
|
|
|
); |
|
531
|
|
|
if ($smcFunc['db_num_rows']($request) > 0) |
|
532
|
|
|
{ |
|
533
|
|
|
list ($context['ban_suggestions']['member']['id'], $context['ban_suggestions']['member']['name'], $context['ban_suggestions']['main_ip'], $context['ban_suggestions']['email']) = $smcFunc['db_fetch_row']($request); |
|
534
|
|
|
$context['ban_suggestions']['main_ip'] = inet_dtop($context['ban_suggestions']['main_ip']); |
|
535
|
|
|
} |
|
536
|
|
|
$smcFunc['db_free_result']($request); |
|
537
|
|
|
|
|
538
|
|
|
if (!empty($context['ban_suggestions']['member']['id'])) |
|
539
|
|
|
{ |
|
540
|
|
|
$context['ban_suggestions']['href'] = $scripturl . '?action=profile;u=' . $context['ban_suggestions']['member']['id']; |
|
541
|
|
|
$context['ban_suggestions']['member']['link'] = '<a href="' . $context['ban_suggestions']['href'] . '">' . $context['ban_suggestions']['member']['name'] . '</a>'; |
|
542
|
|
|
|
|
543
|
|
|
// Default the ban name to the name of the banned member. |
|
544
|
|
|
$context['ban']['name'] = $context['ban_suggestions']['member']['name']; |
|
545
|
|
|
// @todo: there should be a better solution...used to lock the "Ban on Username" input when banning from profile |
|
546
|
|
|
$context['ban']['from_user'] = true; |
|
547
|
|
|
|
|
548
|
|
|
// Would be nice if we could also ban the hostname. |
|
549
|
|
|
if ((preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $context['ban_suggestions']['main_ip']) == 1 || isValidIPv6($context['ban_suggestions']['main_ip'])) && empty($modSettings['disableHostnameLookup'])) |
|
550
|
|
|
$context['ban_suggestions']['hostname'] = host_from_ip($context['ban_suggestions']['main_ip']); |
|
551
|
|
|
|
|
552
|
|
|
$context['ban_suggestions']['other_ips'] = banLoadAdditionalIPs($context['ban_suggestions']['member']['id']); |
|
553
|
|
|
} |
|
554
|
|
|
} |
|
555
|
|
|
|
|
556
|
|
|
// We come from the mod center. |
|
557
|
|
|
elseif (isset($_GET['msg']) && !empty($_GET['msg'])) |
|
558
|
|
|
{ |
|
559
|
|
|
$request = $smcFunc['db_query']('', ' |
|
560
|
|
|
SELECT poster_name, poster_ip, poster_email |
|
561
|
|
|
FROM {db_prefix}messages |
|
562
|
|
|
WHERE id_msg = {int:message} |
|
563
|
|
|
LIMIT 1', |
|
564
|
|
|
array( |
|
565
|
|
|
'message' => (int) $_REQUEST['msg'], |
|
566
|
|
|
) |
|
567
|
|
|
); |
|
568
|
|
|
if ($smcFunc['db_num_rows']($request) > 0) |
|
569
|
|
|
{ |
|
570
|
|
|
list ($context['ban_suggestions']['member']['name'], $context['ban_suggestions']['main_ip'], $context['ban_suggestions']['email']) = $smcFunc['db_fetch_row']($request); |
|
571
|
|
|
$context['ban_suggestions']['main_ip'] = inet_dtop($context['ban_suggestions']['main_ip']); |
|
572
|
|
|
} |
|
573
|
|
|
$smcFunc['db_free_result']($request); |
|
574
|
|
|
|
|
575
|
|
|
// Can't hurt to ban base on the guest name... |
|
576
|
|
|
$context['ban']['name'] = $context['ban_suggestions']['member']['name']; |
|
577
|
|
|
$context['ban']['from_user'] = true; |
|
578
|
|
|
} |
|
579
|
|
|
} |
|
580
|
|
|
} |
|
581
|
|
|
|
|
582
|
|
|
loadJavaScriptFile('suggest.js', array(), 'smf_suggest'); |
|
583
|
|
|
$context['sub_template'] = 'ban_edit'; |
|
584
|
|
|
|
|
585
|
|
|
} |
|
586
|
|
|
|
|
587
|
|
|
/** |
|
588
|
|
|
* Retrieves all the ban items belonging to a certain ban group |
|
589
|
|
|
* |
|
590
|
|
|
* @param int $start Which item to start with (for pagination purposes) |
|
591
|
|
|
* @param int $items_per_page How many items to show on each page |
|
592
|
|
|
* @param int $sort Not used here |
|
593
|
|
|
* @param int $ban_group_id The ID of the group to get the bans for |
|
594
|
|
|
* @return array An array with information about the returned ban items |
|
595
|
|
|
*/ |
|
596
|
|
|
function list_getBanItems($start = 0, $items_per_page = 0, $sort = 0, $ban_group_id = 0) |
|
|
|
|
|
|
597
|
|
|
{ |
|
598
|
|
|
global $context, $smcFunc, $scripturl; |
|
599
|
|
|
|
|
600
|
|
|
$ban_items = array(); |
|
601
|
|
|
$request = $smcFunc['db_query']('', ' |
|
602
|
|
|
SELECT |
|
603
|
|
|
bi.id_ban, bi.hostname, bi.email_address, bi.id_member, bi.hits, |
|
604
|
|
|
bi.ip_low, bi.ip_high, |
|
605
|
|
|
bg.id_ban_group, bg.name, bg.ban_time, bg.expire_time, bg.reason, bg.notes, bg.cannot_access, bg.cannot_register, bg.cannot_login, bg.cannot_post, |
|
606
|
|
|
COALESCE(mem.id_member, 0) AS id_member, mem.member_name, mem.real_name |
|
607
|
|
|
FROM {db_prefix}ban_groups AS bg |
|
608
|
|
|
LEFT JOIN {db_prefix}ban_items AS bi ON (bi.id_ban_group = bg.id_ban_group) |
|
609
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member) |
|
610
|
|
|
WHERE bg.id_ban_group = {int:current_ban} |
|
611
|
|
|
LIMIT {int:start}, {int:items_per_page}', |
|
612
|
|
|
array( |
|
613
|
|
|
'current_ban' => $ban_group_id, |
|
614
|
|
|
'start' => $start, |
|
615
|
|
|
'items_per_page' => $items_per_page, |
|
616
|
|
|
) |
|
617
|
|
|
); |
|
618
|
|
|
if ($smcFunc['db_num_rows']($request) == 0) |
|
619
|
|
|
fatal_lang_error('ban_not_found', false); |
|
620
|
|
|
|
|
621
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
622
|
|
|
{ |
|
623
|
|
|
if (!isset($context['ban'])) |
|
624
|
|
|
{ |
|
625
|
|
|
$context['ban'] = array( |
|
626
|
|
|
'id' => $row['id_ban_group'], |
|
627
|
|
|
'name' => $row['name'], |
|
628
|
|
|
'expiration' => array( |
|
629
|
|
|
'status' => $row['expire_time'] === null ? 'never' : ($row['expire_time'] < time() ? 'expired' : 'one_day'), |
|
630
|
|
|
'days' => $row['expire_time'] > time() ? floor(($row['expire_time'] - time()) / 86400) : 0 |
|
631
|
|
|
), |
|
632
|
|
|
'reason' => $row['reason'], |
|
633
|
|
|
'notes' => $row['notes'], |
|
634
|
|
|
'cannot' => array( |
|
635
|
|
|
'access' => !empty($row['cannot_access']), |
|
636
|
|
|
'post' => !empty($row['cannot_post']), |
|
637
|
|
|
'register' => !empty($row['cannot_register']), |
|
638
|
|
|
'login' => !empty($row['cannot_login']), |
|
639
|
|
|
), |
|
640
|
|
|
'is_new' => false, |
|
641
|
|
|
'hostname' => '', |
|
642
|
|
|
'email' => '', |
|
643
|
|
|
); |
|
644
|
|
|
} |
|
645
|
|
|
|
|
646
|
|
|
if (!empty($row['id_ban'])) |
|
647
|
|
|
{ |
|
648
|
|
|
$ban_items[$row['id_ban']] = array( |
|
649
|
|
|
'id' => $row['id_ban'], |
|
650
|
|
|
'hits' => $row['hits'], |
|
651
|
|
|
); |
|
652
|
|
|
if (!empty($row['ip_high'])) |
|
653
|
|
|
{ |
|
654
|
|
|
$ban_items[$row['id_ban']]['type'] = 'ip'; |
|
655
|
|
|
$ban_items[$row['id_ban']]['ip'] = range2ip($row['ip_low'], $row['ip_high']); |
|
656
|
|
|
} |
|
657
|
|
View Code Duplication |
elseif (!empty($row['hostname'])) |
|
|
|
|
|
|
658
|
|
|
{ |
|
659
|
|
|
$ban_items[$row['id_ban']]['type'] = 'hostname'; |
|
660
|
|
|
$ban_items[$row['id_ban']]['hostname'] = str_replace('%', '*', $row['hostname']); |
|
661
|
|
|
} |
|
662
|
|
View Code Duplication |
elseif (!empty($row['email_address'])) |
|
|
|
|
|
|
663
|
|
|
{ |
|
664
|
|
|
$ban_items[$row['id_ban']]['type'] = 'email'; |
|
665
|
|
|
$ban_items[$row['id_ban']]['email'] = str_replace('%', '*', $row['email_address']); |
|
666
|
|
|
} |
|
667
|
|
|
elseif (!empty($row['id_member'])) |
|
668
|
|
|
{ |
|
669
|
|
|
$ban_items[$row['id_ban']]['type'] = 'user'; |
|
670
|
|
|
$ban_items[$row['id_ban']]['user'] = array( |
|
671
|
|
|
'id' => $row['id_member'], |
|
672
|
|
|
'name' => $row['real_name'], |
|
673
|
|
|
'href' => $scripturl . '?action=profile;u=' . $row['id_member'], |
|
674
|
|
|
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>', |
|
675
|
|
|
); |
|
676
|
|
|
} |
|
677
|
|
|
// Invalid ban (member probably doesn't exist anymore). |
|
678
|
|
|
else |
|
679
|
|
|
{ |
|
680
|
|
|
unset($ban_items[$row['id_ban']]); |
|
681
|
|
|
removeBanTriggers($row['id_ban']); |
|
682
|
|
|
} |
|
683
|
|
|
} |
|
684
|
|
|
} |
|
685
|
|
|
$smcFunc['db_free_result']($request); |
|
686
|
|
|
|
|
687
|
|
|
return $ban_items; |
|
688
|
|
|
} |
|
689
|
|
|
|
|
690
|
|
|
/** |
|
691
|
|
|
* Gets the number of ban items belonging to a certain ban group |
|
692
|
|
|
* |
|
693
|
|
|
* @return int The number of ban items |
|
694
|
|
|
*/ |
|
695
|
|
|
function list_getNumBanItems() |
|
696
|
|
|
{ |
|
697
|
|
|
global $smcFunc, $context; |
|
698
|
|
|
|
|
699
|
|
|
$ban_group_id = isset($context['ban_group_id']) ? $context['ban_group_id'] : 0; |
|
700
|
|
|
|
|
701
|
|
|
$request = $smcFunc['db_query']('', ' |
|
702
|
|
|
SELECT COUNT(bi.id_ban) |
|
703
|
|
|
FROM {db_prefix}ban_groups AS bg |
|
704
|
|
|
LEFT JOIN {db_prefix}ban_items AS bi ON (bi.id_ban_group = bg.id_ban_group) |
|
705
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member) |
|
706
|
|
|
WHERE bg.id_ban_group = {int:current_ban}', |
|
707
|
|
|
array( |
|
708
|
|
|
'current_ban' => $ban_group_id, |
|
709
|
|
|
) |
|
710
|
|
|
); |
|
711
|
|
|
list($banNumber) = $smcFunc['db_fetch_row']($request); |
|
712
|
|
|
$smcFunc['db_free_result']($request); |
|
713
|
|
|
|
|
714
|
|
|
return $banNumber; |
|
715
|
|
|
} |
|
716
|
|
|
|
|
717
|
|
|
/** |
|
718
|
|
|
* Finds additional IPs related to a certain user |
|
719
|
|
|
* |
|
720
|
|
|
* @param int $member_id The ID of the member to get additional IPs for |
|
721
|
|
|
* @return array An containing two arrays - ips_in_messages (IPs used in posts) and ips_in_errors (IPs used in error messages) |
|
722
|
|
|
*/ |
|
723
|
|
|
function banLoadAdditionalIPs($member_id) |
|
724
|
|
|
{ |
|
725
|
|
|
// Borrowing a few language strings from profile. |
|
726
|
|
|
loadLanguage('Profile'); |
|
727
|
|
|
|
|
728
|
|
|
$search_list = array(); |
|
729
|
|
|
call_integration_hook('integrate_load_addtional_ip_ban', array(&$search_list)); |
|
730
|
|
|
$search_list += array('ips_in_messages' => 'banLoadAdditionalIPsMember', 'ips_in_errors' => 'banLoadAdditionalIPsError'); |
|
731
|
|
|
|
|
732
|
|
|
$return = array(); |
|
733
|
|
|
foreach ($search_list as $key => $callable) |
|
734
|
|
|
if (is_callable($callable)) |
|
735
|
|
|
$return[$key] = call_user_func($callable, $member_id); |
|
736
|
|
|
|
|
737
|
|
|
return $return; |
|
738
|
|
|
} |
|
739
|
|
|
|
|
740
|
|
|
/** |
|
741
|
|
|
* @param int $member_id The ID of the member |
|
742
|
|
|
* @return array An array of IPs used in posts by this member |
|
743
|
|
|
*/ |
|
744
|
|
View Code Duplication |
function banLoadAdditionalIPsMember($member_id) |
|
|
|
|
|
|
745
|
|
|
{ |
|
746
|
|
|
global $smcFunc; |
|
747
|
|
|
|
|
748
|
|
|
// Find some additional IP's used by this member. |
|
749
|
|
|
$message_ips = array(); |
|
750
|
|
|
$request = $smcFunc['db_query']('', ' |
|
751
|
|
|
SELECT DISTINCT poster_ip |
|
752
|
|
|
FROM {db_prefix}messages |
|
753
|
|
|
WHERE id_member = {int:current_user} |
|
754
|
|
|
AND poster_ip IS NOT NULL |
|
755
|
|
|
ORDER BY poster_ip', |
|
756
|
|
|
array( |
|
757
|
|
|
'current_user' => $member_id, |
|
758
|
|
|
) |
|
759
|
|
|
); |
|
760
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
761
|
|
|
$message_ips[] = inet_dtop($row['poster_ip']); |
|
762
|
|
|
$smcFunc['db_free_result']($request); |
|
763
|
|
|
|
|
764
|
|
|
return $message_ips; |
|
765
|
|
|
} |
|
766
|
|
|
|
|
767
|
|
|
/** |
|
768
|
|
|
* @param int $member_id The ID of the member |
|
769
|
|
|
* @return array An array of IPs associated with error messages generated by this user |
|
770
|
|
|
*/ |
|
771
|
|
View Code Duplication |
function banLoadAdditionalIPsError($member_id) |
|
|
|
|
|
|
772
|
|
|
{ |
|
773
|
|
|
global $smcFunc; |
|
774
|
|
|
|
|
775
|
|
|
$error_ips = array(); |
|
776
|
|
|
$request = $smcFunc['db_query']('', ' |
|
777
|
|
|
SELECT DISTINCT ip |
|
778
|
|
|
FROM {db_prefix}log_errors |
|
779
|
|
|
WHERE id_member = {int:current_user} |
|
780
|
|
|
AND ip IS NOT NULL |
|
781
|
|
|
ORDER BY ip', |
|
782
|
|
|
array( |
|
783
|
|
|
'current_user' => $member_id, |
|
784
|
|
|
) |
|
785
|
|
|
); |
|
786
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
787
|
|
|
$error_ips[] = inet_dtop($row['ip']); |
|
788
|
|
|
$smcFunc['db_free_result']($request); |
|
789
|
|
|
|
|
790
|
|
|
return $error_ips; |
|
791
|
|
|
} |
|
792
|
|
|
|
|
793
|
|
|
/** |
|
794
|
|
|
* This function handles submitted forms that add, modify or remove ban triggers. |
|
795
|
|
|
*/ |
|
796
|
|
|
function banEdit2() |
|
797
|
|
|
{ |
|
798
|
|
|
global $smcFunc, $context; |
|
799
|
|
|
|
|
800
|
|
|
checkSession(); |
|
801
|
|
|
validateToken('admin-bet'); |
|
802
|
|
|
|
|
803
|
|
|
$context['ban_errors'] = array(); |
|
804
|
|
|
|
|
805
|
|
|
// Adding or editing a ban group |
|
806
|
|
|
if (isset($_POST['add_ban']) || isset($_POST['modify_ban'])) |
|
807
|
|
|
{ |
|
808
|
|
|
// Let's collect all the information we need |
|
809
|
|
|
$ban_info['id'] = isset($_REQUEST['bg']) ? (int) $_REQUEST['bg'] : 0; |
|
|
|
|
|
|
810
|
|
|
$ban_info['is_new'] = empty($ban_info['id']); |
|
811
|
|
|
$ban_info['expire_date'] = !empty($_POST['expire_date']) ? (int) $_POST['expire_date'] : 0; |
|
812
|
|
|
$ban_info['expiration'] = array( |
|
813
|
|
|
'status' => isset($_POST['expiration']) && in_array($_POST['expiration'], array('never', 'one_day', 'expired')) ? $_POST['expiration'] : 'never', |
|
814
|
|
|
'days' => $ban_info['expire_date'], |
|
815
|
|
|
); |
|
816
|
|
|
$ban_info['db_expiration'] = $ban_info['expiration']['status'] == 'never' ? 'NULL' : ($ban_info['expiration']['status'] == 'one_day' ? time() + 24 * 60 * 60 * $ban_info['expire_date'] : 0); |
|
817
|
|
|
$ban_info['full_ban'] = empty($_POST['full_ban']) ? 0 : 1; |
|
818
|
|
|
$ban_info['reason'] = !empty($_POST['reason']) ? $smcFunc['htmlspecialchars']($_POST['reason'], ENT_QUOTES) : ''; |
|
819
|
|
|
$ban_info['name'] = !empty($_POST['ban_name']) ? $smcFunc['htmlspecialchars']($_POST['ban_name'], ENT_QUOTES) : ''; |
|
820
|
|
|
$ban_info['notes'] = isset($_POST['notes']) ? $smcFunc['htmlspecialchars']($_POST['notes'], ENT_QUOTES) : ''; |
|
821
|
|
|
$ban_info['notes'] = str_replace(array("\r", "\n", ' '), array('', '<br>', ' '), $ban_info['notes']); |
|
822
|
|
|
$ban_info['cannot']['access'] = empty($ban_info['full_ban']) ? 0 : 1; |
|
823
|
|
|
$ban_info['cannot']['post'] = !empty($ban_info['full_ban']) || empty($_POST['cannot_post']) ? 0 : 1; |
|
824
|
|
|
$ban_info['cannot']['register'] = !empty($ban_info['full_ban']) || empty($_POST['cannot_register']) ? 0 : 1; |
|
825
|
|
|
$ban_info['cannot']['login'] = !empty($ban_info['full_ban']) || empty($_POST['cannot_login']) ? 0 : 1; |
|
826
|
|
|
|
|
827
|
|
|
// Adding a new ban group |
|
828
|
|
|
if (empty($_REQUEST['bg'])) |
|
829
|
|
|
$ban_group_id = insertBanGroup($ban_info); |
|
830
|
|
|
// Editing an existing ban group |
|
831
|
|
|
else |
|
832
|
|
|
$ban_group_id = updateBanGroup($ban_info); |
|
833
|
|
|
|
|
834
|
|
|
if (is_numeric($ban_group_id)) |
|
835
|
|
|
{ |
|
836
|
|
|
$ban_info['id'] = $ban_group_id; |
|
837
|
|
|
$ban_info['is_new'] = false; |
|
838
|
|
|
} |
|
839
|
|
|
|
|
840
|
|
|
$context['ban'] = $ban_info; |
|
841
|
|
|
} |
|
842
|
|
|
|
|
843
|
|
|
if (isset($_POST['ban_suggestions'])) |
|
844
|
|
|
// @TODO: is $_REQUEST['bi'] ever set? |
|
|
|
|
|
|
845
|
|
|
$saved_triggers = saveTriggers($_POST['ban_suggestions'], $ban_info['id'], isset($_REQUEST['u']) ? (int) $_REQUEST['u'] : 0, isset($_REQUEST['bi']) ? (int) $_REQUEST['bi'] : 0); |
|
|
|
|
|
|
846
|
|
|
|
|
847
|
|
|
// Something went wrong somewhere... Oh well, let's go back. |
|
848
|
|
|
if (!empty($context['ban_errors'])) |
|
849
|
|
|
{ |
|
850
|
|
|
$context['ban_suggestions'] = !empty($saved_triggers) ? $saved_triggers : array(); |
|
851
|
|
|
$context['ban']['from_user'] = true; |
|
852
|
|
|
$context['ban_suggestions'] = array_merge($context['ban_suggestions'], getMemberData((int) $_REQUEST['u'])); |
|
853
|
|
|
|
|
854
|
|
|
// Not strictly necessary, but it's nice |
|
855
|
|
|
if (!empty($context['ban_suggestions']['member']['id'])) |
|
856
|
|
|
$context['ban_suggestions']['other_ips'] = banLoadAdditionalIPs($context['ban_suggestions']['member']['id']); |
|
857
|
|
|
return BanEdit(); |
|
858
|
|
|
} |
|
859
|
|
|
$context['ban_suggestions']['saved_triggers'] = !empty($saved_triggers) ? $saved_triggers : array(); |
|
860
|
|
|
|
|
861
|
|
|
if (isset($_POST['ban_items'])) |
|
862
|
|
|
{ |
|
863
|
|
|
$ban_group_id = isset($_REQUEST['bg']) ? (int) $_REQUEST['bg'] : 0; |
|
864
|
|
|
array_map('intval', $_POST['ban_items']); |
|
865
|
|
|
|
|
866
|
|
|
removeBanTriggers($_POST['ban_items'], $ban_group_id); |
|
867
|
|
|
} |
|
868
|
|
|
|
|
869
|
|
|
// Register the last modified date. |
|
870
|
|
|
updateSettings(array('banLastUpdated' => time())); |
|
871
|
|
|
|
|
872
|
|
|
// Update the member table to represent the new ban situation. |
|
873
|
|
|
updateBanMembers(); |
|
874
|
|
|
redirectexit('action=admin;area=ban;sa=edit;bg=' . $ban_group_id); |
|
|
|
|
|
|
875
|
|
|
} |
|
876
|
|
|
|
|
877
|
|
|
/** |
|
878
|
|
|
* Saves one or more ban triggers into a ban item: according to the suggestions |
|
879
|
|
|
* checks the $_POST variable to verify if the trigger is present |
|
880
|
|
|
* |
|
881
|
|
|
* @param array $suggestions An array of suggestedtriggers (IP, email, etc.) |
|
882
|
|
|
* @param int $ban_group The ID of the group we're saving bans for |
|
883
|
|
|
* @param int $member The ID of the member associated with this ban (if applicable) |
|
884
|
|
|
* @param int $ban_id The ID of the ban (0 if this is a new ban) |
|
885
|
|
|
* |
|
886
|
|
|
* @return array|bool An array with the triggers if there were errors or false on success |
|
887
|
|
|
*/ |
|
888
|
|
|
function saveTriggers($suggestions = array(), $ban_group, $member = 0, $ban_id = 0) |
|
889
|
|
|
{ |
|
890
|
|
|
global $context; |
|
891
|
|
|
|
|
892
|
|
|
$triggers = array( |
|
893
|
|
|
'main_ip' => '', |
|
894
|
|
|
'hostname' => '', |
|
895
|
|
|
'email' => '', |
|
896
|
|
|
'member' => array( |
|
897
|
|
|
'id' => $member, |
|
898
|
|
|
) |
|
899
|
|
|
); |
|
900
|
|
|
|
|
901
|
|
|
foreach ($suggestions as $key => $value) |
|
902
|
|
|
{ |
|
903
|
|
|
if (is_array($value)) |
|
904
|
|
|
$triggers[$key] = $value; |
|
905
|
|
|
else |
|
906
|
|
|
$triggers[$value] = !empty($_POST[$value]) ? $_POST[$value] : ''; |
|
907
|
|
|
} |
|
908
|
|
|
|
|
909
|
|
|
$ban_triggers = validateTriggers($triggers); |
|
910
|
|
|
|
|
911
|
|
|
// Time to save! |
|
912
|
|
|
if (!empty($ban_triggers['ban_triggers']) && empty($context['ban_errors'])) |
|
913
|
|
|
{ |
|
914
|
|
|
if (empty($ban_id)) |
|
915
|
|
|
addTriggers($ban_group, $ban_triggers['ban_triggers'], $ban_triggers['log_info']); |
|
916
|
|
|
else |
|
917
|
|
|
updateTriggers($ban_id, $ban_group, array_shift($ban_triggers['ban_triggers']), $ban_triggers['log_info']); |
|
918
|
|
|
} |
|
919
|
|
|
if (!empty($context['ban_errors'])) |
|
920
|
|
|
return $triggers; |
|
921
|
|
|
else |
|
922
|
|
|
return false; |
|
923
|
|
|
} |
|
924
|
|
|
|
|
925
|
|
|
/** |
|
926
|
|
|
* This function removes a bunch of triggers based on ids |
|
927
|
|
|
* Doesn't clean the inputs |
|
928
|
|
|
* |
|
929
|
|
|
* @param array $items_ids The items to remove |
|
930
|
|
|
* @param bool|int $group_id The ID of the group these triggers are associated with or false if deleting them from all groups |
|
931
|
|
|
* @return bool Always returns true |
|
932
|
|
|
*/ |
|
933
|
|
|
function removeBanTriggers($items_ids = array(), $group_id = false) |
|
934
|
|
|
{ |
|
935
|
|
|
global $smcFunc, $scripturl; |
|
936
|
|
|
|
|
937
|
|
|
if ($group_id !== false) |
|
938
|
|
|
$group_id = (int) $group_id; |
|
939
|
|
|
|
|
940
|
|
|
if (empty($group_id) && empty($items_ids)) |
|
941
|
|
|
return false; |
|
942
|
|
|
|
|
943
|
|
|
if (!is_array($items_ids)) |
|
944
|
|
|
$items_ids = array($items_ids); |
|
945
|
|
|
|
|
946
|
|
|
$log_info = array(); |
|
947
|
|
|
$ban_items = array(); |
|
948
|
|
|
|
|
949
|
|
|
// First order of business: Load up the info so we can log this... |
|
950
|
|
|
$request = $smcFunc['db_query']('', ' |
|
951
|
|
|
SELECT |
|
952
|
|
|
bi.id_ban, bi.hostname, bi.email_address, bi.id_member, bi.hits, |
|
953
|
|
|
bi.ip_low, bi.ip_high, |
|
954
|
|
|
COALESCE(mem.id_member, 0) AS id_member, mem.member_name, mem.real_name |
|
955
|
|
|
FROM {db_prefix}ban_items AS bi |
|
956
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member) |
|
957
|
|
|
WHERE bi.id_ban IN ({array_int:ban_list})', |
|
958
|
|
|
array( |
|
959
|
|
|
'ban_list' => $items_ids, |
|
960
|
|
|
) |
|
961
|
|
|
); |
|
962
|
|
|
|
|
963
|
|
|
// Get all the info for the log |
|
964
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
965
|
|
|
{ |
|
966
|
|
|
if (!empty($row['id_ban'])) |
|
967
|
|
|
{ |
|
968
|
|
|
$ban_items[$row['id_ban']] = array( |
|
969
|
|
|
'id' => $row['id_ban'], |
|
970
|
|
|
); |
|
971
|
|
|
if (!empty($row['ip_high'])) |
|
972
|
|
|
{ |
|
973
|
|
|
$ban_items[$row['id_ban']]['type'] = 'ip'; |
|
974
|
|
|
$ban_items[$row['id_ban']]['ip'] = range2ip($row['ip_low'], $row['ip_high']); |
|
975
|
|
|
|
|
976
|
|
|
$is_range = (strpos($ban_items[$row['id_ban']]['ip'], '-') !== false || strpos($ban_items[$row['id_ban']]['ip'], '*') !== false); |
|
977
|
|
|
|
|
978
|
|
|
$log_info[] = array( |
|
979
|
|
|
'bantype' => ($is_range ? 'ip_range' : 'main_ip'), |
|
980
|
|
|
'value' => $ban_items[$row['id_ban']]['ip'], |
|
981
|
|
|
); |
|
982
|
|
|
} |
|
983
|
|
View Code Duplication |
elseif (!empty($row['hostname'])) |
|
|
|
|
|
|
984
|
|
|
{ |
|
985
|
|
|
$ban_items[$row['id_ban']]['type'] = 'hostname'; |
|
986
|
|
|
$ban_items[$row['id_ban']]['hostname'] = str_replace('%', '*', $row['hostname']); |
|
987
|
|
|
$log_info[] = array( |
|
988
|
|
|
'bantype' => 'hostname', |
|
989
|
|
|
'value' => $row['hostname'], |
|
990
|
|
|
); |
|
991
|
|
|
} |
|
992
|
|
View Code Duplication |
elseif (!empty($row['email_address'])) |
|
|
|
|
|
|
993
|
|
|
{ |
|
994
|
|
|
$ban_items[$row['id_ban']]['type'] = 'email'; |
|
995
|
|
|
$ban_items[$row['id_ban']]['email'] = str_replace('%', '*', $row['email_address']); |
|
996
|
|
|
$log_info[] = array( |
|
997
|
|
|
'bantype' => 'email', |
|
998
|
|
|
'value' => $ban_items[$row['id_ban']]['email'], |
|
999
|
|
|
); |
|
1000
|
|
|
} |
|
1001
|
|
|
elseif (!empty($row['id_member'])) |
|
1002
|
|
|
{ |
|
1003
|
|
|
$ban_items[$row['id_ban']]['type'] = 'user'; |
|
1004
|
|
|
$ban_items[$row['id_ban']]['user'] = array( |
|
1005
|
|
|
'id' => $row['id_member'], |
|
1006
|
|
|
'name' => $row['real_name'], |
|
1007
|
|
|
'href' => $scripturl . '?action=profile;u=' . $row['id_member'], |
|
1008
|
|
|
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>', |
|
1009
|
|
|
); |
|
1010
|
|
|
$log_info[] = array( |
|
1011
|
|
|
'bantype' => 'user', |
|
1012
|
|
|
'value' => $row['id_member'], |
|
1013
|
|
|
); |
|
1014
|
|
|
} |
|
1015
|
|
|
} |
|
1016
|
|
|
} |
|
1017
|
|
|
|
|
1018
|
|
|
// Log this! |
|
1019
|
|
|
logTriggersUpdates($log_info, false, true); |
|
1020
|
|
|
|
|
1021
|
|
|
$smcFunc['db_free_result']($request); |
|
1022
|
|
|
|
|
1023
|
|
|
if ($group_id !== false) |
|
1024
|
|
|
{ |
|
1025
|
|
|
$smcFunc['db_query']('', ' |
|
1026
|
|
|
DELETE FROM {db_prefix}ban_items |
|
1027
|
|
|
WHERE id_ban IN ({array_int:ban_list}) |
|
1028
|
|
|
AND id_ban_group = {int:ban_group}', |
|
1029
|
|
|
array( |
|
1030
|
|
|
'ban_list' => $items_ids, |
|
1031
|
|
|
'ban_group' => $group_id, |
|
1032
|
|
|
) |
|
1033
|
|
|
); |
|
1034
|
|
|
} |
|
1035
|
|
|
elseif (!empty($items_ids)) |
|
1036
|
|
|
{ |
|
1037
|
|
|
$smcFunc['db_query']('', ' |
|
1038
|
|
|
DELETE FROM {db_prefix}ban_items |
|
1039
|
|
|
WHERE id_ban IN ({array_int:ban_list})', |
|
1040
|
|
|
array( |
|
1041
|
|
|
'ban_list' => $items_ids, |
|
1042
|
|
|
) |
|
1043
|
|
|
); |
|
1044
|
|
|
} |
|
1045
|
|
|
|
|
1046
|
|
|
return true; |
|
1047
|
|
|
} |
|
1048
|
|
|
|
|
1049
|
|
|
/** |
|
1050
|
|
|
* This function removes a bunch of ban groups based on ids |
|
1051
|
|
|
* Doesn't clean the inputs |
|
1052
|
|
|
* |
|
1053
|
|
|
* @param int[] $group_ids The IDs of the groups to remove |
|
1054
|
|
|
* @return bool Returns ture if successful or false if $group_ids is empty |
|
1055
|
|
|
*/ |
|
1056
|
|
|
function removeBanGroups($group_ids) |
|
1057
|
|
|
{ |
|
1058
|
|
|
global $smcFunc; |
|
1059
|
|
|
|
|
1060
|
|
|
if (!is_array($group_ids)) |
|
1061
|
|
|
$group_ids = array($group_ids); |
|
1062
|
|
|
|
|
1063
|
|
|
$group_ids = array_unique($group_ids); |
|
1064
|
|
|
|
|
1065
|
|
|
if (empty($group_ids)) |
|
1066
|
|
|
return false; |
|
1067
|
|
|
|
|
1068
|
|
|
$smcFunc['db_query']('', ' |
|
1069
|
|
|
DELETE FROM {db_prefix}ban_groups |
|
1070
|
|
|
WHERE id_ban_group IN ({array_int:ban_list})', |
|
1071
|
|
|
array( |
|
1072
|
|
|
'ban_list' => $group_ids, |
|
1073
|
|
|
) |
|
1074
|
|
|
); |
|
1075
|
|
|
|
|
1076
|
|
|
return true; |
|
1077
|
|
|
} |
|
1078
|
|
|
|
|
1079
|
|
|
/** |
|
1080
|
|
|
* Removes logs - by default truncate the table |
|
1081
|
|
|
* Doesn't clean the inputs |
|
1082
|
|
|
* |
|
1083
|
|
|
* @param array $ids Empty array to clear the ban log or the IDs of the log entries to remove |
|
1084
|
|
|
* @return bool Returns true if successful or false if $ids is invalid |
|
1085
|
|
|
*/ |
|
1086
|
|
|
function removeBanLogs($ids = array()) |
|
1087
|
|
|
{ |
|
1088
|
|
|
global $smcFunc; |
|
1089
|
|
|
|
|
1090
|
|
|
if (empty($ids)) |
|
1091
|
|
|
$smcFunc['db_query']('truncate_table', ' |
|
1092
|
|
|
TRUNCATE {db_prefix}log_banned', |
|
1093
|
|
|
array( |
|
1094
|
|
|
) |
|
1095
|
|
|
); |
|
1096
|
|
|
else |
|
1097
|
|
|
{ |
|
1098
|
|
|
if (!is_array($ids)) |
|
1099
|
|
|
$ids = array($ids); |
|
1100
|
|
|
|
|
1101
|
|
|
$ids = array_unique($ids); |
|
1102
|
|
|
|
|
1103
|
|
|
if (empty($ids)) |
|
1104
|
|
|
return false; |
|
1105
|
|
|
|
|
1106
|
|
|
$smcFunc['db_query']('', ' |
|
1107
|
|
|
DELETE FROM {db_prefix}log_banned |
|
1108
|
|
|
WHERE id_ban_log IN ({array_int:ban_list})', |
|
1109
|
|
|
array( |
|
1110
|
|
|
'ban_list' => $ids, |
|
1111
|
|
|
) |
|
1112
|
|
|
); |
|
1113
|
|
|
} |
|
1114
|
|
|
|
|
1115
|
|
|
return true; |
|
1116
|
|
|
} |
|
1117
|
|
|
|
|
1118
|
|
|
/** |
|
1119
|
|
|
* This function validates the ban triggers |
|
1120
|
|
|
* |
|
1121
|
|
|
* Errors in $context['ban_errors'] |
|
1122
|
|
|
* |
|
1123
|
|
|
* @param array $triggers The triggers to validate |
|
1124
|
|
|
* @return array An array of riggers and log info ready to be used |
|
1125
|
|
|
*/ |
|
1126
|
|
|
function validateTriggers(&$triggers) |
|
1127
|
|
|
{ |
|
1128
|
|
|
global $context, $smcFunc; |
|
1129
|
|
|
|
|
1130
|
|
|
if (empty($triggers)) |
|
1131
|
|
|
$context['ban_erros'][] = 'ban_empty_triggers'; |
|
1132
|
|
|
|
|
1133
|
|
|
$ban_triggers = array(); |
|
1134
|
|
|
$log_info = array(); |
|
1135
|
|
|
|
|
1136
|
|
|
foreach ($triggers as $key => $value) |
|
1137
|
|
|
{ |
|
1138
|
|
|
if (!empty($value)) |
|
1139
|
|
|
{ |
|
1140
|
|
|
if ($key == 'member') |
|
1141
|
|
|
continue; |
|
1142
|
|
|
|
|
1143
|
|
|
if ($key == 'main_ip') |
|
1144
|
|
|
{ |
|
1145
|
|
|
$value = trim($value); |
|
1146
|
|
|
$ip_parts = ip2range($value); |
|
1147
|
|
|
if (!checkExistingTriggerIP($ip_parts, $value)) |
|
1148
|
|
|
$context['ban_erros'][] = 'invalid_ip'; |
|
1149
|
|
|
else |
|
1150
|
|
|
{ |
|
1151
|
|
|
$ban_triggers['main_ip'] = array( |
|
1152
|
|
|
'ip_low' => $ip_parts['low'], |
|
1153
|
|
|
'ip_high' => $ip_parts['high'] |
|
1154
|
|
|
); |
|
1155
|
|
|
} |
|
1156
|
|
|
} |
|
1157
|
|
|
elseif ($key == 'hostname') |
|
1158
|
|
|
{ |
|
1159
|
|
|
if (preg_match('/[^\w.\-*]/', $value) == 1) |
|
1160
|
|
|
$context['ban_erros'][] = 'invalid_hostname'; |
|
1161
|
|
|
else |
|
1162
|
|
|
{ |
|
1163
|
|
|
// Replace the * wildcard by a MySQL wildcard %. |
|
1164
|
|
|
$value = substr(str_replace('*', '%', $value), 0, 255); |
|
1165
|
|
|
|
|
1166
|
|
|
$ban_triggers['hostname']['hostname'] = $value; |
|
1167
|
|
|
} |
|
1168
|
|
|
} |
|
1169
|
|
|
elseif ($key == 'email') |
|
1170
|
|
|
{ |
|
1171
|
|
|
if (preg_match('/[^\w.\-\+*@]/', $value) == 1) |
|
1172
|
|
|
$context['ban_erros'][] = 'invalid_email'; |
|
1173
|
|
|
|
|
1174
|
|
|
// Check the user is not banning an admin. |
|
1175
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1176
|
|
|
SELECT id_member |
|
1177
|
|
|
FROM {db_prefix}members |
|
1178
|
|
|
WHERE (id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0) |
|
1179
|
|
|
AND email_address LIKE {string:email} |
|
1180
|
|
|
LIMIT 1', |
|
1181
|
|
|
array( |
|
1182
|
|
|
'admin_group' => 1, |
|
1183
|
|
|
'email' => $value, |
|
1184
|
|
|
) |
|
1185
|
|
|
); |
|
1186
|
|
|
if ($smcFunc['db_num_rows']($request) != 0) |
|
1187
|
|
|
$context['ban_erros'][] = 'no_ban_admin'; |
|
1188
|
|
|
$smcFunc['db_free_result']($request); |
|
1189
|
|
|
|
|
1190
|
|
|
$value = substr(strtolower(str_replace('*', '%', $value)), 0, 255); |
|
1191
|
|
|
|
|
1192
|
|
|
$ban_triggers['email']['email_address'] = $value; |
|
1193
|
|
|
} |
|
1194
|
|
|
elseif ($key == 'user') |
|
1195
|
|
|
{ |
|
1196
|
|
|
$user = preg_replace('~&#(\d{4,5}|[2-9]\d{2,4}|1[2-9]\d);~', '&#$1;', $smcFunc['htmlspecialchars']($value, ENT_QUOTES)); |
|
1197
|
|
|
|
|
1198
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1199
|
|
|
SELECT id_member, (id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0) AS isAdmin |
|
1200
|
|
|
FROM {db_prefix}members |
|
1201
|
|
|
WHERE member_name = {string:username} OR real_name = {string:username} |
|
1202
|
|
|
LIMIT 1', |
|
1203
|
|
|
array( |
|
1204
|
|
|
'admin_group' => 1, |
|
1205
|
|
|
'username' => $user, |
|
1206
|
|
|
) |
|
1207
|
|
|
); |
|
1208
|
|
|
if ($smcFunc['db_num_rows']($request) == 0) |
|
1209
|
|
|
$context['ban_erros'][] = 'invalid_username'; |
|
1210
|
|
|
list ($value, $isAdmin) = $smcFunc['db_fetch_row']($request); |
|
1211
|
|
|
$smcFunc['db_free_result']($request); |
|
1212
|
|
|
|
|
1213
|
|
|
if ($isAdmin && strtolower($isAdmin) != 'f') |
|
1214
|
|
|
{ |
|
1215
|
|
|
unset($value); |
|
1216
|
|
|
$context['ban_erros'][] = 'no_ban_admin'; |
|
1217
|
|
|
} |
|
1218
|
|
|
else |
|
1219
|
|
|
$ban_triggers['user']['id_member'] = $value; |
|
1220
|
|
|
} |
|
1221
|
|
|
elseif (in_array($key, array('ips_in_messages', 'ips_in_errors'))) |
|
1222
|
|
|
{ |
|
1223
|
|
|
// Special case, those two are arrays themselves |
|
1224
|
|
|
$values = array_unique($value); |
|
1225
|
|
|
// Don't add the main IP again. |
|
1226
|
|
|
if (isset($triggers['main_ip'])) |
|
1227
|
|
|
$values = array_diff($values, array($triggers['main_ip'])); |
|
1228
|
|
|
unset($value); |
|
1229
|
|
|
foreach ($values as $val) |
|
1230
|
|
|
{ |
|
1231
|
|
|
$val = trim($val); |
|
1232
|
|
|
$ip_parts = ip2range($val); |
|
1233
|
|
|
if (!checkExistingTriggerIP($ip_parts, $val)) |
|
1234
|
|
|
$context['ban_erros'][] = 'invalid_ip'; |
|
1235
|
|
|
else |
|
1236
|
|
|
{ |
|
1237
|
|
|
$ban_triggers[$key][] = array( |
|
1238
|
|
|
'ip_low' => $ip_parts['low'], |
|
1239
|
|
|
'ip_high' => $ip_parts['high'], |
|
1240
|
|
|
); |
|
1241
|
|
|
|
|
1242
|
|
|
$log_info[] = array( |
|
1243
|
|
|
'value' => $val, |
|
1244
|
|
|
'bantype' => 'ip_range', |
|
1245
|
|
|
); |
|
1246
|
|
|
} |
|
1247
|
|
|
} |
|
1248
|
|
|
} |
|
1249
|
|
|
else |
|
1250
|
|
|
$context['ban_erros'][] = 'no_bantype_selected'; |
|
1251
|
|
|
|
|
1252
|
|
|
if (isset($value) && !is_array($value)) |
|
1253
|
|
|
$log_info[] = array( |
|
1254
|
|
|
'value' => $value, |
|
1255
|
|
|
'bantype' => $key, |
|
1256
|
|
|
); |
|
1257
|
|
|
} |
|
1258
|
|
|
} |
|
1259
|
|
|
return array('ban_triggers' => $ban_triggers, 'log_info' => $log_info); |
|
1260
|
|
|
} |
|
1261
|
|
|
|
|
1262
|
|
|
/** |
|
1263
|
|
|
* This function actually inserts the ban triggers into the database |
|
1264
|
|
|
* |
|
1265
|
|
|
* Errors in $context['ban_errors'] |
|
1266
|
|
|
* |
|
1267
|
|
|
* @param int $group_id The ID of the group to add the triggers to (0 to create a new one) |
|
1268
|
|
|
* @param array $triggers The triggers to add |
|
1269
|
|
|
* @param array $logs The log data |
|
1270
|
|
|
* @return bool Whether or not the action was successful |
|
1271
|
|
|
*/ |
|
1272
|
|
|
function addTriggers($group_id = 0, $triggers = array(), $logs = array()) |
|
1273
|
|
|
{ |
|
1274
|
|
|
global $smcFunc, $context; |
|
1275
|
|
|
|
|
1276
|
|
|
if (empty($group_id)) |
|
1277
|
|
|
$context['ban_errors'][] = 'ban_id_empty'; |
|
1278
|
|
|
|
|
1279
|
|
|
// Preset all values that are required. |
|
1280
|
|
|
$values = array( |
|
1281
|
|
|
'id_ban_group' => $group_id, |
|
1282
|
|
|
'hostname' => '', |
|
1283
|
|
|
'email_address' => '', |
|
1284
|
|
|
'id_member' => 0, |
|
1285
|
|
|
'ip_low' => 'null', |
|
1286
|
|
|
'ip_high' => 'null', |
|
1287
|
|
|
); |
|
1288
|
|
|
|
|
1289
|
|
|
$insertKeys = array( |
|
1290
|
|
|
'id_ban_group' => 'int', |
|
1291
|
|
|
'hostname' => 'string', |
|
1292
|
|
|
'email_address' => 'string', |
|
1293
|
|
|
'id_member' => 'int', |
|
1294
|
|
|
'ip_low' => 'inet', |
|
1295
|
|
|
'ip_high' => 'inet', |
|
1296
|
|
|
); |
|
1297
|
|
|
|
|
1298
|
|
|
$insertTriggers = array(); |
|
1299
|
|
|
foreach ($triggers as $key => $trigger) |
|
1300
|
|
|
{ |
|
1301
|
|
|
// Exceptions, exceptions, exceptions...always exceptions... :P |
|
1302
|
|
|
if (in_array($key, array('ips_in_messages', 'ips_in_errors'))) |
|
1303
|
|
|
foreach ($trigger as $real_trigger) |
|
1304
|
|
|
$insertTriggers[] = array_merge($values, $real_trigger); |
|
1305
|
|
|
else |
|
1306
|
|
|
$insertTriggers[] = array_merge($values, $trigger); |
|
1307
|
|
|
} |
|
1308
|
|
|
|
|
1309
|
|
|
if (empty($insertTriggers)) |
|
1310
|
|
|
$context['ban_errors'][] = 'ban_no_triggers'; |
|
1311
|
|
|
|
|
1312
|
|
|
if (!empty($context['ban_errors'])) |
|
1313
|
|
|
return false; |
|
1314
|
|
|
|
|
1315
|
|
|
$smcFunc['db_insert']('', |
|
1316
|
|
|
'{db_prefix}ban_items', |
|
1317
|
|
|
$insertKeys, |
|
1318
|
|
|
$insertTriggers, |
|
1319
|
|
|
array('id_ban') |
|
1320
|
|
|
); |
|
1321
|
|
|
|
|
1322
|
|
|
logTriggersUpdates($logs, true); |
|
1323
|
|
|
|
|
1324
|
|
|
return true; |
|
1325
|
|
|
} |
|
1326
|
|
|
|
|
1327
|
|
|
/** |
|
1328
|
|
|
* This function updates an existing ban trigger into the database |
|
1329
|
|
|
* |
|
1330
|
|
|
* Errors in $context['ban_errors'] |
|
1331
|
|
|
* |
|
1332
|
|
|
* @param int $ban_item The ID of the ban item |
|
1333
|
|
|
* @param int $group_id The ID of the ban group |
|
1334
|
|
|
* @param array $trigger An array of triggers |
|
1335
|
|
|
* @param array $logs An array of log info |
|
1336
|
|
|
*/ |
|
1337
|
|
|
function updateTriggers($ban_item = 0, $group_id = 0, $trigger = array(), $logs = array()) |
|
1338
|
|
|
{ |
|
1339
|
|
|
global $smcFunc, $context; |
|
1340
|
|
|
|
|
1341
|
|
|
if (empty($ban_item)) |
|
1342
|
|
|
$context['ban_errors'][] = 'ban_ban_item_empty'; |
|
1343
|
|
|
if (empty($group_id)) |
|
1344
|
|
|
$context['ban_errors'][] = 'ban_id_empty'; |
|
1345
|
|
|
if (empty($trigger)) |
|
1346
|
|
|
$context['ban_errors'][] = 'ban_no_triggers'; |
|
1347
|
|
|
|
|
1348
|
|
|
if (!empty($context['ban_errors'])) |
|
1349
|
|
|
return; |
|
1350
|
|
|
|
|
1351
|
|
|
// Preset all values that are required. |
|
1352
|
|
|
$values = array( |
|
1353
|
|
|
'id_ban_group' => $group_id, |
|
1354
|
|
|
'hostname' => '', |
|
1355
|
|
|
'email_address' => '', |
|
1356
|
|
|
'id_member' => 0, |
|
1357
|
|
|
'ip_low' => 'null', |
|
1358
|
|
|
'ip_high' => 'null', |
|
1359
|
|
|
); |
|
1360
|
|
|
|
|
1361
|
|
|
$trigger = array_merge($values, $trigger); |
|
1362
|
|
|
|
|
1363
|
|
|
$smcFunc['db_query']('', ' |
|
1364
|
|
|
UPDATE {db_prefix}ban_items |
|
1365
|
|
|
SET |
|
1366
|
|
|
hostname = {string:hostname}, email_address = {string:email_address}, id_member = {int:id_member}, |
|
1367
|
|
|
ip_low = {inet:ip_low}, ip_high = {inet:ip_high} |
|
1368
|
|
|
WHERE id_ban = {int:ban_item} |
|
1369
|
|
|
AND id_ban_group = {int:id_ban_group}', |
|
1370
|
|
|
array_merge($trigger, array( |
|
1371
|
|
|
'id_ban_group' => $group_id, |
|
1372
|
|
|
'ban_item' => $ban_item, |
|
1373
|
|
|
)) |
|
1374
|
|
|
); |
|
1375
|
|
|
|
|
1376
|
|
|
logTriggersUpdates($logs, false); |
|
1377
|
|
|
} |
|
1378
|
|
|
|
|
1379
|
|
|
/** |
|
1380
|
|
|
* A small function to unify logging of triggers (updates and new) |
|
1381
|
|
|
* |
|
1382
|
|
|
* @param array $logs an array of logs, each log contains the following keys: |
|
1383
|
|
|
* - bantype: a known type of ban (ip_range, hostname, email, user, main_ip) |
|
1384
|
|
|
* - value: the value of the bantype (e.g. the IP or the email address banned) |
|
1385
|
|
|
* @param bool $new Whether the trigger is new or an update of an existing one |
|
1386
|
|
|
* @param bool $removal Whether the trigger is being deleted |
|
1387
|
|
|
*/ |
|
1388
|
|
|
function logTriggersUpdates($logs, $new = true, $removal = false) |
|
1389
|
|
|
{ |
|
1390
|
|
|
if (empty($logs)) |
|
1391
|
|
|
return; |
|
1392
|
|
|
|
|
1393
|
|
|
$log_name_map = array( |
|
1394
|
|
|
'main_ip' => 'ip_range', |
|
1395
|
|
|
'hostname' => 'hostname', |
|
1396
|
|
|
'email' => 'email', |
|
1397
|
|
|
'user' => 'member', |
|
1398
|
|
|
'ip_range' => 'ip_range', |
|
1399
|
|
|
); |
|
1400
|
|
|
|
|
1401
|
|
|
// Log the addion of the ban entries into the moderation log. |
|
1402
|
|
|
foreach ($logs as $log) |
|
1403
|
|
|
logAction('ban' . ($removal == true ? 'remove' : ''), array( |
|
|
|
|
|
|
1404
|
|
|
$log_name_map[$log['bantype']] => $log['value'], |
|
1405
|
|
|
'new' => empty($new) ? 0 : 1, |
|
1406
|
|
|
'remove' => empty($removal) ? 0 : 1, |
|
1407
|
|
|
'type' => $log['bantype'], |
|
1408
|
|
|
)); |
|
1409
|
|
|
} |
|
1410
|
|
|
|
|
1411
|
|
|
/** |
|
1412
|
|
|
* Updates an existing ban group |
|
1413
|
|
|
* |
|
1414
|
|
|
* Errors in $context['ban_errors'] |
|
1415
|
|
|
* |
|
1416
|
|
|
* @param array $ban_info An array of info about the ban group. Should have name and may also have an id. |
|
1417
|
|
|
* @return int The ban group's ID |
|
1418
|
|
|
*/ |
|
1419
|
|
|
function updateBanGroup($ban_info = array()) |
|
1420
|
|
|
{ |
|
1421
|
|
|
global $smcFunc, $context; |
|
1422
|
|
|
|
|
1423
|
|
|
if (empty($ban_info['name'])) |
|
1424
|
|
|
$context['ban_errors'][] = 'ban_name_empty'; |
|
1425
|
|
|
if (empty($ban_info['id'])) |
|
1426
|
|
|
$context['ban_errors'][] = 'ban_id_empty'; |
|
1427
|
|
View Code Duplication |
if (empty($ban_info['cannot']['access']) && empty($ban_info['cannot']['register']) && empty($ban_info['cannot']['post']) && empty($ban_info['cannot']['login'])) |
|
|
|
|
|
|
1428
|
|
|
$context['ban_errors'][] = 'ban_unknown_restriction_type'; |
|
1429
|
|
|
|
|
1430
|
|
|
if (!empty($ban_info['id'])) |
|
1431
|
|
|
{ |
|
1432
|
|
|
// Verify the ban group exists. |
|
1433
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1434
|
|
|
SELECT id_ban_group |
|
1435
|
|
|
FROM {db_prefix}ban_groups |
|
1436
|
|
|
WHERE id_ban_group = {int:ban_group} |
|
1437
|
|
|
LIMIT 1', |
|
1438
|
|
|
array( |
|
1439
|
|
|
'ban_group' => $ban_info['id'] |
|
1440
|
|
|
) |
|
1441
|
|
|
); |
|
1442
|
|
|
|
|
1443
|
|
|
if ($smcFunc['db_num_rows']($request) == 0) |
|
1444
|
|
|
$context['ban_errors'][] = 'ban_not_found'; |
|
1445
|
|
|
$smcFunc['db_free_result']($request); |
|
1446
|
|
|
} |
|
1447
|
|
|
|
|
1448
|
|
|
if (!empty($ban_info['name'])) |
|
1449
|
|
|
{ |
|
1450
|
|
|
// Make sure the name does not already exist (Of course, if it exists in the ban group we are editing, proceed.) |
|
1451
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1452
|
|
|
SELECT id_ban_group |
|
1453
|
|
|
FROM {db_prefix}ban_groups |
|
1454
|
|
|
WHERE name = {string:new_ban_name} |
|
1455
|
|
|
AND id_ban_group != {int:ban_group} |
|
1456
|
|
|
LIMIT 1', |
|
1457
|
|
|
array( |
|
1458
|
|
|
'ban_group' => empty($ban_info['id']) ? 0 : $ban_info['id'], |
|
1459
|
|
|
'new_ban_name' => $ban_info['name'], |
|
1460
|
|
|
) |
|
1461
|
|
|
); |
|
1462
|
|
|
if ($smcFunc['db_num_rows']($request) != 0) |
|
1463
|
|
|
$context['ban_errors'][] = 'ban_name_exists'; |
|
1464
|
|
|
$smcFunc['db_free_result']($request); |
|
1465
|
|
|
} |
|
1466
|
|
|
|
|
1467
|
|
|
if (!empty($context['ban_errors'])) |
|
1468
|
|
|
return $ban_info['id']; |
|
1469
|
|
|
|
|
1470
|
|
|
$smcFunc['db_query']('', ' |
|
1471
|
|
|
UPDATE {db_prefix}ban_groups |
|
1472
|
|
|
SET |
|
1473
|
|
|
name = {string:ban_name}, |
|
1474
|
|
|
reason = {string:reason}, |
|
1475
|
|
|
notes = {string:notes}, |
|
1476
|
|
|
expire_time = {raw:expiration}, |
|
1477
|
|
|
cannot_access = {int:cannot_access}, |
|
1478
|
|
|
cannot_post = {int:cannot_post}, |
|
1479
|
|
|
cannot_register = {int:cannot_register}, |
|
1480
|
|
|
cannot_login = {int:cannot_login} |
|
1481
|
|
|
WHERE id_ban_group = {int:id_ban_group}', |
|
1482
|
|
|
array( |
|
1483
|
|
|
'expiration' => $ban_info['db_expiration'], |
|
1484
|
|
|
'cannot_access' => $ban_info['cannot']['access'], |
|
1485
|
|
|
'cannot_post' => $ban_info['cannot']['post'], |
|
1486
|
|
|
'cannot_register' => $ban_info['cannot']['register'], |
|
1487
|
|
|
'cannot_login' => $ban_info['cannot']['login'], |
|
1488
|
|
|
'id_ban_group' => $ban_info['id'], |
|
1489
|
|
|
'ban_name' => $ban_info['name'], |
|
1490
|
|
|
'reason' => $ban_info['reason'], |
|
1491
|
|
|
'notes' => $ban_info['notes'], |
|
1492
|
|
|
) |
|
1493
|
|
|
); |
|
1494
|
|
|
|
|
1495
|
|
|
return $ban_info['id']; |
|
1496
|
|
|
} |
|
1497
|
|
|
|
|
1498
|
|
|
/** |
|
1499
|
|
|
* Creates a new ban group |
|
1500
|
|
|
* If the group is successfully created the ID is returned |
|
1501
|
|
|
* On error the error code is returned or false |
|
1502
|
|
|
* |
|
1503
|
|
|
* Errors in $context['ban_errors'] |
|
1504
|
|
|
* |
|
1505
|
|
|
* @param array $ban_info An array containing 'name', which is the name of the ban group |
|
1506
|
|
|
* @return int The ban group's ID |
|
1507
|
|
|
*/ |
|
1508
|
|
|
function insertBanGroup($ban_info = array()) |
|
1509
|
|
|
{ |
|
1510
|
|
|
global $smcFunc, $context; |
|
1511
|
|
|
|
|
1512
|
|
|
if (empty($ban_info['name'])) |
|
1513
|
|
|
$context['ban_errors'][] = 'ban_name_empty'; |
|
1514
|
|
View Code Duplication |
if (empty($ban_info['cannot']['access']) && empty($ban_info['cannot']['register']) && empty($ban_info['cannot']['post']) && empty($ban_info['cannot']['login'])) |
|
|
|
|
|
|
1515
|
|
|
$context['ban_errors'][] = 'ban_unknown_restriction_type'; |
|
1516
|
|
|
|
|
1517
|
|
|
if (!empty($ban_info['name'])) |
|
1518
|
|
|
{ |
|
1519
|
|
|
// Check whether a ban with this name already exists. |
|
1520
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1521
|
|
|
SELECT id_ban_group |
|
1522
|
|
|
FROM {db_prefix}ban_groups |
|
1523
|
|
|
WHERE name = {string:new_ban_name}' . ' |
|
1524
|
|
|
LIMIT 1', |
|
1525
|
|
|
array( |
|
1526
|
|
|
'new_ban_name' => $ban_info['name'], |
|
1527
|
|
|
) |
|
1528
|
|
|
); |
|
1529
|
|
|
|
|
1530
|
|
|
if ($smcFunc['db_num_rows']($request) == 1) |
|
1531
|
|
|
$context['ban_errors'][] = 'ban_name_exists'; |
|
1532
|
|
|
$smcFunc['db_free_result']($request); |
|
1533
|
|
|
} |
|
1534
|
|
|
|
|
1535
|
|
|
if (!empty($context['ban_errors'])) |
|
1536
|
|
|
return; |
|
1537
|
|
|
|
|
1538
|
|
|
// Yes yes, we're ready to add now. |
|
1539
|
|
|
$ban_info['id'] = $smcFunc['db_insert']('', |
|
1540
|
|
|
'{db_prefix}ban_groups', |
|
1541
|
|
|
array( |
|
1542
|
|
|
'name' => 'string-20', 'ban_time' => 'int', 'expire_time' => 'raw', 'cannot_access' => 'int', 'cannot_register' => 'int', |
|
1543
|
|
|
'cannot_post' => 'int', 'cannot_login' => 'int', 'reason' => 'string-255', 'notes' => 'string-65534', |
|
1544
|
|
|
), |
|
1545
|
|
|
array( |
|
1546
|
|
|
$ban_info['name'], time(), $ban_info['db_expiration'], $ban_info['cannot']['access'], $ban_info['cannot']['register'], |
|
1547
|
|
|
$ban_info['cannot']['post'], $ban_info['cannot']['login'], $ban_info['reason'], $ban_info['notes'], |
|
1548
|
|
|
), |
|
1549
|
|
|
array('id_ban_group'), |
|
1550
|
|
|
1 |
|
1551
|
|
|
); |
|
1552
|
|
|
|
|
1553
|
|
|
if (empty($ban_info['id'])) |
|
1554
|
|
|
$context['ban_errors'][] = 'impossible_insert_new_bangroup'; |
|
1555
|
|
|
|
|
1556
|
|
|
return $ban_info['id']; |
|
1557
|
|
|
} |
|
1558
|
|
|
|
|
1559
|
|
|
/** |
|
1560
|
|
|
* This function handles the ins and outs of the screen for adding new ban |
|
1561
|
|
|
* triggers or modifying existing ones. |
|
1562
|
|
|
* Adding new ban triggers: |
|
1563
|
|
|
* - is accessed by ?action=admin;area=ban;sa=edittrigger;bg=x |
|
1564
|
|
|
* - uses the ban_edit_trigger sub template of ManageBans. |
|
1565
|
|
|
* Editing existing ban triggers: |
|
1566
|
|
|
* - is accessed by ?action=admin;area=ban;sa=edittrigger;bg=x;bi=y |
|
1567
|
|
|
* - uses the ban_edit_trigger sub template of ManageBans. |
|
1568
|
|
|
*/ |
|
1569
|
|
|
function BanEditTrigger() |
|
1570
|
|
|
{ |
|
1571
|
|
|
global $context, $smcFunc, $scripturl; |
|
1572
|
|
|
|
|
1573
|
|
|
$context['sub_template'] = 'ban_edit_trigger'; |
|
1574
|
|
|
$context['form_url'] = $scripturl . '?action=admin;area=ban;sa=edittrigger'; |
|
1575
|
|
|
|
|
1576
|
|
|
$ban_group = isset($_REQUEST['bg']) ? (int) $_REQUEST['bg'] : 0; |
|
1577
|
|
|
$ban_id = isset($_REQUEST['bi']) ? (int) $_REQUEST['bi'] : 0; |
|
1578
|
|
|
|
|
1579
|
|
|
if (empty($ban_group)) |
|
1580
|
|
|
fatal_lang_error('ban_not_found', false); |
|
1581
|
|
|
|
|
1582
|
|
|
if (isset($_POST['add_new_trigger']) && !empty($_POST['ban_suggestions'])) |
|
1583
|
|
|
{ |
|
1584
|
|
|
saveTriggers($_POST['ban_suggestions'], $ban_group, 0, $ban_id); |
|
1585
|
|
|
redirectexit('action=admin;area=ban;sa=edit' . (!empty($ban_group) ? ';bg=' . $ban_group : '')); |
|
1586
|
|
|
} |
|
1587
|
|
|
elseif (isset($_POST['edit_trigger']) && !empty($_POST['ban_suggestions'])) |
|
1588
|
|
|
{ |
|
1589
|
|
|
// The first replaces the old one, the others are added new (simplification, otherwise it would require another query and some work...) |
|
1590
|
|
|
saveTriggers(array_shift($_POST['ban_suggestions']), $ban_group, 0, $ban_id); |
|
1591
|
|
|
if (!empty($_POST['ban_suggestions'])) |
|
1592
|
|
|
saveTriggers($_POST['ban_suggestions'], $ban_group); |
|
1593
|
|
|
|
|
1594
|
|
|
redirectexit('action=admin;area=ban;sa=edit' . (!empty($ban_group) ? ';bg=' . $ban_group : '')); |
|
1595
|
|
|
} |
|
1596
|
|
|
elseif (isset($_POST['edit_trigger'])) |
|
1597
|
|
|
{ |
|
1598
|
|
|
removeBanTriggers($ban_id); |
|
|
|
|
|
|
1599
|
|
|
redirectexit('action=admin;area=ban;sa=edit' . (!empty($ban_group) ? ';bg=' . $ban_group : '')); |
|
1600
|
|
|
} |
|
1601
|
|
|
|
|
1602
|
|
|
loadJavaScriptFile('suggest.js', array(), 'smf_suggest'); |
|
1603
|
|
|
|
|
1604
|
|
|
if (empty($ban_id)) |
|
1605
|
|
|
{ |
|
1606
|
|
|
$context['ban_trigger'] = array( |
|
1607
|
|
|
'id' => 0, |
|
1608
|
|
|
'group' => $ban_group, |
|
1609
|
|
|
'ip' => array( |
|
1610
|
|
|
'value' => '', |
|
1611
|
|
|
'selected' => true, |
|
1612
|
|
|
), |
|
1613
|
|
|
'hostname' => array( |
|
1614
|
|
|
'selected' => false, |
|
1615
|
|
|
'value' => '', |
|
1616
|
|
|
), |
|
1617
|
|
|
'email' => array( |
|
1618
|
|
|
'value' => '', |
|
1619
|
|
|
'selected' => false, |
|
1620
|
|
|
), |
|
1621
|
|
|
'banneduser' => array( |
|
1622
|
|
|
'value' => '', |
|
1623
|
|
|
'selected' => false, |
|
1624
|
|
|
), |
|
1625
|
|
|
'is_new' => true, |
|
1626
|
|
|
); |
|
1627
|
|
|
} |
|
1628
|
|
|
else |
|
1629
|
|
|
{ |
|
1630
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1631
|
|
|
SELECT |
|
1632
|
|
|
bi.id_ban, bi.id_ban_group, bi.hostname, bi.email_address, bi.id_member, |
|
1633
|
|
|
bi.ip_low, bi.ip_high, |
|
1634
|
|
|
mem.member_name, mem.real_name |
|
1635
|
|
|
FROM {db_prefix}ban_items AS bi |
|
1636
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member) |
|
1637
|
|
|
WHERE bi.id_ban = {int:ban_item} |
|
1638
|
|
|
AND bi.id_ban_group = {int:ban_group} |
|
1639
|
|
|
LIMIT 1', |
|
1640
|
|
|
array( |
|
1641
|
|
|
'ban_item' => $ban_id, |
|
1642
|
|
|
'ban_group' => $ban_group, |
|
1643
|
|
|
) |
|
1644
|
|
|
); |
|
1645
|
|
|
if ($smcFunc['db_num_rows']($request) == 0) |
|
1646
|
|
|
fatal_lang_error('ban_not_found', false); |
|
1647
|
|
|
$row = $smcFunc['db_fetch_assoc']($request); |
|
1648
|
|
|
$smcFunc['db_free_result']($request); |
|
1649
|
|
|
|
|
1650
|
|
|
$context['ban_trigger'] = array( |
|
1651
|
|
|
'id' => $row['id_ban'], |
|
1652
|
|
|
'group' => $row['id_ban_group'], |
|
1653
|
|
|
'ip' => array( |
|
1654
|
|
|
'value' => empty($row['ip_low']) ? '' : range2ip($row['ip_low'], $row['ip_high']), |
|
1655
|
|
|
'selected' => !empty($row['ip_low']), |
|
1656
|
|
|
), |
|
1657
|
|
|
'hostname' => array( |
|
1658
|
|
|
'value' => str_replace('%', '*', $row['hostname']), |
|
1659
|
|
|
'selected' => !empty($row['hostname']), |
|
1660
|
|
|
), |
|
1661
|
|
|
'email' => array( |
|
1662
|
|
|
'value' => str_replace('%', '*', $row['email_address']), |
|
1663
|
|
|
'selected' => !empty($row['email_address']) |
|
1664
|
|
|
), |
|
1665
|
|
|
'banneduser' => array( |
|
1666
|
|
|
'value' => $row['member_name'], |
|
1667
|
|
|
'selected' => !empty($row['member_name']) |
|
1668
|
|
|
), |
|
1669
|
|
|
'is_new' => false, |
|
1670
|
|
|
); |
|
1671
|
|
|
} |
|
1672
|
|
|
|
|
1673
|
|
|
createToken('admin-bet'); |
|
1674
|
|
|
} |
|
1675
|
|
|
|
|
1676
|
|
|
/** |
|
1677
|
|
|
* This handles the screen for showing the banned entities |
|
1678
|
|
|
* It is accessed by ?action=admin;area=ban;sa=browse |
|
1679
|
|
|
* It uses sub-tabs for browsing by IP, hostname, email or username. |
|
1680
|
|
|
* |
|
1681
|
|
|
* @uses ManageBans template, browse_triggers sub template. |
|
1682
|
|
|
*/ |
|
1683
|
|
|
function BanBrowseTriggers() |
|
1684
|
|
|
{ |
|
1685
|
|
|
global $modSettings, $context, $scripturl, $smcFunc, $txt; |
|
1686
|
|
|
global $sourcedir, $settings; |
|
1687
|
|
|
|
|
1688
|
|
|
if (!empty($_POST['remove_triggers']) && !empty($_POST['remove']) && is_array($_POST['remove'])) |
|
1689
|
|
|
{ |
|
1690
|
|
|
checkSession(); |
|
1691
|
|
|
|
|
1692
|
|
|
removeBanTriggers($_POST['remove']); |
|
1693
|
|
|
|
|
1694
|
|
|
// Rehabilitate some members. |
|
1695
|
|
|
if ($_REQUEST['entity'] == 'member') |
|
1696
|
|
|
updateBanMembers(); |
|
1697
|
|
|
|
|
1698
|
|
|
// Make sure the ban cache is refreshed. |
|
1699
|
|
|
updateSettings(array('banLastUpdated' => time())); |
|
1700
|
|
|
} |
|
1701
|
|
|
|
|
1702
|
|
|
$context['selected_entity'] = isset($_REQUEST['entity']) && in_array($_REQUEST['entity'], array('ip', 'hostname', 'email', 'member')) ? $_REQUEST['entity'] : 'ip'; |
|
1703
|
|
|
|
|
1704
|
|
|
$listOptions = array( |
|
1705
|
|
|
'id' => 'ban_trigger_list', |
|
1706
|
|
|
'title' => $txt['ban_trigger_browse'], |
|
1707
|
|
|
'items_per_page' => $modSettings['defaultMaxListItems'], |
|
1708
|
|
|
'base_href' => $scripturl . '?action=admin;area=ban;sa=browse;entity=' . $context['selected_entity'], |
|
1709
|
|
|
'default_sort_col' => 'banned_entity', |
|
1710
|
|
|
'no_items_label' => $txt['ban_no_triggers'], |
|
1711
|
|
|
'get_items' => array( |
|
1712
|
|
|
'function' => 'list_getBanTriggers', |
|
1713
|
|
|
'params' => array( |
|
1714
|
|
|
$context['selected_entity'], |
|
1715
|
|
|
), |
|
1716
|
|
|
), |
|
1717
|
|
|
'get_count' => array( |
|
1718
|
|
|
'function' => 'list_getNumBanTriggers', |
|
1719
|
|
|
'params' => array( |
|
1720
|
|
|
$context['selected_entity'], |
|
1721
|
|
|
), |
|
1722
|
|
|
), |
|
1723
|
|
|
'columns' => array( |
|
1724
|
|
|
'banned_entity' => array( |
|
1725
|
|
|
'header' => array( |
|
1726
|
|
|
'value' => $txt['ban_banned_entity'], |
|
1727
|
|
|
), |
|
1728
|
|
|
), |
|
1729
|
|
|
'ban_name' => array( |
|
1730
|
|
|
'header' => array( |
|
1731
|
|
|
'value' => $txt['ban_name'], |
|
1732
|
|
|
), |
|
1733
|
|
|
'data' => array( |
|
1734
|
|
|
'sprintf' => array( |
|
1735
|
|
|
'format' => '<a href="' . $scripturl . '?action=admin;area=ban;sa=edit;bg=%1$d">%2$s</a>', |
|
1736
|
|
|
'params' => array( |
|
1737
|
|
|
'id_ban_group' => false, |
|
1738
|
|
|
'name' => false, |
|
1739
|
|
|
), |
|
1740
|
|
|
), |
|
1741
|
|
|
), |
|
1742
|
|
|
'sort' => array( |
|
1743
|
|
|
'default' => 'bg.name', |
|
1744
|
|
|
'reverse' => 'bg.name DESC', |
|
1745
|
|
|
), |
|
1746
|
|
|
), |
|
1747
|
|
|
'hits' => array( |
|
1748
|
|
|
'header' => array( |
|
1749
|
|
|
'value' => $txt['ban_hits'], |
|
1750
|
|
|
), |
|
1751
|
|
|
'data' => array( |
|
1752
|
|
|
'db' => 'hits', |
|
1753
|
|
|
), |
|
1754
|
|
|
'sort' => array( |
|
1755
|
|
|
'default' => 'bi.hits DESC', |
|
1756
|
|
|
'reverse' => 'bi.hits', |
|
1757
|
|
|
), |
|
1758
|
|
|
), |
|
1759
|
|
|
'check' => array( |
|
1760
|
|
|
'header' => array( |
|
1761
|
|
|
'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check">', |
|
1762
|
|
|
'class' => 'centercol', |
|
1763
|
|
|
), |
|
1764
|
|
|
'data' => array( |
|
1765
|
|
|
'sprintf' => array( |
|
1766
|
|
|
'format' => '<input type="checkbox" name="remove[]" value="%1$d" class="input_check">', |
|
1767
|
|
|
'params' => array( |
|
1768
|
|
|
'id_ban' => false, |
|
1769
|
|
|
), |
|
1770
|
|
|
), |
|
1771
|
|
|
'class' => 'centercol', |
|
1772
|
|
|
), |
|
1773
|
|
|
), |
|
1774
|
|
|
), |
|
1775
|
|
|
'form' => array( |
|
1776
|
|
|
'href' => $scripturl . '?action=admin;area=ban;sa=browse;entity=' . $context['selected_entity'], |
|
1777
|
|
|
'include_start' => true, |
|
1778
|
|
|
'include_sort' => true, |
|
1779
|
|
|
), |
|
1780
|
|
|
'additional_rows' => array( |
|
1781
|
|
|
array( |
|
1782
|
|
|
'position' => 'above_column_headers', |
|
1783
|
|
|
'value' => '<a href="' . $scripturl . '?action=admin;area=ban;sa=browse;entity=ip">' . ($context['selected_entity'] == 'ip' ? '<img src="' . $settings['images_url'] . '/selected.png" alt=">"> ' : '') . $txt['ip'] . '</a> | <a href="' . $scripturl . '?action=admin;area=ban;sa=browse;entity=hostname">' . ($context['selected_entity'] == 'hostname' ? '<img src="' . $settings['images_url'] . '/selected.png" alt=">"> ' : '') . $txt['hostname'] . '</a> | <a href="' . $scripturl . '?action=admin;area=ban;sa=browse;entity=email">' . ($context['selected_entity'] == 'email' ? '<img src="' . $settings['images_url'] . '/selected.png" alt=">"> ' : '') . $txt['email'] . '</a> | <a href="' . $scripturl . '?action=admin;area=ban;sa=browse;entity=member">' . ($context['selected_entity'] == 'member' ? '<img src="' . $settings['images_url'] . '/selected.png" alt=">"> ' : '') . $txt['username'] . '</a>', |
|
1784
|
|
|
), |
|
1785
|
|
|
array( |
|
1786
|
|
|
'position' => 'bottom_of_list', |
|
1787
|
|
|
'value' => '<input type="submit" name="remove_triggers" value="' . $txt['ban_remove_selected_triggers'] . '" data-confirm="' . $txt['ban_remove_selected_triggers_confirm'] . '" class="button_submit you_sure">', |
|
1788
|
|
|
), |
|
1789
|
|
|
), |
|
1790
|
|
|
); |
|
1791
|
|
|
|
|
1792
|
|
|
// Specific data for the first column depending on the selected entity. |
|
1793
|
|
|
if ($context['selected_entity'] === 'ip') |
|
1794
|
|
|
{ |
|
1795
|
|
|
$listOptions['columns']['banned_entity']['data'] = array( |
|
1796
|
|
|
'function' => function($rowData) |
|
1797
|
|
|
{ |
|
1798
|
|
|
return range2ip( |
|
1799
|
|
|
$rowData['ip_low'] |
|
1800
|
|
|
, |
|
1801
|
|
|
$rowData['ip_high'] |
|
1802
|
|
|
); |
|
1803
|
|
|
}, |
|
1804
|
|
|
); |
|
1805
|
|
|
$listOptions['columns']['banned_entity']['sort'] = array( |
|
1806
|
|
|
'default' => 'bi.ip_low, bi.ip_high, bi.ip_low', |
|
1807
|
|
|
'reverse' => 'bi.ip_low DESC, bi.ip_high DESC', |
|
1808
|
|
|
); |
|
1809
|
|
|
} |
|
1810
|
|
View Code Duplication |
elseif ($context['selected_entity'] === 'hostname') |
|
|
|
|
|
|
1811
|
|
|
{ |
|
1812
|
|
|
$listOptions['columns']['banned_entity']['data'] = array( |
|
1813
|
|
|
'function' => function($rowData) use ($smcFunc) |
|
1814
|
|
|
{ |
|
1815
|
|
|
return strtr($smcFunc['htmlspecialchars']($rowData['hostname']), array('%' => '*')); |
|
1816
|
|
|
}, |
|
1817
|
|
|
); |
|
1818
|
|
|
$listOptions['columns']['banned_entity']['sort'] = array( |
|
1819
|
|
|
'default' => 'bi.hostname', |
|
1820
|
|
|
'reverse' => 'bi.hostname DESC', |
|
1821
|
|
|
); |
|
1822
|
|
|
} |
|
1823
|
|
View Code Duplication |
elseif ($context['selected_entity'] === 'email') |
|
|
|
|
|
|
1824
|
|
|
{ |
|
1825
|
|
|
$listOptions['columns']['banned_entity']['data'] = array( |
|
1826
|
|
|
'function' => function($rowData) use ($smcFunc) |
|
1827
|
|
|
{ |
|
1828
|
|
|
return strtr($smcFunc['htmlspecialchars']($rowData['email_address']), array('%' => '*')); |
|
1829
|
|
|
}, |
|
1830
|
|
|
); |
|
1831
|
|
|
$listOptions['columns']['banned_entity']['sort'] = array( |
|
1832
|
|
|
'default' => 'bi.email_address', |
|
1833
|
|
|
'reverse' => 'bi.email_address DESC', |
|
1834
|
|
|
); |
|
1835
|
|
|
} |
|
1836
|
|
|
elseif ($context['selected_entity'] === 'member') |
|
1837
|
|
|
{ |
|
1838
|
|
|
$listOptions['columns']['banned_entity']['data'] = array( |
|
1839
|
|
|
'sprintf' => array( |
|
1840
|
|
|
'format' => '<a href="' . $scripturl . '?action=profile;u=%1$d">%2$s</a>', |
|
1841
|
|
|
'params' => array( |
|
1842
|
|
|
'id_member' => false, |
|
1843
|
|
|
'real_name' => false, |
|
1844
|
|
|
), |
|
1845
|
|
|
), |
|
1846
|
|
|
); |
|
1847
|
|
|
$listOptions['columns']['banned_entity']['sort'] = array( |
|
1848
|
|
|
'default' => 'mem.real_name', |
|
1849
|
|
|
'reverse' => 'mem.real_name DESC', |
|
1850
|
|
|
); |
|
1851
|
|
|
} |
|
1852
|
|
|
|
|
1853
|
|
|
// Create the list. |
|
1854
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
|
1855
|
|
|
createList($listOptions); |
|
1856
|
|
|
|
|
1857
|
|
|
// The list is the only thing to show, so make it the default sub template. |
|
1858
|
|
|
$context['sub_template'] = 'show_list'; |
|
1859
|
|
|
$context['default_list'] = 'ban_trigger_list'; |
|
1860
|
|
|
} |
|
1861
|
|
|
|
|
1862
|
|
|
/** |
|
1863
|
|
|
* Get ban triggers for the given parameters. Callback from $listOptions['get_items'] in BanBrowseTriggers() |
|
1864
|
|
|
* |
|
1865
|
|
|
* @param int $start The item to start with (for pagination purposes) |
|
1866
|
|
|
* @param int $items_per_page How many items to show on each page |
|
1867
|
|
|
* @param string $sort A string telling ORDER BY how to sort the results |
|
1868
|
|
|
* @param string $trigger_type The trigger type - can be 'ip', 'hostname' or 'email' |
|
1869
|
|
|
* @return array An array of ban trigger info for the list |
|
1870
|
|
|
*/ |
|
1871
|
|
|
function list_getBanTriggers($start, $items_per_page, $sort, $trigger_type) |
|
1872
|
|
|
{ |
|
1873
|
|
|
global $smcFunc; |
|
1874
|
|
|
|
|
1875
|
|
|
$where = array( |
|
1876
|
|
|
'ip' => 'bi.ip_low is not null', |
|
1877
|
|
|
'hostname' => 'bi.hostname != {string:blank_string}', |
|
1878
|
|
|
'email' => 'bi.email_address != {string:blank_string}', |
|
1879
|
|
|
); |
|
1880
|
|
|
|
|
1881
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1882
|
|
|
SELECT |
|
1883
|
|
|
bi.id_ban, bi.ip_low, bi.ip_high, bi.hostname, bi.email_address, bi.hits, |
|
1884
|
|
|
bg.id_ban_group, bg.name' . ($trigger_type === 'member' ? ', |
|
1885
|
|
|
mem.id_member, mem.real_name' : '') . ' |
|
1886
|
|
|
FROM {db_prefix}ban_items AS bi |
|
1887
|
|
|
INNER JOIN {db_prefix}ban_groups AS bg ON (bg.id_ban_group = bi.id_ban_group)' . ($trigger_type === 'member' ? ' |
|
1888
|
|
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member)' : ' |
|
1889
|
|
|
WHERE ' . $where[$trigger_type]) . ' |
|
1890
|
|
|
ORDER BY {raw:sort} |
|
1891
|
|
|
LIMIT {int:start}, {int:max}', |
|
1892
|
|
|
array( |
|
1893
|
|
|
'blank_string' => '', |
|
1894
|
|
|
'sort' => $sort, |
|
1895
|
|
|
'start' => $start, |
|
1896
|
|
|
'max' => $items_per_page, |
|
1897
|
|
|
) |
|
1898
|
|
|
); |
|
1899
|
|
|
$ban_triggers = array(); |
|
1900
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
1901
|
|
|
$ban_triggers[] = $row; |
|
1902
|
|
|
$smcFunc['db_free_result']($request); |
|
1903
|
|
|
|
|
1904
|
|
|
return $ban_triggers; |
|
1905
|
|
|
} |
|
1906
|
|
|
|
|
1907
|
|
|
/** |
|
1908
|
|
|
* This returns the total number of ban triggers of the given type. Callback for $listOptions['get_count'] in BanBrowseTriggers(). |
|
1909
|
|
|
* |
|
1910
|
|
|
* @param string $trigger_type The trigger type. Can be 'ip', 'hostname' or 'email' |
|
1911
|
|
|
* @return int The number of triggers of the specified type |
|
1912
|
|
|
*/ |
|
1913
|
|
|
function list_getNumBanTriggers($trigger_type) |
|
1914
|
|
|
{ |
|
1915
|
|
|
global $smcFunc; |
|
1916
|
|
|
|
|
1917
|
|
|
$where = array( |
|
1918
|
|
|
'ip' => 'bi.ip_low is not null', |
|
1919
|
|
|
'hostname' => 'bi.hostname != {string:blank_string}', |
|
1920
|
|
|
'email' => 'bi.email_address != {string:blank_string}', |
|
1921
|
|
|
); |
|
1922
|
|
|
|
|
1923
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1924
|
|
|
SELECT COUNT(*) |
|
1925
|
|
|
FROM {db_prefix}ban_items AS bi' . ($trigger_type === 'member' ? ' |
|
1926
|
|
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = bi.id_member)' : ' |
|
1927
|
|
|
WHERE ' . $where[$trigger_type]), |
|
1928
|
|
|
array( |
|
1929
|
|
|
'blank_string' => '', |
|
1930
|
|
|
) |
|
1931
|
|
|
); |
|
1932
|
|
|
list ($num_triggers) = $smcFunc['db_fetch_row']($request); |
|
1933
|
|
|
$smcFunc['db_free_result']($request); |
|
1934
|
|
|
|
|
1935
|
|
|
return $num_triggers; |
|
1936
|
|
|
} |
|
1937
|
|
|
|
|
1938
|
|
|
/** |
|
1939
|
|
|
* This handles the listing of ban log entries, and allows their deletion. |
|
1940
|
|
|
* Shows a list of logged access attempts by banned users. |
|
1941
|
|
|
* It is accessed by ?action=admin;area=ban;sa=log. |
|
1942
|
|
|
* How it works: |
|
1943
|
|
|
* - allows sorting of several columns. |
|
1944
|
|
|
* - also handles deletion of (a selection of) log entries. |
|
1945
|
|
|
*/ |
|
1946
|
|
|
function BanLog() |
|
1947
|
|
|
{ |
|
1948
|
|
|
global $scripturl, $context, $sourcedir, $txt, $modSettings; |
|
1949
|
|
|
|
|
1950
|
|
|
// Delete one or more entries. |
|
1951
|
|
|
if (!empty($_POST['removeAll']) || (!empty($_POST['removeSelected']) && !empty($_POST['remove']))) |
|
1952
|
|
|
{ |
|
1953
|
|
|
checkSession(); |
|
1954
|
|
|
validateToken('admin-bl'); |
|
1955
|
|
|
|
|
1956
|
|
|
// 'Delete all entries' button was pressed. |
|
1957
|
|
|
if (!empty($_POST['removeAll'])) |
|
1958
|
|
|
removeBanLogs(); |
|
1959
|
|
|
// 'Delete selection' button was pressed. |
|
1960
|
|
|
else |
|
1961
|
|
|
{ |
|
1962
|
|
|
array_map('intval', $_POST['remove']); |
|
1963
|
|
|
removeBanLogs($_POST['remove']); |
|
1964
|
|
|
} |
|
1965
|
|
|
} |
|
1966
|
|
|
|
|
1967
|
|
|
$listOptions = array( |
|
1968
|
|
|
'id' => 'ban_log', |
|
1969
|
|
|
'title' => $txt['ban_log'], |
|
1970
|
|
|
'items_per_page' => $modSettings['defaultMaxListItems'], |
|
1971
|
|
|
'base_href' => $context['admin_area'] == 'ban' ? $scripturl . '?action=admin;area=ban;sa=log' : $scripturl . '?action=admin;area=logs;sa=banlog', |
|
1972
|
|
|
'default_sort_col' => 'date', |
|
1973
|
|
|
'get_items' => array( |
|
1974
|
|
|
'function' => 'list_getBanLogEntries', |
|
1975
|
|
|
), |
|
1976
|
|
|
'get_count' => array( |
|
1977
|
|
|
'function' => 'list_getNumBanLogEntries', |
|
1978
|
|
|
), |
|
1979
|
|
|
'no_items_label' => $txt['ban_log_no_entries'], |
|
1980
|
|
|
'columns' => array( |
|
1981
|
|
|
'ip' => array( |
|
1982
|
|
|
'header' => array( |
|
1983
|
|
|
'value' => $txt['ban_log_ip'], |
|
1984
|
|
|
), |
|
1985
|
|
|
'data' => array( |
|
1986
|
|
|
'sprintf' => array( |
|
1987
|
|
|
'format' => '<a href="' . $scripturl . '?action=trackip;searchip=%1$s">%1$s</a>', |
|
1988
|
|
|
'params' => array( |
|
1989
|
|
|
'ip' => false, |
|
1990
|
|
|
), |
|
1991
|
|
|
), |
|
1992
|
|
|
), |
|
1993
|
|
|
'sort' => array( |
|
1994
|
|
|
'default' => 'lb.ip', |
|
1995
|
|
|
'reverse' => 'lb.ip DESC', |
|
1996
|
|
|
), |
|
1997
|
|
|
), |
|
1998
|
|
|
'email' => array( |
|
1999
|
|
|
'header' => array( |
|
2000
|
|
|
'value' => $txt['ban_log_email'], |
|
2001
|
|
|
), |
|
2002
|
|
|
'data' => array( |
|
2003
|
|
|
'db_htmlsafe' => 'email', |
|
2004
|
|
|
), |
|
2005
|
|
|
'sort' => array( |
|
2006
|
|
|
'default' => 'lb.email = \'\', lb.email', |
|
2007
|
|
|
'reverse' => 'lb.email != \'\', lb.email DESC', |
|
2008
|
|
|
), |
|
2009
|
|
|
), |
|
2010
|
|
|
'member' => array( |
|
2011
|
|
|
'header' => array( |
|
2012
|
|
|
'value' => $txt['ban_log_member'], |
|
2013
|
|
|
), |
|
2014
|
|
|
'data' => array( |
|
2015
|
|
|
'sprintf' => array( |
|
2016
|
|
|
'format' => '<a href="' . $scripturl . '?action=profile;u=%1$d">%2$s</a>', |
|
2017
|
|
|
'params' => array( |
|
2018
|
|
|
'id_member' => false, |
|
2019
|
|
|
'real_name' => false, |
|
2020
|
|
|
), |
|
2021
|
|
|
), |
|
2022
|
|
|
), |
|
2023
|
|
|
'sort' => array( |
|
2024
|
|
|
'default' => 'COALESCE(mem.real_name, 1=1), mem.real_name', |
|
2025
|
|
|
'reverse' => 'COALESCE(mem.real_name, 1=1) DESC, mem.real_name DESC', |
|
2026
|
|
|
), |
|
2027
|
|
|
), |
|
2028
|
|
|
'date' => array( |
|
2029
|
|
|
'header' => array( |
|
2030
|
|
|
'value' => $txt['ban_log_date'], |
|
2031
|
|
|
), |
|
2032
|
|
|
'data' => array( |
|
2033
|
|
|
'function' => function($rowData) |
|
2034
|
|
|
{ |
|
2035
|
|
|
return timeformat($rowData['log_time']); |
|
2036
|
|
|
}, |
|
2037
|
|
|
), |
|
2038
|
|
|
'sort' => array( |
|
2039
|
|
|
'default' => 'lb.log_time DESC', |
|
2040
|
|
|
'reverse' => 'lb.log_time', |
|
2041
|
|
|
), |
|
2042
|
|
|
), |
|
2043
|
|
|
'check' => array( |
|
2044
|
|
|
'header' => array( |
|
2045
|
|
|
'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check">', |
|
2046
|
|
|
'class' => 'centercol', |
|
2047
|
|
|
), |
|
2048
|
|
|
'data' => array( |
|
2049
|
|
|
'sprintf' => array( |
|
2050
|
|
|
'format' => '<input type="checkbox" name="remove[]" value="%1$d" class="input_check">', |
|
2051
|
|
|
'params' => array( |
|
2052
|
|
|
'id_ban_log' => false, |
|
2053
|
|
|
), |
|
2054
|
|
|
), |
|
2055
|
|
|
'class' => 'centercol', |
|
2056
|
|
|
), |
|
2057
|
|
|
), |
|
2058
|
|
|
), |
|
2059
|
|
|
'form' => array( |
|
2060
|
|
|
'href' => $context['admin_area'] == 'ban' ? $scripturl . '?action=admin;area=ban;sa=log' : $scripturl . '?action=admin;area=logs;sa=banlog', |
|
2061
|
|
|
'include_start' => true, |
|
2062
|
|
|
'include_sort' => true, |
|
2063
|
|
|
'token' => 'admin-bl', |
|
2064
|
|
|
), |
|
2065
|
|
|
'additional_rows' => array( |
|
2066
|
|
|
array( |
|
2067
|
|
|
'position' => 'top_of_list', |
|
2068
|
|
|
'value' => ' |
|
2069
|
|
|
<input type="submit" name="removeSelected" value="' . $txt['ban_log_remove_selected'] . '" data-confirm="' . $txt['ban_log_remove_selected_confirm'] . '" class="button_submit you_sure"> |
|
2070
|
|
|
<input type="submit" name="removeAll" value="' . $txt['ban_log_remove_all'] . '" data-confirm="' . $txt['ban_log_remove_all_confirm'] . '" class="button_submit you_sure">', |
|
2071
|
|
|
), |
|
2072
|
|
|
array( |
|
2073
|
|
|
'position' => 'bottom_of_list', |
|
2074
|
|
|
'value' => ' |
|
2075
|
|
|
<input type="submit" name="removeSelected" value="' . $txt['ban_log_remove_selected'] . '" data-confirm="' . $txt['ban_log_remove_selected_confirm'] . '" class="button_submit you_sure"> |
|
2076
|
|
|
<input type="submit" name="removeAll" value="' . $txt['ban_log_remove_all'] . '" data-confirm="' . $txt['ban_log_remove_all_confirm'] . '" class="button_submit you_sure">', |
|
2077
|
|
|
), |
|
2078
|
|
|
), |
|
2079
|
|
|
); |
|
2080
|
|
|
|
|
2081
|
|
|
createToken('admin-bl'); |
|
2082
|
|
|
|
|
2083
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
|
2084
|
|
|
createList($listOptions); |
|
2085
|
|
|
|
|
2086
|
|
|
$context['page_title'] = $txt['ban_log']; |
|
2087
|
|
|
$context['sub_template'] = 'show_list'; |
|
2088
|
|
|
$context['default_list'] = 'ban_log'; |
|
2089
|
|
|
} |
|
2090
|
|
|
|
|
2091
|
|
|
/** |
|
2092
|
|
|
* Load a list of ban log entries from the database. |
|
2093
|
|
|
* (no permissions check). Callback for $listOptions['get_items'] in BanLog() |
|
2094
|
|
|
* |
|
2095
|
|
|
* @param int $start The item to start with (for pagination purposes) |
|
2096
|
|
|
* @param int $items_per_page How many items to show on each page |
|
2097
|
|
|
* @param string $sort A string telling ORDER BY how to sort the results |
|
2098
|
|
|
* @return array An array of info about the ban log entries for the list. |
|
2099
|
|
|
*/ |
|
2100
|
|
|
function list_getBanLogEntries($start, $items_per_page, $sort) |
|
2101
|
|
|
{ |
|
2102
|
|
|
global $smcFunc; |
|
2103
|
|
|
|
|
2104
|
|
|
$dash = '-'; |
|
2105
|
|
|
|
|
2106
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2107
|
|
|
SELECT lb.id_ban_log, lb.id_member, lb.ip AS ip, COALESCE(lb.email, {string:dash}) AS email, lb.log_time, COALESCE(mem.real_name, {string:blank_string}) AS real_name |
|
2108
|
|
|
FROM {db_prefix}log_banned AS lb |
|
2109
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lb.id_member) |
|
2110
|
|
|
ORDER BY {raw:sort} |
|
2111
|
|
|
LIMIT {int:start}, {int:items}', |
|
2112
|
|
|
array( |
|
2113
|
|
|
'blank_string' => '', |
|
2114
|
|
|
'dash' => $dash, |
|
2115
|
|
|
'sort' => $sort, |
|
2116
|
|
|
'start' => $start, |
|
2117
|
|
|
'items' => $items_per_page, |
|
2118
|
|
|
) |
|
2119
|
|
|
); |
|
2120
|
|
|
$log_entries = array(); |
|
2121
|
|
View Code Duplication |
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
|
|
|
|
|
2122
|
|
|
{ |
|
2123
|
|
|
$row['ip'] = $row['ip'] === null ? $dash : inet_dtop($row['ip']); |
|
2124
|
|
|
$log_entries[] = $row; |
|
2125
|
|
|
} |
|
2126
|
|
|
$smcFunc['db_free_result']($request); |
|
2127
|
|
|
|
|
2128
|
|
|
return $log_entries; |
|
2129
|
|
|
} |
|
2130
|
|
|
|
|
2131
|
|
|
/** |
|
2132
|
|
|
* This returns the total count of ban log entries. Callback for $listOptions['get_count'] in BanLog(). |
|
2133
|
|
|
* @return int The total number of ban log entries. |
|
2134
|
|
|
*/ |
|
2135
|
|
|
function list_getNumBanLogEntries() |
|
2136
|
|
|
{ |
|
2137
|
|
|
global $smcFunc; |
|
2138
|
|
|
|
|
2139
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2140
|
|
|
SELECT COUNT(*) |
|
2141
|
|
|
FROM {db_prefix}log_banned AS lb', |
|
2142
|
|
|
array( |
|
2143
|
|
|
) |
|
2144
|
|
|
); |
|
2145
|
|
|
list ($num_entries) = $smcFunc['db_fetch_row']($request); |
|
2146
|
|
|
$smcFunc['db_free_result']($request); |
|
2147
|
|
|
|
|
2148
|
|
|
return $num_entries; |
|
2149
|
|
|
} |
|
2150
|
|
|
|
|
2151
|
|
|
/** |
|
2152
|
|
|
* Convert a range of given IP number into a single string. |
|
2153
|
|
|
* It's practically the reverse function of ip2range(). |
|
2154
|
|
|
* |
|
2155
|
|
|
* @example |
|
2156
|
|
|
* range2ip(array(10, 10, 10, 0), array(10, 10, 20, 255)) returns '10.10.10-20.* |
|
2157
|
|
|
* |
|
2158
|
|
|
* @param array $low The low end of the range in IPv4 format |
|
2159
|
|
|
* @param array $high The high end of the range in IPv4 format |
|
2160
|
|
|
* @return string A string indicating the range |
|
2161
|
|
|
*/ |
|
2162
|
|
|
function range2ip($low, $high) |
|
2163
|
|
|
{ |
|
2164
|
|
|
$low = inet_dtop($low); |
|
|
|
|
|
|
2165
|
|
|
$high = inet_dtop($high); |
|
|
|
|
|
|
2166
|
|
|
|
|
2167
|
|
|
if ($low == '255.255.255.255') return 'unknown'; |
|
2168
|
|
|
if ($low == $high) |
|
2169
|
|
|
return $low; |
|
2170
|
|
|
else |
|
2171
|
|
|
return $low . '-' . $high; |
|
2172
|
|
|
} |
|
2173
|
|
|
|
|
2174
|
|
|
/** |
|
2175
|
|
|
* Checks whether a given IP range already exists in the trigger list. |
|
2176
|
|
|
* If yes, it returns an error message. Otherwise, it returns an array |
|
2177
|
|
|
* optimized for the database. |
|
2178
|
|
|
* |
|
2179
|
|
|
* @param array $ip_array An array of IP trigger data |
|
2180
|
|
|
* @param string $fullip The full IP |
|
2181
|
|
|
* @return boolean|array False if the trigger array is invalid or the passed array if the value doesn't exist in the database |
|
2182
|
|
|
*/ |
|
2183
|
|
|
function checkExistingTriggerIP($ip_array, $fullip = '') |
|
2184
|
|
|
{ |
|
2185
|
|
|
global $smcFunc, $scripturl; |
|
2186
|
|
|
|
|
2187
|
|
|
|
|
2188
|
|
|
$values = array( |
|
2189
|
|
|
'ip_low' => $ip_array['low'], |
|
2190
|
|
|
'ip_high' => $ip_array['high'] |
|
2191
|
|
|
); |
|
2192
|
|
|
|
|
2193
|
|
|
|
|
2194
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2195
|
|
|
SELECT bg.id_ban_group, bg.name |
|
2196
|
|
|
FROM {db_prefix}ban_groups AS bg |
|
2197
|
|
|
INNER JOIN {db_prefix}ban_items AS bi ON |
|
2198
|
|
|
(bi.id_ban_group = bg.id_ban_group) |
|
2199
|
|
|
AND ip_low = {inet:ip_low} AND ip_high = {inet:ip_high} |
|
2200
|
|
|
LIMIT 1', |
|
2201
|
|
|
$values |
|
2202
|
|
|
); |
|
2203
|
|
|
if ($smcFunc['db_num_rows']($request) != 0) |
|
2204
|
|
|
{ |
|
2205
|
|
|
list ($error_id_ban, $error_ban_name) = $smcFunc['db_fetch_row']($request); |
|
2206
|
|
|
fatal_lang_error('ban_trigger_already_exists', false, array( |
|
2207
|
|
|
$fullip, |
|
2208
|
|
|
'<a href="' . $scripturl . '?action=admin;area=ban;sa=edit;bg=' . $error_id_ban . '">' . $error_ban_name . '</a>', |
|
2209
|
|
|
)); |
|
2210
|
|
|
} |
|
2211
|
|
|
$smcFunc['db_free_result']($request); |
|
2212
|
|
|
|
|
2213
|
|
|
return $values; |
|
2214
|
|
|
} |
|
2215
|
|
|
|
|
2216
|
|
|
/** |
|
2217
|
|
|
* As it says... this tries to review the list of banned members, to match new bans. |
|
2218
|
|
|
* Note: is_activated >= 10: a member is banned. |
|
2219
|
|
|
*/ |
|
2220
|
|
|
function updateBanMembers() |
|
2221
|
|
|
{ |
|
2222
|
|
|
global $smcFunc; |
|
2223
|
|
|
|
|
2224
|
|
|
$updates = array(); |
|
2225
|
|
|
$allMembers = array(); |
|
2226
|
|
|
$newMembers = array(); |
|
2227
|
|
|
|
|
2228
|
|
|
// Start by getting all active bans - it's quicker doing this in parts... |
|
2229
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2230
|
|
|
SELECT bi.id_member, bi.email_address |
|
2231
|
|
|
FROM {db_prefix}ban_items AS bi |
|
2232
|
|
|
INNER JOIN {db_prefix}ban_groups AS bg ON (bg.id_ban_group = bi.id_ban_group) |
|
2233
|
|
|
WHERE (bi.id_member > {int:no_member} OR bi.email_address != {string:blank_string}) |
|
2234
|
|
|
AND bg.cannot_access = {int:cannot_access_on} |
|
2235
|
|
|
AND (bg.expire_time IS NULL OR bg.expire_time > {int:current_time})', |
|
2236
|
|
|
array( |
|
2237
|
|
|
'no_member' => 0, |
|
2238
|
|
|
'cannot_access_on' => 1, |
|
2239
|
|
|
'current_time' => time(), |
|
2240
|
|
|
'blank_string' => '', |
|
2241
|
|
|
) |
|
2242
|
|
|
); |
|
2243
|
|
|
$memberIDs = array(); |
|
2244
|
|
|
$memberEmails = array(); |
|
2245
|
|
|
$memberEmailWild = array(); |
|
2246
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
2247
|
|
|
{ |
|
2248
|
|
|
if ($row['id_member']) |
|
2249
|
|
|
$memberIDs[$row['id_member']] = $row['id_member']; |
|
2250
|
|
|
if ($row['email_address']) |
|
2251
|
|
|
{ |
|
2252
|
|
|
// Does it have a wildcard - if so we can't do a IN on it. |
|
2253
|
|
|
if (strpos($row['email_address'], '%') !== false) |
|
2254
|
|
|
$memberEmailWild[$row['email_address']] = $row['email_address']; |
|
2255
|
|
|
else |
|
2256
|
|
|
$memberEmails[$row['email_address']] = $row['email_address']; |
|
2257
|
|
|
} |
|
2258
|
|
|
} |
|
2259
|
|
|
$smcFunc['db_free_result']($request); |
|
2260
|
|
|
|
|
2261
|
|
|
// Build up the query. |
|
2262
|
|
|
$queryPart = array(); |
|
2263
|
|
|
$queryValues = array(); |
|
2264
|
|
|
if (!empty($memberIDs)) |
|
2265
|
|
|
{ |
|
2266
|
|
|
$queryPart[] = 'mem.id_member IN ({array_string:member_ids})'; |
|
2267
|
|
|
$queryValues['member_ids'] = $memberIDs; |
|
2268
|
|
|
} |
|
2269
|
|
|
if (!empty($memberEmails)) |
|
2270
|
|
|
{ |
|
2271
|
|
|
$queryPart[] = 'mem.email_address IN ({array_string:member_emails})'; |
|
2272
|
|
|
$queryValues['member_emails'] = $memberEmails; |
|
2273
|
|
|
} |
|
2274
|
|
|
$count = 0; |
|
2275
|
|
|
foreach ($memberEmailWild as $email) |
|
2276
|
|
|
{ |
|
2277
|
|
|
$queryPart[] = 'mem.email_address LIKE {string:wild_' . $count . '}'; |
|
2278
|
|
|
$queryValues['wild_' . $count++] = $email; |
|
2279
|
|
|
} |
|
2280
|
|
|
|
|
2281
|
|
|
// Find all banned members. |
|
2282
|
|
|
if (!empty($queryPart)) |
|
2283
|
|
|
{ |
|
2284
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2285
|
|
|
SELECT mem.id_member, mem.is_activated |
|
2286
|
|
|
FROM {db_prefix}members AS mem |
|
2287
|
|
|
WHERE ' . implode(' OR ', $queryPart), |
|
2288
|
|
|
$queryValues |
|
2289
|
|
|
); |
|
2290
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
2291
|
|
|
{ |
|
2292
|
|
|
if (!in_array($row['id_member'], $allMembers)) |
|
2293
|
|
|
{ |
|
2294
|
|
|
$allMembers[] = $row['id_member']; |
|
2295
|
|
|
// Do they need an update? |
|
2296
|
|
|
if ($row['is_activated'] < 10) |
|
2297
|
|
|
{ |
|
2298
|
|
|
$updates[($row['is_activated'] + 10)][] = $row['id_member']; |
|
2299
|
|
|
$newMembers[] = $row['id_member']; |
|
2300
|
|
|
} |
|
2301
|
|
|
} |
|
2302
|
|
|
} |
|
2303
|
|
|
$smcFunc['db_free_result']($request); |
|
2304
|
|
|
} |
|
2305
|
|
|
|
|
2306
|
|
|
// We welcome our new members in the realm of the banned. |
|
2307
|
|
|
if (!empty($newMembers)) |
|
2308
|
|
|
$smcFunc['db_query']('', ' |
|
2309
|
|
|
DELETE FROM {db_prefix}log_online |
|
2310
|
|
|
WHERE id_member IN ({array_int:new_banned_members})', |
|
2311
|
|
|
array( |
|
2312
|
|
|
'new_banned_members' => $newMembers, |
|
2313
|
|
|
) |
|
2314
|
|
|
); |
|
2315
|
|
|
|
|
2316
|
|
|
// Find members that are wrongfully marked as banned. |
|
2317
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2318
|
|
|
SELECT mem.id_member, mem.is_activated - 10 AS new_value |
|
2319
|
|
|
FROM {db_prefix}members AS mem |
|
2320
|
|
|
LEFT JOIN {db_prefix}ban_items AS bi ON (bi.id_member = mem.id_member OR mem.email_address LIKE bi.email_address) |
|
2321
|
|
|
LEFT JOIN {db_prefix}ban_groups AS bg ON (bg.id_ban_group = bi.id_ban_group AND bg.cannot_access = {int:cannot_access_activated} AND (bg.expire_time IS NULL OR bg.expire_time > {int:current_time})) |
|
2322
|
|
|
WHERE (bi.id_ban IS NULL OR bg.id_ban_group IS NULL) |
|
2323
|
|
|
AND mem.is_activated >= {int:ban_flag}', |
|
2324
|
|
|
array( |
|
2325
|
|
|
'cannot_access_activated' => 1, |
|
2326
|
|
|
'current_time' => time(), |
|
2327
|
|
|
'ban_flag' => 10, |
|
2328
|
|
|
) |
|
2329
|
|
|
); |
|
2330
|
|
View Code Duplication |
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
|
|
|
|
|
2331
|
|
|
{ |
|
2332
|
|
|
// Don't do this twice! |
|
2333
|
|
|
if (!in_array($row['id_member'], $allMembers)) |
|
2334
|
|
|
{ |
|
2335
|
|
|
$updates[$row['new_value']][] = $row['id_member']; |
|
2336
|
|
|
$allMembers[] = $row['id_member']; |
|
2337
|
|
|
} |
|
2338
|
|
|
} |
|
2339
|
|
|
$smcFunc['db_free_result']($request); |
|
2340
|
|
|
|
|
2341
|
|
|
if (!empty($updates)) |
|
2342
|
|
|
foreach ($updates as $newStatus => $members) |
|
2343
|
|
|
updateMemberData($members, array('is_activated' => $newStatus)); |
|
2344
|
|
|
|
|
2345
|
|
|
// Update the latest member and our total members as banning may change them. |
|
2346
|
|
|
updateStats('member'); |
|
2347
|
|
|
} |
|
2348
|
|
|
|
|
2349
|
|
|
/** |
|
2350
|
|
|
* Gets basic member data for the ban |
|
2351
|
|
|
* |
|
2352
|
|
|
* @param int $id The ID of the member to get data for |
|
2353
|
|
|
* @return array An aray containing the ID, name, main IP and email address of the specified user |
|
2354
|
|
|
*/ |
|
2355
|
|
|
function getMemberData($id) |
|
2356
|
|
|
{ |
|
2357
|
|
|
global $smcFunc; |
|
2358
|
|
|
|
|
2359
|
|
|
$suggestions = array(); |
|
2360
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2361
|
|
|
SELECT id_member, real_name, member_ip, email_address |
|
2362
|
|
|
FROM {db_prefix}members |
|
2363
|
|
|
WHERE id_member = {int:current_user} |
|
2364
|
|
|
LIMIT 1', |
|
2365
|
|
|
array( |
|
2366
|
|
|
'current_user' => $id, |
|
2367
|
|
|
) |
|
2368
|
|
|
); |
|
2369
|
|
|
if ($smcFunc['db_num_rows']($request) > 0) |
|
2370
|
|
|
{ |
|
2371
|
|
|
list ($suggestions['member']['id'], $suggestions['member']['name'], $suggestions['main_ip'], $suggestions['email']) = $smcFunc['db_fetch_row']($request); |
|
2372
|
|
|
$suggestions['main_ip'] = inet_dtop($suggestions['main_ip']); |
|
2373
|
|
|
} |
|
2374
|
|
|
$smcFunc['db_free_result']($request); |
|
2375
|
|
|
|
|
2376
|
|
|
return $suggestions; |
|
2377
|
|
|
} |
|
2378
|
|
|
|
|
2379
|
|
|
?> |
|
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.