phpBB
Statistics
| Revision:

root / branches / phpBB-3_0_0 / phpBB / includes / functions_convert.php

History | View | Annotate | Download (60.7 kB)

1
<?php
2
/**
3
*
4
* @package install
5
* @version $Id: functions_convert.php 11656 2012-01-02 19:00:08Z git-gate $
6
* @copyright (c) 2006 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
* Default avatar width/height
21
* @ignore
22
*/
23
define('DEFAULT_AVATAR_X', 80);
24
define('DEFAULT_AVATAR_Y', 80);
25
26
// Global functions - all functions can be used by convertors
27
28
// SIMPLE FUNCTIONS
29
30
/**
31
* Return the preceding value
32
*/
33
function dec($var)
34
{
35
        return --$var;
36
}
37
38
/**
39
* Return the next value
40
*/
41
function inc($var)
42
{
43
        return ++$var;
44
}
45
46
/**
47
* Return whether the value is positive
48
*/
49
function is_positive($n)
50
{
51
        return ($n > 0) ? 1 : 0;
52
}
53
54
/**
55
* Boolean inverse of the value
56
*/
57
function not($var)
58
{
59
        return ($var) ? 0 : 1;
60
}
61
62
/**
63
* Convert a textual value to it's equivalent boolean value
64
*
65
* @param string $str String to convert (converts yes, on, y, 1 and true to boolean true)
66
* @return boolean The equivalent value
67
*/
68
function str_to_bool($str)
69
{
70
        $str = strtolower($str);
71
        return ($str == 'yes' || $str == 'on' || $str == 'y' || $str == 'true' || $str == '1') ? true : false;
72
}
73
74
/**
75
* Function to mimic php's empty() function (it is the same)
76
*/
77
function is_empty($mixed)
78
{
79
        return empty($mixed);
80
}
81
82
/**
83
* Convert the name of a user's primary group to the appropriate equivalent phpBB group id
84
*
85
* @param string $status The name of the group
86
* @return int The group_id corresponding to the equivalent group
87
*/
88
function str_to_primary_group($status)
89
{
90
        switch (ucfirst(strtolower($status)))
91
        {
92
                case 'Administrator':
93
                        return get_group_id('administrators');
94
                break;
95
96
                case 'Super moderator':
97
                case 'Global moderator':
98
                case 'Moderator':
99
                        return get_group_id('global_moderators');
100
                break;
101
102
                case 'Guest':
103
                case 'Anonymous':
104
                        return get_group_id('guests');
105
                break;
106
107
                default:
108
                        return get_group_id('registered');
109
                break;
110
        }
111
}
112
113
/**
114
* Convert a boolean into the appropriate phpBB constant indicating whether the item is locked
115
*/
116
function is_item_locked($bool)
117
{
118
        return ($bool) ? ITEM_LOCKED : ITEM_UNLOCKED;
119
}
120
121
/**
122
* Convert a value from days to seconds
123
*/
124
function days_to_seconds($days)
125
{
126
        return ($days * 86400);
127
}
128
129
/**
130
* Determine whether a user is anonymous and return the appropriate new user_id
131
*/
132
function is_user_anonymous($user_id)
133
{
134
        return ($user_id > ANONYMOUS) ? $user_id : ANONYMOUS;
135
}
136
137
/**
138
* Generate a key value based on existing values
139
*
140
* @param int $pad Amount to add to the maximum value
141
* @return int Key value
142
*/
143
function auto_id($pad = 0)
144
{
145
        global $auto_id, $convert_row;
146
147
        if (!empty($convert_row['max_id']))
148
        {
149
                return $convert_row['max_id'] + $pad;
150
        }
151
152
        return $auto_id + $pad;
153
}
154
155
/**
156
* Convert a boolean into the appropriate phpBB constant indicating whether the user is active
157
*/
158
function set_user_type($user_active)
159
{
160
        return ($user_active) ? USER_NORMAL : USER_INACTIVE;
161
}
162
163
/**
164
* Convert a value from minutes to hours
165
*/
166
function minutes_to_hours($minutes)
167
{
168
        return ($minutes / 3600);
169
}
170
171
/**
172
* Return the group_id for a given group name
173
*/
174
function get_group_id($group_name)
175
{
176
        global $db, $group_mapping;
177
178
        if (empty($group_mapping))
179
        {
180
                $sql = 'SELECT group_name, group_id
181
                        FROM ' . GROUPS_TABLE;
182
                $result = $db->sql_query($sql);
183
184
                $group_mapping = array();
185
                while ($row = $db->sql_fetchrow($result))
186
                {
187
                        $group_mapping[strtoupper($row['group_name'])] = (int) $row['group_id'];
188
                }
189
                $db->sql_freeresult($result);
190
        }
191
192
        if (!sizeof($group_mapping))
193
        {
194
                add_default_groups();
195
                return get_group_id($group_name);
196
        }
197
198
        if (isset($group_mapping[strtoupper($group_name)]))
199
        {
200
                return $group_mapping[strtoupper($group_name)];
201
        }
202
203
        return $group_mapping['REGISTERED'];
204
}
205
206
/**
207
* Generate the email hash stored in the users table
208
*
209
* Note: Deprecated, calls should directly go to phpbb_email_hash()
210
*/
211
function gen_email_hash($email)
212
{
213
        return phpbb_email_hash($email);
214
}
215
216
/**
217
* Convert a boolean into the appropriate phpBB constant indicating whether the topic is locked
218
*/
219
function is_topic_locked($bool)
220
{
221
        return (!empty($bool)) ? ITEM_LOCKED : ITEM_UNLOCKED;
222
}
223
224
/**
225
* Generate a bbcode_uid value
226
*/
227
function make_uid($timestamp)
228
{
229
        static $last_timestamp, $last_uid;
230
231
        if (empty($last_timestamp) || $timestamp != $last_timestamp)
232
        {
233
                $last_uid = substr(base_convert(unique_id(), 16, 36), 0, BBCODE_UID_LEN);
234
        }
235
        $last_timestamp = $timestamp;
236
        return $last_uid;
237
}
238
239
240
/**
241
* Validate a website address
242
*/
243
function validate_website($url)
244
{
245
        if ($url === 'http://')
246
        {
247
                return '';
248
        }
249
        else if (!preg_match('#^[a-z0-9]+://#i', $url) && strlen($url) > 0)
250
        {
251
                return 'http://' . $url;
252
        }
253
        return $url;
254
}
255
256
/**
257
* Convert nulls to zeros for fields which allowed a NULL value in the source but not the destination
258
*/
259
function null_to_zero($value)
260
{
261
        return ($value === NULL) ? 0 : $value;
262
}
263
264
/**
265
* Convert nulls to empty strings for fields which allowed a NULL value in the source but not the destination
266
*/
267
function null_to_str($value)
268
{
269
        return ($value === NULL) ? '' : $value;
270
}
271
272
// EXTENDED FUNCTIONS
273
274
/**
275
* Get old config value
276
*/
277
function get_config_value($config_name)
278
{
279
        static $convert_config;
280
281
        if (!isset($convert_config))
282
        {
283
                $convert_config = get_config();
284
        }
285
286
        if (!isset($convert_config[$config_name]))
287
        {
288
                return false;
289
        }
290
291
        return (empty($convert_config[$config_name])) ? '' : $convert_config[$config_name];
292
}
293
294
/**
295
* Convert an IP address from the hexadecimal notation to normal dotted-quad notation
296
*/
297
function decode_ip($int_ip)
298
{
299
        if (!$int_ip)
300
        {
301
                return $int_ip;
302
        }
303
304
        $hexipbang = explode('.', chunk_split($int_ip, 2, '.'));
305
306
        // Any mod changing the way ips are stored? Then we are not able to convert and enter the ip "as is" to not "destroy" anything...
307
        if (sizeof($hexipbang) < 4)
308
        {
309
                return $int_ip;
310
        }
311
312
        return hexdec($hexipbang[0]) . '.' . hexdec($hexipbang[1]) . '.' . hexdec($hexipbang[2]) . '.' . hexdec($hexipbang[3]);
313
}
314
315
/**
316
* Reverse the encoding of wild-carded bans
317
*/
318
function decode_ban_ip($int_ip)
319
{
320
        return str_replace('255', '*', decode_ip($int_ip));
321
}
322
323
/**
324
* Determine the MIME-type of a specified filename
325
* This does not actually inspect the file, but simply uses the file extension
326
*/
327
function mimetype($filename)
328
{
329
        if (!preg_match('/\.([a-z0-9]+)$/i', $filename, $m))
330
        {
331
                return 'application/octet-stream';
332
        }
333
334
        switch (strtolower($m[1]))
335
        {
336
                case 'zip':                return 'application/zip';
337
                case 'jpeg':        return 'image/jpeg';
338
                case 'jpg':                return 'image/jpeg';
339
                case 'jpe':                return 'image/jpeg';
340
                case 'png':                return 'image/png';
341
                case 'gif':                return 'image/gif';
342
                case 'htm':
343
                case 'html':        return 'text/html';
344
                case 'tif':                return 'image/tiff';
345
                case 'tiff':        return 'image/tiff';
346
                case 'ras':                return 'image/x-cmu-raster';
347
                case 'pnm':                return 'image/x-portable-anymap';
348
                case 'pbm':                return 'image/x-portable-bitmap';
349
                case 'pgm':                return 'image/x-portable-graymap';
350
                case 'ppm':                return 'image/x-portable-pixmap';
351
                case 'rgb':                return 'image/x-rgb';
352
                case 'xbm':                return 'image/x-xbitmap';
353
                case 'xpm':                return 'image/x-xpixmap';
354
                case 'xwd':                return 'image/x-xwindowdump';
355
                case 'z':                return 'application/x-compress';
356
                case 'gtar':        return 'application/x-gtar';
357
                case 'tgz':                return 'application/x-gtar';
358
                case 'gz':                return 'application/x-gzip';
359
                case 'tar':                return 'application/x-tar';
360
                case 'xls':                return 'application/excel';
361
                case 'pdf':                return 'application/pdf';
362
                case 'ppt':                return 'application/powerpoint';
363
                case 'rm':                return 'application/vnd.rn-realmedia';
364
                case 'wma':                return 'audio/x-ms-wma';
365
                case 'swf':                return 'application/x-shockwave-flash';
366
                case 'ief':                return 'image/ief';
367
                case 'doc':
368
                case 'dot':
369
                case 'wrd':                return 'application/msword';
370
                case 'ai':
371
                case 'eps':
372
                case 'ps':                return 'application/postscript';
373
                case 'asc':
374
                case 'txt':
375
                case 'c':
376
                case 'cc':
377
                case 'h':
378
                case 'hh':
379
                case 'cpp':
380
                case 'hpp':
381
                case 'php':
382
                case 'php3':        return 'text/plain';
383
                default:                 return 'application/octet-stream';
384
        }
385
}
386
387
/**
388
* Obtain the dimensions of all remotely hosted avatars
389
* This should only be called from execute_last
390
* There can be significant network overhead if there are a large number of remote avatars
391
* @todo Look at the option of allowing the user to decide whether this is called or to force the dimensions
392
*/
393
function remote_avatar_dims()
394
{
395
        global $db;
396
397
        $sql = 'SELECT user_id, user_avatar
398
                FROM ' . USERS_TABLE . '
399
                WHERE user_avatar_type = ' . AVATAR_REMOTE;
400
        $result = $db->sql_query($sql);
401
402
        $remote_avatars = array();
403
        while ($row = $db->sql_fetchrow($result))
404
        {
405
                $remote_avatars[(int) $row['user_id']] = $row['user_avatar'];
406
        }
407
        $db->sql_freeresult($result);
408
409
        foreach ($remote_avatars as $user_id => $avatar)
410
        {
411
                $width = (int) get_remote_avatar_dim($avatar, 0);
412
                $height = (int) get_remote_avatar_dim($avatar, 1);
413
414
                $sql = 'UPDATE ' . USERS_TABLE . '
415
                        SET user_avatar_width = ' . (int) $width . ', user_avatar_height = ' . (int) $height . '
416
                        WHERE user_id = ' . $user_id;
417
                $db->sql_query($sql);
418
        }
419
}
420
421
function import_avatar_gallery($gallery_name = '', $subdirs_as_galleries = false)
422
{
423
        global $config, $convert, $phpbb_root_path, $user;
424
425
        $relative_path = empty($convert->convertor['source_path_absolute']);
426
427
        // check for trailing slash
428
        if (rtrim($convert->convertor['avatar_gallery_path'], '/') === '')
429
        {
430
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GALLERY_PATH'], 'import_avatar_gallery()'), __LINE__, __FILE__);
431
        }
432
433
        $src_path = relative_base(path($convert->convertor['avatar_gallery_path'], $relative_path), $relative_path);
434
435
        if (is_dir($src_path))
436
        {
437
                // Do not die on failure... safe mode restrictions may be in effect.
438
                copy_dir($convert->convertor['avatar_gallery_path'], path($config['avatar_gallery_path']) . $gallery_name, !$subdirs_as_galleries, false, false, $relative_path);
439
440
                // only doing 1 level deep. (ibf 1.x)
441
                // notes: ibf has 2 tiers: directly in the avatar directory for base gallery (handled in the above statement), plus subdirs(handled below).
442
                // recursive subdirs ignored. -- i don't know if other forums support recursive galleries. if they do, this following code could be upgraded to be recursive.
443
                if ($subdirs_as_galleries)
444
                {
445
                        $dirlist = array();
446
                        if ($handle = @opendir($src_path))
447
                        {
448
                                while ($entry = readdir($handle))
449
                                {
450
                                        if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
451
                                        {
452
                                                continue;
453
                                        }
454
455
                                        if (is_dir($src_path . $entry))
456
                                        {
457
                                                $dirlist[] = $entry;
458
                                        }
459
                                }
460
                                closedir($handle);
461
                        }
462
                        else if ($dir = @dir($src_path))
463
                        {
464
                                while ($entry = $dir->read())
465
                                {
466
                                        if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
467
                                        {
468
                                                continue;
469
                                        }
470
471
                                        if (is_dir($src_path . $entry))
472
                                        {
473
                                                $dirlist[] = $entry;
474
                                        }
475
                                }
476
                                $dir->close();
477
                        }
478
479
                        for ($i = 0; $i < sizeof($dirlist); ++$i)
480
                        {
481
                                $dir = $dirlist[$i];
482
483
                                // Do not die on failure... safe mode restrictions may be in effect.
484
                                copy_dir(path($convert->convertor['avatar_gallery_path'], $relative_path) . $dir, path($config['avatar_gallery_path']) . $dir, true, false, false, $relative_path);
485
                        }
486
                }
487
        }
488
}
489
490
function import_attachment_files($category_name = '')
491
{
492
        global $config, $convert, $phpbb_root_path, $db, $user;
493
494
        $sql = 'SELECT config_value AS upload_path
495
                FROM ' . CONFIG_TABLE . "
496
                WHERE config_name = 'upload_path'";
497
        $result = $db->sql_query($sql);
498
        $config['upload_path'] = $db->sql_fetchfield('upload_path');
499
        $db->sql_freeresult($result);
500
501
        $relative_path = empty($convert->convertor['source_path_absolute']);
502
503
        if (empty($convert->convertor['upload_path']))
504
        {
505
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_UPLOAD_DIR'], 'import_attachment_files()'), __LINE__, __FILE__);
506
        }
507
508
        if (is_dir(relative_base(path($convert->convertor['upload_path'], $relative_path), $relative_path)))
509
        {
510
                copy_dir($convert->convertor['upload_path'], path($config['upload_path']) . $category_name, true, false, true, $relative_path);
511
        }
512
}
513
514
function attachment_forum_perms($forum_id)
515
{
516
        if (!is_array($forum_id))
517
        {
518
                $forum_id = array($forum_id);
519
        }
520
521
        return serialize($forum_id);
522
}
523
524
// base64todec function
525
// -> from php manual?
526
function base64_unpack($string)
527
{
528
        $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-';
529
        $base = strlen($chars);
530
531
        $length = strlen($string);
532
        $number = 0;
533
534
        for ($i = 1; $i <= $length; $i++)
535
        {
536
                $pos = $length - $i;
537
                $operand = strpos($chars, substr($string, $pos, 1));
538
                $exponent = pow($base, $i-1);
539
                $dec_value = $operand * $exponent;
540
                $number += $dec_value;
541
        }
542
543
        return $number;
544
}
545
546
function _import_check($config_var, $source, $use_target)
547
{
548
        global $convert, $config;
549
550
        $result = array(
551
                'orig_source'        => $source,
552
                'copied'                => false,
553
                'relative_path'        => (empty($convert->convertor['source_path_absolute'])) ? true : false,
554
        );
555
556
        // copy file will prepend $phpBB_root_path
557
        $target = $config[$config_var] . '/' . utf8_basename(($use_target === false) ? $source : $use_target);
558
559
        if (!empty($convert->convertor[$config_var]) && strpos($source, $convert->convertor[$config_var]) !== 0)
560
        {
561
                $source = $convert->convertor[$config_var] . $source;
562
        }
563
564
        $result['source'] = $source;
565
566
        if (file_exists(relative_base($source, $result['relative_path'], __LINE__, __FILE__)))
567
        {
568
                $result['copied'] = copy_file($source, $target, false, false, $result['relative_path']);
569
        }
570
571
        if ($result['copied'])
572
        {
573
                $result['target'] = utf8_basename($target);
574
        }
575
        else
576
        {
577
                $result['target'] = ($use_target !== false) ? $result['orig_source'] : utf8_basename($target);
578
        }
579
580
        return $result;
581
}
582
583
function import_attachment($source, $use_target = false)
584
{
585
        if (empty($source))
586
        {
587
                return '';
588
        }
589
590
        global $convert, $phpbb_root_path, $config, $user;
591
592
        // check for trailing slash
593
        if (rtrim($convert->convertor['upload_path'], '/') === '')
594
        {
595
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_UPLOAD_DIR'], 'import_attachment()'), __LINE__, __FILE__);
596
        }
597
598
        $result = _import_check('upload_path', $source, $use_target);
599
600
        if ($result['copied'])
601
        {
602
                // Thumbnails?
603
                if (is_array($convert->convertor['thumbnails']))
604
                {
605
                        $thumb_dir = $convert->convertor['thumbnails'][0];
606
                        $thumb_prefix = $convert->convertor['thumbnails'][1];
607
                        $thumb_source = $thumb_dir . $thumb_prefix . utf8_basename($result['source']);
608
609
                        if (strpos($thumb_source, $convert->convertor['upload_path']) !== 0)
610
                        {
611
                                $thumb_source = $convert->convertor['upload_path'] . $thumb_source;
612
                        }
613
                        $thumb_target = $config['upload_path'] . '/thumb_' . $result['target'];
614
615
                        if (file_exists(relative_base($thumb_source, $result['relative_path'], __LINE__, __FILE__)))
616
                        {
617
                                copy_file($thumb_source, $thumb_target, false, false, $result['relative_path']);
618
                        }
619
                }
620
        }
621
622
        return $result['target'];
623
}
624
625
function import_rank($source, $use_target = false)
626
{
627
        if (empty($source))
628
        {
629
                return '';
630
        }
631
632
        global $convert, $phpbb_root_path, $config, $user;
633
634
        if (!isset($convert->convertor['ranks_path']))
635
        {
636
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_RANKS_PATH'], 'import_rank()'), __LINE__, __FILE__);
637
        }
638
639
        $result = _import_check('ranks_path', $source, $use_target);
640
        return $result['target'];
641
}
642
643
function import_smiley($source, $use_target = false)
644
{
645
        if (empty($source))
646
        {
647
                return '';
648
        }
649
650
        global $convert, $phpbb_root_path, $config, $user;
651
652
        // check for trailing slash
653
        if (rtrim($convert->convertor['smilies_path'], '/') === '')
654
        {
655
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_SMILIES_PATH'], 'import_smiley()'), __LINE__, __FILE__);
656
        }
657
658
        $result = _import_check('smilies_path', $source, $use_target);
659
        return $result['target'];
660
}
661
662
/*
663
*/
664
function import_avatar($source, $use_target = false, $user_id = false)
665
{
666
        if (empty($source) || preg_match('#^https?:#i', $source) || preg_match('#blank\.(gif|png)$#i', $source))
667
        {
668
                return;
669
        }
670
671
        global $convert, $phpbb_root_path, $config, $user;
672
673
        // check for trailing slash
674
        if (rtrim($convert->convertor['avatar_path'], '/') === '')
675
        {
676
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_AVATAR_PATH'], 'import_avatar()'), __LINE__, __FILE__);
677
        }
678
679
        if ($use_target === false && $user_id !== false)
680
        {
681
                $use_target = $config['avatar_salt'] . '_' . $user_id . '.' . substr(strrchr($source, '.'), 1);
682
        }
683
684
        $result = _import_check('avatar_path', $source, $use_target);
685
686
        return ((!empty($user_id)) ? $user_id : $use_target) . '.' . substr(strrchr($source, '.'), 1);
687
}
688
689
/**
690
* @todo all image dimension functions below (there are a *lot*) should get revisited and converted to one or two functions (no more needed, really).
691
*/
692
693
/**
694
* Calculate the size of the specified image
695
* Called from the following functions for calculating the size of specific image types
696
*/
697
function get_image_dim($source)
698
{
699
        if (empty($source))
700
        {
701
                return array(0, 0);
702
        }
703
704
        global $convert;
705
706
        $relative_path = empty($convert->convertor['source_path_absolute']);
707
708
        if (file_exists(relative_base($source, $relative_path)))
709
        {
710
                $image = relative_base($source, $relative_path);
711
                return @getimagesize($image);
712
        }
713
714
        return false;
715
}
716
717
/**
718
* Obtain the width of the specified smilie
719
*/
720
function get_smiley_width($src)
721
{
722
        return get_smiley_dim($src, 0);
723
}
724
725
/**
726
* Obtain the height of the specified smilie
727
*/
728
function get_smiley_height($src)
729
{
730
        return get_smiley_dim($src, 1);
731
}
732
733
/**
734
* Obtain the size of the specified smilie (using the cache if possible) and cache the value
735
*/
736
function get_smiley_dim($source, $axis)
737
{
738
        if (empty($source))
739
        {
740
                return 15;
741
        }
742
743
        static $smiley_cache = array();
744
745
        if (isset($smiley_cache[$source]))
746
        {
747
                return $smiley_cache[$source][$axis];
748
        }
749
750
        global $convert, $phpbb_root_path, $config, $user;
751
752
        $orig_source = $source;
753
754
        if (!isset($convert->convertor['smilies_path']))
755
        {
756
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_SMILIES_PATH'], 'get_smiley_dim()'), __LINE__, __FILE__);
757
        }
758
759
        if (!empty($convert->convertor['smilies_path']) && strpos($source, $convert->convertor['smilies_path']) !== 0)
760
        {
761
                $source = $convert->convertor['smilies_path'] . $source;
762
        }
763
764
        $smiley_cache[$orig_source] = get_image_dim($source);
765
766
        if (empty($smiley_cache[$orig_source]) || empty($smiley_cache[$orig_source][0]) || empty($smiley_cache[$orig_source][1]))
767
        {
768
                $smiley_cache[$orig_source] = array(15, 15);
769
                return 15;
770
        }
771
772
        return $smiley_cache[$orig_source][$axis];
773
}
774
775
/**
776
* Obtain the width of the specified avatar
777
*/
778
function get_avatar_width($src, $func = false, $arg1 = false, $arg2 = false)
779
{
780
        return get_avatar_dim($src, 0, $func, $arg1, $arg2);
781
}
782
783
/**
784
* Obtain the height of the specified avatar
785
*/
786
function get_avatar_height($src, $func = false, $arg1 = false, $arg2 = false)
787
{
788
        return get_avatar_dim($src, 1, $func, $arg1, $arg2);
789
}
790
791
/**
792
*/
793
function get_avatar_dim($src, $axis, $func = false, $arg1 = false, $arg2 = false)
794
{
795
        $avatar_type = AVATAR_UPLOAD;
796
797
        if ($func)
798
        {
799
                if ($arg1 || $arg2)
800
                {
801
                        $ary = array($arg1);
802
803
                        if ($arg2)
804
                        {
805
                                $ary[] = $arg2;
806
                        }
807
808
                        $avatar_type = call_user_func_array($func, $ary);
809
                }
810
                else
811
                {
812
                        $avatar_type = call_user_func($func);
813
                }
814
        }
815
816
        switch ($avatar_type)
817
        {
818
                case AVATAR_UPLOAD:
819
                        return get_upload_avatar_dim($src, $axis);
820
                break;
821
822
                case AVATAR_GALLERY:
823
                        return get_gallery_avatar_dim($src, $axis);
824
                break;
825
826
                case AVATAR_REMOTE:
827
                         // see notes on this functions usage and (hopefully) model $func to avoid this accordingly
828
                        return get_remote_avatar_dim($src, $axis);
829
                break;
830
831
                default:
832
                        $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
833
                        $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
834
835
                        return $axis ? $default_y : $default_x;
836
                break;
837
        }
838
}
839
840
/**
841
* Obtain the size of the specified uploaded avatar (using the cache if possible) and cache the value
842
*/
843
function get_upload_avatar_dim($source, $axis)
844
{
845
        static $cachedims = false;
846
        static $cachekey = false;
847
848
        if (empty($source))
849
        {
850
                return 0;
851
        }
852
853
        if ($cachekey == $source)
854
        {
855
                return $cachedims[$axis];
856
        }
857
858
        $orig_source = $source;
859
860
        if (substr($source, 0, 7) == 'upload:')
861
        {
862
                $source = substr($source, 7);
863
        }
864
865
        global $convert, $phpbb_root_path, $config, $user;
866
867
        if (!isset($convert->convertor['avatar_path']))
868
        {
869
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_AVATAR_PATH'], 'get_upload_avatar_dim()'), __LINE__, __FILE__);
870
        }
871
872
        if (!empty($convert->convertor['avatar_path']) && strpos($source, $convert->convertor['avatar_path']) !== 0)
873
        {
874
                $source = path($convert->convertor['avatar_path'], empty($convert->convertor['source_path_absolute'])) . $source;
875
        }
876
877
        $cachedims = get_image_dim($source);
878
879
        if (empty($cachedims) || empty($cachedims[0]) || empty($cachedims[1]))
880
        {
881
                $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
882
                $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
883
884
                $cachedims = array($default_x, $default_y);
885
        }
886
887
        return $cachedims[$axis];
888
}
889
890
/**
891
* Obtain the size of the specified gallery avatar (using the cache if possible) and cache the value
892
*/
893
function get_gallery_avatar_dim($source, $axis)
894
{
895
        if (empty($source))
896
        {
897
                return 0;
898
        }
899
900
        static $avatar_cache = array();
901
902
        if (isset($avatar_cache[$source]))
903
        {
904
                return $avatar_cache[$source][$axis];
905
        }
906
907
        global $convert, $phpbb_root_path, $config, $user;
908
909
        $orig_source = $source;
910
911
        if (!isset($convert->convertor['avatar_gallery_path']))
912
        {
913
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GALLERY_PATH'], 'get_gallery_avatar_dim()'), __LINE__, __FILE__);
914
        }
915
916
        if (!empty($convert->convertor['avatar_gallery_path']) && strpos($source, $convert->convertor['avatar_gallery_path']) !== 0)
917
        {
918
                $source = path($convert->convertor['avatar_gallery_path'], empty($convert->convertor['source_path_absolute'])) . $source;
919
        }
920
921
        $avatar_cache[$orig_source] = get_image_dim($source);
922
923
        if (empty($avatar_cache[$orig_source]) || empty($avatar_cache[$orig_source][0]) || empty($avatar_cache[$orig_source][1]))
924
        {
925
                $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
926
                $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
927
928
                $avatar_cache[$orig_source] = array($default_x, $default_y);
929
        }
930
931
        return $avatar_cache[$orig_source][$axis];
932
}
933
934
/**
935
* Obtain the size of the specified remote avatar (using the cache if possible) and cache the value
936
* Whilst it's unlikely that remote avatars will be duplicated, it is possible so caching seems the best option
937
* This should only be called from a post processing step due to the possibility of network timeouts
938
*/
939
function get_remote_avatar_dim($src, $axis)
940
{
941
        if (empty($src))
942
        {
943
                return 0;
944
        }
945
946
        static $remote_avatar_cache = array();
947
948
        // an ugly hack: we assume that the dimensions of each remote avatar are accessed exactly twice (x and y)
949
        if (isset($remote_avatar_cache[$src]))
950
        {
951
                $retval = $remote_avatar_cache[$src][$axis];
952
                unset($remote_avatar_cache);
953
                return $retval;
954
        }
955
956
        $url_info = @parse_url($src);
957
        if (empty($url_info['host']))
958
        {
959
                return 0;
960
        }
961
        $host = $url_info['host'];
962
        $port = (isset($url_info['port'])) ? $url_info['port'] : 0;
963
        $protocol = (isset($url_info['scheme'])) ? $url_info['scheme'] : 'http';
964
        if (empty($port))
965
        {
966
                switch(strtolower($protocol))
967
                {
968
                        case 'ftp':
969
                                $port = 21;
970
                                break;
971
972
                        case 'https':
973
                                $port = 443;
974
                                break;
975
976
                        default:
977
                                $port = 80;
978
                }
979
        }
980
981
        $timeout = @ini_get('default_socket_timeout');
982
        @ini_set('default_socket_timeout', 2);
983
984
        // We're just trying to reach the server to avoid timeouts
985
        $fp = @fsockopen($host, $port, $errno, $errstr, 1);
986
        if ($fp)
987
        {
988
                $remote_avatar_cache[$src] = @getimagesize($src);
989
                fclose($fp);
990
        }
991
992
        $default_x         = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
993
        $default_y         = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
994
        $default         = array($default_x, $default_y);
995
996
        if (empty($remote_avatar_cache[$src]) || empty($remote_avatar_cache[$src][0]) || empty($remote_avatar_cache[$src][1]))
997
        {
998
                $remote_avatar_cache[$src] = $default;
999
        }
1000
        else
1001
        {
1002
                // We trust gallery and uploaded avatars to conform to the size settings; we might have to adjust here
1003
                if ($remote_avatar_cache[$src][0] > $default_x || $remote_avatar_cache[$src][1] > $default_y)
1004
                {
1005
                        $bigger = ($remote_avatar_cache[$src][0] > $remote_avatar_cache[$src][1]) ? 0 : 1;
1006
                        $ratio = $default[$bigger] / $remote_avatar_cache[$src][$bigger];
1007
                        $remote_avatar_cache[$src][0] = (int)($remote_avatar_cache[$src][0] * $ratio);
1008
                        $remote_avatar_cache[$src][1] = (int)($remote_avatar_cache[$src][1] * $ratio);
1009
                }
1010
        }
1011
1012
        @ini_set('default_socket_timeout', $timeout);
1013
        return $remote_avatar_cache[$src][$axis];
1014
}
1015
1016
function set_user_options()
1017
{
1018
        global $convert_row;
1019
1020
        // Key need to be set in row, else default value is chosen
1021
        $keyoptions = array(
1022
                'viewimg'                => array('bit' => 0, 'default' => 1),
1023
                'viewflash'                => array('bit' => 1, 'default' => 1),
1024
                'viewsmilies'        => array('bit' => 2, 'default' => 1),
1025
                'viewsigs'                => array('bit' => 3, 'default' => 1),
1026
                'viewavatars'        => array('bit' => 4, 'default' => 1),
1027
                'viewcensors'        => array('bit' => 5, 'default' => 1),
1028
                'attachsig'                => array('bit' => 6, 'default' => 0),
1029
                'bbcode'                => array('bit' => 8, 'default' => 1),
1030
                'smilies'                => array('bit' => 9, 'default' => 1),
1031
                'popuppm'                => array('bit' => 10, 'default' => 0),
1032
                'sig_bbcode'        => array('bit' => 15, 'default' => 1),
1033
                'sig_smilies'        => array('bit' => 16, 'default' => 1),
1034
                'sig_links'                => array('bit' => 17, 'default' => 1),
1035
        );
1036
1037
        $option_field = 0;
1038
1039
        foreach ($keyoptions as $key => $key_ary)
1040
        {
1041
                $value = (isset($convert_row[$key])) ? (int) $convert_row[$key] : $key_ary['default'];
1042
1043
                if ($value && !($option_field & 1 << $key_ary['bit']))
1044
                {
1045
                        $option_field += 1 << $key_ary['bit'];
1046
                }
1047
        }
1048
1049
        return $option_field;
1050
}
1051
1052
/**
1053
* Index messages on the fly as we convert them
1054
* @todo naderman, can you check that this works with the new search plugins as it's use is currently disabled (and thus untested)
1055
function search_indexing($message = '')
1056
{
1057
        global $fulltext_search, $convert_row;
1058
1059
        if (!isset($convert_row['post_id']))
1060
        {
1061
                return;
1062
        }
1063
1064
        if (!$message)
1065
        {
1066
                if (!isset($convert_row['message']))
1067
                {
1068
                        return;
1069
                }
1070
1071
                $message = $convert_row['message'];
1072
        }
1073
1074
        $title = (isset($convert_row['title'])) ? $convert_row['title'] : '';
1075
1076
        $fulltext_search->index('post', $convert_row['post_id'], $message, $title, $convert_row['poster_id'], $convert_row['forum_id']);
1077
}
1078
*/
1079
1080
function make_unique_filename($filename)
1081
{
1082
        if (!strlen($filename))
1083
        {
1084
                $filename = md5(unique_id()) . '.dat';
1085
        }
1086
        else if ($filename[0] == '.')
1087
        {
1088
                $filename = md5(unique_id()) . $filename;
1089
        }
1090
        else if (preg_match('/\.([a-z]+)$/i', $filename, $m))
1091
        {
1092
                $filename = preg_replace('/\.([a-z]+)$/i', '_' . md5(unique_id()) . '.\1', $filename);
1093
        }
1094
        else
1095
        {
1096
                $filename .= '_' . md5(unique_id()) . '.dat';
1097
        }
1098
1099
        return $filename;
1100
}
1101
1102
function words_unique(&$words)
1103
{
1104
        reset($words);
1105
        $return_array = array();
1106
1107
        $word = current($words);
1108
        do
1109
        {
1110
                $return_array[$word] = $word;
1111
        }
1112
        while ($word = next($words));
1113
1114
        return $return_array;
1115
}
1116
1117
/**
1118
* Adds a user to the specified group and optionally makes them a group leader
1119
* This function does not create the group if it does not exist and so should only be called after the groups have been created
1120
*/
1121
function add_user_group($group_id, $user_id, $group_leader=false)
1122
{
1123
        global $convert, $phpbb_root_path, $config, $user, $db;
1124
1125
        $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1126
                'group_id'                => $group_id,
1127
                'user_id'                => $user_id,
1128
                'group_leader'        => ($group_leader) ? 1 : 0,
1129
                'user_pending'        => 0));
