zentaopms/module/backup/control.php
2023-05-16 10:47:08 +08:00

417 lines
16 KiB
PHP

<?php
/**
* The control file of backup of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package backup
* @version $Id$
* @link http://www.zentao.net
*/
class backup extends control
{
/**
* __construct
*
* @access public
* @return void
*/
public function __construct($moduleName = '', $methodName = '')
{
parent::__construct($moduleName, $methodName);
$this->backupPath = $this->backup->getBackupPath();
if(!is_dir($this->backupPath))
{
if(!mkdir($this->backupPath, 0777, true)) $this->view->error = sprintf($this->lang->backup->error->noWritable, dirname($this->backupPath));
}
else
{
if(!is_writable($this->backupPath)) $this->view->error = sprintf($this->lang->backup->error->noWritable, $this->backupPath);
}
if(!is_writable($this->app->getTmpRoot())) $this->view->error = sprintf($this->lang->backup->error->noWritable, $this->app->getTmpRoot());
}
/**
* Index
*
* @access public
* @return void
*/
public function index()
{
$this->loadModel('action');
$backups = array();
if(empty($this->view->error))
{
$sqlFiles = glob("{$this->backupPath}*.sql*");
if(!empty($sqlFiles))
{
foreach($sqlFiles as $file)
{
$fileName = basename($file);
$backupFile = new stdclass();
$backupFile->time = filemtime($file);
$backupFile->name = substr($fileName, 0, strpos($fileName, '.'));
$backupFile->files[$file] = $this->backup->getBackupSummary($file);
$fileBackup = $this->backup->getBackupFile($backupFile->name, 'file');
if($fileBackup) $backupFile->files[$fileBackup] = $this->backup->getBackupSummary($fileBackup);
$codeBackup = $this->backup->getBackupFile($backupFile->name, 'code');
if($codeBackup) $backupFile->files[$codeBackup] = $this->backup->getBackupSummary($codeBackup);
$backups[$backupFile->name] = $backupFile;
}
}
}
krsort($backups);
$this->view->title = $this->lang->backup->common;
$this->view->position[] = $this->lang->backup->common;
$this->view->backups = $backups;
$this->display();
}
/**
* Backup.
*
* param string $reload yes|no
* @access public
* @return void
*/
public function backup($reload = 'no')
{
if($reload == 'yes') session_write_close();
set_time_limit(0);
$nofile = strpos($this->config->backup->setting, 'nofile') !== false;
$nosafe = strpos($this->config->backup->setting, 'nosafe') !== false;
$fileName = date('YmdHis') . mt_rand(0, 9);
$backFileName = "{$this->backupPath}{$fileName}.sql";
if(!$nosafe) $backFileName .= '.php';
$result = $this->backup->backSQL($backFileName);
if(!$result->result)
{
if($reload == 'yes')
{
return print(sprintf($this->lang->backup->error->noWritable, $this->backupPath));
}
else
{
printf($this->lang->backup->error->noWritable, $this->backupPath);
}
}
if(!$nosafe) $this->backup->addFileHeader($backFileName);
if(!$nofile)
{
$backFileName = "{$this->backupPath}{$fileName}.file";
$result = $this->backup->backFile($backFileName);
if(!$result->result)
{
if($reload == 'yes')
{
return print(sprintf($this->lang->backup->error->backupFile, $result->error));
}
else
{
printf($this->lang->backup->error->backupFile, $result->error);
}
}
$backFileName = "{$this->backupPath}{$fileName}.code";
$result = $this->backup->backCode($backFileName);
if(!$result->result)
{
if($reload == 'yes')
{
return print(sprintf($this->lang->backup->error->backupCode, $result->error));
}
else
{
printf($this->lang->backup->error->backupCode, $result->error);
}
}
}
/* Delete expired backup. */
$backupFiles = glob("{$this->backupPath}*.*");
if(!empty($backupFiles))
{
$time = time();
$zfile = $this->app->loadClass('zfile');
foreach($backupFiles as $file)
{
/* Only delete backup file. */
$fileName = basename($file);
if(!preg_match('/[0-9]+\.(sql|file|code)/', $fileName)) continue;
/* Remove before holdDays file. */
if($time - filemtime($file) > $this->config->backup->holdDays * 24 * 3600)
{
$rmFunc = is_file($file) ? 'removeFile' : 'removeDir';
$zfile->{$rmFunc}($file);
if($rmFunc == 'removeDir') $this->backup->processSummary($file, 0, 0, array(), 0, 'delete');
}
}
}
if($reload == 'yes') return print($this->lang->backup->success->backup);
echo $this->lang->backup->success->backup . "\n";
}
/**
* Restore.
*
* @param string $fileName
* @param string $confirm yes|no
* @access public
* @return void
*/
public function restore($fileName, $confirm = 'no')
{
if($confirm == 'no') return $this->send(array('result' => 'fail', 'message' => $this->lang->backup->confirmRestore));
set_time_limit(0);
/* Restore database. */
if(file_exists("{$this->backupPath}{$fileName}.sql.php"))
{
$sqlBackup = "{$this->backupPath}{$fileName}.sql.php";
$this->backup->removeFileHeader($sqlBackup);
$result = $this->backup->restoreSQL($sqlBackup);
$this->backup->addFileHeader($sqlBackup);
if(!$result->result) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->backup->error->restoreSQL, $result->error)));
}
elseif(file_exists("{$this->backupPath}{$fileName}.sql"))
{
$result = $this->backup->restoreSQL("{$this->backupPath}{$fileName}.sql");
if(!$result->result) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->backup->error->restoreSQL, $result->error)));
}
/* Restore attatchments. */
if(file_exists("{$this->backupPath}{$fileName}.file.zip.php"))
{
$fileBackup = "{$this->backupPath}{$fileName}.file.zip.php";
$this->backup->removeFileHeader($fileBackup);
$result = $this->backup->restoreFile($fileBackup);
$this->backup->addFileHeader($fileBackup);
if(!$result->result) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->backup->error->restoreFile, $result->error)));
}
elseif(file_exists("{$this->backupPath}{$fileName}.file.zip"))
{
$result = $this->backup->restoreFile("{$this->backupPath}{$fileName}.file.zip");
if(!$result->result) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->backup->error->restoreFile, $result->error)));
}
elseif(file_exists("{$this->backupPath}{$fileName}.file"))
{
$result = $this->backup->restoreFile("{$this->backupPath}{$fileName}.file");
if(!$result->result) return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->backup->error->restoreFile, $result->error)));
}
return $this->send(array('result' => 'success', 'message' => $this->lang->backup->success->restore));
}
/**
* remove PHP header.
*
* @param string $fileName
* @access public
* @return void
*/
public function rmPHPHeader($fileName)
{
if(file_exists($this->backupPath . $fileName . '.sql.php'))
{
$this->backup->removeFileHeader($this->backupPath . $fileName . '.sql.php');
rename($this->backupPath . $fileName . '.sql.php', $this->backupPath . $fileName . '.sql');
}
if(file_exists($this->backupPath . $fileName . '.file.zip.php'))
{
$this->backup->removeFileHeader($this->backupPath . $fileName . '.file.zip.php');
rename($this->backupPath . $fileName . '.file.zip.php', $this->backupPath . $fileName . '.file.zip');
}
if(file_exists($this->backupPath . $fileName . '.code.zip.php'))
{
$this->backup->removeFileHeader($this->backupPath . $fileName . '.code.zip.php');
rename($this->backupPath . $fileName . '.code.zip.php', $this->backupPath . $fileName . '.code.zip');
}
return print(js::reload('parent'));
}
/**
* Delete.
*
* @param string $fileName
* @param string $confirm yes|no
* @access public
* @return void
*/
public function delete($fileName, $confirm = 'no')
{
if($confirm == 'no') return print(js::confirm($this->lang->backup->confirmDelete, inlink('delete', "fileName=$fileName&confirm=yes")));
/* Delete database file. */
if(file_exists($this->backupPath . $fileName . '.sql.php') and !unlink($this->backupPath . $fileName . '.sql.php'))
{
return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.sql.php')));
}
if(file_exists($this->backupPath . $fileName . '.sql') and !unlink($this->backupPath . $fileName . '.sql'))
{
return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.sql')));
}
/* Delete attatchments file. */
if(file_exists($this->backupPath . $fileName . '.file.zip.php') and !unlink($this->backupPath . $fileName . '.file.zip.php'))
{
return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.file.zip.php')));
}
if(file_exists($this->backupPath . $fileName . '.file.zip') and !unlink($this->backupPath . $fileName . '.file.zip'))
{
return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.file.zip')));
}
if(file_exists($this->backupPath . $fileName . '.file'))
{
$zfile = $this->app->loadClass('zfile');
$zfile->removeDir($this->backupPath . $fileName . '.file');
$this->backup->processSummary($this->backupPath . $fileName . '.file', 0, 0, array(), 0, 'delete');
}
/* Delete code file. */
if(file_exists($this->backupPath . $fileName . '.code.zip.php') and !unlink($this->backupPath . $fileName . '.code.zip.php'))
{
return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.code.zip.php')));
}
if(file_exists($this->backupPath . $fileName . '.code.zip') and !unlink($this->backupPath . $fileName . '.code.zip'))
{
return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.code.zip')));
}
if(file_exists($this->backupPath . $fileName . '.code'))
{
$zfile = $this->app->loadClass('zfile');
$zfile->removeDir($this->backupPath . $fileName . '.code');
$this->backup->processSummary($this->backupPath . $fileName . '.code', 0, 0, array(), 0, 'delete');
}
return print(js::reload('parent'));
}
/**
* Change hold days.
*
* @access public
* @return void
*/
public function change()
{
if($_POST)
{
$data = fixer::input('post')->get();
$this->loadModel('setting')->setItem('system.backup.holdDays', $data->holdDays);
return print(js::reload('parent.parent'));
}
$this->display();
}
/**
* Setting backup
*
* @access public
* @return void
*/
public function setting()
{
/* Check safe file. */
$statusFile = $this->loadModel('common')->checkSafeFile();
if($statusFile)
{
$this->app->loadLang('extension');
$search = $this->app->getBasePath();
$pos = strpos($statusFile, $search);
$okFile = $statusFile;
if($pos !== false) $okFile = substr_replace($statusFile, '', $pos, strlen($search));
$this->view->error = sprintf($this->lang->extension->noticeOkFile, $okFile, $statusFile);
return print($this->display());
}
if(strtolower($this->server->request_method) == "post")
{
$data = fixer::input('post')->join('setting', ',')->get();
/*save change*/
if(isset($data->holdDays)) $this->loadModel('setting')->setItem('system.backup.holdDays', $data->holdDays);
$setting = '';
if(isset($data->setting)) $setting = $data->setting;
$this->loadModel('setting')->setItem('system.backup.setting', $setting);
$settingDir = $data->settingDir;
if($settingDir)
{
$settingDir = rtrim($settingDir, DS) . DS;
if(!is_dir($settingDir) and mkdir($settingDir, 0777, true)) return print(js::alert($this->lang->backup->error->noCreateDir));
if(!is_writable($settingDir)) return print(js::alert(strip_tags(sprintf($this->lang->backup->error->noWritable, $settingDir))));
if($data->settingDir == $this->app->getTmpRoot() . 'backup' . DS) $settingDir = '';
}
$this->setting->setItem('system.backup.settingDir', $settingDir);
return print(js::reload('parent.parent'));
}
$this->display();
}
/**
* Ajax get progress.
*
* @access public
* @return void
*/
public function ajaxGetProgress()
{
session_write_close();
$files = glob($this->backupPath . '/*.*');
rsort($files);
$fileName = basename($files[0]);
$fileName = substr($fileName, 0, strpos($fileName, '.'));
$sqlFileName = $this->backupPath . $fileName . '.sql';
if(!file_exists($sqlFileName)) $sqlFileName .= '.php';
$sqlFileName = $this->backup->getBackupFile($fileName, 'sql');
if($sqlFileName)
{
$summary = $this->backup->getBackupSummary($sqlFileName);
$message = sprintf($this->lang->backup->progressSQL, $this->backup->processFileSize($summary['size']));
}
$attachFileName = $this->backup->getBackupFile($fileName, 'file');
if($attachFileName)
{
$log = $this->backup->getBackupDirProgress($attachFileName);
$message = sprintf($this->lang->backup->progressAttach, zget($log, 'allCount', 0), zget($log, 'count', 0));
}
$codeFileName = $this->backup->getBackupFile($fileName, 'code');
if($codeFileName)
{
$log = $this->backup->getBackupDirProgress($codeFileName);
$message = sprintf($this->lang->backup->progressCode, zget($log, 'allCount', 0), zget($log, 'count', 0));
}
return print($message);
}
}