~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to www/php/phpBB3/includes/functions_user.php

  • Committer: William Grant
  • Date: 2009-02-23 23:47:02 UTC
  • mfrom: (1099.1.211 new-dispatch)
  • Revision ID: grantw@unimelb.edu.au-20090223234702-db4b1llly46ignwo
Merge from lp:~ivle-dev/ivle/new-dispatch.

Pretty much everything changes. Reread the setup docs. Backup your databases.
Every file is now in a different installed location, the configuration system
is rewritten, the dispatch system is rewritten, URLs are different, the
database is different, worksheets and exercises are no longer on the
filesystem, we use a templating engine, jail service protocols are rewritten,
we don't repeat ourselves, we have authorization rewritten, phpBB is gone,
and probably lots of other things that I cannot remember.

This is certainly the biggest commit I have ever made, and hopefully
the largest I ever will.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
/**
3
 
*
4
 
* @package phpBB3
5
 
* @version $Id: functions_user.php,v 1.242 2007/11/10 18:50:35 kellanved Exp $
6
 
* @copyright (c) 2005 phpBB Group
7
 
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8
 
*
9
 
*/
10
 
 
11
 
/**
12
 
* @ignore
13
 
*/
14
 
if (!defined('IN_PHPBB'))
15
 
{
16
 
        exit;
17
 
}
18
 
 
19
 
/**
20
 
* Obtain user_ids from usernames or vice versa. Returns false on
21
 
* success else the error string
22
 
*
23
 
* @param array &$user_id_ary The user ids to check or empty if usernames used
24
 
* @param array &$username_ary The usernames to check or empty if user ids used
25
 
* @param mixed $user_type Array of user types to check, false if not restricting by user type
26
 
*/
27
 
function user_get_id_name(&$user_id_ary, &$username_ary, $user_type = false)
28
 
{
29
 
        global $db;
30
 
 
31
 
        // Are both arrays already filled? Yep, return else
32
 
        // are neither array filled?
33
 
        if ($user_id_ary && $username_ary)
34
 
        {
35
 
                return false;
36
 
        }
37
 
        else if (!$user_id_ary && !$username_ary)
38
 
        {
39
 
                return 'NO_USERS';
40
 
        }
41
 
 
42
 
        $which_ary = ($user_id_ary) ? 'user_id_ary' : 'username_ary';
43
 
 
44
 
        if ($$which_ary && !is_array($$which_ary))
45
 
        {
46
 
                $$which_ary = array($$which_ary);
47
 
        }
48
 
 
49
 
        $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $$which_ary) : array_map('utf8_clean_string', $$which_ary);
50
 
        unset($$which_ary);
51
 
 
52
 
        $user_id_ary = $username_ary = array();
53
 
 
54
 
        // Grab the user id/username records
55
 
        $sql_where = ($which_ary == 'user_id_ary') ? 'user_id' : 'username_clean';
56
 
        $sql = 'SELECT user_id, username
57
 
                FROM ' . USERS_TABLE . '
58
 
                WHERE ' . $db->sql_in_set($sql_where, $sql_in);
59
 
 
60
 
        if ($user_type !== false && !empty($user_type))
61
 
        {
62
 
                $sql .= ' AND ' . $db->sql_in_set('user_type', $user_type);
63
 
        }
64
 
 
65
 
        $result = $db->sql_query($sql);
66
 
 
67
 
        if (!($row = $db->sql_fetchrow($result)))
68
 
        {
69
 
                $db->sql_freeresult($result);
70
 
                return 'NO_USERS';
71
 
        }
72
 
 
73
 
        do
74
 
        {
75
 
                $username_ary[$row['user_id']] = $row['username'];
76
 
                $user_id_ary[] = $row['user_id'];
77
 
        }
78
 
        while ($row = $db->sql_fetchrow($result));
79
 
        $db->sql_freeresult($result);
80
 
 
81
 
        return false;
82
 
}
83
 
 
84
 
/**
85
 
* Get latest registered username and update database to reflect it
86
 
*/
87
 
function update_last_username()
88
 
{
89
 
        global $db;
90
 
 
91
 
        // Get latest username
92
 
        $sql = 'SELECT user_id, username, user_colour
93
 
                FROM ' . USERS_TABLE . '
94
 
                WHERE user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')
95
 
                ORDER BY user_id DESC';
96
 
        $result = $db->sql_query_limit($sql, 1);
97
 
        $row = $db->sql_fetchrow($result);
98
 
        $db->sql_freeresult($result);
99
 
 
100
 
        if ($row)
101
 
        {
102
 
                set_config('newest_user_id', $row['user_id'], true);
103
 
                set_config('newest_username', $row['username'], true);
104
 
                set_config('newest_user_colour', $row['user_colour'], true);
105
 
        }
106
 
}
107
 
 
108
 
/**
109
 
* Updates a username across all relevant tables/fields
110
 
*
111
 
* @param string $old_name the old/current username
112
 
* @param string $new_name the new username
113
 
*/
114
 
function user_update_name($old_name, $new_name)
115
 
{
116
 
        global $config, $db, $cache;
117
 
 
118
 
        $update_ary = array(
119
 
                FORUMS_TABLE                    => array('forum_last_poster_name'),
120
 
                MODERATOR_CACHE_TABLE   => array('username'),
121
 
                POSTS_TABLE                             => array('post_username'),
122
 
                TOPICS_TABLE                    => array('topic_first_poster_name', 'topic_last_poster_name'),
123
 
        );
124
 
 
125
 
        foreach ($update_ary as $table => $field_ary)
126
 
        {
127
 
                foreach ($field_ary as $field)
128
 
                {
129
 
                        $sql = "UPDATE $table
130
 
                                SET $field = '" . $db->sql_escape($new_name) . "'
131
 
                                WHERE $field = '" . $db->sql_escape($old_name) . "'";
132
 
                        $db->sql_query($sql);
133
 
                }
134
 
        }
135
 
 
136
 
        if ($config['newest_username'] == $old_name)
137
 
        {
138
 
                set_config('newest_username', $new_name, true);
139
 
        }
140
 
}
141
 
 
142
 
/**
143
 
* Add User
144
 
*/
145
 
function user_add($user_row, $cp_data = false)
146
 
{
147
 
        global $db, $user, $auth, $config, $phpbb_root_path, $phpEx;
148
 
 
149
 
        if (empty($user_row['username']) || !isset($user_row['group_id']) || !isset($user_row['user_email']) || !isset($user_row['user_type']))
150
 
        {
151
 
                return false;
152
 
        }
153
 
 
154
 
        $username_clean = utf8_clean_string($user_row['username']);
155
 
 
156
 
        if (empty($username_clean))
157
 
        {
158
 
                return false;
159
 
        }
160
 
 
161
 
        $sql_ary = array(
162
 
                'username'                      => $user_row['username'],
163
 
                'username_clean'        => $username_clean,
164
 
                'user_password'         => (isset($user_row['user_password'])) ? $user_row['user_password'] : '',
165
 
                'user_pass_convert'     => 0,
166
 
                'user_email'            => strtolower($user_row['user_email']),
167
 
                'user_email_hash'       => crc32(strtolower($user_row['user_email'])) . strlen($user_row['user_email']),
168
 
                'group_id'                      => $user_row['group_id'],
169
 
                'user_type'                     => $user_row['user_type'],
170
 
        );
171
 
 
172
 
        // These are the additional vars able to be specified
173
 
        $additional_vars = array(
174
 
                'user_permissions'      => '',
175
 
                'user_timezone'         => $config['board_timezone'],
176
 
                'user_dateformat'       => $config['default_dateformat'],
177
 
                'user_lang'                     => $config['default_lang'],
178
 
                'user_style'            => $config['default_style'],
179
 
                'user_allow_pm'         => 1,
180
 
                'user_actkey'           => '',
181
 
                'user_ip'                       => '',
182
 
                'user_regdate'          => time(),
183
 
                'user_passchg'          => time(),
184
 
                'user_options'          => 895,
185
 
 
186
 
                'user_inactive_reason'  => 0,
187
 
                'user_inactive_time'    => 0,
188
 
                'user_lastmark'                 => time(),
189
 
                'user_lastvisit'                => 0,
190
 
                'user_lastpost_time'    => 0,
191
 
                'user_lastpage'                 => '',
192
 
                'user_posts'                    => 0,
193
 
                'user_dst'                              => (int) $config['board_dst'],
194
 
                'user_colour'                   => '',
195
 
                'user_occ'                              => '',
196
 
                'user_interests'                => '',
197
 
                'user_avatar'                   => '',
198
 
                'user_avatar_type'              => 0,
199
 
                'user_avatar_width'             => 0,
200
 
                'user_avatar_height'    => 0,
201
 
                'user_new_privmsg'              => 0,
202
 
                'user_unread_privmsg'   => 0,
203
 
                'user_last_privmsg'             => 0,
204
 
                'user_message_rules'    => 0,
205
 
                'user_full_folder'              => PRIVMSGS_NO_BOX,
206
 
                'user_emailtime'                => 0,
207
 
 
208
 
                'user_notify'                   => 0,
209
 
                'user_notify_pm'                => 1,
210
 
                'user_notify_type'              => NOTIFY_EMAIL,
211
 
                'user_allow_pm'                 => 1,
212
 
                'user_allow_viewonline' => 1,
213
 
                'user_allow_viewemail'  => 1,
214
 
                'user_allow_massemail'  => 1,
215
 
 
216
 
                'user_sig'                                      => '',
217
 
                'user_sig_bbcode_uid'           => '',
218
 
                'user_sig_bbcode_bitfield'      => '',
219
 
                
220
 
                'user_form_salt'                        => unique_id(),
221
 
        );
222
 
 
223
 
        // Now fill the sql array with not required variables
224
 
        foreach ($additional_vars as $key => $default_value)
225
 
        {
226
 
                $sql_ary[$key] = (isset($user_row[$key])) ? $user_row[$key] : $default_value;
227
 
        }
228
 
 
229
 
        // Any additional variables in $user_row not covered above?
230
 
        $remaining_vars = array_diff(array_keys($user_row), array_keys($sql_ary));
231
 
 
232
 
        // Now fill our sql array with the remaining vars
233
 
        if (sizeof($remaining_vars))
234
 
        {
235
 
                foreach ($remaining_vars as $key)
236
 
                {
237
 
                        $sql_ary[$key] = $user_row[$key];
238
 
                }
239
 
        }
240
 
 
241
 
        $sql = 'INSERT INTO ' . USERS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
242
 
        $db->sql_query($sql);
243
 
 
244
 
        $user_id = $db->sql_nextid();
245
 
 
246
 
        // Insert Custom Profile Fields
247
 
        if ($cp_data !== false && sizeof($cp_data))
248
 
        {
249
 
                $cp_data['user_id'] = (int) $user_id;
250
 
 
251
 
                if (!class_exists('custom_profile'))
252
 
                {
253
 
                        include_once($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx);
254
 
                }
255
 
 
256
 
                $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' .
257
 
                        $db->sql_build_array('INSERT', custom_profile::build_insert_sql_array($cp_data));
258
 
                $db->sql_query($sql);
259
 
        }
260
 
 
261
 
        // Place into appropriate group...
262
 
        $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' ' . $db->sql_build_array('INSERT', array(
263
 
                'user_id'               => (int) $user_id,
264
 
                'group_id'              => (int) $user_row['group_id'],
265
 
                'user_pending'  => 0)
266
 
        );
267
 
        $db->sql_query($sql);
268
 
 
269
 
        // Now make it the users default group...
270
 
        group_set_user_default($user_row['group_id'], array($user_id), false);
271
 
 
272
 
        // set the newest user and adjust the user count if the user is a normal user and no activation mail is sent
273
 
        if ($user_row['user_type'] == USER_NORMAL)
274
 
        {
275
 
                set_config('newest_user_id', $user_id, true);
276
 
                set_config('newest_username', $user_row['username'], true);
277
 
                set_config('num_users', $config['num_users'] + 1, true);
278
 
 
279
 
                $sql = 'SELECT group_colour
280
 
                        FROM ' . GROUPS_TABLE . '
281
 
                        WHERE group_id = ' . $user_row['group_id'];
282
 
                $result = $db->sql_query_limit($sql, 1);
283
 
                $row = $db->sql_fetchrow($result);
284
 
                $db->sql_freeresult($result);
285
 
 
286
 
                set_config('newest_user_colour', $row['group_colour'], true);
287
 
        }
288
 
 
289
 
        return $user_id;
290
 
}
291
 
 
292
 
/**
293
 
* Remove User
294
 
*/
295
 
function user_delete($mode, $user_id, $post_username = false)
296
 
{
297
 
        global $cache, $config, $db, $user, $auth;
298
 
        global $phpbb_root_path, $phpEx;
299
 
 
300
 
        $sql = 'SELECT *
301
 
                FROM ' . USERS_TABLE . '
302
 
                WHERE user_id = ' . $user_id;
303
 
        $result = $db->sql_query($sql);
304
 
        $user_row = $db->sql_fetchrow($result);
305
 
        $db->sql_freeresult($result);
306
 
 
307
 
        if (!$user_row)
308
 
        {
309
 
                return false;
310
 
        }
311
 
 
312
 
        $db->sql_transaction('begin');
313
 
 
314
 
        // Before we begin, we will remove the reports the user issued.
315
 
        $sql = 'SELECT r.post_id, p.topic_id
316
 
                FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p
317
 
                WHERE r.user_id = ' . $user_id . '
318
 
                        AND p.post_id = r.post_id';
319
 
        $result = $db->sql_query($sql);
320
 
 
321
 
        $report_posts = $report_topics = array();
322
 
        while ($row = $db->sql_fetchrow($result))
323
 
        {
324
 
                $report_posts[] = $row['post_id'];
325
 
                $report_topics[] = $row['topic_id'];
326
 
        }
327
 
        $db->sql_freeresult($result);
328
 
 
329
 
        if (sizeof($report_posts))
330
 
        {
331
 
                $report_posts = array_unique($report_posts);
332
 
                $report_topics = array_unique($report_topics);
333
 
 
334
 
                // Get a list of topics that still contain reported posts
335
 
                $sql = 'SELECT DISTINCT topic_id
336
 
                        FROM ' . POSTS_TABLE . '
337
 
                        WHERE ' . $db->sql_in_set('topic_id', $report_topics) . '
338
 
                                AND post_reported = 1
339
 
                                AND ' . $db->sql_in_set('post_id', $report_posts, true);
340
 
                $result = $db->sql_query($sql);
341
 
 
342
 
                $keep_report_topics = array();
343
 
                while ($row = $db->sql_fetchrow($result))
344
 
                {
345
 
                        $keep_report_topics[] = $row['topic_id'];
346
 
                }
347
 
                $db->sql_freeresult($result);
348
 
 
349
 
                if (sizeof($keep_report_topics))
350
 
                {
351
 
                        $report_topics = array_diff($report_topics, $keep_report_topics);
352
 
                }
353
 
                unset($keep_report_topics);
354
 
 
355
 
                // Now set the flags back
356
 
                $sql = 'UPDATE ' . POSTS_TABLE . '
357
 
                        SET post_reported = 0
358
 
                        WHERE ' . $db->sql_in_set('post_id', $report_posts);
359
 
                $db->sql_query($sql);
360
 
 
361
 
                if (sizeof($report_topics))
362
 
                {
363
 
                        $sql = 'UPDATE ' . TOPICS_TABLE . '
364
 
                                SET topic_reported = 0
365
 
                                WHERE ' . $db->sql_in_set('topic_id', $report_topics);
366
 
                        $db->sql_query($sql);
367
 
                }
368
 
        }
369
 
 
370
 
        // Remove reports
371
 
        $db->sql_query('DELETE FROM ' . REPORTS_TABLE . ' WHERE user_id = ' . $user_id);
372
 
 
373
 
        if ($user_row['user_avatar'] && $user_row['user_avatar_type'] == AVATAR_UPLOAD)
374
 
        {
375
 
                avatar_delete('user', $user_row);
376
 
        }
377
 
        
378
 
        switch ($mode)
379
 
        {
380
 
                case 'retain':
381
 
 
382
 
                        if ($post_username === false)
383
 
                        {
384
 
                                $post_username = $user->lang['GUEST'];
385
 
                        }
386
 
 
387
 
                        // If the user is inactive and newly registered we assume no posts from this user being there...
388
 
                        if ($user_row['user_type'] == USER_INACTIVE && $user_row['user_inactive_reason'] == INACTIVE_REGISTER && !$user_row['user_posts'])
389
 
                        {
390
 
                        }
391
 
                        else
392
 
                        {
393
 
                                $sql = 'UPDATE ' . FORUMS_TABLE . '
394
 
                                        SET forum_last_poster_id = ' . ANONYMOUS . ", forum_last_poster_name = '" . $db->sql_escape($post_username) . "', forum_last_poster_colour = ''
395
 
                                        WHERE forum_last_poster_id = $user_id";
396
 
                                $db->sql_query($sql);
397
 
 
398
 
                                $sql = 'UPDATE ' . POSTS_TABLE . '
399
 
                                        SET poster_id = ' . ANONYMOUS . ", post_username = '" . $db->sql_escape($post_username) . "'
400
 
                                        WHERE poster_id = $user_id";
401
 
                                $db->sql_query($sql);
402
 
 
403
 
                                $sql = 'UPDATE ' . POSTS_TABLE . '
404
 
                                        SET post_edit_user = ' . ANONYMOUS . "
405
 
                                        WHERE post_edit_user = $user_id";
406
 
                                $db->sql_query($sql);
407
 
 
408
 
                                $sql = 'UPDATE ' . TOPICS_TABLE . '
409
 
                                        SET topic_poster = ' . ANONYMOUS . ", topic_first_poster_name = '" . $db->sql_escape($post_username) . "', topic_first_poster_colour = ''
410
 
                                        WHERE topic_poster = $user_id";
411
 
                                $db->sql_query($sql);
412
 
 
413
 
                                $sql = 'UPDATE ' . TOPICS_TABLE . '
414
 
                                        SET topic_last_poster_id = ' . ANONYMOUS . ", topic_last_poster_name = '" . $db->sql_escape($post_username) . "', topic_last_poster_colour = ''
415
 
                                        WHERE topic_last_poster_id = $user_id";
416
 
                                $db->sql_query($sql);
417
 
 
418
 
                                // Since we change every post by this author, we need to count this amount towards the anonymous user
419
 
 
420
 
                                // Update the post count for the anonymous user
421
 
                                if ($user_row['user_posts'])
422
 
                                {
423
 
                                        $sql = 'UPDATE ' . USERS_TABLE . '
424
 
                                                SET user_posts = user_posts + ' . $user_row['user_posts'] . '
425
 
                                                WHERE user_id = ' . ANONYMOUS;
426
 
                                        $db->sql_query($sql);
427
 
                                }
428
 
                        }
429
 
                break;
430
 
 
431
 
                case 'remove':
432
 
 
433
 
                        if (!function_exists('delete_posts'))
434
 
                        {
435
 
                                include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
436
 
                        }
437
 
 
438
 
                        $sql = 'SELECT topic_id, COUNT(post_id) AS total_posts
439
 
                                FROM ' . POSTS_TABLE . "
440
 
                                WHERE poster_id = $user_id
441
 
                                GROUP BY topic_id";
442
 
                        $result = $db->sql_query($sql);
443
 
 
444
 
                        $topic_id_ary = array();
445
 
                        while ($row = $db->sql_fetchrow($result))
446
 
                        {
447
 
                                $topic_id_ary[$row['topic_id']] = $row['total_posts'];
448
 
                        }
449
 
                        $db->sql_freeresult($result);
450
 
 
451
 
                        if (sizeof($topic_id_ary))
452
 
                        {
453
 
                                $sql = 'SELECT topic_id, topic_replies, topic_replies_real
454
 
                                        FROM ' . TOPICS_TABLE . '
455
 
                                        WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary));
456
 
                                $result = $db->sql_query($sql);
457
 
 
458
 
                                $del_topic_ary = array();
459
 
                                while ($row = $db->sql_fetchrow($result))
460
 
                                {
461
 
                                        if (max($row['topic_replies'], $row['topic_replies_real']) + 1 == $topic_id_ary[$row['topic_id']])
462
 
                                        {
463
 
                                                $del_topic_ary[] = $row['topic_id'];
464
 
                                        }
465
 
                                }
466
 
                                $db->sql_freeresult($result);
467
 
 
468
 
                                if (sizeof($del_topic_ary))
469
 
                                {
470
 
                                        $sql = 'DELETE FROM ' . TOPICS_TABLE . '
471
 
                                                WHERE ' . $db->sql_in_set('topic_id', $del_topic_ary);
472
 
                                        $db->sql_query($sql);
473
 
                                }
474
 
                        }
