Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 258
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
acp_bots
0.00% covered (danger)
0.00%
0 / 256
0.00% covered (danger)
0.00%
0 / 2
3660
0.00% covered (danger)
0.00%
0 / 1
 main
0.00% covered (danger)
0.00%
0 / 246
0.00% covered (danger)
0.00%
0 / 1
3192
 validate_botname
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3*
4* This file is part of the phpBB Forum Software package.
5*
6* @copyright (c) phpBB Limited <https://www.phpbb.com>
7* @license GNU General Public License, version 2 (GPL-2.0)
8*
9* For full copyright and license information, please see
10* the docs/CREDITS.txt file.
11*
12*/
13
14/**
15* @ignore
16*/
17if (!defined('IN_PHPBB'))
18{
19    exit;
20}
21
22class acp_bots
23{
24    var $u_action;
25
26    function main($id, $mode)
27    {
28        global $config, $db, $user, $template, $cache, $request, $phpbb_log;
29        global $phpbb_root_path, $phpEx;
30
31        $action = $request->variable('action', '');
32        $submit = (isset($_POST['submit'])) ? true : false;
33        $mark    = $request->variable('mark', array(0));
34        $bot_id    = $request->variable('id', 0);
35
36        if (isset($_POST['add']))
37        {
38            $action = 'add';
39        }
40
41        $error = array();
42
43        $user->add_lang('acp/bots');
44        $this->tpl_name = 'acp_bots';
45        $this->page_title = 'ACP_BOTS';
46        $form_key = 'acp_bots';
47        add_form_key($form_key);
48
49        if ($submit && !check_form_key($form_key))
50        {
51            $error[] = $user->lang['FORM_INVALID'];
52        }
53
54        // User wants to do something, how inconsiderate of them!
55        switch ($action)
56        {
57            case 'activate':
58                if ($bot_id || count($mark))
59                {
60                    $sql_id = ($bot_id) ? " = $bot_id" : ' IN (' . implode(', ', $mark) . ')';
61
62                    $sql = 'UPDATE ' . BOTS_TABLE . "
63                        SET bot_active = 1
64                        WHERE bot_id $sql_id";
65                    $db->sql_query($sql);
66                }
67
68                $cache->destroy('_bots');
69            break;
70
71            case 'deactivate':
72                if ($bot_id || count($mark))
73                {
74                    $sql_id = ($bot_id) ? " = $bot_id" : ' IN (' . implode(', ', $mark) . ')';
75
76                    $sql = 'UPDATE ' . BOTS_TABLE . "
77                        SET bot_active = 0
78                        WHERE bot_id $sql_id";
79                    $db->sql_query($sql);
80                }
81
82                $cache->destroy('_bots');
83            break;
84
85            case 'delete':
86                if ($bot_id || count($mark))
87                {
88                    if (confirm_box(true))
89                    {
90                        // We need to delete the relevant user, usergroup and bot entries ...
91                        $sql_id = ($bot_id) ? " = $bot_id" : ' IN (' . implode(', ', $mark) . ')';
92
93                        $sql = 'SELECT bot_name, user_id
94                            FROM ' . BOTS_TABLE . "
95                            WHERE bot_id $sql_id";
96                        $result = $db->sql_query($sql);
97
98                        $user_id_ary = $bot_name_ary = array();
99                        while ($row = $db->sql_fetchrow($result))
100                        {
101                            $user_id_ary[] = (int) $row['user_id'];
102                            $bot_name_ary[] = $row['bot_name'];
103                        }
104                        $db->sql_freeresult($result);
105
106                        $db->sql_transaction('begin');
107
108                        $sql = 'DELETE FROM ' . BOTS_TABLE . "
109                            WHERE bot_id $sql_id";
110                        $db->sql_query($sql);
111
112                        if (count($user_id_ary))
113                        {
114                            $_tables = array(USERS_TABLE, USER_GROUP_TABLE);
115                            foreach ($_tables as $table)
116                            {
117                                $sql = "DELETE FROM $table
118                                    WHERE " . $db->sql_in_set('user_id', $user_id_ary);
119                                $db->sql_query($sql);
120                            }
121                        }
122
123                        $db->sql_transaction('commit');
124
125                        $cache->destroy('_bots');
126
127                        $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BOT_DELETE', false, array(implode(', ', $bot_name_ary)));
128                        trigger_error($user->lang['BOT_DELETED'] . adm_back_link($this->u_action));
129                    }
130                    else
131                    {
132                        confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
133                            'mark'        => $mark,
134                            'id'        => $bot_id,
135                            'mode'        => $mode,
136                            'action'    => $action))
137                        );
138                    }
139                }
140            break;
141
142            case 'edit':
143            case 'add':
144
145                if (!function_exists('user_update_name'))
146                {
147                    include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
148                }
149
150                $bot_row = array(
151                    'bot_name'        => $request->variable('bot_name', '', true),
152                    'bot_agent'        => $request->variable('bot_agent', ''),
153                    'bot_ip'        => $request->variable('bot_ip', ''),
154                    'bot_active'    => $request->variable('bot_active', true),
155                    'bot_lang'        => $request->variable('bot_lang', $config['default_lang']),
156                    'bot_style'        => $request->variable('bot_style' , $config['default_style']),
157                );
158
159                if ($submit)
160                {
161                    if (!$bot_row['bot_agent'] && !$bot_row['bot_ip'])
162                    {
163                        $error[] = $user->lang['ERR_BOT_NO_MATCHES'];
164                    }
165
166                    if ($bot_row['bot_ip'] && !preg_match('#^[\d\.,:]+$#', $bot_row['bot_ip']))
167                    {
168                        if (!$ip_list = gethostbynamel($bot_row['bot_ip']))
169                        {
170                            $error[] = $user->lang['ERR_BOT_NO_IP'];
171                        }
172                        else
173                        {
174                            $bot_row['bot_ip'] = implode(',', $ip_list);
175                        }
176                    }
177                    $bot_row['bot_ip'] = str_replace(' ', '', $bot_row['bot_ip']);
178
179                    // Make sure the admin is not adding a bot with an user agent similar to his one
180                    if ($bot_row['bot_agent'] && substr($user->data['session_browser'], 0, 149) === substr($bot_row['bot_agent'], 0, 149))
181                    {
182                        $error[] = $user->lang['ERR_BOT_AGENT_MATCHES_UA'];
183                    }
184
185                    $bot_name = false;
186                    if ($bot_id)
187                    {
188                        $sql = 'SELECT u.username_clean
189                            FROM ' . BOTS_TABLE . ' b, ' . USERS_TABLE . " u
190                            WHERE b.bot_id = $bot_id
191                                AND u.user_id = b.user_id";
192                        $result = $db->sql_query($sql);
193                        $row = $db->sql_fetchrow($result);
194                        $db->sql_freeresult($result);
195
196                        if (!$bot_row)
197                        {
198                            $error[] = $user->lang['NO_BOT'];
199                        }
200                        else
201                        {
202                            $bot_name = $row['username_clean'];
203                        }
204                    }
205                    if (!$this->validate_botname($bot_row['bot_name'], $bot_name))
206                    {
207                        $error[] = $user->lang['BOT_NAME_TAKEN'];
208                    }
209
210                    if (!count($error))
211                    {
212                        // New bot? Create a new user and group entry
213                        if ($action == 'add')
214                        {
215                            $sql = 'SELECT group_id, group_colour
216                                FROM ' . GROUPS_TABLE . "
217                                WHERE group_name = 'BOTS'
218                                    AND group_type = " . GROUP_SPECIAL;
219                            $result = $db->sql_query($sql);
220                            $group_row = $db->sql_fetchrow($result);
221                            $db->sql_freeresult($result);
222
223                            if (!$group_row)
224                            {
225                                trigger_error($user->lang['NO_BOT_GROUP'] . adm_back_link($this->u_action . "&amp;id=$bot_id&amp;action=$action"), E_USER_WARNING);
226                            }
227
228                            $user_id = user_add(array(
229                                'user_type'                => (int) USER_IGNORE,
230                                'group_id'                => (int) $group_row['group_id'],
231                                'username'                => (string) $bot_row['bot_name'],
232                                'user_regdate'            => time(),
233                                'user_password'            => '',
234                                'user_colour'            => (string) $group_row['group_colour'],
235                                'user_email'            => '',
236                                'user_lang'                => (string) $bot_row['bot_lang'],
237                                'user_style'            => (int) $bot_row['bot_style'],
238                                'user_allow_massemail'    => 0,
239                            ));
240
241                            $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
242                                'user_id'        => (int) $user_id,
243                                'bot_name'        => (string) $bot_row['bot_name'],
244                                'bot_active'    => (int) $bot_row['bot_active'],
245                                'bot_agent'        => (string) $bot_row['bot_agent'],
246                                'bot_ip'        => (string) $bot_row['bot_ip'])
247                            );
248                            $db->sql_query($sql);
249
250                            $log = 'ADDED';
251                        }
252                        else if ($bot_id)
253                        {
254                            $sql = 'SELECT user_id, bot_name
255                                FROM ' . BOTS_TABLE . "
256                                WHERE bot_id = $bot_id";
257                            $result = $db->sql_query($sql);
258                            $row = $db->sql_fetchrow($result);
259                            $db->sql_freeresult($result);
260
261                            if (!$row)
262                            {
263                                trigger_error($user->lang['NO_BOT'] . adm_back_link($this->u_action . "&amp;id=$bot_id&amp;action=$action"), E_USER_WARNING);
264                            }
265
266                            $sql_ary = array(
267                                'user_style'    => (int) $bot_row['bot_style'],
268                                'user_lang'        => (string) $bot_row['bot_lang'],
269                            );
270
271                            if ($bot_row['bot_name'] !== $row['bot_name'])
272                            {
273                                $sql_ary['username'] = (string) $bot_row['bot_name'];
274                                $sql_ary['username_clean'] = (string) utf8_clean_string($bot_row['bot_name']);
275                            }
276
277                            $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE user_id = {$row['user_id']}";
278                            $db->sql_query($sql);
279
280                            $sql = 'UPDATE ' . BOTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
281                                'bot_name'        => (string) $bot_row['bot_name'],
282                                'bot_active'    => (int) $bot_row['bot_active'],
283                                'bot_agent'        => (string) $bot_row['bot_agent'],
284                                'bot_ip'        => (string) $bot_row['bot_ip'])
285                            ) . " WHERE bot_id = $bot_id";
286                            $db->sql_query($sql);
287
288                            // Updated username?
289                            if ($bot_row['bot_name'] !== $row['bot_name'])
290                            {
291                                user_update_name($row['bot_name'], $bot_row['bot_name']);
292                            }
293
294                            $log = 'UPDATED';
295                        }
296
297                        $cache->destroy('_bots');
298
299                        $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BOT_' . $log, false, array($bot_row['bot_name']));
300                        trigger_error($user->lang['BOT_' . $log] . adm_back_link($this->u_action));
301
302                    }
303                }
304                else if ($bot_id)
305                {
306                    $sql = 'SELECT b.*, u.user_lang, u.user_style
307                        FROM ' . BOTS_TABLE . ' b, ' . USERS_TABLE . " u
308                        WHERE b.bot_id = $bot_id
309                            AND u.user_id = b.user_id";
310                    $result = $db->sql_query($sql);
311                    $bot_row = $db->sql_fetchrow($result);
312                    $db->sql_freeresult($result);
313
314                    if (!$bot_row)
315                    {
316                        trigger_error($user->lang['NO_BOT'] . adm_back_link($this->u_action . "&amp;id=$bot_id&amp;action=$action"), E_USER_WARNING);
317                    }
318
319                    $bot_row['bot_lang'] = $bot_row['user_lang'];
320                    $bot_row['bot_style'] = $bot_row['user_style'];
321                    unset($bot_row['user_lang'], $bot_row['user_style']);
322                }
323
324                $s_active_options = [];
325                $_options = array('0' => 'NO', '1' => 'YES');
326                foreach ($_options as $value => $lang)
327                {
328                    $s_active_options[] = [
329                        'value'     => $value,
330                        'selected'    => $bot_row['bot_active'] == $value,
331                        'label'        => $user->lang($lang),
332                    ];
333                }
334
335                $style_select = style_select($bot_row['bot_style'], true);
336                $lang_options = phpbb_language_select($db, $bot_row['bot_lang']);
337
338                $l_title = ($action == 'edit') ? 'EDIT' : 'ADD';
339
340                $template->assign_vars(array(
341                    'L_TITLE'        => $user->lang['BOT_' . $l_title],
342                    'U_ACTION'        => $this->u_action . "&amp;id=$bot_id&amp;action=$action",
343                    'U_BACK'        => $this->u_action,
344                    'ERROR_MSG'        => (count($error)) ? implode('<br />', $error) : '',
345
346                    'BOT_NAME'        => $bot_row['bot_name'],
347                    'BOT_IP'        => $bot_row['bot_ip'],
348                    'BOT_AGENT'        => $bot_row['bot_agent'],
349
350                    'S_EDIT_BOT'        => true,
351                    'S_ACTIVE_OPTIONS'    => [
352                        'id'        => 'bot_active',
353                        'name'        => 'bot_active',
354                        'options'    => $s_active_options,
355                    ],
356                    'S_STYLE_OPTIONS'    => [
357                        'id'        => 'bot_style',
358                        'name'        => 'bot_style',
359                        'options'    => $style_select,
360                    ],
361                    'LANG_OPTIONS'        => [
362                        'id'        => 'bot_lang',
363                        'name'        => 'bot_lang',
364                        'options'    => $lang_options,
365                    ],
366                    'S_ERROR'        => (bool) count($error),
367                ));
368
369                return;
370
371            break;
372        }
373
374        if ($request->is_ajax() && ($action == 'activate' || $action == 'deactivate'))
375        {
376            $json_response = new \phpbb\json_response;
377            $json_response->send(array(
378                'text'    => $user->lang['BOT_' . (($action == 'activate') ? 'DE' : '') . 'ACTIVATE'],
379            ));
380        }
381
382        $s_options = '';
383        $_options = array('activate' => 'BOT_ACTIVATE', 'deactivate' => 'BOT_DEACTIVATE', 'delete' => 'DELETE');
384        foreach ($_options as $value => $lang)
385        {
386            $s_options .= '<option value="' . $value . '">' . $user->lang[$lang] . '</option>';
387        }
388
389        $template->assign_vars(array(
390            'U_ACTION'        => $this->u_action,
391            'S_BOT_OPTIONS'    => $s_options)
392        );
393
394        $sql = 'SELECT b.bot_id, b.bot_name, b.bot_active, u.user_lastvisit
395            FROM ' . BOTS_TABLE . ' b, ' . USERS_TABLE . ' u
396            WHERE u.user_id = b.user_id
397            ORDER BY u.user_lastvisit DESC, b.bot_name ASC';
398        $result = $db->sql_query($sql);
399
400        while ($row = $db->sql_fetchrow($result))
401        {
402            $active_lang = (!$row['bot_active']) ? 'BOT_ACTIVATE' : 'BOT_DEACTIVATE';
403            $active_value = (!$row['bot_active']) ? 'activate' : 'deactivate';
404
405            $template->assign_block_vars('bots', array(
406                'BOT_NAME'        => $row['bot_name'],
407                'BOT_ID'        => $row['bot_id'],
408                'LAST_VISIT'    => ($row['user_lastvisit']) ? $user->format_date($row['user_lastvisit']) : $user->lang['BOT_NEVER'],
409
410                'U_ACTIVATE_DEACTIVATE'    => $this->u_action . "&amp;id={$row['bot_id']}&amp;action=$active_value",
411                'L_ACTIVATE_DEACTIVATE'    => $user->lang[$active_lang],
412                'U_EDIT'                => $this->u_action . "&amp;id={$row['bot_id']}&amp;action=edit",
413                'U_DELETE'                => $this->u_action . "&amp;id={$row['bot_id']}&amp;action=delete")
414            );
415        }
416        $db->sql_freeresult($result);
417    }
418
419    /**
420    * Validate bot name against username table
421    */
422    function validate_botname($newname, $oldname = false)
423    {
424        global $db;
425
426        if ($oldname && utf8_clean_string($newname) === $oldname)
427        {
428            return true;
429        }
430
431        // Admins might want to use names otherwise forbidden, thus we only check for duplicates.
432        $sql = 'SELECT username
433            FROM ' . USERS_TABLE . "
434            WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($newname)) . "'";
435        $result = $db->sql_query($sql);
436        $row = $db->sql_fetchrow($result);
437        $db->sql_freeresult($result);
438
439        return ($row) ? false : true;
440    }
441}