| [ Index ] |
PHP Cross Reference of Nucleus CMS 3.64 |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/) 4 * Copyright (C) 2002-2009 The Nucleus Group 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * (see nucleus/documentation/index.html#license for more info) 11 */ 12 /** 13 * Scripts to create/restore a backup of the Nucleus database 14 * 15 * Based on code in phpBB (http://phpBB.sourceforge.net) 16 * 17 * @license http://nucleuscms.org/license.txt GNU General Public License 18 * @copyright Copyright (C) 2002-2009 The Nucleus Group 19 * @version $Id: backup.php 1470 2010-11-29 22:10:16Z ftruscot $ 20 */ 21 22 23 class Backup 24 { 25 26 /** 27 * Constructor 28 */ 29 function Backup() 30 { 31 // do nothing 32 } 33 34 35 /** 36 * This function creates an sql dump of the database and sends it to 37 * the user as a file (can be gzipped if they want) 38 * 39 * @requires 40 * no output may have preceded (new headers are sent) 41 * @param gzip 42 * 1 = compress backup file, 0 = no compression (default) 43 */ 44 function do_backup($gzip = 0) { 45 global $manager; 46 47 // tables of which backup is needed 48 $tables = array( 49 sql_table('actionlog'), 50 sql_table('ban'), 51 sql_table('blog'), 52 sql_table('comment'), 53 sql_table('config'), 54 sql_table('item'), 55 sql_table('karma'), 56 sql_table('member'), 57 sql_table('skin'), 58 sql_table('skin_desc'), 59 sql_table('team'), 60 sql_table('template'), 61 sql_table('template_desc'), 62 sql_table('plugin'), 63 sql_table('plugin_event'), 64 sql_table('plugin_option'), 65 sql_table('plugin_option_desc'), 66 sql_table('category'), 67 sql_table('activation'), 68 sql_table('tickets'), 69 ); 70 71 // add tables that plugins want to backup to the list 72 // catch all output generated by plugins 73 ob_start(); 74 $res = sql_query('SELECT pfile FROM '.sql_table('plugin')); 75 while ($plugName = sql_fetch_object($res)) { 76 $plug =& $manager->getPlugin($plugName->pfile); 77 if ($plug) $tables = array_merge($tables, (array) $plug->getTableList()); 78 } 79 ob_end_clean(); 80 81 // remove duplicates 82 $tables = array_unique($tables); 83 84 // make sure browsers don't cache the backup 85 header("Pragma: no-cache"); 86 87 // don't allow gzip compression when extension is not loaded 88 if (($gzip != 0) && !extension_loaded("zlib")) { 89 $gzip = 0; 90 } 91 92 if ($gzip) { 93 // use an output buffer 94 @ob_start(); 95 @ob_implicit_flush(0); 96 97 // set filename 98 $filename = 'nucleus_db_backup_'.strftime("%Y-%m-%d-%H-%M-%S", time()).".sql.gz"; 99 } else { 100 $filename = 'nucleus_db_backup_'.strftime("%Y-%m-%d-%H-%M-%S", time()).".sql"; 101 } 102 103 104 // send headers that tell the browser a file is coming 105 header("Content-Type: text/x-delimtext; name=\"$filename\""); 106 header("Content-disposition: attachment; filename=$filename"); 107 108 // dump header 109 echo "#\n"; 110 echo "# This is a backup file generated by Nucleus \n"; 111 echo "# http://www.nucleuscms.org/\n"; 112 echo "#\n"; 113 echo "# backup-date: " . gmdate("d-m-Y H:i:s", time()) . " GMT\n"; 114 global $nucleus; 115 echo "# Nucleus CMS version: " . $nucleus['version'] . "\n"; 116 echo "#\n"; 117 echo "# WARNING: Only try to restore on servers running the exact same version of Nucleus\n"; 118 echo "#\n"; 119 120 // dump all tables 121 reset($tables); 122 array_walk($tables, array(&$this, '_backup_dump_table')); 123 124 if($gzip) { 125 $Size = ob_get_length(); 126 $Crc = crc32(ob_get_contents()); 127 $contents = gzcompress(ob_get_contents()); 128 ob_end_clean(); 129 echo "\x1f\x8b\x08\x00\x00\x00\x00\x00".substr($contents, 0, strlen($contents) - 4).$this->gzip_PrintFourChars($Crc).$this->gzip_PrintFourChars($Size); 130 } 131 132 exit; 133 134 } 135 136 137 /** 138 * Creates a dump for a single table 139 * ($tablename and $key are filled in by array_walk) 140 */ 141 function _backup_dump_table($tablename, $key) { 142 143 echo "#\n"; 144 echo "# TABLE: " . $tablename . "\n"; 145 echo "#\n"; 146 147 // dump table structure 148 $this->_backup_dump_structure($tablename); 149 150 // dump table contents 151 $this->_backup_dump_contents($tablename); 152 } 153 154 /** 155 * Creates a dump of the table structure for one table 156 */ 157 function _backup_dump_structure($tablename) { 158 159 // add command to drop table on restore 160 echo "DROP TABLE IF EXISTS $tablename;\n"; 161 $result = sql_query("SHOW CREATE TABLE $tablename"); 162 $create = sql_fetch_assoc($result); 163 echo $create['Create Table']; 164 echo ";\n\n"; 165 } 166 167 /** 168 * Creates a dump of the table structure for one table 169 */ 170 /* replaced by code above in 3.5 171 function _backup_dump_structure($tablename) { 172 173 // add command to drop table on restore 174 echo "DROP TABLE IF EXISTS $tablename;\n"; 175 echo "CREATE TABLE $tablename(\n"; 176 177 // 178 // Ok lets grab the fields... 179 // 180 $result = mysql_query("SHOW FIELDS FROM $tablename"); 181 $row = mysql_fetch_array($result); 182 while ($row) { 183 184 echo ' `' . $row['Field'] . '` ' . $row['Type']; 185 186 if(isset($row['Default'])) 187 echo ' DEFAULT \'' . $row['Default'] . '\''; 188 189 if($row['Null'] != "YES") 190 echo ' NOT NULL'; 191 192 if($row['Extra'] != "") 193 echo ' ' . $row['Extra']; 194 195 $row = mysql_fetch_array($result); 196 197 // add comma's except for last one 198 if ($row) 199 echo ",\n"; 200 } 201 202 // 203 // Get any Indexed fields from the database... 204 // 205 $result = mysql_query("SHOW KEYS FROM $tablename"); 206 while($row = mysql_fetch_array($result)) { 207 $kname = $row['Key_name']; 208 209 if(($kname != 'PRIMARY') && ($row['Non_unique'] == 0)) 210 $kname = "UNIQUE|$kname"; 211 if(($kname != 'PRIMARY') && ($row['Index_type'] == 'FULLTEXT')) 212 $kname = "FULLTEXT|$kname"; 213 214 if(!is_array($index[$kname])) 215 $index[$kname] = array(); 216 217 $index[$kname][] = $row['Column_name'] . ( ($row['Sub_part']) ? ' (' . $row['Sub_part'] . ')' : ''); 218 } 219 220 while(list($x, $columns) = @each($index)) { 221 echo ", \n"; 222 223 if($x == 'PRIMARY') 224 echo ' PRIMARY KEY (`' . implode($columns, '`, `') . '`)'; 225 elseif (substr($x,0,6) == 'UNIQUE') 226 echo ' UNIQUE KEY ' . substr($x,7) . ' (`' . implode($columns, '`, `') . '`)'; 227 elseif (substr($x,0,8) == 'FULLTEXT') 228 echo ' FULLTEXT KEY ' . substr($x,9) . ' (`' . implode($columns, '`, `') . '`)'; 229 elseif (($x == 'ibody') || ($x == 'cbody')) // karma 2004-05-30 quick and dirty fix. fulltext keys were not in SQL correctly. 230 echo ' FULLTEXT KEY ' . substr($x,9) . ' (`' . implode($columns, '`, `') . '`)'; 231 else 232 echo " KEY $x (`" . implode($columns, '`, `') . '`)'; 233 } 234 235 echo "\n);\n\n"; 236 } 237 */ 238 239 /** 240 * Returns the field named for the given table in the 241 * following format: 242 * 243 * (column1, column2, ..., columnn) 244 */ 245 function _backup_get_field_names($result, $num_fields) { 246 247 /* if (function_exists('mysqli_fetch_fields') ) { 248 249 $fields = mysqli_fetch_fields($result); 250 for ($j = 0; $j < $num_fields; $j++) 251 $fields[$j] = $fields[$j]->name; 252 253 } else {*/ 254 255 $fields = array(); 256 for ($j = 0; $j < $num_fields; $j++) { 257 $fields[] = sql_field_name($result, $j); 258 } 259 260 /* }*/ 261 262 return '(`' . implode('`, `', $fields) . '`)'; 263 } 264 265 /** 266 * Creates a dump of the table content for one table 267 */ 268 function _backup_dump_contents($tablename) { 269 // 270 // Grab the data from the table. 271 // 272 $result = sql_query("SELECT * FROM $tablename"); 273 274 if(sql_num_rows($result) > 0) 275 echo "\n#\n# Table Data for $tablename\n#\n"; 276 277 $num_fields = sql_num_fields($result); 278 279 // 280 // Compose fieldname list 281 // 282 $tablename_list = $this->_backup_get_field_names($result, $num_fields); 283 284 // 285 // Loop through the resulting rows and build the sql statement. 286 // 287 while ($row = sql_fetch_array($result)) 288 { 289 // Start building the SQL statement. 290 291 echo "INSERT INTO `".$tablename."` $tablename_list VALUES("; 292 293 // Loop through the rows and fill in data for each column 294 for ($j = 0; $j < $num_fields; $j++) { 295 if(!isset($row[$j])) { 296 // no data for column 297 echo ' NULL'; 298 } elseif ($row[$j] != '') { 299 // data 300 echo " '" . sql_real_escape_string($row[$j]) . "'"; 301 } else { 302 // empty column (!= no data!) 303 echo "''"; 304 } 305 306 // only add comma when not last column 307 if ($j != ($num_fields - 1)) 308 echo ","; 309 } 310 311 echo ");\n"; 312 313 } 314 315 316 echo "\n"; 317 318 } 319 320 /** 321 * copied from phpBB 322 */ 323 function gzip_PrintFourChars($Val) 324 { 325 for ($i = 0; $i < 4; $i ++) 326 { 327 $return .= chr($Val % 256); 328 $Val = floor($Val / 256); 329 } 330 return $return; 331 } 332 333 /** 334 * Restores a database backup 335 */ 336 function do_restore() { 337 338 $uploadInfo = postFileInfo('backup_file'); 339 340 // first of all: get uploaded file: 341 if (empty($uploadInfo['name'])) 342 return 'No file uploaded'; 343 if (!is_uploaded_file($uploadInfo['tmp_name'])) 344 return 'No file uploaded'; 345 346 $backup_file_name = $uploadInfo['name']; 347 $backup_file_tmpname = $uploadInfo['tmp_name']; 348 $backup_file_type = $uploadInfo['type']; 349 350 if (!file_exists($backup_file_tmpname)) 351 return 'File Upload Error'; 352 353 if (!preg_match("/^(text\/[a-zA-Z]+)|(application\/(x\-)?gzip(\-compressed)?)|(application\/octet-stream)$/is", $backup_file_type) ) 354 return 'The uploaded file is not of the correct type'; 355 356 357 if (preg_match("/\.gz/is",$backup_file_name)) 358 $gzip = 1; 359 else 360 $gzip = 0; 361 362 if (!extension_loaded("zlib") && $gzip) 363 return "Cannot decompress gzipped backup (zlib package not installed)"; 364 365 // get sql query according to gzip setting (either decompress, or not) 366 if($gzip) 367 { 368 // decompress and read 369 $gz_ptr = gzopen($backup_file_tmpname, 'rb'); 370 $sql_query = ""; 371 while( !gzeof($gz_ptr) ) 372 $sql_query .= gzgets($gz_ptr, 100000); 373 } else { 374 // just read 375 $fsize = filesize($backup_file_tmpname); 376 if ($fsize <= 0) 377 $sql_query = ''; 378 else 379 $sql_query = fread(fopen($backup_file_tmpname, 'r'), $fsize); 380 } 381 382 // time to execute the query 383 $this->_execute_queries($sql_query); 384 } 385 386 /** 387 * Executes a SQL query 388 */ 389 function _execute_queries($sql_query) { 390 if (!$sql_query) return; 391 392 // Strip out sql comments... 393 $sql_query = $this->remove_remarks($sql_query); 394 $pieces = $this->split_sql_file($sql_query); 395 396 $sql_count = count($pieces); 397 for($i = 0; $i < $sql_count; $i++) 398 { 399 $sql = trim($pieces[$i]); 400 401 if(!empty($sql) and $sql[0] != "#") 402 { 403 // DEBUG 404 // debug("Executing: " . htmlspecialchars($sql) . "\n"); 405 406 $result = sql_query($sql); 407 if (!$result) debug('SQL Error: ' . sql_error()); 408 409 } 410 } 411 412 } 413 414 /** 415 * remove_remarks will strip the sql comment lines 416 * out of an uploaded sql file 417 */ 418 function remove_remarks($sql) 419 { 420 $lines = explode("\n", $sql); 421 422 // try to keep mem. use down 423 $sql = ""; 424 425 $linecount = count($lines); 426 $output = ""; 427 428 for ($i = 0; $i < $linecount; $i++) 429 { 430 if (($i != ($linecount - 1)) || (strlen($lines[$i]) > 0)) 431 { 432 if ($lines[$i][0] != "#") 433 { 434 $output .= $lines[$i] . "\n"; 435 } 436 else 437 { 438 $output .= "\n"; 439 } 440 // Trading a bit of speed for lower mem. use here. 441 $lines[$i] = ""; 442 } 443 } 444 445 return $output; 446 447 } 448 449 /** 450 * split_sql_file will split an uploaded sql file 451 * into single sql statements. 452 * 453 * Note: expects trim() to have already been run on $sql. 454 * taken from phpBB 455 */ 456 function split_sql_file($sql) 457 { 458 // Split up our string into "possible" SQL statements. 459 $tokens = explode( ";", $sql); 460 461 // try to save mem. 462 $sql = ""; 463 $output = array(); 464 465 // we don't actually care about the matches preg gives us. 466 $matches = array(); 467 468 // this is faster than calling count($tokens) every time thru the loop. 469 $token_count = count($tokens); 470 for ($i = 0; $i < $token_count; $i++) 471 { 472 // Don't wanna add an empty string as the last thing in the array. 473 if (($i != ($token_count - 1)) || (strlen($tokens[$i] > 0))) 474 { 475 476 // even number of quotes means a complete SQL statement 477 if ($this->_evenNumberOfQuotes($tokens[$i])) 478 { 479 $output[] = $tokens[$i]; 480 $tokens[$i] = ""; // save memory. 481 } 482 else 483 { 484 // incomplete sql statement. keep adding tokens until we have a complete one. 485 // $temp will hold what we have so far. 486 $temp = $tokens[$i] . ";"; 487 $tokens[$i] = ""; // save memory.. 488 489 // Do we have a complete statement yet? 490 $complete_stmt = false; 491 492 for ($j = $i + 1; (!$complete_stmt && ($j < $token_count)); $j++) 493 { 494 // odd number of quotes means a completed statement 495 // (in combination with the odd number we had already) 496 if (!$this->_evenNumberOfQuotes($tokens[$j])) 497 { 498 $output[] = $temp . $tokens[$j]; 499 500 // save memory. 501 $tokens[$j] = ""; 502 $temp = ""; 503 504 // exit the loop. 505 $complete_stmt = true; 506 // make sure the outer loop continues at the right point. 507 $i = $j; 508 } 509 else 510 { 511 // even number of unescaped quotes. We still don't have a complete statement. 512 // (1 odd and 1 even always make an odd) 513 $temp .= $tokens[$j] . ";"; 514 // save memory. 515 $tokens[$j] = ""; 516 } 517 518 } // for.. 519 } // else 520 } 521 } 522 523 return $output; 524 } 525 526 /** 527 * sub function of split_sql_file 528 * 529 * taken from phpBB 530 */ 531 function _evenNumberOfQuotes($text) { 532 // This is the total number of single quotes in the token. 533 $total_quotes = preg_match_all("/'/", $text, $matches); 534 // Counts single quotes that are preceded by an odd number of backslashes, 535 // which means they're escaped quotes. 536 $escaped_quotes = preg_match_all("/(?<!\\\\)(\\\\\\\\)*\\\\'/", $text, $matches); 537 538 $unescaped_quotes = $total_quotes - $escaped_quotes; 539 // debug($total_quotes . "-" . $escaped_quotes . "-" . $unescaped_quotes); 540 return (($unescaped_quotes % 2) == 0); 541 } 542 543 } 544 545 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon May 2 16:14:08 2011 | Cross-referenced by PHPXref 0.7.1 |