475
 
 
476
 
                        // Delete posts, attachments, etc.
477
 
                        delete_posts('poster_id', $user_id);
478
 
 
479
 
                break;
480
 
        }
481
 
 
482
 
        $table_ary = array(USERS_TABLE, USER_GROUP_TABLE, TOPICS_WATCH_TABLE, FORUMS_WATCH_TABLE, ACL_USERS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, FORUMS_TRACK_TABLE, PROFILE_FIELDS_DATA_TABLE, MODERATOR_CACHE_TABLE);
483
 
 
484
 
        foreach ($table_ary as $table)
485
 
        {
486
 
                $sql = "DELETE FROM $table
487
 
                        WHERE user_id = $user_id";
488
 
                $db->sql_query($sql);
489
 
        }
490
 
 
491
 
        $cache->destroy('sql', MODERATOR_CACHE_TABLE);
492
 
 
493
 
        // Remove any undelivered mails...
494
 
        $sql = 'SELECT msg_id, user_id
495
 
                FROM ' . PRIVMSGS_TO_TABLE . '
496
 
                WHERE author_id = ' . $user_id . '
497
 
                        AND folder_id = ' . PRIVMSGS_NO_BOX;
498
 
        $result = $db->sql_query($sql);
499
 
 
500
 
        $undelivered_msg = $undelivered_user = array();
501
 
        while ($row = $db->sql_fetchrow($result))
502
 
        {
503
 
                $undelivered_msg[] = $row['msg_id'];
504
 
                $undelivered_user[$row['user_id']][] = true;
505
 
        }
506
 
        $db->sql_freeresult($result);
507
 
 
508
 
        if (sizeof($undelivered_msg))
509
 
        {
510
 
                $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
511
 
                        WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg);
512
 
                $db->sql_query($sql);
513
 
        }
514
 
 
515
 
        $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . '
516
 
                WHERE author_id = ' . $user_id . '
517
 
                        AND folder_id = ' . PRIVMSGS_NO_BOX;
518
 
        $db->sql_query($sql);
519
 
 
520
 
        // Delete all to-information
521
 
        $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . '
522
 
                WHERE user_id = ' . $user_id;
523
 
        $db->sql_query($sql);
524
 
 
525
 
        // Set the remaining author id to anonymous - this way users are still able to read messages from users being removed
526
 
        $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
527
 
                SET author_id = ' . ANONYMOUS . '
528
 
                WHERE author_id = ' . $user_id;
529
 
        $db->sql_query($sql);
530
 
 
531
 
        $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
532
 
                SET author_id = ' . ANONYMOUS . '
533
 
                WHERE author_id = ' . $user_id;
534
 
        $db->sql_query($sql);
535
 
 
536
 
        foreach ($undelivered_user as $_user_id => $ary)
537
 
        {
538
 
                if ($_user_id == $user_id)
539
 
                {
540
 
                        continue;
541
 
                }
542
 
 
543
 
                $sql = 'UPDATE ' . USERS_TABLE . '
544
 
                        SET user_new_privmsg = user_new_privmsg - ' . sizeof($ary) . ',
545
 
                                user_unread_privmsg = user_unread_privmsg - ' . sizeof($ary) . '
546
 
                        WHERE user_id = ' . $_user_id;
547
 
                $db->sql_query($sql);
548
 
        }
549
 
 
550
 
        // Reset newest user info if appropriate
551
 
        if ($config['newest_user_id'] == $user_id)
552
 
        {
553
 
                update_last_username();
554
 
        }
555
 
 
556
 
        // Decrement number of users if this user is active
557
 
        if ($user_row['user_type'] != USER_INACTIVE && $user_row['user_type'] != USER_IGNORE)
558
 
        {
559
 
                set_config('num_users', $config['num_users'] - 1, true);
560
 
        }
561
 
 
562
 
        $db->sql_transaction('commit');
563
 
 
564
 
        return false;
565
 
}
566
 
 
567
 
/**
568
 
* Flips user_type from active to inactive and vice versa, handles group membership updates
569
 
*
570
 
* @param string $mode can be flip for flipping from active/inactive, activate or deactivate
571
 
*/
572
 
function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL)
573
 
{
574
 
        global $config, $db, $user, $auth;
575
 
 
576
 
        $deactivated = $activated = 0;
577
 
        $sql_statements = array();
578
 
 
579
 
        if (!is_array($user_id_ary))
580
 
        {
581
 
                $user_id_ary = array($user_id_ary);
582
 
        }
583
 
 
584
 
        if (!sizeof($user_id_ary))
585
 
        {
586
 
                return;
587
 
        }
588
 
 
589
 
        $sql = 'SELECT user_id, group_id, user_type, user_inactive_reason
590
 
                FROM ' . USERS_TABLE . '
591
 
                WHERE ' . $db->sql_in_set('user_id', $user_id_ary);
592
 
        $result = $db->sql_query($sql);
593
 
 
594
 
        while ($row = $db->sql_fetchrow($result))
595
 
        {
596
 
                $sql_ary = array();
597
 
 
598
 
                if ($row['user_type'] == USER_IGNORE || $row['user_type'] == USER_FOUNDER ||
599
 
                        ($mode == 'activate' && $row['user_type'] != USER_INACTIVE) ||
600
 
                        ($mode == 'deactivate' && $row['user_type'] == USER_INACTIVE))
601
 
                {
602
 
                        continue;
603
 
                }
604
 
 
605
 
                if ($row['user_type'] == USER_INACTIVE)
606
 
                {
607
 
                        $activated++;
608
 
                }
609
 
                else
610
 
                {
611
 
                        $deactivated++;
612
 
 
613
 
                        // Remove the users session key...
614
 
                        $user->reset_login_keys($row['user_id']);
615
 
                }
616
 
 
617
 
                $sql_ary += array(
618
 
                        'user_type'                             => ($row['user_type'] == USER_NORMAL) ? USER_INACTIVE : USER_NORMAL,
619
 
                        'user_inactive_time'    => ($row['user_type'] == USER_NORMAL) ? time() : 0,
620
 
                        'user_inactive_reason'  => ($row['user_type'] == USER_NORMAL) ? $reason : 0,
621
 
                );
622
 
 
623
 
                $sql_statements[$row['user_id']] = $sql_ary;
624
 
        }
625
 
        $db->sql_freeresult($result);
626
 
 
627
 
        if (sizeof($sql_statements))
628
 
        {
629
 
                foreach ($sql_statements as $user_id => $sql_ary)
630
 
                {
631
 
                        $sql = 'UPDATE ' . USERS_TABLE . '
632
 
                                SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
633
 
                                WHERE user_id = ' . $user_id;
634
 
                        $db->sql_query($sql);
635
 
                }
636
 
 
637
 
                $auth->acl_clear_prefetch(array_keys($sql_statements));
638
 
        }
639
 
 
640
 
        if ($deactivated)
641
 
        {
642
 
                set_config('num_users', $config['num_users'] - $deactivated, true);
643
 
        }
644
 
 
645
 
        if ($activated)
646
 
        {
647
 
                set_config('num_users', $config['num_users'] + $activated, true);
648
 
        }
649
 
 
650
 
        // Update latest username
651
 
        update_last_username();
652
 
}
653
 
 
654
 
/**
655
 
* Add a ban or ban exclusion to the banlist. Bans either a user, an IP or an email address
656
 
*
657
 
* @param string $mode Type of ban. One of the following: user, ip, email
658
 
* @param mixed $ban Banned entity. Either string or array with usernames, ips or email addresses
659
 
* @param int $ban_len Ban length in minutes
660
 
* @param string $ban_len_other Ban length as a date (YYYY-MM-DD)
661
 
* @param boolean $ban_exclude Exclude these entities from banning?
662
 
* @param string $ban_reason String describing the reason for this ban
663
 
* @return boolean
664
 
*/
665
 
function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason = '')
666
 
