Verzeichnisstruktur phpBB-3.1.0
- Veröffentlicht
- 27.10.2014
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
acp_database.php
0001 <?php
0002 /**
0003 *
0004 * This file is part of the phpBB Forum Software package.
0005 *
0006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
0007 * @license GNU General Public License, version 2 (GPL-2.0)
0008 *
0009 * For full copyright and license information, please see
0010 * the docs/CREDITS.txt file.
0011 *
0012 */
0013
0014 /**
0015 * @ignore
0016 */
0017 if (!defined('IN_PHPBB'))
0018 {
0019 exit;
0020 }
0021
0022 class acp_database
0023 {
0024 var $db_tools;
0025 var $u_action;
0026
0027 function main($id, $mode)
0028 {
0029 global $cache, $db, $user, $auth, $template, $table_prefix;
0030 global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
0031
0032 $this->db_tools = new \phpbb\db\tools($db);
0033
0034 $user->add_lang('acp/database');
0035
0036 $this->tpl_name = 'acp_database';
0037 $this->page_title = 'ACP_DATABASE';
0038
0039 $action = request_var('action', '');
0040 $submit = (isset($_POST['submit'])) ? true : false;
0041
0042 $template->assign_vars(array(
0043 'MODE' => $mode
0044 ));
0045
0046 switch ($mode)
0047 {
0048 case 'backup':
0049
0050 $this->page_title = 'ACP_BACKUP';
0051
0052 switch ($action)
0053 {
0054 case 'download':
0055 $type = request_var('type', '');
0056 $table = array_intersect($this->db_tools->sql_list_tables(), request_var('table', array('')));
0057 $format = request_var('method', '');
0058 $where = request_var('where', '');
0059
0060 if (!sizeof($table))
0061 {
0062 trigger_error($user->lang['TABLE_SELECT_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING);
0063 }
0064
0065 $store = $download = $structure = $schema_data = false;
0066
0067 if ($where == 'store_and_download' || $where == 'store')
0068 {
0069 $store = true;
0070 }
0071
0072 if ($where == 'store_and_download' || $where == 'download')
0073 {
0074 $download = true;
0075 }
0076
0077 if ($type == 'full' || $type == 'structure')
0078 {
0079 $structure = true;
0080 }
0081
0082 if ($type == 'full' || $type == 'data')
0083 {
0084 $schema_data = true;
0085 }
0086
0087 @set_time_limit(1200);
0088 @set_time_limit(0);
0089
0090 $time = time();
0091
0092 $filename = 'backup_' . $time . '_' . unique_id();
0093 switch ($db->get_sql_layer())
0094 {
0095 case 'mysqli':
0096 case 'mysql4':
0097 case 'mysql':
0098 $extractor = new mysql_extractor($format, $filename, $time, $download, $store);
0099 break;
0100
0101 case 'sqlite':
0102 $extractor = new sqlite_extractor($format, $filename, $time, $download, $store);
0103 break;
0104
0105 case 'sqlite3':
0106 $extractor = new sqlite3_extractor($format, $filename, $time, $download, $store);
0107 break;
0108
0109 case 'postgres':
0110 $extractor = new postgres_extractor($format, $filename, $time, $download, $store);
0111 break;
0112
0113 case 'oracle':
0114 $extractor = new oracle_extractor($format, $filename, $time, $download, $store);
0115 break;
0116
0117 case 'mssql':
0118 case 'mssql_odbc':
0119 case 'mssqlnative':
0120 $extractor = new mssql_extractor($format, $filename, $time, $download, $store);
0121 break;
0122 }
0123
0124 $extractor->write_start($table_prefix);
0125
0126 foreach ($table as $table_name)
0127 {
0128 // Get the table structure
0129 if ($structure)
0130 {
0131 $extractor->write_table($table_name);
0132 }
0133 else
0134 {
0135 // We might wanna empty out all that junk :D
0136 switch ($db->get_sql_layer())
0137 {
0138 case 'sqlite':
0139 case 'sqlite3':
0140 $extractor->flush('DELETE FROM ' . $table_name . ";\n");
0141 break;
0142
0143 case 'mssql':
0144 case 'mssql_odbc':
0145 case 'mssqlnative':
0146 $extractor->flush('TRUNCATE TABLE ' . $table_name . "GO\n");
0147 break;
0148
0149 case 'oracle':
0150 $extractor->flush('TRUNCATE TABLE ' . $table_name . "/\n");
0151 break;
0152
0153 default:
0154 $extractor->flush('TRUNCATE TABLE ' . $table_name . ";\n");
0155 break;
0156 }
0157 }
0158
0159 // Data
0160 if ($schema_data)
0161 {
0162 $extractor->write_data($table_name);
0163 }
0164 }
0165
0166 $extractor->write_end();
0167
0168 add_log('admin', 'LOG_DB_BACKUP');
0169
0170 if ($download == true)
0171 {
0172 exit;
0173 }
0174
0175 trigger_error($user->lang['BACKUP_SUCCESS'] . adm_back_link($this->u_action));
0176 break;
0177
0178 default:
0179 $tables = $this->db_tools->sql_list_tables();
0180 asort($tables);
0181 foreach ($tables as $table_name)
0182 {
0183 if (strlen($table_prefix) === 0 || stripos($table_name, $table_prefix) === 0)
0184 {
0185 $template->assign_block_vars('tables', array(
0186 'TABLE' => $table_name
0187 ));
0188 }
0189 }
0190 unset($tables);
0191
0192 $template->assign_vars(array(
0193 'U_ACTION' => $this->u_action . '&action=download'
0194 ));
0195
0196 $available_methods = array('gzip' => 'zlib', 'bzip2' => 'bz2');
0197
0198 foreach ($available_methods as $type => $module)
0199 {
0200 if (!@extension_loaded($module))
0201 {
0202 continue;
0203 }
0204
0205 $template->assign_block_vars('methods', array(
0206 'TYPE' => $type
0207 ));
0208 }
0209
0210 $template->assign_block_vars('methods', array(
0211 'TYPE' => 'text'
0212 ));
0213 break;
0214 }
0215 break;
0216
0217 case 'restore':
0218
0219 $this->page_title = 'ACP_RESTORE';
0220
0221 switch ($action)
0222 {
0223 case 'submit':
0224 $delete = request_var('delete', '');
0225 $file = request_var('file', '');
0226 $download = request_var('download', '');
0227
0228 if (!preg_match('#^backup_\d{10,}_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches))
0229 {
0230 trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
0231 }
0232
0233 $file_name = $phpbb_root_path . 'store/' . $matches[0];
0234
0235 if (!file_exists($file_name) || !is_readable($file_name))
0236 {
0237 trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
0238 }
0239
0240 if ($delete)
0241 {
0242 if (confirm_box(true))
0243 {
0244 unlink($file_name);
0245 add_log('admin', 'LOG_DB_DELETE');
0246 trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action));
0247 }
0248 else
0249 {
0250 confirm_box(false, $user->lang['DELETE_SELECTED_BACKUP'], build_hidden_fields(array('delete' => $delete, 'file' => $file)));
0251 }
0252 }
0253 else if ($download || confirm_box(true))
0254 {
0255 if ($download)
0256 {
0257 $name = $matches[0];
0258
0259 switch ($matches[1])
0260 {
0261 case 'sql':
0262 $mimetype = 'text/x-sql';
0263 break;
0264 case 'sql.bz2':
0265 $mimetype = 'application/x-bzip2';
0266 break;
0267 case 'sql.gz':
0268 $mimetype = 'application/x-gzip';
0269 break;
0270 }
0271
0272 header('Cache-Control: private, no-cache');
0273 header("Content-Type: $mimetype; name=\"$name\"");
0274 header("Content-disposition: attachment; filename=$name");
0275
0276 @set_time_limit(0);
0277
0278 $fp = @fopen($file_name, 'rb');
0279
0280 if ($fp !== false)
0281 {
0282 while (!feof($fp))
0283 {
0284 echo fread($fp, 8192);
0285 }
0286 fclose($fp);
0287 }
0288
0289 flush();
0290 exit;
0291 }
0292
0293 switch ($matches[1])
0294 {
0295 case 'sql':
0296 $fp = fopen($file_name, 'rb');
0297 $read = 'fread';
0298 $seek = 'fseek';
0299 $eof = 'feof';
0300 $close = 'fclose';
0301 $fgetd = 'fgetd';
0302 break;
0303
0304 case 'sql.bz2':
0305 $fp = bzopen($file_name, 'r');
0306 $read = 'bzread';
0307 $seek = '';
0308 $eof = 'feof';
0309 $close = 'bzclose';
0310 $fgetd = 'fgetd_seekless';
0311 break;
0312
0313 case 'sql.gz':
0314 $fp = gzopen($file_name, 'rb');
0315 $read = 'gzread';
0316 $seek = 'gzseek';
0317 $eof = 'gzeof';
0318 $close = 'gzclose';
0319 $fgetd = 'fgetd';
0320 break;
0321 }
0322
0323 switch ($db->get_sql_layer())
0324 {
0325 case 'mysql':
0326 case 'mysql4':
0327 case 'mysqli':
0328 case 'sqlite':
0329 case 'sqlite3':
0330 while (($sql = $fgetd($fp, ";\n", $read, $seek, $eof)) !== false)
0331 {
0332 $db->sql_query($sql);
0333 }
0334 break;
0335
0336 case 'postgres':
0337 $delim = ";\n";
0338 while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false)
0339 {
0340 $query = trim($sql);
0341
0342 if (substr($query, 0, 13) == 'CREATE DOMAIN')
0343 {
0344 list(, , $domain) = explode(' ', $query);
0345 $sql = "SELECT domain_name
0346 FROM information_schema.domains
0347 WHERE domain_name = '$domain';";
0348 $result = $db->sql_query($sql);
0349 if (!$db->sql_fetchrow($result))
0350 {
0351 $db->sql_query($query);
0352 }
0353 $db->sql_freeresult($result);
0354 }
0355 else
0356 {
0357 $db->sql_query($query);
0358 }
0359
0360 if (substr($query, 0, 4) == 'COPY')
0361 {
0362 while (($sub = $fgetd($fp, "\n", $read, $seek, $eof)) !== '\.')
0363 {
0364 if ($sub === false)
0365 {
0366 trigger_error($user->lang['RESTORE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING);
0367 }
0368 pg_put_line($db->get_db_connect_id(), $sub . "\n");
0369 }
0370 pg_put_line($db->get_db_connect_id(), "\\.\n");
0371 pg_end_copy($db->get_db_connect_id());
0372 }
0373 }
0374 break;
0375
0376 case 'oracle':
0377 while (($sql = $fgetd($fp, "/\n", $read, $seek, $eof)) !== false)
0378 {
0379 $db->sql_query($sql);
0380 }
0381 break;
0382
0383 case 'mssql':
0384 case 'mssql_odbc':
0385 case 'mssqlnative':
0386 while (($sql = $fgetd($fp, "GO\n", $read, $seek, $eof)) !== false)
0387 {
0388 $db->sql_query($sql);
0389 }
0390 break;
0391 }
0392
0393 $close($fp);
0394
0395 // Purge the cache due to updated data
0396 $cache->purge();
0397
0398 add_log('admin', 'LOG_DB_RESTORE');
0399 trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action));
0400 break;
0401 }
0402 else if (!$download)
0403 {
0404 confirm_box(false, $user->lang['RESTORE_SELECTED_BACKUP'], build_hidden_fields(array('file' => $file)));
0405 }
0406
0407 default:
0408 $methods = array('sql');
0409 $available_methods = array('sql.gz' => 'zlib', 'sql.bz2' => 'bz2');
0410
0411 foreach ($available_methods as $type => $module)
0412 {
0413 if (!@extension_loaded($module))
0414 {
0415 continue;
0416 }
0417 $methods[] = $type;
0418 }
0419
0420 $dir = $phpbb_root_path . 'store/';
0421 $dh = @opendir($dir);
0422
0423 $backup_files = array();
0424
0425 if ($dh)
0426 {
0427 while (($file = readdir($dh)) !== false)
0428 {
0429 if (preg_match('#^backup_(\d{10,})_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches))
0430 {
0431 if (in_array($matches[2], $methods))
0432 {
0433 $backup_files[(int) $matches[1]] = $file;
0434 }
0435 }
0436 }
0437 closedir($dh);
0438 }
0439
0440 if (!empty($backup_files))
0441 {
0442 krsort($backup_files);
0443
0444 foreach ($backup_files as $name => $file)
0445 {
0446 $template->assign_block_vars('files', array(
0447 'FILE' => $file,
0448 'NAME' => $user->format_date($name, 'd-m-Y H:i:s', true),
0449 'SUPPORTED' => true,
0450 ));
0451 }
0452 }
0453
0454 $template->assign_vars(array(
0455 'U_ACTION' => $this->u_action . '&action=submit'
0456 ));
0457 break;
0458 }
0459 break;
0460 }
0461 }
0462 }
0463
0464 class base_extractor
0465 {
0466 var $fh;
0467 var $fp;
0468 var $write;
0469 var $close;
0470 var $store;
0471 var $download;
0472 var $time;
0473 var $format;
0474 var $run_comp = false;
0475
0476 function base_extractor($format, $filename, $time, $download = false, $store = false)
0477 {
0478 global $request;
0479
0480 $this->download = $download;
0481 $this->store = $store;
0482 $this->time = $time;
0483 $this->format = $format;
0484
0485 switch ($format)
0486 {
0487 case 'text':
0488 $ext = '.sql';
0489 $open = 'fopen';
0490 $this->write = 'fwrite';
0491 $this->close = 'fclose';
0492 $mimetype = 'text/x-sql';
0493 break;
0494 case 'bzip2':
0495 $ext = '.sql.bz2';
0496 $open = 'bzopen';
0497 $this->write = 'bzwrite';
0498 $this->close = 'bzclose';
0499 $mimetype = 'application/x-bzip2';
0500 break;
0501 case 'gzip':
0502 $ext = '.sql.gz';
0503 $open = 'gzopen';
0504 $this->write = 'gzwrite';
0505 $this->close = 'gzclose';
0506 $mimetype = 'application/x-gzip';
0507 break;
0508 }
0509
0510 if ($download == true)
0511 {
0512 $name = $filename . $ext;
0513 header('Cache-Control: private, no-cache');
0514 header("Content-Type: $mimetype; name=\"$name\"");
0515 header("Content-disposition: attachment; filename=$name");
0516
0517 switch ($format)
0518 {
0519 case 'bzip2':
0520 ob_start();
0521 break;
0522
0523 case 'gzip':
0524 if (strpos($request->header('Accept-Encoding'), 'gzip') !== false && strpos(strtolower($request->header('User-Agent')), 'msie') === false)
0525 {
0526 ob_start('ob_gzhandler');
0527 }
0528 else
0529 {
0530 $this->run_comp = true;
0531 }
0532 break;
0533 }
0534 }
0535
0536 if ($store == true)
0537 {
0538 global $phpbb_root_path;
0539 $file = $phpbb_root_path . 'store/' . $filename . $ext;
0540
0541 $this->fp = $open($file, 'w');
0542
0543 if (!$this->fp)
0544 {
0545 trigger_error('FILE_WRITE_FAIL', E_USER_ERROR);
0546 }
0547 }
0548 }
0549
0550 function write_end()
0551 {
0552 static $close;
0553
0554 if ($this->store)
0555 {
0556 if ($close === null)
0557 {
0558 $close = $this->close;
0559 }
0560 $close($this->fp);
0561 }
0562
0563 // bzip2 must be written all the way at the end
0564 if ($this->download && $this->format === 'bzip2')
0565 {
0566 $c = ob_get_clean();
0567 echo bzcompress($c);
0568 }
0569 }
0570
0571 function flush($data)
0572 {
0573 static $write;
0574 if ($this->store === true)
0575 {
0576 if ($write === null)
0577 {
0578 $write = $this->write;
0579 }
0580 $write($this->fp, $data);
0581 }
0582
0583 if ($this->download === true)
0584 {
0585 if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp))
0586 {
0587 echo $data;
0588 }
0589
0590 // we can write the gzip data as soon as we get it
0591 if ($this->format === 'gzip')
0592 {
0593 if ($this->run_comp)
0594 {
0595 echo gzencode($data);
0596 }
0597 else
0598 {
0599 ob_flush();
0600 flush();
0601 }
0602 }
0603 }
0604 }
0605 }
0606
0607 class mysql_extractor extends base_extractor
0608 {
0609 function write_start($table_prefix)
0610 {
0611 $sql_data = "#\n";
0612 $sql_data .= "# phpBB Backup Script\n";
0613 $sql_data .= "# Dump of tables for $table_prefix\n";
0614 $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
0615 $sql_data .= "#\n";
0616 $this->flush($sql_data);
0617 }
0618
0619 function write_table($table_name)
0620 {
0621 global $db;
0622 static $new_extract;
0623
0624 if ($new_extract === null)
0625 {
0626 if ($db->get_sql_layer() === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>='))
0627 {
0628 $new_extract = true;
0629 }
0630 else
0631 {
0632 $new_extract = false;
0633 }
0634 }
0635
0636 if ($new_extract)
0637 {
0638 $this->new_write_table($table_name);
0639 }
0640 else
0641 {
0642 $this->old_write_table($table_name);
0643 }
0644 }
0645
0646 function write_data($table_name)
0647 {
0648 global $db;
0649 if ($db->get_sql_layer() === 'mysqli')
0650 {
0651 $this->write_data_mysqli($table_name);
0652 }
0653 else
0654 {
0655 $this->write_data_mysql($table_name);
0656 }
0657 }
0658
0659 function write_data_mysqli($table_name)
0660 {
0661 global $db;
0662 $sql = "SELECT *
0663 FROM $table_name";
0664 $result = mysqli_query($db->get_db_connect_id(), $sql, MYSQLI_USE_RESULT);
0665 if ($result != false)
0666 {
0667 $fields_cnt = mysqli_num_fields($result);
0668
0669 // Get field information
0670 $field = mysqli_fetch_fields($result);
0671 $field_set = array();
0672
0673 for ($j = 0; $j < $fields_cnt; $j++)
0674 {
0675 $field_set[] = $field[$j]->name;
0676 }
0677
0678 $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
0679 $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
0680 $fields = implode(', ', $field_set);
0681 $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
0682 $first_set = true;
0683 $query_len = 0;
0684 $max_len = get_usable_memory();
0685
0686 while ($row = mysqli_fetch_row($result))
0687 {
0688 $values = array();
0689 if ($first_set)
0690 {
0691 $query = $sql_data . '(';
0692 }
0693 else
0694 {
0695 $query .= ',(';
0696 }
0697
0698 for ($j = 0; $j < $fields_cnt; $j++)
0699 {
0700 if (!isset($row[$j]) || is_null($row[$j]))
0701 {
0702 $values[$j] = 'NULL';
0703 }
0704 else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024))
0705 {
0706 $values[$j] = $row[$j];
0707 }
0708 else
0709 {
0710 $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
0711 }
0712 }
0713 $query .= implode(', ', $values) . ')';
0714
0715 $query_len += strlen($query);
0716 if ($query_len > $max_len)
0717 {
0718 $this->flush($query . ";\n\n");
0719 $query = '';
0720 $query_len = 0;
0721 $first_set = true;
0722 }
0723 else
0724 {
0725 $first_set = false;
0726 }
0727 }
0728 mysqli_free_result($result);
0729
0730 // check to make sure we have nothing left to flush
0731 if (!$first_set && $query)
0732 {
0733 $this->flush($query . ";\n\n");
0734 }
0735 }
0736 }
0737
0738 function write_data_mysql($table_name)
0739 {
0740 global $db;
0741 $sql = "SELECT *
0742 FROM $table_name";
0743 $result = mysql_unbuffered_query($sql, $db->get_db_connect_id());
0744
0745 if ($result != false)
0746 {
0747 $fields_cnt = mysql_num_fields($result);
0748
0749 // Get field information
0750 $field = array();
0751 for ($i = 0; $i < $fields_cnt; $i++)
0752 {
0753 $field[] = mysql_fetch_field($result, $i);
0754 }
0755 $field_set = array();
0756
0757 for ($j = 0; $j < $fields_cnt; $j++)
0758 {
0759 $field_set[] = $field[$j]->name;
0760 }
0761
0762 $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
0763 $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
0764 $fields = implode(', ', $field_set);
0765 $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
0766 $first_set = true;
0767 $query_len = 0;
0768 $max_len = get_usable_memory();
0769
0770 while ($row = mysql_fetch_row($result))
0771 {
0772 $values = array();
0773 if ($first_set)
0774 {
0775 $query = $sql_data . '(';
0776 }
0777 else
0778 {
0779 $query .= ',(';
0780 }
0781
0782 for ($j = 0; $j < $fields_cnt; $j++)
0783 {
0784 if (!isset($row[$j]) || is_null($row[$j]))
0785 {
0786 $values[$j] = 'NULL';
0787 }
0788 else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp'))
0789 {
0790 $values[$j] = $row[$j];
0791 }
0792 else
0793 {
0794 $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
0795 }
0796 }
0797 $query .= implode(', ', $values) . ')';
0798
0799 $query_len += strlen($query);
0800 if ($query_len > $max_len)
0801 {
0802 $this->flush($query . ";\n\n");
0803 $query = '';
0804 $query_len = 0;
0805 $first_set = true;
0806 }
0807 else
0808 {
0809 $first_set = false;
0810 }
0811 }
0812 mysql_free_result($result);
0813
0814 // check to make sure we have nothing left to flush
0815 if (!$first_set && $query)
0816 {
0817 $this->flush($query . ";\n\n");
0818 }
0819 }
0820 }
0821
0822 function new_write_table($table_name)
0823 {
0824 global $db;
0825
0826 $sql = 'SHOW CREATE TABLE ' . $table_name;
0827 $result = $db->sql_query($sql);
0828 $row = $db->sql_fetchrow($result);
0829
0830 $sql_data = '# Table: ' . $table_name . "\n";
0831 $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
0832 $this->flush($sql_data . $row['Create Table'] . ";\n\n");
0833
0834 $db->sql_freeresult($result);
0835 }
0836
0837 function old_write_table($table_name)
0838 {
0839 global $db;
0840
0841 $sql_data = '# Table: ' . $table_name . "\n";
0842 $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
0843 $sql_data .= "CREATE TABLE $table_name(\n";
0844 $rows = array();
0845
0846 $sql = "SHOW FIELDS
0847 FROM $table_name";
0848 $result = $db->sql_query($sql);
0849
0850 while ($row = $db->sql_fetchrow($result))
0851 {
0852 $line = ' ' . $row['Field'] . ' ' . $row['Type'];
0853
0854 if (!is_null($row['Default']))
0855 {
0856 $line .= " DEFAULT '{$row['Default']}'";
0857 }
0858
0859 if ($row['Null'] != 'YES')
0860 {
0861 $line .= ' NOT NULL';
0862 }
0863
0864 if ($row['Extra'] != '')
0865 {
0866 $line .= ' ' . $row['Extra'];
0867 }
0868
0869 $rows[] = $line;
0870 }
0871 $db->sql_freeresult($result);
0872
0873 $sql = "SHOW KEYS
0874 FROM $table_name";
0875
0876 $result = $db->sql_query($sql);
0877
0878 $index = array();
0879 while ($row = $db->sql_fetchrow($result))
0880 {
0881 $kname = $row['Key_name'];
0882
0883 if ($kname != 'PRIMARY')
0884 {
0885 if ($row['Non_unique'] == 0)
0886 {
0887 $kname = "UNIQUE|$kname";
0888 }
0889 }
0890
0891 if ($row['Sub_part'])
0892 {
0893 $row['Column_name'] .= '(' . $row['Sub_part'] . ')';
0894 }
0895 $index[$kname][] = $row['Column_name'];
0896 }
0897 $db->sql_freeresult($result);
0898
0899 foreach ($index as $key => $columns)
0900 {
0901 $line = ' ';
0902
0903 if ($key == 'PRIMARY')
0904 {
0905 $line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')';
0906 }
0907 else if (strpos($key, 'UNIQUE') === 0)
0908 {
0909 $line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')';
0910 }
0911 else if (strpos($key, 'FULLTEXT') === 0)
0912 {
0913 $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')';
0914 }
0915 else
0916 {
0917 $line .= "KEY $key (" . implode(', ', $columns) . ')';
0918 }
0919
0920 $rows[] = $line;
0921 }
0922
0923 $sql_data .= implode(",\n", $rows);
0924 $sql_data .= "\n);\n\n";
0925
0926 $this->flush($sql_data);
0927 }
0928 }
0929
0930 class sqlite_extractor extends base_extractor
0931 {
0932 function write_start($prefix)
0933 {
0934 $sql_data = "--\n";
0935 $sql_data .= "-- phpBB Backup Script\n";
0936 $sql_data .= "-- Dump of tables for $prefix\n";
0937 $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
0938 $sql_data .= "--\n";
0939 $sql_data .= "BEGIN TRANSACTION;\n";
0940 $this->flush($sql_data);
0941 }
0942
0943 function write_table($table_name)
0944 {
0945 global $db;
0946 $sql_data = '-- Table: ' . $table_name . "\n";
0947 $sql_data .= "DROP TABLE $table_name;\n";
0948
0949 $sql = "SELECT sql
0950 FROM sqlite_master
0951 WHERE type = 'table'
0952 AND name = '" . $db->sql_escape($table_name) . "'
0953 ORDER BY type DESC, name;";
0954 $result = $db->sql_query($sql);
0955 $row = $db->sql_fetchrow($result);
0956 $db->sql_freeresult($result);
0957
0958 // Create Table
0959 $sql_data .= $row['sql'] . ";\n";
0960
0961 $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');");
0962
0963 $ar = array();
0964 while ($row = $db->sql_fetchrow($result))
0965 {
0966 $ar[] = $row;
0967 }
0968 $db->sql_freeresult($result);
0969
0970 foreach ($ar as $value)
0971 {
0972 if (strpos($value['name'], 'autoindex') !== false)
0973 {
0974 continue;
0975 }
0976
0977 $result = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($value['name']) . "');");
0978
0979 $fields = array();
0980 while ($row = $db->sql_fetchrow($result))
0981 {
0982 $fields[] = $row['name'];
0983 }
0984 $db->sql_freeresult($result);
0985
0986 $sql_data .= 'CREATE ' . ($value['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $value['name'] . ' on ' . $table_name . ' (' . implode(', ', $fields) . ");\n";
0987 }
0988
0989 $this->flush($sql_data . "\n");
0990 }
0991
0992 function write_data($table_name)
0993 {
0994 global $db;
0995
0996 $col_types = sqlite_fetch_column_types($db->get_db_connect_id(), $table_name);
0997
0998 $sql = "SELECT *
0999 FROM $table_name";
1000 $result = sqlite_unbuffered_query($db->get_db_connect_id(), $sql);
1001 $rows = sqlite_fetch_all($result, SQLITE_ASSOC);
1002 $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES (';
1003 foreach ($rows as $row)
1004 {
1005 foreach ($row as $column_name => $column_data)
1006 {
1007 if (is_null($column_data))
1008 {
1009 $row[$column_name] = 'NULL';
1010 }
1011 else if ($column_data == '')
1012 {
1013 $row[$column_name] = "''";
1014 }
1015 else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false)
1016 {
1017 $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data));
1018 }
1019 }
1020 $this->flush($sql_insert . implode(', ', $row) . ");\n");
1021 }
1022 }
1023
1024 function write_end()
1025 {
1026 $this->flush("COMMIT;\n");
1027 parent::write_end();
1028 }
1029 }
1030
1031 class sqlite3_extractor extends base_extractor
1032 {
1033 function write_start($prefix)
1034 {
1035 $sql_data = "--\n";
1036 $sql_data .= "-- phpBB Backup Script\n";
1037 $sql_data .= "-- Dump of tables for $prefix\n";
1038 $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
1039 $sql_data .= "--\n";
1040 $sql_data .= "BEGIN TRANSACTION;\n";
1041 $this->flush($sql_data);
1042 }
1043
1044 function write_table($table_name)
1045 {
1046 global $db;
1047 $sql_data = '-- Table: ' . $table_name . "\n";
1048 $sql_data .= "DROP TABLE $table_name;\n";
1049
1050 $sql = "SELECT sql
1051 FROM sqlite_master
1052 WHERE type = 'table'
1053 AND name = '" . $db->sql_escape($table_name) . "'
1054 ORDER BY name ASC;";
1055 $result = $db->sql_query($sql);
1056 $row = $db->sql_fetchrow($result);
1057 $db->sql_freeresult($result);
1058
1059 // Create Table
1060 $sql_data .= $row['sql'] . ";\n";
1061
1062 $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');");
1063
1064 while ($row = $db->sql_fetchrow($result))
1065 {
1066 if (strpos($row['name'], 'autoindex') !== false)
1067 {
1068 continue;
1069 }
1070
1071 $result2 = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($row['name']) . "');");
1072
1073 $fields = array();
1074 while ($row2 = $db->sql_fetchrow($result2))
1075 {
1076 $fields[] = $row2['name'];
1077 }
1078 $db->sql_freeresult($result2);
1079
1080 $sql_data .= 'CREATE ' . ($row['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $row['name'] . ' ON ' . $table_name . ' (' . implode(', ', $fields) . ");\n";
1081 }
1082 $db->sql_freeresult($result);
1083
1084 $this->flush($sql_data . "\n");
1085 }
1086
1087 function write_data($table_name)
1088 {
1089 global $db;
1090
1091 $result = $db->sql_query("PRAGMA table_info('" . $db->sql_escape($table_name) . "');");
1092
1093 $col_types = array();
1094 while ($row = $db->sql_fetchrow($result))
1095 {
1096 $col_types[$row['name']] = $row['type'];
1097 }
1098 $db->sql_freeresult($result);
1099
1100 $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES (';
1101
1102 $sql = "SELECT *
1103 FROM $table_name";
1104 $result = $db->sql_query($sql);
1105
1106 while ($row = $db->sql_fetchrow($result))
1107 {
1108 foreach ($row as $column_name => $column_data)
1109 {
1110 if (is_null($column_data))
1111 {
1112 $row[$column_name] = 'NULL';
1113 }
1114 else if ($column_data === '')
1115 {
1116 $row[$column_name] = "''";
1117 }
1118 else if (stripos($col_types[$column_name], 'text') !== false || stripos($col_types[$column_name], 'char') !== false || stripos($col_types[$column_name], 'blob') !== false)
1119 {
1120 $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data));
1121 }
1122 }
1123 $this->flush($sql_insert . implode(', ', $row) . ");\n");
1124 }
1125 }
1126
1127 function write_end()
1128 {
1129 $this->flush("COMMIT;\n");
1130 parent::write_end();
1131 }
1132 }
1133
1134 class postgres_extractor extends base_extractor
1135 {
1136 function write_start($prefix)
1137 {
1138 $sql_data = "--\n";
1139 $sql_data .= "-- phpBB Backup Script\n";
1140 $sql_data .= "-- Dump of tables for $prefix\n";
1141 $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
1142 $sql_data .= "--\n";
1143 $sql_data .= "BEGIN TRANSACTION;\n";
1144 $this->flush($sql_data);
1145 }
1146
1147 function write_table($table_name)
1148 {
1149 global $db;
1150 static $domains_created = array();
1151
1152 $sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default
1153 FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b
1154 WHERE a.domain_name = b.domain_name
1155 AND b.table_name = '{$table_name}'";
1156 $result = $db->sql_query($sql);
1157 while ($row = $db->sql_fetchrow($result))
1158 {
1159 if (empty($domains_created[$row['domain_name']]))
1160 {
1161 $domains_created[$row['domain_name']] = true;
1162 //$sql_data = "DROP DOMAIN {$row['domain_name']};\n";
1163 $sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}";
1164 if (!empty($row['character_maximum_length']))
1165 {
1166 $sql_data .= '(' . $row['character_maximum_length'] . ')';
1167 }
1168 $sql_data .= ' NOT NULL';
1169 if (!empty($row['domain_default']))
1170 {
1171 $sql_data .= ' DEFAULT ' . $row['domain_default'];
1172 }
1173 $this->flush($sql_data . ";\n");
1174 }
1175 }
1176
1177 $sql_data = '-- Table: ' . $table_name . "\n";
1178 $sql_data .= "DROP TABLE $table_name;\n";
1179 // PGSQL does not "tightly" bind sequences and tables, we must guess...
1180 $sql = "SELECT relname
1181 FROM pg_class
1182 WHERE relkind = 'S'
1183 AND relname = '{$table_name}_seq'";
1184 $result = $db->sql_query($sql);
1185 // We don't even care about storing the results. We already know the answer if we get rows back.
1186 if ($db->sql_fetchrow($result))
1187 {
1188 $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n";
1189 $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n";
1190 }
1191 $db->sql_freeresult($result);
1192
1193 $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
1194 FROM pg_class c, pg_attribute a, pg_type t
1195 WHERE c.relname = '" . $db->sql_escape($table_name) . "'
1196 AND a.attnum > 0
1197 AND a.attrelid = c.oid
1198 AND a.atttypid = t.oid
1199 ORDER BY a.attnum";
1200 $result = $db->sql_query($field_query);
1201
1202 $sql_data .= "CREATE TABLE $table_name(\n";
1203 $lines = array();
1204 while ($row = $db->sql_fetchrow($result))
1205 {
1206 // Get the data from the table
1207 $sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
1208 FROM pg_attrdef d, pg_class c
1209 WHERE (c.relname = '" . $db->sql_escape($table_name) . "')
1210 AND (c.oid = d.adrelid)
1211 AND d.adnum = " . $row['attnum'];
1212 $def_res = $db->sql_query($sql_get_default);
1213 $def_row = $db->sql_fetchrow($def_res);
1214 $db->sql_freeresult($def_res);
1215
1216 if (empty($def_row))
1217 {
1218 unset($row['rowdefault']);
1219 }
1220 else
1221 {
1222 $row['rowdefault'] = $def_row['rowdefault'];
1223 }
1224
1225 if ($row['type'] == 'bpchar')
1226 {
1227 // Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement.
1228 $row['type'] = 'char';
1229 }
1230
1231 $line = ' ' . $row['field'] . ' ' . $row['type'];
1232
1233 if (strpos($row['type'], 'char') !== false)
1234 {
1235 if ($row['lengthvar'] > 0)
1236 {
1237 $line .= '(' . ($row['lengthvar'] - 4) . ')';
1238 }
1239 }
1240
1241 if (strpos($row['type'], 'numeric') !== false)
1242 {
1243 $line .= '(';
1244 $line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff));
1245 $line .= ')';
1246 }
1247
1248 if (isset($row['rowdefault']))
1249 {
1250 $line .= ' DEFAULT ' . $row['rowdefault'];
1251 }
1252
1253 if ($row['notnull'] == 't')
1254 {
1255 $line .= ' NOT NULL';
1256 }
1257
1258 $lines[] = $line;
1259 }
1260 $db->sql_freeresult($result);
1261
1262 // Get the listing of primary keys.
1263 $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
1264 FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia
1265 WHERE (bc.oid = i.indrelid)
1266 AND (ic.oid = i.indexrelid)
1267 AND (ia.attrelid = i.indexrelid)
1268 AND (ta.attrelid = bc.oid)
1269 AND (bc.relname = '" . $db->sql_escape($table_name) . "')
1270 AND (ta.attrelid = i.indrelid)
1271 AND (ta.attnum = i.indkey[ia.attnum-1])
1272 ORDER BY index_name, tab_name, column_name";
1273
1274 $result = $db->sql_query($sql_pri_keys);
1275
1276 $index_create = $index_rows = $primary_key = array();
1277
1278 // We do this in two steps. It makes placing the comma easier
1279 while ($row = $db->sql_fetchrow($result))
1280 {
1281 if ($row['primary_key'] == 't')
1282 {
1283 $primary_key[] = $row['column_name'];
1284 $primary_key_name = $row['index_name'];
1285 }
1286 else
1287 {
1288 // We have to store this all this info because it is possible to have a multi-column key...
1289 // we can loop through it again and build the statement
1290 $index_rows[$row['index_name']]['table'] = $table_name;
1291 $index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false;
1292 $index_rows[$row['index_name']]['column_names'][] = $row['column_name'];
1293 }
1294 }
1295 $db->sql_freeresult($result);
1296
1297 if (!empty($index_rows))
1298 {
1299 foreach ($index_rows as $idx_name => $props)
1300 {
1301 $index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");";
1302 }
1303 }
1304
1305 if (!empty($primary_key))
1306 {
1307 $lines[] = " CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")";
1308 }
1309
1310 // Generate constraint clauses for CHECK constraints
1311 $sql_checks = "SELECT conname as index_name, consrc
1312 FROM pg_constraint, pg_class bc
1313 WHERE conrelid = bc.oid
1314 AND bc.relname = '" . $db->sql_escape($table_name) . "'
1315 AND NOT EXISTS (
1316 SELECT *
1317 FROM pg_constraint as c, pg_inherits as i
1318 WHERE i.inhrelid = pg_constraint.conrelid
1319 AND c.conname = pg_constraint.conname
1320 AND c.consrc = pg_constraint.consrc
1321 AND c.conrelid = i.inhparent
1322 )";
1323 $result = $db->sql_query($sql_checks);
1324
1325 // Add the constraints to the sql file.
1326 while ($row = $db->sql_fetchrow($result))
1327 {
1328 if (!is_null($row['consrc']))
1329 {
1330 $lines[] = ' CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc'];
1331 }
1332 }
1333 $db->sql_freeresult($result);
1334
1335 $sql_data .= implode(", \n", $lines);
1336 $sql_data .= "\n);\n";
1337
1338 if (!empty($index_create))
1339 {
1340 $sql_data .= implode("\n", $index_create) . "\n\n";
1341 }
1342 $this->flush($sql_data);
1343 }
1344
1345 function write_data($table_name)
1346 {
1347 global $db;
1348 // Grab all of the data from current table.
1349 $sql = "SELECT *
1350 FROM $table_name";
1351 $result = $db->sql_query($sql);
1352
1353 $i_num_fields = pg_num_fields($result);
1354 $seq = '';
1355
1356 for ($i = 0; $i < $i_num_fields; $i++)
1357 {
1358 $ary_type[] = pg_field_type($result, $i);
1359 $ary_name[] = pg_field_name($result, $i);
1360
1361 $sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
1362 FROM pg_attrdef d, pg_class c
1363 WHERE (c.relname = '{$table_name}')
1364 AND (c.oid = d.adrelid)
1365 AND d.adnum = " . strval($i + 1);
1366 $result2 = $db->sql_query($sql);
1367 if ($row = $db->sql_fetchrow($result2))
1368 {
1369 // Determine if we must reset the sequences
1370 if (strpos($row['rowdefault'], "nextval('") === 0)
1371 {
1372 $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";
1373 }
1374 }
1375 }
1376
1377 $this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n");
1378 while ($row = $db->sql_fetchrow($result))
1379 {
1380 $schema_vals = array();
1381
1382 // Build the SQL statement to recreate the data.
1383 for ($i = 0; $i < $i_num_fields; $i++)
1384 {
1385 $str_val = $row[$ary_name[$i]];
1386
1387 if (preg_match('#char|text|bool|bytea#i', $ary_type[$i]))
1388 {
1389 $str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val));
1390 $str_empty = '';
1391 }
1392 else
1393 {
1394 $str_empty = '\N';
1395 }
1396
1397 if (empty($str_val) && $str_val !== '0')
1398 {
1399 $str_val = $str_empty;
1400 }
1401
1402 $schema_vals[] = $str_val;
1403 }
1404
1405 // Take the ordered fields and their associated data and build it
1406 // into a valid sql statement to recreate that field in the data.
1407 $this->flush(implode("\t", $schema_vals) . "\n");
1408 }
1409 $db->sql_freeresult($result);
1410 $this->flush("\\.\n");
1411
1412 // Write out the sequence statements
1413 $this->flush($seq);
1414 }
1415
1416 function write_end()
1417 {
1418 $this->flush("COMMIT;\n");
1419 parent::write_end();
1420 }
1421 }
1422
1423 class mssql_extractor extends base_extractor
1424 {
1425 function write_end()
1426 {
1427 $this->flush("COMMIT\nGO\n");
1428 parent::write_end();
1429 }
1430
1431 function write_start($prefix)
1432 {
1433 $sql_data = "--\n";
1434 $sql_data .= "-- phpBB Backup Script\n";
1435 $sql_data .= "-- Dump of tables for $prefix\n";
1436 $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
1437 $sql_data .= "--\n";
1438 $sql_data .= "BEGIN TRANSACTION\n";
1439 $sql_data .= "GO\n";
1440 $this->flush($sql_data);
1441 }
1442
1443 function write_table($table_name)
1444 {
1445 global $db;
1446 $sql_data = '-- Table: ' . $table_name . "\n";
1447 $sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n";
1448 $sql_data .= "DROP TABLE $table_name;\n";
1449 $sql_data .= "GO\n";
1450 $sql_data .= "\nCREATE TABLE [$table_name] (\n";
1451 $rows = array();
1452
1453 $text_flag = false;
1454
1455 $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY
1456 FROM INFORMATION_SCHEMA.COLUMNS
1457 WHERE TABLE_NAME = '$table_name'";
1458 $result = $db->sql_query($sql);
1459
1460 while ($row = $db->sql_fetchrow($result))
1461 {
1462 $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]";
1463
1464 if ($row['DATA_TYPE'] == 'text')
1465 {
1466 $text_flag = true;
1467 }
1468
1469 if ($row['IS_IDENTITY'])
1470 {
1471 $line .= ' IDENTITY (1 , 1)';
1472 }
1473
1474 if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text')
1475 {
1476 $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')';
1477 }
1478
1479 if ($row['IS_NULLABLE'] == 'YES')
1480 {
1481 $line .= ' NULL';
1482 }
1483 else
1484 {
1485 $line .= ' NOT NULL';
1486 }
1487
1488 if ($row['COLUMN_DEFAULT'])
1489 {
1490 $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT'];
1491 }
1492
1493 $rows[] = $line;
1494 }
1495 $db->sql_freeresult($result);
1496
1497 $sql_data .= implode(",\n", $rows);
1498 $sql_data .= "\n) ON [PRIMARY]";
1499
1500 if ($text_flag)
1501 {
1502 $sql_data .= " TEXTIMAGE_ON [PRIMARY]";
1503 }
1504
1505 $sql_data .= "\nGO\n\n";
1506 $rows = array();
1507
1508 $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME
1509 FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
1510 WHERE TABLE_NAME = '$table_name'";
1511 $result = $db->sql_query($sql);
1512 while ($row = $db->sql_fetchrow($result))
1513 {
1514 if (!sizeof($rows))
1515 {
1516 $sql_data .= "ALTER TABLE [$table_name] WITH NOCHECK ADD\n";
1517 $sql_data .= "\tCONSTRAINT [{$row['CONSTRAINT_NAME']}] PRIMARY KEY CLUSTERED \n\t(\n";
1518 }
1519 $rows[] = "\t\t[{$row['COLUMN_NAME']}]";
1520 }
1521 if (sizeof($rows))
1522 {
1523 $sql_data .= implode(",\n", $rows);
1524 $sql_data .= "\n\t) ON [PRIMARY] \nGO\n";
1525 }
1526 $db->sql_freeresult($result);
1527
1528 $index = array();
1529 $sql = "EXEC sp_statistics '$table_name'";
1530 $result = $db->sql_query($sql);
1531 while ($row = $db->sql_fetchrow($result))
1532 {
1533 if ($row['TYPE'] == 3)
1534 {
1535 $index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']';
1536 }
1537 }
1538 $db->sql_freeresult($result);
1539
1540 foreach ($index as $index_name => $column_name)
1541 {
1542 $index[$index_name] = implode(', ', $column_name);
1543 }
1544
1545 foreach ($index as $index_name => $columns)
1546 {
1547 $sql_data .= "\nCREATE INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n";
1548 }
1549 $this->flush($sql_data);
1550 }
1551
1552 function write_data($table_name)
1553 {
1554 global $db;
1555
1556 if ($db->get_sql_layer() === 'mssql')
1557 {
1558 $this->write_data_mssql($table_name);
1559 }
1560 else if($db->get_sql_layer() === 'mssqlnative')
1561 {
1562 $this->write_data_mssqlnative($table_name);
1563 }
1564 else
1565 {
1566 $this->write_data_odbc($table_name);
1567 }
1568 }
1569
1570 function write_data_mssql($table_name)
1571 {
1572 global $db;
1573 $ary_type = $ary_name = array();
1574 $ident_set = false;
1575 $sql_data = '';
1576
1577 // Grab all of the data from current table.
1578 $sql = "SELECT *
1579 FROM $table_name";
1580 $result = $db->sql_query($sql);
1581
1582 $retrieved_data = mssql_num_rows($result);
1583
1584 $i_num_fields = mssql_num_fields($result);
1585
1586 for ($i = 0; $i < $i_num_fields; $i++)
1587 {
1588 $ary_type[$i] = mssql_field_type($result, $i);
1589 $ary_name[$i] = mssql_field_name($result, $i);
1590 }
1591
1592 if ($retrieved_data)
1593 {
1594 $sql = "SELECT 1 as has_identity
1595 FROM INFORMATION_SCHEMA.COLUMNS
1596 WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
1597 $result2 = $db->sql_query($sql);
1598 $row2 = $db->sql_fetchrow($result2);
1599 if (!empty($row2['has_identity']))
1600 {
1601 $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
1602 $ident_set = true;
1603 }
1604 $db->sql_freeresult($result2);
1605 }
1606
1607 while ($row = $db->sql_fetchrow($result))
1608 {
1609 $schema_vals = $schema_fields = array();
1610
1611 // Build the SQL statement to recreate the data.
1612 for ($i = 0; $i < $i_num_fields; $i++)
1613 {
1614 $str_val = $row[$ary_name[$i]];
1615
1616 if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
1617 {
1618 $str_quote = '';
1619 $str_empty = "''";
1620 $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
1621 }
1622 else if (preg_match('#date|timestamp#i', $ary_type[$i]))
1623 {
1624 if (empty($str_val))
1625 {
1626 $str_quote = '';
1627 }
1628 else
1629 {
1630 $str_quote = "'";
1631 }
1632 }
1633 else
1634 {
1635 $str_quote = '';
1636 $str_empty = 'NULL';
1637 }
1638
1639 if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
1640 {
1641 $str_val = $str_empty;
1642 }
1643
1644 $schema_vals[$i] = $str_quote . $str_val . $str_quote;
1645 $schema_fields[$i] = $ary_name[$i];
1646 }
1647
1648 // Take the ordered fields and their associated data and build it
1649 // into a valid sql statement to recreate that field in the data.
1650 $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
1651
1652 $this->flush($sql_data);
1653 $sql_data = '';
1654 }
1655 $db->sql_freeresult($result);
1656
1657 if ($retrieved_data && $ident_set)
1658 {
1659 $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
1660 }
1661 $this->flush($sql_data);
1662 }
1663
1664 function write_data_mssqlnative($table_name)
1665 {
1666 global $db;
1667 $ary_type = $ary_name = array();
1668 $ident_set = false;
1669 $sql_data = '';
1670
1671 // Grab all of the data from current table.
1672 $sql = "SELECT * FROM $table_name";
1673 $db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC));
1674 $result = $db->sql_query($sql);
1675
1676 $retrieved_data = $db->mssqlnative_num_rows($result);
1677
1678 if (!$retrieved_data)
1679 {
1680 $db->sql_freeresult($result);
1681 return;
1682 }
1683
1684 $sql = "SELECT COLUMN_NAME, DATA_TYPE
1685 FROM INFORMATION_SCHEMA.COLUMNS
1686 WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = '" . $db->sql_escape($table_name) . "'";
1687 $result_fields = $db->sql_query($sql);
1688
1689 $i_num_fields = 0;
1690 while ($row = $db->sql_fetchrow($result_fields))
1691 {
1692 $ary_type[$i_num_fields] = $row['DATA_TYPE'];
1693 $ary_name[$i_num_fields] = $row['COLUMN_NAME'];
1694 $i_num_fields++;
1695 }
1696 $db->sql_freeresult($result_fields);
1697
1698 $sql = "SELECT 1 as has_identity
1699 FROM INFORMATION_SCHEMA.COLUMNS
1700 WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
1701 $result2 = $db->sql_query($sql);
1702 $row2 = $db->sql_fetchrow($result2);
1703
1704 if (!empty($row2['has_identity']))
1705 {
1706 $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
1707 $ident_set = true;
1708 }
1709 $db->sql_freeresult($result2);
1710
1711 while ($row = $db->sql_fetchrow($result))
1712 {
1713 $schema_vals = $schema_fields = array();
1714
1715 // Build the SQL statement to recreate the data.
1716 for ($i = 0; $i < $i_num_fields; $i++)
1717 {
1718 $str_val = $row[$ary_name[$i]];
1719
1720 // defaults to type number - better quote just to be safe, so check for is_int too
1721 if (is_int($ary_type[$i]) || preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
1722 {
1723 $str_quote = '';
1724 $str_empty = "''";
1725 $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
1726 }
1727 else if (preg_match('#date|timestamp#i', $ary_type[$i]))
1728 {
1729 if (empty($str_val))
1730 {
1731 $str_quote = '';
1732 }
1733 else
1734 {
1735 $str_quote = "'";
1736 }
1737 }
1738 else
1739 {
1740 $str_quote = '';
1741 $str_empty = 'NULL';
1742 }
1743
1744 if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
1745 {
1746 $str_val = $str_empty;
1747 }
1748
1749 $schema_vals[$i] = $str_quote . $str_val . $str_quote;
1750 $schema_fields[$i] = $ary_name[$i];
1751 }
1752
1753 // Take the ordered fields and their associated data and build it
1754 // into a valid sql statement to recreate that field in the data.
1755 $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
1756
1757 $this->flush($sql_data);
1758 $sql_data = '';
1759 }
1760 $db->sql_freeresult($result);
1761
1762 if ($ident_set)
1763 {
1764 $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
1765 }
1766 $this->flush($sql_data);
1767 }
1768
1769 function write_data_odbc($table_name)
1770 {
1771 global $db;
1772 $ary_type = $ary_name = array();
1773 $ident_set = false;
1774 $sql_data = '';
1775
1776 // Grab all of the data from current table.
1777 $sql = "SELECT *
1778 FROM $table_name";
1779 $result = $db->sql_query($sql);
1780
1781 $retrieved_data = odbc_num_rows($result);
1782
1783 if ($retrieved_data)
1784 {
1785 $sql = "SELECT 1 as has_identity
1786 FROM INFORMATION_SCHEMA.COLUMNS
1787 WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
1788 $result2 = $db->sql_query($sql);
1789 $row2 = $db->sql_fetchrow($result2);
1790 if (!empty($row2['has_identity']))
1791 {
1792 $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
1793 $ident_set = true;
1794 }
1795 $db->sql_freeresult($result2);
1796 }
1797
1798 $i_num_fields = odbc_num_fields($result);
1799
1800 for ($i = 0; $i < $i_num_fields; $i++)
1801 {
1802 $ary_type[$i] = odbc_field_type($result, $i + 1);
1803 $ary_name[$i] = odbc_field_name($result, $i + 1);
1804 }
1805
1806 while ($row = $db->sql_fetchrow($result))
1807 {
1808 $schema_vals = $schema_fields = array();
1809
1810 // Build the SQL statement to recreate the data.
1811 for ($i = 0; $i < $i_num_fields; $i++)
1812 {
1813 $str_val = $row[$ary_name[$i]];
1814
1815 if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
1816 {
1817 $str_quote = '';
1818 $str_empty = "''";
1819 $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
1820 }
1821 else if (preg_match('#date|timestamp#i', $ary_type[$i]))
1822 {
1823 if (empty($str_val))
1824 {
1825 $str_quote = '';
1826 }
1827 else
1828 {
1829 $str_quote = "'";
1830 }
1831 }
1832 else
1833 {
1834 $str_quote = '';
1835 $str_empty = 'NULL';
1836 }
1837
1838 if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
1839 {
1840 $str_val = $str_empty;
1841 }
1842
1843 $schema_vals[$i] = $str_quote . $str_val . $str_quote;
1844 $schema_fields[$i] = $ary_name[$i];
1845 }
1846
1847 // Take the ordered fields and their associated data and build it
1848 // into a valid sql statement to recreate that field in the data.
1849 $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
1850
1851 $this->flush($sql_data);
1852
1853 $sql_data = '';
1854
1855 }
1856 $db->sql_freeresult($result);
1857
1858 if ($retrieved_data && $ident_set)
1859 {
1860 $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
1861 }
1862 $this->flush($sql_data);
1863 }
1864
1865 }
1866
1867 class oracle_extractor extends base_extractor
1868 {
1869 function write_table($table_name)
1870 {
1871 global $db;
1872 $sql_data = '-- Table: ' . $table_name . "\n";
1873 $sql_data .= "DROP TABLE $table_name\n/\n";
1874 $sql_data .= "\nCREATE TABLE $table_name (\n";
1875
1876 $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT
1877 FROM ALL_TAB_COLS
1878 WHERE table_name = '{$table_name}'";
1879 $result = $db->sql_query($sql);
1880
1881 $rows = array();
1882 while ($row = $db->sql_fetchrow($result))
1883 {
1884 $line = ' "' . $row['column_name'] . '" ' . $row['data_type'];
1885
1886 if ($row['data_type'] !== 'CLOB')
1887 {
1888 if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR')
1889 {
1890 $line .= '(' . $row['data_precision'] . ')';
1891 }
1892 else
1893 {
1894 $line .= '(' . $row['data_length'] . ')';
1895 }
1896 }
1897
1898 if (!empty($row['data_default']))
1899 {
1900 $line .= ' DEFAULT ' . $row['data_default'];
1901 }
1902
1903 if ($row['nullable'] == 'N')
1904 {
1905 $line .= ' NOT NULL';
1906 }
1907 $rows[] = $line;
1908 }
1909 $db->sql_freeresult($result);
1910
1911 $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
1912 FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
1913 WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
1914 AND B.CONSTRAINT_TYPE = 'P'
1915 AND A.TABLE_NAME = '{$table_name}'";
1916 $result = $db->sql_query($sql);
1917
1918 $primary_key = array();
1919 $contraint_name = '';
1920 while ($row = $db->sql_fetchrow($result))
1921 {
1922 $constraint_name = '"' . $row['constraint_name'] . '"';
1923 $primary_key[] = '"' . $row['column_name'] . '"';
1924 }
1925 $db->sql_freeresult($result);
1926
1927 if (sizeof($primary_key))
1928 {
1929 $rows[] = " CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')';
1930 }
1931
1932 $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
1933 FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
1934 WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
1935 AND B.CONSTRAINT_TYPE = 'U'
1936 AND A.TABLE_NAME = '{$table_name}'";
1937 $result = $db->sql_query($sql);
1938
1939 $unique = array();
1940 $contraint_name = '';
1941 while ($row = $db->sql_fetchrow($result))
1942 {
1943 $constraint_name = '"' . $row['constraint_name'] . '"';
1944 $unique[] = '"' . $row['column_name'] . '"';
1945 }
1946 $db->sql_freeresult($result);
1947
1948 if (sizeof($unique))
1949 {
1950 $rows[] = " CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')';
1951 }
1952
1953 $sql_data .= implode(",\n", $rows);
1954 $sql_data .= "\n)\n/\n";
1955
1956 $sql = "SELECT A.REFERENCED_NAME, C.*
1957 FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C
1958 WHERE A.REFERENCED_TYPE = 'SEQUENCE'
1959 AND A.NAME = B.TRIGGER_NAME
1960 AND B.TABLE_NAME = '{$table_name}'
1961 AND C.SEQUENCE_NAME = A.REFERENCED_NAME";
1962 $result = $db->sql_query($sql);
1963
1964 $type = request_var('type', '');
1965
1966 while ($row = $db->sql_fetchrow($result))
1967 {
1968 $sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n";
1969 $sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\"";
1970
1971 if ($type == 'full')
1972 {
1973 $sql_data .= ' START WITH ' . $row['last_number'];
1974 }
1975
1976 $sql_data .= "\n/\n";
1977 }
1978 $db->sql_freeresult($result);
1979
1980 $sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY
1981 FROM USER_TRIGGERS
1982 WHERE TABLE_NAME = '{$table_name}'";
1983 $result = $db->sql_query($sql);
1984 while ($row = $db->sql_fetchrow($result))
1985 {
1986 $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n";
1987 }
1988 $db->sql_freeresult($result);
1989
1990 $sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME
1991 FROM USER_INDEXES A, USER_IND_COLUMNS B
1992 WHERE A.UNIQUENESS = 'NONUNIQUE'
1993 AND A.INDEX_NAME = B.INDEX_NAME
1994 AND B.TABLE_NAME = '{$table_name}'";
1995 $result = $db->sql_query($sql);
1996
1997 $index = array();
1998
1999 while ($row = $db->sql_fetchrow($result))
2000 {
2001 $index[$row['index_name']][] = $row['column_name'];
2002 }
2003
2004 foreach ($index as $index_name => $column_names)
2005 {
2006 $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n";
2007 }
2008 $db->sql_freeresult($result);
2009 $this->flush($sql_data);
2010 }
2011
2012 function write_data($table_name)
2013 {
2014 global $db;
2015 $ary_type = $ary_name = array();
2016
2017 // Grab all of the data from current table.
2018 $sql = "SELECT *
2019 FROM $table_name";
2020 $result = $db->sql_query($sql);
2021
2022 $i_num_fields = ocinumcols($result);
2023
2024 for ($i = 0; $i < $i_num_fields; $i++)
2025 {
2026 $ary_type[$i] = ocicolumntype($result, $i + 1);
2027 $ary_name[$i] = ocicolumnname($result, $i + 1);
2028 }
2029
2030 $sql_data = '';
2031
2032 while ($row = $db->sql_fetchrow($result))
2033 {
2034 $schema_vals = $schema_fields = array();
2035
2036 // Build the SQL statement to recreate the data.
2037 for ($i = 0; $i < $i_num_fields; $i++)
2038 {
2039 // Oracle uses uppercase - we use lowercase
2040 $str_val = $row[strtolower($ary_name[$i])];
2041
2042 if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i]))
2043 {
2044 $str_quote = '';
2045 $str_empty = "''";
2046 $str_val = sanitize_data_oracle($str_val);
2047 }
2048 else if (preg_match('#date|timestamp#i', $ary_type[$i]))
2049 {
2050 if (empty($str_val))
2051 {
2052 $str_quote = '';
2053 }
2054 else
2055 {
2056 $str_quote = "'";
2057 }
2058 }
2059 else
2060 {
2061 $str_quote = '';
2062 $str_empty = 'NULL';
2063 }
2064
2065 if (empty($str_val) && $str_val !== '0')
2066 {
2067 $str_val = $str_empty;
2068 }
2069
2070 $schema_vals[$i] = $str_quote . $str_val . $str_quote;
2071 $schema_fields[$i] = '"' . $ary_name[$i] . '"';
2072 }
2073
2074 // Take the ordered fields and their associated data and build it
2075 // into a valid sql statement to recreate that field in the data.
2076 $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n";
2077
2078 $this->flush($sql_data);
2079 }
2080 $db->sql_freeresult($result);
2081 }
2082
2083 function write_start($prefix)
2084 {
2085 $sql_data = "--\n";
2086 $sql_data .= "-- phpBB Backup Script\n";
2087 $sql_data .= "-- Dump of tables for $prefix\n";
2088 $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
2089 $sql_data .= "--\n";
2090 $this->flush($sql_data);
2091 }
2092 }
2093
2094 // 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)
2095 function get_usable_memory()
2096 {
2097 $val = trim(@ini_get('memory_limit'));
2098
2099 if (preg_match('/(\\d+)([mkg]?)/i', $val, $regs))
2100 {
2101 $memory_limit = (int) $regs[1];
2102 switch ($regs[2])
2103 {
2104
2105 case 'k':
2106 case 'K':
2107 $memory_limit *= 1024;
2108 break;
2109
2110 case 'm':
2111 case 'M':
2112 $memory_limit *= 1048576;
2113 break;
2114
2115 case 'g':
2116 case 'G':
2117 $memory_limit *= 1073741824;
2118 break;
2119 }
2120
2121 // how much memory PHP requires at the start of export (it is really a little less)
2122 if ($memory_limit > 6100000)
2123 {
2124 $memory_limit -= 6100000;
2125 }
2126
2127 // allow us to consume half of the total memory available
2128 $memory_limit /= 2;
2129 }
2130 else
2131 {
2132 // set the buffer to 1M if we have no clue how much memory PHP will give us :P
2133 $memory_limit = 1048576;
2134 }
2135
2136 return $memory_limit;
2137 }
2138
2139 function sanitize_data_mssql($text)
2140 {
2141 $data = preg_split('/[\n\t\r\b\f]/', $text);
2142 preg_match_all('/[\n\t\r\b\f]/', $text, $matches);
2143
2144 $val = array();
2145
2146 foreach ($data as $value)
2147 {
2148 if (strlen($value))
2149 {
2150 $val[] = "'" . $value . "'";
2151 }
2152 if (sizeof($matches[0]))
2153 {
2154 $val[] = 'char(' . ord(array_shift($matches[0])) . ')';
2155 }
2156 }
2157
2158 return implode('+', $val);
2159 }
2160
2161 function sanitize_data_oracle($text)
2162 {
2163 // $data = preg_split('/[\0\n\t\r\b\f\'"\/\\\]/', $text);
2164 // preg_match_all('/[\0\n\t\r\b\f\'"\/\\\]/', $text, $matches);
2165 $data = preg_split('/[\0\b\f\'\/]/', $text);
2166 preg_match_all('/[\0\r\b\f\'\/]/', $text, $matches);
2167
2168 $val = array();
2169
2170 foreach ($data as $value)
2171 {
2172 if (strlen($value))
2173 {
2174 $val[] = "'" . $value . "'";
2175 }
2176 if (sizeof($matches[0]))
2177 {
2178 $val[] = 'chr(' . ord(array_shift($matches[0])) . ')';
2179 }
2180 }
2181
2182 return implode('||', $val);
2183 }
2184
2185 function sanitize_data_generic($text)
2186 {
2187 $data = preg_split('/[\n\t\r\b\f]/', $text);
2188 preg_match_all('/[\n\t\r\b\f]/', $text, $matches);
2189
2190 $val = array();
2191
2192 foreach ($data as $value)
2193 {
2194 if (strlen($value))
2195 {
2196 $val[] = "'" . $value . "'";
2197 }
2198 if (sizeof($matches[0]))
2199 {
2200 $val[] = "'" . array_shift($matches[0]) . "'";
2201 }
2202 }
2203
2204 return implode('||', $val);
2205 }
2206
2207 // modified from PHP.net
2208 function fgetd(&$fp, $delim, $read, $seek, $eof, $buffer = 8192)
2209 {
2210 $record = '';
2211 $delim_len = strlen($delim);
2212
2213 while (!$eof($fp))
2214 {
2215 $pos = strpos($record, $delim);
2216 if ($pos === false)
2217 {
2218 $record .= $read($fp, $buffer);
2219 if ($eof($fp) && ($pos = strpos($record, $delim)) !== false)
2220 {
2221 $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR);
2222 return substr($record, 0, $pos);
2223 }
2224 }
2225 else
2226 {
2227 $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR);
2228 return substr($record, 0, $pos);
2229 }
2230 }
2231
2232 return false;
2233 }
2234
2235 function fgetd_seekless(&$fp, $delim, $read, $seek, $eof, $buffer = 8192)
2236 {
2237 static $array = array();
2238 static $record = '';
2239
2240 if (!sizeof($array))
2241 {
2242 while (!$eof($fp))
2243 {
2244 if (strpos($record, $delim) !== false)
2245 {
2246 $array = explode($delim, $record);
2247 $record = array_pop($array);
2248 break;
2249 }
2250 else
2251 {
2252 $record .= $read($fp, $buffer);
2253 }
2254 }
2255 if ($eof($fp) && strpos($record, $delim) !== false)
2256 {
2257 $array = explode($delim, $record);
2258 $record = array_pop($array);
2259 }
2260 }
2261
2262 if (sizeof($array))
2263 {
2264 return array_shift($array);
2265 }
2266
2267 return false;
2268 }
2269