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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

functions_convert.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 61.57 KiB


 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