Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

So funktioniert es


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

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

functions_convert.php

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


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