Verzeichnisstruktur phpBB-3.1.0
- Veröffentlicht
- 27.10.2014
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, $phpbb_root_path, $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; $i < sizeof($dirlist); ++$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, $phpbb_root_path, $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, $phpbb_root_path, $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, $phpbb_root_path, $config, $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, $phpbb_root_path, $config, $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, $phpbb_root_path, $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 $result = _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, $phpbb_root_path, $config, $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 $orig_source = $source;
0862
0863 if (substr($source, 0, 7) == 'upload:')
0864 {
0865 $source = substr($source, 7);
0866 }
0867
0868 global $convert, $phpbb_root_path, $config, $user;
0869
0870 if (!isset($convert->convertor['avatar_path']))
0871 {
0872 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_AVATAR_PATH'], 'get_upload_avatar_dim()'), __LINE__, __FILE__);
0873 }
0874
0875 if (!empty($convert->convertor['avatar_path']) && strpos($source, $convert->convertor['avatar_path']) !== 0)
0876 {
0877 $source = path($convert->convertor['avatar_path'], empty($convert->convertor['source_path_absolute'])) . $source;
0878 }
0879
0880 $cachedims = get_image_dim($source);
0881
0882 if (empty($cachedims) || empty($cachedims[0]) || empty($cachedims[1]))
0883 {
0884 $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
0885 $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
0886
0887 $cachedims = array($default_x, $default_y);
0888 }
0889
0890 return $cachedims[$axis];
0891 }
0892
0893 /**
0894 * Obtain the size of the specified gallery avatar (using the cache if possible) and cache the value
0895 */
0896 function get_gallery_avatar_dim($source, $axis)
0897 {
0898 if (empty($source))
0899 {
0900 return 0;
0901 }
0902
0903 static $avatar_cache = array();
0904
0905 if (isset($avatar_cache[$source]))
0906 {
0907 return $avatar_cache[$source][$axis];
0908 }
0909
0910 global $convert, $phpbb_root_path, $config, $user;
0911
0912 $orig_source = $source;
0913
0914 if (!isset($convert->convertor['avatar_gallery_path']))
0915 {
0916 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GALLERY_PATH'], 'get_gallery_avatar_dim()'), __LINE__, __FILE__);
0917 }
0918
0919 if (!empty($convert->convertor['avatar_gallery_path']) && strpos($source, $convert->convertor['avatar_gallery_path']) !== 0)
0920 {
0921 $source = path($convert->convertor['avatar_gallery_path'], empty($convert->convertor['source_path_absolute'])) . $source;
0922 }
0923
0924 $avatar_cache[$orig_source] = get_image_dim($source);
0925
0926 if (empty($avatar_cache[$orig_source]) || empty($avatar_cache[$orig_source][0]) || empty($avatar_cache[$orig_source][1]))
0927 {
0928 $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
0929 $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
0930
0931 $avatar_cache[$orig_source] = array($default_x, $default_y);
0932 }
0933
0934 return $avatar_cache[$orig_source][$axis];
0935 }
0936
0937 /**
0938 * Obtain the size of the specified remote avatar (using the cache if possible) and cache the value
0939 * Whilst it's unlikely that remote avatars will be duplicated, it is possible so caching seems the best option
0940 * This should only be called from a post processing step due to the possibility of network timeouts
0941 */
0942 function get_remote_avatar_dim($src, $axis)
0943 {
0944 if (empty($src))
0945 {
0946 return 0;
0947 }
0948
0949 static $remote_avatar_cache = array();
0950
0951 // an ugly hack: we assume that the dimensions of each remote avatar are accessed exactly twice (x and y)
0952 if (isset($remote_avatar_cache[$src]))
0953 {
0954 $retval = $remote_avatar_cache[$src][$axis];
0955 unset($remote_avatar_cache);
0956 return $retval;
0957 }
0958
0959 $url_info = @parse_url($src);
0960 if (empty($url_info['host']))
0961 {
0962 return 0;
0963 }
0964 $host = $url_info['host'];
0965 $port = (isset($url_info['port'])) ? $url_info['port'] : 0;
0966 $protocol = (isset($url_info['scheme'])) ? $url_info['scheme'] : 'http';
0967 if (empty($port))
0968 {
0969 switch(strtolower($protocol))
0970 {
0971 case 'ftp':
0972 $port = 21;
0973 break;
0974
0975 case 'https':
0976 $port = 443;
0977 break;
0978
0979 default:
0980 $port = 80;
0981 }
0982 }
0983
0984 $timeout = @ini_get('default_socket_timeout');
0985 @ini_set('default_socket_timeout', 2);
0986
0987 // We're just trying to reach the server to avoid timeouts
0988 $fp = @fsockopen($host, $port, $errno, $errstr, 1);
0989 if ($fp)
0990 {
0991 $remote_avatar_cache[$src] = @getimagesize($src);
0992 fclose($fp);
0993 }
0994
0995 $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
0996 $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
0997 $default = array($default_x, $default_y);
0998
0999 if (empty($remote_avatar_cache[$src]) || empty($remote_avatar_cache[$src][0]) || empty($remote_avatar_cache[$src][1]))
1000 {
1001 $remote_avatar_cache[$src] = $default;
1002 }
1003 else
1004 {
1005 // We trust gallery and uploaded avatars to conform to the size settings; we might have to adjust here
1006 if ($remote_avatar_cache[$src][0] > $default_x || $remote_avatar_cache[$src][1] > $default_y)
1007 {
1008 $bigger = ($remote_avatar_cache[$src][0] > $remote_avatar_cache[$src][1]) ? 0 : 1;
1009 $ratio = $default[$bigger] / $remote_avatar_cache[$src][$bigger];
1010 $remote_avatar_cache[$src][0] = (int) ($remote_avatar_cache[$src][0] * $ratio);
1011 $remote_avatar_cache[$src][1] = (int) ($remote_avatar_cache[$src][1] * $ratio);
1012 }
1013 }
1014
1015 @ini_set('default_socket_timeout', $timeout);
1016 return $remote_avatar_cache[$src][$axis];
1017 }
1018
1019 function set_user_options()
1020 {
1021 global $convert_row;
1022
1023 // Key need to be set in row, else default value is chosen
1024 $keyoptions = array(
1025 'viewimg' => array('bit' => 0, 'default' => 1),
1026 'viewflash' => array('bit' => 1, 'default' => 1),
1027 'viewsmilies' => array('bit' => 2, 'default' => 1),
1028 'viewsigs' => array('bit' => 3, 'default' => 1),
1029 'viewavatars' => array('bit' => 4, 'default' => 1),
1030 'viewcensors' => array('bit' => 5, 'default' => 1),
1031 'attachsig' => array('bit' => 6, 'default' => 0),
1032 'bbcode' => array('bit' => 8, 'default' => 1),
1033 'smilies' => array('bit' => 9, 'default' => 1),
1034 'sig_bbcode' => array('bit' => 15, 'default' => 1),
1035 'sig_smilies' => array('bit' => 16, 'default' => 1),
1036 'sig_links' => array('bit' => 17, 'default' => 1),
1037 );
1038
1039 $option_field = 0;
1040
1041 foreach ($keyoptions as $key => $key_ary)
1042 {
1043 $value = (isset($convert_row[$key])) ? (int) $convert_row[$key] : $key_ary['default'];
1044
1045 if ($value && !($option_field & 1 << $key_ary['bit']))
1046 {
1047 $option_field += 1 << $key_ary['bit'];
1048 }
1049 }
1050
1051 return $option_field;
1052 }
1053
1054 /**
1055 * Index messages on the fly as we convert them
1056 * @todo naderman, can you check that this works with the new search plugins as it's use is currently disabled (and thus untested)
1057 function search_indexing($message = '')
1058 {
1059 global $fulltext_search, $convert_row;
1060
1061 if (!isset($convert_row['post_id']))
1062 {
1063 return;
1064 }
1065
1066 if (!$message)
1067 {
1068 if (!isset($convert_row['message']))
1069 {
1070 return;
1071 }
1072
1073 $message = $convert_row['message'];
1074 }
1075
1076 $title = (isset($convert_row['title'])) ? $convert_row['title'] : '';
1077
1078 $fulltext_search->index('post', $convert_row['post_id'], $message, $title, $convert_row['poster_id'], $convert_row['forum_id']);
1079 }
1080 */
1081
1082 function make_unique_filename($filename)
1083 {
1084 if (!strlen($filename))
1085 {
1086 $filename = md5(unique_id()) . '.dat';
1087 }
1088 else if ($filename[0] == '.')
1089 {
1090 $filename = md5(unique_id()) . $filename;
1091 }
1092 else if (preg_match('/\.([a-z]+)$/i', $filename, $m))
1093 {
1094 $filename = preg_replace('/\.([a-z]+)$/i', '_' . md5(unique_id()) . '.\1', $filename);
1095 }
1096 else
1097 {
1098 $filename .= '_' . md5(unique_id()) . '.dat';
1099 }
1100
1101 return $filename;
1102 }
1103
1104 function words_unique(&$words)
1105 {
1106 reset($words);
1107 $return_array = array();
1108
1109 $word = current($words);
1110 do
1111 {
1112 $return_array[$word] = $word;
1113 }
1114 while ($word = next($words));
1115
1116 return $return_array;
1117 }
1118
1119 /**
1120 * Adds a user to the specified group and optionally makes them a group leader
1121 * This function does not create the group if it does not exist and so should only be called after the groups have been created
1122 */
1123 function add_user_group($group_id, $user_id, $group_leader = false)
1124 {
1125 global $convert, $phpbb_root_path, $config, $user, $db;
1126
1127 $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1128 'group_id' => $group_id,
1129 'user_id' => $user_id,
1130 'group_leader' => ($group_leader) ? 1 : 0,
1131 'user_pending' => 0));
1132 $db->sql_query($sql);
1133 }
1134
1135 // STANDALONE FUNCTIONS
1136
1137 /**
1138 * Add users to the pre-defined "special" groups
1139 *
1140 * @param string $group The name of the special group to add to
1141 * @param string $select_query An SQL query to retrieve the user(s) to add to the group
1142 */
1143 function user_group_auth($group, $select_query, $use_src_db)
1144 {
1145 global $convert, $phpbb_root_path, $config, $user, $db, $src_db, $same_db;
1146
1147 if (!in_array($group, array('guests', 'registered', 'registered_coppa', 'global_moderators', 'administrators', 'bots')))
1148 {
1149 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_WRONG_GROUP'], $group, 'user_group_auth()'), __LINE__, __FILE__, true);
1150 return;
1151 }
1152
1153 $sql = 'SELECT group_id
1154 FROM ' . GROUPS_TABLE . "
1155 WHERE group_name = '" . $db->sql_escape(strtoupper($group)) . "'";
1156 $result = $db->sql_query($sql);
1157 $group_id = (int) $db->sql_fetchfield('group_id');
1158 $db->sql_freeresult($result);
1159
1160 if (!$group_id)
1161 {
1162 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GROUP'], $group, 'user_group_auth()'), __LINE__, __FILE__, true);
1163 return;
1164 }
1165
1166 if ($same_db || !$use_src_db)
1167 {
1168 $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' (user_id, group_id, user_pending)
1169 ' . str_replace('{' . strtoupper($group) . '}', $group_id . ', 0', $select_query);
1170 $db->sql_query($sql);
1171 }
1172 else
1173 {
1174 $result = $src_db->sql_query(str_replace('{' . strtoupper($group) . '}', $group_id . ' ', $select_query));
1175 while ($row = $src_db->sql_fetchrow($result))
1176 {
1177 // this might become quite a lot of INSERTS unfortunately
1178 $sql = 'INSERT INTO ' . USER_GROUP_TABLE . " (user_id, group_id, user_pending)
1179 VALUES ({$row['user_id']}, $group_id, 0)";
1180 $db->sql_query($sql);
1181 }
1182 $src_db->sql_freeresult($result);
1183 }
1184 }
1185
1186 /**
1187 * Retrieves configuration information from the source forum and caches it as an array
1188 * Both database and file driven configuration formats can be handled
1189 * (the type used is specified in $config_schema, see convert_phpbb20.php for more details)
1190 */
1191 function get_config()
1192 {
1193 static $convert_config;
1194 global $user;
1195
1196 if (isset($convert_config))
1197 {
1198 return $convert_config;
1199 }
1200
1201 global $src_db, $same_db, $phpbb_root_path, $config;
1202 global $convert;
1203
1204 if ($convert->config_schema['table_format'] != 'file')
1205 {
1206 if ($convert->mysql_convert && $same_db)
1207 {
1208 $src_db->sql_query("SET NAMES 'binary'");
1209 }
1210
1211 $sql = 'SELECT * FROM ' . $convert->src_table_prefix . $convert->config_schema['table_name'];
1212 $result = $src_db->sql_query($sql);
1213 $row = $src_db->sql_fetchrow($result);
1214
1215 if (!$row)
1216 {
1217 $convert->p_master->error($user->lang['CONV_ERROR_GET_CONFIG'], __LINE__, __FILE__);
1218 }
1219 }
1220
1221 if (is_array($convert->config_schema['table_format']))
1222 {
1223 $convert_config = array();
1224 list($key, $val) = each($convert->config_schema['table_format']);
1225
1226 do
1227 {
1228 $convert_config[$row[$key]] = $row[$val];
1229 }
1230 while ($row = $src_db->sql_fetchrow($result));
1231 $src_db->sql_freeresult($result);
1232
1233 if ($convert->mysql_convert && $same_db)
1234 {
1235 $src_db->sql_query("SET NAMES 'utf8'");
1236 }
1237 }
1238 else if ($convert->config_schema['table_format'] == 'file')
1239 {
1240 $filename = $convert->options['forum_path'] . '/' . $convert->config_schema['filename'];
1241 if (!file_exists($filename))
1242 {
1243 $convert->p_master->error($user->lang('FILE_NOT_FOUND', $filename), __LINE__, __FILE__);
1244 }
1245
1246 if (isset($convert->config_schema['array_name']))
1247 {
1248 unset($convert->config_schema['array_name']);
1249 }
1250
1251 $convert_config = extract_variables_from_file($filename);
1252 if (!empty($convert->config_schema['array_name']))
1253 {
1254 $convert_config = $convert_config[$convert->config_schema['array_name']];
1255 }
1256 }
1257 else
1258 {
1259 $convert_config = $row;
1260 if ($convert->mysql_convert && $same_db)
1261 {
1262 $src_db->sql_query("SET NAMES 'utf8'");
1263 }
1264 }
1265
1266 if (!sizeof($convert_config))
1267 {
1268 $convert->p_master->error($user->lang['CONV_ERROR_CONFIG_EMPTY'], __LINE__, __FILE__);
1269 }
1270
1271 return $convert_config;
1272 }
1273
1274 /**
1275 * Transfers the relevant configuration information from the source forum
1276 * The mapping of fields is specified in $config_schema, see convert_phpbb20.php for more details
1277 */
1278 function restore_config($schema)
1279 {
1280 global $db, $config;
1281
1282 $convert_config = get_config();
1283
1284 foreach ($schema['settings'] as $config_name => $src)
1285 {
1286 if (preg_match('/(.*)\((.*)\)/', $src, $m))
1287 {
1288 $var = (empty($m[2]) || empty($convert_config[$m[2]])) ? "''" : "'" . addslashes($convert_config[$m[2]]) . "'";
1289 $exec = '$config_value = ' . $m[1] . '(' . $var . ');';
1290 // @codingStandardsIgnoreStart
1291 eval($exec);
1292 // @codingStandardsIgnoreEnd
1293 }
1294 else
1295 {
1296 if ($schema['table_format'] != 'file' || empty($schema['array_name']))
1297 {
1298 $config_value = (isset($convert_config[$src])) ? $convert_config[$src] : '';
1299 }
1300 else if (!empty($schema['array_name']))
1301 {
1302 $src_ary = $schema['array_name'];
1303 $config_value = (isset($convert_config[$src_ary][$src])) ? $convert_config[$src_ary][$src] : '';
1304 }
1305 }
1306
1307 if ($config_value !== '')
1308 {
1309 // Most are...
1310 if (is_string($config_value))
1311 {
1312 $config_value = truncate_string(utf8_htmlspecialchars($config_value), 255, 255, false);
1313 }
1314
1315 set_config($config_name, $config_value);
1316 }
1317 }
1318 }
1319
1320 /**
1321 * Update the count of PM's in custom folders for all users
1322 */
1323 function update_folder_pm_count()
1324 {
1325 global $db, $convert, $user;
1326
1327 $sql = 'SELECT user_id, folder_id, COUNT(msg_id) as num_messages
1328 FROM ' . PRIVMSGS_TO_TABLE . '
1329 WHERE folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ', ' . PRIVMSGS_INBOX . ', ' . PRIVMSGS_OUTBOX . ', ' . PRIVMSGS_SENTBOX . ')
1330 GROUP BY folder_id, user_id';
1331 $result = $db->sql_query($sql);
1332
1333 while ($row = $db->sql_fetchrow($result))
1334 {
1335 $db->sql_query('UPDATE ' . PRIVMSGS_FOLDER_TABLE . ' SET pm_count = ' . $row['num_messages'] . '
1336 WHERE user_id = ' . $row['user_id'] . ' AND folder_id = ' . $row['folder_id']);
1337 }
1338 $db->sql_freeresult($result);
1339 }
1340
1341 // Functions mainly used by the main convertor script
1342
1343 function path($path, $path_relative = true)
1344 {
1345 if ($path === false)
1346 {
1347 return '';
1348 }
1349
1350 if (substr($path, -1) != '/')
1351 {
1352 $path .= '/';
1353 }
1354
1355 if (!$path_relative)
1356 {
1357 return $path;
1358 }
1359
1360 if (substr($path, 0, 1) == '/')
1361 {
1362 $path = substr($path, 1);
1363 }
1364
1365 return $path;
1366 }
1367
1368 /**
1369 * Extract the variables defined in a configuration file
1370 * @todo As noted by Xore we need to look at this from a security perspective
1371 */
1372 function extract_variables_from_file($_filename)
1373 {
1374 include($_filename);
1375
1376 $vars = get_defined_vars();
1377 unset($vars['_filename']);
1378
1379 return $vars;
1380 }
1381
1382 function get_path($src_path, $src_url, $test_file)
1383 {
1384 global $config, $phpbb_root_path, $phpEx;
1385
1386 $board_config = get_config();
1387
1388 $test_file = preg_replace('/\.php$/i', ".$phpEx", $test_file);
1389 $src_path = path($src_path);
1390
1391 if (@file_exists($phpbb_root_path . $src_path . $test_file))
1392 {
1393 return $src_path;
1394 }
1395
1396 if (!empty($src_url) && !empty($board_config['server_name']))
1397 {
1398 if (!preg_match('#https?://([^/]+)(.*)#i', $src_url, $m))
1399 {
1400 return false;
1401 }
1402
1403 if ($m[1] != $board_config['server_name'])
1404 {
1405 return false;
1406 }
1407
1408 $url_parts = explode('/', $m[2]);
1409 if (substr($src_url, -1) != '/')
1410 {
1411 if (preg_match('/.*\.([a-z0-9]{3,4})$/i', $url_parts[sizeof($url_parts) - 1]))
1412 {
1413 $url_parts[sizeof($url_parts) - 1] = '';
1414 }
1415 else
1416 {
1417 $url_parts[] = '';
1418 }
1419 }
1420
1421 $script_path = $board_config['script_path'];
1422 if (substr($script_path, -1) == '/')
1423 {
1424 $script_path = substr($script_path, 0, -1);
1425 }
1426
1427 $path_array = array();
1428
1429 $phpbb_parts = explode('/', $script_path);
1430 for ($i = 0; $i < sizeof($url_parts); ++$i)
1431 {
1432 if ($i < sizeof($phpbb_parts[$i]) && $url_parts[$i] == $phpbb_parts[$i])
1433 {
1434 $path_array[] = $url_parts[$i];
1435 unset($url_parts[$i]);
1436 }
1437 else
1438 {
1439 $path = '';
1440 for ($j = $i; $j < sizeof($phpbb_parts); ++$j)
1441 {
1442 $path .= '../';
1443 }
1444 $path .= implode('/', $url_parts);
1445 break;
1446 }
1447 }
1448
1449 if (!empty($path))
1450 {
1451 if (@file_exists($phpbb_root_path . $path . $test_file))
1452 {
1453 return $path;
1454 }
1455 }
1456 }
1457
1458 return false;
1459 }
1460
1461 function compare_table($tables, $tablename, &$prefixes)
1462 {
1463 for ($i = 0, $table_size = sizeof($tables); $i < $table_size; ++$i)
1464 {
1465 if (preg_match('/(.*)' . $tables[$i] . '$/', $tablename, $m))
1466 {
1467 if (empty($m[1]))
1468 {
1469 $m[1] = '*';
1470 }
1471
1472 if (isset($prefixes[$m[1]]))
1473 {
1474 $prefixes[$m[1]]++;
1475 }
1476 else
1477 {
1478 $prefixes[$m[1]] = 1;
1479 }
1480 }
1481 }
1482 }
1483
1484 /**
1485 * Grant permissions to a specified user or group
1486 *
1487 * @param string $ug_type user|group|user_role|group_role
1488 * @param mixed $forum_id forum ids (array|int|0) -> 0 == all forums
1489 * @param mixed $ug_id [int] user_id|group_id : [string] usergroup name
1490 * @param mixed $acl_list [string] acl entry : [array] acl entries : [string] role entry
1491 * @param int $setting ACL_YES|ACL_NO|ACL_NEVER
1492 */
1493 function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO)
1494 {
1495 global $db, $convert, $user, $config;
1496 static $acl_option_ids, $group_ids;
1497
1498 if (($ug_type == 'group' || $ug_type == 'group_role') && is_string($ug_id))
1499 {
1500 if (!isset($group_ids[$ug_id]))
1501 {
1502 $sql = 'SELECT group_id
1503 FROM ' . GROUPS_TABLE . "
1504 WHERE group_name = '" . $db->sql_escape(strtoupper($ug_id)) . "'";
1505 $result = $db->sql_query_limit($sql, 1);
1506 $id = (int) $db->sql_fetchfield('group_id');
1507 $db->sql_freeresult($result);
1508
1509 if (!$id)
1510 {
1511 return;
1512 }
1513
1514 $group_ids[$ug_id] = $id;
1515 }
1516
1517 $ug_id = (int) $group_ids[$ug_id];
1518 }
1519
1520 $table = ($ug_type == 'user' || $ug_type == 'user_role') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE;
1521 $id_field = ($ug_type == 'user' || $ug_type == 'user_role') ? 'user_id' : 'group_id';
1522
1523 // Role based permissions are the simplest to handle so check for them first
1524 if ($ug_type == 'user_role' || $ug_type == 'group_role')
1525 {
1526 if (is_numeric($forum_id))
1527 {
1528 $sql = 'SELECT role_id
1529 FROM ' . ACL_ROLES_TABLE . "
1530 WHERE role_name = 'ROLE_" . $db->sql_escape($acl_list) . "'";
1531 $result = $db->sql_query_limit($sql, 1);
1532 $row = $db->sql_fetchrow($result);
1533 $db->sql_freeresult($result);
1534
1535 // If we have no role id there is something wrong here
1536 if ($row)
1537 {
1538 $sql = "INSERT INTO $table ($id_field, forum_id, auth_role_id) VALUES ($ug_id, $forum_id, " . $row['role_id'] . ')';
1539 $db->sql_query($sql);
1540 }
1541 }
1542
1543 return;
1544 }
1545
1546 // Build correct parameters
1547 $auth = array();
1548
1549 if (!is_array($acl_list))
1550 {
1551 $auth = array($acl_list => $setting);
1552 }
1553 else
1554 {
1555 foreach ($acl_list as $auth_option)
1556 {
1557 $auth[$auth_option] = $setting;
1558 }
1559 }
1560 unset($acl_list);
1561
1562 if (!is_array($forum_id))
1563 {
1564 $forum_id = array($forum_id);
1565 }
1566
1567 // Set any flags as required
1568 foreach ($auth as $auth_option => $acl_setting)
1569 {
1570 $flag = substr($auth_option, 0, strpos($auth_option, '_') + 1);
1571 if (empty($auth[$flag]))
1572 {
1573 $auth[$flag] = $acl_setting;
1574 }
1575 }
1576
1577 if (!is_array($acl_option_ids) || empty($acl_option_ids))
1578 {
1579 $sql = 'SELECT auth_option_id, auth_option
1580 FROM ' . ACL_OPTIONS_TABLE;
1581 $result = $db->sql_query($sql);
1582
1583 while ($row = $db->sql_fetchrow($result))
1584 {
1585 $acl_option_ids[$row['auth_option']] = $row['auth_option_id'];
1586 }
1587 $db->sql_freeresult($result);
1588 }
1589
1590 $sql_forum = 'AND ' . $db->sql_in_set('a.forum_id', array_map('intval', $forum_id), false, true);
1591
1592 $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";
1593 $result = $db->sql_query($sql);
1594
1595 $cur_auth = array();
1596 while ($row = $db->sql_fetchrow($result))
1597 {
1598 $cur_auth[$row['forum_id']][$row['auth_option_id']] = $row['auth_setting'];
1599 }
1600 $db->sql_freeresult($result);
1601
1602 $sql_ary = array();
1603 foreach ($forum_id as $forum)
1604 {
1605 foreach ($auth as $auth_option => $setting)
1606 {
1607 $auth_option_id = $acl_option_ids[$auth_option];
1608
1609 if (!$auth_option_id)
1610 {
1611 continue;
1612 }
1613
1614 switch ($setting)
1615 {
1616 case ACL_NO:
1617 if (isset($cur_auth[$forum][$auth_option_id]))
1618 {
1619 $sql_ary['delete'][] = "DELETE FROM $table
1620 WHERE forum_id = $forum
1621 AND auth_option_id = $auth_option_id
1622 AND $id_field = $ug_id";
1623 }
1624 break;
1625
1626 default:
1627 if (!isset($cur_auth[$forum][$auth_option_id]))
1628 {
1629 $sql_ary['insert'][] = "$ug_id, $forum, $auth_option_id, $setting";
1630 }
1631 else if ($cur_auth[$forum][$auth_option_id] != $setting)
1632 {
1633 $sql_ary['update'][] = "UPDATE " . $table . "
1634 SET auth_setting = $setting
1635 WHERE $id_field = $ug_id
1636 AND forum_id = $forum
1637 AND auth_option_id = $auth_option_id";
1638 }
1639 }
1640 }
1641 }
1642 unset($cur_auth);
1643
1644 $sql = '';
1645 foreach ($sql_ary as $sql_type => $sql_subary)
1646 {
1647 switch ($sql_type)
1648 {
1649 case 'insert':
1650 switch ($db->get_sql_layer())
1651 {
1652 case 'mysql':
1653 case 'mysql4':
1654 $sql = 'VALUES ' . implode(', ', preg_replace('#^(.*?)$#', '(\1)', $sql_subary));
1655 break;
1656
1657 case 'mssql':
1658 case 'sqlite':
1659 case 'sqlite3':
1660 case 'mssqlnative':
1661 $sql = implode(' UNION ALL ', preg_replace('#^(.*?)$#', 'SELECT \1', $sql_subary));
1662 break;
1663
1664 default:
1665 foreach ($sql_subary as $sql)
1666 {
1667 $sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) VALUES ($sql)";
1668 $db->sql_query($sql);
1669 $sql = '';
1670 }
1671 }
1672
1673 if ($sql != '')
1674 {
1675 $sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) $sql";
1676 $db->sql_query($sql);
1677 }
1678 break;
1679
1680 case 'update':
1681 case 'delete':
1682 foreach ($sql_subary as $sql)
1683 {
1684 $db->sql_query($sql);
1685 $sql = '';
1686 }
1687 break;
1688 }
1689 unset($sql_ary[$sql_type]);
1690 }
1691 unset($sql_ary);
1692
1693 }
1694
1695 /**
1696 * Update the count of unread private messages for all users
1697 */
1698 function update_unread_count()
1699 {
1700 global $db;
1701
1702 $sql = 'SELECT user_id, COUNT(msg_id) as num_messages
1703 FROM ' . PRIVMSGS_TO_TABLE . '
1704 WHERE pm_unread = 1
1705 AND folder_id <> ' . PRIVMSGS_OUTBOX . '
1706 GROUP BY user_id';
1707 $result = $db->sql_query($sql);
1708
1709 while ($row = $db->sql_fetchrow($result))
1710 {
1711 $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_unread_privmsg = ' . $row['num_messages'] . '
1712 WHERE user_id = ' . $row['user_id']);
1713 }
1714 $db->sql_freeresult($result);
1715 }
1716
1717 /**
1718 * Add any of the pre-defined "special" groups which are missing from the database
1719 */
1720 function add_default_groups()
1721 {
1722 global $db;
1723
1724 $default_groups = array(
1725 'GUESTS' => array('', 0, 0),
1726 'REGISTERED' => array('', 0, 0),
1727 'REGISTERED_COPPA' => array('', 0, 0),
1728 'GLOBAL_MODERATORS' => array('00AA00', 2, 0),
1729 'ADMINISTRATORS' => array('AA0000', 1, 1),
1730 'BOTS' => array('9E8DA7', 0, 0),
1731 'NEWLY_REGISTERED' => array('', 0, 0),
1732 );
1733
1734 $sql = 'SELECT *
1735 FROM ' . GROUPS_TABLE . '
1736 WHERE ' . $db->sql_in_set('group_name', array_keys($default_groups));
1737 $result = $db->sql_query($sql);
1738
1739 while ($row = $db->sql_fetchrow($result))
1740 {
1741 unset($default_groups[strtoupper($row['group_name'])]);
1742 }
1743 $db->sql_freeresult($result);
1744
1745 $sql_ary = array();
1746
1747 foreach ($default_groups as $name => $data)
1748 {
1749 $sql_ary[] = array(
1750 'group_name' => (string) $name,
1751 'group_desc' => '',
1752 'group_desc_uid' => '',
1753 'group_desc_bitfield' => '',
1754 'group_type' => GROUP_SPECIAL,
1755 'group_colour' => (string) $data[0],
1756 'group_legend' => (int) $data[1],
1757 'group_founder_manage' => (int) $data[2],
1758 );
1759 }
1760
1761 if (sizeof($sql_ary))
1762 {
1763 $db->sql_multi_insert(GROUPS_TABLE, $sql_ary);
1764 }
1765 }
1766
1767 function add_groups_to_teampage()
1768 {
1769 global $db;
1770
1771 $teampage_groups = array(
1772 'ADMINISTRATORS' => 1,
1773 'GLOBAL_MODERATORS' => 2,
1774 );
1775
1776 $sql = 'SELECT *
1777 FROM ' . GROUPS_TABLE . '
1778 WHERE ' . $db->sql_in_set('group_name', array_keys($teampage_groups));
1779 $result = $db->sql_query($sql);
1780
1781 $teampage_ary = array();
1782 while ($row = $db->sql_fetchrow($result))
1783 {
1784 $teampage_ary[] = array(
1785 'group_id' => (int) $row['group_id'],
1786 'teampage_name' => '',
1787 'teampage_position' => (int) $teampage_groups[$row['group_name']],
1788 'teampage_parent' => 0,
1789 );
1790 }
1791 $db->sql_freeresult($result);
1792
1793 if (sizeof($teampage_ary))
1794 {
1795 $db->sql_multi_insert(TEAMPAGE_TABLE, $teampage_ary);
1796 }
1797 }
1798
1799
1800 /**
1801 * Sync post count. We might need to do this in batches.
1802 */
1803 function sync_post_count($offset, $limit)
1804 {
1805 global $db;
1806 $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id
1807 FROM ' . POSTS_TABLE . '
1808 WHERE post_postcount = 1
1809 AND post_visibility = ' . ITEM_APPROVED . '
1810 GROUP BY poster_id
1811 ORDER BY poster_id';
1812 $result = $db->sql_query_limit($sql, $limit, $offset);
1813
1814 while ($row = $db->sql_fetchrow($result))
1815 {
1816 $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['poster_id']}");
1817 }
1818 $db->sql_freeresult($result);
1819 }
1820
1821 /**
1822 * Add the search bots into the database
1823 * This code should be used in execute_last if the source database did not have bots
1824 * If you are converting bots this function should not be called
1825 * @todo We might want to look at sharing the bot list between the install code and this code for consistancy
1826 */
1827 function add_bots()
1828 {
1829 global $db, $convert, $user, $config, $phpbb_root_path, $phpEx;
1830
1831 $db->sql_query($convert->truncate_statement . BOTS_TABLE);
1832
1833 $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name = 'BOTS'";
1834 $result = $db->sql_query($sql);
1835 $group_id = (int) $db->sql_fetchfield('group_id', false, $result);
1836 $db->sql_freeresult($result);
1837
1838 if (!$group_id)
1839 {
1840 add_default_groups();
1841
1842 $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name = 'BOTS'";
1843 $result = $db->sql_query($sql);
1844 $group_id = (int) $db->sql_fetchfield('group_id', false, $result);
1845 $db->sql_freeresult($result);
1846
1847 if (!$group_id)
1848 {
1849 global $install;
1850 $install->error($user->lang['CONV_ERROR_INCONSISTENT_GROUPS'], __LINE__, __FILE__);
1851 }
1852 }
1853
1854 $bots = array(
1855 'AdsBot [Google]' => array('AdsBot-Google', ''),
1856 'Alexa [Bot]' => array('ia_archiver', ''),
1857 'Alta Vista [Bot]' => array('Scooter/', ''),
1858 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''),
1859 'Baidu [Spider]' => array('Baiduspider+(', ''),
1860 'Bing [Bot]' => array('bingbot/', ''),
1861 'Exabot [Bot]' => array('Exabot/', ''),
1862 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''),
1863 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''),
1864 'Francis [Bot]' => array('http://www.neomo.de/', ''),
1865 'Gigabot [Bot]' => array('Gigabot/', ''),
1866 'Google Adsense [Bot]' => array('Mediapartners-Google', ''),
1867 'Google Desktop' => array('Google Desktop', ''),
1868 'Google Feedfetcher' => array('Feedfetcher-Google', ''),
1869 'Google [Bot]' => array('Googlebot', ''),
1870 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''),
1871 'Heritrix [Crawler]' => array('heritrix/1.', ''),
1872 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''),
1873 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''),
1874 'ichiro [Crawler]' => array('ichiro/2', ''),
1875 'Majestic-12 [Bot]' => array('MJ12bot/', ''),
1876 'Metager [Bot]' => array('MetagerBot/', ''),
1877 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''),
1878 'MSN [Bot]' => array('msnbot/', ''),
1879 'MSNbot Media' => array('msnbot-media/', ''),
1880 'NG-Search [Bot]' => array('NG-Search/', ''),
1881 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''),
1882 'Nutch/CVS [Bot]' => array('NutchCVS/', ''),
1883 'OmniExplorer [Bot]' => array('OmniExplorer_Bot/', ''),
1884 'Online link [Validator]' => array('online link validator', ''),
1885 'psbot [Picsearch]' => array('psbot/0', ''),
1886 'Seekport [Bot]' => array('Seekbot/', ''),
1887 'Sensis [Crawler]' => array('Sensis Web Crawler', ''),
1888 'SEO Crawler' => array('SEO search Crawler/', ''),
1889 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''),
1890 'SEOSearch [Crawler]' => array('SEOsearch/', ''),
1891 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''),
1892 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''),
1893 'Synoo [Bot]' => array('SynooBot/', ''),
1894 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''),
1895 'TurnitinBot [Bot]' => array('TurnitinBot/', ''),
1896 'Voyager [Bot]' => array('voyager/1.0', ''),
1897 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''),
1898 'W3C [Linkcheck]' => array('W3C-checklink/', ''),
1899 'W3C [Validator]' => array('W3C_*Validator', ''),
1900 'WiseNut [Bot]' => array('http://www.WISEnutbot.com', ''),
1901 'YaCy [Bot]' => array('yacybot', ''),
1902 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''),
1903 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''),
1904 'Yahoo [Bot]' => array('Yahoo! Slurp', ''),
1905 'YahooSeeker [Bot]' => array('YahooSeeker/', ''),
1906 );
1907
1908 if (!function_exists('user_add'))
1909 {
1910 include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
1911 }
1912
1913 foreach ($bots as $bot_name => $bot_ary)
1914 {
1915 $user_row = array(
1916 'user_type' => USER_IGNORE,
1917 'group_id' => $group_id,
1918 'username' => $bot_name,
1919 'user_regdate' => time(),
1920 'user_password' => '',
1921 'user_colour' => '9E8DA7',
1922 'user_email' => '',
1923 'user_lang' => $config['default_lang'],
1924 'user_style' => 1,
1925 'user_timezone' => 'UTC',
1926 'user_allow_massemail' => 0,
1927 );
1928
1929 $user_id = user_add($user_row);
1930
1931 if ($user_id)
1932 {
1933 $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1934 'bot_active' => 1,
1935 'bot_name' => $bot_name,
1936 'user_id' => $user_id,
1937 'bot_agent' => $bot_ary[0],
1938 'bot_ip' => $bot_ary[1])
1939 );
1940 $db->sql_query($sql);
1941 }
1942 }
1943 }
1944
1945 /**
1946 * Update any dynamic configuration variables after the conversion is finished
1947 * @todo Confirm that this updates all relevant values since it has not necessarily been kept in sync with all changes
1948 */
1949 function update_dynamic_config()
1950 {
1951 global $db, $config;
1952
1953 // Get latest username
1954 $sql = 'SELECT user_id, username, user_colour
1955 FROM ' . USERS_TABLE . '
1956 WHERE user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
1957
1958 if (!empty($config['increment_user_id']))
1959 {
1960 $sql .= ' AND user_id <> ' . $config['increment_user_id'];
1961 }
1962
1963 $sql .= ' ORDER BY user_id DESC';
1964
1965 $result = $db->sql_query_limit($sql, 1);
1966 $row = $db->sql_fetchrow($result);
1967 $db->sql_freeresult($result);
1968
1969 if ($row)
1970 {
1971 set_config('newest_user_id', $row['user_id'], true);
1972 set_config('newest_username', $row['username'], true);
1973 set_config('newest_user_colour', $row['user_colour'], true);
1974 }
1975
1976 // Also do not reset record online user/date. There will be old data or the fresh data from the schema.
1977 // set_config('record_online_users', 1, true);
1978 // set_config('record_online_date', time(), true);
1979
1980 $sql = 'SELECT COUNT(post_id) AS stat
1981 FROM ' . POSTS_TABLE . '
1982 WHERE post_visibility = ' . ITEM_APPROVED;
1983 $result = $db->sql_query($sql);
1984 $row = $db->sql_fetchrow($result);
1985 $db->sql_freeresult($result);
1986
1987 set_config('num_posts', (int) $row['stat'], true);
1988
1989 $sql = 'SELECT COUNT(topic_id) AS stat
1990 FROM ' . TOPICS_TABLE . '
1991 WHERE topic_visibility = ' . ITEM_APPROVED;
1992 $result = $db->sql_query($sql);
1993 $row = $db->sql_fetchrow($result);
1994 $db->sql_freeresult($result);
1995
1996 set_config('num_topics', (int) $row['stat'], true);
1997
1998 $sql = 'SELECT COUNT(user_id) AS stat
1999 FROM ' . USERS_TABLE . '
2000 WHERE user_type IN (' . USER_NORMAL . ',' . USER_FOUNDER . ')';
2001 $result = $db->sql_query($sql);
2002 $row = $db->sql_fetchrow($result);
2003 $db->sql_freeresult($result);
2004
2005 set_config('num_users', (int) $row['stat'], true);
2006
2007 $sql = 'SELECT COUNT(attach_id) as stat
2008 FROM ' . ATTACHMENTS_TABLE . '
2009 WHERE is_orphan = 0';
2010 $result = $db->sql_query($sql);
2011 set_config('num_files', (int) $db->sql_fetchfield('stat'), true);
2012 $db->sql_freeresult($result);
2013
2014 $sql = 'SELECT SUM(filesize) as stat
2015 FROM ' . ATTACHMENTS_TABLE . '
2016 WHERE is_orphan = 0';
2017 $result = $db->sql_query($sql);
2018 set_config('upload_dir_size', (float) $db->sql_fetchfield('stat'), true);
2019 $db->sql_freeresult($result);
2020
2021 /**
2022 * We do not resync users post counts - this can be done by the admin after conversion if wanted.
2023 $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id
2024 FROM ' . POSTS_TABLE . '
2025 WHERE post_postcount = 1
2026 GROUP BY poster_id';
2027 $result = $db->sql_query($sql);
2028
2029 while ($row = $db->sql_fetchrow($result))
2030 {
2031 $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['poster_id']}");
2032 }
2033 $db->sql_freeresult($result);
2034 */
2035 }
2036
2037 /**
2038 * Updates topics_posted entries
2039 */
2040 function update_topics_posted()
2041 {
2042 global $db, $config;
2043
2044 switch ($db->get_sql_layer())
2045 {
2046 case 'sqlite':
2047 case 'sqlite3':
2048 $db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE);
2049 break;
2050
2051 default:
2052 $db->sql_query('TRUNCATE TABLE ' . TOPICS_POSTED_TABLE);
2053 break;
2054 }
2055
2056 // This can get really nasty... therefore we only do the last six months
2057 $get_from_time = time() - (6 * 4 * 7 * 24 * 60 * 60);
2058
2059 // Select forum ids, do not include categories
2060 $sql = 'SELECT forum_id
2061 FROM ' . FORUMS_TABLE . '
2062 WHERE forum_type <> ' . FORUM_CAT;
2063 $result = $db->sql_query($sql);
2064
2065 $forum_ids = array();
2066 while ($row = $db->sql_fetchrow($result))
2067 {
2068 $forum_ids[] = $row['forum_id'];
2069 }
2070 $db->sql_freeresult($result);
2071
2072 // Any global announcements? ;)
2073 $forum_ids[] = 0;
2074
2075 // Now go through the forums and get us some topics...
2076 foreach ($forum_ids as $forum_id)
2077 {
2078 $sql = 'SELECT p.poster_id, p.topic_id
2079 FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t
2080 WHERE t.forum_id = ' . $forum_id . '
2081 AND t.topic_moved_id = 0
2082 AND t.topic_last_post_time > ' . $get_from_time . '
2083 AND t.topic_id = p.topic_id
2084 AND p.poster_id <> ' . ANONYMOUS . '
2085 GROUP BY p.poster_id, p.topic_id';
2086 $result = $db->sql_query($sql);
2087
2088 $posted = array();
2089 while ($row = $db->sql_fetchrow($result))
2090 {
2091 $posted[$row['poster_id']][] = $row['topic_id'];
2092 }
2093 $db->sql_freeresult($result);
2094
2095 $sql_ary = array();
2096 foreach ($posted as $user_id => $topic_row)
2097 {
2098 foreach ($topic_row as $topic_id)
2099 {
2100 $sql_ary[] = array(
2101 'user_id' => (int) $user_id,
2102 'topic_id' => (int) $topic_id,
2103 'topic_posted' => 1,
2104 );
2105 }
2106 }
2107 unset($posted);
2108
2109 if (sizeof($sql_ary))
2110 {
2111 $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary);
2112 }
2113 }
2114 }
2115
2116 /**
2117 * Ensure that all users have a default group specified and update related information such as their colour
2118 */
2119 function fix_empty_primary_groups()
2120 {
2121 global $db;
2122
2123 // Set group ids for users not already having it
2124 $sql = 'UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('registered') . '
2125 WHERE group_id = 0 AND user_type = ' . USER_INACTIVE;
2126 $db->sql_query($sql);
2127
2128 $sql = 'UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('registered') . '
2129 WHERE group_id = 0 AND user_type = ' . USER_NORMAL;
2130 $db->sql_query($sql);
2131
2132 $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('guests') . ' WHERE user_id = ' . ANONYMOUS);
2133
2134 $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . ' WHERE group_id = ' . get_group_id('administrators');
2135 $result = $db->sql_query($sql);
2136
2137 $user_ids = array();
2138 while ($row = $db->sql_fetchrow($result))
2139 {
2140 $user_ids[] = $row['user_id'];
2141 }
2142 $db->sql_freeresult($result);
2143
2144 if (sizeof($user_ids))
2145 {
2146 $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('administrators') . '
2147 WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids));
2148 }
2149
2150 $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . ' WHERE group_id = ' . get_group_id('global_moderators');
2151
2152 $user_ids = array();
2153 while ($row = $db->sql_fetchrow($result))
2154 {
2155 $user_ids[] = $row['user_id'];
2156 }
2157 $db->sql_freeresult($result);
2158
2159 if (sizeof($user_ids))
2160 {
2161 $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('global_moderators') . '
2162 WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids));
2163 }
2164
2165 // Set user colour
2166 $sql = 'SELECT group_id, group_colour FROM ' . GROUPS_TABLE . "
2167 WHERE group_colour <> ''";
2168 $result = $db->sql_query($sql);
2169
2170 while ($row = $db->sql_fetchrow($result))
2171 {
2172 $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_colour = '{$row['group_colour']}' WHERE group_id = {$row['group_id']}");
2173 }
2174 $db->sql_freeresult($result);
2175 }
2176
2177 /**
2178 * Cleanly remove invalid user entries after converting the users table...
2179 */
2180 function remove_invalid_users()
2181 {
2182 global $convert, $db, $phpEx, $phpbb_root_path;
2183
2184 // username_clean is UNIQUE
2185 $sql = 'SELECT user_id
2186 FROM ' . USERS_TABLE . "
2187 WHERE username_clean = ''";
2188 $result = $db->sql_query($sql);
2189 $row = $db->sql_fetchrow($result);
2190 $db->sql_freeresult($result);
2191
2192 if ($row)
2193 {
2194 if (!function_exists('user_delete'))
2195 {
2196 include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
2197 }
2198
2199 user_delete('remove', $row['user_id']);
2200 }
2201 }
2202
2203 function convert_bbcode($message, $convert_size = true, $extended_bbcodes = false)
2204 {
2205 static $orig, $repl, $origx, $replx, $str_from, $str_to;
2206
2207 if (empty($orig))
2208 {
2209 $orig = $repl = array();
2210
2211 $orig[] = '#\[(php|sql)\](.*?)\[/(php|sql)\]#is';
2212 $repl[] = '[code]\2[/code]';
2213
2214 $orig[] = '#\[font=[^\]]+\](.*?)\[/font\]#is';
2215 $repl[] = '\1';
2216
2217 $orig[] = '#\[align=[a-z]+\](.*?)\[/align\]#is';
2218 $repl[] = '\1';
2219
2220 $orig[] = '#\[/list=.*?\]#is';
2221 $repl[] = '[/list]';
2222
2223 $origx = array(
2224 '#\[glow[^\]]+\](.*?)\[/glow\]#is',
2225 '#\[shadow[^\]]+\](.*?)\[/shadow\]#is',
2226 '#\[flash[^\]]+\](.*?)\[/flash\]#is'
2227 );
2228
2229 $replx = array(
2230 '\1',
2231 '\1',
2232 '[url=\1]Flash[/url]'
2233 );
2234
2235 $str_from = array(
2236 '[ftp]', '[/ftp]',
2237 '[ftp=', '[/ftp]',
2238 '[pre]', '[/pre]',
2239 '[table]', '[/table]',
2240 '[td]', '[/td]',
2241 '[tr]', '[/tr]',
2242 '[s]', '[/s]',
2243 '[left]', '[/left]',
2244 '[right]', '[/right]',
2245 '[center]', '[/center]',
2246 '[sub]', '[/sub]',
2247 '[sup]', '[/sup]',
2248 '[tt]', '[/tt]',
2249 '[move]', '[/move]',
2250 '[hr]'
2251 );
2252
2253 $str_to = array(
2254 '[url]', '[/url]',
2255 '[url=', '[/url]',
2256 '[code]', '[/code]',
2257 "\n", '',
2258 '', '',
2259 "\n", '',
2260 '', '',
2261 '', '',
2262 '', '',
2263 '', '',
2264 '', '',
2265 '', '',
2266 '', '',
2267 '', '',
2268 "\n\n"
2269 );
2270
2271 for ($i = 0; $i < sizeof($str_from); ++$i)
2272 {
2273 $origx[] = '#\\' . str_replace(']', '\\]', $str_from[$i]) . '#is';
2274 $replx[] = $str_to[$i];
2275 }
2276 }
2277
2278 if (preg_match_all('#\[email=([^\]]+)\](.*?)\[/email\]#i', $message, $m))
2279 {
2280 for ($i = 0; $i < sizeof($m[1]); ++$i)
2281 {
2282 if ($m[1][$i] == $m[2][$i])
2283 {
2284 $message = str_replace($m[0][$i], '[email]' . $m[1][$i] . '[/email]', $message);
2285 }
2286 else
2287 {
2288 $message = str_replace($m[0][$i], $m[2][$i] . ' ([email]' . $m[1][$i] . '[/email])', $message);
2289 }
2290 }
2291 }
2292
2293 if ($convert_size && preg_match('#\[size=[0-9]+\].*?\[/size\]#i', $message))
2294 {
2295 $size = array(9, 9, 12, 15, 18, 24, 29, 29, 29, 29);
2296 $message = preg_replace('#\[size=([0-9]+)\](.*?)\[/size\]#i', '[size=\1]\2[/size]', $message);
2297 $message = preg_replace('#\[size=[0-9]{2,}\](.*?)\[/size\]#i', '[size=29]\1[/size]', $message);
2298
2299 for ($i = sizeof($size); $i;)
2300 {
2301 $i--;
2302 $message = str_replace('[size=' . $i . ']', '[size=' . $size[$i] . ']', $message);
2303 }
2304 }
2305
2306 if ($extended_bbcodes)
2307 {
2308 $message = preg_replace($origx, $replx, $message);
2309 }
2310
2311 $message = preg_replace($orig, $repl, $message);
2312 return $message;
2313 }
2314
2315
2316 function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $source_relative_path = true)
2317 {
2318 global $convert, $phpbb_root_path, $config, $user, $db;
2319
2320 if (substr($trg, -1) == '/')
2321 {
2322 $trg .= utf8_basename($src);
2323 }
2324 $src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__);
2325 $trg_path = $trg;
2326
2327 if (!$overwrite && @file_exists($trg_path))
2328 {
2329 return true;
2330 }
2331
2332 if (!@file_exists($src_path))
2333 {
2334 return;
2335 }
2336
2337 $path = $phpbb_root_path;
2338 $parts = explode('/', $trg);
2339 unset($parts[sizeof($parts) - 1]);
2340
2341 for ($i = 0; $i < sizeof($parts); ++$i)
2342 {
2343 $path .= $parts[$i] . '/';
2344
2345 if (!is_dir($path))
2346 {
2347 @mkdir($path, 0777);
2348 }
2349 }
2350
2351 if (!phpbb_is_writable($path))
2352 {
2353 @chmod($path, 0777);
2354 }
2355
2356 if (!@copy($src_path, $phpbb_root_path . $trg_path))
2357 {
2358 $convert->p_master->error(sprintf($user->lang['COULD_NOT_COPY'], $src_path, $phpbb_root_path . $trg_path), __LINE__, __FILE__, !$die_on_failure);
2359 return;
2360 }
2361
2362 if ($perm = @fileperms($src_path))
2363 {
2364 @chmod($phpbb_root_path . $trg_path, $perm);
2365 }
2366
2367 return true;
2368 }
2369
2370 function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_failure = true, $source_relative_path = true)
2371 {
2372 global $convert, $phpbb_root_path, $config, $user, $db;
2373
2374 $dirlist = $filelist = $bad_dirs = array();
2375 $src = path($src, $source_relative_path);
2376 $trg = path($trg);
2377 $src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__);
2378 $trg_path = $phpbb_root_path . $trg;
2379
2380 if (!is_dir($trg_path))
2381 {
2382 @mkdir($trg_path, 0777);
2383 @chmod($trg_path, 0777);
2384 }
2385
2386 if (!phpbb_is_writable($trg_path))
2387 {
2388 $bad_dirs[] = path($config['script_path']) . $trg;
2389 }
2390
2391 if ($handle = @opendir($src_path))
2392 {
2393 while ($entry = readdir($handle))
2394 {
2395 if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
2396 {
2397 continue;
2398 }
2399
2400 if (is_dir($src_path . $entry))
2401 {
2402 $dirlist[] = $entry;
2403 }
2404 else
2405 {
2406 $filelist[] = $entry;
2407 }
2408 }
2409 closedir($handle);
2410 }
2411 else if ($dir = @dir($src_path))
2412 {
2413 while ($entry = $dir->read())
2414 {
2415 if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
2416 {
2417 continue;
2418 }
2419
2420 if (is_dir($src_path . $entry))
2421 {
2422 $dirlist[] = $entry;
2423 }
2424 else
2425 {
2426 $filelist[] = $entry;
2427 }
2428 }
2429 $dir->close();
2430 }
2431 else
2432 {
2433 $convert->p_master->error(sprintf($user->lang['CONV_ERROR_COULD_NOT_READ'], relative_base($src, $source_relative_path)), __LINE__, __FILE__);
2434 }
2435
2436 if ($copy_subdirs)
2437 {
2438 for ($i = 0; $i < sizeof($dirlist); ++$i)
2439 {
2440 $dir = $dirlist[$i];
2441
2442 if ($dir == 'CVS')
2443 {
2444 continue;
2445 }
2446
2447 if (!is_dir($trg_path . $dir))
2448 {
2449 @mkdir($trg_path . $dir, 0777);
2450 @chmod($trg_path . $dir, 0777);
2451 }
2452
2453 if (!phpbb_is_writable($trg_path . $dir))
2454 {
2455 $bad_dirs[] = $trg . $dir;
2456 $bad_dirs[] = $trg_path . $dir;
2457 }
2458
2459 if (!sizeof($bad_dirs))
2460 {
2461 copy_dir($src . $dir, $trg . $dir, true, $overwrite, $die_on_failure, $source_relative_path);
2462 }
2463 }
2464 }
2465
2466 if (sizeof($bad_dirs))
2467 {
2468 $str = (sizeof($bad_dirs) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE'];
2469 sort($bad_dirs);
2470 $convert->p_master->error(sprintf($str, implode('<br />', $bad_dirs)), __LINE__, __FILE__);
2471 }
2472
2473 for ($i = 0; $i < sizeof($filelist); ++$i)
2474 {
2475 copy_file($src . $filelist[$i], $trg . $filelist[$i], $overwrite, $die_on_failure, $source_relative_path);
2476 }
2477 }
2478
2479 function relative_base($path, $is_relative = true, $line = false, $file = false)
2480 {
2481 global $convert, $phpbb_root_path, $config, $user, $db;
2482
2483 if (!$is_relative)
2484 {
2485 return $path;
2486 }
2487
2488 if (empty($convert->options['forum_path']) && $is_relative)
2489 {
2490 $line = $line ? $line : __LINE__;
2491 $file = $file ? $file : __FILE__;
2492
2493 $convert->p_master->error($user->lang['CONV_ERROR_NO_FORUM_PATH'], $line, $file);
2494 }
2495
2496 return $convert->options['forum_path'] . '/' . $path;
2497 }
2498
2499 function get_smiley_display()
2500 {
2501 static $smiley_count = 0;
2502 $smiley_count++;
2503 return ($smiley_count < 50) ? 1 : 0;
2504 }
2505
2506
2507 function fill_dateformat($user_dateformat)
2508 {
2509 global $config;
2510
2511 return ((empty($user_dateformat)) ? $config['default_dateformat'] : $user_dateformat);
2512 }
2513