{
667
 
        global $db, $user, $auth, $cache;
668
 
 
669
 
        // Delete stale bans
670
 
        $sql = 'DELETE FROM ' . BANLIST_TABLE . '
671
 
                WHERE ban_end < ' . time() . '
672
 
                        AND ban_end <> 0';
673
 
        $db->sql_query($sql);
674
 
 
675
 
        $ban_list = (!is_array($ban)) ? array_unique(explode("\n", $ban)) : $ban;
676
 
        $ban_list_log = implode(', ', $ban_list);
677
 
 
678
 
        $current_time = time();
679
 
 
680
 
        // Set $ban_end to the unix time when the ban should end. 0 is a permanent ban.
681
 
        if ($ban_len)
682
 
        {
683
 
                if ($ban_len != -1 || !$ban_len_other)
684
 
                {
685
 
                        $ban_end = max($current_time, $current_time + ($ban_len) * 60);
686
 
                }
687
 
                else
688
 
                {
689
 
                        $ban_other = explode('-', $ban_len_other);
690
 
                        if (sizeof($ban_other) == 3 && ((int)$ban_other[0] < 9999) &&
691
 
                                (strlen($ban_other[0]) == 4) && (strlen($ban_other[1]) == 2) && (strlen($ban_other[2]) == 2))
692
 
                        {
693
 
                                $ban_end = max($current_time, gmmktime(0, 0, 0, (int)$ban_other[1], (int)$ban_other[2], (int)$ban_other[0]));
694
 
                        }
695
 
                        else
696
 
                        {
697
 
                                trigger_error('LENGTH_BAN_INVALID');
698
 
                        }
699
 
                }
700
 
        }
701
 
        else
702
 
        {
703
 
                $ban_end = 0;
704
 
        }
705
 
 
706
 
        $founder = $founder_names = array();
707
 
 
708
 
        if (!$ban_exclude)
709
 
        {
710
 
                // Create a list of founder...
711
 
                $sql = 'SELECT user_id, user_email, username_clean
712
 
                        FROM ' . USERS_TABLE . '
713
 
                        WHERE user_type = ' . USER_FOUNDER;
714
 
                $result = $db->sql_query($sql);
715
 
 
716
 
                while ($row = $db->sql_fetchrow($result))
717
 
                {
718
 
                        $founder[$row['user_id']] = $row['user_email'];
719
 
                        $founder_names[$row['user_id']] = $row['username_clean'];
720
 
                }
721
 
                $db->sql_freeresult($result);
722
 
        }
723
 
 
724
 
        $banlist_ary = array();
725
 
 
726
 
        switch ($mode)
727
 
        {
728
 
                case 'user':
729
 
                        $type = 'ban_userid';
730
 
 
731
 
                        if (in_array('*', $ban_list))
732
 
                        {
733
 
                                // Ban all users (it's a good thing that you can exclude people)
734
 
                                $banlist_ary[] = '*';
735
 
                        }
736
 
                        else
737
 
                        {
738
 
                                // Select the relevant user_ids.
739
 
                                $sql_usernames = array();
740
 
 
741
 
                                foreach ($ban_list as $username)
742
 
                                {
743
 
                                        $username = trim($username);
744
 
                                        if ($username != '')
745
 
                                        {
746
 
                                                $clean_name = utf8_clean_string($username);
747
 
                                                if ($clean_name == $user->data['username_clean'])
748
 
                                                {
749
 
                                                        trigger_error('CANNOT_BAN_YOURSELF', E_USER_WARNING);
750
 
                                                }
751
 
                                                if (in_array($clean_name, $founder_names))
752
 
                                                {
753
 
                                                        trigger_error('CANNOT_BAN_FOUNDER', E_USER_WARNING);
754
 
                                                }
755
 
                                                $sql_usernames[] = $clean_name;
756
 
                                        }
757
 
                                }
758
 
 
759
 
                                // Make sure we have been given someone to ban
760
 
                                if (!sizeof($sql_usernames))
761
 
                                {
762
 
                                        trigger_error('NO_USER_SPECIFIED');
763
 
                                }
764
 
 
765
 
                                $sql = 'SELECT user_id
766
 
                                        FROM ' . USERS_TABLE . '
767
 
                                        WHERE ' . $db->sql_in_set('username_clean', $sql_usernames);
768
 
 
769
 
                                // Do not allow banning yourself
770
 
                                if (sizeof($founder))
771
 
                                {
772
 
                                        $sql .= ' AND ' . $db->sql_in_set('user_id', array_merge(array_keys($founder), array($user->data['user_id'])), true);
773
 
                                }
774
 
                                else
775
 
                                {
776
 
                                        $sql .= ' AND user_id <> ' . $user->data['user_id'];
777
 
                                }
778
 
 
779
 
                                $result = $db->sql_query($sql);
780
 
 
781
 
                                if ($row = $db->sql_fetchrow($result))
782
 
                                {
783
 
                                        do
784
 
                                        {
785
 
                                                $banlist_ary[] = (int) $row['user_id'];
786
 
                                        }
787
 
                                        while ($row = $db->sql_fetchrow($result));
788
 
                                }
789
 
                                else
790
 
                                {
791
 
                                        trigger_error('NO_USERS');
792
 
                                }
793
 
                                $db->sql_freeresult($result);
794
 
                        }
795
 
                break;
796
 
 
797
 
                case 'ip':
798
 
                        $type = 'ban_ip';
799
 
 
800
 
                        foreach ($ban_list as $ban_item)
801
 
                        {
802
 
                                if (preg_match('#^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})[ ]*\-[ ]*([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$#', trim($ban_item), $ip_range_explode))
803
 
                                {
804
 
                                        // This is an IP range
805
 
                                        // Don't ask about all this, just don't ask ... !
806
 
                                        $ip_1_counter = $ip_range_explode[1];
807
 
                                        $ip_1_end = $ip_range_explode[5];
808
 
 
809
 
                                        while ($ip_1_counter <= $ip_1_end)
810
 
                                        {
811
 
                                                $ip_2_counter = ($ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[2] : 0;
812
 
                                                $ip_2_end = ($ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[6];
813
 
 
814
 
                                                if ($ip_2_counter == 0 && $ip_2_end == 254)
815
 
                                                {
816
 
                                                        $ip_2_counter = 256;
817
 
                                                        $ip_2_fragment = 256;
818
 
 
819
 
                                                        $banlist_ary[] = "$ip_1_counter.*";
820
 
                                                }
821
 
 
822
 
                                                while ($ip_2_counter <= $ip_2_end)
823
 
                                                {
824
 
                                                        $ip_3_counter = ($ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[3] : 0;
825
 
                                                        $ip_3_end = ($ip_2_counter < $ip_2_end || $ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[7];
826
 
 
827
 
                                                        if ($ip_3_counter == 0 && $ip_3_end == 254)
828
 
                                                        {
829
 
                                                                $ip_3_counter = 256;
830
 
                                                                $ip_3_fragment = 256;
831
 
 
832
 
                                                                $banlist_ary[] = "$ip_1_counter.$ip_2_counter.*";
833
 
                                                        }
834
 
 
835
 
                                                        while ($ip_3_counter <= $ip_3_end)
836
 
                                                        {
837
 
                                                                $ip_4_counter = ($ip_3_counter == $ip_range_explode[3] && $ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[4] : 0;
838
 
                                                                $ip_4_end = ($ip_3_counter < $ip_3_end || $ip_2_counter < $ip_2_end) ? 254 : $ip_range_explode[8];
839
 
 
840
 
                                                                if ($ip_4_counter == 0 && $ip_4_end == 254)
841
 
                                                                {
842
 
                                                                        $ip_4_counter = 256;
843
 
                                                                        $ip_4_fragment = 256;
844
 
 
845
 
                                                                        $banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.*";
846
 
                                                                }
847
 
 
848
 
                                                                while ($ip_4_counter <= $ip_4_end)
849
 
                                                                {
850
 
                                                                        $banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.$ip_4_counter";
851
 
                                                                        $ip_4_counter++;
852
 
                                                                }
853
 
                                                                $ip_3_counter++;
854
 
                                                        }
855
 
                                                        $ip_2_counter++;
856
 
                                                }
857
 
                                                $ip_1_counter++;
858
 
                                        }
859
 
                                }
860
 
                                else if (preg_match('#^([0-9]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})$#', trim($ban_item)) || preg_match('#^[a-f0-9:]+\*?$#i', trim($ban_item)))
861
 
                                {
862
 
                                        // Normal IP address
863
 
                                        $banlist_ary[] = trim($ban_item);
864
 
                                }
865
 
                                else if (preg_match('#^\*$#', trim($ban_item)))
866
 
                                {
867
 
                                        // Ban all IPs
868
 
                                        $banlist_ary[] = '*';
869
 
                                }
870
 
                                else if (preg_match('#^([\w\-_]\.?){2,}$#is', trim($ban_item)))
871
 
                                {
872
 
                                        // hostname
873
 
                                        $ip_ary = gethostbynamel(trim($ban_item));
874
 
 
875
 
                                        if (!empty($ip_ary))
876
 
                                        {
877
 
                                                foreach ($ip_ary as $ip)
878
 
                                                {
879
 
                                                        if ($ip)
880
 
                                                        {
881
 
                                                                if (strlen($ip) > 40)
882
 
                                                                {
883
 
                                                                        continue;
884
 
                                                                }
885
 
 
886
 
                                                                $banlist_ary[] = $ip;
887
 
                                                        }
888
 
                                                }
889
 
                                        }
890
 
                                }
891
 
                                else
892
 
                                {
893
 
                                        trigger_error('NO_IPS_DEFINED');
894
 
                                }
895
 
                        }
896
 
                break;
897
 
 
898
 
                case 'email':
899
 
                        $type = 'ban_email';
900
 
 
901
 
                        foreach ($ban_list as $ban_item)
902
 
                        {
903
 
                                $ban_item = trim($ban_item);
904
 
 
905
 
                                if (preg_match('#^.*?@*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i', $ban_item))
906
 
                                {
907
 
                                        if (strlen($ban_item) > 100)
908
 
                                        {
909
 
                                                continue;
910
 
                                        }
911
 
 
912
 
                                        if (!sizeof($founder) || !in_array($ban_item, $founder))
913
 
                                        {
914
 
                                                $banlist_ary[] = $ban_item;
915
 
                                        }
916
 
                                }
917
 
                        }
918
 
 
919
 
                        if (sizeof($ban_list) == 0)
920
 
                        {
921
 
                                trigger_error('NO_EMAILS_DEFINED');
922
 
                        }
923
 
                break;
924
 
 
925
 
                default:
926
 
                        trigger_error('NO_MODE');
927
 
                break;
928
 
        }
929
 
 
930
 
        // Fetch currently set bans of the specified type and exclude state. Prevent duplicate bans.
931
 
        $sql_where = ($type == 'ban_userid') ? 'ban_userid <> 0' : "$type <> ''";
932
 
 
933
 
        $sql = "SELECT $type
934
 
                FROM " . BANLIST_TABLE . "
935
 
                WHERE $sql_where
936
 
                        AND ban_exclude = $ban_exclude";
937
 
        $result = $db->sql_query($sql);
938
 
 
939
 
        // Reset $sql_where, because we use it later...
940
 
        $sql_where = '';
941
 
 
942
 
        if ($row = $db->sql_fetchrow($result))
943
 
        {
944
 
                $banlist_ary_tmp = array();
945
 
                do
946
 
                {
947
 
                        switch ($mode)
948
 
                        {
949
 
                                case 'user':
950
 
                                        $banlist_ary_tmp[] = $row['ban_userid'];
951
 
                                break;
952
 
 
953
 
                                case 'ip':
954
 
                                        $banlist_ary_tmp[] = $row['ban_ip'];
955
 
                                break;
956
 
 
957
 
                                case 'email':
958
 
                                        $banlist_ary_tmp[] = $row['ban_email'];
959
 
                                break;
960
 
                        }
961
 
                }
962
 
                while ($row = $db->sql_fetchrow($result));
963
 
 
964
 
                $banlist_ary = array_unique(array_diff($banlist_ary, $banlist_ary_tmp));
965
 
                unset($banlist_ary_tmp);
966
 
        }
967
 
        $db->sql_freeresult($result);
968
 
 
969
 
        // We have some entities to ban
970
 
        if (sizeof($banlist_ary))
971
 
        {
972
 
                $sql_ary = array();
973
 
 
974
 
                foreach ($banlist_ary as $ban_entry)
975
 
                {
976
 
                        $sql_ary[] = array(
977
 
                                $type                           => $ban_entry,
978
 
                                'ban_start'                     => (int) $current_time,
979
 
                                'ban_end'                       => (int) $ban_end,
980
 
                                'ban_exclude'           => (int) $ban_exclude,
981
 
                                'ban_reason'            => (string) $ban_reason,
982
 
                                'ban_give_reason'       => (string) $ban_give_reason,
983
 
                        );
984
 
                }
985
 
                
986
 
                $db->sql_multi_insert(BANLIST_TABLE, $sql_ary);
987
 
 
988
 
                // If we are banning we want to logout anyone matching the ban
989
 
                if (!$ban_exclude)
990
 
                {
991
 
                        switch ($mode)
992
 
                        {
993
 
                                case 'user':
994
 
                                        $sql_where = (in_array('*', $banlist_ary)) ? '' : 'WHERE ' . $db->sql_in_set('session_user_id', $banlist_ary);
995
 
                                break;
996
 
 
997
 
                                case 'ip':
998
 
                                        $sql_where = 'WHERE ' . $db->sql_in_set('session_ip', $banlist_ary);
999
 
                                break;
1000
 
 
1001
 
                                case 'email':
1002
 
                                        $banlist_ary_sql = array();
1003
 
 
1004
 
                                        foreach ($banlist_ary as $ban_entry)
1005
 
                                        {
1006
 
                                                $banlist_ary_sql[] = (string) str_replace('*', '%', $ban_entry);
1007
 
                                        }
1008
 
 
1009
 
                                        $sql = 'SELECT user_id
1010
 
                                                FROM ' . USERS_TABLE . '
1011
 
                                                WHERE ' . $db->sql_in_set('user_email', $banlist_ary_sql);
1012
 
                                        $result = $db->sql_query($sql);
1013
 
 
1014
 
                                        $sql_in = array();
1015
 
 
1016
 
                                        if ($row = $db->sql_fetchrow($result))
1017
 
                                        {
1018
 
                                                do
1019
 
                                                {
1020
 
                                                        $sql_in[] = $row['user_id'];
1021
 
                                                }
1022
 
                                                while ($row = $db->sql_fetchrow($result));
1023
 
 
1024
 
                                                $sql_where = 'WHERE ' . $db->sql_in_set('session_user_id', $sql_in);
1025
 
                                        }
1026
 
                                        $db->sql_freeresult($result);
1027
 
                                break;
1028
 
                        }
1029
 
 
1030
 
                        if (isset($sql_where) && $sql_where)
1031
 
                        {
1032
 
                                $sql = 'DELETE FROM ' . SESSIONS_TABLE . "
1033
 
                                        $sql_where";
1034
 
                                $db->sql_query($sql);
1035
 
 
1036
 
                                if ($mode == 'user')
1037
 
                                {
1038
 
                                        $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' ' . ((in_array('*', $banlist_ary)) ? '' : 'WHERE ' . $db->sql_in_set('user_id', $banlist_ary));
1039
 
                                        $db->sql_query($sql);
1040
 
                                }
1041
 
                        }
1042
 
                }
1043
 
 
1044
 
                // Update log
1045
 
                $log_entry = ($ban_exclude) ? 'LOG_BAN_EXCLUDE_' : 'LOG_BAN_';
1046
 
 
1047
 
                // Add to moderator and admin log
1048
 
                add_log('admin', $log_entry . strtoupper($mode), $ban_reason, $ban_list_log);
1049
 
                add_log('mod', 0, 0, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log);
1050
 
 
1051
 
                $cache->destroy('sql', BANLIST_TABLE);
1052
 
 
1053
 
                return true;
1054
 
        }
1055
 
 
1056
 
        // There was nothing to ban/exclude. But destroying the cache because of the removal of stale bans.
1057
 
        $cache->destroy('sql', BANLIST_TABLE);
1058
 
 
1059
 
        return false;
1060
 
}
1061
 
 
1062
 
/**
1063
 
* Unban User
1064
 
*/
1065
 
function user_unban($mode, $ban)
1066
 
{
1067
 
        global $db, $user, $auth, $cache;
1068
 
 
1069
 
        // Delete stale bans
1070
 
        $sql = 'DELETE FROM ' . BANLIST_TABLE . '
1071
 
                WHERE ban_end < ' . time() . '
1072
 
                        AND ban_end <> 0';
1073
 
        $db->sql_query($sql);
1074
 
 
1075
 
        if (!is_array($ban))
1076
 
        {
1077
 
                $ban = array($ban);
1078
 
        }
1079
 
 
1080
 
        $unban_sql = array_map('intval', $ban);
1081
 
 
1082
 
        if (sizeof($unban_sql))
1083
 
        {
1084
 
                // Grab details of bans for logging information later
1085
 
                switch ($mode)
1086
 
                {
1087
 
                        case 'user':
1088
 
                                $sql = 'SELECT u.username AS unban_info
1089
 
                                        FROM ' . USERS_TABLE . ' u, ' . BANLIST_TABLE . ' b
1090
 
                                        WHERE ' . $db->sql_in_set('b.ban_id', $unban_sql) . '
1091
 
                                                AND u.user_id = b.ban_userid';
1092
 
                        break;
1093
 
 
1094
 
                        case 'email':
1095
 
                                $sql = 'SELECT ban_email AS unban_info
1096
 
                                        FROM ' . BANLIST_TABLE . '
1097
 
                                        WHERE ' . $db->sql_in_set('ban_id', $unban_sql);
1098
 
                        break;
1099
 
 
1100
 
                        case 'ip':
1101
 
                                $sql = 'SELECT ban_ip AS unban_info
1102
 
                                        FROM ' . BANLIST_TABLE . '
1103
 
                                        WHERE ' . $db->sql_in_set('ban_id', $unban_sql);
1104
 
                        break;
1105
 
                }
1106
 
                $result = $db->sql_query($sql);
1107
 
 
1108
 
                $l_unban_list = '';
1109
 
                while ($row = $db->sql_fetchrow($result))
1110
 
                {
1111
 
                        $l_unban_list .= (($l_unban_list != '') ? ', ' : '') . $row['unban_info'];
1112
 
                }
1113
 
                $db->sql_freeresult($result);
1114
 
 
1115
 
                $sql = 'DELETE FROM ' . BANLIST_TABLE . '
1116
 
                        WHERE ' . $db->sql_in_set('ban_id', $unban_sql);
1117
 
                $db->sql_query($sql);
1118
 
 
1119
 
                // Add to moderator and admin log
1120
 
                add_log('admin', 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list);
1121
 
                add_log('mod', 0, 0, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list);
1122
 
        }
1123
 
 
1124
 
        $cache->destroy('sql', BANLIST_TABLE);
1125
 
 
1126
 
        return false;
1127
 
}
1128
 
 
1129
 
/**
1130
 
* Whois facility
1131
 
*/
1132
 
function user_ipwhois($ip)
1133
 
{
1134
 
        $ipwhois = '';
1135
 
 
1136
 
        // Check IP
1137
 
        // Only supporting IPv4 at the moment...
1138
 
        if (empty($ip) || !preg_match(get_preg_expression('ipv4'), $ip))
1139
 
        {
1140
 
                return '';
1141
 
        }
1142
 
 
1143
 
        $match = array(
1144
 
                '#RIPE\.NET#is'                         => 'whois.ripe.net',
1145
 
                '#whois\.apnic\.net#is'         => 'whois.apnic.net',
1146
 
                '#nic\.ad\.jp#is'                       => 'whois.nic.ad.jp',
1147
 
                '#whois\.registro\.br#is'       => 'whois.registro.br'
1148
 
        );
1149
 
 
1150
 
        if (($fsk = @fsockopen('whois.arin.net', 43)))
1151
 
        {
1152
 
                fputs($fsk, "$ip\n");
1153
 
                while (!feof($fsk))
1154
 
                {
1155
 
                        $ipwhois .= fgets($fsk, 1024);
1156
 
                }
1157
 
                @fclose($fsk);
1158
 
        }
1159
 
 
1160
 
        foreach (array_keys($match) as $server)
1161
 
        {
1162
 
                if (preg_match($server, $ipwhois))
1163
 
                {
1164
 
                        $ipwhois = '';
1165
 
                        if (($fsk = @fsockopen($match[$server], 43)))
1166
 
                        {
1167
 
                                fputs($fsk, "$ip\n");
1168
 
                                while (!feof($fsk))
1169
 
                                {
1170
 
                                        $ipwhois .= fgets($fsk, 1024);
1171
 
                                }
1172
 
                                @fclose($fsk);
1173
 
                        }
1174
 
                        break;
1175
 
                }
1176
 
        }
1177
 
 
1178
 
        $ipwhois = htmlspecialchars($ipwhois);
1179
 
 
1180
 
        // Magic URL ;)
1181
 
        return trim(make_clickable($ipwhois, false, ''));
1182
 
}
1183
 
 
1184
 
/**
1185
 
* Data validation ... used primarily but not exclusively by ucp modules
1186
 
*
1187
 
* "Master" function for validating a range of data types
1188
 
*/
1189
 
function validate_data($data, $val_ary)
1190
 
{
1191
 
        $error = array();
1192
 
 
1193
 
        foreach ($val_ary as $var => $val_seq)
1194
 
        {
1195
 
                if (!is_array($val_seq[0]))
1196
 
                {
1197
 
                        $val_seq = array($val_seq);
1198
 
                }
1199
 
 
1200
 
                foreach ($val_seq as $validate)
1201
 
                {
1202
 
                        $function = array_shift($validate);
1203
 
                        array_unshift($validate, $data[$var]);
1204
 
 
1205
 
                        if ($result = call_user_func_array('validate_' . $function, $validate))
1206
 
                        {
1207
 
                                $error[] = $result . '_' . strtoupper($var);
1208
 
                        }
1209
 
                }
1210
 
        }
1211
 
 
1212
 
        return $error;
1213
 
}
1214
 
 
1215
 
/**
1216
 
* Validate String
1217
 
*
1218
 
* @return       boolean|string  Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
1219
 
*/
1220
 
function validate_string($string, $optional = false, $min = 0, $max = 0)
1221
 
{
1222
 
        if (empty($string) && $optional)
1223
 
        {
1224
 
                return false;
1225
 
        }
1226
 
 
1227
 
        if ($min && utf8_strlen(htmlspecialchars_decode($string)) < $min)
1228
 
        {
1229
 
                return 'TOO_SHORT';
1230
 
        }
1231
 
        else if ($max && utf8_strlen(htmlspecialchars_decode($string)) > $max)
1232
 
        {
1233
 
                return 'TOO_LONG';
1234
 
        }
1235
 
 
1236
 
        return false;
1237
 
}
1238
 
 
1239
 
/**
1240
 
* Validate Number
1241
 
*
1242
 
* @return       boolean|string  Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
1243
 
*/
1244
 
function validate_num($num, $optional = false, $min = 0, $max = 1E99)
1245
 
{
1246
 
        if (empty($num) && $optional)
1247
 
        {
1248
 
                return false;
1249
 
        }
1250
 
 
1251
 
        if ($num < $min)
1252
 
        {
1253
 
                return 'TOO_SMALL';
1254
 
        }
1255
 
        else if ($num > $max)
1256
 
        {
1257
 
                return 'TOO_LARGE';
1258
 
        }
1259
 
 
1260
 
        return false;
1261
 
}
1262
 
 
1263
 
/**
1264
 
* Validate Match
1265
 
*
1266
 
* @return       boolean|string  Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
1267
 
*/
1268
 
function validate_match($string, $optional = false, $match = '')
1269
 
{
1270
 
        if (empty($string) && $optional)
1271
 
        {
1272
 
                return false;
1273
 
        }
1274
 
 
1275
 
        if (empty($match))
1276
 
        {
1277
 
                return false;
1278
 
        }
1279
 
 
1280
 
        if (!preg_match($match, $string))
1281
 
        {
1282
 
                return 'WRONG_DATA';
1283
 
        }
1284
 
 
1285
 
        return false;
1286
 
}
1287
 
 
1288
 
/**
1289
 
* Check to see if the username has been taken, or if it is disallowed.
1290
 
* Also checks if it includes the " character, which we don't allow in usernames.
1291
 
* Used for registering, changing names, and posting anonymously with a username
1292
 
*
1293
 
* @param string $username The username to check
1294
 
* @param string $allowed_username An allowed username, default being $user->data['username']
1295
 
*
1296
 
* @return       mixed   Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
1297
 
*/
1298
 
function validate_username($username, $allowed_username = false)
1299
 
{
1300
 
        global $config, $db, $user, $cache;
1301
 
 
1302
 
        $clean_username = utf8_clean_string($username);
1303
 
        $allowed_username = ($allowed_username === false) ? $user->data['username_clean'] : utf8_clean_string($allowed_username);
1304
 
 
1305
 
        if ($allowed_username == $clean_username)
1306
 
        {
1307
 
                return false;
1308
 
        }
1309
 
 
1310
 
        // ... fast checks first.
1311
 
        if (strpos($username, '&quot;') !== false || strpos($username, '"') !== false || empty($clean_username))
1312
 
        {
1313
 
                return 'INVALID_CHARS';
1314
 
        }
1315
 
 
1316
 
        $mbstring = $pcre = false;
1317
 
 
1318
 
        // generic UTF-8 character types supported?
1319
 
        if ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false)
1320
 
        {
1321
 
                $pcre = true;
1322
 
        }
1323
 
        else if (function_exists('mb_ereg_match'))
1324
 
        {
1325
 
                mb_regex_encoding('UTF-8');
1326
 
                $mbstring = true;
1327
 
        }
1328
 
 
1329
 
        switch ($config['allow_name_chars'])
1330
 
        {
1331
 
                case 'USERNAME_CHARS_ANY':
1332
 
                        $pcre = true;
1333
 
                        $regex = '.+';
1334
 
                break;
1335
 
 
1336
 
                case 'USERNAME_ALPHA_ONLY':
1337
 
                        $pcre = true;
1338
 
                        $regex = '[A-Za-z0-9]+';
1339
 
                break;
1340
 
 
1341
 
                case 'USERNAME_ALPHA_SPACERS':
1342
 
                        $pcre = true;
1343
 
                        $regex = '[A-Za-z0-9-[\]_+ ]+';
1344
 
                break;
1345
 
 
1346
 
                case 'USERNAME_LETTER_NUM':
1347
 
                        if ($pcre)
1348
 
                        {
1349
 
                                $regex = '[\p{Lu}\p{Ll}\p{N}]+';
1350
 
                        }
1351
 
                        else if ($mbstring)
1352
 
                        {
1353
 
                                $regex = '[[:upper:][:lower:][:digit:]]+';
1354
 
                        }
1355
 
                        else
1356
 
                        {
1357
 
                                $pcre = true;
1358
 
                                $regex = '[a-zA-Z0-9]+';
1359
 
                        }
1360
 
                break;
1361
 
 
1362
 
                case 'USERNAME_LETTER_NUM_SPACERS':
1363
 
                        if ($pcre)
1364
 
                        {
1365
 
                                $regex = '[-\]_+ [\p{Lu}\p{Ll}\p{N}]+';
1366
 
                        }
1367
 
                        else if ($mbstring)
1368
 
                        {
1369
 
                                $regex = '[-\]_+ [[:upper:][:lower:][:digit:]]+';
1370
 
                        }
1371
 
                        else
1372
 
                        {
1373
 
                                $pcre = true;
1374
 
                                $regex = '[-\]_+ [a-zA-Z0-9]+';
1375
 
                        }
1376
 
                break;
1377
 
 
1378
 
                case 'USERNAME_ASCII':
1379
 
                default:
1380
 
                        $pcre = true;
1381
 
                        $regex = '[\x01-\x7F]+';
1382
 
                break;
1383
 
        }
1384
 
 
1385
 
        if ($pcre)
1386
 
        {
1387
 
                if (!preg_match('#^' . $regex . '$#u', $username))
1388
 
                {
1389
 
                        return 'INVALID_CHARS';
1390
 
                }
1391
 
        }
1392
 
        else if ($mbstring)
1393
 
        {
1394
 
                $matches = array();
1395
 
                mb_ereg_search_init('^' . $username . '$', $regex, $matches);
1396
 
                if (!mb_ereg_search())
1397
 
                {
1398
 
                        return 'INVALID_CHARS';
1399
 
                }
1400
 
        }
1401
 
 
1402
 
        $sql = 'SELECT username
1403
 
                FROM ' . USERS_TABLE . "
1404
 
                WHERE username_clean = '" . $db->sql_escape($clean_username) . "'";
1405
 
        $result = $db->sql_query($sql);
1406
 
        $row = $db->sql_fetchrow($result);
1407
 
        $db->sql_freeresult($result);
1408
 
 
1409
 
        if ($row)
1410
 
        {
1411
 
                return 'USERNAME_TAKEN';
1412
 
        }
1413
 
 
1414
 
        $sql = 'SELECT group_name
1415
 
                FROM ' . GROUPS_TABLE . "
1416
 
                WHERE LOWER(group_name) = '" . $db->sql_escape(utf8_strtolower($username)) . "'";
1417
 
        $result = $db->sql_query($sql);
1418
 
        $row = $db->sql_fetchrow($result);
1419
 
        $db->sql_freeresult($result);
1420
 
 
1421
 
        if ($row)
1422
 
        {
1423
 
                return 'USERNAME_TAKEN';
1424
 
        }
1425
 
 
1426
 
        $bad_usernames = $cache->obtain_disallowed_usernames();
1427
 
 
1428
 
        foreach ($bad_usernames as $bad_username)
1429
 
        {
1430
 
                if (preg_match('#^' . $bad_username . '$#', $clean_username))
1431
 
                {
1432
 
                        return 'USERNAME_DISALLOWED';
1433
 
                }
1434
 
        }
1435
 
 
1436
 
        $sql = 'SELECT word
1437
 
                FROM ' . WORDS_TABLE;
1438
 
        $result = $db->sql_query($sql);
1439
 
 
1440
 
        while ($row = $db->sql_fetchrow($result))
1441
 
        {
1442
 
                if (preg_match('#(' . str_replace('\*', '.*?', preg_quote($row['word'], '#')) . ')#i', $username))
1443
 
                {
1444
 
                        $db->sql_freeresult($result);
1445
 
                        return 'USERNAME_DISALLOWED';
1446
 
                }
1447
 
        }
1448
 
        $db->sql_freeresult($result);
1449
 
 
1450
 
        return false;
1451
 
}
1452
 
 
1453
 
/**
1454
 
* Check to see if the password meets the complexity settings
1455
 
*
1456
 
* @return       boolean|string  Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
1457
 
*/
1458
 
function validate_password($password)
1459
 
{
1460
 
        global $config, $db, $user;
1461
 
 
1462
 
        if (!$password)
1463
 
        {
1464
 
                return false;
1465
 
        }
1466
 
 
1467
 
        $pcre = $mbstring = false;
1468
 
 
1469
 
        // generic UTF-8 character types supported?
1470
 
        if ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false)
1471
 
        {
1472
 
                $upp = '\p{Lu}';
1473
 
                $low = '\p{Ll}';
1474
 
                $let = '\p{L}';
1475
 
                $num = '\p{N}';
1476
 
                $sym = '[^\p{Lu}\p{Ll}\p{N}]';
1477
 
                $pcre = true;
1478
 
        }
1479
 
        else if (function_exists('mb_ereg_match'))
1480
 
        {
1481
 
                mb_regex_encoding('UTF-8');
1482
 
                $upp = '[[:upper:]]';
1483
 
                $low = '[[:lower:]]';
1484
 
                $let = '[[:lower:][:upper:]]';
1485
 
                $num = '[[:digit:]]';
1486
 
                $sym = '[^[:upper:][:lower:][:digit:]]';
1487
 
                $mbstring = true;
1488
 
        }
1489
 
        else
1490
 
        {
1491
 
                $upp = '[A-Z]';
1492
 
                $low = '[a-z]';
1493
 
                $let = '[a-zA-Z]';
1494
 
                $num = '[0-9]';
1495
 
                $sym = '[^A-Za-z0-9]';
1496
 
                $pcre = true;
1497
 
        }
1498
 
 
1499
 
        $chars = array();
1500
 
 
1501
 
        switch ($config['pass_complex'])
1502
 
        {
1503
 
                case 'PASS_TYPE_CASE':
1504
 
                        $chars[] = $low;
1505
 
                        $chars[] = $upp;
1506
 
                break;
1507
 
 
1508
 
                case 'PASS_TYPE_ALPHA':
1509
 
                        $chars[] = $let;
1510
 
                        $chars[] = $num;
1511
 
                break;
1512
 
 
1513
 
                case 'PASS_TYPE_SYMBOL':
1514
 
                        $chars[] = $low;
1515
 
                        $chars[] = $upp;
1516
 
                        $chars[] = $num;
1517
 
                        $chars[] = $sym;
1518
 
                break;
1519
 
        }
1520
 
 
1521
 
        if ($pcre)
1522
 
        {
1523
 
                foreach ($chars as $char)
1524
 
                {
1525
 
                        if (!preg_match('#' . $char . '#u', $password))
1526
 
                        {
1527
 
                                return 'INVALID_CHARS';
1528
 
                        }
1529
 
                }
1530
 
        }
1531
 
        else if ($mbstring)
1532
 
        {
1533
 
                foreach ($chars as $char)
1534
 
                {
1535
 
                        if (mb_ereg($char, $password) === false)
1536
 
                        {
1537
 
                                return 'INVALID_CHARS';
1538
 
                        }
1539
 
                }
1540
 
        }
1541
 
 
1542
 
        return false;
1543
 
}
1544
 
 
1545
 
/**
1546
 
* Check to see if email address is banned or already present in the DB
1547
 
*
1548
 
* @param string $email The email to check
1549
 
* @param string $allowed_email An allowed email, default being $user->data['user_email']
1550
 
*
1551
 
* @return mixed Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
1552
 
*/
1553
 
function validate_email($email, $allowed_email = false)
1554
 
{
1555
 
        global $config, $db, $user;
1556
 
 
1557
 
        $email = strtolower($email);
1558
 
        $allowed_email = ($allowed_email === false) ? strtolower($user->data['user_email']) : strtolower($allowed_email);
1559
 
 
1560
 
        if ($allowed_email == $email)
1561
 
        {
1562
 
                return false;
1563
 
        }
1564
 
 
1565
 
        if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email))
1566
 
        {
1567
 
                return 'EMAIL_INVALID';
1568
 
        }
1569
 
 
1570
 
        // Check MX record.
1571
 
        // The idea for this is from reading the UseBB blog/announcement. :)
1572
 
        if ($config['email_check_mx'])
1573
 
        {
1574
 
                list(, $domain) = explode('@', $email);
1575
 
 
1576
 
                if (phpbb_checkdnsrr($domain, 'A') === false && phpbb_checkdnsrr($domain, 'MX') === false)
1577
 
                {
1578
 
                        return 'DOMAIN_NO_MX_RECORD';
1579
 
                }
1580
 
        }
1581
 
 
1582
 
        if ($user->check_ban(false, false, $email, true) == true)
1583
 
        {
1584
 
                return 'EMAIL_BANNED';
1585
 
        }
1586
 
 
1587
 
        if (!$config['allow_emailreuse'])
1588
 
        {
1589
 
                $sql = 'SELECT user_email_hash
1590
 
                        FROM ' . USERS_TABLE . "
1591
 
                        WHERE user_email_hash = " . (crc32($email) . strlen($email));
1592
 
                $result = $db->sql_query($sql);
1593
 
                $row = $db->sql_fetchrow($result);
1594
 
                $db->sql_freeresult($result);
1595
 
 
1596
 
                if ($row)
1597
 
                {
1598
 
                        return 'EMAIL_TAKEN';
1599
 
                }
1600
 
        }
1601
 
 
1602
 
        return false;
1603
 
}
1604
 
 
1605
 
/**
1606
 
* Validate jabber address
1607
 
* Taken from the jabber class within flyspray (see author notes)
1608
 
*
1609
 
* @author flyspray.org
1610
 
*/
1611
 
function validate_jabber($jid)
1612
 
{
1613
 
        if (!$jid)
1614
 
        {
1615
 
                return false;
1616
 
        }
1617
 
 
1618
 
        $seperator_pos = strpos($jid, '@');
1619
 
 
1620
 
        if ($seperator_pos === false)
1621
 
        {
1622
 
                return 'WRONG_DATA';
1623
 
        }
1624
 
 
1625
 
        $username = substr($jid, 0, $seperator_pos);
1626
 
        $realm = substr($jid, $seperator_pos + 1);
1627
 
 
1628
 
        if (strlen($username) == 0 || strlen($realm) < 3)
1629
 
        {
1630
 
                return 'WRONG_DATA';
1631
 
        }
1632
 
 
1633
 
        $arr = explode('.', $realm);
1634
 
 
1635
 
        if (sizeof($arr) == 0)
1636
 
        {
1637
 
                return 'WRONG_DATA';
1638
 
        }
1639
 
 
1640
 
        foreach ($arr as $part)
1641
 
        {
1642
 
                if (substr($part, 0, 1) == '-' || substr($part, -1, 1) == '-')
1643
 
                {
1644
 
                        return 'WRONG_DATA';
1645
 
                }
1646
 
 
1647
 
                if (!preg_match("@^[a-zA-Z0-9-.]+$@", $part))
1648
 
                {
1649
 
                        return 'WRONG_DATA';
1650
 
                }
1651
 
        }
1652
 
 
1653
 
        $boundary = array(array(0, 127), array(192, 223), array(224, 239), array(240, 247), array(248, 251), array(252, 253));
1654
 
 
1655
 
        // Prohibited Characters RFC3454 + RFC3920
1656
 
        $prohibited = array(
1657
 
                // Table C.1.1
1658
 
                array(0x0020, 0x0020),          // SPACE
1659
 
                // Table C.1.2
1660
 
                array(0x00A0, 0x00A0),          // NO-BREAK SPACE
1661
 
                array(0x1680, 0x1680),          // OGHAM SPACE MARK
1662
 
                array(0x2000, 0x2001),          // EN QUAD
1663
 
                array(0x2001, 0x2001),          // EM QUAD
1664
 
                array(0x2002, 0x2002),          // EN SPACE
1665
 
                array(0x2003, 0x2003),          // EM SPACE
1666
 
                array(0x2004, 0x2004),          // THREE-PER-EM SPACE
1667
 
                array(0x2005, 0x2005),          // FOUR-PER-EM SPACE
1668
 
                array(0x2006, 0x2006),          // SIX-PER-EM SPACE
1669
 
                array(0x2007, 0x2007),          // FIGURE SPACE
1670
 
                array(0x2008, 0x2008),          // PUNCTUATION SPACE
1671
 
                array(0x2009, 0x2009),          // THIN SPACE
1672
 
                array(0x200A, 0x200A),          // HAIR SPACE
1673
 
                array(0x200B, 0x200B),          // ZERO WIDTH SPACE
1674
 
                array(0x202F, 0x202F),          // NARROW NO-BREAK SPACE
1675
 
                array(0x205F, 0x205F),          // MEDIUM MATHEMATICAL SPACE
1676
 
                array(0x3000, 0x3000),          // IDEOGRAPHIC SPACE
1677
 
                // Table C.2.1
1678
 
                array(0x0000, 0x001F),          // [CONTROL CHARACTERS]
1679
 
                array(0x007F, 0x007F),          // DELETE
1680
 
                // Table C.2.2
1681
 
                array(0x0080, 0x009F),          // [CONTROL CHARACTERS]
1682
 
                array(0x06DD, 0x06DD),          // ARABIC END OF AYAH
1683
 
                array(0x070F, 0x070F),          // SYRIAC ABBREVIATION MARK
1684
 
                array(0x180E, 0x180E),          // MONGOLIAN VOWEL SEPARATOR
1685
 
                array(0x200C, 0x200C),          // ZERO WIDTH NON-JOINER
1686
 
                array(0x200D, 0x200D),          // ZERO WIDTH JOINER
1687
 
                array(0x2028, 0x2028),          // LINE SEPARATOR
1688
 
                array(0x2029, 0x2029),          // PARAGRAPH SEPARATOR
1689
 
                array(0x2060, 0x2060),          // WORD JOINER
1690
 
                array(0x2061, 0x2061),          // FUNCTION APPLICATION
1691
 
                array(0x2062, 0x2062),          // INVISIBLE TIMES
1692
 
                array(0x2063, 0x2063),          // INVISIBLE SEPARATOR
1693
 
                array(0x206A, 0x206F),          // [CONTROL CHARACTERS]
1694
 
                array(0xFEFF, 0xFEFF),          // ZERO WIDTH NO-BREAK SPACE
1695
 
                array(0xFFF9, 0xFFFC),          // [CONTROL CHARACTERS]
1696
 
                array(0x1D173, 0x1D17A),        // [MUSICAL CONTROL CHARACTERS]
1697
 
                // Table C.3
1698
 
                array(0xE000, 0xF8FF),          // [PRIVATE USE, PLANE 0]
1699
 
                array(0xF0000, 0xFFFFD),        // [PRIVATE USE, PLANE 15]
1700
 
                array(0x100000, 0x10FFFD),      // [PRIVATE USE, PLANE 16]
1701
 
                // Table C.4
1702
 
                array(0xFDD0, 0xFDEF),          // [NONCHARACTER CODE POINTS]
1703
 
                array(0xFFFE, 0xFFFF),          // [NONCHARACTER CODE POINTS]
1704
 
                array(0x1FFFE, 0x1FFFF),        // [NONCHARACTER CODE POINTS]
1705
 
                array(0x2FFFE, 0x2FFFF),        // [NONCHARACTER CODE POINTS]
1706
 
                array(0x3FFFE, 0x3FFFF),        // [NONCHARACTER CODE POINTS]
1707
 
                array(0x4FFFE, 0x4FFFF),        // [NONCHARACTER CODE POINTS]
1708
 
                array(0x5FFFE, 0x5FFFF),        // [NONCHARACTER CODE POINTS]
1709
 
                array(0x6FFFE, 0x6FFFF),        // [NONCHARACTER CODE POINTS]
1710
 
                array(0x7FFFE, 0x7FFFF),        // [NONCHARACTER CODE POINTS]
1711
 
                array(0x8FFFE, 0x8FFFF),        // [NONCHARACTER CODE POINTS]
1712
 
                array(0x9FFFE, 0x9FFFF),        // [NONCHARACTER CODE POINTS]
1713
 
                array(0xAFFFE, 0xAFFFF),        // [NONCHARACTER CODE POINTS]
1714
 
                array(0xBFFFE, 0xBFFFF),        // [NONCHARACTER CODE POINTS]
1715
 
                array(0xCFFFE, 0xCFFFF),        // [NONCHARACTER CODE POINTS]
1716
 
                array(0xDFFFE, 0xDFFFF),        // [NONCHARACTER CODE POINTS]
1717
 
                array(0xEFFFE, 0xEFFFF),        // [NONCHARACTER CODE POINTS]
1718
 
                array(0xFFFFE, 0xFFFFF),        // [NONCHARACTER CODE POINTS]
1719
 
                array(0x10FFFE, 0x10FFFF),      // [NONCHARACTER CODE POINTS]
1720
 
                // Table C.5
1721
 
                array(0xD800, 0xDFFF),          // [SURROGATE CODES]
1722
 
                // Table C.6
1723
 
                array(0xFFF9, 0xFFF9),          // INTERLINEAR ANNOTATION ANCHOR
1724
 
                array(0xFFFA, 0xFFFA),          // INTERLINEAR ANNOTATION SEPARATOR
1725
 
                array(0xFFFB, 0xFFFB),          // INTERLINEAR ANNOTATION TERMINATOR
1726
 
                array(0xFFFC, 0xFFFC),          // OBJECT REPLACEMENT CHARACTER
1727
 
                array(0xFFFD, 0xFFFD),          // REPLACEMENT CHARACTER
1728
 
                // Table C.7
1729
 
                array(0x2FF0, 0x2FFB),          // [IDEOGRAPHIC DESCRIPTION CHARACTERS]
1730
 
                // Table C.8
1731
 
                array(0x0340, 0x0340),          // COMBINING GRAVE TONE MARK
1732
 
                array(0x0341, 0x0341),          // COMBINING ACUTE TONE MARK
1733
 
                array(0x200E, 0x200E),          // LEFT-TO-RIGHT MARK
1734
 
                array(0x200F, 0x200F),          // RIGHT-TO-LEFT MARK
1735
 
                array(0x202A, 0x202A),          // LEFT-TO-RIGHT EMBEDDING
1736
 
                array(0x202B, 0x202B),          // RIGHT-TO-LEFT EMBEDDING
1737
 
                array(0x202C, 0x202C),          // POP DIRECTIONAL FORMATTING
1738
 
                array(0x202D, 0x202D),          // LEFT-TO-RIGHT OVERRIDE
1739
 
                array(0x202E, 0x202E),          // RIGHT-TO-LEFT OVERRIDE
1740
 
                array(0x206A, 0x206A),          // INHIBIT SYMMETRIC SWAPPING
1741
 
                array(0x206B, 0x206B),          // ACTIVATE SYMMETRIC SWAPPING
1742
 
                array(0x206C, 0x206C),          // INHIBIT ARABIC FORM SHAPING
1743
 
                array(0x206D, 0x206D),          // ACTIVATE ARABIC FORM SHAPING
1744
 
                array(0x206E, 0x206E),          // NATIONAL DIGIT SHAPES
1745
 
                array(0x206F, 0x206F),          // NOMINAL DIGIT SHAPES
1746
 
                // Table C.9
1747
 
                array(0xE0001, 0xE0001),        // LANGUAGE TAG
1748
 
                array(0xE0020, 0xE007F),        // [TAGGING CHARACTERS]
1749
 
                // RFC3920
1750
 
                array(0x22, 0x22),                      // "
1751
 
                array(0x26, 0x26),                      // &
1752
 
                array(0x27, 0x27),                      // '
1753
 
                array(0x2F, 0x2F),                      // /
1754
 
                array(0x3A, 0x3A),                      // :
1755
 
                array(0x3C, 0x3C),                      // <
1756
 
                array(0x3E, 0x3E),                      // >
1757
 
                array(0x40, 0x40)                       // @
1758
 
        );
1759
 
 
1760
 
        $pos = 0;
1761
 
        $result = true;
1762
 
 
1763
 
        while ($pos < strlen($username))
1764
 
        {
1765
 
                $len = $uni = 0;
1766
 
                for ($i = 0; $i <= 5; $i++)
1767
 
                {
1768
 
                        if (ord($username[$pos]) >= $boundary[$i][0] && ord($username[$pos]) <= $boundary[$i][1])
1769
 
                        {
1770
 
                                $len = $i + 1;
1771
 
                                $uni = (ord($username[$pos]) - $boundary[$i][0]) * pow(2, $i * 6);
1772
 
 
1773
 
                                for ($k = 1; $k < $len; $k++)
1774
 
                                {
1775
 
                                        $uni += (ord($username[$pos + $k]) - 128) * pow(2, ($i - $k) * 6);
1776
 
                                }
1777
 
 
1778
 
                                break;
1779
 
                        }
1780
 
                }
1781
 
 
1782
 
                if ($len == 0)
1783
 
                {
1784
 
                        return 'WRONG_DATA';
1785
 
                }
1786
 
 
1787
 
                foreach ($prohibited as $pval)
1788
 
                {
1789
 
                        if ($uni >= $pval[0] && $uni <= $pval[1])
1790
 
                        {
1791
 
                                $result = false;
1792
 
                                break 2;
1793
 
                        }
1794
 
                }
1795
 
 
1796
 
                $pos = $pos + $len;
1797
 
        }
1798
 
 
1799
 
        if (!$result)
1800
 
        {
1801
 
                return 'WRONG_DATA';
1802
 
        }
1803
 
 
1804
 
        return false;
1805
 
}
1806
 
 
1807
 
/**
1808
 
* Remove avatar
1809
 
*/
1810
 
function avatar_delete($mode, $row, $clean_db = false)
1811
 
{
1812
 
        global $phpbb_root_path, $config, $db, $user;
1813
 
 
1814
 
        // Check if the users avatar is actually *not* a group avatar
1815
 
        if ($mode == 'user')
1816
 
        {
1817
 
                if (strpos($row['user_avatar'], 'g') === 0 || (((int)$row['user_avatar'] !== 0) && ((int)$row['user_avatar'] !== (int)$row['user_id'])))
1818
 
                {
1819
 
                        return false;
1820
 
                }
1821
 
        }
1822
 
        
1823
 
        if ($clean_db)
1824
 
        {
1825
 
                avatar_remove_db($row[$mode . '_avatar']);
1826
 
        }
1827
 
        $filename = get_avatar_filename($row[$mode . '_avatar']);
1828
 
        if (file_exists($phpbb_root_path . $config['avatar_path'] . '/' . $filename))
1829
 
        {
1830
 
                @unlink($phpbb_root_path . $config['avatar_path'] . '/' . $filename);
1831
 
                return true;
1832
 
        }
1833
 
 
1834
 
        return false;
1835
 
}
1836
 
 
1837
 
/**
1838
 
* Remote avatar linkage
1839
 
*/
1840
 
function avatar_remote($data, &$error)
1841
 
{
1842
 
        global $config, $db, $user, $phpbb_root_path, $phpEx;
1843
 
 
1844
 
        if (!preg_match('#^(http|https|ftp)://#i', $data['remotelink']))
1845
 
        {
1846
 
                $data['remotelink'] = 'http://' . $data['remotelink'];
1847
 
        }
1848
 
        if (!preg_match('#^(http|https|ftp)://(?:(.*?\.)*?[a-z0-9\-]+?\.[a-z]{2,4}|(?:\d{1,3}\.){3,5}\d{1,3}):?([0-9]*?).*?\.(gif|jpg|jpeg|png)$#i', $data['remotelink']))
1849
 
        {
1850
 
                $error[] = $user->lang['AVATAR_URL_INVALID'];
1851
 
                return false;
1852
 
        }
1853
 
 
1854
 
        // Make sure getimagesize works...
1855
 
        if (($image_data = @getimagesize($data['remotelink'])) === false && (empty($data['width']) || empty($data['height'])))
1856
 
        {
1857
 
                $error[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
1858
 
                return false;
1859
 
        }
1860
 
 
1861
 
        if (!empty($image_data) && ($image_data[0] < 2 || $image_data[1] < 2))
1862
 
        {
1863
 
                $error[] = $user->lang['AVATAR_NO_SIZE'];
1864
 
                return false;
1865
 
        }
1866
 
 
1867
 
        $width = ($data['width'] && $data['height']) ? $data['width'] : $image_data[0];
1868
 
        $height = ($data['width'] && $data['height']) ? $data['height'] : $image_data[1];
1869
 
 
1870
 
        if ($width < 2 || $height < 2)
1871
 
        {
1872
 
                $error[] = $user->lang['AVATAR_NO_SIZE'];
1873
 
                return false;
1874
 
        }
1875
 
 
1876
 
        // Check image type
1877
 
        include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx);
1878
 
        $types = fileupload::image_types();
1879
 
        $extension = strtolower(filespec::get_extension($data['remotelink']));
1880
 
 
1881
 
        if (!empty($image_data) && (!isset($types[$image_data[2]]) || !in_array($extension, $types[$image_data[2]])))
1882
 
        {
1883
 
                if (!isset($types[$image_data[2]]))
1884
 
                {
1885
 
                        $error[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
1886
 
                }
1887
 
                else
1888
 
                {
1889
 
                        $error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$image_data[2]][0], $extension);
1890
 
                }
1891
 
                return false;
1892
 
        }
1893
 
 
1894
 
        if ($config['avatar_max_width'] || $config['avatar_max_height'])
1895
 
        {
1896
 
                if ($width > $config['avatar_max_width'] || $height > $config['avatar_max_height'])
1897
 
                {
1898
 
                        $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $width, $height);
1899
 
                        return false;
1900
 
                }
1901
 
        }