1130
        $db->sql_query($sql);
1131
}
1132
1133
// STANDALONE FUNCTIONS
1134
1135
/**
1136
* Add users to the pre-defined "special" groups
1137
*
1138
* @param string $group The name of the special group to add to
1139
* @param string $select_query An SQL query to retrieve the user(s) to add to the group
1140
*/
1141
function user_group_auth($group, $select_query, $use_src_db)
1142
{
1143
        global $convert, $phpbb_root_path, $config, $user, $db, $src_db, $same_db;
1144
1145
        if (!in_array($group, array('guests', 'registered', 'registered_coppa', 'global_moderators', 'administrators', 'bots')))
1146
        {
1147
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_WRONG_GROUP'], $group, 'user_group_auth()'), __LINE__, __FILE__, true);
1148
                return;
1149
        }
1150
1151
        $sql = 'SELECT group_id
1152
                FROM ' . GROUPS_TABLE . "
1153
                WHERE group_name = '" . $db->sql_escape(strtoupper($group)) . "'";
1154
        $result = $db->sql_query($sql);
1155
        $group_id = (int) $db->sql_fetchfield('group_id');
1156
        $db->sql_freeresult($result);
1157
1158
        if (!$group_id)
1159
        {
1160
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GROUP'], $group, 'user_group_auth()'), __LINE__, __FILE__, true);
1161
                return;
1162
        }
1163
1164
        if ($same_db || !$use_src_db)
1165
        {
1166
                $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' (user_id, group_id, user_pending)
1167
                        ' . str_replace('{' . strtoupper($group) . '}', $group_id . ', 0', $select_query);
1168
                $db->sql_query($sql);
1169
        }
1170
        else
1171
        {
1172
                $result = $src_db->sql_query(str_replace('{' . strtoupper($group) . '}', $group_id . ' ', $select_query));
1173
                while ($row = $src_db->sql_fetchrow($result))
1174
                {
1175
                        // this might become quite a lot of INSERTS unfortunately
1176
                        $sql = 'INSERT INTO ' . USER_GROUP_TABLE . " (user_id, group_id, user_pending)
1177
                                VALUES ({$row['user_id']}, $group_id, 0)";
1178
                        $db->sql_query($sql);
1179
                }
1180
                $src_db->sql_freeresult($result);
1181
        }
1182
}
1183
1184
/**
1185
* Retrieves configuration information from the source forum and caches it as an array
1186
* Both database and file driven configuration formats can be handled
1187
* (the type used is specified in $config_schema, see convert_phpbb20.php for more details)
1188
*/
1189
function get_config()
1190
{
1191
        static $convert_config;
1192
        global $user;
1193
1194
        if (isset($convert_config))
1195
        {
1196
                return $convert_config;
1197
        }
1198
1199
        global $src_db, $same_db, $phpbb_root_path, $config;
1200
        global $convert;
1201
1202
        if ($convert->config_schema['table_format'] != 'file')
1203
        {
1204
                if ($convert->mysql_convert && $same_db)
1205
                {
1206
                        $src_db->sql_query("SET NAMES 'binary'");
1207
                }
1208
1209
                $sql = 'SELECT * FROM ' . $convert->src_table_prefix . $convert->config_schema['table_name'];
1210
                $result = $src_db->sql_query($sql);
1211
                $row = $src_db->sql_fetchrow($result);
1212
1213
                if (!$row)
1214
                {
1215
                        $convert->p_master->error($user->lang['CONV_ERROR_GET_CONFIG'], __LINE__, __FILE__);
1216
                }
1217
        }
1218
1219
        if (is_array($convert->config_schema['table_format']))
1220
        {
1221
                $convert_config = array();
1222
                list($key, $val) = each($convert->config_schema['table_format']);
1223
1224
                do
1225
                {
1226
                        $convert_config[$row[$key]] = $row[$val];
1227
                }
1228
                while ($row = $src_db->sql_fetchrow($result));
1229
                $src_db->sql_freeresult($result);
1230
1231
                if ($convert->mysql_convert && $same_db)
1232
                {
1233
                        $src_db->sql_query("SET NAMES 'utf8'");
1234
                }
1235
        }
1236
        else if ($convert->config_schema['table_format'] == 'file')
1237
        {
1238
                $filename = $convert->options['forum_path'] . '/' . $convert->config_schema['filename'];
1239
                if (!file_exists($filename))
1240
                {
1241
                        $convert->p_master->error($user->lang['FILE_NOT_FOUND'] . ': ' . $filename, __LINE__, __FILE__);
1242
                }
1243
1244
                if (isset($convert->config_schema['array_name']))
1245
                {
1246
                        unset($convert->config_schema['array_name']);
1247
                }
1248
1249
                $convert_config = extract_variables_from_file($filename);
1250
                if (!empty($convert->config_schema['array_name']))
1251
                {
1252
                        $convert_config = $convert_config[$convert->config_schema['array_name']];
1253
                }
1254
        }
1255
        else
1256
        {
1257
                $convert_config = $row;
1258
                if ($convert->mysql_convert && $same_db)
1259
                {
1260
                        $src_db->sql_query("SET NAMES 'utf8'");
1261
                }
1262
        }
1263
1264
        if (!sizeof($convert_config))
1265
        {
1266
                $convert->p_master->error($user->lang['CONV_ERROR_CONFIG_EMPTY'], __LINE__, __FILE__);
1267
        }
1268
1269
        return $convert_config;
1270
}
1271
1272
/**
1273
* Transfers the relevant configuration information from the source forum
1274
* The mapping of fields is specified in $config_schema, see convert_phpbb20.php for more details
1275
*/
1276
function restore_config($schema)
1277
{
1278
        global $db, $config;
1279
1280
        $convert_config = get_config();
1281
1282
        foreach ($schema['settings'] as $config_name => $src)
1283
        {
1284
                if (preg_match('/(.*)\((.*)\)/', $src, $m))
1285
                {
1286
                        $var = (empty($m[2]) || empty($convert_config[$m[2]])) ? "''" : "'" . addslashes($convert_config[$m[2]]) . "'";
1287
                        $exec = '$config_value = ' . $m[1] . '(' . $var . ');';
1288
                        eval($exec);
1289
                }
1290
                else
1291
                {
1292
                        if ($schema['table_format'] != 'file' || empty($schema['array_name']))
1293
                        {
1294
                                $config_value = (isset($convert_config[$src])) ? $convert_config[$src] : '';
1295
                        }
1296
                        else if (!empty($schema['array_name']))
1297
                        {
1298
                                $src_ary = $schema['array_name'];
1299
                                $config_value = (isset($convert_config[$src_ary][$src])) ? $convert_config[$src_ary][$src] : '';
1300
                        }
1301
                   }
1302
1303
                if ($config_value !== '')
1304
                {
1305
                        // Most are...
1306
                        if (is_string($config_value))
1307
                        {
1308
                                $config_value = truncate_string(utf8_htmlspecialchars($config_value), 255, 255, false);
1309
                        }
1310
1311
                        set_config($config_name, $config_value);
1312
                }
1313
        }
1314
}
1315
1316
/**
1317
* Update the count of PM's in custom folders for all users
1318
*/
1319
function update_folder_pm_count()
1320
{
1321
        global $db, $convert, $user;
1322
1323
        $sql = 'SELECT user_id, folder_id, COUNT(msg_id) as num_messages
1324
                FROM ' . PRIVMSGS_TO_TABLE . '
1325
                WHERE folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ', ' . PRIVMSGS_INBOX . ', ' . PRIVMSGS_OUTBOX . ', ' . PRIVMSGS_SENTBOX . ')
1326
                GROUP BY folder_id, user_id';
1327
        $result = $db->sql_query($sql);
1328
1329
        while ($row = $db->sql_fetchrow($result))
1330
        {
1331
                $db->sql_query('UPDATE ' . PRIVMSGS_FOLDER_TABLE . ' SET pm_count = ' . $row['num_messages'] . '
1332
                        WHERE user_id = ' . $row['user_id'] . ' AND folder_id = ' . $row['folder_id']);
1333
        }
1334
        $db->sql_freeresult($result);
1335
}
1336
1337
// Functions mainly used by the main convertor script
1338
1339
function path($path, $path_relative = true)
1340
{
1341
        if ($path === false)
1342
        {
1343
                return '';
1344
        }
1345
1346
        if (substr($path, -1) != '/')
1347
        {
1348
                $path .= '/';
1349
        }
1350
1351
        if (!$path_relative)
1352
        {
1353
                return $path;
1354
        }
1355
1356
        if (substr($path, 0, 1) == '/')
1357
        {
1358
                $path = substr($path, 1);
1359
        }
1360
1361
        return $path;
1362
}
1363
1364
/**
1365
* Extract the variables defined in a configuration file
1366
* @todo As noted by Xore we need to look at this from a security perspective
1367
*/
1368
function extract_variables_from_file($_filename)
1369
{
1370
        include($_filename);
1371
1372
        $vars = get_defined_vars();
1373
        unset($vars['_filename']);
1374
1375
        return $vars;
1376
}
1377
1378
function get_path($src_path, $src_url, $test_file)
1379
{
1380
        global $config, $phpbb_root_path, $phpEx;
1381
1382
        $board_config = get_config();
1383
1384
        $test_file = preg_replace('/\.php$/i', ".$phpEx", $test_file);
1385
        $src_path = path($src_path);
1386
1387
        if (@file_exists($phpbb_root_path . $src_path . $test_file))
1388
        {
1389
                return $src_path;
1390
        }
1391
1392
        if (!empty($src_url) && !empty($board_config['server_name']))
1393
        {
1394
                if (!preg_match('#https?://([^/]+)(.*)#i', $src_url, $m))
1395
                {
1396
                        return false;
1397
                }
1398
1399
                if ($m[1] != $board_config['server_name'])
1400
                {
1401
                        return false;
1402
                }
1403
1404
                $url_parts = explode('/', $m[2]);
1405
                if (substr($src_url, -1) != '/')
1406
                {
1407
                        if (preg_match('/.*\.([a-z0-9]{3,4})$/i', $url_parts[sizeof($url_parts) - 1]))
1408
                        {
1409
                                $url_parts[sizeof($url_parts) - 1] = '';
1410
                        }
1411
                        else
1412
                        {
1413
                                $url_parts[] = '';
1414
                        }
1415
                }
1416
1417
                $script_path = $board_config['script_path'];
1418
                if (substr($script_path, -1) == '/')
1419
                {
1420
                        $script_path = substr($script_path, 0, -1);
1421
                }
1422
1423
                $path_array = array();
1424
1425
                $phpbb_parts = explode('/', $script_path);
1426
                for ($i = 0; $i < sizeof($url_parts); ++$i)
1427
                {
1428
                        if ($i < sizeof($phpbb_parts[$i]) && $url_parts[$i] == $phpbb_parts[$i])
1429
                        {
1430
                                $path_array[] = $url_parts[$i];
1431
                                unset($url_parts[$i]);
1432
                        }
1433
                        else
1434
                        {
1435
                                $path = '';
1436
                                for ($j = $i; $j < sizeof($phpbb_parts); ++$j)
1437
                                {
1438
                                        $path .= '../';
1439
                                }
1440
                                $path .= implode('/', $url_parts);
1441
                                break;
1442
                        }
1443
                }
1444
1445
                if (!empty($path))
1446
                {
1447
                        if (@file_exists($phpbb_root_path . $path . $test_file))
1448
                        {
1449
                                return $path;
1450
                        }
1451
                }
1452
        }
1453
1454
        return false;
1455
}
1456
1457
function compare_table($tables, $tablename, &$prefixes)
1458
{
1459
        for ($i = 0, $table_size = sizeof($tables); $i < $table_size; ++$i)
1460
        {
1461
                if (preg_match('/(.*)' . $tables[$i] . '$/', $tablename, $m))
1462
                {
1463
                        if (empty($m[1]))
1464
                        {
1465
                                $m[1] = '*';
1466
                        }
1467
1468
                        if (isset($prefixes[$m[1]]))
1469
                        {
1470
                                $prefixes[$m[1]]++;
1471
                        }
1472
                        else
1473
                        {
1474
                                $prefixes[$m[1]] = 1;
1475
                        }
1476
                }
1477
        }
1478
}
1479
1480
/**
1481
* Grant permissions to a specified user or group
1482
*
1483
* @param string $ug_type user|group|user_role|group_role
1484
* @param mixed $forum_id forum ids (array|int|0) -> 0 == all forums
1485
* @param mixed $ug_id [int] user_id|group_id : [string] usergroup name
1486
* @param mixed $acl_list [string] acl entry : [array] acl entries : [string] role entry
1487
* @param int $setting ACL_YES|ACL_NO|ACL_NEVER
1488
*/
1489
function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO)
1490
{
1491
        global $db, $convert, $user, $config;
1492
        static $acl_option_ids, $group_ids;
1493
1494
        if (($ug_type == 'group' || $ug_type == 'group_role') && is_string($ug_id))
1495
        {
1496
                if (!isset($group_ids[$ug_id]))
1497
                {
1498
                        $sql = 'SELECT group_id
1499
                                FROM ' . GROUPS_TABLE . "
1500
                                WHERE group_name = '" . $db->sql_escape(strtoupper($ug_id)) . "'";
1501
                        $result = $db->sql_query_limit($sql, 1);
1502
                        $id = (int) $db->sql_fetchfield('group_id');
1503
                        $db->sql_freeresult($result);
1504
1505
                        if (!$id)
1506
                        {
1507
                                return;
1508
                        }
1509
1510
                        $group_ids[$ug_id] = $id;
1511
                }
1512
1513
                $ug_id = (int) $group_ids[$ug_id];
1514
        }
1515
1516
        $table = ($ug_type == 'user' || $ug_type == 'user_role') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE;
1517
        $id_field = ($ug_type == 'user' || $ug_type == 'user_role') ? 'user_id' : 'group_id';
1518
1519
        // Role based permissions are the simplest to handle so check for them first
1520
        if ($ug_type == 'user_role' || $ug_type == 'group_role')
1521
        {
1522
                if (is_numeric($forum_id))
1523
                {
1524
                        $sql = 'SELECT role_id
1525
                                FROM ' . ACL_ROLES_TABLE . "
1526
                                WHERE role_name = 'ROLE_" . $db->sql_escape($acl_list) . "'";
1527
                        $result = $db->sql_query_limit($sql, 1);
1528
                        $row = $db->sql_fetchrow($result);
1529
                        $db->sql_freeresult($result);
1530
1531
                        // If we have no role id there is something wrong here
1532
                        if ($row)
1533
                        {
1534
                                $sql = "INSERT INTO $table ($id_field, forum_id, auth_role_id) VALUES ($ug_id, $forum_id, " . $row['role_id'] . ')';
1535
                                $db->sql_query($sql);
1536
                        }
1537
                }
1538
1539
                return;
1540
        }
1541
1542
        // Build correct parameters
1543
        $auth = array();
1544
1545
        if (!is_array($acl_list))
1546
        {
1547
                $auth = array($acl_list => $setting);
1548
        }
1549
        else
1550
        {
1551
                foreach ($acl_list as $auth_option)
1552
                {
1553
                        $auth[$auth_option] = $setting;
1554
                }
1555
        }
1556
        unset($acl_list);
1557
1558
        if (!is_array($forum_id))
1559
        {
1560
                $forum_id = array($forum_id);
1561
        }
1562
1563
        // Set any flags as required
1564
        foreach ($auth as $auth_option => $acl_setting)
1565
        {
1566
                $flag = substr($auth_option, 0, strpos($auth_option, '_') + 1);
1567
                if (empty($auth[$flag]))
1568
                {
1569
                        $auth[$flag] = $acl_setting;
1570
                }
1571
        }
1572
1573
        if (!is_array($acl_option_ids) || empty($acl_option_ids))
1574
        {
1575
                $sql = 'SELECT auth_option_id, auth_option
1576
                        FROM ' . ACL_OPTIONS_TABLE;
1577
                $result = $db->sql_query($sql);
1578
1579
                while ($row = $db->sql_fetchrow($result))
1580
                {
1581
                        $acl_option_ids[$row['auth_option']] = $row['auth_option_id'];
1582
                }
1583
                $db->sql_freeresult($result);
1584
        }
1585
1586
        $sql_forum = 'AND ' . $db->sql_in_set('a.forum_id', array_map('intval', $forum_id), false, true);
1587
1588
        $sql = ($ug_type == 'user') ? 'SELECT o.auth_option_id, o.auth_option, a.forum_id, a.auth_setting FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . " o WHERE a.auth_option_id = o.auth_option_id $sql_forum AND a.user_id = $ug_id" : 'SELECT o.auth_option_id, o.auth_option, a.forum_id, a.auth_setting FROM ' . ACL_GROUPS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . " o WHERE a.auth_option_id = o.auth_option_id $sql_forum AND a.group_id = $ug_id";
1589
        $result = $db->sql_query($sql);
1590
1591
        $cur_auth = array();
1592
        while ($row = $db->sql_fetchrow($result))
1593
        {
1594
                $cur_auth[$row['forum_id']][$row['auth_option_id']] = $row['auth_setting'];
1595
        }
1596
        $db->sql_freeresult($result);
1597
1598
        $sql_ary = array();
1599
        foreach ($forum_id as $forum)
1600
        {
1601
                foreach ($auth as $auth_option => $setting)
1602
                {
1603
                        $auth_option_id = $acl_option_ids[$auth_option];
1604
1605
                        if (!$auth_option_id)
1606
                        {
1607
                                continue;
1608
                        }
1609
1610
                        switch ($setting)
1611
                        {
1612
                                case ACL_NO:
1613
                                        if (isset($cur_auth[$forum][$auth_option_id]))
1614
                                        {
1615
                                                $sql_ary['delete'][] = "DELETE FROM $table
1616
                                                        WHERE forum_id = $forum
1617
                                                                AND auth_option_id = $auth_option_id
1618
                                                                AND $id_field = $ug_id";
1619
                                        }
1620
                                break;
1621
1622
                                default:
1623
                                        if (!isset($cur_auth[$forum][$auth_option_id]))
1624
                                        {
1625
                                                $sql_ary['insert'][] = "$ug_id, $forum, $auth_option_id, $setting";
1626
                                        }
1627
                                        else if ($cur_auth[$forum][$auth_option_id] != $setting)
1628
                                        {
1629
                                                $sql_ary['update'][] = "UPDATE " . $table . "
1630
                                                        SET auth_setting = $setting
1631
                                                        WHERE $id_field = $ug_id
1632
                                                                AND forum_id = $forum
1633
                                                                AND auth_option_id = $auth_option_id";
1634
                                        }
1635
                        }
1636
                }
1637
        }
1638
        unset($cur_auth);
1639
1640
        $sql = '';
1641
        foreach ($sql_ary as $sql_type => $sql_subary)
1642
        {
1643
                switch ($sql_type)
1644
                {
1645
                        case 'insert':
1646
                                switch ($db->sql_layer)
1647
                                {
1648
                                        case 'mysql':
1649
                                        case 'mysql4':
1650
                                                $sql = 'VALUES ' . implode(', ', preg_replace('#^(.*?)$#', '(\1)', $sql_subary));
1651
                                        break;
1652
1653
                                        case 'mssql':
1654
                                        case 'sqlite':
1655
                                        case 'mssqlnative':
1656
                                                $sql = implode(' UNION ALL ', preg_replace('#^(.*?)$#', 'SELECT \1', $sql_subary));
1657
                                        break;
1658
1659
                                        default:
1660
                                                foreach ($sql_subary as $sql)
1661
                                                {
1662
                                                        $sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) VALUES ($sql)";
1663
                                                        $db->sql_query($sql);
1664
                                                        $sql = '';
1665
                                                }
1666
                                }
1667
1668
                                if ($sql != '')
1669
                                {
1670
                                        $sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) $sql";
1671
                                        $db->sql_query($sql);
1672
                                }
1673
                        break;
1674
1675
                        case 'update':
1676
                        case 'delete':
1677
                                foreach ($sql_subary as $sql)
1678
                                {
1679
                                        $db->sql_query($sql);
1680
                                        $sql = '';
1681
                                }
1682
                        break;
1683
                }
