Verzeichnisstruktur phpBB-3.0.0


Veröffentlicht
12.12.2007

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:50 - Dateigröße: 59.75 KiB


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