408 Zeilen
Kein EOL
15 KiB
PHP
408 Zeilen
Kein EOL
15 KiB
PHP
<?php
|
|
/**
|
|
*
|
|
* @package CL-Core
|
|
* @subpackage DB-Backup
|
|
* @version $Rev$
|
|
* @author Ortwin Pinke <o.pinke@conlite.org>
|
|
* @copyright (c) 2012-2013, conlite.org
|
|
*
|
|
* $Id$
|
|
*/
|
|
/* @var $sess Contenido_Session */
|
|
/* @var $perm Contenido_Perm */
|
|
/* @var $auth Contenido_Challenge_Crypt_Auth */
|
|
/* @var $notification Contenido_Notification */
|
|
|
|
if (!defined('CON_FRAMEWORK')) {
|
|
die('Illegal call');
|
|
}
|
|
|
|
define('CL_BACKUP_COUNT_LINES', 20000);
|
|
define('CL_BACKUP_MAX_RELOADS', 600);
|
|
define('CL_BACKUP_VERSION', 'CL DB-Backup 1.3.4');
|
|
define('CL_BACKUP_PATH', $cfg['path']['conlite_backup']);
|
|
define('CL_BACKUP_LOGFILE', $cfg['path']['conlite_logs'] . "db-backup-log.txt");
|
|
define('CL_BACKUP_START_IMG', $cfg['path']['contenido_html'] . $cfg['path']['images'] . "db_backup_start.png");
|
|
define('CL_BACKUP_START_IMG_OFF', $cfg['path']['contenido_html'] . $cfg['path']['images'] . "db_backup_start_off.png");
|
|
|
|
$aMessage = array();
|
|
$bNoBackup = false;
|
|
$bFinalStep = false;
|
|
// check backup path
|
|
if (!is_dir(CL_BACKUP_PATH) || !is_writable(CL_BACKUP_PATH)) {
|
|
$notification->displayNotification("error", i18n("Backupfolder missing or not writable!"));
|
|
$bNoBackup = true;
|
|
}
|
|
$backup_action = (isset($_GET['cl_action']) ? $_GET['cl_action'] : '');
|
|
|
|
// check dbuser rights
|
|
/*
|
|
echo "<pre>";
|
|
$oDb = new DB_ConLite();
|
|
//echo $sSql = "SHOW GRANTS FOR '".$cfg['db']['connection']['user']."'@'".$cfg['db']['connection']['host']."';";
|
|
echo $sSql = "SHOW GRANTS FOR '" . $cfg['db']['connection']['user'] . "';";
|
|
$oDb->query($sSql);
|
|
while ($oDb->next_record()) {
|
|
print_r($oDb->toArray());
|
|
}
|
|
*/
|
|
|
|
$sTable = "";
|
|
$bk_filename = str_replace(array("&cl_action=backupnow", "&"), array("", "&"), $sess->self_url()); // web28 - 2011-07-02 - Security Fix - PHP_SELF
|
|
$info_h1 = i18n("Start your Backup!");
|
|
$info_h2 = ' ';
|
|
$oImgButton = new cHTMLImage();
|
|
if ($bNoBackup) {
|
|
$oImgButton->setSrc(CL_BACKUP_START_IMG_OFF);
|
|
$oImgButton->setAlt(mi18n("Backup not possible!"));
|
|
} else {
|
|
$oImgButton->setSrc(CL_BACKUP_START_IMG);
|
|
$oImgButton->setAlt(mi18n("Click to start Backup!"));
|
|
}
|
|
$sImage = $oImgButton->render();
|
|
$oStartButton = new cHTMLLink($sess->self_url() . "&cl_action=backupnow");
|
|
$oStartButton->_setContent($sImage);
|
|
$button_back = ($bNoBackup) ? $sImage : $oStartButton->toHtml();
|
|
|
|
//aktiviert die Ausgabepufferung
|
|
ob_start();
|
|
|
|
//Start Session
|
|
session_name('dbdump');
|
|
if (!isset($_SESSION)) {
|
|
session_start();
|
|
}
|
|
//unset($_SESSION['dump']);
|
|
//#### BACKUP ANFANG #######
|
|
if (isset($_SESSION['dump'])) {
|
|
$dump = $_SESSION['dump'];
|
|
$info_h2 = ' ';
|
|
$button_back = ' ';
|
|
} else {
|
|
$oUser = new User();
|
|
$oUser->loadUserByUserID($auth->auth['uid']);
|
|
$bHasPermission = ($oUser->getUserProperty("system", "cl_backup_allowed") == 'true') ? true : false;
|
|
if (!$perm->isSysadmin() && !$bHasPermission) {
|
|
$notification->displayNotification("error", i18n("Permission denied!"));
|
|
exit();
|
|
}
|
|
}
|
|
|
|
cInclude("classes", "class.cl_db_backup.php");
|
|
|
|
if ($backup_action == 'backupnow') {
|
|
$oDB = new DB_ConLite();
|
|
$oDB2 = new DB_ConLite();
|
|
|
|
$info_h1 = i18n("Starting Backup.");
|
|
$info_h2 = ' ';
|
|
|
|
$restore = array();
|
|
unset($_SESSION['restore']);
|
|
$dump = array();
|
|
unset($_SESSION['dump']);
|
|
|
|
|
|
@set_time_limit(0);
|
|
|
|
//BOF Disable "STRICT" mode!
|
|
$vers = $oDB->getClientInfo();
|
|
if (substr($vers, 0, 1) > 4) {
|
|
$oDB->query("SET SESSION sql_mode=''");
|
|
//@mysql_query("SET SESSION sql_mode=''", $oDB->Link_ID);
|
|
}
|
|
//EOF Disable "STRICT" mode!
|
|
|
|
$mysql_version = '-- MySQL-Client-Version: ' . $oDB->getClientInfo() . "\n--\n";
|
|
|
|
$schema = '-- ConLite ' . $cfg['version'] . "\n" .
|
|
'--' . "\n" .
|
|
'-- ' . CL_BACKUP_VERSION . ' (c) 2012-' . date('Y') . ' php-backoffice.de' . "\n" .
|
|
'--' . "\n" .
|
|
'-- Database: ' . $cfg['db']['connection']['database'] . "\n" .
|
|
'-- Database Server: ' . $oDB->getServerInfo() . "\n" .
|
|
'--' . "\n" . $mysql_version .
|
|
'-- Backup Date: ' . date("r") . "\n\n";
|
|
$backup_file = 'dbd_' . $cfg['db']['connection']['database'] . '-' . date('YmdHis');
|
|
$dump['file'] = CL_BACKUP_PATH . $backup_file;
|
|
|
|
if (!isset($dump['compress'])) {
|
|
if (getEffectiveSetting("cl-backup", "use_gzip", false) == 'true') {
|
|
$dump['compress'] = true;
|
|
$dump['file'] .= '.sql.gz';
|
|
} else {
|
|
$dump['compress'] = false;
|
|
$dump['file'] .= '.sql';
|
|
}
|
|
}
|
|
|
|
if (!isset($dump['complete_inserts'])) {
|
|
if (getEffectiveSetting("cl-backup", "complete_inserts", false) == 'true') {
|
|
$dump['complete_inserts'] = 'yes';
|
|
}
|
|
}
|
|
|
|
$oDB->query("SHOW TABLE STATUS FROM `" . $cfg['db']['connection']['database'] . "` LIKE '" . $cfg['sql']['sqlprefix'] . "_%'");
|
|
$dump['num_tables'] = $oDB->num_rows();
|
|
|
|
//Tabellennamen in Array einlesen
|
|
$dump['tables'] = Array();
|
|
$dump['num_rows'] = -1;
|
|
//echo "<pre>";
|
|
if ($dump['num_tables'] > 0) {
|
|
$dump['num_rows'] = 0;
|
|
for ($i = 0; $i < $dump['num_tables']; $i++) {
|
|
$oDB->next_record();
|
|
$row = $oDB->toArray();
|
|
$dump['tables'][$i] = $row['Name'];
|
|
$oDB2->query("SELECT COUNT(*) FROM " . $row['Name']);
|
|
$oDB2->next_record();
|
|
//$result = mysql_query("SELECT COUNT(*) FROM ".$row['Name'], $oDB->Link_ID);
|
|
$aTmp = $oDB2->toArray();
|
|
$dump['num_rows'] += $aTmp[0];
|
|
//print_r($row);
|
|
}
|
|
$dump['nr'] = 0;
|
|
|
|
$dump['table_offset'] = 0;
|
|
$_SESSION['dump'] = $dump;
|
|
//echo '<pre>';
|
|
//print_r($dump);
|
|
/*
|
|
* Statuszeile kompatibel zu MySQLDumper (MSD)
|
|
* AUFBAU der Statuszeile:
|
|
* -- Status:tabellenzahl:datensätze:Multipart:Datenbankname:script:scriptversion:Kommentar:MySQLVersion:Backupflags:SQLBefore:SQLAfter:Charset:EXTINFO
|
|
* Aufbau Backupflags (1 Zeichen pro Flag, 0 oder 1, 2=unbekannt)
|
|
* (complete inserts)(extended inserts)(ignore inserts)(delayed inserts)(downgrade)(lock tables)(optimize tables)
|
|
*/
|
|
$statusline = array();
|
|
$statusline['tables'] = $dump['num_tables'];
|
|
$statusline['records'] = $dump['num_rows'];
|
|
$statusline['part'] = 'MP_0';
|
|
$statusline['dbname'] = $cfg['db']['connection']['database'];
|
|
$statusline['script'] = 'php';
|
|
$statusline['scriptversion'] = '1.24';
|
|
$statusline['comment'] = 'Backup made by ' . CL_BACKUP_VERSION;
|
|
$statusline['mysqlversion'] = $oDB->getServerInfo();
|
|
$statusline['flags'] = '2222222';
|
|
$statusline['sqlbefore'] = '';
|
|
$statusline['sqlafter'] = '';
|
|
$statusline['charset'] = $oDB->getClientEncoding();
|
|
$statusline['extinfo'] = 'EXTINFO';
|
|
|
|
$sStatLine = "-- Status:";
|
|
$sStatLine .= implode(":", $statusline) . "\n\n";
|
|
;
|
|
$schema = $sStatLine . $schema;
|
|
//die($schema);
|
|
$oClBackup = new clDbBackup();
|
|
$oClBackup->_writeToDumpFile($schema);
|
|
$selbstaufruf = '<script language="javascript" type="text/javascript">setTimeout("document.dump.submit()", 3000);</script></div>';
|
|
} else {
|
|
$aMessage['level'] = Contenido_Notification::LEVEL_ERROR;
|
|
$aMessage['text'] = "Error: Cannot read database!";
|
|
//else ERROR
|
|
}
|
|
}
|
|
//Seite neu laden wenn noch nicht alle Tabellen ausgelesen sind
|
|
if ($dump['num_tables'] > 0 && $backup_action != 'backupnow') {
|
|
|
|
if (!is_object($oClBackup)) {
|
|
$oClBackup = new clDbBackup();
|
|
}
|
|
|
|
$info_h1 = i18n("Backup in Progress!");
|
|
|
|
@set_time_limit(0);
|
|
|
|
if ($dump['nr'] < $dump['num_tables']) {
|
|
$nr = $dump['nr'];
|
|
$dump['aufruf'] ++;
|
|
$table_ok = i18n("Tables saved: ") . ($nr + 1) . '<br><br>' . i18n("Last processed: ")
|
|
. $dump['tables'][$nr] . '<br><br>' . i18n("Pageviews: ") . $dump['aufruf'];
|
|
|
|
//Neue Tabelle
|
|
if ($dump['table_offset'] == 0) {
|
|
$dump['table_records'] = $oClBackup->_writeTableHeader($dump['tables'][$nr]);
|
|
$dump['anzahl_zeilen'] = CL_BACKUP_COUNT_LINES;
|
|
$dump['table_offset'] = 1;
|
|
$dump['zeilen_offset'] = 0;
|
|
} else {
|
|
//Daten aus Tabelle lesen
|
|
//GetTableData($dump['tables'][$nr]);
|
|
$oClBackup->_writeTableData($dump['tables'][$nr]);
|
|
}
|
|
|
|
$_SESSION['dump'] = $dump;
|
|
|
|
$selbstaufruf = '<script type="text/javascript">setTimeout("document.dump.submit()", 10);</script>';
|
|
//Verhindert Endlosschleife - Script wir nach MAX_RELOADS beendet
|
|
if ($dump['aufruf'] > CL_BACKUP_MAX_RELOADS) {
|
|
$selbstaufruf = '';
|
|
}
|
|
} else { //Fertig
|
|
$info_h2 = ' ';
|
|
$info_h1 = i18n("Backup done!");
|
|
$table_ok = i18n("Tables saved: ") . $dump['nr'] . '<br><br>' . i18n("Pageviews: ") . $dump['aufruf'];
|
|
$selbstaufruf = '';
|
|
unset($_SESSION['dump']);
|
|
$oBackButton = new cHTMLLink($sess->self_url());
|
|
$oBackButton->_setContent(i18n("Go Back to Overview"));
|
|
$button_back = $oBackButton->toHtml();
|
|
$bFinalStep = true;
|
|
if (!is_object($oClBackup)) {
|
|
$oClBackup = new clDbBackup();
|
|
}
|
|
$oClBackup->writeLog();
|
|
}
|
|
}
|
|
//#### BACKUP ENDE #######
|
|
// Let's build the file table
|
|
if (!isset($_SESSION['dump']) && !$bFinalStep) {
|
|
if (!is_object($oClBackup)) {
|
|
$oClBackup = new clDbBackup();
|
|
}
|
|
$aFiles = $oClBackup->getDumpFiles(CL_BACKUP_PATH);
|
|
//print_r($aFiles);
|
|
$oFileList = new cScrollList();
|
|
$oFileList->objTable->setID("files_tab");
|
|
$oFileList->setHeader(mi18n("#"), mi18n("Date"), mi18n("Filename"), mi18n("Filesize"), mi18n("Tables/Entries"), "", mi18n("Actions"));
|
|
$oFileList->objHeaderItem->updateAttributes(array('style' => "width: 20px; padding: 0 4px;white-space:nowrap; border: 1px solid #B3B3B3; border-bottom: 0;"));
|
|
$oFileList->setSortable(1, true);
|
|
$oFileList->setSortable(2, true);
|
|
$iLoop = 0;
|
|
if (is_array($aFiles) && count($aFiles) > 0) {
|
|
foreach ($aFiles as $sKey => $aFile) {
|
|
// send file on request
|
|
if ($cl_action == 'download_file' && $fileid == $sKey) {
|
|
$oClBackup->sendFile(CL_BACKUP_PATH . $aFile['filename']);
|
|
die();
|
|
}
|
|
|
|
if ($cl_action == 'del_file' && $fileid == $sKey) {
|
|
if (unlink(CL_BACKUP_PATH . $aFile['filename'])) {
|
|
$notification->displayNotification('info', i18n("File successfully deleted."));
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$oDelImg = new cHTMLImage();
|
|
$oDelImg->setSrc($cfg['path']['contenido_html'] . $cfg['path']['images'] . "but_delete.gif");
|
|
$oDelImg->setClass("img_but");
|
|
$oDelImg->setAlt(i18n("Delete File"));
|
|
$oDelete = new cHTMLLink($sess->url($sess->self_url() . "&cl_action=del_file&fileid=$sKey"), "delete");
|
|
$oDelete->setContent($oDelImg->render());
|
|
|
|
$oDownloadImg = new cHTMLImage();
|
|
$oDownloadImg->setSrc($cfg['path']['contenido_html'] . $cfg['path']['images'] . "but_downloadlist.gif");
|
|
$oDownloadImg->setClass("img_but");
|
|
$oDownloadImg->setAlt(i18n("Download File"));
|
|
$oDownload = new cHTMLLink($sess->url($sess->self_url() . "&cl_action=download_file&fileid=$sKey"), "download");
|
|
$oDownload->setContent($oDownloadImg->render());
|
|
|
|
$aFileStats = readStatusLineFromFile(CL_BACKUP_PATH . $aFile['filename']);
|
|
if (is_array($aFileStats)) {
|
|
$sFileStats = $aFileStats['tables'] . " / " . $aFileStats['records'];
|
|
} else {
|
|
$sFileStats = '';
|
|
}
|
|
|
|
$oFileList->setData($iLoop, $iLoop + 1, date("Y-m-d H:i", $aFile['ctime']), $aFile['filename'], human_readable_size($aFile['size']), $sFileStats, " ", $oDelete->render() . $oDownload->render());
|
|
$iLoop++;
|
|
}
|
|
}
|
|
|
|
$sFileList = $oFileList->render(true);
|
|
}
|
|
|
|
function readStatusLineFromFile($sFile) {
|
|
$FileName = basename($sFile);
|
|
if (strtolower(substr($FileName, -2)) == 'gz') {
|
|
$fp = gzopen($sFile, "r");
|
|
if ($fp === false)
|
|
die('Can\'t open file ' . $FileName);
|
|
$sline = gzgets($fp, 40960);
|
|
gzclose($fp);
|
|
} else {
|
|
$fp = fopen($sFile, "r");
|
|
if ($fp === false)
|
|
die('Can\'t open file ' . $FileName);
|
|
$sline = fgets($fp, 5000);
|
|
fclose($fp);
|
|
}
|
|
$aStatusLine = clStatusLine2Array($sline);
|
|
return $aStatusLine;
|
|
}
|
|
|
|
function clStatusLine2Array($sLine) {
|
|
|
|
if (substr($sLine, 0, 9) != "-- Status")
|
|
return false;
|
|
|
|
$aStatus = explode(":", $sLine);
|
|
|
|
$aRet = array();
|
|
$aRet['tables'] = $aStatus[1];
|
|
$aRet['records'] = $aStatus[2];
|
|
$aRet['dbname'] = $aStatus[4];
|
|
if ((isset($aStatus[12])) && trim($aStatus[12]) != 'EXTINFO') {
|
|
$aRet['charset'] = $aStatus[12];
|
|
} else {
|
|
$aRet['charset'] = '?';
|
|
}
|
|
return $aRet;
|
|
}
|
|
?>
|
|
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title><?php echo CL_BACKUP_VERSION; ?></title>
|
|
<style type="text/css">
|
|
body {position: relative; padding-bottom: 3em;}
|
|
h2, p {margin: 0;}
|
|
#wrapper {margin: 0 auto;}
|
|
#content {text-align: center;}
|
|
#dumpfile_table {margin: 30px 0;}
|
|
table#files_tab {margin: 0 auto; border-collapse: collapse;}
|
|
#footer {position: fixed; bottom: 0.6em; right: 0.6em; color: #666; font-weight: normal; font-size: 0.8em;}
|
|
.img_but {margin-right: 4px;}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<?php
|
|
echo '<form name="dump" action="' . $bk_filename . '" method="POST"></form>';
|
|
?>
|
|
<div id="wrapper">
|
|
<div id="header">
|
|
<?php
|
|
if (!empty($aMessage)) {
|
|
$oNoti = new Contenido_Notification();
|
|
$oNoti->displayNotification($aMessage['level'], $aMessage['text']);
|
|
}
|
|
?>
|
|
</div>
|
|
<div id="content">
|
|
<h1><?php echo $info_h1; ?></h1>
|
|
<h2><?php echo $info_h2; ?></h2>
|
|
<p><?php echo $info_p; ?></p>
|
|
<p><b><?php echo $table_ok; ?></b></p>
|
|
<p><?php echo $button_back; ?></p>
|
|
</div>
|
|
<div id="dumpfile_table">
|
|
<?php echo $sFileList ?>
|
|
</div>
|
|
<div id="footer">Database Backup for ConLite [<?php echo CL_BACKUP_VERSION; ?>]</div>
|
|
</div>
|
|
<!-- body_eof //-->
|
|
<?php
|
|
if ($selbstaufruf != '')
|
|
echo $selbstaufruf;
|
|
?>
|
|
</body>
|
|
</html>
|
|
<?php
|
|
//Pufferinhalte an den Client ausgeben
|
|
ob_end_flush();
|
|
?>
|