1684
                unset($sql_ary[$sql_type]);
1685
        }
1686
        unset($sql_ary);
1687
1688
}
1689
1690
/**
1691
* Update the count of unread private messages for all users
1692
*/
1693
function update_unread_count()
1694
{
1695
        global $db;
1696
1697
        $sql = 'SELECT user_id, COUNT(msg_id) as num_messages
1698
                FROM ' . PRIVMSGS_TO_TABLE . '
1699
                WHERE pm_unread = 1
1700
                        AND folder_id <> ' . PRIVMSGS_OUTBOX . '
1701
                GROUP BY user_id';
1702
        $result = $db->sql_query($sql);
1703
1704
        while ($row = $db->sql_fetchrow($result))
1705
        {
1706
                $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_unread_privmsg = ' . $row['num_messages'] . '
1707
                        WHERE user_id = ' . $row['user_id']);
1708
        }
1709
        $db->sql_freeresult($result);
1710
}
1711
1712
/**
1713
* Add any of the pre-defined "special" groups which are missing from the database
1714
*/
1715
function add_default_groups()
1716
{
1717
        global $db;
1718
1719
        $default_groups = array(
1720
                'GUESTS'                        => array('', 0, 0),
1721
                'REGISTERED'                => array('', 0, 0),
1722
                'REGISTERED_COPPA'        => array('', 0, 0),
1723
                'GLOBAL_MODERATORS'        => array('00AA00', 1, 0),
1724
                'ADMINISTRATORS'        => array('AA0000', 1, 1),
1725
                'BOTS'                                => array('9E8DA7', 0, 0),
1726
                'NEWLY_REGISTERED'                => array('', 0, 0),
1727
        );
1728
1729
        $sql = 'SELECT *
1730
                FROM ' . GROUPS_TABLE . '
1731
                WHERE ' . $db->sql_in_set('group_name', array_keys($default_groups));
1732
        $result = $db->sql_query($sql);
1733
1734
        while ($row = $db->sql_fetchrow($result))
1735
        {
1736
                unset($default_groups[strtoupper($row['group_name'])]);
1737
        }
1738
        $db->sql_freeresult($result);
1739
1740
        $sql_ary = array();
1741
1742
        foreach ($default_groups as $name => $data)
1743
        {
1744
                $sql_ary[] = array(
1745
                        'group_name'                        => (string) $name,
1746
                        'group_desc'                        => '',
1747
                        'group_desc_uid'                => '',
1748
                        'group_desc_bitfield'        => '',
1749
                        'group_type'                        => GROUP_SPECIAL,
1750
                        'group_colour'                        => (string) $data[0],
1751
                        'group_legend'                        => (int) $data[1],
1752
                        'group_founder_manage'        => (int) $data[2]
1753
                );
1754
        }
1755
1756
        if (sizeof($sql_ary))
1757
        {
1758
                $db->sql_multi_insert(GROUPS_TABLE, $sql_ary);
1759
        }
1760
}
1761
1762
1763
/**
1764
* Sync post count. We might need to do this in batches.
1765
*/
1766
function sync_post_count($offset, $limit)
1767
{
1768
        global $db;
1769
        $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id
1770
                        FROM ' . POSTS_TABLE . '
1771
                        WHERE post_postcount = 1
1772
                                AND post_approved = 1
1773
                        GROUP BY poster_id
1774
                        ORDER BY poster_id';
1775
        $result = $db->sql_query_limit($sql, $limit, $offset);
1776
1777
        while ($row = $db->sql_fetchrow($result))
1778
        {
1779
                $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['poster_id']}");
1780
        }
