Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

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