science-ation/config/backuprestore.php

381 lines
13 KiB
PHP

<?
/*
This file is part of the 'Science Fair In A Box' project
SFIAB Website: http://www.sfiab.ca
Copyright (C) 2008 James Grant <james@lightbox.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
?>
<?
require("../common.inc.php");
require_once("../user.inc.php");
user_auth_required('committee', 'config');
//make sure backup/restore folder exists, and htaccess it to deny access
if(!file_exists("../data/backuprestore"))
mkdir("../data/backuprestore");
if(!file_exists("../data/backuprestore/.htaccess"))
file_put_contents("../data/backuprestore/.htaccess","Order Deny,Allow\r\nDeny From All\r\n");
if(get_value_from_array($_GET,'action') == "backup") {
$ts=time();
$dump="#SFIAB SQL BACKUP: ".date("r",$ts)."\n";
$dump.="#SFIAB VERSION: ".$config['version']."\n";
$dump.="#SFIAB DB VERSION: ".$config['DBVERSION']."\n";
$dump.="#SFIAB FAIR NAME: ".$config['fairname']."\n";
$dump.="#-------------------------------------------------\n";
$tableq=$pdo->prepare("SHOW TABLES FROM `$DBNAME`");
$tableq->execute();
while($tr=$tableq->fetch(PDO::FETCH_NUM)) {
$table=$tr[0];
$dump.="#TABLE: $table\n";
$columnq=$pdo->prepare("SHOW COLUMNS FROM `$table`");
$columnq->execute();
$str="INSERT INTO `$table` (";
unset($fields);
$fields=array();
while($cr=$columnq->fetch(PDO::FETCH_OBJ)) {
$str.="`".$cr->Field."`,";
$fields[]=$cr->Field;
}
$str=substr($str,0,-1);
$str.=") VALUES (";
$dataq=$pdo->prepare("SELECT * FROM `$table` ORDER BY `{$fields[0]}`");
$dataq->execute();
while($data=$dataq->fetch(PDO::FETCH_OBJ)) {
$insertstr=$str;
foreach($fields AS $field) {
if(is_null($data->$field))
$insertstr.="NULL,";
else
{
$escaped=str_replace("\\","\\\\",$data->$field);
$escaped=str_replace("'","''",$escaped);
$escaped=str_replace("\n","\\n",$escaped);
$escaped=str_replace("\r","\\r",$escaped);
$insertstr.="'".$escaped."',";
}
}
$insertstr=substr($insertstr,0,-1);
$insertstr.=");";
$dump.=$insertstr."\n";
}
}
header("Content-Type: text/sql");
header("Content-Disposition: attachment; filename=sfiab_backup_".date("Y-m-d-H-i-s",$ts).".sql");
header("Content-Length: ".strlen($dump));
//Make IE with SSL work
header("Pragma: public");
echo $dump;
}
else if($_POST['action']=="restore") {
echo send_header("Database Backup/Restore",
array('Committee Main' => 'committee_main.php',
'SFIAB Configuration' => 'config/index.php')
,"backup_restore"
);
echo i18n("Processing file: %1",array($_FILES['restore']['name']))."<br />\n";
echo "<br />\n";
do {
//hmm just some random filename
$tmpfilename=md5(rand().time().$_FILES['restore']['name']);
} while(file_exists("../data/backuprestore/$tmpfilename"));
move_uploaded_file($_FILES['restore']['tmp_name'],"../data/backuprestore/$tmpfilename");
$fp=fopen("../data/backuprestore/$tmpfilename","r");
for($x=0;$x<4;$x++) {
$line=fgets($fp,1024);
$hdr[$x]=split(":",trim($line),2);
}
fclose($fp);
if(trim($hdr[0][0])=="#SFIAB SQL BACKUP") {
echo "<table class=\"tableview\">\n";
$now=date("r");
echo "<tr><th>".i18n("Information")."</th><th>".i18n("Restore File")."</th><th>".i18n("Live System")."</th></tr>\n";
if(trim($hdr[0][1])<trim($now)) $cl="happy"; else { $cl="error"; $err=true; }
echo "<tr class=\"$cl\"><td>".i18n("Date/Time")."</td><td>".$hdr[0][1]."</td><td>$now</td></tr>\n";
if(version_compare(trim($hdr[1][1]),$config['version'])==0) $cl="happy"; else { $cl="error"; $err=true; }
echo "<tr class=\"$cl\"><td>".i18n("SFIAB Version")."</td><td>".$hdr[1][1]."</td><td>".$config['version']."</td></tr>\n";
if(version_compare(trim($hdr[2][1]),$config['DBVERSION'])==0) $cl="happy"; else { $cl="error"; $err=true; }
echo "<tr class=\"$cl\"><td>".i18n("Database Version")."</td><td>".$hdr[2][1]."</td><td>".$config['DBVERSION']."</td></tr>\n";
if(trim($hdr[3][1])==$config['fairname']) $cl="happy"; else { $cl="error"; $err=true; }
echo "<tr class=\"$cl\"><td>".i18n("Fair Name")."</td><td>".$hdr[3][1]."</td><td>".$config['fairname']."</td></tr>\n";
echo "</table>\n";
echo "<br />\n";
if($err) {
echo error(i18n("Warning, there are discrepencies between the restore file and your current live system. Proceed at your own risk!"));
}
echo "<form method=\"post\" action=\"backuprestore.php\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"restoreproceed\">\n";
echo "<input type=\"hidden\" name=\"filename\" value=\"".$_FILES['restore']['name']."\">\n";
echo "<input type=\"hidden\" name=\"realfilename\" value=\"$tmpfilename\">\n";
echo "<input type=\"submit\" value=\"".i18n("Proceed with Database Restore")."\">";
echo "</form>\n";
echo "<br />\n";
echo "<a href=\"backuprestore.php\">";
echo i18n("If you are not going to proceed, please click here to clean up the temporary files which may contain confidential information!");
echo "</a>\n";
}
else
{
echo error(i18n("This file is NOT a SFIAB SQL BACKUP file"));
echo i18n("Only backups created with the SFIAB Backup Creator can be used to restore from.");
echo "<br />\n";
}
send_footer();
}
else if($_POST['action']=="restoreproceed") {
echo send_header("Database Backup/Restore",
array('Committee Main' => 'committee_main.php',
'SFIAB Configuration' => 'config/index.php')
,"backup_restore"
);
//make sure the filename's good before we used it
if(mb_ereg("^[a-z0-9]{32}$",$_POST['realfilename']) && file_exists("../data/backuprestore/".$_POST['realfilename'])) {
$filename=$_POST['realfilename'];
echo i18n("Proceeding with database restore from %1",array($_POST['filename']))."...";
$lines=file("../data/backuprestore/$filename");
$err=false;
echo "<pre>";
foreach($lines AS $line) {
$line=trim($line);
if(mb_ereg("^#TABLE: (.*)",$line,$args)) {
//empty out the table
$sql="TRUNCATE TABLE `".$args[1]."`";
// echo $sql."\n";
$stmt = $pdo->prepare($sql);
$stmt->execute();
}
else if(mb_ereg("^#",$line)) {
//just skip it
}
else
{
//insert the new data
$stmt = $pdo->prepare($line);
$stmt->execute();
if($pdo->errorInfo()) {
echo $line."\n";
echo $pdo->errorInfo()."\n";
$err=true;
}
}
}
echo "</pre>";
if($err) {
echo error(i18n("An error occured while importing the restore database"));
}
else
echo happy(i18n("Database successfully restored"));
unlink("../data/backuprestore/$filename");
}
else
echo error(i18n("Invalid filename"));
send_footer();
}
else if ($_POST['action'] == 'clean_judges') {
//select all judges
$query = $pdo->prepare('SELECT * FROM users WHERE types LIKE "judge"');
$query->execute();
echo $pdo->errorInfo();
// Go through each judge and test:
while($judge = $query->fetch(PDO::FETCH_ASSOC)){
//if they are deleted
if ($judge['deleted'] == 'yes') {
// Make types an array if it isn't already. Allows user_purge function to work properly
if (!is_array($judge['types'])){
$judge['types'] = array($judge['types']);
}
user_purge($judge, 'judge');
}
else{
// Find max year of judge
$max_year_query = $pdo->prepare('SELECT year FROM users WHERE uid = '. $judge['uid'] .' ORDER BY year DESC limit 1');
$max_year_query->execute();
$judge_max_year = $max_year_query->fetch(PDO::FETCH_ASSOC);
// Grab old judge info.
// Old judge info consists of all entries in the database that are not the most recent for the specific judge
$deletable = $pdo->prepare('SELECT * FROM users WHERE uid ='. $judge['uid'] .' AND year NOT LIKE '.$judge_max_year['year']);
$deletable->execute();
// and if they have old data from previous fair years
if ($deletable->rowCount() > 0){
// delete old data one by one
while ($old_judge_data = $deletable->fetch(PDO::FETCH_ASSOC)){
if (!is_array($old_judge_data['type'])){
$old_judge_data['types'] = array($old_judge_data['types']);
}
user_purge($old_judge_data, 'judge');
}
}
}
}
echo send_header("Database Backup/Restore",
array('Committee Main' => 'committee_main.php',
'SFIAB Configuration' => 'config/index.php')
,"backup_restore"
);
$stmt = $pdo->prepare("OPTIMIZE TABLE users, users_judge");
$stmt->execute();
$str = $pdo->errorInfo();
echo $str;
if($str == '')
echo happy(i18n("Old judge data purged."));
else{
error(i18n($str));}
}
else if ($_POST['action'] == 'clean_parents') {
$query_parents = $pdo->prepare('SELECT * FROM users WHERE types LIKE "parent" AND year !='.$config['FAIRYEAR']);
$query_parents->execute();
while($parent = $query_parents->fetch(PDO::FETCH_ASSOC)){
if (!is_array($parent['types'])){
$parent['types'] = array($parent['types']);
}
user_purge($parent, 'parent');
}
echo send_header("Database Backup/Restore",
array('Committee Main' => 'committee_main.php',
'SFIAB Configuration' => 'config/index.php')
,"backup_restore"
);
$stmt = $pdo->prepare("OPTIMIZE TABLE users, users_parent");
$stmt->execute();
$str = $pdo->errorInfo();
echo $str;
if($str == '')
echo happy(i18n("Old parent data purged."));
else{
error(i18n($str));}
}
else
{
echo send_header("Database Backup/Restore",
array('Committee Main' => 'committee_main.php',
'SFIAB Configuration' => 'config/index.php')
,"backup_restore"
);
//we try to remove temp files every time we load this page, who knows, maybe they navigated away
//last time instead of clicking the link to come back here
$dh=opendir("../data/backuprestore");
$removed=false;
while($fn=readdir($dh)) {
if(mb_ereg("[a-z0-9]{32}",$fn)) {
unlink("../data/backuprestore/$fn");
$removed=true;
}
}
closedir($dh);
if($removed) {
echo happy(i18n("Temporary files successfully removed"));
}
echo "<h3>".i18n("Backup Database")."</h3>\n";
echo "<a href=\"backuprestore.php?action=backup\">".i18n("Create Database Backup File")."</a><br />\n";
echo "<br /><br />\n";
echo "<hr />\n";
echo "<h3>".i18n("Restore Database")."</h3>\n";
echo error(i18n("WARNING: Importing a backup will completely DESTROY all data currently in the database and replace it with what is in the backup file"));
echo "<form method=\"post\" action=\"backuprestore.php\" enctype=\"multipart/form-data\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"restore\">\n";
echo "<input type=\"file\" name=\"restore\">\n";
echo "<input type=\"submit\" value=\"".i18n("Upload Restore File")."\">\n";
echo "</form>\n";
echo "<br>";
echo "<h3>".i18n("Clean Database")."</h3>\n";
echo error(i18n("WARNING: Cleaning the database COMPLETELY DELETES old data on users"));
echo "<font size = 4 color=\"red\"> RECOMMENDED: Backup database before using the below buttons</font><br><br>";
echo "<font color=\"red\"> Remove Old Judge Data <ul> <li> All information about who has judged in past fairs will be lost
<li> All deleted judges will be purged from the system </ul></font>";
echo "<br><font color=\"red\"> Remove Old Emergency Contact / Parent Data<ul> <li> All parent information or other emergency contact information from all previous fair years will be purged from the system
<li> It will no longer be possible to email any emergency contacts from previous fair years once the button is clicked </ul></font><br>";
echo "<table>";
echo "<tr><td style = \"width: 46%\">";
echo "<form method=\"post\" action=\"backuprestore.php\" enctype=\"multipart/form-data\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"clean_judges\">\n";
echo "<input type=\"submit\" onClick=\"return confirmClick('Are you sure you wish to purge old judge data?')\" value=\"".i18n("Remove Old Judge Data")."\">\n";
echo "</form>";
echo "</td><td>";
echo "<form method=\"post\" action=\"backuprestore.php\" enctype=\"multipart/form-data\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"clean_parents\">\n";
echo "<input type=\"submit\" onClick=\"return confirmClick('Are you sure you wish to purge old parent data?')\" value=\"".i18n("Remove Old Emergency Contact / Parent Data")."\">\n";
echo "</form>";
send_footer();
}
?>