1781
        $db->sql_freeresult($result);
1782
}
1783
1784
/**
1785
* Add the search bots into the database
1786
* This code should be used in execute_last if the source database did not have bots
1787
* If you are converting bots this function should not be called
1788
* @todo We might want to look at sharing the bot list between the install code and this code for consistancy
1789
*/
1790
function add_bots()
1791
{
1792
        global $db, $convert, $user, $config, $phpbb_root_path, $phpEx;
1793
1794
        $db->sql_query($convert->truncate_statement . BOTS_TABLE);
1795
1796
        $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name = 'BOTS'";
1797
        $result = $db->sql_query($sql);
1798
        $group_id = (int) $db->sql_fetchfield('group_id', false, $result);
1799
        $db->sql_freeresult($result);
1800
1801
        if (!$group_id)
1802
        {
1803
                add_default_groups();
1804
1805
                $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name = 'BOTS'";
1806
                $result = $db->sql_query($sql);
1807
                $group_id = (int) $db->sql_fetchfield('group_id', false, $result);
1808
                $db->sql_freeresult($result);
1809
1810
                if (!$group_id)
1811
                {
1812
                        global $install;
1813
                        $install->error($user->lang['CONV_ERROR_INCONSISTENT_GROUPS'], __LINE__, __FILE__);
1814
                }
1815
        }
1816
1817
        $bots = array(
1818
                'AdsBot [Google]'                        => array('AdsBot-Google', ''),
1819
                'Alexa [Bot]'                                => array('ia_archiver', ''),
1820
                'Alta Vista [Bot]'                        => array('Scooter/', ''),
1821
                'Ask Jeeves [Bot]'                        => array('Ask Jeeves', ''),
1822
                'Baidu [Spider]'                        => array('Baiduspider+(', ''),
1823
                'Bing [Bot]'                                => array('bingbot/', ''),
1824
                'Exabot [Bot]'                                => array('Exabot/', ''),
1825
                'FAST Enterprise [Crawler]'        => array('FAST Enterprise Crawler', ''),
1826
                'FAST WebCrawler [Crawler]'        => array('FAST-WebCrawler/', ''),
1827
                'Francis [Bot]'                                => array('http://www.neomo.de/', ''),
1828
                'Gigabot [Bot]'                                => array('Gigabot/', ''),
1829
                'Google Adsense [Bot]'                => array('Mediapartners-Google', ''),
1830
                'Google Desktop'                        => array('Google Desktop', ''),
1831
                'Google Feedfetcher'                => array('Feedfetcher-Google', ''),
1832
                'Google [Bot]'                                => array('Googlebot', ''),
1833
                'Heise IT-Markt [Crawler]'        => array('heise-IT-Markt-Crawler', ''),
1834
                'Heritrix [Crawler]'                => array('heritrix/1.', ''),
1835
                'IBM Research [Bot]'                => array('ibm.com/cs/crawler', ''),
1836
                'ICCrawler - ICjobs'                => array('ICCrawler - ICjobs', ''),
1837
                'ichiro [Crawler]'                        => array('ichiro/2', ''),
1838
                'Majestic-12 [Bot]'                        => array('MJ12bot/', ''),
1839
                'Metager [Bot]'                                => array('MetagerBot/', ''),
1840
                'MSN NewsBlogs'                                => array('msnbot-NewsBlogs/', ''),
1841
                'MSN [Bot]'                                        => array('msnbot/', ''),
1842
                'MSNbot Media'                                => array('msnbot-media/', ''),
1843
                'NG-Search [Bot]'                        => array('NG-Search/', ''),
1844
                'Nutch [Bot]'                                => array('http://lucene.apache.org/nutch/', ''),
1845
                'Nutch/CVS [Bot]'                        => array('NutchCVS/', ''),
1846
                'OmniExplorer [Bot]'                => array('OmniExplorer_Bot/', ''),
1847
                'Online link [Validator]'        => array('online link validator', ''),
1848
                'psbot [Picsearch]'                        => array('psbot/0', ''),
1849
                'Seekport [Bot]'                        => array('Seekbot/', ''),
1850
                'Sensis [Crawler]'                        => array('Sensis Web Crawler', ''),
1851
                'SEO Crawler'                                => array('SEO search Crawler/', ''),
1852
                'Seoma [Crawler]'                        => array('Seoma [SEO Crawler]', ''),
1853
                'SEOSearch [Crawler]'                => array('SEOsearch/', ''),
1854
                'Snappy [Bot]'                                => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''),
1855
                'Steeler [Crawler]'                        => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''),
