[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * This file is part of the phpBB Forum Software package. 5 * 6 * @copyright (c) phpBB Limited <https://www.phpbb.com> 7 * @license GNU General Public License, version 2 (GPL-2.0) 8 * 9 * For full copyright and license information, please see 10 * the docs/CREDITS.txt file. 11 * 12 */ 13 14 /** 15 * @ignore 16 */ 17 if (!defined('IN_PHPBB')) 18 { 19 exit; 20 } 21 22 class acp_database 23 { 24 var $db_tools; 25 var $u_action; 26 public $page_title; 27 28 function main($id, $mode) 29 { 30 global $cache, $db, $user, $template, $table_prefix, $request; 31 global $phpbb_root_path, $phpbb_container, $phpbb_log; 32 33 $this->db_tools = $phpbb_container->get('dbal.tools'); 34 35 $user->add_lang('acp/database'); 36 37 $this->tpl_name = 'acp_database'; 38 $this->page_title = 'ACP_DATABASE'; 39 40 $action = $request->variable('action', ''); 41 42 $form_key = 'acp_database'; 43 add_form_key($form_key); 44 45 $template->assign_vars(array( 46 'MODE' => $mode 47 )); 48 49 switch ($mode) 50 { 51 case 'backup': 52 53 $this->page_title = 'ACP_BACKUP'; 54 55 switch ($action) 56 { 57 case 'download': 58 $type = $request->variable('type', ''); 59 $table = array_intersect($this->db_tools->sql_list_tables(), $request->variable('table', array(''))); 60 $format = $request->variable('method', ''); 61 62 if (!count($table)) 63 { 64 trigger_error($user->lang['TABLE_SELECT_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); 65 } 66 67 if (!check_form_key($form_key)) 68 { 69 trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); 70 } 71 72 @set_time_limit(1200); 73 @set_time_limit(0); 74 75 $time = time(); 76 77 $filename = 'backup_' . $time . '_' . unique_id(); 78 79 /** @var phpbb\db\extractor\extractor_interface $extractor Database extractor */ 80 $extractor = $phpbb_container->get('dbal.extractor'); 81 $extractor->init_extractor($format, $filename, $time, false, true); 82 83 $extractor->write_start($table_prefix); 84 85 foreach ($table as $table_name) 86 { 87 // Get the table structure 88 if ($type == 'full') 89 { 90 $extractor->write_table($table_name); 91 } 92 else 93 { 94 // We might wanna empty out all that junk :D 95 switch ($db->get_sql_layer()) 96 { 97 case 'sqlite3': 98 $extractor->flush('DELETE FROM ' . $table_name . ";\n"); 99 break; 100 101 case 'mssql_odbc': 102 case 'mssqlnative': 103 $extractor->flush('TRUNCATE TABLE ' . $table_name . "GO\n"); 104 break; 105 106 case 'oracle': 107 $extractor->flush('TRUNCATE TABLE ' . $table_name . "/\n"); 108 break; 109 110 default: 111 $extractor->flush('TRUNCATE TABLE ' . $table_name . ";\n"); 112 } 113 } 114 115 // Only supported types are full and data, therefore always write the data 116 $extractor->write_data($table_name); 117 } 118 119 $extractor->write_end(); 120 121 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_BACKUP'); 122 123 trigger_error($user->lang['BACKUP_SUCCESS'] . adm_back_link($this->u_action)); 124 break; 125 126 default: 127 $tables = $this->db_tools->sql_list_tables(); 128 asort($tables); 129 foreach ($tables as $table_name) 130 { 131 if (strlen($table_prefix) === 0 || stripos($table_name, $table_prefix) === 0) 132 { 133 $template->assign_block_vars('tables', array( 134 'TABLE' => $table_name 135 )); 136 } 137 } 138 unset($tables); 139 140 $template->assign_vars(array( 141 'U_ACTION' => $this->u_action . '&action=download' 142 )); 143 144 $available_methods = array('gzip' => 'zlib', 'bzip2' => 'bz2'); 145 146 foreach ($available_methods as $type => $module) 147 { 148 if (!@extension_loaded($module)) 149 { 150 continue; 151 } 152 153 $template->assign_block_vars('methods', array( 154 'TYPE' => $type 155 )); 156 } 157 158 $template->assign_block_vars('methods', array( 159 'TYPE' => 'text' 160 )); 161 break; 162 } 163 break; 164 165 case 'restore': 166 167 $this->page_title = 'ACP_RESTORE'; 168 169 switch ($action) 170 { 171 case 'submit': 172 $delete = $request->variable('delete', ''); 173 $file = $request->variable('file', ''); 174 175 $backup_info = $this->get_backup_file($phpbb_root_path . 'store/', $file); 176 177 if (empty($backup_info) || !is_readable($backup_info['file_name'])) 178 { 179 trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); 180 } 181 182 if ($delete) 183 { 184 if (confirm_box(true)) 185 { 186 unlink($backup_info['file_name']); 187 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_DELETE'); 188 trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action)); 189 } 190 else 191 { 192 confirm_box(false, $user->lang['DELETE_SELECTED_BACKUP'], build_hidden_fields(array('delete' => $delete, 'file' => $file))); 193 } 194 } 195 else if (confirm_box(true)) 196 { 197 switch ($backup_info['extension']) 198 { 199 case 'sql': 200 $fp = fopen($backup_info['file_name'], 'rb'); 201 $read = 'fread'; 202 $seek = 'fseek'; 203 $eof = 'feof'; 204 $close = 'fclose'; 205 $fgetd = 'fgetd'; 206 break; 207 208 case 'sql.bz2': 209 $fp = bzopen($backup_info['file_name'], 'r'); 210 $read = 'bzread'; 211 $seek = ''; 212 $eof = 'feof'; 213 $close = 'bzclose'; 214 $fgetd = 'fgetd_seekless'; 215 break; 216 217 case 'sql.gz': 218 $fp = gzopen($backup_info['file_name'], 'rb'); 219 $read = 'gzread'; 220 $seek = 'gzseek'; 221 $eof = 'gzeof'; 222 $close = 'gzclose'; 223 $fgetd = 'fgetd'; 224 break; 225 226 default: 227 trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); 228 return; 229 } 230 231 switch ($db->get_sql_layer()) 232 { 233 case 'mysqli': 234 case 'sqlite3': 235 while (($sql = $fgetd($fp, ";\n", $read, $seek, $eof)) !== false) 236 { 237 $db->sql_query($sql); 238 } 239 break; 240 241 case 'postgres': 242 $delim = ";\n"; 243 while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false) 244 { 245 $query = trim($sql); 246 247 if (substr($query, 0, 13) == 'CREATE DOMAIN') 248 { 249 list(, , $domain) = explode(' ', $query); 250 $sql = "SELECT domain_name 251 FROM information_schema.domains 252 WHERE domain_name = '$domain';"; 253 $result = $db->sql_query($sql); 254 if (!$db->sql_fetchrow($result)) 255 { 256 $db->sql_query($query); 257 } 258 $db->sql_freeresult($result); 259 } 260 else 261 { 262 $db->sql_query($query); 263 } 264 265 if (substr($query, 0, 4) == 'COPY') 266 { 267 while (($sub = $fgetd($fp, "\n", $read, $seek, $eof)) !== '\.') 268 { 269 if ($sub === false) 270 { 271 trigger_error($user->lang['RESTORE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING); 272 } 273 pg_put_line($db->get_db_connect_id(), $sub . "\n"); 274 } 275 pg_put_line($db->get_db_connect_id(), "\\.\n"); 276 pg_end_copy($db->get_db_connect_id()); 277 } 278 } 279 break; 280 281 case 'oracle': 282 while (($sql = $fgetd($fp, "/\n", $read, $seek, $eof)) !== false) 283 { 284 $db->sql_query($sql); 285 } 286 break; 287 288 case 'mssql_odbc': 289 case 'mssqlnative': 290 while (($sql = $fgetd($fp, "GO\n", $read, $seek, $eof)) !== false) 291 { 292 $db->sql_query($sql); 293 } 294 break; 295 } 296 297 $close($fp); 298 299 // Purge the cache due to updated data 300 $cache->purge(); 301 302 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_RESTORE'); 303 trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action)); 304 break; 305 } 306 else 307 { 308 confirm_box(false, $user->lang['RESTORE_SELECTED_BACKUP'], build_hidden_fields(array('file' => $file))); 309 } 310 311 default: 312 $backup_files = $this->get_file_list($phpbb_root_path . 'store/'); 313 314 if (!empty($backup_files)) 315 { 316 krsort($backup_files); 317 318 foreach ($backup_files as $name => $file) 319 { 320 $template->assign_block_vars('files', array( 321 'FILE' => sha1($file), 322 'NAME' => $user->format_date($name, 'd-m-Y H:i', true), 323 'SUPPORTED' => true, 324 )); 325 } 326 } 327 328 $template->assign_vars(array( 329 'U_ACTION' => $this->u_action . '&action=submit' 330 )); 331 break; 332 } 333 break; 334 } 335 } 336 337 /** 338 * Get backup file from file hash 339 * 340 * @param string $directory Relative path to directory 341 * @param string $file_hash Hash of selected file 342 * 343 * @return array Backup file data or empty array if unable to find file 344 */ 345 protected function get_backup_file($directory, $file_hash) 346 { 347 $backup_data = []; 348 349 $file_list = $this->get_file_list($directory); 350 $supported_extensions = $this->get_supported_extensions(); 351 352 foreach ($file_list as $file) 353 { 354 preg_match('#^backup_(\d{10,})_(?:[a-z\d]{16}|[a-z\d]{32})\.(sql(?:\.(?:gz|bz2))?)$#i', $file, $matches); 355 if (sha1($file) === $file_hash && in_array($matches[2], $supported_extensions)) 356 { 357 $backup_data = [ 358 'file_name' => $directory . $file, 359 'extension' => $matches[2], 360 ]; 361 break; 362 } 363 } 364 365 return $backup_data; 366 } 367 368 /** 369 * Get backup file list for directory 370 * 371 * @param string $directory Relative path to backup directory 372 * 373 * @return array List of backup files in specified directory 374 */ 375 protected function get_file_list($directory) 376 { 377 $supported_extensions = $this->get_supported_extensions(); 378 379 $dh = @opendir($directory); 380 381 $backup_files = []; 382 383 if ($dh) 384 { 385 while (($file = readdir($dh)) !== false) 386 { 387 if (preg_match('#^backup_(\d{10,})_(?:[a-z\d]{16}|[a-z\d]{32})\.(sql(?:\.(?:gz|bz2))?)$#i', $file, $matches)) 388 { 389 if (in_array($matches[2], $supported_extensions)) 390 { 391 $backup_files[(int) $matches[1]] = $file; 392 } 393 } 394 } 395 closedir($dh); 396 } 397 398 return $backup_files; 399 } 400 401 /** 402 * Get supported extensions for backup 403 * 404 * @return array List of supported extensions 405 */ 406 protected function get_supported_extensions() 407 { 408 $extensions = ['sql']; 409 $available_methods = ['sql.gz' => 'zlib', 'sql.bz2' => 'bz2']; 410 411 foreach ($available_methods as $type => $module) 412 { 413 if (!@extension_loaded($module)) 414 { 415 continue; 416 } 417 $extensions[] = $type; 418 } 419 420 return $extensions; 421 } 422 } 423 424 // 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) 425 function get_usable_memory() 426 { 427 $val = trim(@ini_get('memory_limit')); 428 429 if (preg_match('/(\\d+)([mkg]?)/i', $val, $regs)) 430 { 431 $memory_limit = (int) $regs[1]; 432 switch ($regs[2]) 433 { 434 435 case 'k': 436 case 'K': 437 $memory_limit *= 1024; 438 break; 439 440 case 'm': 441 case 'M': 442 $memory_limit *= 1048576; 443 break; 444 445 case 'g': 446 case 'G': 447 $memory_limit *= 1073741824; 448 break; 449 } 450 451 // how much memory PHP requires at the start of export (it is really a little less) 452 if ($memory_limit > 6100000) 453 { 454 $memory_limit -= 6100000; 455 } 456 457 // allow us to consume half of the total memory available 458 $memory_limit /= 2; 459 } 460 else 461 { 462 // set the buffer to 1M if we have no clue how much memory PHP will give us :P 463 $memory_limit = 1048576; 464 } 465 466 return $memory_limit; 467 } 468 469 function sanitize_data_mssql($text) 470 { 471 $data = preg_split('/[\n\t\r\b\f]/', $text); 472 preg_match_all('/[\n\t\r\b\f]/', $text, $matches); 473 474 $val = array(); 475 476 foreach ($data as $value) 477 { 478 if (strlen($value)) 479 { 480 $val[] = "'" . $value . "'"; 481 } 482 if (count($matches[0])) 483 { 484 $val[] = 'char(' . ord(array_shift($matches[0])) . ')'; 485 } 486 } 487 488 return implode('+', $val); 489 } 490 491 function sanitize_data_oracle($text) 492 { 493 // $data = preg_split('/[\0\n\t\r\b\f\'"\/\\\]/', $text); 494 // preg_match_all('/[\0\n\t\r\b\f\'"\/\\\]/', $text, $matches); 495 $data = preg_split('/[\0\b\f\'\/]/', $text); 496 preg_match_all('/[\0\r\b\f\'\/]/', $text, $matches); 497 498 $val = array(); 499 500 foreach ($data as $value) 501 { 502 if (strlen($value)) 503 { 504 $val[] = "'" . $value . "'"; 505 } 506 if (count($matches[0])) 507 { 508 $val[] = 'chr(' . ord(array_shift($matches[0])) . ')'; 509 } 510 } 511 512 return implode('||', $val); 513 } 514 515 function sanitize_data_generic($text) 516 { 517 $data = preg_split('/[\n\t\r\b\f]/', $text); 518 preg_match_all('/[\n\t\r\b\f]/', $text, $matches); 519 520 $val = array(); 521 522 foreach ($data as $value) 523 { 524 if (strlen($value)) 525 { 526 $val[] = "'" . $value . "'"; 527 } 528 if (count($matches[0])) 529 { 530 $val[] = "'" . array_shift($matches[0]) . "'"; 531 } 532 } 533 534 return implode('||', $val); 535 } 536 537 // modified from PHP.net 538 function fgetd(&$fp, $delim, $read, $seek, $eof, $buffer = 8192) 539 { 540 $record = ''; 541 $delim_len = strlen($delim); 542 543 while (!$eof($fp)) 544 { 545 $pos = strpos($record, $delim); 546 if ($pos === false) 547 { 548 $record .= $read($fp, $buffer); 549 if ($eof($fp) && ($pos = strpos($record, $delim)) !== false) 550 { 551 $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR); 552 return substr($record, 0, $pos); 553 } 554 } 555 else 556 { 557 $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR); 558 return substr($record, 0, $pos); 559 } 560 } 561 562 return false; 563 } 564 565 function fgetd_seekless(&$fp, $delim, $read, $seek, $eof, $buffer = 8192) 566 { 567 static $array = array(); 568 static $record = ''; 569 570 if (!count($array)) 571 { 572 while (!$eof($fp)) 573 { 574 if (strpos($record, $delim) !== false) 575 { 576 $array = explode($delim, $record); 577 $record = array_pop($array); 578 break; 579 } 580 else 581 { 582 $record .= $read($fp, $buffer); 583 } 584 } 585 if ($eof($fp) && strpos($record, $delim) !== false) 586 { 587 $array = explode($delim, $record); 588 $record = array_pop($array); 589 } 590 } 591 592 if (count($array)) 593 { 594 return array_shift($array); 595 } 596 597 return false; 598 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |