phpBB
Statistics
| Revision:

root / trunk / phpBB / includes / functions_convert.php

History | View | Annotate | Download (60.7 kB)

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