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