1902
 
 
1903
 
        if ($config['avatar_min_width'] || $config['avatar_min_height'])
1904
 
        {
1905
 
                if ($width < $config['avatar_min_width'] || $height < $config['avatar_min_height'])
1906
 
                {
1907
 
                        $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $width, $height);
1908
 
                        return false;
1909
 
                }
1910
 
        }
1911
 
 
1912
 
        return array(AVATAR_REMOTE, $data['remotelink'], $width, $height);
1913
 
}
1914
 
 
1915
 
/**
1916
 
* Avatar upload using the upload class
1917
 
*/
1918
 
function avatar_upload($data, &$error)
1919
 
{
1920
 
        global $phpbb_root_path, $config, $db, $user, $phpEx;
1921
 
 
1922
 
        // Init upload class
1923
 
        include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx);
1924
 
        $upload = new fileupload('AVATAR_', array('jpg', 'jpeg', 'gif', 'png'), $config['avatar_filesize'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height']);
1925
 
 
1926
 
        if (!empty($_FILES['uploadfile']['name']))
1927
 
        {
1928
 
                $file = $upload->form_upload('uploadfile');
1929
 
        }
1930
 
        else
1931
 
        {
1932
 
                $file = $upload->remote_upload($data['uploadurl']);
1933
 
        }
1934
 
        
1935
 
        $prefix = $config['avatar_salt'] . '_';
1936
 
        $file->clean_filename('avatar', $prefix, $data['user_id']);
1937
 
 
1938
 
        $destination = $config['avatar_path'];
1939
 
 
1940
 
        // Adjust destination path (no trailing slash)
1941
 
        if (substr($destination, -1, 1) == '/' || substr($destination, -1, 1) == '\\')
1942
 
        {
1943
 
                $destination = substr($destination, 0, -1);
1944
 
        }
1945
 
 
1946
 
        $destination = str_replace(array('../', '..\\', './', '.\\'), '', $destination);
1947
 
        if ($destination && ($destination[0] == '/' || $destination[0] == "\\"))
1948
 
        {
1949
 
                $destination = '';
1950
 
        }
1951
 
 
1952
 
        // Move file and overwrite any existing image
1953
 
        $file->move_file($destination, true);
1954
 
 
1955
 
        if (sizeof($file->error))
1956
 
        {
1957
 
                $file->remove();
1958
 
                $error = array_merge($error, $file->error);
1959
 
        }
1960
 
 
1961
 
        return array(AVATAR_UPLOAD, $data['user_id'] . '_' . time() . '.' . $file->get('extension'), $file->get('width'), $file->get('height'));
1962
 
}
1963
 
 
1964
 
/**
1965
 
* Generates avatar filename from the database entry
1966
 
*/
1967
 
function get_avatar_filename($avatar_entry)
1968
 
{
1969
 
        global $config;
1970
 
 
1971
 
        
1972
 
        if ($avatar_entry[0] === 'g')
1973
 
        {
1974
 
                $avatar_group = true;
1975
 
                $avatar_entry = substr($avatar_entry, 1);
1976
 
        }
1977
 
        else
1978
 
        {
1979
 
                $avatar_group = false;
1980
 
        }
1981
 
        $ext                    = substr(strrchr($avatar_entry, '.'), 1);
1982
 
        $avatar_entry   = intval($avatar_entry);
1983
 
        return $config['avatar_salt'] . '_' . (($avatar_group) ? 'g' : '') . $avatar_entry . '.' . $ext;
1984
 
}
1985
 
 
1986
 
/**
1987
 
* Avatar Gallery
1988
 
*/
1989
 
function avatar_gallery($category, $avatar_select, $items_per_column, $block_var = 'avatar_row')
1990
 
{
1991
 
        global $user, $cache, $template;
1992
 
        global $config, $phpbb_root_path;
1993
 
 
1994
 
        $avatar_list = array();
1995
 
 
1996
 
        $path = $phpbb_root_path . $config['avatar_gallery_path'];
1997
 
 
1998
 
        if (!file_exists($path) || !is_dir($path))
1999
 
        {
2000
 
                $avatar_list = array($user->lang['NO_AVATAR_CATEGORY'] => array());
2001
 
        }
2002
 
        else
2003
 
        {
2004
 
                // Collect images
2005
 
                $dp = @opendir($path);
2006
 
 
2007
 
                if (!$dp)
2008
 
                {
2009
 
                        return array($user->lang['NO_AVATAR_CATEGORY'] => array());
2010
 
                }
2011
 
 
2012
 
                while (($file = readdir($dp)) !== false)
2013
 
                {
2014
 
                        if ($file[0] != '.' && preg_match('#^[^&"\'<>]+$#i', $file) && is_dir("$path/$file"))
2015
 
                        {
2016
 
                                $avatar_row_count = $avatar_col_count = 0;
2017
 
        
2018
 
                                if ($dp2 = @opendir("$path/$file"))
2019
 
                                {
2020
 
                                        while (($sub_file = readdir($dp2)) !== false)
2021
 
                                        {
2022
 
                                                if (preg_match('#^[^&\'"<>]+\.(?:gif|png|jpe?g)$#i', $sub_file))
2023
 
                                                {
2024
 
                                                        $avatar_list[$file][$avatar_row_count][$avatar_col_count] = array(
2025
 
                                                                'file'          => "$file/$sub_file",
2026
 
                                                                'filename'      => $sub_file,
2027
 
                                                                'name'          => ucfirst(str_replace('_', ' ', preg_replace('#^(.*)\..*$#', '\1', $sub_file))),
2028
 
                                                        );
2029
 
                                                        $avatar_col_count++;
2030
 
                                                        if ($avatar_col_count == $items_per_column)
2031
 
                                                        {
2032
 
                                                                $avatar_row_count++;
2033
 
                                                                $avatar_col_count = 0;
2034
 
                                                        }
2035
 
                                                }
2036
 
                                        }
2037
 
                                        closedir($dp2);
2038
 
                                }
2039
 
                        }
2040
 
                }
2041
 
                closedir($dp);
2042
 
        }
2043
 
 
2044
 
        if (!sizeof($avatar_list))
2045
 
        {
2046
 
                $avatar_list = array($user->lang['NO_AVATAR_CATEGORY'] => array());
2047
 
        }
2048
 
 
2049
 
        @ksort($avatar_list);
2050
 
 
2051
 
        $category = (!$category) ? key($avatar_list) : $category;
2052
 
        $avatar_categories = array_keys($avatar_list);
2053
 
 
2054
 
        $s_category_options = '';
2055
 
        foreach ($avatar_categories as $cat)
2056
 
        {
2057
 
                $s_category_options .= '<option value="' . $cat . '"' . (($cat == $category) ? ' selected="selected"' : '') . '>' . $cat . '</option>';
2058
 
        }
2059
 
 
2060
 
        $template->assign_vars(array(
2061
 
                'S_AVATARS_ENABLED'             => true,
2062
 
                'S_IN_AVATAR_GALLERY'   => true,
2063
 
                'S_CAT_OPTIONS'                 => $s_category_options)
2064
 
        );
2065
 
 
2066
 
        $avatar_list = (isset($avatar_list[$category])) ? $avatar_list[$category] : array();
2067
 
 
2068
 
        foreach ($avatar_list as $avatar_row_ary)
2069
 
        {
2070
 
                $template->assign_block_vars($block_var, array());
2071
 
 
2072
 
                foreach ($avatar_row_ary as $avatar_col_ary)
2073
 
                {
2074
 
                        $template->assign_block_vars($block_var . '.avatar_column', array(
2075
 
                                'AVATAR_IMAGE'  => $phpbb_root_path . $config['avatar_gallery_path'] . '/' . $avatar_col_ary['file'],
2076
 
                                'AVATAR_NAME'   => $avatar_col_ary['name'],
2077
 
                                'AVATAR_FILE'   => $avatar_col_ary['filename'])
2078
 
                        );
2079
 
 
2080
 
                        $template->assign_block_vars($block_var . '.avatar_option_column', array(
2081
 
                                'AVATAR_IMAGE'  => $phpbb_root_path . $config['avatar_gallery_path'] . '/' . $avatar_col_ary['file'],
2082
 
                                'S_OPTIONS_AVATAR'      => $avatar_col_ary['filename'])
2083
 
                        );
2084
 
                }
2085
 
        }
2086
 
 
2087
 
        return $avatar_list;
2088
 
}
2089
 
 
2090
 
 
2091
 
/**
2092
 
* Tries to (re-)establish avatar dimensions
2093
 
*/
2094
 
function avatar_get_dimensions($avatar, $avatar_type, &$error, $current_x = 0, $current_y = 0)
2095
 
{
2096
 
        global $config, $phpbb_root_path, $user;
2097
 
        
2098
 
        switch ($avatar_type)
2099
 
        {
2100
 
                case AVATAR_REMOTE :
2101
 
                        break;
2102
 
 
2103
 
                case AVATAR_UPLOAD :
2104
 
                        $avatar = $phpbb_root_path . $config['avatar_path'] . '/' . get_avatar_filename($avatar);
2105
 
                        break;
2106
 
                
2107
 
                case AVATAR_GALLERY :
2108
 
                        $avatar = $phpbb_root_path . $config['avatar_gallery_path'] . '/' . $avatar ;
2109
 
                        break;
2110
 
        }
2111
 
 
2112
 
        // Make sure getimagesize works...
2113
 
        if (($image_data = @getimagesize($avatar)) === false)
2114
 
        {
2115
 
                $error[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
2116
 
                return false;
2117
 
        }
2118
 
 
2119
 
        if ($image_data[0] < 2 || $image_data[1] < 2)
2120
 
        {
2121
 
                $error[] = $user->lang['AVATAR_NO_SIZE'];
2122
 
                return false;
2123
 
        }
2124
 
        
2125
 
        // try to maintain ratio
2126
 
        if (!(empty($current_x) && empty($current_y)))
2127
 
        {
2128
 
                if ($current_x != 0)
2129
 
                {
2130
 
                        $image_data[1] = (int) floor(($current_x / $image_data[0]) * $image_data[1]);
2131
 
                        $image_data[1] = min($config['avatar_max_height'], $image_data[1]);
2132
 
                        $image_data[1] = max($config['avatar_min_height'], $image_data[1]);
2133
 
                }
2134
 
                if ($current_y != 0)
2135
 
                {
2136
 
                        $image_data[0] = (int) floor(($current_y / $image_data[1]) * $image_data[0]);
2137
 
                        $image_data[0] = min($config['avatar_max_width'], $image_data[1]);
2138
 
                        $image_data[0] = max($config['avatar_min_width'], $image_data[1]);
2139
 
                }
2140
 
        }
2141
 
        return array($image_data[0], $image_data[1]);
2142
 
}
2143
 
 
2144
 
/**
2145
 
* Uploading/Changing user avatar
2146
 
*/
2147
 
function avatar_process_user(&$error, $custom_userdata = false)
2148
 
{
2149
 
        global $config, $phpbb_root_path, $auth, $user, $db;
2150
 
 
2151
 
        $data = array(
2152
 
                'uploadurl'             => request_var('uploadurl', ''),
2153
 
                'remotelink'    => request_var('remotelink', ''),
2154
 
                'width'                 => request_var('width', 0),
2155
 
                'height'                => request_var('height', 0),
2156
 
        );
2157
 
 
2158
 
        $error = validate_data($data, array(
2159
 
                'uploadurl'             => array('string', true, 5, 255),
2160
 
                'remotelink'    => array('string', true, 5, 255),
2161
 
                'width'                 => array('string', true, 1, 3),
2162
 
                'height'                => array('string', true, 1, 3),
2163
 
        ));
2164
 
 
2165
 
        if (sizeof($error))
2166
 
        {
2167
 
                return false;
2168
 
        }
2169
 
 
2170
 
        $sql_ary = array();
2171
 
 
2172
 
        if ($custom_userdata === false)
2173
 
        {
2174
 
                $userdata = &$user->data;
2175
 
        }
2176
 
        else
2177
 
        {
2178
 
                $userdata = &$custom_userdata;
2179
 
        }
2180
 
 
2181
 
        $data['user_id'] = $userdata['user_id'];
2182
 
        $change_avatar = ($custom_userdata === false) ? $auth->acl_get('u_chgavatar') : true;
2183
 
        $avatar_select = basename(request_var('avatar_select', ''));
2184
 
 
2185
 
        // Can we upload?
2186
 
        $can_upload = ($config['allow_avatar_upload'] && file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $change_avatar && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false;
2187
 
 
2188
 
        if ((!empty($_FILES['uploadfile']['name']) || $data['uploadurl']) && $can_upload)
2189
 
        {
2190
 
                list($sql_ary['user_avatar_type'], $sql_ary['user_avatar'], $sql_ary['user_avatar_width'], $sql_ary['user_avatar_height']) = avatar_upload($data, $error);
2191
 
        }
2192
 
        else if ($data['remotelink'] && $change_avatar && $config['allow_avatar_remote'])
2193
 
        {
2194
 
                list($sql_ary['user_avatar_type'], $sql_ary['user_avatar'], $sql_ary['user_avatar_width'], $sql_ary['user_avatar_height']) = avatar_remote($data, $error);
2195
 
        }
2196
 
        else if ($avatar_select && $change_avatar && $config['allow_avatar_local'])
2197
 
        {
2198
 
                $category = basename(request_var('category', ''));
2199
 
 
2200
 
                $sql_ary['user_avatar_type'] = AVATAR_GALLERY;
2201
 
                $sql_ary['user_avatar'] = $avatar_select;
2202
 
 
2203
 
                // check avatar gallery
2204
 
                if (!is_dir($phpbb_root_path . $config['avatar_gallery_path'] . '/' . $category))
2205
 
                {
2206
 
                        $sql_ary['user_avatar'] = '';
2207
 
                        $sql_ary['user_avatar_type'] = $sql_ary['user_avatar_width'] = $sql_ary['user_avatar_height'] = 0;
2208
 
                }
2209
 
                else
2210
 
                {
2211
 
                        list($sql_ary['user_avatar_width'], $sql_ary['user_avatar_height']) = getimagesize($phpbb_root_path . $config['avatar_gallery_path'] . '/' . $category . '/' . $sql_ary['user_avatar']);
2212
 
                        $sql_ary['user_avatar'] = $category . '/' . $sql_ary['user_avatar'];
2213
 
                }
2214
 
        }
2215
 
        else if (isset($_POST['delete']) && $change_avatar)
2216
 
        {
2217
 
                $sql_ary['user_avatar'] = '';
2218
 
                $sql_ary['user_avatar_type'] = $sql_ary['user_avatar_width'] = $sql_ary['user_avatar_height'] = 0;
2219
 
        }
2220
 
        else if (!empty($userdata['user_avatar']))
2221
 
        {
2222
 
                // Only update the dimensions
2223
 
                
2224
 
                if (empty($data['width']) || empty($data['height']))
2225
 
                {
2226
 
                        if ($dims = avatar_get_dimensions($userdata['user_avatar'], $userdata['user_avatar_type'], $error, $data['width'], $data['height']))
2227
 
                        {
2228
 
                                list($guessed_x, $guessed_y) = $dims;
2229
 
                                if (empty($data['width']))
2230
 
                                {
2231
 
                                        $data['width'] = $guessed_x;
2232
 
                                }
2233
 
                                if (empty($data['height']))
2234
 
                                {
2235
 
                                        $data['height'] = $guessed_y;
2236
 
                                }
2237
 
                        }
2238
 
                }
2239
 
                if (($config['avatar_max_width'] || $config['avatar_max_height']) &&
2240
 
                        (($data['width'] != $userdata['user_avatar_width']) || $data['height'] != $userdata['user_avatar_height']))
2241
 
                {
2242
 
                        if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height'])
2243
 
                        {
2244
 
                                $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']);
2245
 
                        }
2246
 
                }
2247
 
 
2248
 
                if (!sizeof($error))
2249
 
                {
2250
 
                        if ($config['avatar_min_width'] || $config['avatar_min_height'])
2251
 
                        {
2252
 
                                if ($data['width'] < $config['avatar_min_width'] || $data['height'] < $config['avatar_min_height'])
2253
 
                                {
2254
 
                                        $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']);
2255
 
                                }
2256
 
                        }
2257
 
                }
2258
 
 
2259
 
                if (!sizeof($error))
2260
 
                {
2261
 
                        $sql_ary['user_avatar_width'] = $data['width'];
2262
 
                        $sql_ary['user_avatar_height'] = $data['height'];
2263
 
                }
2264
 
        }
2265
 
 
2266
 
        if (!sizeof($error))
2267
 
        {
2268
 
                // Do we actually have any data to update?
2269
 
                if (sizeof($sql_ary))
2270
 
                {
2271
 
                        $sql = 'UPDATE ' . USERS_TABLE . '
2272
 
                                SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
2273
 
                                WHERE user_id = ' . (($custom_userdata === false) ? $user->data['user_id'] : $custom_userdata['user_id']);
2274
 
                        $db->sql_query($sql);
2275
 
 
2276
 
                        if (isset($sql_ary['user_avatar']))
2277
 
                        {
2278
 
                                $userdata = ($custom_userdata === false) ? $user->data : $custom_userdata;
2279
 
 
2280
 
                                // Delete old avatar if present
2281
 
                                if ((!empty($userdata['user_avatar']) && empty($sql_ary['user_avatar']) && $userdata['user_avatar_type'] == AVATAR_UPLOAD)
2282
 
                                   || ( !empty($userdata['user_avatar']) && !empty($sql_ary['user_avatar']) && $userdata['user_avatar_type'] == AVATAR_UPLOAD && $sql_ary['user_avatar_type'] != AVATAR_UPLOAD))
2283
 
                                {
2284
 
                                        avatar_delete('user', $userdata);
2285
 
                                }
2286
 
                        }
2287
 
                }
2288
 
        }
2289
 
 
2290
 
        return (sizeof($error)) ? false : true;
2291
 
}
2292
 
 
2293
 
//
2294
 
// Usergroup functions
2295
 
//
2296
 
 
2297
 
/**
2298
 
* Add or edit a group. If we're editing a group we only update user
2299
 
* parameters such as rank, etc. if they are changed
2300
 
*/
2301
 
function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow_desc_bbcode = false, $allow_desc_urls = false, $allow_desc_smilies = false)
2302
 
{
2303
 
        global $phpbb_root_path, $config, $db, $user, $file_upload;
2304
 
 
2305
 
        $error = array();
2306
 
        $attribute_ary = array(
2307
 
                'group_colour'                  => 'string',
2308
 
                'group_rank'                    => 'int',
2309
 
                'group_avatar'                  => 'string',
2310
 
                'group_avatar_type'             => 'int',
2311
 
                'group_avatar_width'    => 'int',
2312
 
                'group_avatar_height'   => 'int',
2313
 
 
2314
 
                'group_receive_pm'              => 'int',
2315
 
                'group_legend'                  => 'int',
2316
 
                'group_message_limit'   => 'int',
2317
 
 
2318
 
                'group_founder_manage'  => 'int',
2319
 
        );
2320
 
 
2321
 
        // Those are group-only attributes
2322
 
        $group_only_ary = array('group_receive_pm', 'group_legend', 'group_message_limit', 'group_founder_manage');
2323
 
 
2324
 
        // Check data. Limit group name length.
2325
 
        if (!utf8_strlen($name) || utf8_strlen($name) > 60)
2326
 
        {
2327
 
                $error[] = (!utf8_strlen($name)) ? $user->lang['GROUP_ERR_USERNAME'] : $user->lang['GROUP_ERR_USER_LONG'];
2328
 
        }
2329
 
        
2330
 
        $err = group_validate_groupname($group_id, $name);
2331
 
        if (!empty($err))
2332
 
        {
2333
 
                $error[] = $user->lang[$err];
2334
 
        }
2335
 
        
2336
 
        if (!in_array($type, array(GROUP_OPEN, GROUP_CLOSED, GROUP_HIDDEN, GROUP_SPECIAL, GROUP_FREE)))
2337
 
        {
2338
 
                $error[] = $user->lang['GROUP_ERR_TYPE'];
2339
 
        }
2340
 
 
2341
 
        if (!sizeof($error))
2342
 
        {
2343
 
                $user_ary = array();
2344
 
                $sql_ary = array(
2345
 
                        'group_name'                    => (string) $name,
2346
 
                        'group_desc'                    => (string) $desc,
2347
 
                        'group_desc_uid'                => '',
2348
 
                        'group_desc_bitfield'   => '',
2349
 
                        'group_type'                    => (int) $type,
2350
 
                );
2351
 
 
2352
 
                // Parse description
2353
 
                if ($desc)
2354
 
                {
2355
 
                        generate_text_for_storage($sql_ary['group_desc'], $sql_ary['group_desc_uid'], $sql_ary['group_desc_bitfield'], $sql_ary['group_desc_options'], $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies);
2356
 
                }
2357
 
 
2358
 
                if (sizeof($group_attributes))
2359
 
                {
2360
 
                        foreach ($attribute_ary as $attribute => $_type)
2361
 
                        {
2362
 
                                if (isset($group_attributes[$attribute]))
2363
 
                                {
2364
 
                                        settype($group_attributes[$attribute], $_type);
2365
 
                                        $sql_ary[$attribute] = $group_attributes[$attribute];
2366
 
                                }
2367
 
                        }
2368
 
                }
2369
 
 
2370
 
                // Setting the log message before we set the group id (if group gets added)
2371
 
                $log = ($group_id) ? 'LOG_GROUP_UPDATED' : 'LOG_GROUP_CREATED';
2372
 
 
2373
 
                $query = '';
2374
 
 
2375
 
                if ($group_id)
2376
 
                {
2377
 
                        $sql = 'SELECT user_id
2378
 
                                FROM ' . USERS_TABLE . '
2379
 
                                WHERE group_id = ' . $group_id;
2380
 
                        $result = $db->sql_query($sql);
2381
 
 
2382
 
                        while ($row = $db->sql_fetchrow($result))
2383
 
                        {
2384
 
                                $user_ary[] = $row['user_id'];
2385
 
                        }
2386
 
                        $db->sql_freeresult($result);
2387
 
 
2388
 
                        if (isset($sql_ary['group_avatar']) && !$sql_ary['group_avatar'])
2389
 
                        {
2390
 
                                remove_default_avatar($group_id, $user_ary);
2391
 
                        }
2392
 
                        if (isset($sql_ary['group_rank']) && !$sql_ary['group_rank'])
2393
 
                        {
2394
 
                                remove_default_rank($group_id, $user_ary);
2395
 
                        }
2396
 
 
2397
 
                        $sql = 'UPDATE ' . GROUPS_TABLE . '
2398
 
                                SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
2399
 
                                WHERE group_id = $group_id";
2400
 
                        $db->sql_query($sql);
2401
 
 
2402
 
                        // Since we may update the name too, we need to do this on other tables too...
2403
 
                        $sql = 'UPDATE ' . MODERATOR_CACHE_TABLE . "
2404
 
                                SET group_name = '" . $db->sql_escape($sql_ary['group_name']) . "'
2405
 
                                WHERE group_id = $group_id";
2406
 
                        $db->sql_query($sql);
2407
 
                }
2408
 
                else
2409
 
                {
2410
 
                        $sql = 'INSERT INTO ' . GROUPS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
2411
 
                        $db->sql_query($sql);
2412
 
                }
2413
 
 
2414
 
                if (!$group_id)
2415
 
                {
2416
 
                        $group_id = $db->sql_nextid();
2417
 
                        if (isset($sql_ary['group_avatar_type']) && $sql_ary['group_avatar_type'] == AVATAR_UPLOAD)
2418
 
                        {
2419
 
                                group_correct_avatar($group_id, $sql_ary['group_avatar']);
2420
 
                        }
2421
 
                }
2422
 
 
2423
 
                // Set user attributes
2424
 
                $sql_ary = array();
2425
 
                if (sizeof($group_attributes))
2426
 
                {
2427
 
                        foreach ($attribute_ary as $attribute => $_type)
2428
 
                        {
2429
 
                                if (isset($group_attributes[$attribute]) && !in_array($attribute, $group_only_ary))
2430
 
                                {
2431
 
                                        // If we are about to set an avatar, we will not overwrite user avatars if no group avatar is set...
2432
 
                                        if (strpos($attribute, 'group_avatar') === 0 && !$group_attributes[$attribute])
2433
 
                                        {
2434
 
                                                continue;
2435
 
                                        }
2436
 
 
2437
 
                                        $sql_ary[$attribute] = $group_attributes[$attribute];
2438
 
                                }
2439
 
                        }
2440
 
                }
2441
 
 
2442
 
                if (sizeof($sql_ary) && sizeof($user_ary))
2443
 
                {
2444
 
                        group_set_user_default($group_id, $user_ary, $sql_ary);
2445
 
                }
2446
 
 
2447
 
                $name = ($type == GROUP_SPECIAL) ? $user->lang['G_' . $name] : $name;
2448
 
                add_log('admin', $log, $name);
2449
 
 
2450
 
                group_update_listings($group_id);
2451
 
        }
2452
 
 
2453
 
        return (sizeof($error)) ? $error : false;
2454
 
}
2455
 
 
2456
 
 
2457
 
/**
2458
 
* Changes a group avatar's filename to conform to the naming scheme
2459
 
*/
2460
 
function group_correct_avatar($group_id, $old_entry)
2461
 
{
2462
 
        global $config, $db, $phpbb_root_path;
2463
 
 
2464
 
        $group_id               = (int)$group_id;
2465
 
        $ext                    = substr(strrchr($old_entry, '.'), 1);
2466
 
        $old_filename   = get_avatar_filename($old_entry);
2467
 
        $new_filename   = $config['avatar_salt'] . "_g$group_id.$ext";
2468
 
        $new_entry              = 'g' . $group_id . '_' . substr(time(), -5) . ".$ext";
2469
 
        
2470
 
        $avatar_path = $phpbb_root_path . $config['avatar_path'];
2471
 
        if (@rename($avatar_path . '/'. $old_filename, $avatar_path . '/' . $new_filename))
2472
 
        {
2473
 
                $sql = 'UPDATE ' . GROUPS_TABLE . '
2474
 
                        SET group_avatar = \'' . $db->sql_escape($new_entry) . "'
2475
 
                        WHERE group_id = $group_id";
2476
 
                $db->sql_query($sql);
2477
 
        }
2478
 
}
2479
 
 
2480
 
 
2481
 
/**
2482
 
* Remove avatar also for users not having the group as default
2483
 
*/
2484
 
function avatar_remove_db($avatar_name)
2485
 
{
2486
 
        global $config, $db;
2487
 
        
2488
 
        $sql = 'UPDATE ' . USERS_TABLE . "
2489
 
                SET user_avatar = '',
2490
 
                user_avatar_type = 0
2491
 
                WHERE user_avatar = '" . $db->sql_escape($avatar_name) . '\'';
2492
 
        $db->sql_query($sql);
2493
 
}
2494
 
 
2495
 
 
2496
 
/**
2497
 
* Group Delete
2498
 
*/
2499
 
function group_delete($group_id, $group_name = false)
2500
 
{
2501
 
        global $db, $phpbb_root_path, $phpEx;
2502
 
 
2503
 
        if (!$group_name)
2504
 
        {
2505
 
                $group_name = get_group_name($group_id);
2506
 
        }
2507
 
 
2508
 
        $start = 0;
2509
 
 
2510
 
        do
2511
 
        {
2512
 
                $user_id_ary = $username_ary = array();
2513
 
 
2514
 
                // Batch query for group members, call group_user_del
2515
 
                $sql = 'SELECT u.user_id, u.username
2516
 
                        FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . " u
2517
 
                        WHERE ug.group_id = $group_id
2518
 
                                AND u.user_id = ug.user_id";
2519
 
                $result = $db->sql_query_limit($sql, 200, $start);
2520
 
 
2521
 
                if ($row = $db->sql_fetchrow($result))
2522
 
                {
2523
 
                        do
2524
 
                        {
2525
 
                                $user_id_ary[] = $row['user_id'];
2526
 
                                $username_ary[] = $row['username'];
2527
 
 
2528
 
                                $start++;
2529
 
                        }
2530
 
                        while ($row = $db->sql_fetchrow($result));
2531
 
 
2532
 
                        group_user_del($group_id, $user_id_ary, $username_ary, $group_name);
2533
 
                }
2534
 
                else
2535
 
                {
2536
 
                        $start = 0;
2537
 
                }
2538
 
                $db->sql_freeresult($result);
2539
 
        }
2540
 
        while ($start);
2541
 
 
2542
 
        // Delete group
2543
 
        $sql = 'DELETE FROM ' . GROUPS_TABLE . "
2544
 
                WHERE group_id = $group_id";
2545
 
        $db->sql_query($sql);
2546
 
 
2547
 
        // Delete auth entries from the groups table
2548
 
        $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . "
2549
 
                WHERE group_id = $group_id";
2550
 
        $db->sql_query($sql);
2551
 
 
2552
 
        // Re-cache moderators
2553
 
        if (!function_exists('cache_moderators'))
2554
 
        {
2555
 
                include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
2556
 
        }
2557
 
 
2558
 
        cache_moderators();
2559
 
 
2560
 
        add_log('admin', 'LOG_GROUP_DELETE', $group_name);
2561
 
 
2562
 
        // Return false - no error
2563
 
        return false;
2564
 
}
2565
 
 
2566
 
/**
2567
 
* Add user(s) to group
2568
 
*
2569
 
* @return mixed false if no errors occurred, else the user lang string for the relevant error, for example 'NO_USER'
2570
 
*/
2571
 
function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $default = false, $leader = 0, $pending = 0, $group_attributes = false)
2572
 
{
2573
 
        global $db, $auth;
2574
 
 
2575
 
        // We need both username and user_id info
2576
 
        $result = user_get_id_name($user_id_ary, $username_ary);
2577
 
 
2578
 
        if (!sizeof($user_id_ary) || $result !== false)
2579
 
        {
2580
 
                return 'NO_USER';
2581
 
        }
2582
 
 
2583
 
        // Remove users who are already members of this group
2584
 
        $sql = 'SELECT user_id, group_leader
2585
 
                FROM ' . USER_GROUP_TABLE . '
2586
 
                WHERE ' . $db->sql_in_set('user_id', $user_id_ary) . "
2587
 
                        AND group_id = $group_id";
2588
 
        $result = $db->sql_query($sql);
2589
 
 
2590
 
        $add_id_ary = $update_id_ary = array();
2591
 
        while ($row = $db->sql_fetchrow($result))
2592
 
        {
2593
 
                $add_id_ary[] = (int) $row['user_id'];
2594
 
 
2595
 
                if ($leader && !$row['group_leader'])
2596
 
                {
2597
 
                        $update_id_ary[] = (int) $row['user_id'];
2598
 
                }
2599
 
        }
2600
 
        $db->sql_freeresult($result);
2601
 
 
2602
 
        // Do all the users exist in this group?
2603
 
        $add_id_ary = array_diff($user_id_ary, $add_id_ary);
2604
 
 
2605
 
        // If we have no users
2606
 
        if (!sizeof($add_id_ary) && !sizeof($update_id_ary))
2607
 
        {
2608
 
                return 'GROUP_USERS_EXIST';
2609
 
        }
2610
 
 
2611
 
        $db->sql_transaction('begin');
2612
 
 
2613
 
        // Insert the new users
2614
 
        if (sizeof($add_id_ary))
2615
 
        {
2616
 
                $sql_ary = array();
2617
 
 
2618
 
                foreach ($add_id_ary as $user_id)
2619
 
                {
2620
 
                        $sql_ary[] = array(
2621
 
                                'user_id'               => (int) $user_id,
2622
 
                                'group_id'              => (int) $group_id,
2623
 
                                'group_leader'  => (int) $leader,
2624
 
                                'user_pending'  => (int) $pending,
2625
 
                        );
2626
 
                }
2627
 
 
2628
 
                $db->sql_multi_insert(USER_GROUP_TABLE, $sql_ary);
2629
 
        }
2630
 
 
2631
 
        if (sizeof($update_id_ary))
2632
 
        {
2633
 
                $sql = 'UPDATE ' . USER_GROUP_TABLE . '
2634
 
                        SET group_leader = 1
2635
 
                        WHERE ' . $db->sql_in_set('user_id', $update_id_ary) . "
2636
 
                                AND group_id = $group_id";
2637
 
                $db->sql_query($sql);
2638
 
        }
2639
 
 
2640
 
        if ($default)
2641
 
        {
2642
 
                group_set_user_default($group_id, $user_id_ary, $group_attributes);
2643
 
        }
2644
 
 
2645
 
        $db->sql_transaction('commit');
2646
 
 
2647
 
        // Clear permissions cache of relevant users
2648
 
        $auth->acl_clear_prefetch($user_id_ary);
2649
 
 
2650
 
        if (!$group_name)
2651
 
        {
2652
 
                $group_name = get_group_name($group_id);
2653
 
        }
2654
 
 
2655
 
        $log = ($leader) ? 'LOG_MODS_ADDED' : 'LOG_USERS_ADDED';
2656
 
 
2657
 
        add_log('admin', $log, $group_name, implode(', ', $username_ary));
2658
 
 
2659
 
        group_update_listings($group_id);
2660
 
 
2661
 
        // Return false - no error
2662
 
        return false;
2663
 
}
2664
 
 
2665
 
/**
2666
 
* Remove a user/s from a given group. When we remove users we update their
2667
 
* default group_id. We do this by examining which "special" groups they belong
2668
 
* to. The selection is made based on a reasonable priority system
2669
 
*
2670
 
* @return false if no errors occurred, else the user lang string for the relevant error, for example 'NO_USER'
2671
 
*/
2672
 
function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false)
2673
 
