[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/includes/acp/ -> acp_database.php (source)

   1  <?php
   2  /**
   3  *
   4  * @package acp
   5  * @version $Id$
   6  * @copyright (c) 2005 phpBB Group
   7  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
   8  *
   9  */
  10  
  11  /**
  12  * @ignore
  13  */
  14  if (!defined('IN_PHPBB'))
  15  {
  16      exit;
  17  }
  18  
  19  /**
  20  * @package acp
  21  */
  22  class acp_database
  23  {
  24      var $db_tools;
  25      var $u_action;
  26  
  27  	function main($id, $mode)
  28      {
  29          global $cache, $db, $user, $auth, $template, $table_prefix;
  30          global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
  31  
  32          if (!class_exists('phpbb_db_tools'))
  33          {
  34              require($phpbb_root_path . 'includes/db/db_tools.' . $phpEx);
  35          }
  36          $this->db_tools = new phpbb_db_tools($db);
  37  
  38          $user->add_lang('acp/database');
  39  
  40          $this->tpl_name = 'acp_database';
  41          $this->page_title = 'ACP_DATABASE';
  42  
  43          $action    = request_var('action', '');
  44          $submit = (isset($_POST['submit'])) ? true : false;
  45  
  46          $template->assign_vars(array(
  47              'MODE'    => $mode
  48          ));
  49  
  50          switch ($mode)
  51          {
  52              case 'backup':
  53  
  54                  $this->page_title = 'ACP_BACKUP';
  55  
  56                  switch ($action)
  57                  {
  58                      case 'download':
  59                          $type    = request_var('type', '');
  60                          $table    = array_intersect($this->db_tools->sql_list_tables(), request_var('table', array('')));
  61                          $format    = request_var('method', '');
  62                          $where    = request_var('where', '');
  63  
  64                          if (!sizeof($table))
  65                          {
  66                              trigger_error($user->lang['TABLE_SELECT_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING);
  67                          }
  68  
  69                          $store = $download = $structure = $schema_data = false;
  70  
  71                          if ($where == 'store_and_download' || $where == 'store')
  72                          {
  73                              $store = true;
  74                          }
  75  
  76                          if ($where == 'store_and_download' || $where == 'download')
  77                          {
  78                              $download = true;
  79                          }
  80  
  81                          if ($type == 'full' || $type == 'structure')
  82                          {
  83                              $structure = true;
  84                          }
  85  
  86                          if ($type == 'full' || $type == 'data')
  87                          {
  88                              $schema_data = true;
  89                          }
  90  
  91                          @set_time_limit(1200);
  92                          @set_time_limit(0);
  93  
  94                          $time = time();
  95  
  96                          $filename = 'backup_' . $time . '_' . unique_id();
  97                          switch ($db->sql_layer)
  98                          {
  99                              case 'mysqli':
 100                              case 'mysql4':
 101                              case 'mysql':
 102                                  $extractor = new mysql_extractor($download, $store, $format, $filename, $time);
 103                              break;
 104  
 105                              case 'sqlite':
 106                                  $extractor = new sqlite_extractor($download, $store, $format, $filename, $time);
 107                              break;
 108  
 109                              case 'postgres':
 110                                  $extractor = new postgres_extractor($download, $store, $format, $filename, $time);
 111                              break;
 112  
 113                              case 'oracle':
 114                                  $extractor = new oracle_extractor($download, $store, $format, $filename, $time);
 115                              break;
 116  
 117                              case 'mssql':
 118                              case 'mssql_odbc':
 119                              case 'mssqlnative':
 120                                  $extractor = new mssql_extractor($download, $store, $format, $filename, $time);
 121                              break;
 122  
 123                              case 'firebird':
 124                                  $extractor = new firebird_extractor($download, $store, $format, $filename, $time);
 125                              break;
 126                          }
 127  
 128                          $extractor->write_start($table_prefix);
 129  
 130                          foreach ($table as $table_name)
 131                          {
 132                              // Get the table structure
 133                              if ($structure)
 134                              {
 135                                  $extractor->write_table($table_name);
 136                              }
 137                              else
 138                              {
 139                                  // We might wanna empty out all that junk :D
 140                                  switch ($db->sql_layer)
 141                                  {
 142                                      case 'sqlite':
 143                                      case 'firebird':
 144                                          $extractor->flush('DELETE FROM ' . $table_name . ";\n");
 145                                      break;
 146  
 147                                      case 'mssql':
 148                                      case 'mssql_odbc':
 149                                      case 'mssqlnative':
 150                                          $extractor->flush('TRUNCATE TABLE ' . $table_name . "GO\n");
 151                                      break;
 152  
 153                                      case 'oracle':
 154                                          $extractor->flush('TRUNCATE TABLE ' . $table_name . "/\n");
 155                                      break;
 156  
 157                                      default:
 158                                          $extractor->flush('TRUNCATE TABLE ' . $table_name . ";\n");
 159                                      break;
 160                                  }
 161                              }
 162  
 163                              // Data
 164                              if ($schema_data)
 165                              {
 166                                  $extractor->write_data($table_name);
 167                              }
 168                          }
 169  
 170                          $extractor->write_end();
 171  
 172                          add_log('admin', 'LOG_DB_BACKUP');
 173  
 174                          if ($download == true)
 175                          {
 176                              exit;
 177                          }
 178  
 179                          trigger_error($user->lang['BACKUP_SUCCESS'] . adm_back_link($this->u_action));
 180                      break;
 181  
 182                      default:
 183                          $tables = $this->db_tools->sql_list_tables();
 184                          asort($tables);
 185                          foreach ($tables as $table_name)
 186                          {
 187                              if (strlen($table_prefix) === 0 || stripos($table_name, $table_prefix) === 0)
 188                              {
 189                                  $template->assign_block_vars('tables', array(
 190                                      'TABLE'    => $table_name
 191                                  ));
 192                              }
 193                          }
 194                          unset($tables);
 195  
 196                          $template->assign_vars(array(
 197                              'U_ACTION'    => $this->u_action . '&amp;action=download'
 198                          ));
 199  
 200                          $available_methods = array('gzip' => 'zlib', 'bzip2' => 'bz2');
 201  
 202                          foreach ($available_methods as $type => $module)
 203                          {
 204                              if (!@extension_loaded($module))
 205                              {
 206                                  continue;
 207                              }
 208  
 209                              $template->assign_block_vars('methods', array(
 210                                  'TYPE'    => $type
 211                              ));
 212                          }
 213  
 214                          $template->assign_block_vars('methods', array(
 215                              'TYPE'    => 'text'
 216                          ));
 217                      break;
 218                  }
 219              break;
 220  
 221              case 'restore':
 222  
 223                  $this->page_title = 'ACP_RESTORE';
 224  
 225                  switch ($action)
 226                  {
 227                      case 'submit':
 228                          $delete = request_var('delete', '');
 229                          $file = request_var('file', '');
 230                          $download = request_var('download', '');
 231  
 232                          if (!preg_match('#^backup_\d{10,}_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches))
 233                          {
 234                              trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
 235                          }
 236  
 237                          $file_name = $phpbb_root_path . 'store/' . $matches[0];
 238  
 239                          if (!file_exists($file_name) || !is_readable($file_name))
 240                          {
 241                              trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
 242                          }
 243  
 244                          if ($delete)
 245                          {
 246                              if (confirm_box(true))
 247                              {
 248                                  unlink($file_name);
 249                                  add_log('admin', 'LOG_DB_DELETE');
 250                                  trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action));
 251                              }
 252                              else
 253                              {
 254                                  confirm_box(false, $user->lang['DELETE_SELECTED_BACKUP'], build_hidden_fields(array('delete' => $delete, 'file' => $file)));
 255                              }
 256                          }
 257                          else if ($download || confirm_box(true))
 258                          {
 259                              if ($download)
 260                              {
 261                                  $name = $matches[0];
 262  
 263                                  switch ($matches[1])
 264                                  {
 265                                      case 'sql':
 266                                          $mimetype = 'text/x-sql';
 267                                      break;
 268                                      case 'sql.bz2':
 269                                          $mimetype = 'application/x-bzip2';
 270                                      break;
 271                                      case 'sql.gz':
 272                                          $mimetype = 'application/x-gzip';
 273                                      break;
 274                                  }
 275  
 276                                  header('Pragma: no-cache');
 277                                  header("Content-Type: $mimetype; name=\"$name\"");
 278                                  header("Content-disposition: attachment; filename=$name");
 279  
 280                                  @set_time_limit(0);
 281  
 282                                  $fp = @fopen($file_name, 'rb');
 283  
 284                                  if ($fp !== false)
 285                                  {
 286                                      while (!feof($fp))
 287                                      {
 288                                          echo fread($fp, 8192);
 289                                      }
 290                                      fclose($fp);
 291                                  }
 292  
 293                                  flush();
 294                                  exit;
 295                              }
 296  
 297                              switch ($matches[1])
 298                              {
 299                                  case 'sql':
 300                                      $fp = fopen($file_name, 'rb');
 301                                      $read = 'fread';
 302                                      $seek = 'fseek';
 303                                      $eof = 'feof';
 304                                      $close = 'fclose';
 305                                      $fgetd = 'fgetd';
 306                                  break;
 307  
 308                                  case 'sql.bz2':
 309                                      $fp = bzopen($file_name, 'r');
 310                                      $read = 'bzread';
 311                                      $seek = '';
 312                                      $eof = 'feof';
 313                                      $close = 'bzclose';
 314                                      $fgetd = 'fgetd_seekless';
 315                                  break;
 316  
 317                                  case 'sql.gz':
 318                                      $fp = gzopen($file_name, 'rb');
 319                                      $read = 'gzread';
 320                                      $seek = 'gzseek';
 321                                      $eof = 'gzeof';
 322                                      $close = 'gzclose';
 323                                      $fgetd = 'fgetd';
 324                                  break;
 325                              }
 326  
 327                              switch ($db->sql_layer)
 328                              {
 329                                  case 'mysql':
 330                                  case 'mysql4':
 331                                  case 'mysqli':
 332                                  case 'sqlite':
 333                                      while (($sql = $fgetd($fp, ";\n", $read, $seek, $eof)) !== false)
 334                                      {
 335                                          $db->sql_query($sql);
 336                                      }
 337                                  break;
 338  
 339                                  case 'firebird':
 340                                      $delim = ";\n";
 341                                      while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false)
 342                                      {
 343                                          $query = trim($sql);
 344                                          if (substr($query, 0, 8) === 'SET TERM')
 345                                          {
 346                                              $delim = $query[9] . "\n";
 347                                              continue;
 348                                          }
 349                                          $db->sql_query($query);
 350                                      }
 351                                  break;
 352  
 353                                  case 'postgres':
 354                                      $delim = ";\n";
 355                                      while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false)
 356                                      {
 357                                          $query = trim($sql);
 358  
 359                                          if (substr($query, 0, 13) == 'CREATE DOMAIN')
 360                                          {
 361                                              list(, , $domain) = explode(' ', $query);
 362                                              $sql = "SELECT domain_name
 363                                                  FROM information_schema.domains
 364                                                  WHERE domain_name = '$domain';";
 365                                              $result = $db->sql_query($sql);
 366                                              if (!$db->sql_fetchrow($result))
 367                                              {
 368                                                  $db->sql_query($query);
 369                                              }
 370                                              $db->sql_freeresult($result);
 371                                          }
 372                                          else
 373                                          {
 374                                              $db->sql_query($query);
 375                                          }
 376  
 377                                          if (substr($query, 0, 4) == 'COPY')
 378                                          {
 379                                              while (($sub = $fgetd($fp, "\n", $read, $seek, $eof)) !== '\.')
 380                                              {
 381                                                  if ($sub === false)
 382                                                  {
 383                                                      trigger_error($user->lang['RESTORE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING);
 384                                                  }
 385                                                  pg_put_line($db->db_connect_id, $sub . "\n");
 386                                              }
 387                                              pg_put_line($db->db_connect_id, "\\.\n");
 388                                              pg_end_copy($db->db_connect_id);
 389                                          }
 390                                      }
 391                                  break;
 392  
 393                                  case 'oracle':
 394                                      while (($sql = $fgetd($fp, "/\n", $read, $seek, $eof)) !== false)
 395                                      {
 396                                          $db->sql_query($sql);
 397                                      }
 398                                  break;
 399  
 400                                  case 'mssql':
 401                                  case 'mssql_odbc':
 402                                  case 'mssqlnative':
 403                                      while (($sql = $fgetd($fp, "GO\n", $read, $seek, $eof)) !== false)
 404                                      {
 405                                          $db->sql_query($sql);
 406                                      }
 407                                  break;
 408                              }
 409  
 410                              $close($fp);
 411  
 412                              // Purge the cache due to updated data
 413                              $cache->purge();
 414  
 415                              add_log('admin', 'LOG_DB_RESTORE');
 416                              trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action));
 417                              break;
 418                          }
 419                          else if (!$download)
 420                          {
 421                              confirm_box(false, $user->lang['RESTORE_SELECTED_BACKUP'], build_hidden_fields(array('file' => $file)));
 422                          }
 423  
 424                      default:
 425                          $methods = array('sql');
 426                          $available_methods = array('sql.gz' => 'zlib', 'sql.bz2' => 'bz2');
 427  
 428                          foreach ($available_methods as $type => $module)
 429                          {
 430                              if (!@extension_loaded($module))
 431                              {
 432                                  continue;
 433                              }
 434                              $methods[] = $type;
 435                          }
 436  
 437                          $dir = $phpbb_root_path . 'store/';
 438                          $dh = @opendir($dir);
 439  
 440                          $backup_files = array();
 441  
 442                          if ($dh)
 443                          {
 444                              while (($file = readdir($dh)) !== false)
 445                              {
 446                                  if (preg_match('#^backup_(\d{10,})_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches))
 447                                  {
 448                                      if (in_array($matches[2], $methods))
 449                                      {
 450                                          $backup_files[(int) $matches[1]] = $file;
 451                                      }
 452                                  }
 453                              }
 454                              closedir($dh);
 455                          }
 456  
 457                          if (!empty($backup_files))
 458                          {
 459                              krsort($backup_files);
 460  
 461                              foreach ($backup_files as $name => $file)
 462                              {
 463                                  $template->assign_block_vars('files', array(
 464                                      'FILE'        => $file,
 465                                      'NAME'        => $user->format_date($name, 'd-m-Y H:i:s', true),
 466                                      'SUPPORTED'    => true,
 467                                  ));
 468                              }
 469                          }
 470  
 471                          $template->assign_vars(array(
 472                              'U_ACTION'    => $this->u_action . '&amp;action=submit'
 473                          ));
 474                      break;
 475                  }
 476              break;
 477          }
 478      }
 479  }
 480  
 481  /**
 482  * @package acp
 483  */
 484  class base_extractor
 485  {
 486      var $fh;
 487      var $fp;
 488      var $write;
 489      var $close;
 490      var $store;
 491      var $download;
 492      var $time;
 493      var $format;
 494      var $run_comp = false;
 495  
 496  	function base_extractor($download = false, $store = false, $format, $filename, $time)
 497      {
 498          $this->download = $download;
 499          $this->store = $store;
 500          $this->time = $time;
 501          $this->format = $format;
 502  
 503          switch ($format)
 504          {
 505              case 'text':
 506                  $ext = '.sql';
 507                  $open = 'fopen';
 508                  $this->write = 'fwrite';
 509                  $this->close = 'fclose';
 510                  $mimetype = 'text/x-sql';
 511              break;
 512              case 'bzip2':
 513                  $ext = '.sql.bz2';
 514                  $open = 'bzopen';
 515                  $this->write = 'bzwrite';
 516                  $this->close = 'bzclose';
 517                  $mimetype = 'application/x-bzip2';
 518              break;
 519              case 'gzip':
 520                  $ext = '.sql.gz';
 521                  $open = 'gzopen';
 522                  $this->write = 'gzwrite';
 523                  $this->close = 'gzclose';
 524                  $mimetype = 'application/x-gzip';
 525              break;
 526          }
 527  
 528          if ($download == true)
 529          {
 530              $name = $filename . $ext;
 531              header('Pragma: no-cache');
 532              header("Content-Type: $mimetype; name=\"$name\"");
 533              header("Content-disposition: attachment; filename=$name");
 534  
 535              switch ($format)
 536              {
 537                  case 'bzip2':
 538                      ob_start();
 539                  break;
 540  
 541                  case 'gzip':
 542                      if ((isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'msie') === false)
 543                      {
 544                          ob_start('ob_gzhandler');
 545                      }
 546                      else
 547                      {
 548                          $this->run_comp = true;
 549                      }
 550                  break;
 551              }
 552          }
 553  
 554          if ($store == true)
 555          {
 556              global $phpbb_root_path;
 557              $file = $phpbb_root_path . 'store/' . $filename . $ext;
 558  
 559              $this->fp = $open($file, 'w');
 560  
 561              if (!$this->fp)
 562              {
 563                  trigger_error('FILE_WRITE_FAIL', E_USER_ERROR);
 564              }
 565          }
 566      }
 567  
 568  	function write_end()
 569      {
 570          static $close;
 571  
 572          if ($this->store)
 573          {
 574              if ($close === null)
 575              {
 576                  $close = $this->close;
 577              }
 578              $close($this->fp);
 579          }
 580  
 581          // bzip2 must be written all the way at the end
 582          if ($this->download && $this->format === 'bzip2')
 583          {
 584              $c = ob_get_clean();
 585              echo bzcompress($c);
 586          }
 587      }
 588  
 589  	function flush($data)
 590      {
 591          static $write;
 592          if ($this->store === true)
 593          {
 594              if ($write === null)
 595              {
 596                  $write = $this->write;
 597              }
 598              $write($this->fp, $data);
 599          }
 600  
 601          if ($this->download === true)
 602          {
 603              if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp))
 604              {
 605                  echo $data;
 606              }
 607  
 608              // we can write the gzip data as soon as we get it
 609              if ($this->format === 'gzip')
 610              {
 611                  if ($this->run_comp)
 612                  {
 613                      echo gzencode($data);
 614                  }
 615                  else
 616                  {
 617                      ob_flush();
 618                      flush();
 619                  }
 620              }
 621          }
 622      }
 623  }
 624  
 625  /**
 626  * @package acp
 627  */
 628  class mysql_extractor extends base_extractor
 629  {
 630  	function write_start($table_prefix)
 631      {
 632          $sql_data = "#\n";
 633          $sql_data .= "# phpBB Backup Script\n";
 634          $sql_data .= "# Dump of tables for $table_prefix\n";
 635          $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
 636          $sql_data .= "#\n";
 637          $this->flush($sql_data);
 638      }
 639  
 640  	function write_table($table_name)
 641      {
 642          global $db;
 643          static $new_extract;
 644  
 645          if ($new_extract === null)
 646          {
 647              if ($db->sql_layer === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>='))
 648              {
 649                  $new_extract = true;
 650              }
 651              else
 652              {
 653                  $new_extract = false;
 654              }
 655          }
 656  
 657          if ($new_extract)
 658          {
 659              $this->new_write_table($table_name);
 660          }
 661          else
 662          {
 663              $this->old_write_table($table_name);
 664          }
 665      }
 666  
 667  	function write_data($table_name)
 668      {
 669          global $db;
 670          if ($db->sql_layer === 'mysqli')
 671          {
 672              $this->write_data_mysqli($table_name);
 673          }
 674          else
 675          {
 676              $this->write_data_mysql($table_name);
 677          }
 678      }
 679  
 680  	function write_data_mysqli($table_name)
 681      {
 682          global $db;
 683          $sql = "SELECT *
 684              FROM $table_name";
 685          $result = mysqli_query($db->db_connect_id, $sql, MYSQLI_USE_RESULT);
 686          if ($result != false)
 687          {
 688              $fields_cnt = mysqli_num_fields($result);
 689  
 690              // Get field information
 691              $field = mysqli_fetch_fields($result);
 692              $field_set = array();
 693  
 694              for ($j = 0; $j < $fields_cnt; $j++)
 695              {
 696                  $field_set[] = $field[$j]->name;
 697              }
 698  
 699              $search            = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
 700              $replace        = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
 701              $fields            = implode(', ', $field_set);
 702              $sql_data        = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
 703              $first_set        = true;
 704              $query_len        = 0;
 705              $max_len        = get_usable_memory();
 706  
 707              while ($row = mysqli_fetch_row($result))
 708              {
 709                  $values    = array();
 710                  if ($first_set)
 711                  {
 712                      $query = $sql_data . '(';
 713                  }
 714                  else
 715                  {
 716                      $query  .= ',(';
 717                  }
 718  
 719                  for ($j = 0; $j < $fields_cnt; $j++)
 720                  {
 721                      if (!isset($row[$j]) || is_null($row[$j]))
 722                      {
 723                          $values[$j] = 'NULL';
 724                      }
 725                      else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024))
 726                      {
 727                          $values[$j] = $row[$j];
 728                      }
 729                      else
 730                      {
 731                          $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
 732                      }
 733                  }
 734                  $query .= implode(', ', $values) . ')';
 735  
 736                  $query_len += strlen($query);
 737                  if ($query_len > $max_len)
 738                  {
 739                      $this->flush($query . ";\n\n");
 740                      $query = '';
 741                      $query_len = 0;
 742                      $first_set = true;
 743                  }
 744                  else
 745                  {
 746                      $first_set = false;
 747                  }
 748              }
 749              mysqli_free_result($result);
 750  
 751              // check to make sure we have nothing left to flush
 752              if (!$first_set && $query)
 753              {
 754                  $this->flush($query . ";\n\n");
 755              }
 756          }
 757      }
 758  
 759  	function write_data_mysql($table_name)
 760      {
 761          global $db;
 762          $sql = "SELECT *
 763              FROM $table_name";
 764          $result = mysql_unbuffered_query($sql, $db->db_connect_id);
 765  
 766          if ($result != false)
 767          {
 768              $fields_cnt = mysql_num_fields($result);
 769  
 770              // Get field information
 771              $field = array();
 772              for ($i = 0; $i < $fields_cnt; $i++)
 773              {
 774                  $field[] = mysql_fetch_field($result, $i);
 775              }
 776              $field_set = array();
 777  
 778              for ($j = 0; $j < $fields_cnt; $j++)
 779              {
 780                  $field_set[] = $field[$j]->name;
 781              }
 782  
 783              $search            = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
 784              $replace        = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
 785              $fields            = implode(', ', $field_set);
 786              $sql_data        = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
 787              $first_set        = true;
 788              $query_len        = 0;
 789              $max_len        = get_usable_memory();
 790  
 791              while ($row = mysql_fetch_row($result))
 792              {
 793                  $values = array();
 794                  if ($first_set)
 795                  {
 796                      $query = $sql_data . '(';
 797                  }
 798                  else
 799                  {
 800                      $query  .= ',(';
 801                  }
 802  
 803                  for ($j = 0; $j < $fields_cnt; $j++)
 804                  {
 805                      if (!isset($row[$j]) || is_null($row[$j]))
 806                      {
 807                          $values[$j] = 'NULL';
 808                      }
 809                      else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp'))
 810                      {
 811                          $values[$j] = $row[$j];
 812                      }
 813                      else
 814                      {
 815                          $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
 816                      }
 817                  }
 818                  $query .= implode(', ', $values) . ')';
 819  
 820                  $query_len += strlen($query);
 821                  if ($query_len > $max_len)
 822                  {
 823                      $this->flush($query . ";\n\n");
 824                      $query = '';
 825                      $query_len = 0;
 826                      $first_set = true;
 827                  }
 828                  else
 829                  {
 830                      $first_set = false;
 831                  }
 832              }
 833              mysql_free_result($result);
 834  
 835              // check to make sure we have nothing left to flush
 836              if (!$first_set && $query)
 837              {
 838                  $this->flush($query . ";\n\n");
 839              }
 840          }
 841      }
 842  
 843  	function new_write_table($table_name)
 844      {
 845          global $db;
 846  
 847          $sql = 'SHOW CREATE TABLE ' . $table_name;
 848          $result = $db->sql_query($sql);
 849          $row = $db->sql_fetchrow($result);
 850  
 851          $sql_data = '# Table: ' . $table_name . "\n";
 852          $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
 853          $this->flush($sql_data . $row['Create Table'] . ";\n\n");
 854  
 855          $db->sql_freeresult($result);
 856      }
 857  
 858  	function old_write_table($table_name)
 859      {
 860          global $db;
 861  
 862          $sql_data = '# Table: ' . $table_name . "\n";
 863          $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
 864          $sql_data .= "CREATE TABLE $table_name(\n";
 865          $rows = array();
 866  
 867          $sql = "SHOW FIELDS
 868              FROM $table_name";
 869          $result = $db->sql_query($sql);
 870  
 871          while ($row = $db->sql_fetchrow($result))
 872          {
 873              $line = '   ' . $row['Field'] . ' ' . $row['Type'];
 874  
 875              if (!is_null($row['Default']))
 876              {
 877                  $line .= " DEFAULT '{$row['Default']}'";
 878              }
 879  
 880              if ($row['Null'] != 'YES')
 881              {
 882                  $line .= ' NOT NULL';
 883              }
 884  
 885              if ($row['Extra'] != '')
 886              {
 887                  $line .= ' ' . $row['Extra'];
 888              }
 889  
 890              $rows[] = $line;
 891          }
 892          $db->sql_freeresult($result);
 893  
 894          $sql = "SHOW KEYS
 895              FROM $table_name";
 896  
 897          $result = $db->sql_query($sql);
 898  
 899          $index = array();
 900          while ($row = $db->sql_fetchrow($result))
 901          {
 902              $kname = $row['Key_name'];
 903  
 904              if ($kname != 'PRIMARY')
 905              {
 906                  if ($row['Non_unique'] == 0)
 907                  {
 908                      $kname = "UNIQUE|$kname";
 909                  }
 910              }
 911  
 912              if ($row['Sub_part'])
 913              {
 914                  $row['Column_name'] .= '(' . $row['Sub_part'] . ')';
 915              }
 916              $index[$kname][] = $row['Column_name'];
 917          }
 918          $db->sql_freeresult($result);
 919  
 920          foreach ($index as $key => $columns)
 921          {
 922              $line = '   ';
 923  
 924              if ($key == 'PRIMARY')
 925              {
 926                  $line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')';
 927              }
 928              else if (strpos($key, 'UNIQUE') === 0)
 929              {
 930                  $line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')';
 931              }
 932              else if (strpos($key, 'FULLTEXT') === 0)
 933              {
 934                  $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')';
 935              }
 936              else
 937              {
 938                  $line .= "KEY $key (" . implode(', ', $columns) . ')';
 939              }
 940  
 941              $rows[] = $line;
 942          }
 943  
 944          $sql_data .= implode(",\n", $rows);
 945          $sql_data .= "\n);\n\n";
 946  
 947          $this->flush($sql_data);
 948      }
 949  }
 950  
 951  /**
 952  * @package acp
 953  */
 954  class sqlite_extractor extends base_extractor
 955  {
 956  	function write_start($prefix)
 957      {
 958          $sql_data = "--\n";
 959          $sql_data .= "-- phpBB Backup Script\n";
 960          $sql_data .= "-- Dump of tables for $prefix\n";
 961          $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
 962          $sql_data .= "--\n";
 963          $sql_data .= "BEGIN TRANSACTION;\n";
 964          $this->flush($sql_data);
 965      }
 966  
 967  	function write_table($table_name)
 968      {
 969          global $db;
 970          $sql_data = '-- Table: ' . $table_name . "\n";
 971          $sql_data .= "DROP TABLE $table_name;\n";
 972  
 973          $sql = "SELECT sql
 974              FROM sqlite_master
 975              WHERE type = 'table'
 976                  AND name = '" . $db->sql_escape($table_name) . "'
 977              ORDER BY type DESC, name;";
 978          $result = $db->sql_query($sql);
 979          $row = $db->sql_fetchrow($result);
 980          $db->sql_freeresult($result);
 981  
 982          // Create Table
 983          $sql_data .= $row['sql'] . ";\n";
 984  
 985          $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');");
 986  
 987          $ar = array();
 988          while ($row = $db->sql_fetchrow($result))
 989          {
 990              $ar[] = $row;
 991          }
 992          $db->sql_freeresult($result);
 993  
 994          foreach ($ar as $value)
 995          {
 996              if (strpos($value['name'], 'autoindex') !== false)
 997              {
 998                  continue;
 999              }
1000  
1001              $result = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($value['name']) . "');");
1002  
1003              $fields = array();
1004              while ($row = $db->sql_fetchrow($result))
1005              {
1006                  $fields[] = $row['name'];
1007              }
1008              $db->sql_freeresult($result);
1009  
1010              $sql_data .= 'CREATE ' . ($value['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $value['name'] . ' on ' . $table_name . ' (' . implode(', ', $fields) . ");\n";
1011          }
1012  
1013          $this->flush($sql_data . "\n");
1014      }
1015  
1016  	function write_data($table_name)
1017      {
1018          global $db;
1019          static $proper;
1020  
1021          if (is_null($proper))
1022          {
1023              $proper = version_compare(PHP_VERSION, '5.1.3', '>=');
1024          }
1025  
1026          if ($proper)
1027          {
1028              $col_types = sqlite_fetch_column_types($db->db_connect_id, $table_name);
1029          }
1030          else
1031          {
1032              $sql = "SELECT sql
1033                  FROM sqlite_master
1034                  WHERE type = 'table'
1035                      AND name = '" . $table_name . "'";
1036              $table_data = sqlite_single_query($db->db_connect_id, $sql);
1037              $table_data = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', '', $table_data);
1038              $table_data = trim($table_data);
1039  
1040              preg_match('#\((.*)\)#s', $table_data, $matches);
1041  
1042              $table_cols = explode(',', trim($matches[1]));
1043              foreach ($table_cols as $declaration)
1044              {
1045                  $entities = preg_split('#\s+#', trim($declaration));
1046                  $column_name = preg_replace('/"?([^"]+)"?/', '\1', $entities[0]);
1047  
1048                  // Hit a primary key, those are not what we need :D
1049                  if (empty($entities[1]) || (strtolower($entities[0]) === 'primary' && strtolower($entities[1]) === 'key'))
1050                  {
1051                      continue;
1052                  }
1053                  $col_types[$column_name] = $entities[1];
1054              }
1055          }
1056  
1057          $sql = "SELECT *
1058              FROM $table_name";
1059          $result = sqlite_unbuffered_query($db->db_connect_id, $sql);
1060          $rows = sqlite_fetch_all($result, SQLITE_ASSOC);
1061          $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES (';
1062          foreach ($rows as $row)
1063          {
1064              foreach ($row as $column_name => $column_data)
1065              {
1066                  if (is_null($column_data))
1067                  {
1068                      $row[$column_name] = 'NULL';
1069                  }
1070                  else if ($column_data == '')
1071                  {
1072                      $row[$column_name] = "''";
1073                  }
1074                  else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false)
1075                  {
1076                      $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data));
1077                  }
1078              }
1079              $this->flush($sql_insert . implode(', ', $row) . ");\n");
1080          }
1081      }
1082  
1083  	function write_end()
1084      {
1085          $this->flush("COMMIT;\n");
1086          parent::write_end();
1087      }
1088  }
1089  
1090  /**
1091  * @package acp
1092  */
1093  class postgres_extractor extends base_extractor
1094  {
1095  	function write_start($prefix)
1096      {
1097          $sql_data = "--\n";
1098          $sql_data .= "-- phpBB Backup Script\n";
1099          $sql_data .= "-- Dump of tables for $prefix\n";
1100          $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
1101          $sql_data .= "--\n";
1102          $sql_data .= "BEGIN TRANSACTION;\n";
1103          $this->flush($sql_data);
1104      }
1105  
1106  	function write_table($table_name)
1107      {
1108          global $db;
1109          static $domains_created = array();
1110  
1111          $sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default
1112              FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b
1113              WHERE a.domain_name = b.domain_name
1114                  AND b.table_name = '{$table_name}'";
1115          $result = $db->sql_query($sql);
1116          while ($row = $db->sql_fetchrow($result))
1117          {
1118              if (empty($domains_created[$row['domain_name']]))
1119              {
1120                  $domains_created[$row['domain_name']] = true;
1121                  //$sql_data = "DROP DOMAIN {$row['domain_name']};\n";
1122                  $sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}";
1123                  if (!empty($row['character_maximum_length']))
1124                  {
1125                      $sql_data .= '(' . $row['character_maximum_length'] . ')';
1126                  }
1127                  $sql_data .= ' NOT NULL';
1128                  if (!empty($row['domain_default']))
1129                  {
1130                      $sql_data .= ' DEFAULT ' . $row['domain_default'];
1131                  }
1132                  $this->flush($sql_data . ";\n");
1133              }
1134          }
1135  
1136          $sql_data = '-- Table: ' . $table_name . "\n";
1137          $sql_data .= "DROP TABLE $table_name;\n";
1138          // PGSQL does not "tightly" bind sequences and tables, we must guess...
1139          $sql = "SELECT relname
1140              FROM pg_class
1141              WHERE relkind = 'S'
1142                  AND relname = '{$table_name}_seq'";
1143          $result = $db->sql_query($sql);
1144          // We don't even care about storing the results. We already know the answer if we get rows back.
1145          if ($db->sql_fetchrow($result))
1146          {
1147              $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n";
1148              $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n";
1149          }
1150          $db->sql_freeresult($result);
1151  
1152          $field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull
1153              FROM pg_class c, pg_attribute a, pg_type t
1154              WHERE c.relname = '" . $db->sql_escape($table_name) . "'
1155                  AND a.attnum > 0
1156                  AND a.attrelid = c.oid
1157                  AND a.atttypid = t.oid
1158              ORDER BY a.attnum";
1159          $result = $db->sql_query($field_query);
1160  
1161          $sql_data .= "CREATE TABLE $table_name(\n";
1162          $lines = array();
1163          while ($row = $db->sql_fetchrow($result))
1164          {
1165              // Get the data from the table
1166              $sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
1167                  FROM pg_attrdef d, pg_class c
1168                  WHERE (c.relname = '" . $db->sql_escape($table_name) . "')
1169                      AND (c.oid = d.adrelid)
1170                      AND d.adnum = " . $row['attnum'];
1171              $def_res = $db->sql_query($sql_get_default);
1172              $def_row = $db->sql_fetchrow($def_res);
1173              $db->sql_freeresult($def_res);
1174  
1175              if (empty($def_row))
1176              {
1177                  unset($row['rowdefault']);
1178              }
1179              else
1180              {
1181                  $row['rowdefault'] = $def_row['rowdefault'];
1182              }
1183  
1184              if ($row['type'] == 'bpchar')
1185              {
1186                  // Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement.
1187                  $row['type'] = 'char';
1188              }
1189  
1190              $line = '  ' . $row['field'] . ' ' . $row['type'];
1191  
1192              if (strpos($row['type'], 'char') !== false)
1193              {
1194                  if ($row['lengthvar'] > 0)
1195                  {
1196                      $line .= '(' . ($row['lengthvar'] - 4) . ')';
1197                  }
1198              }
1199  
1200              if (strpos($row['type'], 'numeric') !== false)
1201              {
1202                  $line .= '(';
1203                  $line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff));
1204                  $line .= ')';
1205              }
1206  
1207              if (isset($row['rowdefault']))
1208              {
1209                  $line .= ' DEFAULT ' . $row['rowdefault'];
1210              }
1211  
1212              if ($row['notnull'] == 't')
1213              {
1214                  $line .= ' NOT NULL';
1215              }
1216  
1217              $lines[] = $line;
1218          }
1219          $db->sql_freeresult($result);
1220  
1221  
1222          // Get the listing of primary keys.
1223          $sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key
1224              FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia
1225              WHERE (bc.oid = i.indrelid)
1226                  AND (ic.oid = i.indexrelid)
1227                  AND (ia.attrelid = i.indexrelid)
1228                  AND    (ta.attrelid = bc.oid)
1229                  AND (bc.relname = '" . $db->sql_escape($table_name) . "')
1230                  AND (ta.attrelid = i.indrelid)
1231                  AND (ta.attnum = i.indkey[ia.attnum-1])
1232              ORDER BY index_name, tab_name, column_name";
1233  
1234          $result = $db->sql_query($sql_pri_keys);
1235  
1236          $index_create = $index_rows = $primary_key = array();
1237  
1238          // We do this in two steps. It makes placing the comma easier
1239          while ($row = $db->sql_fetchrow($result))
1240          {
1241              if ($row['primary_key'] == 't')
1242              {
1243                  $primary_key[] = $row['column_name'];
1244                  $primary_key_name = $row['index_name'];
1245              }
1246              else
1247              {
1248                  // We have to store this all this info because it is possible to have a multi-column key...
1249                  // we can loop through it again and build the statement
1250                  $index_rows[$row['index_name']]['table'] = $table_name;
1251                  $index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false;
1252                  $index_rows[$row['index_name']]['column_names'][] = $row['column_name'];
1253              }
1254          }
1255          $db->sql_freeresult($result);
1256  
1257          if (!empty($index_rows))
1258          {
1259              foreach ($index_rows as $idx_name => $props)
1260              {
1261                  $index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");";
1262              }
1263          }
1264  
1265          if (!empty($primary_key))
1266          {
1267              $lines[] = "  CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")";
1268          }
1269  
1270          // Generate constraint clauses for CHECK constraints
1271          $sql_checks = "SELECT conname as index_name, consrc
1272              FROM pg_constraint, pg_class bc
1273              WHERE conrelid = bc.oid
1274                  AND bc.relname = '" . $db->sql_escape($table_name) . "'
1275                  AND NOT EXISTS (
1276                      SELECT *
1277                          FROM pg_constraint as c, pg_inherits as i
1278                          WHERE i.inhrelid = pg_constraint.conrelid
1279                              AND c.conname = pg_constraint.conname
1280                              AND c.consrc = pg_constraint.consrc
1281                              AND c.conrelid = i.inhparent
1282                  )";
1283          $result = $db->sql_query($sql_checks);
1284  
1285          // Add the constraints to the sql file.
1286          while ($row = $db->sql_fetchrow($result))
1287          {
1288              if (!is_null($row['consrc']))
1289              {
1290                  $lines[] = '  CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc'];
1291              }
1292          }
1293          $db->sql_freeresult($result);
1294  
1295          $sql_data .= implode(", \n", $lines);
1296          $sql_data .= "\n);\n";
1297  
1298          if (!empty($index_create))
1299          {
1300              $sql_data .= implode("\n", $index_create) . "\n\n";
1301          }
1302          $this->flush($sql_data);
1303      }
1304  
1305  	function write_data($table_name)
1306      {
1307          global $db;
1308          // Grab all of the data from current table.
1309          $sql = "SELECT *
1310              FROM $table_name";
1311          $result = $db->sql_query($sql);
1312  
1313          $i_num_fields = pg_num_fields($result);
1314          $seq = '';
1315  
1316          for ($i = 0; $i < $i_num_fields; $i++)
1317          {
1318              $ary_type[] = pg_field_type($result, $i);
1319              $ary_name[] = pg_field_name($result, $i);
1320  
1321  
1322              $sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
1323                  FROM pg_attrdef d, pg_class c
1324                  WHERE (c.relname = '{$table_name}')
1325                      AND (c.oid = d.adrelid)
1326                      AND d.adnum = " . strval($i + 1);
1327              $result2 = $db->sql_query($sql);
1328              if ($row = $db->sql_fetchrow($result2))
1329              {
1330                  // Determine if we must reset the sequences
1331                  if (strpos($row['rowdefault'], "nextval('") === 0)
1332                  {
1333                      $seq .= "SELECT SETVAL('{$table_name}_seq',(select case when max({$ary_name[$i]})>0 then max({$ary_name[$i]})+1 else 1 end FROM {$table_name}));\n";
1334                  }
1335              }
1336          }
1337  
1338          $this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n");
1339          while ($row = $db->sql_fetchrow($result))
1340          {
1341              $schema_vals = array();
1342  
1343              // Build the SQL statement to recreate the data.
1344              for ($i = 0; $i < $i_num_fields; $i++)
1345              {
1346                  $str_val = $row[$ary_name[$i]];
1347  
1348                  if (preg_match('#char|text|bool|bytea#i', $ary_type[$i]))
1349                  {
1350                      $str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val));
1351                      $str_empty = '';
1352                  }
1353                  else
1354                  {
1355                      $str_empty = '\N';
1356                  }
1357  
1358                  if (empty($str_val) && $str_val !== '0')
1359                  {
1360                      $str_val = $str_empty;
1361                  }
1362  
1363                  $schema_vals[] = $str_val;
1364              }
1365  
1366              // Take the ordered fields and their associated data and build it
1367              // into a valid sql statement to recreate that field in the data.
1368              $this->flush(implode("\t", $schema_vals) . "\n");
1369          }
1370          $db->sql_freeresult($result);
1371          $this->flush("\\.\n");
1372  
1373          // Write out the sequence statements
1374          $this->flush($seq);
1375      }
1376  
1377  	function write_end()
1378      {
1379          $this->flush("COMMIT;\n");
1380          parent::write_end();
1381      }
1382  }
1383  
1384  /**
1385  * @package acp
1386  */
1387  class mssql_extractor extends base_extractor
1388  {
1389  	function write_end()
1390      {
1391          $this->flush("COMMIT\nGO\n");
1392          parent::write_end();
1393      }
1394  
1395  	function write_start($prefix)
1396      {
1397          $sql_data = "--\n";
1398          $sql_data .= "-- phpBB Backup Script\n";
1399          $sql_data .= "-- Dump of tables for $prefix\n";
1400          $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
1401          $sql_data .= "--\n";
1402          $sql_data .= "BEGIN TRANSACTION\n";
1403          $sql_data .= "GO\n";
1404          $this->flush($sql_data);
1405      }
1406  
1407  	function write_table($table_name)
1408      {
1409          global $db;
1410          $sql_data = '-- Table: ' . $table_name . "\n";
1411          $sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n";
1412          $sql_data .= "DROP TABLE $table_name;\n";
1413          $sql_data .= "GO\n";
1414          $sql_data .= "\nCREATE TABLE [$table_name] (\n";
1415          $rows = array();
1416  
1417          $text_flag = false;
1418  
1419          $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY
1420              FROM INFORMATION_SCHEMA.COLUMNS
1421              WHERE TABLE_NAME = '$table_name'";
1422          $result = $db->sql_query($sql);
1423  
1424          while ($row = $db->sql_fetchrow($result))
1425          {
1426              $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]";
1427  
1428              if ($row['DATA_TYPE'] == 'text')
1429              {
1430                  $text_flag = true;
1431              }
1432  
1433              if ($row['IS_IDENTITY'])
1434              {
1435                  $line .= ' IDENTITY (1 , 1)';
1436              }
1437  
1438              if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text')
1439              {
1440                  $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')';
1441              }
1442  
1443              if ($row['IS_NULLABLE'] == 'YES')
1444              {
1445                  $line .= ' NULL';
1446              }
1447              else
1448              {
1449                  $line .= ' NOT NULL';
1450              }
1451  
1452              if ($row['COLUMN_DEFAULT'])
1453              {
1454                  $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT'];
1455              }
1456  
1457              $rows[] = $line;
1458          }
1459          $db->sql_freeresult($result);
1460  
1461          $sql_data .= implode(",\n", $rows);
1462          $sql_data .= "\n) ON [PRIMARY]";
1463  
1464          if ($text_flag)
1465          {
1466              $sql_data .= " TEXTIMAGE_ON [PRIMARY]";
1467          }
1468  
1469          $sql_data .= "\nGO\n\n";
1470          $rows = array();
1471  
1472          $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME
1473              FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
1474              WHERE TABLE_NAME = '$table_name'";
1475          $result = $db->sql_query($sql);
1476          while ($row = $db->sql_fetchrow($result))
1477          {
1478              if (!sizeof($rows))
1479              {
1480                  $sql_data .= "ALTER TABLE [$table_name] WITH NOCHECK ADD\n";
1481                  $sql_data .= "\tCONSTRAINT [{$row['CONSTRAINT_NAME']}] PRIMARY KEY  CLUSTERED \n\t(\n";
1482              }
1483              $rows[] = "\t\t[{$row['COLUMN_NAME']}]";
1484          }
1485          if (sizeof($rows))
1486          {
1487              $sql_data .= implode(",\n", $rows);
1488              $sql_data .= "\n\t)  ON [PRIMARY] \nGO\n";
1489          }
1490          $db->sql_freeresult($result);
1491  
1492          $index = array();
1493          $sql = "EXEC sp_statistics '$table_name'";
1494          $result = $db->sql_query($sql);
1495          while ($row = $db->sql_fetchrow($result))
1496          {
1497              if ($row['TYPE'] == 3)
1498              {
1499                  $index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']';
1500              }
1501          }
1502          $db->sql_freeresult($result);
1503  
1504          foreach ($index as $index_name => $column_name)
1505          {
1506              $index[$index_name] = implode(', ', $column_name);
1507          }
1508  
1509          foreach ($index as $index_name => $columns)
1510          {
1511              $sql_data .= "\nCREATE  INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n";
1512          }
1513          $this->flush($sql_data);
1514      }
1515  
1516  	function write_data($table_name)
1517      {
1518          global $db;
1519  
1520          if ($db->sql_layer === 'mssql')
1521          {
1522              $this->write_data_mssql($table_name);
1523          }
1524          else if($db->sql_layer === 'mssqlnative')
1525          {
1526              $this->write_data_mssqlnative($table_name);
1527          }
1528          else
1529          {
1530              $this->write_data_odbc($table_name);
1531          }
1532      }
1533  
1534  	function write_data_mssql($table_name)
1535      {
1536          global $db;
1537          $ary_type = $ary_name = array();
1538          $ident_set = false;
1539          $sql_data = '';
1540  
1541          // Grab all of the data from current table.
1542          $sql = "SELECT *
1543              FROM $table_name";
1544          $result = $db->sql_query($sql);
1545  
1546          $retrieved_data = mssql_num_rows($result);
1547  
1548          $i_num_fields = mssql_num_fields($result);
1549  
1550          for ($i = 0; $i < $i_num_fields; $i++)
1551          {
1552              $ary_type[$i] = mssql_field_type($result, $i);
1553              $ary_name[$i] = mssql_field_name($result, $i);
1554          }
1555  
1556          if ($retrieved_data)
1557          {
1558              $sql = "SELECT 1 as has_identity
1559                  FROM INFORMATION_SCHEMA.COLUMNS
1560                  WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
1561              $result2 = $db->sql_query($sql);
1562              $row2 = $db->sql_fetchrow($result2);
1563              if (!empty($row2['has_identity']))
1564              {
1565                  $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
1566                  $ident_set = true;
1567              }
1568              $db->sql_freeresult($result2);
1569          }
1570  
1571          while ($row = $db->sql_fetchrow($result))
1572          {
1573              $schema_vals = $schema_fields = array();
1574  
1575              // Build the SQL statement to recreate the data.
1576              for ($i = 0; $i < $i_num_fields; $i++)
1577              {
1578                  $str_val = $row[$ary_name[$i]];
1579  
1580                  if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
1581                  {
1582                      $str_quote = '';
1583                      $str_empty = "''";
1584                      $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
1585                  }
1586                  else if (preg_match('#date|timestamp#i', $ary_type[$i]))
1587                  {
1588                      if (empty($str_val))
1589                      {
1590                          $str_quote = '';
1591                      }
1592                      else
1593                      {
1594                          $str_quote = "'";
1595                      }
1596                  }
1597                  else
1598                  {
1599                      $str_quote = '';
1600                      $str_empty = 'NULL';
1601                  }
1602  
1603                  if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
1604                  {
1605                      $str_val = $str_empty;
1606                  }
1607  
1608                  $schema_vals[$i] = $str_quote . $str_val . $str_quote;
1609                  $schema_fields[$i] = $ary_name[$i];
1610              }
1611  
1612              // Take the ordered fields and their associated data and build it
1613              // into a valid sql statement to recreate that field in the data.
1614              $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
1615  
1616              $this->flush($sql_data);
1617              $sql_data = '';
1618          }
1619          $db->sql_freeresult($result);
1620  
1621          if ($retrieved_data && $ident_set)
1622          {
1623              $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
1624          }
1625          $this->flush($sql_data);
1626      }
1627      
1628  	function write_data_mssqlnative($table_name)
1629      {
1630          global $db;
1631          $ary_type = $ary_name = array();
1632          $ident_set = false;
1633          $sql_data = '';
1634  
1635          // Grab all of the data from current table.
1636          $sql = "SELECT * FROM $table_name";
1637          $db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC));
1638          $result = $db->sql_query($sql);
1639  
1640          $retrieved_data = $db->mssqlnative_num_rows($result);
1641  
1642          if (!$retrieved_data)
1643          {
1644              $db->sql_freeresult($result);
1645              return;
1646          }
1647  
1648          $sql = "SELECT * FROM $table_name";
1649          $result_fields = $db->sql_query_limit($sql, 1);
1650  
1651          $row = new result_mssqlnative($result_fields);
1652          $i_num_fields = $row->num_fields();
1653          
1654          for ($i = 0; $i < $i_num_fields; $i++)
1655          {
1656              $ary_type[$i] = $row->field_type($i);
1657              $ary_name[$i] = $row->field_name($i);
1658          }
1659          $db->sql_freeresult($result_fields);
1660  
1661          $sql = "SELECT 1 as has_identity
1662              FROM INFORMATION_SCHEMA.COLUMNS
1663              WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
1664          $result2 = $db->sql_query($sql);
1665          $row2 = $db->sql_fetchrow($result2);
1666          
1667          if (!empty($row2['has_identity']))
1668          {
1669              $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
1670              $ident_set = true;
1671          }
1672          $db->sql_freeresult($result2);
1673  
1674          while ($row = $db->sql_fetchrow($result))
1675          {
1676              $schema_vals = $schema_fields = array();
1677  
1678              // Build the SQL statement to recreate the data.
1679              for ($i = 0; $i < $i_num_fields; $i++)
1680              {
1681                  $str_val = $row[$ary_name[$i]];
1682  
1683                  // defaults to type number - better quote just to be safe, so check for is_int too
1684                  if (is_int($ary_type[$i]) || preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
1685                  {
1686                      $str_quote = '';
1687                      $str_empty = "''";
1688                      $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
1689                  }
1690                  else if (preg_match('#date|timestamp#i', $ary_type[$i]))
1691                  {
1692                      if (empty($str_val))
1693                      {
1694                          $str_quote = '';
1695                      }
1696                      else
1697                      {
1698                          $str_quote = "'";
1699                      }
1700                  }
1701                  else
1702                  {
1703                      $str_quote = '';
1704                      $str_empty = 'NULL';
1705                  }
1706  
1707                  if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
1708                  {
1709                      $str_val = $str_empty;
1710                  }
1711  
1712                  $schema_vals[$i] = $str_quote . $str_val . $str_quote;
1713                  $schema_fields[$i] = $ary_name[$i];
1714              }
1715  
1716              // Take the ordered fields and their associated data and build it
1717              // into a valid sql statement to recreate that field in the data.
1718              $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
1719  
1720              $this->flush($sql_data);
1721              $sql_data = '';
1722          }
1723          $db->sql_freeresult($result);
1724  
1725          if ($ident_set)
1726          {
1727              $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
1728          }
1729          $this->flush($sql_data);
1730      }    
1731      
1732  	function write_data_odbc($table_name)
1733      {
1734          global $db;
1735          $ary_type = $ary_name = array();
1736          $ident_set = false;
1737          $sql_data = '';
1738  
1739          // Grab all of the data from current table.
1740          $sql = "SELECT *
1741              FROM $table_name";
1742          $result = $db->sql_query($sql);
1743  
1744          $retrieved_data = odbc_num_rows($result);
1745  
1746          if ($retrieved_data)
1747          {
1748              $sql = "SELECT 1 as has_identity
1749                  FROM INFORMATION_SCHEMA.COLUMNS
1750                  WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
1751              $result2 = $db->sql_query($sql);
1752              $row2 = $db->sql_fetchrow($result2);
1753              if (!empty($row2['has_identity']))
1754              {
1755                  $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
1756                  $ident_set = true;
1757              }
1758              $db->sql_freeresult($result2);
1759          }
1760  
1761          $i_num_fields = odbc_num_fields($result);
1762  
1763          for ($i = 0; $i < $i_num_fields; $i++)
1764          {
1765              $ary_type[$i] = odbc_field_type($result, $i + 1);
1766              $ary_name[$i] = odbc_field_name($result, $i + 1);
1767          }
1768  
1769          while ($row = $db->sql_fetchrow($result))
1770          {
1771              $schema_vals = $schema_fields = array();
1772  
1773              // Build the SQL statement to recreate the data.
1774              for ($i = 0; $i < $i_num_fields; $i++)
1775              {
1776                  $str_val = $row[$ary_name[$i]];
1777  
1778                  if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
1779                  {
1780                      $str_quote = '';
1781                      $str_empty = "''";
1782                      $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
1783                  }
1784                  else if (preg_match('#date|timestamp#i', $ary_type[$i]))
1785                  {
1786                      if (empty($str_val))
1787                      {
1788                          $str_quote = '';
1789                      }
1790                      else
1791                      {
1792                          $str_quote = "'";
1793                      }
1794                  }
1795                  else
1796                  {
1797                      $str_quote = '';
1798                      $str_empty = 'NULL';
1799                  }
1800  
1801                  if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
1802                  {
1803                      $str_val = $str_empty;
1804                  }
1805  
1806                  $schema_vals[$i] = $str_quote . $str_val . $str_quote;
1807                  $schema_fields[$i] = $ary_name[$i];
1808              }
1809  
1810              // Take the ordered fields and their associated data and build it
1811              // into a valid sql statement to recreate that field in the data.
1812              $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
1813  
1814              $this->flush($sql_data);
1815  
1816              $sql_data = '';
1817  
1818          }
1819          $db->sql_freeresult($result);
1820  
1821          if ($retrieved_data && $ident_set)
1822          {
1823              $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
1824          }
1825          $this->flush($sql_data);
1826      }
1827  
1828  }
1829  
1830  /**
1831  * @package acp
1832  */
1833  class oracle_extractor extends base_extractor
1834  {
1835  	function write_table($table_name)
1836      {
1837          global $db;
1838          $sql_data = '-- Table: ' . $table_name . "\n";
1839          $sql_data .= "DROP TABLE $table_name\n/\n";
1840          $sql_data .= "\nCREATE TABLE $table_name (\n";
1841  
1842          $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT
1843              FROM ALL_TAB_COLS
1844              WHERE table_name = '{$table_name}'";
1845          $result = $db->sql_query($sql);
1846  
1847          $rows = array();
1848          while ($row = $db->sql_fetchrow($result))
1849          {
1850              $line = '  "' . $row['column_name'] . '" ' . $row['data_type'];
1851  
1852              if ($row['data_type'] !== 'CLOB')
1853              {
1854                  if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR')
1855                  {
1856                      $line .= '(' . $row['data_precision'] . ')';
1857                  }
1858                  else
1859                  {
1860                      $line .= '(' . $row['data_length'] . ')';
1861                  }
1862              }
1863  
1864              if (!empty($row['data_default']))
1865              {
1866                  $line .= ' DEFAULT ' . $row['data_default'];
1867              }
1868  
1869              if ($row['nullable'] == 'N')
1870              {
1871                  $line .= ' NOT NULL';
1872              }
1873              $rows[] = $line;
1874          }
1875          $db->sql_freeresult($result);
1876  
1877          $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
1878              FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
1879              WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
1880                  AND B.CONSTRAINT_TYPE = 'P'
1881                  AND A.TABLE_NAME = '{$table_name}'";
1882          $result = $db->sql_query($sql);
1883  
1884          $primary_key = array();
1885          $contraint_name = '';
1886          while ($row = $db->sql_fetchrow($result))
1887          {
1888              $constraint_name = '"' . $row['constraint_name'] . '"';
1889              $primary_key[] = '"' . $row['column_name'] . '"';
1890          }
1891          $db->sql_freeresult($result);
1892  
1893          if (sizeof($primary_key))
1894          {
1895              $rows[] = "  CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')';
1896          }
1897  
1898          $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
1899              FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
1900              WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
1901                  AND B.CONSTRAINT_TYPE = 'U'
1902                  AND A.TABLE_NAME = '{$table_name}'";
1903          $result = $db->sql_query($sql);
1904  
1905          $unique = array();
1906          $contraint_name = '';
1907          while ($row = $db->sql_fetchrow($result))
1908          {
1909              $constraint_name = '"' . $row['constraint_name'] . '"';
1910              $unique[] = '"' . $row['column_name'] . '"';
1911          }
1912          $db->sql_freeresult($result);
1913  
1914          if (sizeof($unique))
1915          {
1916              $rows[] = "  CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')';
1917          }
1918  
1919          $sql_data .= implode(",\n", $rows);
1920          $sql_data .= "\n)\n/\n";
1921  
1922          $sql = "SELECT A.REFERENCED_NAME, C.*
1923              FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C
1924              WHERE A.REFERENCED_TYPE = 'SEQUENCE'
1925                  AND A.NAME = B.TRIGGER_NAME
1926                  AND B.TABLE_NAME = '{$table_name}'
1927                  AND C.SEQUENCE_NAME = A.REFERENCED_NAME";
1928          $result = $db->sql_query($sql);
1929  
1930          $type = request_var('type', '');
1931  
1932          while ($row = $db->sql_fetchrow($result))
1933          {
1934              $sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n";
1935              $sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\"";
1936  
1937              if ($type == 'full')
1938              {
1939                  $sql_data .= ' START WITH ' . $row['last_number'];
1940              }
1941  
1942              $sql_data .= "\n/\n";
1943          }
1944          $db->sql_freeresult($result);
1945  
1946          $sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY
1947              FROM USER_TRIGGERS
1948              WHERE TABLE_NAME = '{$table_name}'";
1949          $result = $db->sql_query($sql);
1950          while ($row = $db->sql_fetchrow($result))
1951          {
1952              $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n";
1953          }
1954          $db->sql_freeresult($result);
1955  
1956          $sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME
1957              FROM USER_INDEXES A, USER_IND_COLUMNS B
1958              WHERE A.UNIQUENESS = 'NONUNIQUE'
1959                  AND A.INDEX_NAME = B.INDEX_NAME
1960                  AND B.TABLE_NAME = '{$table_name}'";
1961          $result = $db->sql_query($sql);
1962  
1963          $index = array();
1964  
1965          while ($row = $db->sql_fetchrow($result))
1966          {
1967              $index[$row['index_name']][] = $row['column_name'];
1968          }
1969  
1970          foreach ($index as $index_name => $column_names)
1971          {
1972              $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n";
1973          }
1974          $db->sql_freeresult($result);
1975          $this->flush($sql_data);
1976      }
1977  
1978  	function write_data($table_name)
1979      {
1980          global $db;
1981          $ary_type = $ary_name = array();
1982  
1983          // Grab all of the data from current table.
1984          $sql = "SELECT *
1985              FROM $table_name";
1986          $result = $db->sql_query($sql);
1987  
1988          $i_num_fields = ocinumcols($result);
1989  
1990          for ($i = 0; $i < $i_num_fields; $i++)
1991          {
1992              $ary_type[$i] = ocicolumntype($result, $i + 1);
1993              $ary_name[$i] = ocicolumnname($result, $i + 1);
1994          }
1995  
1996          $sql_data = '';
1997  
1998          while ($row = $db->sql_fetchrow($result))
1999          {
2000              $schema_vals = $schema_fields = array();
2001  
2002              // Build the SQL statement to recreate the data.
2003              for ($i = 0; $i < $i_num_fields; $i++)
2004              {
2005                  // Oracle uses uppercase - we use lowercase
2006                  $str_val = $row[strtolower($ary_name[$i])];
2007  
2008                  if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i]))
2009                  {
2010                      $str_quote = '';
2011                      $str_empty = "''";
2012                      $str_val = sanitize_data_oracle($str_val);
2013                  }
2014                  else if (preg_match('#date|timestamp#i', $ary_type[$i]))
2015                  {
2016                      if (empty($str_val))
2017                      {
2018                          $str_quote = '';
2019                      }
2020                      else
2021                      {
2022                          $str_quote = "'";
2023                      }
2024                  }
2025                  else
2026                  {
2027                      $str_quote = '';
2028                      $str_empty = 'NULL';
2029                  }
2030  
2031                  if (empty($str_val) && $str_val !== '0')
2032                  {
2033                      $str_val = $str_empty;
2034                  }
2035  
2036                  $schema_vals[$i] = $str_quote . $str_val . $str_quote;
2037                  $schema_fields[$i] = '"' . $ary_name[$i] . '"';
2038              }
2039  
2040              // Take the ordered fields and their associated data and build it
2041              // into a valid sql statement to recreate that field in the data.
2042              $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n";
2043  
2044              $this->flush($sql_data);
2045          }
2046          $db->sql_freeresult($result);
2047      }
2048  
2049  	function write_start($prefix)
2050      {
2051          $sql_data = "--\n";
2052          $sql_data .= "-- phpBB Backup Script\n";
2053          $sql_data .= "-- Dump of tables for $prefix\n";
2054          $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
2055          $sql_data .= "--\n";
2056          $this->flush($sql_data);
2057      }
2058  }
2059  
2060  /**
2061  * @package acp
2062  */
2063  class firebird_extractor extends base_extractor
2064  {
2065  	function write_start($prefix)
2066      {
2067          $sql_data = "--\n";
2068          $sql_data .= "-- phpBB Backup Script\n";
2069          $sql_data .= "-- Dump of tables for $prefix\n";
2070          $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
2071          $sql_data .= "--\n";
2072          $this->flush($sql_data);
2073      }
2074  
2075  	function write_data($table_name)
2076      {
2077          global $db;
2078          $ary_type = $ary_name = array();
2079  
2080          // Grab all of the data from current table.
2081          $sql = "SELECT *
2082              FROM $table_name";
2083          $result = $db->sql_query($sql);
2084  
2085          $i_num_fields = ibase_num_fields($result);
2086  
2087          for ($i = 0; $i < $i_num_fields; $i++)
2088          {
2089              $info = ibase_field_info($result, $i);
2090              $ary_type[$i] = $info['type'];
2091              $ary_name[$i] = $info['name'];
2092          }
2093  
2094          while ($row = $db->sql_fetchrow($result))
2095          {
2096              $schema_vals = $schema_fields = array();
2097  
2098              // Build the SQL statement to recreate the data.
2099              for ($i = 0; $i < $i_num_fields; $i++)
2100              {
2101                  $str_val = $row[strtolower($ary_name[$i])];
2102  
2103                  if (preg_match('#char|text|bool|varbinary|blob#i', $ary_type[$i]))
2104                  {
2105                      $str_quote = '';
2106                      $str_empty = "''";
2107                      $str_val = sanitize_data_generic(str_replace("'", "''", $str_val));
2108                  }
2109                  else if (preg_match('#date|timestamp#i', $ary_type[$i]))
2110                  {
2111                      if (empty($str_val))
2112                      {
2113                          $str_quote = '';
2114                      }
2115                      else
2116                      {
2117                          $str_quote = "'";
2118                      }
2119                  }
2120                  else
2121                  {
2122                      $str_quote = '';
2123                      $str_empty = 'NULL';
2124                  }
2125  
2126                  if (empty($str_val) && $str_val !== '0')
2127                  {
2128                      $str_val = $str_empty;
2129                  }
2130  
2131                  $schema_vals[$i] = $str_quote . $str_val . $str_quote;
2132                  $schema_fields[$i] = '"' . $ary_name[$i] . '"';
2133              }
2134  
2135              // Take the ordered fields and their associated data and build it
2136              // into a valid sql statement to recreate that field in the data.
2137              $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n";
2138  
2139              $this->flush($sql_data);
2140          }
2141          $db->sql_freeresult($result);
2142      }
2143  
2144  	function write_table($table_name)
2145      {
2146          global $db;
2147  
2148          $sql_data = '-- Table: ' . $table_name . "\n";
2149          $sql_data .= "DROP TABLE $table_name;\n";
2150  
2151          $data_types = array(7 => 'SMALLINT', 8 => 'INTEGER', 10 => 'FLOAT', 12 => 'DATE', 13 => 'TIME', 14 => 'CHARACTER', 27 => 'DOUBLE PRECISION', 35 => 'TIMESTAMP', 37 => 'VARCHAR', 40 => 'CSTRING', 261 => 'BLOB', 701 => 'DECIMAL', 702 => 'NUMERIC');
2152  
2153          $sql_data .= "\nCREATE TABLE $table_name (\n";
2154  
2155          $sql = 'SELECT DISTINCT R.RDB$FIELD_NAME as FNAME, R.RDB$NULL_FLAG as NFLAG, R.RDB$DEFAULT_SOURCE as DSOURCE, F.RDB$FIELD_TYPE as FTYPE, F.RDB$FIELD_SUB_TYPE as STYPE, F.RDB$FIELD_LENGTH as FLEN
2156              FROM RDB$RELATION_FIELDS R
2157              JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME
2158              LEFT JOIN RDB$FIELD_DIMENSIONS D ON R.RDB$FIELD_SOURCE = D.RDB$FIELD_NAME
2159              WHERE F.RDB$SYSTEM_FLAG = 0
2160                  AND R.RDB$RELATION_NAME = \''. $table_name . '\'
2161              ORDER BY R.RDB$FIELD_POSITION';
2162          $result = $db->sql_query($sql);
2163  
2164          $rows = array();
2165          while ($row = $db->sql_fetchrow($result))
2166          {
2167              $line = "\t" . '"' . $row['fname'] . '" ' . $data_types[$row['ftype']];
2168  
2169              if ($row['ftype'] == 261 && $row['stype'] == 1)
2170              {
2171                  $line .= ' SUB_TYPE TEXT';
2172              }
2173  
2174              if ($row['ftype'] == 37 || $row['ftype'] == 14)
2175              {
2176                  $line .= ' (' . $row['flen'] . ')';
2177              }
2178  
2179              if (!empty($row['dsource']))
2180              {
2181                  $line .= ' ' . $row['dsource'];
2182              }
2183  
2184              if (!empty($row['nflag']))
2185              {
2186                  $line .= ' NOT NULL';
2187              }
2188              $rows[] = $line;
2189          }
2190          $db->sql_freeresult($result);
2191  
2192          $sql_data .= implode(",\n", $rows);
2193          $sql_data .= "\n);\n";
2194          $keys = array();
2195  
2196          $sql = 'SELECT I.RDB$FIELD_NAME as NAME
2197              FROM RDB$RELATION_CONSTRAINTS RC, RDB$INDEX_SEGMENTS I, RDB$INDICES IDX
2198              WHERE (I.RDB$INDEX_NAME = RC.RDB$INDEX_NAME)
2199                  AND (IDX.RDB$INDEX_NAME = RC.RDB$INDEX_NAME)
2200                  AND (RC.RDB$RELATION_NAME = \''. $table_name . '\')
2201              ORDER BY I.RDB$FIELD_POSITION';
2202          $result = $db->sql_query($sql);
2203  
2204          while ($row = $db->sql_fetchrow($result))
2205          {
2206              $keys[] = $row['name'];
2207          }
2208  
2209          if (sizeof($keys))
2210          {
2211              $sql_data .= "\nALTER TABLE $table_name ADD PRIMARY KEY (" . implode(', ', $keys) . ');';
2212          }
2213  
2214          $db->sql_freeresult($result);
2215  
2216          $sql = 'SELECT I.RDB$INDEX_NAME as INAME, I.RDB$UNIQUE_FLAG as UFLAG, S.RDB$FIELD_NAME as FNAME
2217              FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME=I.RDB$INDEX_NAME
2218              WHERE (I.RDB$SYSTEM_FLAG IS NULL  OR  I.RDB$SYSTEM_FLAG=0)
2219                  AND I.RDB$FOREIGN_KEY IS NULL
2220                  AND I.RDB$RELATION_NAME = \''. $table_name . '\'
2221                  AND I.RDB$INDEX_NAME NOT STARTING WITH \'RDB$\'
2222              ORDER BY S.RDB$FIELD_POSITION';
2223          $result = $db->sql_query($sql);
2224  
2225          $index = array();
2226          while ($row = $db->sql_fetchrow($result))
2227          {
2228              $index[$row['iname']]['unique'] = !empty($row['uflag']);
2229              $index[$row['iname']]['values'][] = $row['fname'];
2230          }
2231  
2232          foreach ($index as $index_name => $data)
2233          {
2234              $sql_data .= "\nCREATE ";
2235              if ($data['unique'])
2236              {
2237                  $sql_data .= 'UNIQUE ';
2238              }
2239              $sql_data .= "INDEX $index_name ON $table_name(" . implode(', ', $data['values']) . ");";
2240          }
2241          $sql_data .= "\n";
2242  
2243          $db->sql_freeresult($result);
2244  
2245          $sql = 'SELECT D1.RDB$DEPENDENT_NAME as DNAME, D1.RDB$FIELD_NAME as FNAME, D1.RDB$DEPENDENT_TYPE, R1.RDB$RELATION_NAME
2246              FROM RDB$DEPENDENCIES D1
2247              LEFT JOIN RDB$RELATIONS R1 ON ((D1.RDB$DEPENDENT_NAME = R1.RDB$RELATION_NAME) AND (NOT (R1.RDB$VIEW_BLR IS NULL)))
2248              WHERE (D1.RDB$DEPENDED_ON_TYPE = 0)
2249                  AND (D1.RDB$DEPENDENT_TYPE <> 3)
2250                  AND (D1.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\')
2251              UNION SELECT DISTINCT F2.RDB$RELATION_NAME, D2.RDB$FIELD_NAME, D2.RDB$DEPENDENT_TYPE, R2.RDB$RELATION_NAME FROM RDB$DEPENDENCIES D2, RDB$RELATION_FIELDS F2
2252              LEFT JOIN RDB$RELATIONS R2 ON ((F2.RDB$RELATION_NAME = R2.RDB$RELATION_NAME) AND (NOT (R2.RDB$VIEW_BLR IS NULL)))
2253              WHERE (D2.RDB$DEPENDENT_TYPE = 3)
2254                  AND (D2.RDB$DEPENDENT_NAME = F2.RDB$FIELD_SOURCE)
2255                  AND (D2.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\')
2256              ORDER BY 1, 2';
2257          $result = $db->sql_query($sql);
2258          while ($row = $db->sql_fetchrow($result))
2259          {
2260              $sql = 'SELECT T1.RDB$DEPENDED_ON_NAME as GEN, T1.RDB$FIELD_NAME, T1.RDB$DEPENDED_ON_TYPE
2261                  FROM RDB$DEPENDENCIES T1
2262                  WHERE (T1.RDB$DEPENDENT_NAME = \'' . $row['dname'] . '\')
2263                      AND (T1.RDB$DEPENDENT_TYPE = 2 AND T1.RDB$DEPENDED_ON_TYPE = 14)
2264                  UNION ALL SELECT DISTINCT D.RDB$DEPENDED_ON_NAME, D.RDB$FIELD_NAME, D.RDB$DEPENDED_ON_TYPE
2265                  FROM RDB$DEPENDENCIES D, RDB$RELATION_FIELDS F
2266                  WHERE (D.RDB$DEPENDENT_TYPE = 3)
2267                      AND (D.RDB$DEPENDENT_NAME = F.RDB$FIELD_SOURCE)
2268                      AND (F.RDB$RELATION_NAME = \'' . $row['dname'] . '\')
2269                  ORDER BY 1,2';
2270              $result2 = $db->sql_query($sql);
2271              $row2 = $db->sql_fetchrow($result2);
2272              $db->sql_freeresult($result2);
2273              $gen_name = $row2['gen'];
2274  
2275              $sql_data .= "\nDROP GENERATOR " . $gen_name . ";";
2276              $sql_data .= "\nSET TERM ^ ;";
2277              $sql_data .= "\nCREATE GENERATOR " . $gen_name . "^";
2278              $sql_data .= "\nSET GENERATOR  " . $gen_name . " TO 0^\n";
2279              $sql_data .= "\nCREATE TRIGGER {$row['dname']} FOR $table_name";
2280              $sql_data .= "\nBEFORE INSERT\nAS\nBEGIN";
2281              $sql_data .= "\n  NEW.{$row['fname']} = GEN_ID(" . $gen_name . ", 1);";
2282              $sql_data .= "\nEND^\n";
2283              $sql_data .= "\nSET TERM ; ^\n";
2284          }
2285  
2286          $this->flush($sql_data);
2287  
2288          $db->sql_freeresult($result);
2289      }
2290  }
2291  
2292  // get how much space we allow for a chunk of data, very similar to phpMyAdmin's way of doing things ;-) (hey, we only do this for MySQL anyway :P)
2293  function get_usable_memory()
2294  {
2295      $val = trim(@ini_get('memory_limit'));
2296  
2297      if (preg_match('/(\\d+)([mkg]?)/i', $val, $regs))
2298      {
2299          $memory_limit = (int) $regs[1];
2300          switch ($regs[2])
2301          {
2302  
2303              case 'k':
2304              case 'K':
2305                  $memory_limit *= 1024;
2306              break;
2307  
2308              case 'm':
2309              case 'M':
2310                  $memory_limit *= 1048576;
2311              break;
2312  
2313              case 'g':
2314              case 'G':
2315                  $memory_limit *= 1073741824;
2316              break;
2317          }
2318  
2319          // how much memory PHP requires at the start of export (it is really a little less)
2320          if ($memory_limit > 6100000)
2321          {
2322              $memory_limit -= 6100000;
2323          }
2324  
2325          // allow us to consume half of the total memory available
2326          $memory_limit /= 2;
2327      }
2328      else
2329      {
2330          // set the buffer to 1M if we have no clue how much memory PHP will give us :P
2331          $memory_limit = 1048576;
2332      }
2333  
2334      return $memory_limit;
2335  }
2336  
2337  function sanitize_data_mssql($text)
2338  {
2339      $data = preg_split('/[\n\t\r\b\f]/', $text);
2340      preg_match_all('/[\n\t\r\b\f]/', $text, $matches);
2341  
2342      $val = array();
2343  
2344      foreach ($data as $value)
2345      {
2346          if (strlen($value))
2347          {
2348              $val[] = "'" . $value . "'";
2349          }
2350          if (sizeof($matches[0]))
2351          {
2352              $val[] = 'char(' . ord(array_shift($matches[0])) . ')';
2353          }
2354      }
2355  
2356      return implode('+', $val);
2357  }
2358  
2359  function sanitize_data_oracle($text)
2360  {
2361  //    $data = preg_split('/[\0\n\t\r\b\f\'"\/\\\]/', $text);
2362  //    preg_match_all('/[\0\n\t\r\b\f\'"\/\\\]/', $text, $matches);
2363      $data = preg_split('/[\0\b\f\'\/]/', $text);
2364      preg_match_all('/[\0\r\b\f\'\/]/', $text, $matches);
2365  
2366      $val = array();
2367  
2368      foreach ($data as $value)
2369      {
2370          if (strlen($value))
2371          {
2372              $val[] = "'" . $value . "'";
2373          }
2374          if (sizeof($matches[0]))
2375          {
2376              $val[] = 'chr(' . ord(array_shift($matches[0])) . ')';
2377          }
2378      }
2379  
2380      return implode('||', $val);
2381  }
2382  
2383  function sanitize_data_generic($text)
2384  {
2385      $data = preg_split('/[\n\t\r\b\f]/', $text);
2386      preg_match_all('/[\n\t\r\b\f]/', $text, $matches);
2387  
2388      $val = array();
2389  
2390      foreach ($data as $value)
2391      {
2392          if (strlen($value))
2393          {
2394              $val[] = "'" . $value . "'";
2395          }
2396          if (sizeof($matches[0]))
2397          {
2398              $val[] = "'" . array_shift($matches[0]) . "'";
2399          }
2400      }
2401  
2402      return implode('||', $val);
2403  }
2404  
2405  // modified from PHP.net
2406  function fgetd(&$fp, $delim, $read, $seek, $eof, $buffer = 8192)
2407  {
2408      $record = '';
2409      $delim_len = strlen($delim);
2410  
2411      while (!$eof($fp))
2412      {
2413          $pos = strpos($record, $delim);
2414          if ($pos === false)
2415          {
2416              $record .= $read($fp, $buffer);
2417              if ($eof($fp) && ($pos = strpos($record, $delim)) !== false)
2418              {
2419                  $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR);
2420                  return substr($record, 0, $pos);
2421              }
2422          }
2423          else
2424          {
2425              $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR);
2426              return substr($record, 0, $pos);
2427          }
2428      }
2429  
2430      return false;
2431  }
2432  
2433  function fgetd_seekless(&$fp, $delim, $read, $seek, $eof, $buffer = 8192)
2434  {
2435      static $array = array();
2436      static $record = '';
2437  
2438      if (!sizeof($array))
2439      {
2440          while (!$eof($fp))
2441          {
2442              if (strpos($record, $delim) !== false)
2443              {
2444                  $array = explode($delim, $record);
2445                  $record = array_pop($array);
2446                  break;
2447              }
2448              else
2449              {
2450                  $record .= $read($fp, $buffer);
2451              }
2452          }
2453          if ($eof($fp) && strpos($record, $delim) !== false)
2454          {
2455              $array = explode($delim, $record);
2456              $record = array_pop($array);
2457          }
2458      }
2459  
2460      if (sizeof($array))
2461      {
2462          return array_shift($array);
2463      }
2464  
2465      return false;
2466  }
2467  
2468  ?>


Generated: Wed Oct 2 15:03:47 2013 Cross-referenced by PHPXref 0.7.1