1856
                'Synoo [Bot]'                                => array('SynooBot/', ''),
1857
                'Telekom [Bot]'                                => array('crawleradmin.t-info@telekom.de', ''),
1858
                'TurnitinBot [Bot]'                        => array('TurnitinBot/', ''),
1859
                'Voyager [Bot]'                                => array('voyager/1.0', ''),
1860
                'W3 [Sitesearch]'                        => array('W3 SiteSearch Crawler', ''),
1861
                'W3C [Linkcheck]'                        => array('W3C-checklink/', ''),
1862
                'W3C [Validator]'                        => array('W3C_*Validator', ''),
1863
                'WiseNut [Bot]'                                => array('http://www.WISEnutbot.com', ''),
1864
                'YaCy [Bot]'                                => array('yacybot', ''),
1865
                'Yahoo MMCrawler [Bot]'                => array('Yahoo-MMCrawler/', ''),
1866
                'Yahoo Slurp [Bot]'                        => array('Yahoo! DE Slurp', ''),
1867
                'Yahoo [Bot]'                                => array('Yahoo! Slurp', ''),
1868
                'YahooSeeker [Bot]'                        => array('YahooSeeker/', ''),
1869
        );
1870
1871
        if (!function_exists('user_add'))
1872
        {
1873
                include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
1874
        }
