[ Index ]

PHP Cross Reference of phpBB-3.3.0-deutsch

title

Body

[close]

/includes/ -> functions_convert.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  /**
  15  * @ignore
  16  */
  17  if (!defined('IN_PHPBB'))
  18  {
  19      exit;
  20  }
  21  
  22  /**
  23  * Default avatar width/height
  24  * @ignore
  25  */
  26  define('DEFAULT_AVATAR_X', 80);
  27  define('DEFAULT_AVATAR_Y', 80);
  28  
  29  // Global functions - all functions can be used by convertors
  30  
  31  // SIMPLE FUNCTIONS
  32  
  33  /**
  34  * Return the preceding value
  35  */
  36  function dec($var)
  37  {
  38      return --$var;
  39  }
  40  
  41  /**
  42  * Return the next value
  43  */
  44  function inc($var)
  45  {
  46      return ++$var;
  47  }
  48  
  49  /**
  50  * Return whether the value is positive
  51  */
  52  function is_positive($n)
  53  {
  54      return ($n > 0) ? 1 : 0;
  55  }
  56  
  57  /**
  58  * Boolean inverse of the value
  59  */
  60  function not($var)
  61  {
  62      return ($var) ? 0 : 1;
  63  }
  64  
  65  /**
  66  * Convert a textual value to it's equivalent boolean value
  67  *
  68  * @param string $str String to convert (converts yes, on, y, 1 and true to boolean true)
  69  * @return boolean The equivalent value
  70  */
  71  function str_to_bool($str)
  72  {
  73      $str = strtolower($str);
  74      return ($str == 'yes' || $str == 'on' || $str == 'y' || $str == 'true' || $str == '1') ? true : false;
  75  }
  76  
  77  /**
  78  * Function to mimic php's empty() function (it is the same)
  79  */
  80  function is_empty($mixed)
  81  {
  82      return empty($mixed);
  83  }
  84  
  85  /**
  86  * Convert the name of a user's primary group to the appropriate equivalent phpBB group id
  87  *
  88  * @param string $status The name of the group
  89  * @return int The group_id corresponding to the equivalent group
  90  */
  91  function str_to_primary_group($status)
  92  {
  93      switch (ucfirst(strtolower($status)))
  94      {
  95          case 'Administrator':
  96              return get_group_id('administrators');
  97          break;
  98  
  99          case 'Super moderator':
 100          case 'Global moderator':
 101          case 'Moderator':
 102              return get_group_id('global_moderators');
 103          break;
 104  
 105          case 'Guest':
 106          case 'Anonymous':
 107              return get_group_id('guests');
 108          break;
 109  
 110          default:
 111              return get_group_id('registered');
 112          break;
 113      }
 114  }
 115  
 116  /**
 117  * Convert a boolean into the appropriate phpBB constant indicating whether the item is locked
 118  */
 119  function is_item_locked($bool)
 120  {
 121      return ($bool) ? ITEM_LOCKED : ITEM_UNLOCKED;
 122  }
 123  
 124  /**
 125  * Convert a value from days to seconds
 126  */
 127  function days_to_seconds($days)
 128  {
 129      return ($days * 86400);
 130  }
 131  
 132  /**
 133  * Determine whether a user is anonymous and return the appropriate new user_id
 134  */
 135  function is_user_anonymous($user_id)
 136  {
 137      return ($user_id > ANONYMOUS) ? $user_id : ANONYMOUS;
 138  }
 139  
 140  /**
 141  * Generate a key value based on existing values
 142  *
 143  * @param int $pad Amount to add to the maximum value
 144  * @return int Key value
 145  */
 146  function auto_id($pad = 0)
 147  {
 148      global $auto_id, $convert_row;
 149  
 150      if (!empty($convert_row['max_id']))
 151      {
 152          return $convert_row['max_id'] + $pad;
 153      }
 154  
 155      return $auto_id + $pad;
 156  }
 157  
 158  /**
 159  * Convert a boolean into the appropriate phpBB constant indicating whether the user is active
 160  */
 161  function set_user_type($user_active)
 162  {
 163      return ($user_active) ? USER_NORMAL : USER_INACTIVE;
 164  }
 165  
 166  /**
 167  * Convert a value from minutes to hours
 168  */
 169  function minutes_to_hours($minutes)
 170  {
 171      return ($minutes / 3600);
 172  }
 173  
 174  /**
 175  * Return the group_id for a given group name
 176  */
 177  function get_group_id($group_name)
 178  {
 179      global $db, $group_mapping;
 180  
 181      if (empty($group_mapping))
 182      {
 183          $sql = 'SELECT group_name, group_id
 184              FROM ' . GROUPS_TABLE;
 185          $result = $db->sql_query($sql);
 186  
 187          $group_mapping = array();
 188          while ($row = $db->sql_fetchrow($result))
 189          {
 190              $group_mapping[strtoupper($row['group_name'])] = (int) $row['group_id'];
 191          }
 192          $db->sql_freeresult($result);
 193      }
 194  
 195      if (!count($group_mapping))
 196      {
 197          add_default_groups();
 198          return get_group_id($group_name);
 199      }
 200  
 201      if (isset($group_mapping[strtoupper($group_name)]))
 202      {
 203          return $group_mapping[strtoupper($group_name)];
 204      }
 205  
 206      return $group_mapping['REGISTERED'];
 207  }
 208  
 209  /**
 210  * Convert a boolean into the appropriate phpBB constant indicating whether the topic is locked
 211  */
 212  function is_topic_locked($bool)
 213  {
 214      return (!empty($bool)) ? ITEM_LOCKED : ITEM_UNLOCKED;
 215  }
 216  
 217  /**
 218  * Generate a bbcode_uid value
 219  */
 220  function make_uid($timestamp)
 221  {
 222      static $last_timestamp, $last_uid;
 223  
 224      if (empty($last_timestamp) || $timestamp != $last_timestamp)
 225      {
 226          $last_uid = substr(base_convert(unique_id(), 16, 36), 0, BBCODE_UID_LEN);
 227      }
 228      $last_timestamp = $timestamp;
 229      return $last_uid;
 230  }
 231  
 232  
 233  /**
 234  * Validate a website address
 235  */
 236  function validate_website($url)
 237  {
 238      if ($url === 'http://')
 239      {
 240          return '';
 241      }
 242      else if (!preg_match('#^http[s]?://#i', $url) && strlen($url) > 0)
 243      {
 244          return 'http://' . $url;
 245      }
 246      return $url;
 247  }
 248  
 249  /**
 250  * Convert nulls to zeros for fields which allowed a NULL value in the source but not the destination
 251  */
 252  function null_to_zero($value)
 253  {
 254      return ($value === NULL) ? 0 : $value;
 255  }
 256  
 257  /**
 258  * Convert nulls to empty strings for fields which allowed a NULL value in the source but not the destination
 259  */
 260  function null_to_str($value)
 261  {
 262      return ($value === NULL) ? '' : $value;
 263  }
 264  
 265  // EXTENDED FUNCTIONS
 266  
 267  /**
 268  * Get old config value
 269  */
 270  function get_config_value($config_name)
 271  {
 272      static $convert_config;
 273  
 274      if (!isset($convert_config))
 275      {
 276          $convert_config = get_config();
 277      }
 278  
 279      if (!isset($convert_config[$config_name]))
 280      {
 281          return false;
 282      }
 283  
 284      return (empty($convert_config[$config_name])) ? '' : $convert_config[$config_name];
 285  }
 286  
 287  /**
 288  * Convert an IP address from the hexadecimal notation to normal dotted-quad notation
 289  */
 290  function decode_ip($int_ip)
 291  {
 292      if (!$int_ip)
 293      {
 294          return $int_ip;
 295      }
 296  
 297      $hexipbang = explode('.', chunk_split($int_ip, 2, '.'));
 298  
 299      // 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...
 300      if (count($hexipbang) < 4)
 301      {
 302          return $int_ip;
 303      }
 304  
 305      return hexdec($hexipbang[0]) . '.' . hexdec($hexipbang[1]) . '.' . hexdec($hexipbang[2]) . '.' . hexdec($hexipbang[3]);
 306  }
 307  
 308  /**
 309  * Reverse the encoding of wild-carded bans
 310  */
 311  function decode_ban_ip($int_ip)
 312  {
 313      return str_replace('255', '*', decode_ip($int_ip));
 314  }
 315  
 316  /**
 317  * Determine the MIME-type of a specified filename
 318  * This does not actually inspect the file, but simply uses the file extension
 319  */
 320  function mimetype($filename)
 321  {
 322      if (!preg_match('/\.([a-z0-9]+)$/i', $filename, $m))
 323      {
 324          return 'application/octet-stream';
 325      }
 326  
 327      switch (strtolower($m[1]))
 328      {
 329          case 'zip':        return 'application/zip';
 330          case 'jpeg':    return 'image/jpeg';
 331          case 'jpg':        return 'image/jpeg';
 332          case 'jpe':        return 'image/jpeg';
 333          case 'png':        return 'image/png';
 334          case 'gif':        return 'image/gif';
 335          case 'htm':
 336          case 'html':    return 'text/html';
 337          case 'tif':        return 'image/tiff';
 338          case 'tiff':    return 'image/tiff';
 339          case 'ras':        return 'image/x-cmu-raster';
 340          case 'pnm':        return 'image/x-portable-anymap';
 341          case 'pbm':        return 'image/x-portable-bitmap';
 342          case 'pgm':        return 'image/x-portable-graymap';
 343          case 'ppm':        return 'image/x-portable-pixmap';
 344          case 'rgb':        return 'image/x-rgb';
 345          case 'xbm':        return 'image/x-xbitmap';
 346          case 'xpm':        return 'image/x-xpixmap';
 347          case 'xwd':        return 'image/x-xwindowdump';
 348          case 'z':        return 'application/x-compress';
 349          case 'gtar':    return 'application/x-gtar';
 350          case 'tgz':        return 'application/x-gtar';
 351          case 'gz':        return 'application/x-gzip';
 352          case 'tar':        return 'application/x-tar';
 353          case 'xls':        return 'application/excel';
 354          case 'pdf':        return 'application/pdf';
 355          case 'ppt':        return 'application/powerpoint';
 356          case 'rm':        return 'application/vnd.rn-realmedia';
 357          case 'wma':        return 'audio/x-ms-wma';
 358          case 'swf':        return 'application/x-shockwave-flash';
 359          case 'ief':        return 'image/ief';
 360          case 'doc':
 361          case 'dot':
 362          case 'wrd':        return 'application/msword';
 363          case 'ai':
 364          case 'eps':
 365          case 'ps':        return 'application/postscript';
 366          case 'asc':
 367          case 'txt':
 368          case 'c':
 369          case 'cc':
 370          case 'h':
 371          case 'hh':
 372          case 'cpp':
 373          case 'hpp':
 374          case 'php':
 375          case 'php3':    return 'text/plain';
 376          default:         return 'application/octet-stream';
 377      }
 378  }
 379  
 380  /**
 381  * Obtain the dimensions of all remotely hosted avatars
 382  * This should only be called from execute_last
 383  * There can be significant network overhead if there are a large number of remote avatars
 384  * @todo Look at the option of allowing the user to decide whether this is called or to force the dimensions
 385  */
 386  function remote_avatar_dims()
 387  {
 388      global $db;
 389  
 390      $sql = 'SELECT user_id, user_avatar
 391          FROM ' . USERS_TABLE . '
 392          WHERE user_avatar_type = ' . AVATAR_REMOTE;
 393      $result = $db->sql_query($sql);
 394  
 395      $remote_avatars = array();
 396      while ($row = $db->sql_fetchrow($result))
 397      {
 398          $remote_avatars[(int) $row['user_id']] = $row['user_avatar'];
 399      }
 400      $db->sql_freeresult($result);
 401  
 402      foreach ($remote_avatars as $user_id => $avatar)
 403      {
 404          $width = (int) get_remote_avatar_dim($avatar, 0);
 405          $height = (int) get_remote_avatar_dim($avatar, 1);
 406  
 407          $sql = 'UPDATE ' . USERS_TABLE . '
 408              SET user_avatar_width = ' . (int) $width . ', user_avatar_height = ' . (int) $height . '
 409              WHERE user_id = ' . $user_id;
 410          $db->sql_query($sql);
 411      }
 412  }
 413  
 414  function import_avatar_gallery($gallery_name = '', $subdirs_as_galleries = false)
 415  {
 416      global $config, $convert, $user;
 417  
 418      $relative_path = empty($convert->convertor['source_path_absolute']);
 419  
 420      // check for trailing slash
 421      if (rtrim($convert->convertor['avatar_gallery_path'], '/') === '')
 422      {
 423          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GALLERY_PATH'], 'import_avatar_gallery()'), __LINE__, __FILE__);
 424      }
 425  
 426      $src_path = relative_base(path($convert->convertor['avatar_gallery_path'], $relative_path), $relative_path);
 427  
 428      if (is_dir($src_path))
 429      {
 430          // Do not die on failure... safe mode restrictions may be in effect.
 431          copy_dir($convert->convertor['avatar_gallery_path'], path($config['avatar_gallery_path']) . $gallery_name, !$subdirs_as_galleries, false, false, $relative_path);
 432  
 433          // only doing 1 level deep. (ibf 1.x)
 434          // notes: ibf has 2 tiers: directly in the avatar directory for base gallery (handled in the above statement), plus subdirs(handled below).
 435          // 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.
 436          if ($subdirs_as_galleries)
 437          {
 438              $dirlist = array();
 439              if ($handle = @opendir($src_path))
 440              {
 441                  while ($entry = readdir($handle))
 442                  {
 443                      if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
 444                      {
 445                          continue;
 446                      }
 447  
 448                      if (is_dir($src_path . $entry))
 449                      {
 450                          $dirlist[] = $entry;
 451                      }
 452                  }
 453                  closedir($handle);
 454              }
 455              else if ($dir = @dir($src_path))
 456              {
 457                  while ($entry = $dir->read())
 458                  {
 459                      if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
 460                      {
 461                          continue;
 462                      }
 463  
 464                      if (is_dir($src_path . $entry))
 465                      {
 466                          $dirlist[] = $entry;
 467                      }
 468                  }
 469                  $dir->close();
 470              }
 471  
 472              for ($i = 0, $end = count($dirlist); $i < $end; ++$i)
 473              {
 474                  $dir = $dirlist[$i];
 475  
 476                  // Do not die on failure... safe mode restrictions may be in effect.
 477                  copy_dir(path($convert->convertor['avatar_gallery_path'], $relative_path) . $dir, path($config['avatar_gallery_path']) . $dir, true, false, false, $relative_path);
 478              }
 479          }
 480      }
 481  }
 482  
 483  function import_attachment_files($category_name = '')
 484  {
 485      global $config, $convert, $db, $user;
 486  
 487      $sql = 'SELECT config_value AS upload_path
 488          FROM ' . CONFIG_TABLE . "
 489          WHERE config_name = 'upload_path'";
 490      $result = $db->sql_query($sql);
 491      $config['upload_path'] = $db->sql_fetchfield('upload_path');
 492      $db->sql_freeresult($result);
 493  
 494      $relative_path = empty($convert->convertor['source_path_absolute']);
 495  
 496      if (empty($convert->convertor['upload_path']))
 497      {
 498          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_UPLOAD_DIR'], 'import_attachment_files()'), __LINE__, __FILE__);
 499      }
 500  
 501      if (is_dir(relative_base(path($convert->convertor['upload_path'], $relative_path), $relative_path)))
 502      {
 503          copy_dir($convert->convertor['upload_path'], path($config['upload_path']) . $category_name, true, false, true, $relative_path);
 504      }
 505  }
 506  
 507  function attachment_forum_perms($forum_id)
 508  {
 509      if (!is_array($forum_id))
 510      {
 511          $forum_id = array($forum_id);
 512      }
 513  
 514      return serialize($forum_id);
 515  }
 516  
 517  // base64todec function
 518  // -> from php manual?
 519  function base64_unpack($string)
 520  {
 521      $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-';
 522      $base = strlen($chars);
 523  
 524      $length = strlen($string);
 525      $number = 0;
 526  
 527      for ($i = 1; $i <= $length; $i++)
 528      {
 529          $pos = $length - $i;
 530          $operand = strpos($chars, substr($string, $pos, 1));
 531          $exponent = pow($base, $i-1);
 532          $dec_value = $operand * $exponent;
 533          $number += $dec_value;
 534      }
 535  
 536      return $number;
 537  }
 538  
 539  function _import_check($config_var, $source, $use_target)
 540  {
 541      global $convert, $config;
 542  
 543      $result = array(
 544          'orig_source'    => $source,
 545          'copied'        => false,
 546          'relative_path'    => (empty($convert->convertor['source_path_absolute'])) ? true : false,
 547      );
 548  
 549      // copy file will prepend $phpBB_root_path
 550      $target = $config[$config_var] . '/' . utf8_basename(($use_target === false) ? $source : $use_target);
 551  
 552      if (!empty($convert->convertor[$config_var]) && strpos($source, $convert->convertor[$config_var]) !== 0)
 553      {
 554          $source = $convert->convertor[$config_var] . $source;
 555      }
 556  
 557      $result['source'] = $source;
 558  
 559      if (file_exists(relative_base($source, $result['relative_path'], __LINE__, __FILE__)))
 560      {
 561          $result['copied'] = copy_file($source, $target, false, false, $result['relative_path']);
 562      }
 563  
 564      if ($result['copied'])
 565      {
 566          $result['target'] = utf8_basename($target);
 567      }
 568      else
 569      {
 570          $result['target'] = ($use_target !== false) ? $result['orig_source'] : utf8_basename($target);
 571      }
 572  
 573      return $result;
 574  }
 575  
 576  function import_attachment($source, $use_target = false)
 577  {
 578      if (empty($source))
 579      {
 580          return '';
 581      }
 582  
 583      global $convert, $config, $user;
 584  
 585      // check for trailing slash
 586      if (rtrim($convert->convertor['upload_path'], '/') === '')
 587      {
 588          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_UPLOAD_DIR'], 'import_attachment()'), __LINE__, __FILE__);
 589      }
 590  
 591      $result = _import_check('upload_path', $source, $use_target);
 592  
 593      if ($result['copied'])
 594      {
 595          // Thumbnails?
 596          if (is_array($convert->convertor['thumbnails']))
 597          {
 598              $thumb_dir = $convert->convertor['thumbnails'][0];
 599              $thumb_prefix = $convert->convertor['thumbnails'][1];
 600              $thumb_source = $thumb_dir . $thumb_prefix . utf8_basename($result['source']);
 601  
 602              if (strpos($thumb_source, $convert->convertor['upload_path']) !== 0)
 603              {
 604                  $thumb_source = $convert->convertor['upload_path'] . $thumb_source;
 605              }
 606              $thumb_target = $config['upload_path'] . '/thumb_' . $result['target'];
 607  
 608              if (file_exists(relative_base($thumb_source, $result['relative_path'], __LINE__, __FILE__)))
 609              {
 610                  copy_file($thumb_source, $thumb_target, false, false, $result['relative_path']);
 611              }
 612          }
 613      }
 614  
 615      return $result['target'];
 616  }
 617  
 618  function import_rank($source, $use_target = false)
 619  {
 620      if (empty($source))
 621      {
 622          return '';
 623      }
 624  
 625      global $convert, $user;
 626  
 627      if (!isset($convert->convertor['ranks_path']))
 628      {
 629          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_RANKS_PATH'], 'import_rank()'), __LINE__, __FILE__);
 630      }
 631  
 632      $result = _import_check('ranks_path', $source, $use_target);
 633      return $result['target'];
 634  }
 635  
 636  function import_smiley($source, $use_target = false)
 637  {
 638      if (empty($source))
 639      {
 640          return '';
 641      }
 642  
 643      global $convert, $user;
 644  
 645      // check for trailing slash
 646      if (rtrim($convert->convertor['smilies_path'], '/') === '')
 647      {
 648          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_SMILIES_PATH'], 'import_smiley()'), __LINE__, __FILE__);
 649      }
 650  
 651      $result = _import_check('smilies_path', $source, $use_target);
 652      return $result['target'];
 653  }
 654  
 655  /*
 656  */
 657  function import_avatar($source, $use_target = false, $user_id = false)
 658  {
 659      if (empty($source) || preg_match('#^https?:#i', $source) || preg_match('#blank\.(gif|png)$#i', $source))
 660      {
 661          return;
 662      }
 663  
 664      global $convert, $config, $user;
 665  
 666      // check for trailing slash
 667      if (rtrim($convert->convertor['avatar_path'], '/') === '')
 668      {
 669          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_AVATAR_PATH'], 'import_avatar()'), __LINE__, __FILE__);
 670      }
 671  
 672      if ($use_target === false && $user_id !== false)
 673      {
 674          $use_target = $config['avatar_salt'] . '_' . $user_id . '.' . substr(strrchr($source, '.'), 1);
 675      }
 676  
 677      _import_check('avatar_path', $source, $use_target);
 678  
 679      return ((!empty($user_id)) ? $user_id : $use_target) . '.' . substr(strrchr($source, '.'), 1);
 680  }
 681  
 682  /**
 683  * @todo all image dimension functions below (there are a *lot*) should get revisited and converted to one or two functions (no more needed, really).
 684  */
 685  
 686  /**
 687  * Calculate the size of the specified image
 688  * Called from the following functions for calculating the size of specific image types
 689  */
 690  function get_image_dim($source)
 691  {
 692      if (empty($source))
 693      {
 694          return array(0, 0);
 695      }
 696  
 697      global $convert;
 698  
 699      $relative_path = empty($convert->convertor['source_path_absolute']);
 700  
 701      if (file_exists(relative_base($source, $relative_path)))
 702      {
 703          $image = relative_base($source, $relative_path);
 704          return @getimagesize($image);
 705      }
 706  
 707      return false;
 708  }
 709  
 710  /**
 711  * Obtain the width of the specified smilie
 712  */
 713  function get_smiley_width($src)
 714  {
 715      return get_smiley_dim($src, 0);
 716  }
 717  
 718  /**
 719  * Obtain the height of the specified smilie
 720  */
 721  function get_smiley_height($src)
 722  {
 723      return get_smiley_dim($src, 1);
 724  }
 725  
 726  /**
 727  * Obtain the size of the specified smilie (using the cache if possible) and cache the value
 728  */
 729  function get_smiley_dim($source, $axis)
 730  {
 731      if (empty($source))
 732      {
 733          return 15;
 734      }
 735  
 736      static $smiley_cache = array();
 737  
 738      if (isset($smiley_cache[$source]))
 739      {
 740          return $smiley_cache[$source][$axis];
 741      }
 742  
 743      global $convert, $user;
 744  
 745      $orig_source = $source;
 746  
 747      if (!isset($convert->convertor['smilies_path']))
 748      {
 749          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_SMILIES_PATH'], 'get_smiley_dim()'), __LINE__, __FILE__);
 750      }
 751  
 752      if (!empty($convert->convertor['smilies_path']) && strpos($source, $convert->convertor['smilies_path']) !== 0)
 753      {
 754          $source = $convert->convertor['smilies_path'] . $source;
 755      }
 756  
 757      $smiley_cache[$orig_source] = get_image_dim($source);
 758  
 759      if (empty($smiley_cache[$orig_source]) || empty($smiley_cache[$orig_source][0]) || empty($smiley_cache[$orig_source][1]))
 760      {
 761          $smiley_cache[$orig_source] = array(15, 15);
 762          return 15;
 763      }
 764  
 765      return $smiley_cache[$orig_source][$axis];
 766  }
 767  
 768  /**
 769  * Obtain the width of the specified avatar
 770  */
 771  function get_avatar_width($src, $func = false, $arg1 = false, $arg2 = false)
 772  {
 773      return get_avatar_dim($src, 0, $func, $arg1, $arg2);
 774  }
 775  
 776  /**
 777  * Obtain the height of the specified avatar
 778  */
 779  function get_avatar_height($src, $func = false, $arg1 = false, $arg2 = false)
 780  {
 781      return get_avatar_dim($src, 1, $func, $arg1, $arg2);
 782  }
 783  
 784  /**
 785  */
 786  function get_avatar_dim($src, $axis, $func = false, $arg1 = false, $arg2 = false)
 787  {
 788      $avatar_type = AVATAR_UPLOAD;
 789  
 790      if ($func)
 791      {
 792          if ($arg1 || $arg2)
 793          {
 794              $ary = array($arg1);
 795  
 796              if ($arg2)
 797              {
 798                  $ary[] = $arg2;
 799              }
 800  
 801              $avatar_type = call_user_func_array($func, $ary);
 802          }
 803          else
 804          {
 805              $avatar_type = call_user_func($func);
 806          }
 807      }
 808  
 809      switch ($avatar_type)
 810      {
 811          case AVATAR_UPLOAD:
 812              return get_upload_avatar_dim($src, $axis);
 813          break;
 814  
 815          case AVATAR_GALLERY:
 816              return get_gallery_avatar_dim($src, $axis);
 817          break;
 818  
 819          case AVATAR_REMOTE:
 820              // see notes on this functions usage and (hopefully) model $func to avoid this accordingly
 821              return get_remote_avatar_dim($src, $axis);
 822          break;
 823  
 824          default:
 825              $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
 826              $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
 827  
 828              return $axis ? $default_y : $default_x;
 829          break;
 830      }
 831  }
 832  
 833  /**
 834  * Obtain the size of the specified uploaded avatar (using the cache if possible) and cache the value
 835  */
 836  function get_upload_avatar_dim($source, $axis)
 837  {
 838      static $cachedims = false;
 839      static $cachekey = false;
 840  
 841      if (empty($source))
 842      {
 843          return 0;
 844      }
 845  
 846      if ($cachekey == $source)
 847      {
 848          return $cachedims[$axis];
 849      }
 850  
 851      if (substr($source, 0, 7) == 'upload:')
 852      {
 853          $source = substr($source, 7);
 854      }
 855  
 856      global $convert, $user;
 857  
 858      if (!isset($convert->convertor['avatar_path']))
 859      {
 860          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_AVATAR_PATH'], 'get_upload_avatar_dim()'), __LINE__, __FILE__);
 861      }
 862  
 863      if (!empty($convert->convertor['avatar_path']) && strpos($source, $convert->convertor['avatar_path']) !== 0)
 864      {
 865          $source = path($convert->convertor['avatar_path'], empty($convert->convertor['source_path_absolute'])) . $source;
 866      }
 867  
 868      $cachedims = get_image_dim($source);
 869  
 870      if (empty($cachedims) || empty($cachedims[0]) || empty($cachedims[1]))
 871      {
 872          $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
 873          $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
 874  
 875          $cachedims = array($default_x, $default_y);
 876      }
 877  
 878      return $cachedims[$axis];
 879  }
 880  
 881  /**
 882  * Obtain the size of the specified gallery avatar (using the cache if possible) and cache the value
 883  */
 884  function get_gallery_avatar_dim($source, $axis)
 885  {
 886      if (empty($source))
 887      {
 888          return 0;
 889      }
 890  
 891      static $avatar_cache = array();
 892  
 893      if (isset($avatar_cache[$source]))
 894      {
 895          return $avatar_cache[$source][$axis];
 896      }
 897  
 898      global $convert, $user;
 899  
 900      $orig_source = $source;
 901  
 902      if (!isset($convert->convertor['avatar_gallery_path']))
 903      {
 904          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GALLERY_PATH'], 'get_gallery_avatar_dim()'), __LINE__, __FILE__);
 905      }
 906  
 907      if (!empty($convert->convertor['avatar_gallery_path']) && strpos($source, $convert->convertor['avatar_gallery_path']) !== 0)
 908      {
 909          $source = path($convert->convertor['avatar_gallery_path'], empty($convert->convertor['source_path_absolute'])) . $source;
 910      }
 911  
 912      $avatar_cache[$orig_source] = get_image_dim($source);
 913  
 914      if (empty($avatar_cache[$orig_source]) || empty($avatar_cache[$orig_source][0]) || empty($avatar_cache[$orig_source][1]))
 915      {
 916          $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
 917          $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
 918  
 919          $avatar_cache[$orig_source] = array($default_x, $default_y);
 920      }
 921  
 922      return $avatar_cache[$orig_source][$axis];
 923  }
 924  
 925  /**
 926  * Obtain the size of the specified remote avatar (using the cache if possible) and cache the value
 927  * Whilst it's unlikely that remote avatars will be duplicated, it is possible so caching seems the best option
 928  * This should only be called from a post processing step due to the possibility of network timeouts
 929  */
 930  function get_remote_avatar_dim($src, $axis)
 931  {
 932      if (empty($src))
 933      {
 934          return 0;
 935      }
 936  
 937      static $remote_avatar_cache = array();
 938  
 939      // an ugly hack: we assume that the dimensions of each remote avatar are accessed exactly twice (x and y)
 940      if (isset($remote_avatar_cache[$src]))
 941      {
 942          $retval = $remote_avatar_cache[$src][$axis];
 943          unset($remote_avatar_cache);
 944          return $retval;
 945      }
 946  
 947      $url_info = @parse_url($src);
 948      if (empty($url_info['host']))
 949      {
 950          return 0;
 951      }
 952      $host = $url_info['host'];
 953      $port = (isset($url_info['port'])) ? $url_info['port'] : 0;
 954      $protocol = (isset($url_info['scheme'])) ? $url_info['scheme'] : 'http';
 955      if (empty($port))
 956      {
 957          switch (strtolower($protocol))
 958          {
 959              case 'ftp':
 960                  $port = 21;
 961                  break;
 962  
 963              case 'https':
 964                  $port = 443;
 965                  break;
 966  
 967              default:
 968                  $port = 80;
 969          }
 970      }
 971  
 972      $timeout = @ini_get('default_socket_timeout');
 973      @ini_set('default_socket_timeout', 2);
 974  
 975      // We're just trying to reach the server to avoid timeouts
 976      $fp = @fsockopen($host, $port, $errno, $errstr, 1);
 977      if ($fp)
 978      {
 979          $remote_avatar_cache[$src] = @getimagesize($src);
 980          fclose($fp);
 981      }
 982  
 983      $default_x     = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X;
 984      $default_y     = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y;
 985      $default     = array($default_x, $default_y);
 986  
 987      if (empty($remote_avatar_cache[$src]) || empty($remote_avatar_cache[$src][0]) || empty($remote_avatar_cache[$src][1]))
 988      {
 989          $remote_avatar_cache[$src] = $default;
 990      }
 991      else
 992      {
 993          // We trust gallery and uploaded avatars to conform to the size settings; we might have to adjust here
 994          if ($remote_avatar_cache[$src][0] > $default_x || $remote_avatar_cache[$src][1] > $default_y)
 995          {
 996              $bigger = ($remote_avatar_cache[$src][0] > $remote_avatar_cache[$src][1]) ? 0 : 1;
 997              $ratio = $default[$bigger] / $remote_avatar_cache[$src][$bigger];
 998              $remote_avatar_cache[$src][0] = (int) ($remote_avatar_cache[$src][0] * $ratio);
 999              $remote_avatar_cache[$src][1] = (int) ($remote_avatar_cache[$src][1] * $ratio);
1000          }
1001      }
1002  
1003      @ini_set('default_socket_timeout', $timeout);
1004      return $remote_avatar_cache[$src][$axis];
1005  }
1006  
1007  function set_user_options()
1008  {
1009      global $convert_row;
1010  
1011      // Key need to be set in row, else default value is chosen
1012      $keyoptions = array(
1013          'viewimg'        => array('bit' => 0, 'default' => 1),
1014          'viewflash'        => array('bit' => 1, 'default' => 1),
1015          'viewsmilies'    => array('bit' => 2, 'default' => 1),
1016          'viewsigs'        => array('bit' => 3, 'default' => 1),
1017          'viewavatars'    => array('bit' => 4, 'default' => 1),
1018          'viewcensors'    => array('bit' => 5, 'default' => 1),
1019          'attachsig'        => array('bit' => 6, 'default' => 0),
1020          'bbcode'        => array('bit' => 8, 'default' => 1),
1021          'smilies'        => array('bit' => 9, 'default' => 1),
1022          'sig_bbcode'    => array('bit' => 15, 'default' => 1),
1023          'sig_smilies'    => array('bit' => 16, 'default' => 1),
1024          'sig_links'        => array('bit' => 17, 'default' => 1),
1025      );
1026  
1027      $option_field = 0;
1028  
1029      foreach ($keyoptions as $key => $key_ary)
1030      {
1031          $value = (isset($convert_row[$key])) ? (int) $convert_row[$key] : $key_ary['default'];
1032  
1033          if ($value && !($option_field & 1 << $key_ary['bit']))
1034          {
1035              $option_field += 1 << $key_ary['bit'];
1036          }
1037      }
1038  
1039      return $option_field;
1040  }
1041  
1042  /**
1043  * Index messages on the fly as we convert them
1044  * @todo naderman, can you check that this works with the new search plugins as it's use is currently disabled (and thus untested)
1045  function search_indexing($message = '')
1046  {
1047      global $fulltext_search, $convert_row;
1048  
1049      if (!isset($convert_row['post_id']))
1050      {
1051          return;
1052      }
1053  
1054      if (!$message)
1055      {
1056          if (!isset($convert_row['message']))
1057          {
1058              return;
1059          }
1060  
1061          $message = $convert_row['message'];
1062      }
1063  
1064      $title = (isset($convert_row['title'])) ? $convert_row['title'] : '';
1065  
1066      $fulltext_search->index('post', $convert_row['post_id'], $message, $title, $convert_row['poster_id'], $convert_row['forum_id']);
1067  }
1068  */
1069  
1070  function make_unique_filename($filename)
1071  {
1072      if (!strlen($filename))
1073      {
1074          $filename = md5(unique_id()) . '.dat';
1075      }
1076      else if ($filename[0] == '.')
1077      {
1078          $filename = md5(unique_id()) . $filename;
1079      }
1080      else if (preg_match('/\.([a-z]+)$/i', $filename, $m))
1081      {
1082          $filename = preg_replace('/\.([a-z]+)$/i', '_' . md5(unique_id()) . '.\1', $filename);
1083      }
1084      else
1085      {
1086          $filename .= '_' . md5(unique_id()) . '.dat';
1087      }
1088  
1089      return $filename;
1090  }
1091  
1092  function words_unique(&$words)
1093  {
1094      reset($words);
1095      $return_array = array();
1096  
1097      $word = current($words);
1098      do
1099      {
1100          $return_array[$word] = $word;
1101      }
1102      while ($word = next($words));
1103  
1104      return $return_array;
1105  }
1106  
1107  /**
1108  * Adds a user to the specified group and optionally makes them a group leader
1109  * This function does not create the group if it does not exist and so should only be called after the groups have been created
1110  */
1111  function add_user_group($group_id, $user_id, $group_leader = false)
1112  {
1113      global $db;
1114  
1115      $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1116          'group_id'        => $group_id,
1117          'user_id'        => $user_id,
1118          'group_leader'    => ($group_leader) ? 1 : 0,
1119          'user_pending'    => 0));
1120      $db->sql_query($sql);
1121  }
1122  
1123  // STANDALONE FUNCTIONS
1124  
1125  /**
1126  * Add users to the pre-defined "special" groups
1127  *
1128  * @param string $group The name of the special group to add to
1129  * @param string $select_query An SQL query to retrieve the user(s) to add to the group
1130  */
1131  function user_group_auth($group, $select_query, $use_src_db)
1132  {
1133      global $convert, $user, $db, $src_db, $same_db;
1134  
1135      if (!in_array($group, array('guests', 'registered', 'registered_coppa', 'global_moderators', 'administrators', 'bots')))
1136      {
1137          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_WRONG_GROUP'], $group, 'user_group_auth()'), __LINE__, __FILE__, true);
1138          return;
1139      }
1140  
1141      $sql = 'SELECT group_id
1142          FROM ' . GROUPS_TABLE . "
1143          WHERE group_name = '" . $db->sql_escape(strtoupper($group)) . "'";
1144      $result = $db->sql_query($sql);
1145      $group_id = (int) $db->sql_fetchfield('group_id');
1146      $db->sql_freeresult($result);
1147  
1148      if (!$group_id)
1149      {
1150          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GROUP'], $group, 'user_group_auth()'), __LINE__, __FILE__, true);
1151          return;
1152      }
1153  
1154      if ($same_db || !$use_src_db)
1155      {
1156          $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' (user_id, group_id, user_pending)
1157              ' . str_replace('{' . strtoupper($group) . '}', $group_id . ', 0', $select_query);
1158          $db->sql_query($sql);
1159      }
1160      else
1161      {
1162          $result = $src_db->sql_query(str_replace('{' . strtoupper($group) . '}', $group_id . ' ', $select_query));
1163          while ($row = $src_db->sql_fetchrow($result))
1164          {
1165              // this might become quite a lot of INSERTS unfortunately
1166              $sql = 'INSERT INTO ' . USER_GROUP_TABLE . " (user_id, group_id, user_pending)
1167                  VALUES ({$row['user_id']}, $group_id, 0)";
1168              $db->sql_query($sql);
1169          }
1170          $src_db->sql_freeresult($result);
1171      }
1172  }
1173  
1174  /**
1175  * Retrieves configuration information from the source forum and caches it as an array
1176  * Both database and file driven configuration formats can be handled
1177  * (the type used is specified in $config_schema, see convert_phpbb20.php for more details)
1178  */
1179  function get_config()
1180  {
1181      static $convert_config;
1182      global $user;
1183  
1184      if (isset($convert_config))
1185      {
1186          return $convert_config;
1187      }
1188  
1189      global $src_db, $same_db;
1190      global $convert;
1191  
1192      if ($convert->config_schema['table_format'] != 'file')
1193      {
1194          if ($convert->mysql_convert && $same_db)
1195          {
1196              $src_db->sql_query("SET NAMES 'binary'");
1197          }
1198  
1199          $sql = 'SELECT * FROM ' . $convert->src_table_prefix . $convert->config_schema['table_name'];
1200          $result = $src_db->sql_query($sql);
1201          $row = $src_db->sql_fetchrow($result);
1202  
1203          if (!$row)
1204          {
1205              $convert->p_master->error($user->lang['CONV_ERROR_GET_CONFIG'], __LINE__, __FILE__);
1206          }
1207      }
1208  
1209      if (is_array($convert->config_schema['table_format']))
1210      {
1211          $convert_config = array();
1212          $key = key($convert->config_schema['table_format']);
1213          $val = current($convert->config_schema['table_format']);
1214  
1215          do
1216          {
1217              $convert_config[$row[$key]] = $row[$val];
1218          }
1219          while ($row = $src_db->sql_fetchrow($result));
1220          $src_db->sql_freeresult($result);
1221  
1222          if ($convert->mysql_convert && $same_db)
1223          {
1224              $src_db->sql_query("SET NAMES 'utf8'");
1225          }
1226      }
1227      else if ($convert->config_schema['table_format'] == 'file')
1228      {
1229          $filename = $convert->options['forum_path'] . '/' . $convert->config_schema['filename'];
1230          if (!file_exists($filename))
1231          {
1232              $convert->p_master->error($user->lang('FILE_NOT_FOUND', $filename), __LINE__, __FILE__);
1233          }
1234  
1235          if (isset($convert->config_schema['array_name']))
1236          {
1237              unset($convert->config_schema['array_name']);
1238          }
1239  
1240          $convert_config = extract_variables_from_file($filename);
1241          if (!empty($convert->config_schema['array_name']))
1242          {
1243              $convert_config = $convert_config[$convert->config_schema['array_name']];
1244          }
1245      }
1246      else
1247      {
1248          $convert_config = $row;
1249          if ($convert->mysql_convert && $same_db)
1250          {
1251              $src_db->sql_query("SET NAMES 'utf8'");
1252          }
1253      }
1254  
1255      if (!count($convert_config))
1256      {
1257          $convert->p_master->error($user->lang['CONV_ERROR_CONFIG_EMPTY'], __LINE__, __FILE__);
1258      }
1259  
1260      return $convert_config;
1261  }
1262  
1263  /**
1264  * Transfers the relevant configuration information from the source forum
1265  * The mapping of fields is specified in $config_schema, see convert_phpbb20.php for more details
1266  */
1267  function restore_config($schema)
1268  {
1269      global $config;
1270  
1271      $convert_config = get_config();
1272  
1273      foreach ($schema['settings'] as $config_name => $src)
1274      {
1275          if (preg_match('/(.*)\((.*)\)/', $src, $m))
1276          {
1277              $var = (empty($m[2]) || empty($convert_config[$m[2]])) ? "''" : "'" . addslashes($convert_config[$m[2]]) . "'";
1278              $exec = '$config_value = ' . $m[1] . '(' . $var . ');';
1279              // @codingStandardsIgnoreStart
1280              eval($exec);
1281              // @codingStandardsIgnoreEnd
1282          }
1283          else
1284          {
1285              if ($schema['table_format'] != 'file' || empty($schema['array_name']))
1286              {
1287                  $config_value = (isset($convert_config[$src])) ? $convert_config[$src] : '';
1288              }
1289              else if (!empty($schema['array_name']))
1290              {
1291                  $src_ary = $schema['array_name'];
1292                  $config_value = (isset($convert_config[$src_ary][$src])) ? $convert_config[$src_ary][$src] : '';
1293              }
1294          }
1295  
1296          if ($config_value !== '')
1297          {
1298              // Most are...
1299              if (is_string($config_value))
1300              {
1301                  $config_value = truncate_string(utf8_htmlspecialchars($config_value), 255, 255, false);
1302              }
1303  
1304              $config->set($config_name, $config_value);
1305          }
1306      }
1307  }
1308  
1309  /**
1310  * Update the count of PM's in custom folders for all users
1311  */
1312  function update_folder_pm_count()
1313  {
1314      global $db;
1315  
1316      $sql = 'SELECT user_id, folder_id, COUNT(msg_id) as num_messages
1317          FROM ' . PRIVMSGS_TO_TABLE . '
1318          WHERE folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ', ' . PRIVMSGS_INBOX . ', ' . PRIVMSGS_OUTBOX . ', ' . PRIVMSGS_SENTBOX . ')
1319          GROUP BY folder_id, user_id';
1320      $result = $db->sql_query($sql);
1321  
1322      while ($row = $db->sql_fetchrow($result))
1323      {
1324          $db->sql_query('UPDATE ' . PRIVMSGS_FOLDER_TABLE . ' SET pm_count = ' . $row['num_messages'] . '
1325              WHERE user_id = ' . $row['user_id'] . ' AND folder_id = ' . $row['folder_id']);
1326      }
1327      $db->sql_freeresult($result);
1328  }
1329  
1330  // Functions mainly used by the main convertor script
1331  
1332  function path($path, $path_relative = true)
1333  {
1334      if ($path === false)
1335      {
1336          return '';
1337      }
1338  
1339      if (substr($path, -1) != '/')
1340      {
1341          $path .= '/';
1342      }
1343  
1344      if (!$path_relative)
1345      {
1346          return $path;
1347      }
1348  
1349      if (substr($path, 0, 1) == '/')
1350      {
1351          $path = substr($path, 1);
1352      }
1353  
1354      return $path;
1355  }
1356  
1357  /**
1358  * Extract the variables defined in a configuration file
1359  * @todo As noted by Xore we need to look at this from a security perspective
1360  */
1361  function extract_variables_from_file($_filename)
1362  {
1363      include($_filename);
1364  
1365      $vars = get_defined_vars();
1366      unset($vars['_filename']);
1367  
1368      return $vars;
1369  }
1370  
1371  function get_path($src_path, $src_url, $test_file)
1372  {
1373      global $phpbb_root_path, $phpEx;
1374  
1375      $board_config = get_config();
1376  
1377      $test_file = preg_replace('/\.php$/i', ".$phpEx", $test_file);
1378      $src_path = path($src_path);
1379  
1380      if (@file_exists($phpbb_root_path . $src_path . $test_file))
1381      {
1382          return $src_path;
1383      }
1384  
1385      if (!empty($src_url) && !empty($board_config['server_name']))
1386      {
1387          if (!preg_match('#https?://([^/]+)(.*)#i', $src_url, $m))
1388          {
1389              return false;
1390          }
1391  
1392          if ($m[1] != $board_config['server_name'])
1393          {
1394              return false;
1395          }
1396  
1397          $url_parts = explode('/', $m[2]);
1398          if (substr($src_url, -1) != '/')
1399          {
1400              if (preg_match('/.*\.([a-z0-9]{3,4})$/i', $url_parts[count($url_parts) - 1]))
1401              {
1402                  $url_parts[count($url_parts) - 1] = '';
1403              }
1404              else
1405              {
1406                  $url_parts[] = '';
1407              }
1408          }
1409  
1410          $script_path = $board_config['script_path'];
1411          if (substr($script_path, -1) == '/')
1412          {
1413              $script_path = substr($script_path, 0, -1);
1414          }
1415  
1416          $path_array = array();
1417  
1418          $phpbb_parts = explode('/', $script_path);
1419          for ($i = 0, $end = count($url_parts); $i < $end; ++$i)
1420          {
1421              if ($i < count($phpbb_parts[$i]) && $url_parts[$i] == $phpbb_parts[$i])
1422              {
1423                  $path_array[] = $url_parts[$i];
1424                  unset($url_parts[$i]);
1425              }
1426              else
1427              {
1428                  $path = '';
1429                  for ($j = $i, $end2 = count($phpbb_parts); $j < $end2; ++$j)
1430                  {
1431                      $path .= '../';
1432                  }
1433                  $path .= implode('/', $url_parts);
1434                  break;
1435              }
1436          }
1437  
1438          if (!empty($path))
1439          {
1440              if (@file_exists($phpbb_root_path . $path . $test_file))
1441              {
1442                  return $path;
1443              }
1444          }
1445      }
1446  
1447      return false;
1448  }
1449  
1450  function compare_table($tables, $tablename, &$prefixes)
1451  {
1452      for ($i = 0, $table_size = count($tables); $i < $table_size; ++$i)
1453      {
1454          if (preg_match('/(.*)' . $tables[$i] . '$/', $tablename, $m))
1455          {
1456              if (empty($m[1]))
1457              {
1458                  $m[1] = '*';
1459              }
1460  
1461              if (isset($prefixes[$m[1]]))
1462              {
1463                  $prefixes[$m[1]]++;
1464              }
1465              else
1466              {
1467                  $prefixes[$m[1]] = 1;
1468              }
1469          }
1470      }
1471  }
1472  
1473  /**
1474  * Grant permissions to a specified user or group
1475  *
1476  * @param string $ug_type user|group|user_role|group_role
1477  * @param mixed $forum_id forum ids (array|int|0) -> 0 == all forums
1478  * @param mixed $ug_id [int] user_id|group_id : [string] usergroup name
1479  * @param mixed $acl_list [string] acl entry : [array] acl entries : [string] role entry
1480  * @param int $setting ACL_YES|ACL_NO|ACL_NEVER
1481  */
1482  function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO)
1483  {
1484      global $db;
1485      static $acl_option_ids, $group_ids;
1486  
1487      if (($ug_type == 'group' || $ug_type == 'group_role') && is_string($ug_id))
1488      {
1489          if (!isset($group_ids[$ug_id]))
1490          {
1491              $sql = 'SELECT group_id
1492                  FROM ' . GROUPS_TABLE . "
1493                  WHERE group_name = '" . $db->sql_escape(strtoupper($ug_id)) . "'";
1494              $result = $db->sql_query_limit($sql, 1);
1495              $id = (int) $db->sql_fetchfield('group_id');
1496              $db->sql_freeresult($result);
1497  
1498              if (!$id)
1499              {
1500                  return;
1501              }
1502  
1503              $group_ids[$ug_id] = $id;
1504          }
1505  
1506          $ug_id = (int) $group_ids[$ug_id];
1507      }
1508  
1509      $table = ($ug_type == 'user' || $ug_type == 'user_role') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE;
1510      $id_field = ($ug_type == 'user' || $ug_type == 'user_role') ? 'user_id' : 'group_id';
1511  
1512      // Role based permissions are the simplest to handle so check for them first
1513      if ($ug_type == 'user_role' || $ug_type == 'group_role')
1514      {
1515          if (is_numeric($forum_id))
1516          {
1517              $sql = 'SELECT role_id
1518                  FROM ' . ACL_ROLES_TABLE . "
1519                  WHERE role_name = 'ROLE_" . $db->sql_escape($acl_list) . "'";
1520              $result = $db->sql_query_limit($sql, 1);
1521              $row = $db->sql_fetchrow($result);
1522              $db->sql_freeresult($result);
1523  
1524              // If we have no role id there is something wrong here
1525              if ($row)
1526              {
1527                  $sql = "INSERT INTO $table ($id_field, forum_id, auth_role_id) VALUES ($ug_id, $forum_id, " . $row['role_id'] . ')';
1528                  $db->sql_query($sql);
1529              }
1530          }
1531  
1532          return;
1533      }
1534  
1535      // Build correct parameters
1536      $auth = array();
1537  
1538      if (!is_array($acl_list))
1539      {
1540          $auth = array($acl_list => $setting);
1541      }
1542      else
1543      {
1544          foreach ($acl_list as $auth_option)
1545          {
1546              $auth[$auth_option] = $setting;
1547          }
1548      }
1549      unset($acl_list);
1550  
1551      if (!is_array($forum_id))
1552      {
1553          $forum_id = array($forum_id);
1554      }
1555  
1556      // Set any flags as required
1557      foreach ($auth as $auth_option => $acl_setting)
1558      {
1559          $flag = substr($auth_option, 0, strpos($auth_option, '_') + 1);
1560          if (empty($auth[$flag]))
1561          {
1562              $auth[$flag] = $acl_setting;
1563          }
1564      }
1565  
1566      if (!is_array($acl_option_ids) || empty($acl_option_ids))
1567      {
1568          $sql = 'SELECT auth_option_id, auth_option
1569              FROM ' . ACL_OPTIONS_TABLE;
1570          $result = $db->sql_query($sql);
1571  
1572          while ($row = $db->sql_fetchrow($result))
1573          {
1574              $acl_option_ids[$row['auth_option']] = $row['auth_option_id'];
1575          }
1576          $db->sql_freeresult($result);
1577      }
1578  
1579      $sql_forum = 'AND ' . $db->sql_in_set('a.forum_id', array_map('intval', $forum_id), false, true);
1580  
1581      $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";
1582      $result = $db->sql_query($sql);
1583  
1584      $cur_auth = array();
1585      while ($row = $db->sql_fetchrow($result))
1586      {
1587          $cur_auth[$row['forum_id']][$row['auth_option_id']] = $row['auth_setting'];
1588      }
1589      $db->sql_freeresult($result);
1590  
1591      $sql_ary = array();
1592      foreach ($forum_id as $forum)
1593      {
1594          foreach ($auth as $auth_option => $setting)
1595          {
1596              $auth_option_id = $acl_option_ids[$auth_option];
1597  
1598              if (!$auth_option_id)
1599              {
1600                  continue;
1601              }
1602  
1603              switch ($setting)
1604              {
1605                  case ACL_NO:
1606                      if (isset($cur_auth[$forum][$auth_option_id]))
1607                      {
1608                          $sql_ary['delete'][] = "DELETE FROM $table
1609                              WHERE forum_id = $forum
1610                                  AND auth_option_id = $auth_option_id
1611                                  AND $id_field = $ug_id";
1612                      }
1613                  break;
1614  
1615                  default:
1616                      if (!isset($cur_auth[$forum][$auth_option_id]))
1617                      {
1618                          $sql_ary['insert'][] = "$ug_id, $forum, $auth_option_id, $setting";
1619                      }
1620                      else if ($cur_auth[$forum][$auth_option_id] != $setting)
1621                      {
1622                          $sql_ary['update'][] = "UPDATE " . $table . "
1623                              SET auth_setting = $setting
1624                              WHERE $id_field = $ug_id
1625                                  AND forum_id = $forum
1626                                  AND auth_option_id = $auth_option_id";
1627                      }
1628              }
1629          }
1630      }
1631      unset($cur_auth);
1632  
1633      $sql = '';
1634      foreach ($sql_ary as $sql_type => $sql_subary)
1635      {
1636          switch ($sql_type)
1637          {
1638              case 'insert':
1639                  switch ($db->get_sql_layer())
1640                  {
1641                      case 'sqlite3':
1642                      case 'mssqlnative':
1643                          $sql = implode(' UNION ALL ', preg_replace('#^(.*?)$#', 'SELECT \1', $sql_subary));
1644                      break;
1645  
1646                      default:
1647                          foreach ($sql_subary as $sql)
1648                          {
1649                              $sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) VALUES ($sql)";
1650                              $db->sql_query($sql);
1651                              $sql = '';
1652                          }
1653                  }
1654  
1655                  if ($sql != '')
1656                  {
1657                      $sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) $sql";
1658                      $db->sql_query($sql);
1659                  }
1660              break;
1661  
1662              case 'update':
1663              case 'delete':
1664                  foreach ($sql_subary as $sql)
1665                  {
1666                      $db->sql_query($sql);
1667                      $sql = '';
1668                  }
1669              break;
1670          }
1671          unset($sql_ary[$sql_type]);
1672      }
1673      unset($sql_ary);
1674  
1675  }
1676  
1677  /**
1678  * Update the count of unread private messages for all users
1679  */
1680  function update_unread_count()
1681  {
1682      global $db;
1683  
1684      $sql = 'SELECT user_id, COUNT(msg_id) as num_messages
1685          FROM ' . PRIVMSGS_TO_TABLE . '
1686          WHERE pm_unread = 1
1687              AND folder_id <> ' . PRIVMSGS_OUTBOX . '
1688          GROUP BY user_id';
1689      $result = $db->sql_query($sql);
1690  
1691      while ($row = $db->sql_fetchrow($result))
1692      {
1693          $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_unread_privmsg = ' . $row['num_messages'] . '
1694              WHERE user_id = ' . $row['user_id']);
1695      }
1696      $db->sql_freeresult($result);
1697  }
1698  
1699  /**
1700  * Add any of the pre-defined "special" groups which are missing from the database
1701  */
1702  function add_default_groups()
1703  {
1704      global $db;
1705  
1706      $default_groups = array(
1707          'GUESTS'            => array('', 0, 0),
1708          'REGISTERED'        => array('', 0, 0),
1709          'REGISTERED_COPPA'    => array('', 0, 0),
1710          'GLOBAL_MODERATORS'    => array('00AA00', 2, 0),
1711          'ADMINISTRATORS'    => array('AA0000', 1, 1),
1712          'BOTS'                => array('9E8DA7', 0, 0),
1713          'NEWLY_REGISTERED'        => array('', 0, 0),
1714      );
1715  
1716      $sql = 'SELECT *
1717          FROM ' . GROUPS_TABLE . '
1718          WHERE ' . $db->sql_in_set('group_name', array_keys($default_groups));
1719      $result = $db->sql_query($sql);
1720  
1721      while ($row = $db->sql_fetchrow($result))
1722      {
1723          unset($default_groups[strtoupper($row['group_name'])]);
1724      }
1725      $db->sql_freeresult($result);
1726  
1727      $sql_ary = array();
1728  
1729      foreach ($default_groups as $name => $data)
1730      {
1731          $sql_ary[] = array(
1732              'group_name'            => (string) $name,
1733              'group_desc'            => '',
1734              'group_desc_uid'        => '',
1735              'group_desc_bitfield'    => '',
1736              'group_type'            => GROUP_SPECIAL,
1737              'group_colour'            => (string) $data[0],
1738              'group_legend'            => (int) $data[1],
1739              'group_founder_manage'    => (int) $data[2],
1740          );
1741      }
1742  
1743      if (count($sql_ary))
1744      {
1745          $db->sql_multi_insert(GROUPS_TABLE, $sql_ary);
1746      }
1747  }
1748  
1749  function add_groups_to_teampage()
1750  {
1751      global $db;
1752  
1753      $teampage_groups = array(
1754          'ADMINISTRATORS'    => 1,
1755          'GLOBAL_MODERATORS'    => 2,
1756      );
1757  
1758      $sql = 'SELECT *
1759          FROM ' . GROUPS_TABLE . '
1760          WHERE ' . $db->sql_in_set('group_name', array_keys($teampage_groups));
1761      $result = $db->sql_query($sql);
1762  
1763      $teampage_ary = array();
1764      while ($row = $db->sql_fetchrow($result))
1765      {
1766          $teampage_ary[] = array(
1767              'group_id'                => (int) $row['group_id'],
1768              'teampage_name'            => '',
1769              'teampage_position'        => (int) $teampage_groups[$row['group_name']],
1770              'teampage_parent'        => 0,
1771          );
1772      }
1773      $db->sql_freeresult($result);
1774  
1775      if (count($teampage_ary))
1776      {
1777          $db->sql_multi_insert(TEAMPAGE_TABLE, $teampage_ary);
1778      }
1779  }
1780  
1781  
1782  /**
1783  * Sync post count. We might need to do this in batches.
1784  */
1785  function sync_post_count($offset, $limit)
1786  {
1787      global $db;
1788      $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id
1789              FROM ' . POSTS_TABLE . '
1790              WHERE post_postcount = 1
1791                  AND post_visibility = ' . ITEM_APPROVED . '
1792              GROUP BY poster_id
1793              ORDER BY poster_id';
1794      $result = $db->sql_query_limit($sql, $limit, $offset);
1795  
1796      while ($row = $db->sql_fetchrow($result))
1797      {
1798          $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['poster_id']}");
1799      }
1800      $db->sql_freeresult($result);
1801  }
1802  
1803  /**
1804  * Add the search bots into the database
1805  * This code should be used in execute_last if the source database did not have bots
1806  * If you are converting bots this function should not be called
1807  * @todo We might want to look at sharing the bot list between the install code and this code for consistancy
1808  */
1809  function add_bots()
1810  {
1811      global $db, $convert, $user, $config, $phpbb_root_path, $phpEx;
1812  
1813      $db->sql_query($convert->truncate_statement . BOTS_TABLE);
1814  
1815      $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name = 'BOTS'";
1816      $result = $db->sql_query($sql);
1817      $group_id = (int) $db->sql_fetchfield('group_id', false, $result);
1818      $db->sql_freeresult($result);
1819  
1820      if (!$group_id)
1821      {
1822          add_default_groups();
1823  
1824          $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name = 'BOTS'";
1825          $result = $db->sql_query($sql);
1826          $group_id = (int) $db->sql_fetchfield('group_id', false, $result);
1827          $db->sql_freeresult($result);
1828  
1829          if (!$group_id)
1830          {
1831              global $install;
1832              $install->error($user->lang['CONV_ERROR_INCONSISTENT_GROUPS'], __LINE__, __FILE__);
1833          }
1834      }
1835  
1836      $bots = array(
1837          'AdsBot [Google]'            => array('AdsBot-Google', ''),
1838          'Alexa [Bot]'                => array('ia_archiver', ''),
1839          'Alta Vista [Bot]'            => array('Scooter/', ''),
1840          'Ask Jeeves [Bot]'            => array('Ask Jeeves', ''),
1841          'Baidu [Spider]'            => array('Baiduspider+(', ''),
1842          'Bing [Bot]'                => array('bingbot/', ''),
1843          'Exabot [Bot]'                => array('Exabot/', ''),
1844          'FAST Enterprise [Crawler]'    => array('FAST Enterprise Crawler', ''),
1845          'FAST WebCrawler [Crawler]'    => array('FAST-WebCrawler/', ''),
1846          'Francis [Bot]'                => array('http://www.neomo.de/', ''),
1847          'Gigabot [Bot]'                => array('Gigabot/', ''),
1848          'Google Adsense [Bot]'        => array('Mediapartners-Google', ''),
1849          'Google Desktop'            => array('Google Desktop', ''),
1850          'Google Feedfetcher'        => array('Feedfetcher-Google', ''),
1851          'Google [Bot]'                => array('Googlebot', ''),
1852          'Heise IT-Markt [Crawler]'    => array('heise-IT-Markt-Crawler', ''),
1853          'Heritrix [Crawler]'        => array('heritrix/1.', ''),
1854          'IBM Research [Bot]'        => array('ibm.com/cs/crawler', ''),
1855          'ICCrawler - ICjobs'        => array('ICCrawler - ICjobs', ''),
1856          'ichiro [Crawler]'            => array('ichiro/2', ''),
1857          'Majestic-12 [Bot]'            => array('MJ12bot/', ''),
1858          'Metager [Bot]'                => array('MetagerBot/', ''),
1859          'MSN NewsBlogs'                => array('msnbot-NewsBlogs/', ''),
1860          'MSN [Bot]'                    => array('msnbot/', ''),
1861          'MSNbot Media'                => array('msnbot-media/', ''),
1862          'NG-Search [Bot]'            => array('NG-Search/', ''),
1863          'Nutch [Bot]'                => array('http://lucene.apache.org/nutch/', ''),
1864          'Nutch/CVS [Bot]'            => array('NutchCVS/', ''),
1865          'OmniExplorer [Bot]'        => array('OmniExplorer_Bot/', ''),
1866          'Online link [Validator]'    => array('online link validator', ''),
1867          'psbot [Picsearch]'            => array('psbot/0', ''),
1868          'Seekport [Bot]'            => array('Seekbot/', ''),
1869          'Sensis [Crawler]'            => array('Sensis Web Crawler', ''),
1870          'SEO Crawler'                => array('SEO search Crawler/', ''),
1871          'Seoma [Crawler]'            => array('Seoma [SEO Crawler]', ''),
1872          'SEOSearch [Crawler]'        => array('SEOsearch/', ''),
1873          'Snappy [Bot]'                => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''),
1874          'Steeler [Crawler]'            => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''),
1875          'Synoo [Bot]'                => array('SynooBot/', ''),
1876          'Telekom [Bot]'                => array('crawleradmin.t-info@telekom.de', ''),
1877          'TurnitinBot [Bot]'            => array('TurnitinBot/', ''),
1878          'Voyager [Bot]'                => array('voyager/1.0', ''),
1879          'W3 [Sitesearch]'            => array('W3 SiteSearch Crawler', ''),
1880          'W3C [Linkcheck]'            => array('W3C-checklink/', ''),
1881          'W3C [Validator]'            => array('W3C_*Validator', ''),
1882          'WiseNut [Bot]'                => array('http://www.WISEnutbot.com', ''),
1883          'YaCy [Bot]'                => array('yacybot', ''),
1884          'Yahoo MMCrawler [Bot]'        => array('Yahoo-MMCrawler/', ''),
1885          'Yahoo Slurp [Bot]'            => array('Yahoo! DE Slurp', ''),
1886          'Yahoo [Bot]'                => array('Yahoo! Slurp', ''),
1887          'YahooSeeker [Bot]'            => array('YahooSeeker/', ''),
1888      );
1889  
1890      if (!function_exists('user_add'))
1891      {
1892          include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
1893      }
1894  
1895      foreach ($bots as $bot_name => $bot_ary)
1896      {
1897          $user_row = array(
1898              'user_type'                => USER_IGNORE,
1899              'group_id'                => $group_id,
1900              'username'                => $bot_name,
1901              'user_regdate'            => time(),
1902              'user_password'            => '',
1903              'user_colour'            => '9E8DA7',
1904              'user_email'            => '',
1905              'user_lang'                => $config['default_lang'],
1906              'user_style'            => 1,
1907              'user_timezone'            => 'UTC',
1908              'user_allow_massemail'    => 0,
1909          );
1910  
1911          $user_id = user_add($user_row);
1912  
1913          if ($user_id)
1914          {
1915              $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1916                  'bot_active'    => 1,
1917                  'bot_name'        => $bot_name,
1918                  'user_id'        => $user_id,
1919                  'bot_agent'        => $bot_ary[0],
1920                  'bot_ip'        => $bot_ary[1])
1921              );
1922              $db->sql_query($sql);
1923          }
1924      }
1925  }
1926  
1927  /**
1928  * Update any dynamic configuration variables after the conversion is finished
1929  * @todo Confirm that this updates all relevant values since it has not necessarily been kept in sync with all changes
1930  */
1931  function update_dynamic_config()
1932  {
1933      global $db, $config;
1934  
1935      // Get latest username
1936      $sql = 'SELECT user_id, username, user_colour
1937          FROM ' . USERS_TABLE . '
1938          WHERE user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
1939  
1940      if (!empty($config['increment_user_id']))
1941      {
1942          $sql .= ' AND user_id <> ' . $config['increment_user_id'];
1943      }
1944  
1945      $sql .= ' ORDER BY user_id DESC';
1946  
1947      $result = $db->sql_query_limit($sql, 1);
1948      $row = $db->sql_fetchrow($result);
1949      $db->sql_freeresult($result);
1950  
1951      if ($row)
1952      {
1953          $config->set('newest_user_id', $row['user_id'], false);
1954          $config->set('newest_username', $row['username'], false);
1955          $config->set('newest_user_colour', $row['user_colour'], false);
1956      }
1957  
1958  //    Also do not reset record online user/date. There will be old data or the fresh data from the schema.
1959  //    set_config('record_online_users', 1, true);
1960  //    set_config('record_online_date', time(), true);
1961  
1962      $sql = 'SELECT COUNT(post_id) AS stat
1963          FROM ' . POSTS_TABLE . '
1964          WHERE post_visibility = ' . ITEM_APPROVED;
1965      $result = $db->sql_query($sql);
1966      $row = $db->sql_fetchrow($result);
1967      $db->sql_freeresult($result);
1968  
1969      $config->set('num_posts', (int) $row['stat'], false);
1970  
1971      $sql = 'SELECT COUNT(topic_id) AS stat
1972          FROM ' . TOPICS_TABLE . '
1973          WHERE topic_visibility = ' . ITEM_APPROVED;
1974      $result = $db->sql_query($sql);
1975      $row = $db->sql_fetchrow($result);
1976      $db->sql_freeresult($result);
1977  
1978      $config->set('num_topics', (int) $row['stat'], false);
1979  
1980      $sql = 'SELECT COUNT(user_id) AS stat
1981          FROM ' . USERS_TABLE . '
1982          WHERE user_type IN (' . USER_NORMAL . ',' . USER_FOUNDER . ')';
1983      $result = $db->sql_query($sql);
1984      $row = $db->sql_fetchrow($result);
1985      $db->sql_freeresult($result);
1986  
1987      $config->set('num_users', (int) $row['stat'], false);
1988  
1989      $sql = 'SELECT COUNT(attach_id) as stat
1990          FROM ' . ATTACHMENTS_TABLE . '
1991          WHERE is_orphan = 0';
1992      $result = $db->sql_query($sql);
1993      $config->set('num_files', (int) $db->sql_fetchfield('stat'), false);
1994      $db->sql_freeresult($result);
1995  
1996      $sql = 'SELECT SUM(filesize) as stat
1997          FROM ' . ATTACHMENTS_TABLE . '
1998          WHERE is_orphan = 0';
1999      $result = $db->sql_query($sql);
2000      $config->set('upload_dir_size', (float) $db->sql_fetchfield('stat'), false);
2001      $db->sql_freeresult($result);
2002  
2003      /**
2004      * We do not resync users post counts - this can be done by the admin after conversion if wanted.
2005      $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id
2006          FROM ' . POSTS_TABLE . '
2007          WHERE post_postcount = 1
2008          GROUP BY poster_id';
2009      $result = $db->sql_query($sql);
2010  
2011      while ($row = $db->sql_fetchrow($result))
2012      {
2013          $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['poster_id']}");
2014      }
2015      $db->sql_freeresult($result);
2016      */
2017  }
2018  
2019  /**
2020  * Updates topics_posted entries
2021  */
2022  function update_topics_posted()
2023  {
2024      global $db;
2025  
2026      switch ($db->get_sql_layer())
2027      {
2028          case 'sqlite3':
2029              $db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE);
2030          break;
2031  
2032          default:
2033              $db->sql_query('TRUNCATE TABLE ' . TOPICS_POSTED_TABLE);
2034          break;
2035      }
2036  
2037      // This can get really nasty... therefore we only do the last six months
2038      $get_from_time = time() - (6 * 4 * 7 * 24 * 60 * 60);
2039  
2040      // Select forum ids, do not include categories
2041      $sql = 'SELECT forum_id
2042          FROM ' . FORUMS_TABLE . '
2043          WHERE forum_type <> ' . FORUM_CAT;
2044      $result = $db->sql_query($sql);
2045  
2046      $forum_ids = array();
2047      while ($row = $db->sql_fetchrow($result))
2048      {
2049          $forum_ids[] = $row['forum_id'];
2050      }
2051      $db->sql_freeresult($result);
2052  
2053      // Any global announcements? ;)
2054      $forum_ids[] = 0;
2055  
2056      // Now go through the forums and get us some topics...
2057      foreach ($forum_ids as $forum_id)
2058      {
2059          $sql = 'SELECT p.poster_id, p.topic_id
2060              FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t
2061              WHERE t.forum_id = ' . $forum_id . '
2062                  AND t.topic_moved_id = 0
2063                  AND t.topic_last_post_time > ' . $get_from_time . '
2064                  AND t.topic_id = p.topic_id
2065                  AND p.poster_id <> ' . ANONYMOUS . '
2066              GROUP BY p.poster_id, p.topic_id';
2067          $result = $db->sql_query($sql);
2068  
2069          $posted = array();
2070          while ($row = $db->sql_fetchrow($result))
2071          {
2072              $posted[$row['poster_id']][] = $row['topic_id'];
2073          }
2074          $db->sql_freeresult($result);
2075  
2076          $sql_ary = array();
2077          foreach ($posted as $user_id => $topic_row)
2078          {
2079              foreach ($topic_row as $topic_id)
2080              {
2081                  $sql_ary[] = array(
2082                      'user_id'        => (int) $user_id,
2083                      'topic_id'        => (int) $topic_id,
2084                      'topic_posted'    => 1,
2085                  );
2086              }
2087          }
2088          unset($posted);
2089  
2090          if (count($sql_ary))
2091          {
2092              $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary);
2093          }
2094      }
2095  }
2096  
2097  /**
2098  * Ensure that all users have a default group specified and update related information such as their colour
2099  */
2100  function fix_empty_primary_groups()
2101  {
2102      global $db;
2103  
2104      // Set group ids for users not already having it
2105      $sql = 'UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('registered') . '
2106          WHERE group_id = 0 AND user_type = ' . USER_INACTIVE;
2107      $db->sql_query($sql);
2108  
2109      $sql = 'UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('registered') . '
2110          WHERE group_id = 0 AND user_type = ' . USER_NORMAL;
2111      $db->sql_query($sql);
2112  
2113      $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('guests') . ' WHERE user_id = ' . ANONYMOUS);
2114  
2115      $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . ' WHERE group_id = ' . get_group_id('administrators');
2116      $result = $db->sql_query($sql);
2117  
2118      $user_ids = array();
2119      while ($row = $db->sql_fetchrow($result))
2120      {
2121          $user_ids[] = $row['user_id'];
2122      }
2123      $db->sql_freeresult($result);
2124  
2125      if (count($user_ids))
2126      {
2127          $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('administrators') . '
2128              WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids));
2129      }
2130  
2131      $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . ' WHERE group_id = ' . get_group_id('global_moderators');
2132      $result = $db->sql_query($sql);
2133  
2134      $user_ids = array();
2135      while ($row = $db->sql_fetchrow($result))
2136      {
2137          $user_ids[] = $row['user_id'];
2138      }
2139      $db->sql_freeresult($result);
2140  
2141      if (count($user_ids))
2142      {
2143          $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('global_moderators') . '
2144              WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids));
2145      }
2146  
2147      // Set user colour
2148      $sql = 'SELECT group_id, group_colour FROM ' . GROUPS_TABLE . "
2149          WHERE group_colour <> ''";
2150      $result = $db->sql_query($sql);
2151  
2152      while ($row = $db->sql_fetchrow($result))
2153      {
2154          $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_colour = '{$row['group_colour']}' WHERE group_id = {$row['group_id']}");
2155      }
2156      $db->sql_freeresult($result);
2157  }
2158  
2159  /**
2160  * Cleanly remove invalid user entries after converting the users table...
2161  */
2162  function remove_invalid_users()
2163  {
2164      global $db, $phpEx, $phpbb_root_path;
2165  
2166      // username_clean is UNIQUE
2167      $sql = 'SELECT user_id
2168          FROM ' . USERS_TABLE . "
2169          WHERE username_clean = ''";
2170      $result = $db->sql_query($sql);
2171      $row = $db->sql_fetchrow($result);
2172      $db->sql_freeresult($result);
2173  
2174      if ($row)
2175      {
2176          if (!function_exists('user_delete'))
2177          {
2178              include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
2179          }
2180  
2181          user_delete('remove', $row['user_id']);
2182      }
2183  }
2184  
2185  function convert_bbcode($message, $convert_size = true, $extended_bbcodes = false)
2186  {
2187      static $orig, $repl, $origx, $replx, $str_from, $str_to;
2188  
2189      if (empty($orig))
2190      {
2191          $orig = $repl = array();
2192  
2193          $orig[] = '#\[(php|sql)\](.*?)\[/(php|sql)\]#is';
2194          $repl[] = '[code]\2[/code]';
2195  
2196          $orig[] = '#\[font=[^\]]+\](.*?)\[/font\]#is';
2197          $repl[] = '\1';
2198  
2199          $orig[] = '#\[align=[a-z]+\](.*?)\[/align\]#is';
2200          $repl[] = '\1';
2201  
2202          $orig[] = '#\[/list=.*?\]#is';
2203          $repl[] = '[/list]';
2204  
2205          $origx = array(
2206              '#\[glow[^\]]+\](.*?)\[/glow\]#is',
2207              '#\[shadow[^\]]+\](.*?)\[/shadow\]#is',
2208              '#\[flash[^\]]+\](.*?)\[/flash\]#is'
2209          );
2210  
2211          $replx = array(
2212              '\1',
2213              '\1',
2214              '[url=\1]Flash[/url]'
2215          );
2216  
2217          $str_from = array(
2218              '[ftp]',    '[/ftp]',
2219              '[ftp=',    '[/ftp]',
2220              '[pre]',    '[/pre]',
2221              '[table]',    '[/table]',
2222              '[td]',        '[/td]',
2223              '[tr]',        '[/tr]',
2224              '[s]',        '[/s]',
2225              '[left]',    '[/left]',
2226              '[right]',    '[/right]',
2227              '[center]',    '[/center]',
2228              '[sub]',    '[/sub]',
2229              '[sup]',    '[/sup]',
2230              '[tt]',        '[/tt]',
2231              '[move]',    '[/move]',
2232              '[hr]'
2233          );
2234  
2235          $str_to = array(
2236              '[url]',    '[/url]',
2237              '[url=',    '[/url]',
2238              '[code]',    '[/code]',
2239              "\n",        '',
2240              '',            '',
2241              "\n",        '',
2242              '',            '',
2243              '',            '',
2244              '',            '',
2245              '',            '',
2246              '',            '',
2247              '',            '',
2248              '',            '',
2249              '',            '',
2250              "\n\n"
2251          );
2252  
2253          for ($i = 0, $end = count($str_from); $i < $end; ++$i)
2254          {
2255              $origx[] = '#\\' . str_replace(']', '\\]', $str_from[$i]) . '#is';
2256              $replx[] = $str_to[$i];
2257          }
2258      }
2259  
2260      if (preg_match_all('#\[email=([^\]]+)\](.*?)\[/email\]#i', $message, $m))
2261      {
2262          for ($i = 0, $end = count($m[1]); $i < $end; ++$i)
2263          {
2264              if ($m[1][$i] == $m[2][$i])
2265              {
2266                  $message = str_replace($m[0][$i], '[email]' . $m[1][$i] . '[/email]', $message);
2267              }
2268              else
2269              {
2270                  $message = str_replace($m[0][$i], $m[2][$i] . ' ([email]' . $m[1][$i] . '[/email])', $message);
2271              }
2272          }
2273      }
2274  
2275      if ($convert_size && preg_match('#\[size=[0-9]+\].*?\[/size\]#i', $message))
2276      {
2277          $size = array(9, 9, 12, 15, 18, 24, 29, 29, 29, 29);
2278          $message = preg_replace('#\[size=([0-9]+)\](.*?)\[/size\]#i', '[size=\1]\2[/size]', $message);
2279          $message = preg_replace('#\[size=[0-9]{2,}\](.*?)\[/size\]#i', '[size=29]\1[/size]', $message);
2280  
2281          for ($i = count($size); $i;)
2282          {
2283              $i--;
2284              $message = str_replace('[size=' . $i . ']', '[size=' . $size[$i] . ']', $message);
2285          }
2286      }
2287  
2288      if ($extended_bbcodes)
2289      {
2290          $message = preg_replace($origx, $replx, $message);
2291      }
2292  
2293      $message = preg_replace($orig, $repl, $message);
2294      return $message;
2295  }
2296  
2297  
2298  function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $source_relative_path = true)
2299  {
2300      global $convert, $phpbb_root_path, $user, $phpbb_filesystem;
2301  
2302      /** @var \phpbb\filesystem\filesystem_interface $filesystem */
2303      $filesystem = $phpbb_filesystem;
2304  
2305      if (substr($trg, -1) == '/')
2306      {
2307          $trg .= utf8_basename($src);
2308      }
2309      $src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__);
2310      $trg_path = $trg;
2311  
2312      if (!$overwrite && @file_exists($trg_path))
2313      {
2314          return true;
2315      }
2316  
2317      if (!@file_exists($src_path))
2318      {
2319          return;
2320      }
2321  
2322      $path = $phpbb_root_path;
2323      $parts = explode('/', $trg);
2324      unset($parts[count($parts) - 1]);
2325  
2326      for ($i = 0, $end = count($parts); $i < $end; ++$i)
2327      {
2328          $path .= $parts[$i] . '/';
2329  
2330          if (!is_dir($path))
2331          {
2332              @mkdir($path, 0777);
2333          }
2334      }
2335  
2336      if (!$filesystem->is_writable($path))
2337      {
2338          @chmod($path, 0777);
2339      }
2340  
2341      if (!@copy($src_path, $phpbb_root_path . $trg_path))
2342      {
2343          $convert->p_master->error(sprintf($user->lang['COULD_NOT_COPY'], $src_path, $phpbb_root_path . $trg_path), __LINE__, __FILE__, !$die_on_failure);
2344          return;
2345      }
2346  
2347      if ($perm = @fileperms($src_path))
2348      {
2349          @chmod($phpbb_root_path . $trg_path, $perm);
2350      }
2351  
2352      return true;
2353  }
2354  
2355  function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_failure = true, $source_relative_path = true)
2356  {
2357      global $convert, $phpbb_root_path, $config, $user, $phpbb_filesystem;
2358  
2359      /** @var \phpbb\filesystem\filesystem_interface $filesystem */
2360      $filesystem = $phpbb_filesystem;
2361  
2362      $dirlist = $filelist = $bad_dirs = array();
2363      $src = path($src, $source_relative_path);
2364      $trg = path($trg);
2365      $src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__);
2366      $trg_path = $phpbb_root_path . $trg;
2367  
2368      if (!is_dir($trg_path))
2369      {
2370          @mkdir($trg_path, 0777);
2371          @chmod($trg_path, 0777);
2372      }
2373  
2374      if (!$filesystem->is_writable($trg_path))
2375      {
2376          $bad_dirs[] = path($config['script_path']) . $trg;
2377      }
2378  
2379      if ($handle = @opendir($src_path))
2380      {
2381          while ($entry = readdir($handle))
2382          {
2383              if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
2384              {
2385                  continue;
2386              }
2387  
2388              if (is_dir($src_path . $entry))
2389              {
2390                  $dirlist[] = $entry;
2391              }
2392              else
2393              {
2394                  $filelist[] = $entry;
2395              }
2396          }
2397          closedir($handle);
2398      }
2399      else if ($dir = @dir($src_path))
2400      {
2401          while ($entry = $dir->read())
2402          {
2403              if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm')
2404              {
2405                  continue;
2406              }
2407  
2408              if (is_dir($src_path . $entry))
2409              {
2410                  $dirlist[] = $entry;
2411              }
2412              else
2413              {
2414                  $filelist[] = $entry;
2415              }
2416          }
2417          $dir->close();
2418      }
2419      else
2420      {
2421          $convert->p_master->error(sprintf($user->lang['CONV_ERROR_COULD_NOT_READ'], relative_base($src, $source_relative_path)), __LINE__, __FILE__);
2422      }
2423  
2424      if ($copy_subdirs)
2425      {
2426          for ($i = 0, $end = count($dirlist); $i < $end; ++$i)
2427          {
2428              $dir = $dirlist[$i];
2429  
2430              if ($dir == 'CVS')
2431              {
2432                  continue;
2433              }
2434  
2435              if (!is_dir($trg_path . $dir))
2436              {
2437                  @mkdir($trg_path . $dir, 0777);
2438                  @chmod($trg_path . $dir, 0777);
2439              }
2440  
2441              if (!$filesystem->is_writable($trg_path . $dir))
2442              {
2443                  $bad_dirs[] = $trg . $dir;
2444                  $bad_dirs[] = $trg_path . $dir;
2445              }
2446  
2447              if (!count($bad_dirs))
2448              {
2449                  copy_dir($src . $dir, $trg . $dir, true, $overwrite, $die_on_failure, $source_relative_path);
2450              }
2451          }
2452      }
2453  
2454      if (count($bad_dirs))
2455      {
2456          $str = (count($bad_dirs) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE'];
2457          sort($bad_dirs);
2458          $convert->p_master->error(sprintf($str, implode('<br />', $bad_dirs)), __LINE__, __FILE__);
2459      }
2460  
2461      for ($i = 0, $end = count($filelist); $i < $end; ++$i)
2462      {
2463          copy_file($src . $filelist[$i], $trg . $filelist[$i], $overwrite, $die_on_failure, $source_relative_path);
2464      }
2465  }
2466  
2467  function relative_base($path, $is_relative = true, $line = false, $file = false)
2468  {
2469      global $convert, $user;
2470  
2471      if (!$is_relative)
2472      {
2473          return $path;
2474      }
2475  
2476      if (empty($convert->options['forum_path']) && $is_relative)
2477      {
2478          $line = $line ? $line : __LINE__;
2479          $file = $file ? $file : __FILE__;
2480  
2481          $convert->p_master->error($user->lang['CONV_ERROR_NO_FORUM_PATH'], $line, $file);
2482      }
2483  
2484      return $convert->options['forum_path'] . '/' . $path;
2485  }
2486  
2487  function get_smiley_display()
2488  {
2489      static $smiley_count = 0;
2490      $smiley_count++;
2491      return ($smiley_count < 50) ? 1 : 0;
2492  }
2493  
2494  
2495  function fill_dateformat($user_dateformat)
2496  {
2497      global $config;
2498  
2499      return ((empty($user_dateformat)) ? $config['default_dateformat'] : $user_dateformat);
2500  }


Generated: Tue Apr 7 19:44:41 2020 Cross-referenced by PHPXref 0.7.1