{
2674
 
        global $db, $auth;
2675
 
 
2676
 
        $group_order = array('ADMINISTRATORS', 'GLOBAL_MODERATORS', 'REGISTERED_COPPA', 'REGISTERED', 'BOTS', 'GUESTS');
2677
 
 
2678
 
        // We need both username and user_id info
2679
 
        $result = user_get_id_name($user_id_ary, $username_ary);
2680
 
 
2681
 
        if (!sizeof($user_id_ary) || $result !== false)
2682
 
        {
2683
 
                return 'NO_USER';
2684
 
        }
2685
 
 
2686
 
        $sql = 'SELECT *
2687
 
                FROM ' . GROUPS_TABLE . '
2688
 
                WHERE ' . $db->sql_in_set('group_name', $group_order);
2689
 
        $result = $db->sql_query($sql);
2690
 
 
2691
 
        $group_order_id = $special_group_data = array();
2692
 
        while ($row = $db->sql_fetchrow($result))
2693
 
        {
2694
 
                $group_order_id[$row['group_name']] = $row['group_id'];
2695
 
 
2696
 
                $special_group_data[$row['group_id']] = array(
2697
 
                        'group_colour'                  => $row['group_colour'],
2698
 
                        'group_rank'                            => $row['group_rank'],
2699
 
                );
2700
 
 
2701
 
                // Only set the group avatar if one is defined...
2702
 
                if ($row['group_avatar'])
2703
 
                {
2704
 
                        $special_group_data[$row['group_id']] = array_merge($special_group_data[$row['group_id']], array(
2705
 
                                'group_avatar'                  => $row['group_avatar'],
2706
 
                                'group_avatar_type'             => $row['group_avatar_type'],
2707
 
                                'group_avatar_width'            => $row['group_avatar_width'],
2708
 
                                'group_avatar_height'   => $row['group_avatar_height'])
2709
 
                        );
2710
 
                }
2711
 
        }
2712
 
        $db->sql_freeresult($result);
2713
 
 
2714
 
        // Get users default groups - we only need to reset default group membership if the group from which the user gets removed is set as default
2715
 
        $sql = 'SELECT user_id, group_id
2716
 
                FROM ' . USERS_TABLE . '
2717
 
                WHERE ' . $db->sql_in_set('user_id', $user_id_ary);
2718
 
        $result = $db->sql_query($sql);
2719
 
 
2720
 
        $default_groups = array();
2721
 
        while ($row = $db->sql_fetchrow($result))
2722
 
        {
2723
 
                $default_groups[$row['user_id']] = $row['group_id'];
2724
 
        }
2725
 
        $db->sql_freeresult($result);
2726
 
 
2727
 
        // What special group memberships exist for these users?
2728
 
        $sql = 'SELECT g.group_id, g.group_name, ug.user_id
2729
 
                FROM ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g
2730
 
                WHERE ' . $db->sql_in_set('ug.user_id', $user_id_ary) . "
2731
 
                        AND g.group_id = ug.group_id
2732
 
                        AND g.group_id <> $group_id
2733
 
                        AND g.group_type = " . GROUP_SPECIAL . '
2734
 
                ORDER BY ug.user_id, g.group_id';
2735
 
        $result = $db->sql_query($sql);
2736
 
 
2737
 
        $temp_ary = array();
2738
 
        while ($row = $db->sql_fetchrow($result))
2739
 
        {
2740
 
                if ($default_groups[$row['user_id']] == $group_id && (!isset($temp_ary[$row['user_id']]) || array_search($row['group_name'], $group_order) < $temp_ary[$row['user_id']]))
2741
 
                {
2742
 
                        $temp_ary[$row['user_id']] = $row['group_id'];
2743
 
                }
2744
 
        }
2745
 
        $db->sql_freeresult($result);
2746
 
 
2747
 
        $sql_where_ary = array();
2748
 
        foreach ($temp_ary as $uid => $gid)
2749
 
        {
2750
 
                $sql_where_ary[$gid][] = $uid;
2751
 
        }
2752
 
        unset($temp_ary);
2753
 
 
2754
 
        foreach ($special_group_data as $gid => $default_data_ary)
2755
 
        {
2756
 
                if (isset($sql_where_ary[$gid]) && sizeof($sql_where_ary[$gid]))
2757
 
                {
2758
 
                        remove_default_rank($group_id, $sql_where_ary[$gid]);
2759
 
                        remove_default_avatar($group_id, $sql_where_ary[$gid]);
2760
 
                        group_set_user_default($gid, $sql_where_ary[$gid], $default_data_ary);
2761
 
                }
2762
 
        }
2763
 
        unset($special_group_data);
2764
 
 
2765
 
        $sql = 'DELETE FROM ' . USER_GROUP_TABLE . "
2766
 
                WHERE group_id = $group_id
2767
 
                        AND " . $db->sql_in_set('user_id', $user_id_ary);
2768
 
        $db->sql_query($sql);
2769
 
 
2770
 
        // Clear permissions cache of relevant users
2771
 
        $auth->acl_clear_prefetch($user_id_ary);
2772
 
 
2773
 
        if (!$group_name)
2774
 
        {
2775
 
                $group_name = get_group_name($group_id);
2776
 
        }
2777
 
 
2778
 
        $log = 'LOG_GROUP_REMOVE';
2779
 
 
2780
 
        add_log('admin', $log, $group_name, implode(', ', $username_ary));
2781
 
 
2782
 
        group_update_listings($group_id);
2783
 
 
2784
 
        // Return false - no error
2785
 
        return false;
2786
 
}
2787
 
 
2788
 
 
2789
 