1875
1876
        foreach ($bots as $bot_name => $bot_ary)
1877
        {
1878
                $user_row = array(
1879
                        'user_type'                                => USER_IGNORE,
1880
                        'group_id'                                => $group_id,
1881
                        'username'                                => $bot_name,
1882
                        'user_regdate'                        => time(),
1883
                        'user_password'                        => '',
1884
                        'user_colour'                        => '9E8DA7',
1885
                        'user_email'                        => '',
1886
                        'user_lang'                                => $config['default_lang'],
1887
                        'user_style'                        => 1,
1888
                        'user_timezone'                        => 0,
1889
                        'user_allow_massemail'        => 0,
1890
                );
1891
1892
                $user_id = user_add($user_row);
1893
1894
                if ($user_id)
1895
                {
1896
                        $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1897
                                'bot_active'        => 1,
1898
                                'bot_name'                => $bot_name,
1899
                                'user_id'                => $user_id,
1900
                                'bot_agent'                => $bot_ary[0],
1901
                                'bot_ip'                => $bot_ary[1])
1902
                        );
1903
                        $db->sql_query($sql);
1904
                }
1905
        }
1906
}
1907
1908
/**
1909
* Update any dynamic configuration variables after the conversion is finished
1910
* @todo Confirm that this updates all relevant values since it has not necessarily been kept in sync with all changes
1911
*/
1912
function update_dynamic_config()
1913
{
1914
        global $db, $config;
1915
1916
        // Get latest username
1917
        $sql = 'SELECT user_id, username, user_colour
1918
                FROM ' . USERS_TABLE . '
1919
                WHERE user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
1920
1921
        if (!empty($config['increment_user_id']))
1922
        {
1923
                $sql .= ' AND user_id <> ' . $config['increment_user_id'];
1924
        }
1925
1926
        $sql .= ' ORDER BY user_id DESC';
1927
1928
        $result = $db->sql_query_limit($sql, 1);
1929
        $row = $db->sql_fetchrow($result);
1930
        $db->sql_freeresult($result);
1931
1932
        if ($row)
1933
        {
1934
                set_config('newest_user_id', $row['user_id'], true);
1935
                set_config('newest_username', $row['username'], true);
1936
                set_config('newest_user_colour', $row['user_colour'], true);
1937
        }
1938
1939
//        Also do not reset record online user/date. There will be old data or the fresh data from the schema.
1940
//        set_config('record_online_users', 1, true);
1941
//        set_config('record_online_date', time(), true);
1942
1943
        $sql = 'SELECT COUNT(post_id) AS stat
1944
                FROM ' . POSTS_TABLE . '
1945
                WHERE post_approved = 1';
1946
        $result = $db->sql_query($sql);
1947
        $row = $db->sql_fetchrow($result);
1948
        $db->sql_freeresult($result);
1949
1950
        set_config('num_posts', (int) $row['stat'], true);
1951
1952
        $sql = 'SELECT COUNT(topic_id) AS stat
1953
                FROM ' . TOPICS_TABLE . '
1954
                WHERE topic_approved = 1';
1955
        $result = $db->sql_query($sql);
1956
        $row = $db->sql_fetchrow($result);
1957
        $db->sql_freeresult($result);
1958
1959
        set_config('num_topics', (int) $row['stat'], true);
1960
1961
        $sql = 'SELECT COUNT(user_id) AS stat
1962
                FROM ' . USERS_TABLE . '
1963
                WHERE user_type IN (' . USER_NORMAL . ',' . USER_FOUNDER . ')';
1964
        $result = $db->sql_query($sql);
1965
        $row = $db->sql_fetchrow($result);
1966
        $db->sql_freeresult($result);
1967
1968
        set_config('num_users', (int) $row['stat'], true);
1969
1970
        $sql = 'SELECT COUNT(attach_id) as stat
1971
                FROM ' . ATTACHMENTS_TABLE . '
1972
                WHERE is_orphan = 0';
1973
        $result = $db->sql_query($sql);
1974
        set_config('num_files', (int) $db->sql_fetchfield('stat'), true);
1975
        $db->sql_freeresult($result);
1976
1977
        $sql = 'SELECT SUM(filesize) as stat
1978
                FROM ' . ATTACHMENTS_TABLE . '
1979
                WHERE is_orphan = 0';
1980
        $result = $db->sql_query($sql);
1981
        set_config('upload_dir_size', (float) $db->sql_fetchfield('stat'), true);
1982
        $db->sql_freeresult($result);
1983
1984
        /**
1985
        * We do not resync users post counts - this can be done by the admin after conversion if wanted.
1986
        $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id
1987
                FROM ' . POSTS_TABLE . '
1988
                WHERE post_postcount = 1
1989
                GROUP BY poster_id';
1990
        $result = $db->sql_query($sql);
1991
1992
        while ($row = $db->sql_fetchrow($result))
1993
        {
1994
                $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['poster_id']}");
1995
        }
1996
        $db->sql_freeresult($result);
1997
        */
1998
}
1999
2000
/**
2001
* Updates topics_posted entries
2002
*/
2003
function update_topics_posted()
2004
{
2005
        global $db, $config;
2006
2007
        switch ($db->sql_layer)
2008
        {
2009
                case 'sqlite':
2010
                case 'firebird':
2011
                        $db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE);
2012
                break;
2013
2014
                default:
2015
                        $db->sql_query('TRUNCATE TABLE ' . TOPICS_POSTED_TABLE);
2016
                break;
2017
        }
