Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
functions_convert.php
0001 <?php
0002 /**
0003 *
0004 * This file is part of the phpBB Forum Software package.
0005 *
0006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
0007 * @license GNU General Public License, version 2 (GPL-2.0)
0008 *
0009 * For full copyright and license information, please see
0010 * the docs/CREDITS.txt file.
0011 *
0012 */
0013
0014 /**
0015 * @ignore
0016 */
0017 if (!defined('IN_PHPBB'))
0018 {
0019 exit;
0020 }
0021
0022 /**
0023 * Default avatar width/height
0024 * @ignore
0025 */
0026 define('DEFAULT_AVATAR_X', 80);
0027 define('DEFAULT_AVATAR_Y', 80);
0028
0029 // Global functions - all functions can be used by convertors
0030
0031 // SIMPLE FUNCTIONS
0032
0033 /**
0034 * Return the preceding value
0035 */
0036 function dec($var)
0037 {
0038 return --$var;
0039 }
0040
0041 /**
0042 * Return the next value
0043 */
0044 function inc($var)
0045 {
0046 return ++$var;
0047 }
0048
0049 /**
0050 * Return whether the value is positive
0051 */
0052 function is_positive($n)
0053 {
0054 return ($n > 0) ? 1 : 0;
0055 }
0056
0057 /**
0058 * Boolean inverse of the value
0059 */
0060 function not($var)
0061 {
0062 return ($var) ? 0 : 1;
0063 }
0064
0065 /**
0066 * Convert a textual value to it's equivalent boolean value
0067 *
0068 * @param string $str String to convert (converts yes, on, y, 1 and true to boolean true)
0069 * @return boolean The equivalent value
0070 */
0071 function str_to_bool($str)
0072 {
0073 $str = strtolower($str);
0074 return ($str == 'yes' || $str == 'on' || $str == 'y' || $str == 'true' || $str == '1') ? true : false;
0075 }
0076
0077 /**
0078 * Function to mimic php's empty() function (it is the same)
0079 */
0080 function is_empty($mixed)
0081 {
0082 return empty($mixed);
0083 }
0084
0085 /**
0086 * Convert the name of a user's primary group to the appropriate equivalent phpBB group id
0087 *
0088 * @param string $status The name of the group
0089 * @return int The group_id corresponding to the equivalent group
0090 */
0091 function str_to_primary_group($status)
0092 {
0093 switch (ucfirst(strtolower($status)))
0094 {
0095 case 'Administrator':
0096 return get_group_id('administrators');
0097 break;
0098
0099 case 'Super moderator':
0100 case 'Global moderator':
0101 case 'Moderator':
0102 return get_group_id('global_moderators');
0103 break;
0104
0105 case 'Guest':
0106 case 'Anonymous':
0107 return get_group_id('guests');
0108 break;
0109
0110 default:
0111 return get_group_id('registered');
0112 break;
0113 }
0114 }
0115
0116 /**
0117 * Convert a boolean into the appropriate phpBB constant indicating whether the item is locked
0118 */
0119 function is_item_locked($bool)
0120 {
0121 return ($bool) ? ITEM_LOCKED : ITEM_UNLOCKED;
0122 }
0123
0124 /**
0125 * Convert a value from days to seconds
0126 */
0127 function days_to_seconds($days)
0128 {
0129 return ($days * 86400);
0130 }
0131
0132 /**
0133 * Determine whether a user is anonymous and return the appropriate new user_id
0134 */
0135 function is_user_anonymous($user_id)
0136 {
0137 return ($user_id > ANONYMOUS) ? $user_id : ANONYMOUS;
0138 }
0139
0140 /**
0141 * Generate a key value based on existing values
0142 *
0143 * @param int $pad Amount to add to the maximum value
0144 * @return int Key value
0145 */
0146 function auto_id($pad = 0)
0147 {
0148 global $auto_id, $convert_row;
0149
0150 if (!empty($convert_row['max_id']))
0151 {
0152 return $convert_row['max_id'] + $pad;
0153 }
0154
0155 return $auto_id + $pad;
0156 }
0157
0158 /**
0159 * Convert a boolean into the appropriate phpBB constant indicating whether the user is active
0160 */
0161 function set_user_type($user_active)
0162 {
0163 return ($user_active) ? USER_NORMAL : USER_INACTIVE;
0164 }
0165
0166 /**
0167 * Convert a value from minutes to hours
0168 */
0169 function minutes_to_hours($minutes)
0170 {
0171 return ($minutes / 3600);
0172 }
0173
0174 /**
0175 * Return the group_id for a given group name
0176 */
0177 function get_group_id($group_name)
0178 {
0179 global $db, $group_mapping;
0180
0181 if (empty($group_mapping))
0182 {
0183 $sql = 'SELECT group_name, group_id
0184 FROM ' . GROUPS_TABLE;
0185 $result = $db->sql_query($sql);
0186
0187 $group_mapping = array();
0188 while ($row = $db->sql_fetchrow($result))
0189 {
0190 $group_mapping[strtoupper($row['group_name'])] = (int) $row['group_id'];
0191 }
0192 $db->sql_freeresult($result);
0193 }
0194
0195 if (!count($group_mapping))
0196 {
0197 add_default_groups();
0198 return get_group_id($group_name);
0199 }
0200
0201 if (isset($group_mapping[strtoupper($group_name)]))
0202 {
0203 return $group_mapping[strtoupper($group_name)];
0204 }
0205
0206 return $group_mapping['REGISTERED'];
0207 }
0208
0209 /**
0210 * Convert a boolean into the appropriate phpBB constant indicating whether the topic is locked
0211 */
0212 function is_topic_locked($bool)
0213 {
0214 return (!empty($bool)) ? ITEM_LOCKED : ITEM_UNLOCKED;
0215 }
0216
0217 /**
0218 * Generate a bbcode_uid value
0219 */
0220 function make_uid($timestamp)
0221 {
0222 static $last_timestamp, $last_uid;
0223
0224 if (empty($last_timestamp) || $timestamp != $last_timestamp)
0225 {
0226 $last_uid = substr(base_convert(unique_id(), 16, 36), 0, BBCODE_UID_LEN);
0227 }
0228 $last_timestamp = $timestamp;
0229 return $last_uid;
0230 }
0231
0232
0233 /**
0234 * Validate a website address
0235 */
0236 function validate_website($url)
0237 {
0238 if ($url === 'http://')
0239 {
0240 return '';
0241 }
0242 else if (!preg_match('#^http[s]?://#i', $url) && strlen($url) > 0)
0243 {
0244 return 'http://' . $url;
0245 }
0246 return $url;
0247 }
0248
0249 /**
0250 * Convert nulls to zeros for fields which allowed a NULL value in the source but not the destination
0251 */
0252 function null_to_zero($value)
0253 {
0254 return ($value === NULL) ? 0 : $value;
0255 }
0256
0257 /**
0258 * Convert nulls to empty strings for fields which allowed a NULL value in the source but not the destination
0259 */
0260 function null_to_str($value)
0261 {
0262 return ($value === NULL) ? '' : $value;
0263 }
0264
0265 // EXTENDED FUNCTIONS
0266
0267 /**
0268 * Get old config value
0269 */
0270 function get_config_value($config_name)
0271 {
0272 static $convert_config;
0273
0274 if (!isset($convert_config))
0275 {
0276 $convert_config = get_config();
0277 }
0278
0279 if (!isset($convert_config[$config_name]))
0280 {
0281 return false;
0282 }
0283
0284 return (empty($convert_config[$config_name])) ? '' : $convert_config[$config_name];
0285 }
0286
0287 /**
0288 * Convert an IP address from the hexadecimal notation to normal dotted-quad notation
0289 */
0290 function decode_ip($int_ip)
0291 {
0292 if (!$int_ip)
0293 {
0294 return $int_ip;
0295 }
0296
0297 $hexipbang = explode('.', chunk_split($int_ip, 2, '.'));
0298
0299 // 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...
0300 if (count($hexipbang) < 4)
0301 {
0302 return $int_ip;
0303 }
0304
0305 return hexdec($hexipbang[0]) . '.' . hexdec($hexipbang[1]) . '.' . hexdec($hexipbang[2]) . '.' . hexdec($hexipbang[3]);
0306 }
0307
0308 /**
0309 * Reverse the encoding of wild-carded bans
0310 */
0311 function decode_ban_ip($int_ip)
0312 {
0313 return str_replace('255', '*', decode_ip($int_ip));
0314 }
0315
0316 /**
0317 * Determine the MIME-type of a specified filename
0318 * This does not actually inspect the file, but simply uses the file extension
0319 */
0320 function mimetype($filename)
0321 {
0322 if (!preg_match('/\.([a-z0-9]+)$/i', $filename, $m))
0323 {
0324 return 'application/octet-stream';
0325 }
0326
0327 switch (strtolower($m[1]))
0328 {
0329 case 'zip': return 'application/zip';
0330 case 'jpeg': return 'image/jpeg';
0331 case 'jpg': return 'image/jpeg';
0332 case 'jpe': return 'image/jpeg';
0333 case 'png': return 'image/png';
0334 case 'gif': return 'image/gif';
0335 case 'htm':
0336 case 'html': return 'text/html';
0337 case 'tif': return 'image/tiff';
0338 case 'tiff': return 'image/tiff';
0339 case 'ras': return 'image/x-cmu-raster';
0340 case 'pnm': return 'image/x-portable-anymap';
0341 case 'pbm': return 'image/x-portable-bitmap';
0342 case 'pgm': return 'image/x-portable-graymap';
0343 case 'ppm': return 'image/x-portable-pixmap';
0344 case 'rgb': return 'image/x-rgb';
0345 case 'xbm': return 'image/x-xbitmap';
0346 case 'xpm': return 'image/x-xpixmap';
0347 case 'xwd': return 'image/x-xwindowdump';
0348 case 'z': return 'application/x-compress';
0349 case 'gtar': return 'application/x-gtar';
0350 case 'tgz': return 'application/x-gtar';
0351 case 'gz': return 'application/x-gzip';
0352 case 'tar': return 'application/x-tar';
0353 case 'xls': return 'application/excel';
0354 case 'pdf': return 'application/pdf';
0355 case 'ppt': return 'application/powerpoint';
0356 case 'rm': return 'application/vnd.rn-realmedia';
0357 case 'wma': return 'audio/x-ms-wma';
0358 case 'swf': return 'application/x-shockwave-flash';
0359 case 'ief': return 'image/ief';
0360 case 'doc':
0361 case 'dot':
0362 case 'wrd': return 'application/msword';
0363 case 'ai':
0364 case 'eps':
0365 case 'ps': return 'application/postscript';
0366 case 'asc':
0367 case 'txt':
0368 case 'c':
0369 case 'cc':
0370 case 'h':
0371 case 'hh':
0372 case 'cpp':
0373 case 'hpp':
0374 case 'php':
0375 case 'php3': return 'text/plain';
0376 default: return 'application/octet-stream';
0377 }
0378 }
0379
0380 /**
0381 * Obtain the dimensions of all remotely hosted avatars
0382 * This should only be called from execute_last
0383 * There can be significant network overhead if there are a large number of remote avatars
0384 * @todo Look at the option of allowing the user to decide whether this is called or to force the dimensions
0385 */
0386 function remote_avatar_dims()
0387 {
0388 global $db;
0389
0390 $sql = 'SELECT user_id, user_avatar
0391 FROM ' . USERS_TABLE . '
0392 WHERE user_avatar_type = ' . AVATAR_REMOTE;
0393 $result = $db->sql_query($sql);
0394
0395 $remote_avatars = array();
0396 while ($row = $db->sql_fetchrow($result))
0397 {
0398 $remote_avatars[(int) $row['user_id']] = $row['user_avatar'];
0399 }
0400 $db->sql_freeresult($result);
0401
0402 foreach ($remote_avatars as $user_id => $avatar)
0403 {
0404 $width = (int) get_remote_avatar_dim($avatar, 0);
0405 $height = (int) get_remote_avatar_dim($avatar, 1);
0406
0407 $sql = 'UPDATE ' . USERS_TABLE . '
0408 SET user_avatar_width = ' . (int) $width . ', user_avatar_height = ' . (int) $height . '
0409 WHERE user_id = ' . $user_id;
0410 $db->sql_query($sql);
0411 }
0412 }
0413
0414 function import_avatar_gallery($gallery_name = '', $subdirs_as_galleries = false)
0415 {
0416 global $config, $convert, $user;
0417
0418 $relative_path = empty($convert->convertor['source_path_absolute']);
0419
0420 // check for trailing slash
0421 if (rtrim($convert->convertor['avatar_gallery_path'], '/') === '')
0422 {
0423 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GALLERY_PATH'], 'import_avatar_gallery()'), __LINE__, __FILE__);
0424 }
0425
0426 $src_path = relative_base(path($convert->convertor['avatar_gallery_path'], $relative_path), $relative_path);
0427
0428 if (is_dir($src_path))
0429 {
0430 // Do not die on failure... safe mode restrictions may be in effect.
0431 copy_dir($convert->convertor['avatar_gallery_path'], path($config['avatar_gallery_path']) . $gallery_name, !$subdirs_as_galleries, false, false, $relative_path);
0432
0433 // only doing 1 level deep. (ibf 1.x)
0434 // notes: ibf has 2 tiers: directly in the avatar directory for base gallery (handled in the above statement), plus subdirs(handled below).
0435 // 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.
0436 if ($subdirs_as_galleries)
0437 {
0438 $dirlist = array();
0439 if ($handle = @opendir($src_path))
0440 {
0441 while ($entry = readdir($handle))
0442 {
0443 if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
0444 {
0445 continue;
0446 }
0447
0448 if (is_dir($src_path . $entry))
0449 {
0450 $dirlist[] = $entry;
0451 }
0452 }
0453 closedir($handle);
0454 }
0455 else if ($dir = @dir($src_path))
0456 {
0457 while ($entry = $dir->read())
0458 {
0459 if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
0460 {
0461 continue;
0462 }
0463
0464 if (is_dir($src_path . $entry))
0465 {
0466 $dirlist[] = $entry;
0467 }
0468 }
0469 $dir->close();
0470 }
0471
0472 for ($i = 0, $end = count($dirlist); $i < $end; ++$i)
0473 {
0474 $dir = $dirlist[$i];
0475
0476 // Do not die on failure... safe mode restrictions may be in effect.
0477 copy_dir(path($convert->convertor['avatar_gallery_path'], $relative_path) . $dir, path($config['avatar_gallery_path']) . $dir, true, false, false, $relative_path);
0478 }
0479 }
0480 }
0481 }
0482
0483 function import_attachment_files($category_name = '')
0484 {
0485 global $config, $convert, $db, $user;
0486
0487 $sql = 'SELECT config_value AS upload_path
0488 FROM ' . CONFIG_TABLE . "
0489 WHERE config_name = 'upload_path'";
0490 $result = $db->sql_query($sql);
0491 $config['upload_path'] = $db->sql_fetchfield('upload_path');
0492 $db->sql_freeresult($result);
0493
0494 $relative_path = empty($convert->convertor['source_path_absolute']);
0495
0496 if (empty($convert->convertor['upload_path']))
0497 {
0498 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_UPLOAD_DIR'], 'import_attachment_files()'), __LINE__, __FILE__);
0499 }
0500
0501 if (is_dir(relative_base(path($convert->convertor['upload_path'], $relative_path), $relative_path)))
0502 {
0503 copy_dir($convert->convertor['upload_path'], path($config['upload_path']) . $category_name, true, false, true, $relative_path);
0504 }
0505 }
0506
0507 function attachment_forum_perms($forum_id)
0508 {
0509 if (!is_array($forum_id))
0510 {
0511 $forum_id = array($forum_id);
0512 }
0513
0514 return serialize($forum_id);
0515 }
0516
0517 // base64todec function
0518 // -> from php manual?
0519 function base64_unpack($string)
0520 {
0521 $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-';
0522 $base = strlen($chars);
0523
0524 $length = strlen($string);
0525 $number = 0;
0526
0527 for ($i = 1; $i <= $length; $i++)
0528 {
0529 $pos = $length - $i;
0530 $operand = strpos($chars, substr($string, $pos, 1));
0531 $exponent = pow($base, $i-1);
0532 $dec_value = $operand * $exponent;
0533 $number += $dec_value;
0534 }
0535
0536 return $number;
0537 }
0538
0539 function _import_check($config_var, $source, $use_target)
0540 {
0541 global $convert, $config;
0542
0543 $result = array(
0544 'orig_source' => $source,
0545 'copied' => false,
0546 'relative_path' => (empty($convert->convertor['source_path_absolute'])) ? true : false,
0547 );
0548
0549 // copy file will prepend $phpBB_root_path
0550 $target = $config[$config_var] . '/' . utf8_basename(($use_target === false) ? $source : $use_target);
0551
0552 if (!empty($convert->convertor[$config_var]) && strpos($source, $convert->convertor[$config_var]) !== 0)
0553 {
0554 $source = $convert->convertor[$config_var] . $source;
0555 }
0556
0557 $result['source'] = $source;
0558
0559 if (file_exists(relative_base($source, $result['relative_path'], __LINE__, __FILE__)))
0560 {
0561 $result['copied'] = copy_file($source, $target, false, false, $result['relative_path']);
0562 }
0563
0564 if ($result['copied'])
0565 {
0566 $result['target'] = utf8_basename($target);
0567 }
0568 else
0569 {
0570 $result['target'] = ($use_target !== false) ? $result['orig_source'] : utf8_basename($target);
0571 }
0572
0573 return $result;
0574 }
0575
0576 function import_attachment($source, $use_target = false)
0577 {
0578 if (empty($source))
0579 {
0580 return '';
0581 }
0582
0583 global $convert, $config, $user;
0584
0585 // check for trailing slash
0586 if (rtrim($convert->convertor['upload_path'], '/') === '')
0587 {
0588 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_UPLOAD_DIR'], 'import_attachment()'), __LINE__, __FILE__);
0589 }
0590
0591 $result = _import_check('upload_path', $source, $use_target);
0592
0593 if ($result['copied'])
0594 {
0595 // Thumbnails?
0596 if (is_array($convert->convertor['thumbnails']))
0597 {
0598 $thumb_dir = $convert->convertor['thumbnails'][0];
0599 $thumb_prefix = $convert->convertor['thumbnails'][1];
0600 $thumb_source = $thumb_dir . $thumb_prefix . utf8_basename($result['source']);
0601
0602 if (strpos($thumb_source, $convert->convertor['upload_path']) !== 0)
0603 {
0604 $thumb_source = $convert->convertor['upload_path'] . $thumb_source;
0605 }
0606 $thumb_target = $config['upload_path'] . '/thumb_' . $result['target'];
0607
0608 if (file_exists(relative_base($thumb_source, $result['relative_path'], __LINE__, __FILE__)))
0609 {
0610 copy_file($thumb_source, $thumb_target, false, false, $result['relative_path']);
0611 }
0612 }
0613 }
0614
0615 return $result['target'];
0616 }
0617
0618 function import_rank($source, $use_target = false)
0619 {
0620 if (empty($source))
0621 {
0622 return '';
0623 }
0624
0625 global $convert, $user;
0626
0627 if (!isset($convert->convertor['ranks_path']))
0628 {
0629 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_RANKS_PATH'], 'import_rank()'), __LINE__, __FILE__);
0630 }
0631
0632 $result = _import_check('ranks_path', $source, $use_target);
0633 return $result['target'];
0634 }
0635
0636 function import_smiley($source, $use_target = false)
0637 {
0638 if (empty($source))
0639 {
0640 return '';
0641 }
0642
0643 global $convert, $user;
0644
0645 // check for trailing slash
0646 if (rtrim($convert->convertor['smilies_path'], '/') === '')
0647 {
0648 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_SMILIES_PATH'], 'import_smiley()'), __LINE__, __FILE__);
0649 }
0650
0651 $result = _import_check('smilies_path', $source, $use_target);
0652 return $result['target'];
0653 }
0654
0655 /*
0656 */
0657 function import_avatar($source, $use_target = false, $user_id = false)
0658 {
0659 if (empty($source) || preg_match('#^https?:#i', $source) || preg_match('#blank\.(gif|png)$#i', $source))
0660 {
0661 return;
0662 }
0663
0664 global $convert, $config, $user;
0665
0666 // check for trailing slash
0667 if (rtrim($convert->convertor['avatar_path'], '/') === '')
0668 {
0669 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_AVATAR_PATH'], 'import_avatar()'), __LINE__, __FILE__);
0670 }
0671
0672 if ($use_target === false && $user_id !== false)
0673 {
0674 $use_target = $config['avatar_salt'] . '_' . $user_id . '.' . substr(strrchr($source, '.'), 1);
0675 }
0676
0677 _import_check('avatar_path', $source, $use_target);
0678
0679 return ((!empty($user_id)) ? $user_id : $use_target) . '.' . substr(strrchr($source, '.'), 1);
0680 }
0681
0682 /**
0683 * @todo all image dimension functions below (there are a *lot*) should get revisited and converted to one or two functions (no more needed, really).
0684 */
0685
0686 /**
0687 * Calculate the size of the specified image
0688 * Called from the following functions for calculating the size of specific image types
0689 */
0690 function get_image_dim($source)
0691 {
0692 if (empty($source))
0693 {
0694 return array(0, 0);
0695 }
0696
0697 global $convert;
0698
0699 $relative_path = empty($convert->convertor['source_path_absolute']);
0700
0701 if (file_exists(relative_base($source, $relative_path)))
0702 {
0703 $image = relative_base($source, $relative_path);
0704 return @getimagesize($image);
0705 }
0706
0707 return false;
0708 }
0709
0710 /**
0711 * Obtain the width of the specified smilie
0712 */
0713 function get_smiley_width($src)
0714 {
0715 return get_smiley_dim($src, 0);
0716 }
0717
0718 /**
0719 * Obtain the height of the specified smilie
0720 */
0721 function get_smiley_height($src)
0722 {
0723 return get_smiley_dim($src, 1);
0724 }
0725
0726 /**
0727 * Obtain the size of the specified smilie (using the cache if possible) and cache the value
0728 */
0729 function get_smiley_dim($source, $axis)
0730 {
0731 if (empty($source))
0732 {
0733 return 15;
0734 }
0735
0736 static $smiley_cache = array();
0737
0738 if (isset($smiley_cache[$source]))
0739 {
0740 return $smiley_cache[$source][$axis];
0741 }
0742
0743 global $convert, $user;
0744
0745 $orig_source = $source;
0746
0747 if (!isset($convert->convertor['smilies_path']))
0748 {
0749 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_SMILIES_PATH'], 'get_smiley_dim()'), __LINE__, __FILE__);
0750 }
0751
0752 if (!empty($convert->convertor['smilies_path']) && strpos($source, $convert->convertor['smilies_path']) !== 0)
0753 {
0754 $source = $convert->convertor['smilies_path'] . $source;
0755 }
0756
0757 $smiley_cache[$orig_source] = get_image_dim($source);
0758
0759 if (empty($smiley_cache[$orig_source]) || empty($smiley_cache[$orig_source][0]) || empty($smiley_cache[$orig_source][1]))
0760 {
0761 $smiley_cache[$orig_source] = array(15, 15);
0762 return 15;
0763 }
0764
0765 return $smiley_cache[$orig_source][$axis];
0766 }
0767
0768 /**
0769 * Obtain the width of the specified avatar
0770 */
0771 function get_avatar_width($src, $func = false, $arg1 = false, $arg2 = false)
0772 {
0773 return get_avatar_dim($src, 0, $func, $arg1, $arg2);
0774 }
0775
0776 /**
0777 * Obtain the height of the specified avatar
0778 */
0779 function get_avatar_height($src, $func = false, $arg1 = false, $arg2 = false)
0780 {
0781 return get_avatar_dim($src, 1, $func, $arg1, $arg2);
0782 }
0783
0784 /**
0785 */
0786 function get_avatar_dim($src, $axis, $func = false, $arg1 = false, $arg2 = false)
0787 {
0788 $avatar_type = AVATAR_UPLOAD;
0789
0790 if ($func)
0791 {
0792 if ($arg1 || $arg2)
0793 {
0794 $ary = array($arg1);
0795
0796 if ($arg2)
0797 {
0798 $ary[] = $arg2;
0799 }
0800
0801 $avatar_type = call_user_func_array($func, $ary);
0802 }
0803 else
0804 {
0805 $avatar_type = call_user_func($func);
0806 }
0807 }
0808
0809 switch ($avatar_type)
0810 {
0811 case AVATAR_UPLOAD:
0812 return get_upload_avatar_dim($src, $axis);
0813 break;
0814
0815 case AVATAR_GALLERY:
0816 return get_gallery_avatar_dim($src, $axis);
0817 break;
0818
0819 case AVATAR_REMOTE:
0820 // see notes on this functions usage and (hopefully) model $func to avoid this accordingly
0821 return get_remote_avatar_dim($src, $axis);
0822 break;
0823
0824 default:
0825 $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
0826 $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
0827
0828 return $axis ? $default_y : $default_x;
0829 break;
0830 }
0831 }
0832
0833 /**
0834 * Obtain the size of the specified uploaded avatar (using the cache if possible) and cache the value
0835 */
0836 function get_upload_avatar_dim($source, $axis)
0837 {
0838 static $cachedims = false;
0839 static $cachekey = false;
0840
0841 if (empty($source))
0842 {
0843 return 0;
0844 }
0845
0846 if ($cachekey == $source)
0847 {
0848 return $cachedims[$axis];
0849 }
0850
0851 if (substr($source, 0, 7) == 'upload:')
0852 {
0853 $source = substr($source, 7);
0854 }
0855
0856 global $convert, $user;
0857
0858 if (!isset($convert->convertor['avatar_path']))
0859 {
0860 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_AVATAR_PATH'], 'get_upload_avatar_dim()'), __LINE__, __FILE__);
0861 }
0862
0863 if (!empty($convert->convertor['avatar_path']) && strpos($source, $convert->convertor['avatar_path']) !== 0)
0864 {
0865 $source = path($convert->convertor['avatar_path'], empty($convert->convertor['source_path_absolute'])) . $source;
0866 }
0867
0868 $cachedims = get_image_dim($source);
0869
0870 if (empty($cachedims) || empty($cachedims[0]) || empty($cachedims[1]))
0871 {
0872 $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
0873 $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
0874
0875 $cachedims = array($default_x, $default_y);
0876 }
0877
0878 return $cachedims[$axis];
0879 }
0880
0881 /**
0882 * Obtain the size of the specified gallery avatar (using the cache if possible) and cache the value
0883 */
0884 function get_gallery_avatar_dim($source, $axis)
0885 {
0886 if (empty($source))
0887 {
0888 return 0;
0889 }
0890
0891 static $avatar_cache = array();
0892
0893 if (isset($avatar_cache[$source]))
0894 {
0895 return $avatar_cache[$source][$axis];
0896 }
0897
0898 global $convert, $user;
0899
0900 $orig_source = $source;
0901
0902 if (!isset($convert->convertor['avatar_gallery_path']))
0903 {
0904 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GALLERY_PATH'], 'get_gallery_avatar_dim()'), __LINE__, __FILE__);
0905 }
0906
0907 if (!empty($convert->convertor['avatar_gallery_path']) && strpos($source, $convert->convertor['avatar_gallery_path']) !== 0)
0908 {
0909 $source = path($convert->convertor['avatar_gallery_path'], empty($convert->convertor['source_path_absolute'])) . $source;
0910 }
0911
0912 $avatar_cache[$orig_source] = get_image_dim($source);
0913
0914 if (empty($avatar_cache[$orig_source]) || empty($avatar_cache[$orig_source][0]) || empty($avatar_cache[$orig_source][1]))
0915 {
0916 $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
0917 $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
0918
0919 $avatar_cache[$orig_source] = array($default_x, $default_y);
0920 }
0921
0922 return $avatar_cache[$orig_source][$axis];
0923 }
0924
0925 /**
0926 * Obtain the size of the specified remote avatar (using the cache if possible) and cache the value
0927 * Whilst it's unlikely that remote avatars will be duplicated, it is possible so caching seems the best option
0928 * This should only be called from a post processing step due to the possibility of network timeouts
0929 */
0930 function get_remote_avatar_dim($src, $axis)
0931 {
0932 if (empty($src))
0933 {
0934 return 0;
0935 }
0936
0937 static $remote_avatar_cache = array();
0938
0939 // an ugly hack: we assume that the dimensions of each remote avatar are accessed exactly twice (x and y)
0940 if (isset($remote_avatar_cache[$src]))
0941 {
0942 $retval = $remote_avatar_cache[$src][$axis];
0943 unset($remote_avatar_cache);
0944 return $retval;
0945 }
0946
0947 $url_info = @parse_url($src);
0948 if (empty($url_info['host']))
0949 {
0950 return 0;
0951 }
0952 $host = $url_info['host'];
0953 $port = (isset($url_info['port'])) ? $url_info['port'] : 0;
0954 $protocol = (isset($url_info['scheme'])) ? $url_info['scheme'] : 'http';
0955 if (empty($port))
0956 {
0957 switch (strtolower($protocol))
0958 {
0959 case 'ftp':
0960 $port = 21;
0961 break;
0962
0963 case 'https':
0964 $port = 443;
0965 break;
0966
0967 default:
0968 $port = 80;
0969 }
0970 }
0971
0972 $timeout = @ini_get('default_socket_timeout');
0973 @ini_set('default_socket_timeout', 2);
0974
0975 // We're just trying to reach the server to avoid timeouts
0976 $fp = @fsockopen($host, $port, $errno, $errstr, 1);
0977 if ($fp)
0978 {
0979 $remote_avatar_cache[$src] = @getimagesize($src);
0980 fclose($fp);
0981 }
0982
0983 $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
0984 $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
0985 $default = array($default_x, $default_y);
0986
0987 if (empty($remote_avatar_cache[$src]) || empty($remote_avatar_cache[$src][0]) || empty($remote_avatar_cache[$src][1]))
0988 {
0989 $remote_avatar_cache[$src] = $default;
0990 }
0991 else
0992 {
0993 // We trust gallery and uploaded avatars to conform to the size settings; we might have to adjust here
0994 if ($remote_avatar_cache[$src][0] > $default_x || $remote_avatar_cache[$src][1] > $default_y)
0995 {
0996 $bigger = ($remote_avatar_cache[$src][0] > $remote_avatar_cache[$src][1]) ? 0 : 1;
0997 $ratio = $default[$bigger] / $remote_avatar_cache[$src][$bigger];
0998 $remote_avatar_cache[$src][0] = (int) ($remote_avatar_cache[$src][0] * $ratio);
0999 $remote_avatar_cache[$src][1] = (int) ($remote_avatar_cache[$src][1] * $ratio);
1000 }
1001 }
1002
1003 @ini_set('default_socket_timeout', $timeout);
1004 return $remote_avatar_cache[$src][$axis];
1005 }
1006
1007 function set_user_options()
1008 {
1009 global $convert_row;
1010
1011 // Key need to be set in row, else default value is chosen
1012 $keyoptions = array(
1013 'viewimg' => array('bit' => 0, 'default' => 1),
1014 'viewflash' => array('bit' => 1, 'default' => 1),
1015 'viewsmilies' => array('bit' => 2, 'default' => 1),
1016 'viewsigs' => array('bit' => 3, 'default' => 1),
1017 'viewavatars' => array('bit' => 4, 'default' => 1),
1018 'viewcensors' => array('bit' => 5, 'default' => 1),
1019 'attachsig' => array('bit' => 6, 'default' => 0),
1020 'bbcode' => array('bit' => 8, 'default' => 1),
1021 'smilies' => array('bit' => 9, 'default' => 1),
1022 'sig_bbcode' => array('bit' => 15, 'default' => 1),
1023 'sig_smilies' => array('bit' => 16, 'default' => 1),
1024 'sig_links' => array('bit' => 17, 'default' => 1),
1025 );
1026
1027 $option_field = 0;
1028
1029 foreach ($keyoptions as $key => $key_ary)
1030 {
1031 $value = (isset($convert_row[$key])) ? (int) $convert_row[$key] : $key_ary['default'];
1032
1033 if ($value && !($option_field & 1 << $key_ary['bit']))
1034 {
1035 $option_field += 1 << $key_ary['bit'];
1036 }
1037 }
1038
1039 return $option_field;
1040 }
1041
1042 /**
1043 * Index messages on the fly as we convert them
1044 * @todo naderman, can you check that this works with the new search plugins as it's use is currently disabled (and thus untested)
1045 function search_indexing($message = '')
1046 {
1047 global $fulltext_search, $convert_row;
1048
1049 if (!isset($convert_row['post_id']))
1050 {
1051 return;
1052 }
1053
1054 if (!$message)
1055 {
1056 if (!isset($convert_row['message']))
1057 {
1058 return;
1059 }
1060
1061 $message = $convert_row['message'];
1062 }
1063
1064 $title = (isset($convert_row['title'])) ? $convert_row['title'] : '';
1065
1066 $fulltext_search->index('post', $convert_row['post_id'], $message, $title, $convert_row['poster_id'], $convert_row['forum_id']);
1067 }
1068 */
1069
1070 function make_unique_filename($filename)
1071 {
1072 if (!strlen($filename))
1073 {
1074 $filename = md5(unique_id()) . '.dat';
1075 }
1076 else if ($filename[0] == '.')
1077 {
1078 $filename = md5(unique_id()) . $filename;
1079 }
1080 else if (preg_match('/\.([a-z]+)$/i', $filename, $m))
1081 {
1082 $filename = preg_replace('/\.([a-z]+)$/i', '_' . md5(unique_id()) . '.\1', $filename);
1083 }
1084 else
1085 {
1086 $filename .= '_' . md5(unique_id()) . '.dat';
1087 }
1088
1089 return $filename;
1090 }
1091
1092 function words_unique(&$words)
1093 {
1094 reset($words);
1095 $return_array = array();
1096
1097 $word = current($words);
1098 do
1099 {
1100 $return_array[$word] = $word;
1101 }
1102 while ($word = next($words));
1103
1104 return $return_array;
1105 }
1106
1107 /**
1108 * Adds a user to the specified group and optionally makes them a group leader
1109 * This function does not create the group if it does not exist and so should only be called after the groups have been created
1110 */
1111 function add_user_group($group_id, $user_id, $group_leader = false)
1112 {
1113 global $db;
1114
1115 $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1116 'group_id' => $group_id,
1117 'user_id' => $user_id,
1118 'group_leader' => ($group_leader) ? 1 : 0,
1119 'user_pending' => 0));
1120 $db->sql_query($sql);
1121 }
1122
1123 // STANDALONE FUNCTIONS
1124
1125 /**
1126 * Add users to the pre-defined "special" groups
1127 *
1128 * @param string $group The name of the special group to add to
1129 * @param string $select_query An SQL query to retrieve the user(s) to add to the group
1130 * @param bool $use_src_db
1131 */
1132 function user_group_auth($group, $select_query, $use_src_db)
1133 {
1134 global $convert, $user, $db, $src_db, $same_db;
1135
1136 if (!in_array($group, array('guests', 'registered', 'registered_coppa', 'global_moderators', 'administrators', 'bots')))
1137 {
1138 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_WRONG_GROUP'], $group, 'user_group_auth()'), __LINE__, __FILE__, true);
1139 return;
1140 }
1141
1142 $sql = 'SELECT group_id
1143 FROM ' . GROUPS_TABLE . "
1144 WHERE group_name = '" . $db->sql_escape(strtoupper($group)) . "'";
1145 $result = $db->sql_query($sql);
1146 $group_id = (int) $db->sql_fetchfield('group_id');
1147 $db->sql_freeresult($result);
1148
1149 if (!$group_id)
1150 {
1151 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GROUP'], $group, 'user_group_auth()'), __LINE__, __FILE__, true);
1152 return;
1153 }
1154
1155 if ($same_db || !$use_src_db)
1156 {
1157 $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' (user_id, group_id, user_pending)
1158 ' . str_replace('{' . strtoupper($group) . '}', $group_id . ', 0', $select_query);
1159 $db->sql_query($sql);
1160 }
1161 else
1162 {
1163 $result = $src_db->sql_query(str_replace('{' . strtoupper($group) . '}', $group_id . ' ', $select_query));
1164 while ($row = $src_db->sql_fetchrow($result))
1165 {
1166 // this might become quite a lot of INSERTS unfortunately
1167 $sql = 'INSERT INTO ' . USER_GROUP_TABLE . " (user_id, group_id, user_pending)
1168 VALUES ({$row['user_id']}, $group_id, 0)";
1169 $db->sql_query($sql);
1170 }
1171 $src_db->sql_freeresult($result);
1172 }
1173 }
1174
1175 /**
1176 * Retrieves configuration information from the source forum and caches it as an array
1177 * Both database and file driven configuration formats can be handled
1178 * (the type used is specified in $config_schema, see convert_phpbb20.php for more details)
1179 */
1180 function get_config()
1181 {
1182 static $convert_config;
1183 global $user;
1184
1185 if (isset($convert_config))
1186 {
1187 return $convert_config;
1188 }
1189
1190 global $src_db, $same_db;
1191 global $convert;
1192
1193 if ($convert->config_schema['table_format'] != 'file')
1194 {
1195 if ($convert->mysql_convert && $same_db)
1196 {
1197 $src_db->sql_query("SET NAMES 'binary'");
1198 }
1199
1200 $sql = 'SELECT * FROM ' . $convert->src_table_prefix . $convert->config_schema['table_name'];
1201 $result = $src_db->sql_query($sql);
1202 $row = $src_db->sql_fetchrow($result);
1203
1204 if (!$row)
1205 {
1206 $convert->p_master->error($user->lang['CONV_ERROR_GET_CONFIG'], __LINE__, __FILE__);
1207 }
1208 }
1209
1210 if (is_array($convert->config_schema['table_format']))
1211 {
1212 $convert_config = array();
1213 $key = key($convert->config_schema['table_format']);
1214 $val = current($convert->config_schema['table_format']);
1215
1216 do
1217 {
1218 $convert_config[$row[$key]] = $row[$val];
1219 }
1220 while ($row = $src_db->sql_fetchrow($result));
1221 $src_db->sql_freeresult($result);
1222
1223 if ($convert->mysql_convert && $same_db)
1224 {
1225 $src_db->sql_query("SET NAMES 'utf8'");
1226 }
1227 }
1228 else if ($convert->config_schema['table_format'] == 'file')
1229 {
1230 $filename = $convert->options['forum_path'] . '/' . $convert->config_schema['filename'];
1231 if (!file_exists($filename))
1232 {
1233 $convert->p_master->error($user->lang('FILE_NOT_FOUND', $filename), __LINE__, __FILE__);
1234 }
1235
1236 if (isset($convert->config_schema['array_name']))
1237 {
1238 unset($convert->config_schema['array_name']);
1239 }
1240
1241 $convert_config = extract_variables_from_file($filename);
1242 if (!empty($convert->config_schema['array_name']))
1243 {
1244 $convert_config = $convert_config[$convert->config_schema['array_name']];
1245 }
1246 }
1247 else
1248 {
1249 $convert_config = $row;
1250 if ($convert->mysql_convert && $same_db)
1251 {
1252 $src_db->sql_query("SET NAMES 'utf8'");
1253 }
1254 }
1255
1256 if (!count($convert_config))
1257 {
1258 $convert->p_master->error($user->lang['CONV_ERROR_CONFIG_EMPTY'], __LINE__, __FILE__);
1259 }
1260
1261 return $convert_config;
1262 }
1263
1264 /**
1265 * Transfers the relevant configuration information from the source forum
1266 * The mapping of fields is specified in $config_schema, see convert_phpbb20.php for more details
1267 */
1268 function restore_config($schema)
1269 {
1270 global $config;
1271
1272 $convert_config = get_config();
1273
1274 foreach ($schema['settings'] as $config_name => $src)
1275 {
1276 if (preg_match('/(.*)\((.*)\)/', $src, $m))
1277 {
1278 $var = (empty($m[2]) || empty($convert_config[$m[2]])) ? "''" : "'" . addslashes($convert_config[$m[2]]) . "'";
1279 $exec = '$config_value = ' . $m[1] . '(' . $var . ');';
1280 // @codingStandardsIgnoreStart
1281 eval($exec);
1282 // @codingStandardsIgnoreEnd
1283 }
1284 else
1285 {
1286 if ($schema['table_format'] != 'file' || empty($schema['array_name']))
1287 {
1288 $config_value = (isset($convert_config[$src])) ? $convert_config[$src] : '';
1289 }
1290 else if (!empty($schema['array_name']))
1291 {
1292 $src_ary = $schema['array_name'];
1293 $config_value = (isset($convert_config[$src_ary][$src])) ? $convert_config[$src_ary][$src] : '';
1294 }
1295 }
1296
1297 if ($config_value !== '')
1298 {
1299 // Most are...
1300 if (is_string($config_value))
1301 {
1302 $config_value = truncate_string(utf8_htmlspecialchars($config_value), 255, 255, false);
1303 }
1304
1305 $config->set($config_name, $config_value);
1306 }
1307 }
1308 }
1309
1310 /**
1311 * Update the count of PM's in custom folders for all users
1312 */
1313 function update_folder_pm_count()
1314 {
1315 global $db;
1316
1317 $sql = 'SELECT user_id, folder_id, COUNT(msg_id) as num_messages
1318 FROM ' . PRIVMSGS_TO_TABLE . '
1319 WHERE folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ', ' . PRIVMSGS_INBOX . ', ' . PRIVMSGS_OUTBOX . ', ' . PRIVMSGS_SENTBOX . ')
1320 GROUP BY folder_id, user_id';
1321 $result = $db->sql_query($sql);
1322
1323 while ($row = $db->sql_fetchrow($result))
1324 {
1325 $db->sql_query('UPDATE ' . PRIVMSGS_FOLDER_TABLE . ' SET pm_count = ' . $row['num_messages'] . '
1326 WHERE user_id = ' . $row['user_id'] . ' AND folder_id = ' . $row['folder_id']);
1327 }
1328 $db->sql_freeresult($result);
1329 }
1330
1331 // Functions mainly used by the main convertor script
1332
1333 function path($path, $path_relative = true)
1334 {
1335 if ($path === false)
1336 {
1337 return '';
1338 }
1339
1340 if (substr($path, -1) != '/')
1341 {
1342 $path .= '/';
1343 }
1344
1345 if (!$path_relative)
1346 {
1347 return $path;
1348 }
1349
1350 if (substr($path, 0, 1) == '/')
1351 {
1352 $path = substr($path, 1);
1353 }
1354
1355 return $path;
1356 }
1357
1358 /**
1359 * Extract the variables defined in a configuration file
1360 * @todo As noted by Xore we need to look at this from a security perspective
1361 */
1362 function extract_variables_from_file($_filename)
1363 {
1364 include($_filename);
1365
1366 $vars = get_defined_vars();
1367 unset($vars['_filename']);
1368
1369 return $vars;
1370 }
1371
1372 function get_path($src_path, $src_url, $test_file)
1373 {
1374 global $phpbb_root_path, $phpEx;
1375
1376 $board_config = get_config();
1377
1378 $test_file = preg_replace('/\.php$/i', ".$phpEx", $test_file);
1379 $src_path = path($src_path);
1380
1381 if (@file_exists($phpbb_root_path . $src_path . $test_file))
1382 {
1383 return $src_path;
1384 }
1385
1386 if (!empty($src_url) && !empty($board_config['server_name']))
1387 {
1388 if (!preg_match('#https?://([^/]+)(.*)#i', $src_url, $m))
1389 {
1390 return false;
1391 }
1392
1393 if ($m[1] != $board_config['server_name'])
1394 {
1395 return false;
1396 }
1397
1398 $url_parts = explode('/', $m[2]);
1399 if (substr($src_url, -1) != '/')
1400 {
1401 if (preg_match('/.*\.([a-z0-9]{3,4})$/i', $url_parts[count($url_parts) - 1]))
1402 {
1403 $url_parts[count($url_parts) - 1] = '';
1404 }
1405 else
1406 {
1407 $url_parts[] = '';
1408 }
1409 }
1410
1411 $script_path = $board_config['script_path'];
1412 if (substr($script_path, -1) == '/')
1413 {
1414 $script_path = substr($script_path, 0, -1);
1415 }
1416
1417 $path_array = array();
1418
1419 $phpbb_parts = explode('/', $script_path);
1420 for ($i = 0, $end = count($url_parts); $i < $end; ++$i)
1421 {
1422 if ($i < count($phpbb_parts[$i]) && $url_parts[$i] == $phpbb_parts[$i])
1423 {
1424 $path_array[] = $url_parts[$i];
1425 unset($url_parts[$i]);
1426 }
1427 else
1428 {
1429 $path = '';
1430 for ($j = $i, $end2 = count($phpbb_parts); $j < $end2; ++$j)
1431 {
1432 $path .= '../';
1433 }
1434 $path .= implode('/', $url_parts);
1435 break;
1436 }
1437 }
1438
1439 if (!empty($path))
1440 {
1441 if (@file_exists($phpbb_root_path . $path . $test_file))
1442 {
1443 return $path;
1444 }
1445 }
1446 }
1447
1448 return false;
1449 }
1450
1451 function compare_table($tables, $tablename, &$prefixes)
1452 {
1453 for ($i = 0, $table_size = count($tables); $i < $table_size; ++$i)
1454 {
1455 if (preg_match('/(.*)' . $tables[$i] . '$/', $tablename, $m))
1456 {
1457 if (empty($m[1]))
1458 {
1459 $m[1] = '*';
1460 }
1461
1462 if (isset($prefixes[$m[1]]))
1463 {
1464 $prefixes[$m[1]]++;
1465 }
1466 else
1467 {
1468 $prefixes[$m[1]] = 1;
1469 }
1470 }
1471 }
1472 }
1473
1474 /**
1475 * Grant permissions to a specified user or group
1476 *
1477 * @param string $ug_type user|group|user_role|group_role
1478 * @param mixed $forum_id forum ids (array|int|0) -> 0 == all forums
1479 * @param mixed $ug_id [int] user_id|group_id : [string] usergroup name
1480 * @param mixed $acl_list [string] acl entry : [array] acl entries : [string] role entry
1481 * @param int $setting ACL_YES|ACL_NO|ACL_NEVER
1482 */
1483 function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO)
1484 {
1485 global $db;
1486 static $acl_option_ids, $group_ids;
1487
1488 if (($ug_type == 'group' || $ug_type == 'group_role') && is_string($ug_id))
1489 {
1490 if (!isset($group_ids[$ug_id]))
1491 {
1492 $sql = 'SELECT group_id
1493 FROM ' . GROUPS_TABLE . "
1494 WHERE group_name = '" . $db->sql_escape(strtoupper($ug_id)) . "'";
1495 $result = $db->sql_query_limit($sql, 1);
1496 $id = (int) $db->sql_fetchfield('group_id');
1497 $db->sql_freeresult($result);
1498
1499 if (!$id)
1500 {
1501 return;
1502 }
1503
1504 $group_ids[$ug_id] = $id;
1505 }
1506
1507 $ug_id = (int) $group_ids[$ug_id];
1508 }
1509
1510 $table = ($ug_type == 'user' || $ug_type == 'user_role') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE;
1511 $id_field = ($ug_type == 'user' || $ug_type == 'user_role') ? 'user_id' : 'group_id';
1512
1513 // Role based permissions are the simplest to handle so check for them first
1514 if ($ug_type == 'user_role' || $ug_type == 'group_role')
1515 {
1516 if (is_numeric($forum_id))
1517 {
1518 $sql = 'SELECT role_id
1519 FROM ' . ACL_ROLES_TABLE . "
1520 WHERE role_name = 'ROLE_" . $db->sql_escape($acl_list) . "'";
1521 $result = $db->sql_query_limit($sql, 1);
1522 $row = $db->sql_fetchrow($result);
1523 $db->sql_freeresult($result);
1524
1525 // If we have no role id there is something wrong here
1526 if ($row)
1527 {
1528 $sql = "INSERT INTO $table ($id_field, forum_id, auth_role_id) VALUES ($ug_id, $forum_id, " . $row['role_id'] . ')';
1529 $db->sql_query($sql);
1530 }
1531 }
1532
1533 return;
1534 }
1535
1536 // Build correct parameters
1537 $auth = array();
1538
1539 if (!is_array($acl_list))
1540 {
1541 $auth = array($acl_list => $setting);
1542 }
1543 else
1544 {
1545 foreach ($acl_list as $auth_option)
1546 {
1547 $auth[$auth_option] = $setting;
1548 }
1549 }
1550 unset($acl_list);
1551
1552 if (!is_array($forum_id))
1553 {
1554 $forum_id = array($forum_id);
1555 }
1556
1557 // Set any flags as required
1558 foreach ($auth as $auth_option => $acl_setting)
1559 {
1560 $flag = substr($auth_option, 0, strpos($auth_option, '_') + 1);
1561 if (empty($auth[$flag]))
1562 {
1563 $auth[$flag] = $acl_setting;
1564 }
1565 }
1566
1567 if (!is_array($acl_option_ids) || empty($acl_option_ids))
1568 {
1569 $sql = 'SELECT auth_option_id, auth_option
1570 FROM ' . ACL_OPTIONS_TABLE;
1571 $result = $db->sql_query($sql);
1572
1573 while ($row = $db->sql_fetchrow($result))
1574 {
1575 $acl_option_ids[$row['auth_option']] = $row['auth_option_id'];
1576 }
1577 $db->sql_freeresult($result);
1578 }
1579
1580 $sql_forum = 'AND ' . $db->sql_in_set('a.forum_id', array_map('intval', $forum_id), false, true);
1581
1582 $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";
1583 $result = $db->sql_query($sql);
1584
1585 $cur_auth = array();
1586 while ($row = $db->sql_fetchrow($result))
1587 {
1588 $cur_auth[$row['forum_id']][$row['auth_option_id']] = $row['auth_setting'];
1589 }
1590 $db->sql_freeresult($result);
1591
1592 $sql_ary = array();
1593 foreach ($forum_id as $forum)
1594 {
1595 foreach ($auth as $auth_option => $setting)
1596 {
1597 $auth_option_id = $acl_option_ids[$auth_option];
1598
1599 if (!$auth_option_id)
1600 {
1601 continue;
1602 }
1603
1604 switch ($setting)
1605 {
1606 case ACL_NO:
1607 if (isset($cur_auth[$forum][$auth_option_id]))
1608 {
1609 $sql_ary['delete'][] = "DELETE FROM $table
1610 WHERE forum_id = $forum
1611 AND auth_option_id = $auth_option_id
1612 AND $id_field = $ug_id";
1613 }
1614 break;
1615
1616 default:
1617 if (!isset($cur_auth[$forum][$auth_option_id]))
1618 {
1619 $sql_ary['insert'][] = "$ug_id, $forum, $auth_option_id, $setting";
1620 }
1621 else if ($cur_auth[$forum][$auth_option_id] != $setting)
1622 {
1623 $sql_ary['update'][] = "UPDATE " . $table . "
1624 SET auth_setting = $setting
1625 WHERE $id_field = $ug_id
1626 AND forum_id = $forum
1627 AND auth_option_id = $auth_option_id";
1628 }
1629 }
1630 }
1631 }
1632 unset($cur_auth);
1633
1634 $sql = '';
1635 foreach ($sql_ary as $sql_type => $sql_subary)
1636 {
1637 switch ($sql_type)
1638 {
1639 case 'insert':
1640 switch ($db->get_sql_layer())
1641 {
1642 case 'sqlite3':
1643 case 'mssqlnative':
1644 $sql = implode(' UNION ALL ', preg_replace('#^(.*?)$#', 'SELECT \1', $sql_subary));
1645 break;
1646
1647 default:
1648 foreach ($sql_subary as $sql)
1649 {
1650 $sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) VALUES ($sql)";
1651 $db->sql_query($sql);
1652 $sql = '';
1653 }
1654 }
1655
1656 if ($sql != '')
1657 {
1658 $sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) $sql";
1659 $db->sql_query($sql);
1660 }
1661 break;
1662
1663 case 'update':
1664 case 'delete':
1665 foreach ($sql_subary as $sql)
1666 {
1667 $db->sql_query($sql);
1668 $sql = '';
1669 }
1670 break;
1671 }
1672 unset($sql_ary[$sql_type]);
1673 }
1674 unset($sql_ary);
1675
1676 }
1677
1678 /**
1679 * Update the count of unread private messages for all users
1680 */
1681 function update_unread_count()
1682 {
1683 global $db;
1684
1685 $sql = 'SELECT user_id, COUNT(msg_id) as num_messages
1686 FROM ' . PRIVMSGS_TO_TABLE . '
1687 WHERE pm_unread = 1
1688 AND folder_id <> ' . PRIVMSGS_OUTBOX . '
1689 GROUP BY user_id';
1690 $result = $db->sql_query($sql);
1691
1692 while ($row = $db->sql_fetchrow($result))
1693 {
1694 $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_unread_privmsg = ' . $row['num_messages'] . '
1695 WHERE user_id = ' . $row['user_id']);
1696 }
1697 $db->sql_freeresult($result);
1698 }
1699
1700 /**
1701 * Add any of the pre-defined "special" groups which are missing from the database
1702 */
1703 function add_default_groups()
1704 {
1705 global $db;
1706
1707 $default_groups = array(
1708 'GUESTS' => array('', 0, 0),
1709 'REGISTERED' => array('', 0, 0),
1710 'REGISTERED_COPPA' => array('', 0, 0),
1711 'GLOBAL_MODERATORS' => array('00AA00', 2, 0),
1712 'ADMINISTRATORS' => array('AA0000', 1, 1),
1713 'BOTS' => array('9E8DA7', 0, 0),
1714 'NEWLY_REGISTERED' => array('', 0, 0),
1715 );
1716
1717 $sql = 'SELECT *
1718 FROM ' . GROUPS_TABLE . '
1719 WHERE ' . $db->sql_in_set('group_name', array_keys($default_groups));
1720 $result = $db->sql_query($sql);
1721
1722 while ($row = $db->sql_fetchrow($result))
1723 {
1724 unset($default_groups[strtoupper($row['group_name'])]);
1725 }
1726 $db->sql_freeresult($result);
1727
1728 $sql_ary = array();
1729
1730 foreach ($default_groups as $name => $data)
1731 {
1732 $sql_ary[] = array(
1733 'group_name' => (string) $name,
1734 'group_desc' => '',
1735 'group_desc_uid' => '',
1736 'group_desc_bitfield' => '',
1737 'group_type' => GROUP_SPECIAL,
1738 'group_colour' => (string) $data[0],
1739 'group_legend' => (int) $data[1],
1740 'group_founder_manage' => (int) $data[2],
1741 );
1742 }
1743
1744 if (count($sql_ary))
1745 {
1746 $db->sql_multi_insert(GROUPS_TABLE, $sql_ary);
1747 }
1748 }
1749
1750 function add_groups_to_teampage()
1751 {
1752 global $db;
1753
1754 $teampage_groups = array(
1755 'ADMINISTRATORS' => 1,
1756 'GLOBAL_MODERATORS' => 2,
1757 );
1758
1759 $sql = 'SELECT *
1760 FROM ' . GROUPS_TABLE . '
1761 WHERE ' . $db->sql_in_set('group_name', array_keys($teampage_groups));
1762 $result = $db->sql_query($sql);
1763
1764 $teampage_ary = array();
1765 while ($row = $db->sql_fetchrow($result))
1766 {
1767 $teampage_ary[] = array(
1768 'group_id' => (int) $row['group_id'],
1769 'teampage_name' => '',
1770 'teampage_position' => (int) $teampage_groups[$row['group_name']],
1771 'teampage_parent' => 0,
1772 );
1773 }
1774 $db->sql_freeresult($result);
1775
1776 if (count($teampage_ary))
1777 {
1778 $db->sql_multi_insert(TEAMPAGE_TABLE, $teampage_ary);
1779 }
1780 }
1781
1782
1783 /**
1784 * Sync post count. We might need to do this in batches.
1785 */
1786 function sync_post_count($offset, $limit)
1787 {
1788 global $db;
1789 $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id
1790 FROM ' . POSTS_TABLE . '
1791 WHERE post_postcount = 1
1792 AND post_visibility = ' . ITEM_APPROVED . '
1793 GROUP BY poster_id
1794 ORDER BY poster_id';
1795 $result = $db->sql_query_limit($sql, $limit, $offset);
1796
1797 while ($row = $db->sql_fetchrow($result))
1798 {
1799 $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['poster_id']}");
1800 }
1801 $db->sql_freeresult($result);
1802 }
1803
1804 /**
1805 * Add the search bots into the database
1806 * This code should be used in execute_last if the source database did not have bots
1807 * If you are converting bots this function should not be called
1808 * @todo We might want to look at sharing the bot list between the install code and this code for consistancy
1809 */
1810 function add_bots()
1811 {
1812 global $db, $convert, $user, $config, $phpbb_root_path, $phpEx;
1813
1814 $db->sql_query($convert->truncate_statement . BOTS_TABLE);
1815
1816 $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name = 'BOTS'";
1817 $result = $db->sql_query($sql);
1818 $group_id = (int) $db->sql_fetchfield('group_id', false, $result);
1819 $db->sql_freeresult($result);
1820
1821 if (!$group_id)
1822 {
1823 add_default_groups();
1824
1825 $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name = 'BOTS'";
1826 $result = $db->sql_query($sql);
1827 $group_id = (int) $db->sql_fetchfield('group_id', false, $result);
1828 $db->sql_freeresult($result);
1829
1830 if (!$group_id)
1831 {
1832 global $install;
1833 $install->error($user->lang['CONV_ERROR_INCONSISTENT_GROUPS'], __LINE__, __FILE__);
1834 }
1835 }
1836
1837 $bots = array(
1838 'AdsBot [Google]' => array('AdsBot-Google', ''),
1839 'Ahrefs [Bot]' => array('AhrefsBot/', ''),
1840 'Alexa [Bot]' => array('ia_archiver', ''),
1841 'Alta Vista [Bot]' => array('Scooter/', ''),
1842 'Amazon [Bot]' => array('Amazonbot/', ''),
1843 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''),
1844 'Baidu [Spider]' => array('Baiduspider', ''),
1845 'Bing [Bot]' => array('bingbot/', ''),
1846 'DuckDuckGo [Bot]' => array('DuckDuckBot/', ''),
1847 'Exabot [Bot]' => array('Exabot/', ''),
1848 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''),
1849 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''),
1850 'Francis [Bot]' => array('http://www.neomo.de/', ''),
1851 'Gigabot [Bot]' => array('Gigabot/', ''),
1852 'Google Adsense [Bot]' => array('Mediapartners-Google', ''),
1853 'Google Desktop' => array('Google Desktop', ''),
1854 'Google Feedfetcher' => array('Feedfetcher-Google', ''),
1855 'Google [Bot]' => array('Googlebot', ''),
1856 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''),
1857 'Heritrix [Crawler]' => array('heritrix/1.', ''),
1858 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''),
1859 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''),
1860 'ichiro [Crawler]' => array('ichiro/', ''),
1861 'Majestic-12 [Bot]' => array('MJ12bot/', ''),
1862 'Metager [Bot]' => array('MetagerBot/', ''),
1863 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''),
1864 'MSN [Bot]' => array('msnbot/', ''),
1865 'MSNbot Media' => array('msnbot-media/', ''),
1866 'NG-Search [Bot]' => array('NG-Search/', ''),
1867 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''),
1868 'Nutch/CVS [Bot]' => array('NutchCVS/', ''),
1869 'OmniExplorer [Bot]' => array('OmniExplorer_Bot/', ''),
1870 'Online link [Validator]' => array('online link validator', ''),
1871 'psbot [Picsearch]' => array('psbot/0', ''),
1872 'Seekport [Bot]' => array('Seekbot/', ''),
1873 'Semrush [Bot]' => array('SemrushBot/', ''),
1874 'Sensis [Crawler]' => array('Sensis Web Crawler', ''),
1875 'SEO Crawler' => array('SEO search Crawler/', ''),
1876 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''),
1877 'SEOSearch [Crawler]' => array('SEOsearch/', ''),
1878 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''),
1879 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''),
1880 'Synoo [Bot]' => array('SynooBot/', ''),
1881 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''),
1882 'TurnitinBot [Bot]' => array('TurnitinBot/', ''),
1883 'Voyager [Bot]' => array('voyager/', ''),
1884 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''),
1885 'W3C [Linkcheck]' => array('W3C-checklink/', ''),
1886 'W3C [Validator]' => array('W3C_*Validator', ''),
1887 'WiseNut [Bot]' => array('http://www.WISEnutbot.com', ''),
1888 'YaCy [Bot]' => array('yacybot', ''),
1889 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''),
1890 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''),
1891 'Yahoo [Bot]' => array('Yahoo! Slurp', ''),
1892 'YahooSeeker [Bot]' => array('YahooSeeker/', ''),
1893 );
1894
1895 if (!function_exists('user_add'))
1896 {
1897 include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
1898 }
1899
1900 foreach ($bots as $bot_name => $bot_ary)
1901 {
1902 $user_row = array(
1903 'user_type' => USER_IGNORE,
1904 'group_id' => $group_id,
1905 'username' => $bot_name,
1906 'user_regdate' => time(),
1907 'user_password' => '',
1908 'user_colour' => '9E8DA7',
1909 'user_email' => '',
1910 'user_lang' => $config['default_lang'],
1911 'user_style' => 1,
1912 'user_timezone' => 'UTC',
1913 'user_allow_massemail' => 0,
1914 );
1915
1916 $user_id = user_add($user_row);
1917
1918 if ($user_id)
1919 {
1920 $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1921 'bot_active' => 1,
1922 'bot_name' => $bot_name,
1923 'user_id' => $user_id,
1924 'bot_agent' => $bot_ary[0],
1925 'bot_ip' => $bot_ary[1])
1926 );
1927 $db->sql_query($sql);
1928 }
1929 }
1930 }
1931
1932 /**
1933 * Update any dynamic configuration variables after the conversion is finished
1934 * @todo Confirm that this updates all relevant values since it has not necessarily been kept in sync with all changes
1935 */
1936 function update_dynamic_config()
1937 {
1938 global $db, $config;
1939
1940 // Get latest username
1941 $sql = 'SELECT user_id, username, user_colour
1942 FROM ' . USERS_TABLE . '
1943 WHERE user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
1944
1945 if (!empty($config['increment_user_id']))
1946 {
1947 $sql .= ' AND user_id <> ' . $config['increment_user_id'];
1948 }
1949
1950 $sql .= ' ORDER BY user_id DESC';
1951
1952 $result = $db->sql_query_limit($sql, 1);
1953 $row = $db->sql_fetchrow($result);
1954 $db->sql_freeresult($result);
1955
1956 if ($row)
1957 {
1958 $config->set('newest_user_id', $row['user_id'], false);
1959 $config->set('newest_username', $row['username'], false);
1960 $config->set('newest_user_colour', $row['user_colour'], false);
1961 }
1962
1963 // Also do not reset record online user/date. There will be old data or the fresh data from the schema.
1964 // set_config('record_online_users', 1, true);
1965 // set_config('record_online_date', time(), true);
1966
1967 $sql = 'SELECT COUNT(post_id) AS stat
1968 FROM ' . POSTS_TABLE . '
1969 WHERE post_visibility = ' . ITEM_APPROVED;
1970 $result = $db->sql_query($sql);
1971 $row = $db->sql_fetchrow($result);
1972 $db->sql_freeresult($result);
1973
1974 $config->set('num_posts', (int) $row['stat'], false);
1975
1976 $sql = 'SELECT COUNT(topic_id) AS stat
1977 FROM ' . TOPICS_TABLE . '
1978 WHERE topic_visibility = ' . ITEM_APPROVED;
1979 $result = $db->sql_query($sql);
1980 $row = $db->sql_fetchrow($result);
1981 $db->sql_freeresult($result);
1982
1983 $config->set('num_topics', (int) $row['stat'], false);
1984
1985 $sql = 'SELECT COUNT(user_id) AS stat
1986 FROM ' . USERS_TABLE . '
1987 WHERE user_type IN (' . USER_NORMAL . ',' . USER_FOUNDER . ')';
1988 $result = $db->sql_query($sql);
1989 $row = $db->sql_fetchrow($result);
1990 $db->sql_freeresult($result);
1991
1992 $config->set('num_users', (int) $row['stat'], false);
1993
1994 $sql = 'SELECT COUNT(attach_id) as stat
1995 FROM ' . ATTACHMENTS_TABLE . '
1996 WHERE is_orphan = 0';
1997 $result = $db->sql_query($sql);
1998 $config->set('num_files', (int) $db->sql_fetchfield('stat'), false);
1999 $db->sql_freeresult($result);
2000
2001 $sql = 'SELECT SUM(filesize) as stat
2002 FROM ' . ATTACHMENTS_TABLE . '
2003 WHERE is_orphan = 0';
2004 $result = $db->sql_query($sql);
2005 $config->set('upload_dir_size', (float) $db->sql_fetchfield('stat'), false);
2006 $db->sql_freeresult($result);
2007
2008 /**
2009 * We do not resync users post counts - this can be done by the admin after conversion if wanted.
2010 $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id
2011 FROM ' . POSTS_TABLE . '
2012 WHERE post_postcount = 1
2013 GROUP BY poster_id';
2014 $result = $db->sql_query($sql);
2015
2016 while ($row = $db->sql_fetchrow($result))
2017 {
2018 $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['poster_id']}");
2019 }
2020 $db->sql_freeresult($result);
2021 */
2022 }
2023
2024 /**
2025 * Updates topics_posted entries
2026 */
2027 function update_topics_posted()
2028 {
2029 global $db;
2030
2031 switch ($db->get_sql_layer())
2032 {
2033 case 'sqlite3':
2034 $db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE);
2035 break;
2036
2037 default:
2038 $db->sql_query('TRUNCATE TABLE ' . TOPICS_POSTED_TABLE);
2039 break;
2040 }
2041
2042 // This can get really nasty... therefore we only do the last six months
2043 $get_from_time = time() - (6 * 4 * 7 * 24 * 60 * 60);
2044
2045 // Select forum ids, do not include categories
2046 $sql = 'SELECT forum_id
2047 FROM ' . FORUMS_TABLE . '
2048 WHERE forum_type <> ' . FORUM_CAT;
2049 $result = $db->sql_query($sql);
2050
2051 $forum_ids = array();
2052 while ($row = $db->sql_fetchrow($result))
2053 {
2054 $forum_ids[] = $row['forum_id'];
2055 }
2056 $db->sql_freeresult($result);
2057
2058 // Any global announcements? ;)
2059 $forum_ids[] = 0;
2060
2061 // Now go through the forums and get us some topics...
2062 foreach ($forum_ids as $forum_id)
2063 {
2064 $sql = 'SELECT p.poster_id, p.topic_id
2065 FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t
2066 WHERE t.forum_id = ' . $forum_id . '
2067 AND t.topic_moved_id = 0
2068 AND t.topic_last_post_time > ' . $get_from_time . '
2069 AND t.topic_id = p.topic_id
2070 AND p.poster_id <> ' . ANONYMOUS . '
2071 GROUP BY p.poster_id, p.topic_id';
2072 $result = $db->sql_query($sql);
2073
2074 $posted = array();
2075 while ($row = $db->sql_fetchrow($result))
2076 {
2077 $posted[$row['poster_id']][] = $row['topic_id'];
2078 }
2079 $db->sql_freeresult($result);
2080
2081 $sql_ary = array();
2082 foreach ($posted as $user_id => $topic_row)
2083 {
2084 foreach ($topic_row as $topic_id)
2085 {
2086 $sql_ary[] = array(
2087 'user_id' => (int) $user_id,
2088 'topic_id' => (int) $topic_id,
2089 'topic_posted' => 1,
2090 );
2091 }
2092 }
2093 unset($posted);
2094
2095 if (count($sql_ary))
2096 {
2097 $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary);
2098 }
2099 }
2100 }
2101
2102 /**
2103 * Ensure that all users have a default group specified and update related information such as their colour
2104 */
2105 function fix_empty_primary_groups()
2106 {
2107 global $db;
2108
2109 // Set group ids for users not already having it
2110 $sql = 'UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('registered') . '
2111 WHERE group_id = 0 AND user_type = ' . USER_INACTIVE;
2112 $db->sql_query($sql);
2113
2114 $sql = 'UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('registered') . '
2115 WHERE group_id = 0 AND user_type = ' . USER_NORMAL;
2116 $db->sql_query($sql);
2117
2118 $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('guests') . ' WHERE user_id = ' . ANONYMOUS);
2119
2120 $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . ' WHERE group_id = ' . get_group_id('administrators');
2121 $result = $db->sql_query($sql);
2122
2123 $user_ids = array();
2124 while ($row = $db->sql_fetchrow($result))
2125 {
2126 $user_ids[] = $row['user_id'];
2127 }
2128 $db->sql_freeresult($result);
2129
2130 if (count($user_ids))
2131 {
2132 $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('administrators') . '
2133 WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids));
2134 }
2135
2136 $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . ' WHERE group_id = ' . get_group_id('global_moderators');
2137 $result = $db->sql_query($sql);
2138
2139 $user_ids = array();
2140 while ($row = $db->sql_fetchrow($result))
2141 {
2142 $user_ids[] = $row['user_id'];
2143 }
2144 $db->sql_freeresult($result);
2145
2146 if (count($user_ids))
2147 {
2148 $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('global_moderators') . '
2149 WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids));
2150 }
2151
2152 // Set user colour
2153 $sql = 'SELECT group_id, group_colour FROM ' . GROUPS_TABLE . "
2154 WHERE group_colour <> ''";
2155 $result = $db->sql_query($sql);
2156
2157 while ($row = $db->sql_fetchrow($result))
2158 {
2159 $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_colour = '{$row['group_colour']}' WHERE group_id = {$row['group_id']}");
2160 }
2161 $db->sql_freeresult($result);
2162 }
2163
2164 /**
2165 * Cleanly remove invalid user entries after converting the users table...
2166 */
2167 function remove_invalid_users()
2168 {
2169 global $db, $phpEx, $phpbb_root_path;
2170
2171 // username_clean is UNIQUE
2172 $sql = 'SELECT user_id
2173 FROM ' . USERS_TABLE . "
2174 WHERE username_clean = ''";
2175 $result = $db->sql_query($sql);
2176 $row = $db->sql_fetchrow($result);
2177 $db->sql_freeresult($result);
2178
2179 if ($row)
2180 {
2181 if (!function_exists('user_delete'))
2182 {
2183 include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
2184 }
2185
2186 user_delete('remove', $row['user_id']);
2187 }
2188 }
2189
2190 function convert_bbcode($message, $convert_size = true, $extended_bbcodes = false)
2191 {
2192 static $orig, $repl, $origx, $replx, $str_from, $str_to;
2193
2194 if (empty($orig))
2195 {
2196 $orig = $repl = array();
2197
2198 $orig[] = '#\[(php|sql)\](.*?)\[/(php|sql)\]#is';
2199 $repl[] = '[code]\2[/code]';
2200
2201 $orig[] = '#\[font=[^\]]+\](.*?)\[/font\]#is';
2202 $repl[] = '\1';
2203
2204 $orig[] = '#\[align=[a-z]+\](.*?)\[/align\]#is';
2205 $repl[] = '\1';
2206
2207 $orig[] = '#\[/list=.*?\]#is';
2208 $repl[] = '[/list]';
2209
2210 $origx = array(
2211 '#\[glow[^\]]+\](.*?)\[/glow\]#is',
2212 '#\[shadow[^\]]+\](.*?)\[/shadow\]#is',
2213 '#\[flash[^\]]+\](.*?)\[/flash\]#is'
2214 );
2215
2216 $replx = array(
2217 '\1',
2218 '\1',
2219 '[url=\1]Flash[/url]'
2220 );
2221
2222 $str_from = array(
2223 '[ftp]', '[/ftp]',
2224 '[ftp=', '[/ftp]',
2225 '[pre]', '[/pre]',
2226 '[table]', '[/table]',
2227 '[td]', '[/td]',
2228 '[tr]', '[/tr]',
2229 '[s]', '[/s]',
2230 '[left]', '[/left]',
2231 '[right]', '[/right]',
2232 '[center]', '[/center]',
2233 '[sub]', '[/sub]',
2234 '[sup]', '[/sup]',
2235 '[tt]', '[/tt]',
2236 '[move]', '[/move]',
2237 '[hr]'
2238 );
2239
2240 $str_to = array(
2241 '[url]', '[/url]',
2242 '[url=', '[/url]',
2243 '[code]', '[/code]',
2244 "\n", '',
2245 '', '',
2246 "\n", '',
2247 '', '',
2248 '', '',
2249 '', '',
2250 '', '',
2251 '', '',
2252 '', '',
2253 '', '',
2254 '', '',
2255 "\n\n"
2256 );
2257
2258 for ($i = 0, $end = count($str_from); $i < $end; ++$i)
2259 {
2260 $origx[] = '#\\' . str_replace(']', '\\]', $str_from[$i]) . '#is';
2261 $replx[] = $str_to[$i];
2262 }
2263 }
2264
2265 if (preg_match_all('#\[email=([^\]]+)\](.*?)\[/email\]#i', $message, $m))
2266 {
2267 for ($i = 0, $end = count($m[1]); $i < $end; ++$i)
2268 {
2269 if ($m[1][$i] == $m[2][$i])
2270 {
2271 $message = str_replace($m[0][$i], '[email]' . $m[1][$i] . '[/email]', $message);
2272 }
2273 else
2274 {
2275 $message = str_replace($m[0][$i], $m[2][$i] . ' ([email]' . $m[1][$i] . '[/email])', $message);
2276 }
2277 }
2278 }
2279
2280 if ($convert_size && preg_match('#\[size=[0-9]+\].*?\[/size\]#i', $message))
2281 {
2282 $size = array(9, 9, 12, 15, 18, 24, 29, 29, 29, 29);
2283 $message = preg_replace('#\[size=([0-9]+)\](.*?)\[/size\]#i', '[size=\1]\2[/size]', $message);
2284 $message = preg_replace('#\[size=[0-9]{2,}\](.*?)\[/size\]#i', '[size=29]\1[/size]', $message);
2285
2286 for ($i = count($size); $i;)
2287 {
2288 $i--;
2289 $message = str_replace('[size=' . $i . ']', '[size=' . $size[$i] . ']', $message);
2290 }
2291 }
2292
2293 if ($extended_bbcodes)
2294 {
2295 $message = preg_replace($origx, $replx, $message);
2296 }
2297
2298 $message = preg_replace($orig, $repl, $message);
2299 return $message;
2300 }
2301
2302
2303 function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $source_relative_path = true)
2304 {
2305 global $convert, $phpbb_root_path, $user, $phpbb_filesystem;
2306
2307 /** @var \phpbb\filesystem\filesystem_interface $filesystem */
2308 $filesystem = $phpbb_filesystem;
2309
2310 if (substr($trg, -1) == '/')
2311 {
2312 $trg .= utf8_basename($src);
2313 }
2314 $src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__);
2315 $trg_path = $trg;
2316
2317 if (!$overwrite && @file_exists($trg_path))
2318 {
2319 return true;
2320 }
2321
2322 if (!@file_exists($src_path))
2323 {
2324 return;
2325 }
2326
2327 $path = $phpbb_root_path;
2328 $parts = explode('/', $trg);
2329 unset($parts[count($parts) - 1]);
2330
2331 for ($i = 0, $end = count($parts); $i < $end; ++$i)
2332 {
2333 $path .= $parts[$i] . '/';
2334
2335 if (!is_dir($path))
2336 {
2337 @mkdir($path, 0777);
2338 }
2339 }
2340
2341 if (!$filesystem->is_writable($path))
2342 {
2343 @chmod($path, 0777);
2344 }
2345
2346 if (!@copy($src_path, $phpbb_root_path . $trg_path))
2347 {
2348 $convert->p_master->error(sprintf($user->lang['COULD_NOT_COPY'], $src_path, $phpbb_root_path . $trg_path), __LINE__, __FILE__, !$die_on_failure);
2349 return;
2350 }
2351
2352 if ($perm = @fileperms($src_path))
2353 {
2354 @chmod($phpbb_root_path . $trg_path, $perm);
2355 }
2356
2357 return true;
2358 }
2359
2360 function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_failure = true, $source_relative_path = true)
2361 {
2362 global $convert, $phpbb_root_path, $config, $user, $phpbb_filesystem;
2363
2364 /** @var \phpbb\filesystem\filesystem_interface $filesystem */
2365 $filesystem = $phpbb_filesystem;
2366
2367 $dirlist = $filelist = $bad_dirs = array();
2368 $src = path($src, $source_relative_path);
2369 $trg = path($trg);
2370 $src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__);
2371 $trg_path = $phpbb_root_path . $trg;
2372
2373 if (!is_dir($trg_path))
2374 {
2375 @mkdir($trg_path, 0777);
2376 @chmod($trg_path, 0777);
2377 }
2378
2379 if (!$filesystem->is_writable($trg_path))
2380 {
2381 $bad_dirs[] = path($config['script_path']) . $trg;
2382 }
2383
2384 if ($handle = @opendir($src_path))
2385 {
2386 while ($entry = readdir($handle))
2387 {
2388 if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
2389 {
2390 continue;
2391 }
2392
2393 if (is_dir($src_path . $entry))
2394 {
2395 $dirlist[] = $entry;
2396 }
2397 else
2398 {
2399 $filelist[] = $entry;
2400 }
2401 }
2402 closedir($handle);
2403 }
2404 else if ($dir = @dir($src_path))
2405 {
2406 while ($entry = $dir->read())
2407 {
2408 if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
2409 {
2410 continue;
2411 }
2412
2413 if (is_dir($src_path . $entry))
2414 {
2415 $dirlist[] = $entry;
2416 }
2417 else
2418 {
2419 $filelist[] = $entry;
2420 }
2421 }
2422 $dir->close();
2423 }
2424 else
2425 {
2426 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_COULD_NOT_READ'], relative_base($src, $source_relative_path)), __LINE__, __FILE__);
2427 }
2428
2429 if ($copy_subdirs)
2430 {
2431 for ($i = 0, $end = count($dirlist); $i < $end; ++$i)
2432 {
2433 $dir = $dirlist[$i];
2434
2435 if ($dir == 'CVS')
2436 {
2437 continue;
2438 }
2439
2440 if (!is_dir($trg_path . $dir))
2441 {
2442 @mkdir($trg_path . $dir, 0777);
2443 @chmod($trg_path . $dir, 0777);
2444 }
2445
2446 if (!$filesystem->is_writable($trg_path . $dir))
2447 {
2448 $bad_dirs[] = $trg . $dir;
2449 $bad_dirs[] = $trg_path . $dir;
2450 }
2451
2452 if (!count($bad_dirs))
2453 {
2454 copy_dir($src . $dir, $trg . $dir, true, $overwrite, $die_on_failure, $source_relative_path);
2455 }
2456 }
2457 }
2458
2459 if (count($bad_dirs))
2460 {
2461 $str = (count($bad_dirs) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE'];
2462 sort($bad_dirs);
2463 $convert->p_master->error(sprintf($str, implode('<br />', $bad_dirs)), __LINE__, __FILE__);
2464 }
2465
2466 for ($i = 0, $end = count($filelist); $i < $end; ++$i)
2467 {
2468 copy_file($src . $filelist[$i], $trg . $filelist[$i], $overwrite, $die_on_failure, $source_relative_path);
2469 }
2470 }
2471
2472 function relative_base($path, $is_relative = true, $line = false, $file = false)
2473 {
2474 global $convert, $user;
2475
2476 if (!$is_relative)
2477 {
2478 return $path;
2479 }
2480
2481 if (empty($convert->options['forum_path']) && $is_relative)
2482 {
2483 $line = $line ? $line : __LINE__;
2484 $file = $file ? $file : __FILE__;
2485
2486 $convert->p_master->error($user->lang['CONV_ERROR_NO_FORUM_PATH'], $line, $file);
2487 }
2488
2489 return $convert->options['forum_path'] . '/' . $path;
2490 }
2491
2492 function get_smiley_display()
2493 {
2494 static $smiley_count = 0;
2495 $smiley_count++;
2496 return ($smiley_count < 50) ? 1 : 0;
2497 }
2498
2499
2500 function fill_dateformat($user_dateformat)
2501 {
2502 global $config;
2503
2504 return ((empty($user_dateformat)) ? $config['default_dateformat'] : $user_dateformat);
2505 }
2506