/**
2790
 
* Removes the group avatar of the default group from the users in user_ids who have that group as default.
2791
 
*/
2792
 
function remove_default_avatar($group_id, $user_ids)
2793
 
{
2794
 
        global $db;
2795
 
 
2796
 
        if (!is_array($user_ids))
2797
 
        {
2798
 
                $user_ids = array($user_ids);
2799
 
        }
2800
 
        if (empty($user_ids))
2801
 
        {
2802
 
                return false;
2803
 
        }
2804
 
 
2805
 
        $user_ids = array_map('intval', $user_ids);
2806
 
 
2807
 
        $sql = 'SELECT *
2808
 
                FROM ' . GROUPS_TABLE . '
2809
 
                WHERE group_id = ' . (int)$group_id;
2810
 
        $result = $db->sql_query($sql);
2811
 
        if (!$row = $db->sql_fetchrow($result))
2812
 
        {
2813
 
                $db->sql_freeresult($result);
2814
 
                return false;
2815
 
        }
2816
 
        $db->sql_freeresult($result);
2817
 
        
2818
 
        $sql = 'UPDATE ' . USERS_TABLE . "
2819
 
                SET user_avatar = '',
2820
 
                        user_avatar_type = 0,
2821
 
                        user_avatar_width = 0,
2822
 
                        user_avatar_height = 0
2823
 
                WHERE group_id = " . (int) $group_id . "
2824
 
                AND user_avatar = '" . $db->sql_escape($row['group_avatar']) . "'
2825
 
                AND " . $db->sql_in_set('user_id', $user_ids);
2826
 
        
2827
 
        $db->sql_query($sql);
2828
 
}
2829
 
 
2830
 