2018
2019
        // This can get really nasty... therefore we only do the last six months
2020
        $get_from_time = time() - (6 * 4 * 7 * 24 * 60 * 60);
2021
2022
        // Select forum ids, do not include categories
2023
        $sql = 'SELECT forum_id
2024
                FROM ' . FORUMS_TABLE . '
2025
                WHERE forum_type <> ' . FORUM_CAT;
2026
        $result = $db->sql_query($sql);
2027
2028
        $forum_ids = array();
2029
        while ($row = $db->sql_fetchrow($result))
2030
        {
2031
                $forum_ids[] = $row['forum_id'];
2032
        }
2033
        $db->sql_freeresult($result);
2034
2035
        // Any global announcements? ;)
2036
        $forum_ids[] = 0;
2037
2038
        // Now go through the forums and get us some topics...
2039
        foreach ($forum_ids as $forum_id)
2040
        {
2041
                $sql = 'SELECT p.poster_id, p.topic_id
2042
                        FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t
2043
                        WHERE t.forum_id = ' . $forum_id . '
2044
                                AND t.topic_moved_id = 0
2045
                                AND t.topic_last_post_time > ' . $get_from_time . '
2046
                                AND t.topic_id = p.topic_id
2047
                                AND p.poster_id <> ' . ANONYMOUS . '
2048
                        GROUP BY p.poster_id, p.topic_id';
2049
                $result = $db->sql_query($sql);
2050
2051
                $posted = array();
2052
                while ($row = $db->sql_fetchrow($result))
2053
                {
2054
                        $posted[$row['poster_id']][] = $row['topic_id'];
2055
                }
2056
                $db->sql_freeresult($result);
2057
2058
                $sql_ary = array();
2059
                foreach ($posted as $user_id => $topic_row)
2060
                {
2061
                        foreach ($topic_row as $topic_id)
2062
                        {
2063
                                $sql_ary[] = array(
2064
                                        'user_id'                => (int) $user_id,
2065
                                        'topic_id'                => (int) $topic_id,
2066
                                        'topic_posted'        => 1,
2067
                                );
2068
                        }
2069
                }
2070
                unset($posted);
2071
2072
                if (sizeof($sql_ary))
2073
                {
2074
                        $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary);
2075
                }
2076
        }
2077
}
2078
2079
/**
2080
* Ensure that all users have a default group specified and update related information such as their colour
2081
*/
2082
function fix_empty_primary_groups()
2083
{
2084
        global $db;
2085
2086
        // Set group ids for users not already having it
2087
        $sql = 'UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('registered') . '
2088
                WHERE group_id = 0 AND user_type = ' . USER_INACTIVE;
2089
        $db->sql_query($sql);
2090
2091
        $sql = 'UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('registered') . '
2092
                WHERE group_id = 0 AND user_type = ' . USER_NORMAL;
2093
        $db->sql_query($sql);
2094
2095
        $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('guests') . ' WHERE user_id = ' . ANONYMOUS);
2096
2097
        $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . ' WHERE group_id = ' . get_group_id('administrators');
2098
        $result = $db->sql_query($sql);
2099
2100
        $user_ids = array();
2101
        while ($row = $db->sql_fetchrow($result))
2102
        {
2103
                $user_ids[] = $row['user_id'];
2104
        }
2105
        $db->sql_freeresult($result);
2106
2107
        if (sizeof($user_ids))
2108
        {
2109
                $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('administrators') . '
2110
                        WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids));
2111
        }
2112
2113
        $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . ' WHERE group_id = ' . get_group_id('global_moderators');
2114
2115
        $user_ids = array();
2116
        while ($row = $db->sql_fetchrow($result))
2117
        {
2118
                $user_ids[] = $row['user_id'];
2119
        }
2120
        $db->sql_freeresult($result);
2121
2122
        if (sizeof($user_ids))
2123
        {
2124
                $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('global_moderators') . '
2125
                        WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids));
2126
        }
2127
2128
        // Set user colour
2129
        $sql = 'SELECT group_id, group_colour FROM ' . GROUPS_TABLE . "
2130
                WHERE group_colour <> ''";
2131
        $result = $db->sql_query($sql);
2132
2133
        while ($row = $db->sql_fetchrow($result))
2134
        {
2135
                $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_colour = '{$row['group_colour']}' WHERE group_id = {$row['group_id']}");
2136
        }
2137
        $db->sql_freeresult($result);
