1<?php 2/** 3 * MyBB 1.8 4 * Copyright 2014 MyBB Group, All Rights Reserved 5 * 6 * Website: http://www.mybb.com 7 * License: http://www.mybb.com/about/license 8 * 9 */ 10 11// Disallow direct access to this file for security reasons 12if(!defined("IN_MYBB")) 13{ 14 die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined."); 15} 16 17/** 18 * Allows us to refresh cache to prevent over flowing 19 * 20 * @param resource $fp 21 * @param string $contents 22 */ 23function clear_overflow($fp, &$contents) 24{ 25 global $mybb; 26 27 if($mybb->input['method'] == 'disk') 28 { 29 if($mybb->input['filetype'] == 'gzip') 30 { 31 gzwrite($fp, $contents); 32 } 33 else 34 { 35 fwrite($fp, $contents); 36 } 37 } 38 else 39 { 40 if($mybb->input['filetype'] == "gzip") 41 { 42 echo gzencode($contents); 43 } 44 else 45 { 46 echo $contents; 47 } 48 } 49 50 $contents = ''; 51} 52 53$page->add_breadcrumb_item($lang->database_backups, "index.php?module=tools-backupdb"); 54 55$plugins->run_hooks("admin_tools_backupdb_begin"); 56 57if($mybb->input['action'] == "dlbackup") 58{ 59 if(empty($mybb->input['file'])) 60 { 61 flash_message($lang->error_file_not_specified, 'error'); 62 admin_redirect("index.php?module=tools-backupdb"); 63 } 64 65 $plugins->run_hooks("admin_tools_backupdb_dlbackup"); 66 67 $file = basename($mybb->input['file']); 68 $ext = get_extension($file); 69 70 if(file_exists(MYBB_ADMIN_DIR.'backups/'.$file) && filetype(MYBB_ADMIN_DIR.'backups/'.$file) == 'file' && ($ext == 'gz' || $ext == 'sql')) 71 { 72 $plugins->run_hooks("admin_tools_backupdb_dlbackup_commit"); 73 74 // Log admin action 75 log_admin_action($file); 76 77 header('Content-disposition: attachment; filename='.$file); 78 header("Content-type: ".$ext); 79 header("Content-length: ".filesize(MYBB_ADMIN_DIR.'backups/'.$file)); 80 81 $handle = fopen(MYBB_ADMIN_DIR.'backups/'.$file, 'rb'); 82 while(!feof($handle)) 83 { 84 echo fread($handle, 8192); 85 } 86 fclose($handle); 87 } 88 else 89 { 90 flash_message($lang->error_invalid_backup, 'error'); 91 admin_redirect("index.php?module=tools-backupdb"); 92 } 93} 94 95if($mybb->input['action'] == "delete") 96{ 97 if($mybb->get_input('no')) 98 { 99 admin_redirect("index.php?module=tools-backupdb"); 100 } 101 102 $file = basename($mybb->input['file']); 103 104 if(!trim($mybb->input['file']) || !file_exists(MYBB_ADMIN_DIR.'backups/'.$file)) 105 { 106 flash_message($lang->error_backup_doesnt_exist, 'error'); 107 admin_redirect("index.php?module=tools-backupdb"); 108 } 109 110 $plugins->run_hooks("admin_tools_backupdb_delete"); 111 112 if($mybb->request_method == "post") 113 { 114 $delete = @unlink(MYBB_ADMIN_DIR.'backups/'.$file); 115 116 if($delete) 117 { 118 $plugins->run_hooks("admin_tools_backupdb_delete_commit"); 119 120 // Log admin action 121 log_admin_action($file); 122 123 flash_message($lang->success_backup_deleted, 'success'); 124 admin_redirect("index.php?module=tools-backupdb"); 125 } 126 else 127 { 128 flash_message($lang->error_backup_not_deleted, 'error'); 129 admin_redirect("index.php?module=tools-backupdb"); 130 } 131 } 132 else 133 { 134 $page->output_confirm_action("index.php?module=tools-backupdb&action=delete&file={$mybb->input['file']}", $lang->confirm_backup_deletion); 135 } 136} 137 138if($mybb->input['action'] == "backup") 139{ 140 $plugins->run_hooks("admin_tools_backupdb_backup"); 141 142 if($mybb->request_method == "post") 143 { 144 if(empty($mybb->input['tables']) || !is_array($mybb->input['tables'])) 145 { 146 flash_message($lang->error_tables_not_selected, 'error'); 147 admin_redirect("index.php?module=tools-backupdb&action=backup"); 148 } 149 150 @set_time_limit(0); 151 152 if($mybb->input['method'] == 'disk') 153 { 154 $file = MYBB_ADMIN_DIR.'backups/backup_'.date("_Ymd_His_").random_str(16); 155 156 if($mybb->input['filetype'] == 'gzip') 157 { 158 if(!function_exists('gzopen')) // check zlib-ness 159 { 160 flash_message($lang->error_no_zlib, 'error'); 161 admin_redirect("index.php?module=tools-backupdb&action=backup"); 162 } 163 164 $fp = gzopen($file.'.incomplete.sql.gz', 'w9'); 165 } 166 else 167 { 168 $fp = fopen($file.'.incomplete.sql', 'w'); 169 } 170 } 171 else 172 { 173 $file = 'backup_'.substr(md5($mybb->user['uid'].TIME_NOW), 0, 10).random_str(54); 174 if($mybb->input['filetype'] == 'gzip') 175 { 176 if(!function_exists('gzopen')) // check zlib-ness 177 { 178 flash_message($lang->error_no_zlib, 'error'); 179 admin_redirect("index.php?module=tools-backupdb&action=backup"); 180 } 181 182 // Send headers for gzip file 183 header('Content-Type: application/x-gzip'); 184 header('Content-Disposition: attachment; filename="'.$file.'.sql.gz"'); 185 } 186 else 187 { 188 // Send standard headers for .sql 189 header('Content-Type: text/x-sql'); 190 header('Content-Disposition: attachment; filename="'.$file.'.sql"'); 191 } 192 } 193 $db->set_table_prefix(''); 194 195 $time = date('dS F Y \a\t H:i', TIME_NOW); 196 $header = "-- MyBB Database Backup\n-- Generated: {$time}\n-- -------------------------------------\n\n"; 197 $contents = $header; 198 foreach($mybb->input['tables'] as $table) 199 { 200 if(!$db->table_exists($db->escape_string($table))) 201 { 202 continue; 203 } 204 if($mybb->input['analyzeoptimize'] == 1) 205 { 206 $db->optimize_table($table); 207 $db->analyze_table($table); 208 } 209 210 $field_list = array(); 211 $fields_array = $db->show_fields_from($table); 212 foreach($fields_array as $field) 213 { 214 $field_list[] = $field['Field']; 215 } 216 217 $fields = "`".implode("`,`", $field_list)."`"; 218 if($mybb->input['contents'] != 'data') 219 { 220 $structure = $db->show_create_table($table).";\n"; 221 $contents .= $structure; 222 223 if(isset($fp)) 224 { 225 clear_overflow($fp, $contents); 226 } 227 } 228 229 if($mybb->input['contents'] != 'structure') 230 { 231 if($db->engine == 'mysqli') 232 { 233 $query = mysqli_query($db->read_link, "SELECT * FROM {$db->table_prefix}{$table}", MYSQLI_USE_RESULT); 234 } 235 else 236 { 237 $query = $db->simple_select($table); 238 } 239 240 while($row = $db->fetch_array($query)) 241 { 242 $insert = "INSERT INTO {$table} ($fields) VALUES ("; 243 $comma = ''; 244 foreach($field_list as $field) 245 { 246 if(!isset($row[$field]) || is_null($row[$field])) 247 { 248 $insert .= $comma."NULL"; 249 } 250 else if($db->engine == 'mysqli') 251 { 252 $insert .= $comma."'".mysqli_real_escape_string($db->read_link, $row[$field])."'"; 253 } 254 else 255 { 256 $insert .= $comma."'".$db->escape_string($row[$field])."'"; 257 } 258 $comma = ','; 259 } 260 $insert .= ");\n"; 261 $contents .= $insert; 262 263 if(isset($fp)) 264 { 265 clear_overflow($fp, $contents); 266 } 267 } 268 $db->free_result($query); 269 } 270 } 271 272 $db->set_table_prefix(TABLE_PREFIX); 273 274 if($mybb->input['method'] == 'disk') 275 { 276 if($mybb->input['filetype'] == 'gzip') 277 { 278 gzwrite($fp, $contents); 279 gzclose($fp); 280 rename($file.'.incomplete.sql.gz', $file.'.sql.gz'); 281 } 282 else 283 { 284 fwrite($fp, $contents); 285 fclose($fp); 286 rename($file.'.incomplete.sql', $file.'.sql'); 287 } 288 289 if($mybb->input['filetype'] == 'gzip') 290 { 291 $ext = '.sql.gz'; 292 } 293 else 294 { 295 $ext = '.sql'; 296 } 297 298 $plugins->run_hooks("admin_tools_backupdb_backup_disk_commit"); 299 300 // Log admin action 301 log_admin_action("disk", $file.$ext); 302 303 $file_from_admindir = 'index.php?module=tools-backupdb&action=dlbackup&file='.basename($file).$ext; 304 flash_message("<span><em>{$lang->success_backup_created}</em></span><p>{$lang->backup_saved_to}<br />{$file}{$ext} (<a href=\"{$file_from_admindir}\">{$lang->download}</a>)</p>", 'success'); 305 admin_redirect("index.php?module=tools-backupdb"); 306 } 307 else 308 { 309 $plugins->run_hooks("admin_tools_backupdb_backup_download_commit"); 310 311 // Log admin action 312 log_admin_action("download"); 313 314 if($mybb->input['filetype'] == 'gzip') 315 { 316 echo gzencode($contents); 317 } 318 else 319 { 320 echo $contents; 321 } 322 } 323 324 exit; 325 } 326 327 $page->extra_header = " <script type=\"text/javascript\"> 328 function changeSelection(action, prefix) 329 { 330 var select_box = document.getElementById('table_select'); 331 332 for(var i = 0; i < select_box.length; i++) 333 { 334 if(action == 'select') 335 { 336 select_box[i].selected = true; 337 } 338 else if(action == 'deselect') 339 { 340 select_box[i].selected = false; 341 } 342 else if(action == 'forum' && prefix != 0) 343 { 344 select_box[i].selected = false; 345 var row = select_box[i].value; 346 var subString = row.substring(prefix.length, 0); 347 if(subString == prefix) 348 { 349 select_box[i].selected = true; 350 } 351 } 352 } 353 } 354 </script>\n"; 355 356 $page->add_breadcrumb_item($lang->new_database_backup); 357 $page->output_header($lang->new_database_backup); 358 359 $sub_tabs['database_backup'] = array( 360 'title' => $lang->database_backups, 361 'link' => "index.php?module=tools-backupdb" 362 ); 363 364 $sub_tabs['new_backup'] = array( 365 'title' => $lang->new_backup, 366 'link' => "index.php?module=tools-backupdb&action=backup", 367 'description' => $lang->new_backup_desc 368 ); 369 370 $page->output_nav_tabs($sub_tabs, 'new_backup'); 371 372 // Check if file is writable, before allowing submission 373 if(!is_writable(MYBB_ADMIN_DIR."/backups")) 374 { 375 $lang->update_button = ''; 376 $page->output_alert($lang->alert_not_writable); 377 $cannot_write = true; 378 } 379 380 $table = new Table; 381 $table->construct_header($lang->table_selection); 382 $table->construct_header($lang->backup_options); 383 384 $table_selects = array(); 385 $table_list = $db->list_tables($config['database']['database']); 386 foreach($table_list as $id => $table_name) 387 { 388 $table_selects[$table_name] = $table_name; 389 } 390 391 $form = new Form("index.php?module=tools-backupdb&action=backup", "post", "table_selection", 0, "table_selection"); 392 393 $table->construct_cell("{$lang->table_select_desc}\n<br /><br />\n<a href=\"javascript:changeSelection('select', 0);\">{$lang->select_all}</a><br />\n<a href=\"javascript:changeSelection('deselect', 0);\">{$lang->deselect_all}</a><br />\n<a href=\"javascript:changeSelection('forum', '".TABLE_PREFIX."');\">{$lang->select_forum_tables}</a>\n<br /><br />\n<div class=\"form_row\">".$form->generate_select_box("tables[]", $table_selects, false, array('multiple' => true, 'id' => 'table_select', 'size' => 20))."</div>", array('rowspan' => 5, 'width' => '50%', 'style' => 'border-bottom: 0px')); 394 $table->construct_row(); 395 396 $table->construct_cell("<strong>{$lang->file_type}</strong><br />\n{$lang->file_type_desc}<br />\n<div class=\"form_row\">".$form->generate_radio_button("filetype", "gzip", $lang->gzip_compressed, array('checked' => 1))."<br />\n".$form->generate_radio_button("filetype", "plain", $lang->plain_text)."</div>", array('width' => '50%')); 397 $table->construct_row(); 398 $table->construct_cell("<strong>{$lang->save_method}</strong><br />\n{$lang->save_method_desc}<br /><div class=\"form_row\">".$form->generate_radio_button("method", "disk", $lang->backup_directory)."<br />\n".$form->generate_radio_button("method", "download", $lang->download, array('checked' => 1))."</div>", array('width' => '50%')); 399 $table->construct_row(); 400 $table->construct_cell("<strong>{$lang->backup_contents}</strong><br />\n{$lang->backup_contents_desc}<br /><div class=\"form_row\">".$form->generate_radio_button("contents", "both", $lang->structure_and_data, array('checked' => 1))."<br />\n".$form->generate_radio_button("contents", "structure", $lang->structure_only)."<br />\n".$form->generate_radio_button("contents", "data", $lang->data_only)."</div>", array('width' => '50%')); 401 $table->construct_row(); 402 $table->construct_cell("<strong>{$lang->analyze_and_optimize}</strong><br />\n{$lang->analyze_and_optimize_desc}<br /><div class=\"form_row\">".$form->generate_yes_no_radio("analyzeoptimize")."</div>", array('width' => '50%')); 403 $table->construct_row(); 404 405 $table->output($lang->new_database_backup); 406 407 $buttons[] = $form->generate_submit_button($lang->perform_backup); 408 $form->output_submit_wrapper($buttons); 409 410 $form->end(); 411 412 $page->output_footer(); 413} 414 415if(!$mybb->input['action']) 416{ 417 $page->add_breadcrumb_item($lang->backups); 418 $page->output_header($lang->database_backups); 419 420 $sub_tabs['database_backup'] = array( 421 'title' => $lang->database_backups, 422 'link' => "index.php?module=tools-backupdb", 423 'description' => $lang->database_backups_desc 424 ); 425 426 $sub_tabs['new_backup'] = array( 427 'title' => $lang->new_backup, 428 'link' => "index.php?module=tools-backupdb&action=backup", 429 ); 430 431 $plugins->run_hooks("admin_tools_backupdb_start"); 432 433 $page->output_nav_tabs($sub_tabs, 'database_backup'); 434 435 $backups = array(); 436 $dir = MYBB_ADMIN_DIR.'backups/'; 437 $handle = opendir($dir); 438 439 if($handle !== false) 440 { 441 while(($file = readdir($handle)) !== false) 442 { 443 if(filetype(MYBB_ADMIN_DIR.'backups/'.$file) == 'file') 444 { 445 $ext = get_extension($file); 446 if($ext == 'gz' || $ext == 'sql') 447 { 448 $backups[@filemtime(MYBB_ADMIN_DIR.'backups/'.$file)] = array( 449 "file" => $file, 450 "time" => @filemtime(MYBB_ADMIN_DIR.'backups/'.$file), 451 "type" => $ext 452 ); 453 } 454 } 455 } 456 closedir($handle); 457 } 458 459 $count = count($backups); 460 krsort($backups); 461 462 $table = new Table; 463 $table->construct_header($lang->backup_filename); 464 $table->construct_header($lang->file_size, array("class" => "align_center")); 465 $table->construct_header($lang->creation_date); 466 $table->construct_header($lang->controls, array("class" => "align_center")); 467 468 foreach($backups as $backup) 469 { 470 $time = "-"; 471 if($backup['time']) 472 { 473 $time = my_date('relative', $backup['time']); 474 } 475 476 $table->construct_cell("<a href=\"index.php?module=tools-backupdb&action=dlbackup&file={$backup['file']}\">{$backup['file']}</a>"); 477 $table->construct_cell(get_friendly_size(filesize(MYBB_ADMIN_DIR.'backups/'.$backup['file'])), array("class" => "align_center")); 478 $table->construct_cell($time); 479 $table->construct_cell("<a href=\"index.php?module=tools-backupdb&action=backup&action=delete&file={$backup['file']}&my_post_key={$mybb->post_code}\" onclick=\"return AdminCP.deleteConfirmation(this, '{$lang->confirm_backup_deletion}')\">{$lang->delete}</a>", array("class" => "align_center")); 480 $table->construct_row(); 481 } 482 483 if($count == 0) 484 { 485 $table->construct_cell($lang->no_backups, array('colspan' => 4)); 486 $table->construct_row(); 487 } 488 489 $table->output($lang->existing_database_backups); 490 $page->output_footer(); 491} 492