[ Index ]

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


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1