/**
2831
 
* Removes the group rank of the default group from the users in user_ids who have that group as default.
2832
 
*/
2833
 
function remove_default_rank($group_id, $user_ids)
2834
 
{
2835
 
        global $db;
2836
 
 
2837
 
        if (!is_array($user_ids))
2838
 
        {
2839
 
                $user_ids = array($user_ids);
2840
 
        }
2841
 
        if (empty($user_ids))
2842
 
        {
2843
 
                return false;
2844
 
        }
2845
 
 
2846
 
        $user_ids = array_map('intval', $user_ids);
2847
 
 
2848
 
        $sql = 'SELECT *
2849
 
                FROM ' . GROUPS_TABLE . '
2850
 
                WHERE group_id = ' . (int)$group_id;
2851
 
        $result = $db->sql_query($sql);
2852
 
        if (!$row = $db->sql_fetchrow($result))
2853
 
        {
2854
 
                $db->sql_freeresult($result);
2855
 
                return false;
2856
 
        }
2857
 
        $db->sql_freeresult($result);
2858
 
 
2859
 
        $sql = 'UPDATE ' . USERS_TABLE . '
2860
 
                SET user_rank = 0
2861
 
                WHERE group_id = ' . (int)$group_id . '
2862
 
                AND user_rank <> 0
2863
 
                AND user_rank = ' . (int)$row['group_rank'] . '
2864
 
                AND ' . $db->sql_in_set('user_id', $user_ids);
2865
 
        $db->sql_query($sql);
2866
 
}
2867
 
 
2868
 