2138
}
2139
2140
/**
2141
* Cleanly remove invalid user entries after converting the users table...
2142
*/
2143
function remove_invalid_users()
2144
{
2145
        global $convert, $db, $phpEx, $phpbb_root_path;
2146
2147
        // username_clean is UNIQUE
2148
        $sql = 'SELECT user_id
2149
                FROM ' . USERS_TABLE . "
2150
                WHERE username_clean = ''";
2151
        $result = $db->sql_query($sql);
2152
        $row = $db->sql_fetchrow($result);
2153
        $db->sql_freeresult($result);
2154
2155
        if ($row)
2156
        {
2157
                if (!function_exists('user_delete'))
2158
                {
2159
                        include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
2160
                }
2161
2162
                user_delete('remove', $row['user_id']);
2163
        }
2164
}
2165
2166
function convert_bbcode($message, $convert_size = true, $extended_bbcodes = false)
2167
{
2168
        static $orig, $repl, $origx, $replx, $str_from, $str_to;
2169
2170
        if (empty($orig))
2171
        {
2172
                $orig = $repl = array();
2173
2174
                $orig[] = '#\[(php|sql)\](.*?)\[/(php|sql)\]#is';
2175
                $repl[] = '[code]\2[/code]';
2176
2177
                $orig[] = '#\[font=[^\]]+\](.*?)\[/font\]#is';
2178
                $repl[] = '\1';
2179
2180
                $orig[] = '#\[align=[a-z]+\](.*?)\[/align\]#is';
2181
                $repl[] = '\1';
2182
2183
                $orig[] = '#\[/list=.*?\]#is';
2184
                $repl[] = '[/list]';
2185
2186
                $origx = array(
2187
                        '#\[glow[^\]]+\](.*?)\[/glow\]#is',
2188
                        '#\[shadow[^\]]+\](.*?)\[/shadow\]#is',
2189
                        '#\[flash[^\]]+\](.*?)\[/flash\]#is'
2190
                );
2191
2192
                $replx = array(
2193
                        '\1',
2194
                        '\1',
2195
                        '[url=\1]Flash[/url]'
2196
                );
2197
2198
                $str_from = array(
2199
                        '[ftp]',        '[/ftp]',
2200
                        '[ftp=',        '[/ftp]',
2201
                        '[pre]',        '[/pre]',
2202
                        '[table]',        '[/table]',
2203
                        '[td]',                '[/td]',
2204
                        '[tr]',                '[/tr]',
2205
                        '[s]',                '[/s]',
2206
                        '[left]',        '[/left]',
2207
                        '[right]',        '[/right]',
2208
                        '[center]',        '[/center]',
2209
                        '[sub]',        '[/sub]',
2210
                        '[sup]',        '[/sup]',
2211
                        '[tt]',                '[/tt]',
2212
                        '[move]',        '[/move]',
2213
                        '[hr]'
2214
                );
2215
2216
                $str_to = array(
2217
                        '[url]',        '[/url]',
2218
                        '[url=',        '[/url]',
2219
                        '[code]',        '[/code]',
2220
                        "\n",                '',
2221
                        '',                        '',
2222
                        "\n",                '',
2223
                        '',                        '',
2224
                        '',                        '',
2225
                        '',                        '',
2226
                        '',                        '',
2227
                        '',                        '',
2228
                        '',                        '',
2229
                        '',                        '',
2230
                        '',                        '',
2231
                        "\n\n"
2232
                );
2233
2234
                for ($i = 0; $i < sizeof($str_from); ++$i)
2235
                {
2236
                        $origx[] = '#\\' . str_replace(']', '\\]', $str_from[$i]) . '#is';
2237
                        $replx[] = $str_to[$i];
2238
                }
2239
        }
2240
2241
        if (preg_match_all('#\[email=([^\]]+)\](.*?)\[/email\]#i', $message, $m))
2242
        {
2243
                for ($i = 0; $i < sizeof($m[1]); ++$i)
2244
                {
2245
                        if ($m[1][$i] == $m[2][$i])
2246
                        {
2247
                                $message = str_replace($m[0][$i], '[email]' . $m[1][$i] . '[/email]', $message);
2248
                        }
2249
                        else
2250
                        {
2251
                                $message = str_replace($m[0][$i], $m[2][$i] . ' ([email]' . $m[1][$i] . '[/email])', $message);
2252
                        }
2253
                }
2254
        }
2255
2256
        if ($convert_size && preg_match('#\[size=[0-9]+\].*?\[/size\]#i', $message))
2257
        {
2258
                $size = array(9, 9, 12, 15, 18, 24, 29, 29, 29, 29);
2259
                $message = preg_replace('#\[size=([0-9]+)\](.*?)\[/size\]#i', '[size=\1]\2[/size]', $message);
2260
                $message = preg_replace('#\[size=[0-9]{2,}\](.*?)\[/size\]#i', '[size=29]\1[/size]', $message);
2261
2262
                for ($i = sizeof($size); $i; )
2263
                {
2264
                        $i--;
2265
                        $message = str_replace('[size=' . $i . ']', '[size=' . $size[$i] . ']', $message);
2266
                }
2267
        }
2268
2269
        if ($extended_bbcodes)
2270
        {
2271
                $message = preg_replace($origx, $replx, $message);
2272
        }
2273
2274
        $message = preg_replace($orig, $repl, $message);
2275
        return $message;
2276
}
2277
2278
2279
function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $source_relative_path = true)
2280
{
2281
        global $convert, $phpbb_root_path, $config, $user, $db;
2282
2283
        if (substr($trg, -1) == '/')
2284
        {
2285
                $trg .= utf8_basename($src);
2286
        }
2287
        $src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__);
2288
        $trg_path = $trg;
2289
2290
        if (!$overwrite && @file_exists($trg_path))
2291
        {
2292
                return true;
2293
        }
2294
2295
        if (!@file_exists($src_path))
2296
        {
2297
                return;
2298
        }
2299
2300
        $path = $phpbb_root_path;
2301
        $parts = explode('/', $trg);
2302
        unset($parts[sizeof($parts) - 1]);
2303
2304
        for ($i = 0; $i < sizeof($parts); ++$i)
2305
        {
2306
                $path .= $parts[$i] . '/';
2307
2308
                if (!is_dir($path))
2309
                {
2310
                        @mkdir($path, 0777);
2311
                }
2312
        }
2313
2314
        if (!phpbb_is_writable($path))
2315
        {
2316
                @chmod($path, 0777);
2317
        }
2318
2319
        if (!@copy($src_path, $phpbb_root_path . $trg_path))
2320
        {
2321
                $convert->p_master->error(sprintf($user->lang['COULD_NOT_COPY'], $src_path, $phpbb_root_path . $trg_path), __LINE__, __FILE__, !$die_on_failure);
2322
                return;
2323
        }
2324
2325
        if ($perm = @fileperms($src_path))
2326
        {
2327
                @chmod($phpbb_root_path . $trg_path, $perm);
2328
        }
2329
2330
        return true;
2331
}
2332
2333
function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_failure = true, $source_relative_path = true)
2334
{
2335
        global $convert, $phpbb_root_path, $config, $user, $db;
2336
2337
        $dirlist = $filelist = $bad_dirs = array();
2338
        $src = path($src, $source_relative_path);
2339
        $trg = path($trg);
2340
        $src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__);
2341
        $trg_path = $phpbb_root_path . $trg;
2342
2343
        if (!is_dir($trg_path))
2344
        {
2345
                @mkdir($trg_path, 0777);
2346
                @chmod($trg_path, 0777);
2347
        }
2348
2349
        if (!phpbb_is_writable($trg_path))
2350
        {
2351
                $bad_dirs[] = path($config['script_path']) . $trg;
2352
        }
2353
2354
        if ($handle = @opendir($src_path))
2355
        {
2356
                while ($entry = readdir($handle))
2357
                {
2358
                        if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
2359
                        {
2360
                                continue;
2361
                        }
2362
2363
                        if (is_dir($src_path . $entry))
2364
                        {
2365
                                $dirlist[] = $entry;
2366
                        }
2367
                        else
2368
                        {
2369
                                $filelist[] = $entry;
2370
                        }
2371
                }
2372
                closedir($handle);
2373
        }
2374
        else if ($dir = @dir($src_path))
2375
        {
2376
                while ($entry = $dir->read())
2377
                {
2378
                        if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
2379
                        {
2380
                                continue;
2381
                        }
2382
2383
                        if (is_dir($src_path . $entry))
2384
                        {
2385
                                $dirlist[] = $entry;
2386
                        }
2387
                        else
2388
                        {
2389
                                $filelist[] = $entry;
2390
                        }
2391
                }
2392
                $dir->close();
2393
        }
2394
        else
2395
        {
2396
                $convert->p_master->error(sprintf($user->lang['CONV_ERROR_COULD_NOT_READ'], relative_base($src, $source_relative_path)), __LINE__, __FILE__);
2397
        }
2398
2399
        if ($copy_subdirs)
2400
        {
2401
                for ($i = 0; $i < sizeof($dirlist); ++$i)
2402
                {
2403
                        $dir = $dirlist[$i];
2404
2405
                        if ($dir == 'CVS')
2406
                        {
2407
                                continue;
2408
                        }
2409
2410
                        if (!is_dir($trg_path . $dir))
2411
                        {
2412
                                @mkdir($trg_path . $dir, 0777);
2413
                                @chmod($trg_path . $dir, 0777);
2414
                        }
2415
2416
                        if (!phpbb_is_writable($trg_path . $dir))
2417
                        {
2418
                                $bad_dirs[] = $trg . $dir;
2419
                                $bad_dirs[] = $trg_path . $dir;
2420
                        }
2421
2422
                        if (!sizeof($bad_dirs))
2423
                        {
2424
                                copy_dir($src . $dir, $trg . $dir, true, $overwrite, $die_on_failure, $source_relative_path);
2425
                        }
2426
                }
2427
        }
2428
2429
        if (sizeof($bad_dirs))
2430
        {
2431
                $str = (sizeof($bad_dirs) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE'];
2432
                sort($bad_dirs);
2433
                $convert->p_master->error(sprintf($str, implode('<br />', $bad_dirs)), __LINE__, __FILE__);
2434
        }
2435
2436
        for ($i = 0; $i < sizeof($filelist); ++$i)
2437
        {
2438
                copy_file($src . $filelist[$i], $trg . $filelist[$i], $overwrite, $die_on_failure, $source_relative_path);
2439
        }
2440
}
2441
2442
function relative_base($path, $is_relative = true, $line = false, $file = false)
2443
{
2444
        global $convert, $phpbb_root_path, $config, $user, $db;
2445
2446
        if (!$is_relative)
2447
        {
2448
                return $path;
2449
        }
2450
2451
        if (empty($convert->options['forum_path']) && $is_relative)
2452
        {
2453
                $line = $line ? $line : __LINE__;
2454
                $file = $file ? $file : __FILE__;
2455
2456
                $convert->p_master->error($user->lang['CONV_ERROR_NO_FORUM_PATH'], $line, $file);
2457
        }
2458
2459
        return $convert->options['forum_path'] . '/' . $path;
2460
}
2461
2462
function get_smiley_display()
2463
{
2464
        static $smiley_count = 0;
2465
        $smiley_count++;
2466
        return ($smiley_count < 50) ? 1 : 0;
2467
}
2468
2469
2470
function fill_dateformat($user_dateformat)
2471
{
2472
        global $config;
2473
2474
        return ((empty($user_dateformat)) ? $config['default_dateformat'] : $user_dateformat);
2475
}
2476
2477
2478
2479
?>