/**
2869
 
* This is used to promote (to leader), demote or set as default a member/s
2870
 
*/
2871
 
function group_user_attributes($action, $group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $group_attributes = false)
2872
 
{
2873
 
        global $db, $auth, $phpbb_root_path, $phpEx, $config;
2874
 
 
2875
 
        // We need both username and user_id info
2876
 
        $result = user_get_id_name($user_id_ary, $username_ary);
2877
 
 
2878
 
        if (!sizeof($user_id_ary) || $result !== false)
2879
 
        {
2880
 
                return false;
2881
 
        }
2882
 
 
2883
 
        if (!$group_name)
2884
 
        {
2885
 
                $group_name = get_group_name($group_id);
2886
 
        }
2887
 
 
2888
 
        switch ($action)
2889
 
        {
2890
 
                case 'demote':
2891
 
                case 'promote':
2892
 
                        $sql = 'UPDATE ' . USER_GROUP_TABLE . '
2893
 
                                SET group_leader = ' . (($action == 'promote') ? 1 : 0) . "
2894
 
                                WHERE group_id = $group_id
2895
 
                                        AND " . $db->sql_in_set('user_id', $user_id_ary);
2896
 
                        $db->sql_query($sql);
2897
 
 
2898
 
                        $log = ($action == 'promote') ? 'LOG_GROUP_PROMOTED' : 'LOG_GROUP_DEMOTED';
2899
 
                break;
2900
 
 
2901
 
                case 'approve':
2902
 
                        // Make sure we only approve those which are pending ;)
2903
 
                        $sql = 'SELECT u.user_id, u.user_email, u.username, u.username_clean, u.user_notify_type, u.user_jabber, u.user_lang
2904
 
                                FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug
2905
 
                                WHERE ug.group_id = ' . $group_id . '
2906
 
                                        AND ug.user_pending = 1
2907
 
                                        AND ug.user_id = u.user_id
2908
 
                                        AND ' . $db->sql_in_set('ug.user_id', $user_id_ary);
2909
 
                        $result = $db->sql_query($sql);
2910
 
 
2911
 
                        $user_id_ary = $email_users = array();
2912
 
                        while ($row = $db->sql_fetchrow($result))
2913
 
                        {
2914
 
                                $user_id_ary[] = $row['user_id'];
2915
 
                                $email_users[] = $row;
2916
 
                        }
2917
 
                        $db->sql_freeresult($result);
2918
 
 
2919
 
                        if (!sizeof($user_id_ary))
2920
 
                        {
2921
 
                                return false;
2922
 
                        }
2923
 
 
2924
 
                        $sql = 'UPDATE ' . USER_GROUP_TABLE . "
2925
 
                                SET user_pending = 0
2926
 
                                WHERE group_id = $group_id
2927
 
                                        AND " . $db->sql_in_set('user_id', $user_id_ary);
2928
 
                        $db->sql_query($sql);
2929
 
 
2930
 
                        // Send approved email to users...
2931
 
                        include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
2932
 
                        $messenger = new messenger();
2933
 
 
2934
 
                        foreach ($email_users as $row)
2935
 
                        {
2936
 
                                $messenger->template('group_approved', $row['user_lang']);
2937
 
 
2938
 
                                $messenger->to($row['user_email'], $row['username']);
2939
 
                                $messenger->im($row['user_jabber'], $row['username']);
2940
 
 
2941
 
                                $messenger->assign_vars(array(
2942
 
                                        'USERNAME'              => htmlspecialchars_decode($row['username']),
2943
 
                                        'GROUP_NAME'    => htmlspecialchars_decode($group_name),
2944
 
                                        'U_GROUP'               => generate_board_url() . "/ucp.$phpEx?i=groups&mode=membership")
2945
 
                                );
2946
 
 
2947
 
                                $messenger->send($row['user_notify_type']);
2948
 
                        }
2949
 
 
2950
 
                        $messenger->save_queue();
2951
 
 
2952
 
                        $log = 'LOG_USERS_APPROVED';
2953
 
                break;
2954
 
 
2955
 
                case 'default':
2956
 
                        $sql = 'SELECT user_id, group_id FROM ' . USERS_TABLE . '
2957
 
                                WHERE ' . $db->sql_in_set('user_id', $user_id_ary, false, true);
2958
 
                        $result = $db->sql_query($sql);
2959
 
 
2960
 
                        $groups = array();
2961
 
                        while ($row = $db->sql_fetchrow($result))
2962
 
                        {
2963
 
                                if (!isset($groups[$row['group_id']]))
2964
 
                                {
2965
 
                                        $groups[$row['group_id']] = array();
2966
 
                                }
2967
 
                                $groups[$row['group_id']][] = $row['user_id'];
2968
 
                        }
2969
 
                        $db->sql_freeresult($result);
2970
 
 
2971
 
                        foreach ($groups as $gid => $uids)
2972
 
                        {
2973
 
                                remove_default_rank($gid, $uids);
2974
 
                                remove_default_avatar($gid, $uids);
2975
 
                        }
2976
 
                        group_set_user_default($group_id, $user_id_ary, $group_attributes);
2977
 
                        $log = 'LOG_GROUP_DEFAULTS';
2978
 
                break;
2979
 
        }
2980
 
 
2981
 
        // Clear permissions cache of relevant users
2982
 
        $auth->acl_clear_prefetch($user_id_ary);
2983
 
 
2984
 
        add_log('admin', $log, $group_name, implode(', ', $username_ary));
2985
 
 
2986
 
        group_update_listings($group_id);
2987
 
 
2988
 
        return true;
2989
 
}
2990
 
 
2991
 
/**
2992
 
* A small version of validate_username to check for a group name's existence. To be called directly.
2993
 
*/
2994
 
function group_validate_groupname($group_id, $group_name)
2995
 
{
2996
 
        global $config, $db;
2997
 
 
2998
 
        $group_name =  utf8_clean_string($group_name);
2999
 
 
3000
 
        if (!empty($group_id))
3001
 
        {
3002
 
                $sql = 'SELECT group_name
3003
 
                        FROM ' . GROUPS_TABLE . '
3004
 
                        WHERE group_id = ' . (int) $group_id;
3005
 
                $result = $db->sql_query($sql);
3006
 
                $row = $db->sql_fetchrow($result);
3007
 
                $db->sql_freeresult($result);
3008
 
 
3009
 
                if (!$row)
3010
 
                {
3011
 
                        return false;
3012
 
                }
3013
 
 
3014
 
                $allowed_groupname = utf8_clean_string($row['group_name']);
3015
 
 
3016
 
                if ($allowed_groupname == $group_name)
3017
 
                {
3018
 
                        return false;
3019
 
                }
3020
 
        }
3021
 
 
3022
 
        $sql = 'SELECT group_name
3023
 
                FROM ' . GROUPS_TABLE . "
3024
 
                WHERE LOWER(group_name) = '" . $db->sql_escape(utf8_strtolower($group_name)) . "'";
3025
 
        $result = $db->sql_query($sql);
3026
 
        $row = $db->sql_fetchrow($result);
3027
 
        $db->sql_freeresult($result);
3028
 
        
3029
 
        if ($row)
3030
 
        {
3031
 
                return 'GROUP_NAME_TAKEN';
3032
 
        }
3033
 
 
3034
 
        return false;
3035
 
}
3036
 
 
3037
 
/**
3038
 
* Set users default group
3039
 
*
3040
 
* @private
3041
 
*/
3042
 
function group_set_user_default($group_id, $user_id_ary, $group_attributes = false, $update_listing = false)
3043
 
{
3044
 
        global $db;
3045
 
 
3046
 
        if (empty($user_id_ary))
3047
 
        {
3048
 
                return;
3049
 
        }
3050
 
 
3051
 
        $attribute_ary = array(
3052
 
                'group_colour'                  => 'string',
3053
 
                'group_rank'                    => 'int',
3054
 
                'group_avatar'                  => 'string',
3055
 
                'group_avatar_type'             => 'int',
3056
 
                'group_avatar_width'    => 'int',
3057
 
                'group_avatar_height'   => 'int',
3058
 
        );
3059
 
 
3060
 
        $sql_ary = array(
3061
 
                'group_id'              => $group_id
3062
 
        );
3063
 
 
3064
 
        // Were group attributes passed to the function? If not we need to obtain them
3065
 
        if ($group_attributes === false)
3066
 
        {
3067
 
                $sql = 'SELECT ' . implode(', ', array_keys($attribute_ary)) . '
3068
 
                        FROM ' . GROUPS_TABLE . "
3069
 
                        WHERE group_id = $group_id";
3070
 
                $result = $db->sql_query($sql);
3071
 
                $group_attributes = $db->sql_fetchrow($result);
3072
 
                $db->sql_freeresult($result);
3073
 
        }
3074
 
 
3075
 
        foreach ($attribute_ary as $attribute => $type)
3076
 
        {
3077
 
                if (isset($group_attributes[$attribute]))
3078
 
                {
3079
 
                        // If we are about to set an avatar or rank, we will not overwrite with empty, unless we are not actually changing the default group
3080
 
                        if ((strpos($attribute, 'group_avatar') === 0 || strpos($attribute, 'group_rank') === 0) && !$group_attributes[$attribute])
3081
 
                        {
3082
 
                                continue;
3083
 
                        }
3084
 
 
3085
 
                        settype($group_attributes[$attribute], $type);
3086
 
                        $sql_ary[str_replace('group_', 'user_', $attribute)] = $group_attributes[$attribute];
3087
 
                }
3088
 
        }
3089
 
 
3090
 
        // Before we update the user attributes, we will make a list of those having now the group avatar assigned
3091
 
        if (in_array('user_avatar', array_keys($sql_ary)))
3092
 
        {
3093
 
                // Ok, get the original avatar data from users having an uploaded one (we need to remove these from the filesystem)
3094
 
                $sql = 'SELECT user_id, group_id, user_avatar
3095
 
                        FROM ' . USERS_TABLE . '
3096
 
                        WHERE ' . $db->sql_in_set('user_id', $user_id_ary) . '
3097
 
                                AND user_avatar_type = ' . AVATAR_UPLOAD;
3098
 
                $result = $db->sql_query($sql);
3099
 
 
3100
 
                while ($row = $db->sql_fetchrow($result))
3101
 
                {
3102
 
                        avatar_delete('user', $row);
3103
 
                }
3104
 
                $db->sql_freeresult($result);
3105
 
        }
3106
 
        else
3107
 
        {
3108
 
                unset($sql_ary['user_avatar_type']);
3109
 
                unset($sql_ary['user_avatar_height']);
3110
 
                unset($sql_ary['user_avatar_width']);
3111
 
        }
3112
 
 
3113
 
        $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
3114
 
                WHERE ' . $db->sql_in_set('user_id', $user_id_ary);
3115
 
        $db->sql_query($sql);
3116
 
 
3117
 
        if (in_array('user_colour', array_keys($sql_ary)))
3118
 
        {
3119
 
                // Update any cached colour information for these users
3120
 
                $sql = 'UPDATE ' . FORUMS_TABLE . " SET forum_last_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "'
3121
 
                        WHERE " . $db->sql_in_set('forum_last_poster_id', $user_id_ary);
3122
 
                $db->sql_query($sql);
3123
 
 
3124
 
                $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_first_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "'
3125
 
                        WHERE " . $db->sql_in_set('topic_poster', $user_id_ary);
3126
 
                $db->sql_query($sql);
3127
 
 
3128
 
                $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_last_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "'
3129
 
                        WHERE " . $db->sql_in_set('topic_last_poster_id', $user_id_ary);
3130
 
                $db->sql_query($sql);
3131
 
 
3132
 
                global $config;
3133
 
 
3134
 
                if (in_array($config['newest_user_id'], $user_id_ary))
3135
 
                {
3136
 
                        set_config('newest_user_colour', $sql_ary['user_colour'], true);
3137
 
                }
3138
 
        }
3139
 
 
3140
 
        if ($update_listing)
3141
 
        {
3142
 
                group_update_listings($group_id);
3143
 
        }
3144
 
}
3145
 
 
3146
 
/**
3147
 
* Get group name
3148
 
*/
3149
 
function get_group_name($group_id)
3150
 
{
3151
 
        global $db, $user;
3152
 
 
3153
 
        $sql = 'SELECT group_name, group_type
3154
 
                FROM ' . GROUPS_TABLE . '
3155
 
                WHERE group_id = ' . (int) $group_id;
3156
 
        $result = $db->sql_query($sql);
3157
 
        $row = $db->sql_fetchrow($result);
3158
 
        $db->sql_freeresult($result);
3159
 
 
3160
 
        if (!$row)
3161
 
        {
3162
 
                return '';
3163
 
        }
3164
 
 
3165
 
        return ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
3166
 
}
3167
 
 
3168
 
/**
3169
 
* Obtain either the members of a specified group, the groups the specified user is subscribed to
3170
 
* or checking if a specified user is in a specified group. This function does not return pending memberships.
3171
 
*
3172
 
* Note: Never use this more than once... first group your users/groups
3173
 
*/
3174
 
function group_memberships($group_id_ary = false, $user_id_ary = false, $return_bool = false)
3175
 
{
3176
 
        global $db;
3177
 
 
3178
 
        if (!$group_id_ary && !$user_id_ary)
3179
 
        {
3180
 
                return true;
3181
 
        }
3182
 
 
3183
 
        if ($user_id_ary)
3184
 
        {
3185
 
                $user_id_ary = (!is_array($user_id_ary)) ? array($user_id_ary) : $user_id_ary;
3186
 
        }
3187
 
 
3188
 
        if ($group_id_ary)
3189
 
        {
3190
 
                $group_id_ary = (!is_array($group_id_ary)) ? array($group_id_ary) : $group_id_ary;
3191
 
        }
3192
 
 
3193
 
        $sql = 'SELECT ug.*, u.username, u.username_clean, u.user_email
3194
 
                FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u
3195
 
                WHERE ug.user_id = u.user_id
3196
 
                        AND ug.user_pending = 0 AND ';
3197
 
 
3198
 
        if ($group_id_ary)
3199
 
        {
3200
 
                $sql .= ' ' . $db->sql_in_set('ug.group_id', $group_id_ary);
3201
 
        }
3202
 
 
3203
 
        if ($user_id_ary)
3204
 
        {
3205
 
                $sql .= ($group_id_ary) ? ' AND ' : ' ';
3206
 
                $sql .= $db->sql_in_set('ug.user_id', $user_id_ary);
3207
 
        }
3208
 
 
3209
 
        $result = ($return_bool) ? $db->sql_query_limit($sql, 1) : $db->sql_query($sql);
3210
 
 
3211
 
        $row = $db->sql_fetchrow($result);
3212
 
 
3213
 
        if ($return_bool)
3214
 
        {
3215
 
                $db->sql_freeresult($result);
3216
 
                return ($row) ? true : false;
3217
 
        }
3218
 
 
3219
 
        if (!$row)
3220
 
        {
3221
 
                return false;
3222
 
        }
3223
 
 
3224
 
        $return = array();
3225
 
 
3226
 
        do
3227
 
        {
3228
 
                $return[] = $row;
3229
 
        }
3230
 
        while ($row = $db->sql_fetchrow($result));
3231
 
 
3232
 
        $db->sql_freeresult($result);
3233
 
 
3234
 
        return $return;
3235
 
}
3236
 
 
3237
 
/**
3238
 
* Re-cache moderators and foes if group has a_ or m_ permissions
3239
 
*/
3240
 
function group_update_listings($group_id)
3241
 
{
3242
 
        global $auth;
3243
 
 
3244
 
        $hold_ary = $auth->acl_group_raw_data($group_id, array('a_', 'm_'));
3245
 
 
3246
 
        if (!sizeof($hold_ary))
3247
 
        {
3248
 
                return;
3249
 
        }
3250
 
 
3251
 
        $mod_permissions = $admin_permissions = false;
3252
 
 
3253
 
        foreach ($hold_ary as $g_id => $forum_ary)
3254
 
        {
3255
 
                foreach ($forum_ary as $forum_id => $auth_ary)
3256
 
                {
3257
 
                        foreach ($auth_ary as $auth_option => $setting)
3258
 
                        {
3259
 
                                if ($mod_permissions && $admin_permissions)
3260
 
                                {
3261
 
                                        break 3;
3262
 
                                }
3263
 
 
3264
 
                                if ($setting != ACL_YES)
3265
 
                                {
3266
 
                                        continue;
3267
 
                                }
3268
 
 
3269
 
                                if ($auth_option == 'm_')
3270
 
                                {
3271
 
                                        $mod_permissions = true;
3272
 
                                }
3273
 
 
3274
 
                                if ($auth_option == 'a_')
3275
 
                                {
3276
 
                                        $admin_permissions = true;
3277
 
                                }
3278
 
                        }
3279
 
                }
3280
 
        }
3281
 
 
3282
 
        if ($mod_permissions)
3283
 
        {
3284
 
                if (!function_exists('cache_moderators'))
3285
 
                {
3286
 
                        global $phpbb_root_path, $phpEx;
3287
 
                        include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
3288
 
                }
3289
 
                cache_moderators();
3290
 
        }
3291
 
 
3292
 
        if ($mod_permissions || $admin_permissions)
3293
 
        {
3294
 
                if (!function_exists('update_foes'))
3295
 
                {
3296
 
                        global $phpbb_root_path, $phpEx;
3297
 
                        include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
3298
 
                }
3299
 
                update_foes(array($group_id));
3300
 
        }
3301
 
}
3302
 
 
3303
 
?>
 
 
b'\\ No newline at end of file'