Struggeling with relocating
Dieser Commit ist enthalten in:
Commit
89ea01c429
301 geänderte Dateien mit 59926 neuen und 0 gelöschten Zeilen
715
inc/functions/functions.php
Normale Datei
715
inc/functions/functions.php
Normale Datei
|
|
@ -0,0 +1,715 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of MySQLDumper released under the GNU/GPL 2 license
|
||||
* http://www.mysqldumper.net
|
||||
*
|
||||
* @package MySQLDumper
|
||||
* @version SVN: $rev: 1207 $
|
||||
* @author $Author$
|
||||
* @lastmodified $Date$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Output human readable Byte-Values
|
||||
*
|
||||
* @param integer $bytes Bytes to convert to human readable format
|
||||
* @param boolean $useHTML Decides whether explaining span-tags should surround
|
||||
* the returned string
|
||||
*
|
||||
* @return string human readable output
|
||||
*/
|
||||
function byteOutput($bytes, $useHTML = true)
|
||||
{
|
||||
$precision = 2;
|
||||
if (!is_numeric($bytes) || $bytes < 0) {
|
||||
return false;
|
||||
}
|
||||
for ($level = 0; $bytes >= 1024; $level++) {
|
||||
$bytes /= 1024;
|
||||
}
|
||||
switch ($level)
|
||||
{
|
||||
case 0:
|
||||
$suffix = '<span class="explain" title="Bytes">B</span>';
|
||||
break;
|
||||
case 1:
|
||||
$suffix = '<span class="explain" title="KiloBytes">KB</span>';
|
||||
break;
|
||||
case 2:
|
||||
$suffix = '<span class="explain" title="MegaBytes">MB</span>';
|
||||
break;
|
||||
case 3:
|
||||
$suffix = '<span class="explain" title="GigaBytes">GB</span>';
|
||||
break;
|
||||
case 4:
|
||||
$suffix = '<span class="explain" title="TeraBytes">TB</span>';
|
||||
break;
|
||||
case 5:
|
||||
$suffix = '<span class="explain" title="PetaBytes">PB</span>';
|
||||
break;
|
||||
case 6:
|
||||
$suffix = '<span class="explain" title="ExaBytes">EB</span>';
|
||||
break;
|
||||
case 7:
|
||||
$suffix = '<span class="explain" title="YottaBytes">ZB</span>';
|
||||
break;
|
||||
|
||||
default:
|
||||
$suffix = '';
|
||||
break;
|
||||
}
|
||||
if (!$useHTML) {
|
||||
$suffix = strip_tags($suffix);
|
||||
}
|
||||
$ret = sprintf("%01." . $precision . "f", round($bytes, $precision));
|
||||
return $ret . ' ' . $suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Multipart files
|
||||
*
|
||||
* @param string $dir Directory to check
|
||||
* @param string $prefix Only check files with this prefix
|
||||
* @param string $suffix Only check files with this suffix
|
||||
*
|
||||
* @return array Array $file['filename']=true | false
|
||||
*/
|
||||
function deleteMultipartFiles($dir, $prefix = '', $suffix = '')
|
||||
{
|
||||
$deleted = array();
|
||||
if (substr($dir, -1) != '/') {
|
||||
$dir .= '/';
|
||||
}
|
||||
if (is_dir($dir)) {
|
||||
$d = opendir($dir);
|
||||
while ($file = readdir($d)) {
|
||||
if (is_file($dir . $file)) {
|
||||
$del = false;
|
||||
if ($prefix > '' && substr($file, 0, strlen($prefix)) == $prefix) $del = true;
|
||||
if ($suffix > '' && substr($file, strlen($file) - strlen($suffix), strlen($suffix)) == $suffix) $del = true;
|
||||
if ($del)
|
||||
{
|
||||
if (unlink($dir . $file)) $deleted[$file] = true;
|
||||
else $deleted[$file] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($d);
|
||||
return $deleted;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a database to the global $databases-Array and set necessary indexes
|
||||
*
|
||||
* @param string $db_name Databaase-Name
|
||||
* @param string $praefix Table-Prefix
|
||||
* @param string $cbd Command before Dump
|
||||
* @param string $cad Command after Dump
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function addDatabaseToConfig($db_name)
|
||||
{
|
||||
global $databases;
|
||||
if (!isset($databases)) $databases = array();
|
||||
if (!isset($databases[$db_name])) $databases[$db_name] = array();
|
||||
if (!isset($databases[$db_name]['dump'])) $databases[$db_name]['dump'] = 0;
|
||||
if (!isset($databases[$db_name]['prefix'])) $databases[$db_name]['prefix'] = '';
|
||||
if (!isset($databases[$db_name]['command_before_dump'])) $databases[$db_name]['command_before_dump'] = '';
|
||||
if (!isset($databases[$db_name]['command_after_dump'])) $databases[$db_name]['command_after_dump'] = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check settings of language, config file, reloads list of databases and save result to configuration
|
||||
*
|
||||
* @return string String with checked and added databases
|
||||
*/
|
||||
function setDefaultConfig()
|
||||
{
|
||||
global $config, $databases, $out, $lang, $dbo;
|
||||
|
||||
// check language and fallback to englisch if language file is not readable
|
||||
$lang_file = './language/' . $config['language'] . '/lang.php';
|
||||
if (!file_exists($lang_file) || !is_readable($lang_file))
|
||||
{
|
||||
$config['language'] = 'en';
|
||||
}
|
||||
include ('./language/' . $config['language'] . '/lang.php');
|
||||
|
||||
getConfig($config['config_file']); // falls back to config mysqldumper if something is wrong
|
||||
// get list of databases for this user
|
||||
$dbUser = $dbo->getDatabases();
|
||||
foreach ($dbUser as $db)
|
||||
{
|
||||
// new found db? -> add it
|
||||
if (!isset($databases[$db])) $databases[$db] = array();
|
||||
}
|
||||
ksort($databases);
|
||||
foreach ($databases as $db_name => $val)
|
||||
{
|
||||
if ($dbo->selectDb($db_name, true))
|
||||
{
|
||||
addDatabaseToConfig($db_name);
|
||||
$out .= $lang['L_SAVING_DB_FORM'] . " " . $db_name . " " . $lang['L_ADDED'] . "\n";
|
||||
}
|
||||
else
|
||||
unset($databases[$db_name]);
|
||||
}
|
||||
saveConfig();
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save actual configuration to file
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function saveConfig()
|
||||
{
|
||||
global $config, $databases, $configDontsave;
|
||||
|
||||
$config['multipart_groesse'] = $config['multipartgroesse1'] * (($config['multipartgroesse2'] == 1) ? 1024 : 1024 * 1024);
|
||||
if (!isset($config['email_maxsize'])) $config['email_maxsize'] = $config['email_maxsize1'] * (($config['email_maxsize2'] == 1) ? 1024 : 1024 * 1024);
|
||||
if (!isset($config['cron_execution_path'])) $config['cron_execution_path'] = "msd_cron/";
|
||||
|
||||
$config2 = $config;
|
||||
foreach ($config2 as $var => $val)
|
||||
{
|
||||
if (in_array($var, $configDontsave)) unset($config2[$var]);
|
||||
}
|
||||
|
||||
$t = '$config=array_merge($config,unserialize(base64_decode(\'' . base64_encode(serialize($config2)) . "')));\r\n";
|
||||
if (isset($databases)) $t .= '$databases=array_merge($databases,unserialize(base64_decode(\'' . base64_encode(serialize($databases)) . "')));\r\n";
|
||||
|
||||
$pars_all = '<?php' . "\n" . $t . "\n?>";
|
||||
|
||||
$ret = true;
|
||||
$file = './' . $config['paths']['config'] . $config['config_file'] . '.php';
|
||||
if ($fp = @fopen($file, "wb"))
|
||||
{
|
||||
if (!fwrite($fp, $pars_all)) $ret = false;
|
||||
if (!fclose($fp)) $ret = false;
|
||||
@chmod($file, 0777);
|
||||
}
|
||||
else
|
||||
$ret = false;
|
||||
if ($ret)
|
||||
{
|
||||
$_SESSION['config'] = $config;
|
||||
$ret = writeCronScript();
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build string of array according to Perl syntax (needed to save Perl configuration file)
|
||||
*
|
||||
* @param array $arr Array to build the string from
|
||||
* @param string $mode 0 for strings, 1 for int values
|
||||
*
|
||||
* @return string The converted Perl string
|
||||
*/
|
||||
function myImplode($arr, $mode = 0) // 0=String, 1=intval
|
||||
{
|
||||
if (!is_array($arr)) return false;
|
||||
foreach ($arr as $key => $val)
|
||||
{
|
||||
if ($mode == 0) $arr[$key] = Html::escapeSpecialchars($val);
|
||||
else $arr[$key] = intval($val);
|
||||
}
|
||||
if ($mode == 0) $ret = '("' . implode('","', $arr) . '")';
|
||||
else $ret = '(' . implode(',', $arr) . ')';
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and save the actual configuration file for Perl (used by crondump.pl)
|
||||
*
|
||||
* @return boolean true on success or false on failure
|
||||
*/
|
||||
function writeCronScript()
|
||||
{
|
||||
global $config, $databases, $cron_db_array, $cron_dbpraefix_array, $cron_db_cbd_array, $cron_db_cad_array;
|
||||
if (!isset($config['email_maxsize'])) $config['email_maxsize'] = $config['email_maxsize1'] * (($config['email_maxsize2'] == 1) ? 1024 : 1024 * 1024);
|
||||
if (isset($config['db_actual'])) $cron_dbname = $config['db_actual'];
|
||||
else
|
||||
{
|
||||
//get first database name from database-array (this is the case at fresh installing)
|
||||
$dbs = array_keys($databases);
|
||||
$cron_dbname = $dbs[0];
|
||||
}
|
||||
// -2 = Multidump configuration
|
||||
// -3 = all databases - nothing to do
|
||||
// get standard values for all databases
|
||||
$cron_db_array = ''; //$databases['Name'];
|
||||
$cron_dbpraefix_array = ''; //$databases['praefix'];
|
||||
$cron_command_before_dump = ''; //$databases['command_before_dump'];
|
||||
$cron_command_after_dump = ''; //$databases['command_after_dump'];
|
||||
|
||||
|
||||
$cron_ftp_server = '';
|
||||
$cron_ftp_port = '';
|
||||
$cron_ftp_mode = '';
|
||||
$cron_ftp_user = '';
|
||||
$cron_ftp_pass = '';
|
||||
$cron_ftp_dir = '';
|
||||
$cron_ftp_timeout = '';
|
||||
$cron_ftp_ssl = '';
|
||||
$cron_ftp_transfer = '';
|
||||
|
||||
//build db-arrays
|
||||
foreach ($databases as $k => $v)
|
||||
{
|
||||
//should we dump this database
|
||||
if (isset($databases[$k]['dump']) && $databases[$k]['dump'] === 1)
|
||||
{
|
||||
$cron_db_array[] .= $k;
|
||||
$cron_dbpraefix_array[] .= $databases[$k]['prefix'];
|
||||
$cron_command_before_dump[] .= $databases[$k]['command_before_dump'];
|
||||
$cron_command_after_dump[] .= $databases[$k]['command_after_dump'];
|
||||
}
|
||||
}
|
||||
|
||||
//build ftp-arrays
|
||||
foreach ($config['ftp'] as $k => $v)
|
||||
{
|
||||
$cron_ftp_server[] .= $config['ftp'][$k]['server'];
|
||||
$cron_ftp_port[] .= $config['ftp'][$k]['port'];
|
||||
$cron_ftp_mode[] .= $config['ftp'][$k]['mode'];
|
||||
$cron_ftp_user[] .= $config['ftp'][$k]['user'];
|
||||
$cron_ftp_pass[] .= $config['ftp'][$k]['pass'];
|
||||
$cron_ftp_dir[] .= $config['ftp'][$k]['dir'];
|
||||
$cron_ftp_timeout[] .= $config['ftp'][$k]['timeout'];
|
||||
$cron_ftp_ssl[] .= $config['ftp'][$k]['ssl'];
|
||||
$cron_ftp_transfer[] .= $config['ftp'][$k]['transfer'];
|
||||
}
|
||||
|
||||
$r = str_replace("\\\\", "/", $config['paths']['root']);
|
||||
$r = str_replace("@", "\@", $r);
|
||||
|
||||
//built recipient_cc-arrays
|
||||
$recipients_cc = '';
|
||||
foreach ($config['email']['recipient_cc'] as $k => $v)
|
||||
{
|
||||
$recipients_cc .= '"' . $config['email']['recipient_cc'][$k]['name'] . '" <' . $config['email']['recipient_cc'][$k]['address'] . '>, ';
|
||||
}
|
||||
$recipients_cc = substr($recipients_cc, 0, -2);
|
||||
|
||||
// auf manchen Server wird statt 0 ein leerer String gespeichert -> fuehrt zu einem Syntax-Fehler
|
||||
// hier die entsprechenden Ja/Nein-Variablen sicherheitshalber in intvalues aendern
|
||||
$int_array = array(
|
||||
'dbport',
|
||||
'cron_compression',
|
||||
'cron_printout',
|
||||
'multi_part',
|
||||
'multipart_groesse',
|
||||
'email_maxsize',
|
||||
//'auto_delete][activated',
|
||||
//'auto_delete][max_backup_files',
|
||||
'perlspeed',
|
||||
'optimize_tables_beforedump',
|
||||
'logcompression',
|
||||
'log_maxsize',
|
||||
'cron_completelog',
|
||||
'use_sendmail',
|
||||
'smtp_port',
|
||||
'smtp_useauth',
|
||||
'smtp_usessl');
|
||||
|
||||
foreach ($int_array as $i)
|
||||
{
|
||||
if (is_array($i))
|
||||
{
|
||||
foreach ($i as $key => $val)
|
||||
{
|
||||
$int_array[$key] = intval($val);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isset($config[$i])) $config[$i] = 0;
|
||||
$config[$i] = intval($config[$i]);
|
||||
}
|
||||
}
|
||||
if ($config['dbport'] == 0) $config['dbport'] = 3306;
|
||||
|
||||
$cronscript = "<?php\n#Vars - written at " . date("Y-m-d H:i") . "\n";
|
||||
$cronscript .= '$dbhost="' . $config['dbhost'] . '";' . "\n";
|
||||
$cronscript .= '$dbname="' . $cron_dbname . '";' . "\n";
|
||||
$cronscript .= '$dbuser="' . Html::escapeSpecialchars($config['dbuser']) . '";' . "\n";
|
||||
$cronscript .= '$dbpass="' . Html::escapeSpecialchars($config['dbpass']) . '";' . "\n";
|
||||
$cronscript .= '$dbport=' . $config['dbport'] . ';' . "\n";
|
||||
$cronscript .= '$dbsocket="' . Html::escapeSpecialchars($config['dbsocket']) . '";' . "\n";
|
||||
$cronscript .= '$compression=' . $config['cron_compression'] . ';' . "\n";
|
||||
$cronscript .= '$sendmail_call="' . Html::escapeSpecialchars($config['sendmail_call']) . '";' . "\n";
|
||||
$cronscript .= '$backup_path="' . $config['paths']['root'] . $config['paths']['backup'] . '";' . "\n";
|
||||
$cronscript .= '$cron_printout=' . $config['cron_printout'] . ';' . "\n";
|
||||
$cronscript .= '$cronmail=' . $config['send_mail'] . ';' . "\n";
|
||||
$cronscript .= '$cronmail_dump=' . $config['email']['attach_backup'] . ';' . "\n";
|
||||
$cronscript .= '$cronmailto="' . Html::escapeSpecialchars('"' . $config['email']['recipient_name'] . '" <' . $config['email']['recipient_address'] . '>') . '";' . "\n";
|
||||
$cronscript .= '$cronmailto_cc="' . Html::escapeSpecialchars($recipients_cc) . '";' . "\n";
|
||||
$cronscript .= '$cronmailfrom="' . Html::escapeSpecialchars('"' . $config['email']['sender_name'] . '" <' . $config['email']['sender_address'] . '>') . '";' . "\n";
|
||||
$cronscript .= '$cron_use_sendmail=' . $config['use_sendmail'] . ';' . "\n";
|
||||
$cronscript .= '$cron_smtp="' . Html::escapeSpecialchars($config['smtp_server']) . '";' . "\n";
|
||||
$cronscript .= '$smtp_port=' . $config['smtp_port'] . ';' . "\n";
|
||||
$cronscript .= '$smtp_useauth=' . $config['smtp_useauth'] . ';' . "\n";
|
||||
$cronscript .= '$smtp_usessl=' . $config['smtp_usessl'] . ';' . "\n";
|
||||
$cronscript .= '$smtp_user="' . $config['smtp_user'] . '";' . "\n";
|
||||
$cronscript .= '$smtp_pass="' . $config['smtp_pass'] . '";' . "\n";
|
||||
$cronscript .= '@cron_db_array=' . myImplode($cron_db_array) . ';' . "\n";
|
||||
$cronscript .= '@cron_dbpraefix_array=' . myImplode($cron_dbpraefix_array) . ';' . "\n";
|
||||
$cronscript .= '@cron_command_before_dump=' . myImplode($cron_command_before_dump) . ';' . "\n";
|
||||
$cronscript .= '@cron_command_after_dump=' . myImplode($cron_command_after_dump) . ';' . "\n";
|
||||
|
||||
$cronscript .= '@ftp_server=' . myImplode($cron_ftp_server) . ';' . "\n";
|
||||
$cronscript .= '@ftp_port=' . myImplode($cron_ftp_port, 1) . ';' . "\n";
|
||||
$cronscript .= '@ftp_mode=' . myImplode($cron_ftp_mode, 1) . ';' . "\n";
|
||||
$cronscript .= '@ftp_user=' . myImplode($cron_ftp_user) . ';' . "\n";
|
||||
$cronscript .= '@ftp_pass=' . myImplode($cron_ftp_pass) . ';' . "\n";
|
||||
$cronscript .= '@ftp_dir=' . myImplode($cron_ftp_dir) . ';' . "\n";
|
||||
$cronscript .= '@ftp_timeout=' . myImplode($cron_ftp_timeout, 1) . ';' . "\n";
|
||||
$cronscript .= '@ftp_useSSL=' . myImplode($cron_ftp_ssl, 1) . ';' . "\n";
|
||||
$cronscript .= '@ftp_transfer=' . myImplode($cron_ftp_transfer, 1) . ';' . "\n";
|
||||
|
||||
$cronscript .= '$mp=' . $config['multi_part'] . ';' . "\n";
|
||||
$cronscript .= '$multipart_groesse=' . $config['multipart_groesse'] . ';' . "\n";
|
||||
$cronscript .= '$email_maxsize=' . $config['email_maxsize'] . ';' . "\n";
|
||||
$cronscript .= '$auto_delete=' . $config['auto_delete']['activated'] . ';' . "\n";
|
||||
$cronscript .= '$max_backup_files=' . $config['auto_delete']['max_backup_files'] . ';' . "\n";
|
||||
$cronscript .= '$perlspeed=' . $config['perlspeed'] . ';' . "\n";
|
||||
$cronscript .= '$optimize_tables_beforedump=' . $config['optimize_tables_beforedump'] . ';' . "\n";
|
||||
$cronscript .= '$logcompression=' . $config['logcompression'] . ';' . "\n";
|
||||
|
||||
//add .gz to logfiles?
|
||||
if ($config['logcompression'] === 1)
|
||||
{
|
||||
$cronscript .= '$logdatei="' . $config['paths']['root'] . $config['files']['perllog'] . '.gz";' . "\n";
|
||||
$cronscript .= '$completelogdatei="' . $config['paths']['root'] . $config['files']['perllogcomplete'] . '.gz";' . "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$cronscript .= '$logdatei="' . $config['paths']['root'] . $config['files']['perllog'] . '";' . "\n";
|
||||
$cronscript .= '$completelogdatei="' . $config['paths']['root'] . $config['files']['perllogcomplete'] . '";' . "\n";
|
||||
}
|
||||
$cronscript .= '$log_maxsize=' . $config['log_maxsize'] . ';' . "\n";
|
||||
$cronscript .= '$complete_log=' . $config['cron_completelog'] . ';' . "\n";
|
||||
$cronscript .= '$cron_comment="' . Html::escapeSpecialchars(stripslashes($config['cron_comment'])) . '";' . "\n";
|
||||
$cronscript .= "?>";
|
||||
|
||||
// Save config
|
||||
$ret = true;
|
||||
$sfile = './' . $config['paths']['config'] . $config['config_file'] . '.conf.php';
|
||||
if (file_exists($sfile)) @unlink($sfile);
|
||||
|
||||
if ($fp = @fopen($sfile, "wb"))
|
||||
{
|
||||
if (!fwrite($fp, $cronscript)) $ret = false;
|
||||
if (!fclose($fp)) $ret = false;
|
||||
@chmod("$sfile", 0777);
|
||||
}
|
||||
else
|
||||
$ret = false;
|
||||
|
||||
// if standard config was deleted -> restore it with the actual values
|
||||
if (!file_exists('./' . $config['paths']['config'] . "mysqldumper.conf.php"))
|
||||
{
|
||||
$sfile = './' . $config['paths']['config'] . 'mysqldumper.conf.php';
|
||||
if ($fp = fopen($sfile, "wb"))
|
||||
{
|
||||
if (!fwrite($fp, $cronscript)) $ret = false;
|
||||
if (!fclose($fp)) $ret = false;
|
||||
@chmod("$sfile", 0777);
|
||||
}
|
||||
else
|
||||
$ret = false;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect log file information and return it as assoziative array
|
||||
*
|
||||
* @param boolean $logcompression Watch for compressed (true) or uncompressed files
|
||||
*
|
||||
* @return array Associative array with information
|
||||
*/
|
||||
function getLogFileInfo($logcompression)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$l = Array();
|
||||
$sum = $s = $l['log_size'] = $l['perllog_size'] = $l['perllogcomplete_size'] = $l['errorlog_size'] = $l['log_totalsize'] = 0;
|
||||
if ($logcompression == 1)
|
||||
{
|
||||
$l['log'] = $config['files']['log'] . ".gz";
|
||||
$l['perllog'] = $config['files']['perllog'] . ".gz";
|
||||
$l['perllogcomplete'] = $config['files']['perllogcomplete'] . ".gz";
|
||||
$l['errorlog'] = $config['paths']['log'] . "error.log.gz";
|
||||
}
|
||||
else
|
||||
{
|
||||
$l['log'] = $config['files']['log'];
|
||||
$l['perllog'] = $config['files']['perllog'];
|
||||
$l['perllogcomplete'] = $config['files']['perllogcomplete'];
|
||||
$l['errorlog'] = $config['paths']['log'] . "error.log";
|
||||
}
|
||||
$l['log_size'] += @filesize($l['log']);
|
||||
$sum += $l['log_size'];
|
||||
$l['perllog_size'] += @filesize($l['perllog']);
|
||||
$sum += $l['perllog_size'];
|
||||
$l['perllogcomplete_size'] += @filesize($l['perllogcomplete']);
|
||||
$sum += $l['perllogcomplete_size'];
|
||||
$l['errorlog_size'] += @filesize($l['errorlog']);
|
||||
$sum += $l['errorlog_size'];
|
||||
$l['log_totalsize'] += $sum;
|
||||
|
||||
return $l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete log file and recreates it.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function deleteLog()
|
||||
{
|
||||
global $config;
|
||||
$log = date('d.m.Y H:i:s') . " Log created.\n";
|
||||
if (file_exists($config['files']['log'] . '.gz')) @unlink($config['files']['log'] . '.gz');
|
||||
if (file_exists($config['files']['log'] . '.gz')) @unlink($config['files']['log']);
|
||||
if ($config['logcompression'] == 1)
|
||||
{
|
||||
$fp = @gzopen($config['files']['log'] . '.gz', "wb");
|
||||
@gzwrite($fp, $log);
|
||||
@gzclose($fp);
|
||||
@chmod($config['files']['log'] . '.gz', 0777);
|
||||
}
|
||||
else
|
||||
{
|
||||
$fp = @fopen($config['files']['log'], "wb");
|
||||
@fwrite($fp, $log);
|
||||
@fclose($fp);
|
||||
@chmod($config['files']['log'], 0777);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect accessable databases for the current SQL-User in $config-array and returns output-string with all dbs
|
||||
* Additionally it adds all found databases in the global var $databases
|
||||
*
|
||||
* @param boolean $printout Wether to return the output string or not
|
||||
* @param string $db Optional name of a database to add manually
|
||||
*
|
||||
* @return string Output string containing all found dbs
|
||||
*/
|
||||
function searchDatabases($printout = 0, $db = '')
|
||||
{
|
||||
global $config, $lang, $dbo, $databases;
|
||||
$databases = array();
|
||||
$ret = '';
|
||||
$db_list = $dbo->getDatabases();
|
||||
// add manual added db to array, but only if it was not detected before
|
||||
if ($db > '' && !in_array($db, $db_list)) $db_list[] = $db;
|
||||
// now check if we can select the db - if not, we can't access the database
|
||||
if (sizeof($db_list) > 0)
|
||||
{
|
||||
foreach ($db_list as $db)
|
||||
{
|
||||
$res = $dbo->selectDb($db, true);
|
||||
|
||||
if ($res === true)
|
||||
{
|
||||
addDatabaseToConfig($db);
|
||||
if ($printout == 1) $ret .= Html::getOkMsg($lang['L_FOUND_DB'] . ' `' . $db);
|
||||
} elseif ($printout == 1) {
|
||||
$ret .= Html::getErrorMsg($lang['L_ERROR'].' : '.$res);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* realpath implementation working on any server
|
||||
*
|
||||
* @return $dir string The application path
|
||||
*/
|
||||
function myRealpath()
|
||||
{
|
||||
$dir = dirname(__FILE__);
|
||||
$dir = str_replace('\\', '/', $dir);
|
||||
$dir = str_replace('//', '/', $dir);
|
||||
if (substr($dir, -14) == '/inc/functions') $dir = substr($dir, 0, -13);
|
||||
if (substr($dir, -1) != '/') $dir .= '/';
|
||||
return $dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove tags recursivly from array or from string
|
||||
*
|
||||
* @param $value string | array Value/s to strip
|
||||
*
|
||||
* @return string|array Cleaned values
|
||||
*/
|
||||
function myStripTags($value)
|
||||
{
|
||||
global $dont_strip;
|
||||
if (is_array($value))
|
||||
{
|
||||
foreach ($value as $key => $val)
|
||||
{
|
||||
if (!in_array($key, $dont_strip)) $ret[$key] = myStripTags($val);
|
||||
else $ret[$key] = $val;
|
||||
}
|
||||
}
|
||||
else
|
||||
$ret = trim(strip_tags($value));
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* First start output buffering then start SESSION
|
||||
* Reads configuration and main-language file lang.php and creates
|
||||
* Database-Object $dbo
|
||||
*
|
||||
* @param string $json Return JSON-Encoded answer
|
||||
* @param string $send_header If set to false headers are completely skipped
|
||||
* @return void
|
||||
*/
|
||||
function obstart($json = false, $send_header = true)
|
||||
{
|
||||
global $dbo, $config, $databases, $dump, $lang;
|
||||
if ($config['ob_gzhandler'])
|
||||
{
|
||||
if (!@ob_start("ob_gzhandler")) @ob_start();
|
||||
}
|
||||
|
||||
// if default config file doesn't exists, it is a new installation -> redirect to installation
|
||||
if (!$json && !file_exists('./work/config/mysqldumper.php'))
|
||||
{
|
||||
header("location: install.php");
|
||||
die();
|
||||
exit();
|
||||
}
|
||||
|
||||
session_name('MySQLDumper');
|
||||
$res = session_start();
|
||||
if (false === $res) die("Error starting session! Check server.");
|
||||
if (isset($_SESSION['config_file'])) $config['config_file'] = $_SESSION['config_file'];
|
||||
else $config['config_file'] = 'mysqldumper';
|
||||
if ($send_header)
|
||||
{
|
||||
header('Pragma: no-cache');
|
||||
header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1
|
||||
header('Expires: -1'); // Datum in der Vergangenheit
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Last-Modified: ' . gmdate("D, d M Y H:i:s") . ' GMT');
|
||||
if (!$json) header('Content-Type: text/html; charset=UTF-8');
|
||||
else header('Content-type: application/x-json');
|
||||
}
|
||||
// get config from configuration file if not set
|
||||
if (!isset($_SESSION['config'])) getConfig($config['config_file']);
|
||||
else
|
||||
{
|
||||
// otherwise get parameters from session
|
||||
$config = array_merge($config, $_SESSION['config']);
|
||||
if (isset($_SESSION['databases'])) $databases = $_SESSION['databases'];
|
||||
if (isset($_SESSION['dump'])) $dump = $_SESSION['dump'];
|
||||
}
|
||||
// special case -> configuration is set to a language that was deleted meanwhile
|
||||
if (!is_readable('./language/' . $config['language'] . '/lang.php')) $config['language'] = 'en';
|
||||
|
||||
include ('./language/' . $config['language'] . '/lang.php');
|
||||
// create database object
|
||||
$dbo = MsdDbFactory::getAdapter($config['dbhost'], $config['dbuser'], $config['dbpass'], $config['dbport'], $config['dbsocket']);
|
||||
if (!isset($_SESSION['databases'])) setDefaultConfig();
|
||||
//echo $config['db_actual'];
|
||||
// die();
|
||||
if (isset($config['db_actual']) && $config['db_actual'] > '') $dbo->selectDb($config['db_actual']);
|
||||
else
|
||||
{
|
||||
if (!isset($databases)) {
|
||||
// no config loaded -> SetDefault-Values
|
||||
setDefaultConfig();
|
||||
}
|
||||
// get first DB-Name and set as actual db
|
||||
$dbNames = array_keys($databases);
|
||||
$config['db_actual'] = $dbNames[0];
|
||||
$dbo->selectDb($config['db_actual']);
|
||||
}
|
||||
//$_SESSION['config'] = $config;
|
||||
//$_SESSION['databases'] = $databases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add end of body/html, end output buffering and output the buffer
|
||||
*
|
||||
* @param boolean $ajax
|
||||
* @return void
|
||||
*/
|
||||
function obend($ajax = false)
|
||||
{
|
||||
global $config, $databases;
|
||||
$_SESSION['databases'] = $databases;
|
||||
$_SESSION['config'] = $config;
|
||||
if (!$ajax) {
|
||||
echo '</div>' . "\n\n" . '</body>' . "\n\n" . '</html>';
|
||||
// close HTML-page
|
||||
}
|
||||
@ob_end_flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unique prefixes from an array
|
||||
*
|
||||
* and return new array containing the different prefixes
|
||||
*
|
||||
* @param array $array Array to scan for prefixes
|
||||
* @param boolean $addNoneOption Wether to add a first entry '---'
|
||||
*
|
||||
* @return $prefix_array array The array conatining the unique prefixes
|
||||
*/
|
||||
function getPrefixArray($array, $addNoneOption = true)
|
||||
{
|
||||
$prefixes = array();
|
||||
$keys = array_keys($array);
|
||||
foreach ($keys as $k) {
|
||||
$pos = strpos($k, '_'); // find '_'
|
||||
if ($pos !== false) {
|
||||
$prefix = substr($k, 0, $pos);
|
||||
if (!in_array($prefix, $prefixes)) {
|
||||
$prefixes[$prefix] = $prefix;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($addNoneOption) {
|
||||
$prefixes['-1'] = '---';
|
||||
}
|
||||
ksort($prefixes);
|
||||
return $prefixes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implode the given keys of multidimensional array using the implode string
|
||||
*
|
||||
* @param array $array The array to implode
|
||||
* @param string $key The values that should be imploded
|
||||
* @param string $implodeString The string to concatenate the values with
|
||||
*
|
||||
* @return string The impoloded valuies as string
|
||||
*/
|
||||
function implodeSubarray($array, $key, $implodeString = ', ')
|
||||
{
|
||||
$ret = '';
|
||||
foreach ($array as $k => $v) {
|
||||
$ret .= $v[$key] . $implodeString;
|
||||
}
|
||||
if (strlen($ret) > 1) {
|
||||
$ret = substr($ret, 0, -(strlen($implodeString)));
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
668
inc/functions/functions_dump.php
Normale Datei
668
inc/functions/functions_dump.php
Normale Datei
|
|
@ -0,0 +1,668 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of MySQLDumper released under the GNU/GPL 2 license
|
||||
* http://www.mysqldumper.net
|
||||
*
|
||||
* @package MySQLDumper
|
||||
* @version SVN: $rev: 1209 $
|
||||
* @author $Author$
|
||||
* @lastmodified $Date$
|
||||
*/
|
||||
|
||||
if (!defined('MSD_VERSION')) die('No direct access.');
|
||||
|
||||
/**
|
||||
* Creates a new backup file including the header information
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function createNewFile()
|
||||
{
|
||||
global $dump, $databases, $config, $lang, $log;
|
||||
|
||||
// Dateiname aus Datum und Uhrzeit bilden
|
||||
if ($dump['part'] - $dump['part_offset'] == 1) {
|
||||
$dump['filename_stamp'] = date("Y_m_d_H_i", time());
|
||||
}
|
||||
if ($config['multi_part'] == 1) {
|
||||
$dateiname = $dump['db_actual'] . '_' . $dump['filename_stamp']
|
||||
. '_part_' . ($dump['part'] - $dump['part_offset']);
|
||||
} else {
|
||||
$dateiname = $dump['db_actual'] . '_' . date("Y_m_d_H_i", time());
|
||||
}
|
||||
$endung = ($config['compression']) ? '.sql.gz' : '.sql';
|
||||
$dump['backupdatei'] = $dateiname . $endung;
|
||||
$_SESSION['log']['files_created'][] = $dump['backupdatei'];
|
||||
|
||||
if (file_exists($config['paths']['backup'] . $dump['backupdatei'])) {
|
||||
unlink($config['paths']['backup'] . $dump['backupdatei']);
|
||||
}
|
||||
$curTime = date("Y-m-d H:i");
|
||||
$statuszeile = getStatusLine() . "\n-- Dump by MySQLDumper " . MSD_VERSION
|
||||
. ' (' . $config['homepage'] . ')' . "\n";
|
||||
$statuszeile .= '/*!40101 SET NAMES \'' . $dump['dump_encoding']
|
||||
. '\' */;' . "\n";
|
||||
$statuszeile .= 'SET FOREIGN_KEY_CHECKS=0;' . "\n";
|
||||
|
||||
if ($dump['part'] - $dump['part_offset'] == 1) {
|
||||
$log->write(
|
||||
Log::PHP,
|
||||
sprintf(
|
||||
$lang['L_SAVING_DATA_TO_FILE'],
|
||||
$dump['db_actual'],
|
||||
$dump['backupdatei']
|
||||
)
|
||||
);
|
||||
if ($dump['part'] == 1) {
|
||||
$dump['table_offset'] = 0;
|
||||
$dump['countdata'] = 0;
|
||||
}
|
||||
// Seitenerstaufruf -> Backupdatei anlegen
|
||||
$dump['data'] = $statuszeile . '-- Dump created: ' . $curTime;
|
||||
} else {
|
||||
if ($config['multi_part'] != 0) {
|
||||
$log->write(
|
||||
Log::PHP,
|
||||
sprintf(
|
||||
$lang['L_SAVING_DATA_TO_MULTIPART_FILE'],
|
||||
$dump['backupdatei']
|
||||
)
|
||||
);
|
||||
$dump['data'] = $statuszeile . '-- ' . ' This is part '
|
||||
. ($dump['part'] - $dump['part_offset']) . ' of the backup.'
|
||||
. "\n\n" . $dump['data'];
|
||||
}
|
||||
}
|
||||
writeToDumpFile();
|
||||
$dump['part']++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the first statusline with information for backup files
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getStatusLine()
|
||||
{
|
||||
// strcuture of status line:
|
||||
// -- Status:nrOfTables:nrOfRecords:Multipart:database:script:
|
||||
// scriptversion:comment:MySQL-Version:Backupflags(unused):SQLBefore:
|
||||
//SQLAfter:Charset:CharsetEXTINFO
|
||||
|
||||
global $databases, $config, $dump;
|
||||
if (!defined('MSD_MYSQL_VERSION')) {
|
||||
GetMySQLVersion();
|
||||
}
|
||||
$tline = "-- \n-- TABLE-INFO\r\n";
|
||||
|
||||
foreach ($dump['databases'][$dump['db_actual']]['tables']
|
||||
as $tableName => $val) {
|
||||
$tline .= "-- TABLE|" . $tableName . '|' . $val['records']
|
||||
. '|' . $val['data_length'] . '|' . $val['update_time'] . '|'
|
||||
. $val['engine'] . "\n";
|
||||
}
|
||||
$flags = 1;
|
||||
$mp = 'MP_0';
|
||||
if ($config['multi_part'] == 1) {
|
||||
$mp = "MP_" . ($dump['part'] - $dump['part_offset']);
|
||||
}
|
||||
$statusline = "-- Status:"
|
||||
. $dump['databases'][$dump['db_actual']]['table_count']
|
||||
. ':' . $dump['databases'][$dump['db_actual']]['records_total']
|
||||
. ":$mp:" . $dump['db_actual'] . ":PHP:" . MSD_VERSION . ":"
|
||||
. $dump['comment'] . ":";
|
||||
$statusline .= MSD_MYSQL_VERSION . ":$flags:::" . $dump['dump_encoding']
|
||||
. ":EXTINFO\n" . $tline . "-- " . "EOF TABLE-INFO\n-- ";
|
||||
return $statusline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the DROP and CREATE TABLE string for dump file.
|
||||
*
|
||||
* Parameter $withdata decides if we should add the
|
||||
* "ALTER TABLE DISABLE KEYS"-query.
|
||||
*
|
||||
* @param string $db The database
|
||||
* @param string $table The table
|
||||
* @param integer $withdata Add DISABLE KEYS
|
||||
* @return string $def Created Query-string or false on error
|
||||
*/
|
||||
function getCreateString($db, $table, $withdata = 1)
|
||||
{
|
||||
global $dbo, $config, $dump, $lang, $log;
|
||||
|
||||
$def = "\n\n--\n-- Table structure for table `$table`\n--\n";
|
||||
if ($dump['databases'][$dump['db_actual']]['tables'][$table]['engine']
|
||||
== 'VIEW') {
|
||||
$def .= "DROP VIEW IF EXISTS `$table`;\n";
|
||||
$withdata = 0;
|
||||
} else {
|
||||
$def .= "DROP TABLE IF EXISTS `$table`;\n";
|
||||
}
|
||||
$createStatement = $dbo->getTableCreate($table, $db);
|
||||
$def .= $createStatement . ';' . "\n\n";
|
||||
if ($withdata == 1) {
|
||||
$def .= "--\n-- Dumping data for table `$table`\n--\n";
|
||||
$def .= "/*!40000 ALTER TABLE `$table` DISABLE KEYS */;\n";
|
||||
}
|
||||
$log->write(Log::PHP, sprintf($lang['L_CREATE_TABLE_SAVED'], $table));
|
||||
return $def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read records from table, build query-strings and write them to dump file
|
||||
*
|
||||
* @param string $db The database to read from
|
||||
* @param string $table The table to read from
|
||||
* @return void
|
||||
*/
|
||||
function getContent($db, $table)
|
||||
{
|
||||
global $dbo, $config, $dump, $lang, $log;
|
||||
|
||||
$content = '';
|
||||
$fields = $dbo->getTableColumns($table, $db);
|
||||
// TODO decide if the type of field needs to be escaped and placed between quotes
|
||||
// also handle NULL-values very strict for MySQL-servers running with sql-mod=STRICT
|
||||
$fieldNames = array_keys($fields);
|
||||
$fieldList = '`' . implode('`,`', $fieldNames) . '`';
|
||||
// indicator if the actual table is fully dumped in this call
|
||||
$tableDone = 0;
|
||||
$sql = 'SELECT * FROM `' . $db . '`.`' . $table . '` LIMIT '
|
||||
. $dump['table_record_offset'] . ',' . ($dump['restzeilen'] + 1);
|
||||
$result = $dbo->query($sql, MsdDbFactory::ARRAY_NUMERIC);
|
||||
$numRows = @count($result);
|
||||
if ($numRows > 0) {
|
||||
// we've got records - get fields
|
||||
$numfields = count($result[0]);
|
||||
if ($numRows > $dump['restzeilen']) {
|
||||
// there are more records to get - table is not fully dumped
|
||||
$dump['table_record_offset'] += $dump['restzeilen']; //set table record offset for next call
|
||||
$numRows--; // correct counter - we only used the last record to find out if there is more to fetch
|
||||
unset($result[$numRows]);
|
||||
} else {
|
||||
// table is done -> increase table offset
|
||||
$recordsSaved = $dump['table_record_offset'] + $numRows;
|
||||
$log->write(
|
||||
Log::PHP,
|
||||
sprintf(
|
||||
$lang['L_BACKUP_TABLE_DONE'],
|
||||
$table,
|
||||
String::formatNumber($recordsSaved)
|
||||
)
|
||||
);
|
||||
$dump['table_offset']++;
|
||||
$dump['table_offset_total']++;
|
||||
$dump['table_record_offset'] = 0;
|
||||
$tableDone = 1;
|
||||
}
|
||||
foreach ($result as $row) {
|
||||
//if($config['backup_using_updates']==1){
|
||||
$insert = 'INSERT INTO `' . $table . '` (' . $fieldList
|
||||
. ') VALUES (';
|
||||
//TODO implement REPLACE INTO for expert mode
|
||||
// }
|
||||
//else{
|
||||
//$insert='REPLACE INTO `'.$table.'` '.$complete.' VALUES (';
|
||||
// }
|
||||
|
||||
foreach ($row as $field => $val) {
|
||||
if ($val != '') $insert .= '\'' . $dbo->escape($val) . '\',';
|
||||
else $insert .= '\'\',';
|
||||
}
|
||||
$insert = substr($insert, 0, -1) . ');' . "\n";
|
||||
$dump['data'] .= $insert;
|
||||
$dump['restzeilen']--;
|
||||
$dump['countdata']++;
|
||||
if (strlen($dump['data']) > $config['memory_limit']
|
||||
|| ($config['multi_part'] == 1
|
||||
&& strlen($dump['data']) + MULTIPART_FILESIZE_BUFFER
|
||||
> $config['multipart_groesse'])) {
|
||||
writeToDumpFile();
|
||||
}
|
||||
}
|
||||
if ($tableDone == 1) {
|
||||
// check if records have been saved and add "enable keys"
|
||||
$tables = $dump['databases'][$dump['db_actual']]['tables'];
|
||||
if ($tables[$table]['dump_records'] == 1) {
|
||||
$dump['data'] .= "/*!40000 ALTER TABLE `$table`"
|
||||
." ENABLE KEYS */;";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// table corrupt -> skip it
|
||||
$dump['table_offset']++;
|
||||
$dump['table_offset_total']++;
|
||||
$dump['table_record_offset'] = 0;
|
||||
$dump['restzeilen'] = $dump['restzeilen'] - $numRows;
|
||||
$dump['data'] .= "/*!40000 ALTER TABLE `$table` ENABLE KEYS */;\n";
|
||||
if (strlen($dump['data']) > $config['memory_limit']
|
||||
|| ($config['multi_part'] == 1 && strlen($dump['data'])
|
||||
+ MULTIPART_FILESIZE_BUFFER > $config['multipart_groesse'])) {
|
||||
writeToDumpFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the created data of global var $dump['data'] to the dump file.
|
||||
*
|
||||
* If Multipart is used and the maximum filesize is reached a new file is
|
||||
* created. Sets global var $dump['filesize'] to new vaule for printing
|
||||
* on sccreen.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function writeToDumpFile()
|
||||
{
|
||||
global $config, $dump;
|
||||
$file = $config['paths']['backup'] . $dump['backupdatei'];
|
||||
|
||||
if ($config['compression'] == 1) {
|
||||
if ($dump['data'] != '') {
|
||||
$fp = gzopen($file, 'ab');
|
||||
gzwrite($fp, $dump['data']);
|
||||
gzclose($fp);
|
||||
}
|
||||
} else {
|
||||
if ($dump['data'] != '') {
|
||||
$fp = fopen($file, 'ab');
|
||||
fwrite($fp, $dump['data']);
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
$dump['data'] = '';
|
||||
clearstatcache();
|
||||
$dump['filesize'] = intval(@filesize($file));
|
||||
// if Multipart is used and maximum filesize is reached -> create new file
|
||||
if ($config['multi_part'] == 1) {
|
||||
if ($dump['filesize'] + MULTIPART_FILESIZE_BUFFER
|
||||
> $config['multipart_groesse']) {
|
||||
@chmod($file, 0777);
|
||||
createNewFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is a next db to be dumped
|
||||
*
|
||||
* Sets the global flag $dump['backup_done']
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function checkForNextDB()
|
||||
{
|
||||
global $dump;
|
||||
// a check, if another db should be saved is at the end of the script
|
||||
// backup of actual db is done -> lets check if there is more to do
|
||||
$nextDb = getNextKey($dump['databases'], $dump['db_actual']);
|
||||
if ($nextDb !== false) {
|
||||
$dump['backup_done'] = 0;
|
||||
//-1 instead of 0 is needed for the execution of command before backup
|
||||
$dump['table_offset'] = -1;
|
||||
$dump['db_actual'] = $nextDb;
|
||||
$dump['part_offset'] = $dump['part'] - 1;
|
||||
} else {
|
||||
$dump['backup_done'] = 1;
|
||||
$dump['table_offset_total']--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute queries before and after the backup process
|
||||
*
|
||||
* Queries are saved in the configuration profile
|
||||
*
|
||||
* @param string $when Before (b) or after backup process
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function executeCommand($when)
|
||||
{
|
||||
// TODO implement execution of command before/after backup
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send e-mail and attach file
|
||||
*
|
||||
* @param string $file
|
||||
* @return boolean
|
||||
*/
|
||||
function doEmail($file)
|
||||
{
|
||||
global $config, $dump, $lang, $log;
|
||||
include ('lib/phpmailer/php5/class.phpmailer.php');
|
||||
include ('inc/classes/helper/Html.php');
|
||||
// get some status info from actual file
|
||||
$rootpath = $config['paths']['root'] . $config['paths']['backup'];
|
||||
$fileInfo = ReadStatusline($file);
|
||||
$fileInfo['size'] = @filesize($rootpath . $file);
|
||||
$database = $fileInfo['dbname'];
|
||||
$tablesSaved = $fileInfo['tables'];
|
||||
$recordsSaved = $fileInfo['tables'];
|
||||
|
||||
if (sizeof($_SESSION['email']['filelist']) == 0) {
|
||||
// first call after backup -> create file list of all files for each database
|
||||
$_SESSION['email']['filelist'] = array();
|
||||
foreach ($_SESSION['log']['email'] as $filename) {
|
||||
$statusInfo = ReadStatusline($filename);
|
||||
if (!isset($_SESSION['email']['filelist'][$statusInfo['dbname']])) {
|
||||
$_SESSION['email']['filelist'][$statusInfo['dbname']] = array();
|
||||
}
|
||||
$_SESSION['email']['filelist'][$statusInfo['dbname']][] = $filename;
|
||||
}
|
||||
}
|
||||
// create file list for specific database
|
||||
$filelist = '';
|
||||
foreach ($_SESSION['email']['filelist'][$database] as $filename) {
|
||||
$phpSelf = $_SERVER['PHP_SELF'];
|
||||
$linkToFile = '<a href="' . getServerProtocol()
|
||||
. $_SERVER['HTTP_HOST']
|
||||
. substr($phpSelf, 0, strrpos($phpSelf, '/'))
|
||||
. '/' . $config['paths']['backup'] . $filename . '">'
|
||||
. $filename . '</a>';
|
||||
$filelist .= $linkToFile;
|
||||
if ($file == $filename && $config['email']['attach_backup']) {
|
||||
$filelist .= ' (' . $lang['L_ATTACHED_AS_FILE'] . ')';
|
||||
}
|
||||
$filelist .= '<br />' . "\n";
|
||||
}
|
||||
|
||||
$mail = new PHPMailer();
|
||||
$mail->CharSet = 'utf-8';
|
||||
$mail->PlugInDir = 'lib/phpmailer/php5/';
|
||||
$mail->From = $config['email']['sender_address'];
|
||||
$mail->FromName = $config['email']['sender_name'];
|
||||
$mail->AddAddress($config['email']['recipient_address'], $config['email']['recipient_name']);
|
||||
|
||||
// add cc-recipients
|
||||
foreach ($config['email']['recipient_cc'] as $recipient) {
|
||||
if ($recipient['address'] > '') {
|
||||
$mail->AddCC($recipient['address'], $recipient['name']);
|
||||
}
|
||||
}
|
||||
//build subject
|
||||
$subject = $lang['L_DUMP_FILENAME'] . ': ' . $file;
|
||||
if ($fileInfo['comment'] > '') {
|
||||
$subject = $fileInfo['comment'] . ', ' . $subject;
|
||||
}
|
||||
$mail->Subject = $subject;
|
||||
|
||||
$mail->Timeout = 60;
|
||||
// set used mail-method
|
||||
$mail->IsMail(); //defaults to php-mail-function
|
||||
if ($config['use_mailer'] == 1) {
|
||||
$mail->IsSendmail();
|
||||
$mail->Sendmail = $config['sendmail_call'];
|
||||
} elseif ($config['use_mailer'] == 2) {
|
||||
$mail->IsSMTP();
|
||||
//debug
|
||||
//$mail->SMTPDebug = PHP_INT_MAX;
|
||||
$mail->Host = $config['smtp_server'];
|
||||
$mail->Port = $config['smtp_port'];
|
||||
// auth?
|
||||
if ($config['smtp_useauth']) {
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = $config['smtp_user'];
|
||||
$mail->Password = $config['smtp_pass'];
|
||||
}
|
||||
//use ssl?
|
||||
if ($config['smtp_usessl']) {
|
||||
$mail->SMTPSecure = 'tls';
|
||||
}
|
||||
}
|
||||
|
||||
//build mail body
|
||||
$body = '';
|
||||
|
||||
//add attachement?
|
||||
if ($config['email']['attach_backup']) {
|
||||
//check if file is bigger than allowed max size
|
||||
if ($config['email_maxsize'] > 0
|
||||
&& $fileInfo['size'] > $config['email_maxsize']) {
|
||||
// attachement too big -> don't attach and paste message to body
|
||||
$body .= sprintf(
|
||||
$lang['L_EMAILBODY_TOOBIG'],
|
||||
byteOutput($config['email_maxsize']),
|
||||
$database,
|
||||
$file . ' (' . byte_output(
|
||||
filesize($config['paths']['backup'] . $file)
|
||||
)
|
||||
. ')<br />'
|
||||
);
|
||||
} else {
|
||||
// add file as attachement
|
||||
$mail->AddAttachment($rootpath . $file);
|
||||
$body .= sprintf($lang['L_EMAILBODY_ATTACH'], $database, $filelist);
|
||||
}
|
||||
} else {
|
||||
// don't attach backup file according to configuration
|
||||
$body .= sprintf(
|
||||
$lang['L_EMAILBODY_TOOBIG'],
|
||||
byteOutput($config['email_maxsize']),
|
||||
$database,
|
||||
"$file (" . byteOutput(
|
||||
filesize($config['paths']['backup'] . $file)
|
||||
)
|
||||
. ")<br />"
|
||||
);
|
||||
}
|
||||
|
||||
//set body
|
||||
$mail->MsgHTML($body);
|
||||
//build alternative-body without tags for mail-clients blocking HTML
|
||||
$altBody = strip_tags(Html::br2nl($body));
|
||||
$mail->AltBody = $altBody;
|
||||
|
||||
$mail->Timeout = 30;
|
||||
$ret = $mail->Send();
|
||||
if (!$ret) {
|
||||
writeToErrorLog(
|
||||
'', '', $lang['L_MAILERROR'] . ' -> ' . $mail->ErrorInfo, 0
|
||||
);
|
||||
$log->write(Log::PHP, $lang['L_MAILERROR']);
|
||||
} else {
|
||||
$msg = $lang['L_EMAIL_WAS_SEND'] . "`"
|
||||
. $config['email']['recipient_address'];
|
||||
$log->write(Log::PHP, $msg);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers a file via FTP and logs each action
|
||||
*
|
||||
* @param integer $ftpConnectionIndex Index of FTP-Connection in configuration
|
||||
* @param string $sourceFile File to transfer
|
||||
* @return void
|
||||
*/
|
||||
function sendViaFTP($ftpConnectionIndex, $sourceFile)
|
||||
{
|
||||
global $config, $lang, $log;
|
||||
|
||||
$upload = false;
|
||||
$i = $ftpConnectionIndex; // I am lazy ;)
|
||||
// connect to ftp server
|
||||
if ($config['ftp'][$i]['ssl'] == 0) {
|
||||
$connId = @ftp_connect(
|
||||
$config['ftp'][$i]['server'],
|
||||
$config['ftp'][$i]['port'],
|
||||
$config['ftp'][$i]['timeout']
|
||||
);
|
||||
} else {
|
||||
$connId = @ftp_ssl_connect(
|
||||
$config['ftp'][$i]['server'],
|
||||
$config['ftp'][$i]['port'],
|
||||
$config['ftp'][$i]['timeout']
|
||||
);
|
||||
}
|
||||
|
||||
if (is_resource($connId)) {
|
||||
$log->write(
|
||||
Log::PHP,
|
||||
$lang['L_FTP'] . ': ' .
|
||||
sprintf(
|
||||
$lang['L_FTP_CONNECTION_SUCCESS'],
|
||||
$config['ftp'][$i]['server'],
|
||||
$config['ftp'][$i]['port']
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$msg = sprintf(
|
||||
$lang['L_FTP_CONNECTION_ERROR'],
|
||||
$config['ftp'][$i]['server'],
|
||||
$config['ftp'][$i]['port']
|
||||
);
|
||||
writeToErrorLog('', '', $lang['L_FTP'] . ': ' . $msg, 0);
|
||||
}
|
||||
|
||||
// login using user and password
|
||||
$loginResult = @ftp_login(
|
||||
$connId,
|
||||
$config['ftp'][$i]['user'],
|
||||
$config['ftp'][$i]['pass']
|
||||
);
|
||||
if (!$loginResult) {
|
||||
writeToErrorLog(
|
||||
'',
|
||||
'',
|
||||
$lang['L_FTP'] . ': ' . sprintf(
|
||||
$lang['L_FTP_LOGIN_ERROR'],
|
||||
$config['ftp'][$i]['user']
|
||||
),
|
||||
0
|
||||
);
|
||||
} else {
|
||||
$log->write(
|
||||
Log::PHP,
|
||||
$lang['L_FTP'] . ': ' . sprintf(
|
||||
$lang['L_FTP_LOGIN_SUCCESS'],
|
||||
$config['ftp'][$i]['user']
|
||||
)
|
||||
);
|
||||
}
|
||||
if ($config['ftp'][$i]['mode'] == 1) {
|
||||
if (@ftp_pasv($connId, true)) {
|
||||
$log->write(
|
||||
Log::PHP,
|
||||
$lang['L_FTP'] . ': ' . $lang['L_FTP_PASV_SUCCESS']
|
||||
);
|
||||
} else {
|
||||
writeToErrorLog(
|
||||
'', '',
|
||||
$lang['L_FTP'] . ': ' . $lang['L_FTP_PASV_ERROR'], 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Upload der Datei
|
||||
$dest = $config['ftp'][$i]['dir'] . $sourceFile;
|
||||
$source = $config['paths']['backup'] . $sourceFile;
|
||||
$upload = @ftp_put($connId, $dest, $source, FTP_BINARY);
|
||||
// Upload-Status überprüfen
|
||||
if (!$upload) {
|
||||
writeToErrorLog(
|
||||
'', '', sprintf($lang['L_FTP_FILE_TRANSFER_ERROR'], $sourceFile), 0
|
||||
);
|
||||
} else {
|
||||
$log->write(
|
||||
Log::PHP,
|
||||
sprintf($lang['L_FTP_FILE_TRANSFER_SUCCESS'], $sourceFile)
|
||||
);
|
||||
}
|
||||
|
||||
// Schließen des FTP-Streams
|
||||
@ftp_quit($connId);
|
||||
$log->write(Log::PHP, $lang['L_FTP_CONNECTION_CLOSED']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all information about a dump process and stores it in global $dump-Array
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function prepareDumpProcess()
|
||||
{
|
||||
global $databases, $dump, $config, $tableInfos;
|
||||
$dump['databases'] = array();
|
||||
$dump['records_total'] = 0;
|
||||
$dump['tables_total'] = 0;
|
||||
$dump['datasize_total'] = 0;
|
||||
// make copy of database-array to make changes for value "dump" just here
|
||||
$dbs = $databases;
|
||||
// first check if any db is marked to be dumped
|
||||
$dbToDumpExists = false;
|
||||
foreach ($dbs as $val) {
|
||||
if (isset($val['dump']) && $val['dump'] == 1) {
|
||||
// Db should be saved
|
||||
$dbToDumpExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// no db selected for dump -> set actual db to be dumped
|
||||
if (!$dbToDumpExists) {
|
||||
$dbs[$config['db_actual']]['dump'] = 1;
|
||||
}
|
||||
|
||||
// find out which databases and tables should be saved
|
||||
// dump=0 -> don't dump records
|
||||
// dump=1 -> dump records using "INSERT INTO"
|
||||
foreach ($dbs as $dbName => $val) {
|
||||
if (isset($val['dump']) && $val['dump'] > 0) {
|
||||
// db should be dumped
|
||||
// now lets check which tables should be saved
|
||||
// for now we save all tables -> later check prefixes etc...
|
||||
$tableInfos = getTableInfo($dbName);
|
||||
if (isset($tableInfos[$dbName])) {
|
||||
if (!isset($dump['databases'][$dbName])) {
|
||||
$dump['databases'][$dbName] = array();
|
||||
}
|
||||
// calculate sums
|
||||
$dump['databases'][$dbName] = $tableInfos[$dbName];
|
||||
$dump['databases'][$dbName]['prefix'] = '';
|
||||
if (isset($databases[$dbName]['prefix'])) {
|
||||
$dump['databases'][$dbName]['prefix'] =
|
||||
$databases[$dbName]['prefix'];
|
||||
}
|
||||
$dump['records_total'] +=
|
||||
$dump['databases'][$dbName]['records_total'];
|
||||
$dump['tables_total'] +=
|
||||
$dump['databases'][$dbName]['table_count'];
|
||||
$dump['datasize_total'] +=
|
||||
$dump['databases'][$dbName]['datasize_total'];
|
||||
|
||||
// check if tables are selected ->
|
||||
// then remove all others from array and correct sums
|
||||
if ($dbName == $_SESSION['config']['db_actual']
|
||||
&& isset($dump['selected_tables'])
|
||||
&& is_array($dump['selected_tables'])
|
||||
&& count($dump['selected_tables']) > 0) {
|
||||
foreach ($dump['databases'][$dbName]['tables']
|
||||
as $tablename => $val) {
|
||||
if (!in_array($tablename, $dump['selected_tables'])) {
|
||||
$dump['databases'][$dbName]['tables'][$tablename]['dump_structure'] = 0;
|
||||
$dump['databases'][$dbName]['tables'][$tablename]['dump_records'] = 0;
|
||||
|
||||
// remove table from todo-list
|
||||
unset($dump['databases'][$dbName]['tables'][$tablename]);
|
||||
// substract values of table from sums
|
||||
$dump['tables_total']--;
|
||||
$dump['databases'][$dbName]['table_count']--;
|
||||
$dump['databases'][$dbName]['records_total'] -= $val['records'];
|
||||
$dump['databases'][$dbName]['datasize_total'] -= $val['data_length'];
|
||||
$dump['databases'][$dbName]['size_total'] -= $val['data_length'] + $val['index_length'];
|
||||
$dump['datasize_total'] -= $val['data_length'];
|
||||
$dump['records_total'] -= $val['records'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// set db to be dumped first -> start index is needed
|
||||
$dbNames=array_keys($dump['databases']);
|
||||
$dump['db_actual'] = $dbNames[0];
|
||||
}
|
||||
|
||||
370
inc/functions/functions_files.php
Normale Datei
370
inc/functions/functions_files.php
Normale Datei
|
|
@ -0,0 +1,370 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of MySQLDumper released under the GNU/GPL 2 license
|
||||
* http://www.mysqldumper.net
|
||||
*
|
||||
* @package MySQLDumper
|
||||
* @version SVN: $rev: 1207 $
|
||||
* @author $Author$
|
||||
* @lastmodified $Date$
|
||||
*/
|
||||
|
||||
if (!defined('MSD_VERSION')) die('No direct access.');
|
||||
/**
|
||||
* Read list of backups in work/backup and create selectbox.
|
||||
*
|
||||
* Used in backup converter.
|
||||
*
|
||||
* @param string $selected selected file
|
||||
* @return string String containing HTML-selectbox ready to output
|
||||
*/
|
||||
function getFilelisteCombo($selected)
|
||||
{
|
||||
global $config;
|
||||
$files = array();
|
||||
$dir = new DirectoryIterator($config['paths']['backup']);
|
||||
foreach ($dir as $fileinfo)
|
||||
{
|
||||
$file = $fileinfo->getFilename();
|
||||
if ($file[0] != '.' && $fileinfo->isFile())
|
||||
{
|
||||
$size = byteOutput($fileinfo->getSize());
|
||||
$files["$file"] = $file . ' (' . $size . ')';
|
||||
}
|
||||
}
|
||||
ksort($files);
|
||||
$r = Html::getOptionlist($files, $selected);
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reformat a date from format dd.mm.yyyy hh:mm to yyyy.mm.dd hh:mm to make it sortable.
|
||||
*
|
||||
* @param string $datum Datetime taken from filename
|
||||
* @return string
|
||||
*/
|
||||
function getSortableDate($datum)
|
||||
{
|
||||
$p = explode(' ', $datum);
|
||||
$uhrzeit = $p[1];
|
||||
$p2 = explode('.', $p[0]);
|
||||
$day = $p2[0];
|
||||
$month = $p2[1];
|
||||
$year = $p2[2];
|
||||
return $year . '.' . $month . '.' . $day . ' ' . $uhrzeit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a dump file and converts it.
|
||||
*
|
||||
* Places field names in backticks and splitts files into 10 MB-Parts.
|
||||
*
|
||||
* @param string $filesource File to convert
|
||||
* @param string $db_name Database name will be used to create filenames and statusline
|
||||
* @param string $cp Target copy file
|
||||
* @return void
|
||||
*/
|
||||
function convert($filesource, $db_name, $cp)
|
||||
{
|
||||
global $config, $lang;
|
||||
@ini_set('max_input_time', '0'); // for real big dumps
|
||||
|
||||
|
||||
$filesize = 0;
|
||||
$max_filesize = 1024 * 1024 * 10; //10 MB splitsize
|
||||
$part = 1;
|
||||
$cps = (substr(strtolower($filesource), -2) == "gz") ? 1 : 0;
|
||||
// we compare the string size with this value (not the real filesie)
|
||||
//so if file is compressed we need to adjust it
|
||||
if ($cps == 1) $max_filesize *= 7;
|
||||
|
||||
$filedestination = $db_name . '_' . date("Y_m_d_H_i", time());
|
||||
echo "<h5>" . sprintf($lang['L_CONVERT_FILEREAD'], $filesource) . ".....</h5><span style=\"font-size:10px;\">";
|
||||
if (file_exists($config['paths']['backup'] . $filedestination)) unlink($config['paths']['backup'] . $filedestination);
|
||||
$f = ($cps == 1) ? gzopen($config['paths']['backup'] . $filesource, "r") : fopen($config['paths']['backup'] . $filesource, "r");
|
||||
$z = ($cp == 1) ? gzopen($config['paths']['backup'] . $filedestination . '_part_1.sql.gz', "w") : fopen($config['paths']['backup'] . $filedestination . '_part_1.sql', "w");
|
||||
|
||||
$zeile = getPseudoStatusline($part, $db_name) . "\r\n";
|
||||
($cp == 1) ? gzwrite($z, $zeile) : fwrite($z, $zeile);
|
||||
$zeile = '';
|
||||
flush();
|
||||
|
||||
$insert = $mode = "";
|
||||
$n = 0;
|
||||
$eof = ($cps == 1) ? gzeof($f) : feof($f);
|
||||
$splitable = false; // can the file be splitted? Try to avoid splitting before a command is completed
|
||||
WHILE (!$eof)
|
||||
{
|
||||
flush();
|
||||
$eof = ($cps == 1) ? gzeof($f) : feof($f);
|
||||
$zeile = ($cps == 1) ? gzgets($f, 5144000) : fgets($f, 5144000);
|
||||
|
||||
$t = strtolower(substr($zeile, 0, 10));
|
||||
if ($t > '')
|
||||
{
|
||||
switch ($t)
|
||||
{
|
||||
case 'insert int':
|
||||
{
|
||||
// eine neue Insert Anweisung beginnt
|
||||
if (strpos($zeile, '(') === false)
|
||||
{
|
||||
//Feldnamen stehen in der naechsten Zeile - holen
|
||||
$zeile .= "\n\r";
|
||||
$zeile .= ($cps == 1) ? trim(gzgets($f, 8192)) : trim(fgets($f, 8192));
|
||||
$zeile .= ' ';
|
||||
}
|
||||
|
||||
// get INSERT-Satement
|
||||
$insert = substr($zeile, 0, strpos($zeile, '('));
|
||||
if (substr(strtoupper($insert), -7) != 'VALUES ') $insert .= ' VALUES ';
|
||||
$mode = 'insert';
|
||||
$splitable = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'create tab':
|
||||
{
|
||||
$mode = 'create';
|
||||
WHILE (substr(rtrim($zeile), -1) != ';')
|
||||
{
|
||||
$zeile .= fgets($f, 8192);
|
||||
}
|
||||
$zeile = setBackticks($zeile) . "\n\r";
|
||||
$splitable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($mode == 'insert')
|
||||
{
|
||||
if (substr(rtrim($zeile), strlen($zeile) - 3, 2) == ');') $splitable = true;
|
||||
|
||||
// Komma loeschen
|
||||
$zeile = str_replace('),(', ");\n\r" . $insert . ' (', $zeile);
|
||||
}
|
||||
|
||||
if ($splitable == true && $filesize > $max_filesize) // start new file?
|
||||
{
|
||||
$part++;
|
||||
if ($mode == 'insert') // Insert -> first complete Insert-Statement, then begin new file
|
||||
{
|
||||
if ($cp == 1)
|
||||
{
|
||||
gzwrite($z, $zeile);
|
||||
gzclose($z);
|
||||
$z = gzopen($config['paths']['backup'] . $filedestination . '_part_' . $part . '.sql.gz', "w");
|
||||
$zeile = getPseudoStatusline($part, $db_name) . "\r\n";
|
||||
gzwrite($z, $zeile);
|
||||
$zeile = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite($z, $zeile);
|
||||
fclose($z);
|
||||
$z = fopen($config['paths']['backup'] . $filedestination . '_part_' . $part . '.sql', "w");
|
||||
$zeile = getPseudoStatusline($part, $db_name) . "\r\n";
|
||||
gzwrite($z, $zeile);
|
||||
$zeile = '';
|
||||
}
|
||||
}
|
||||
else // first close last file, then begin new one and write new beginning command
|
||||
{
|
||||
if ($cp == 1)
|
||||
{
|
||||
gzclose($z);
|
||||
$z = gzopen($config['paths']['backup'] . $filedestination . '_part_' . $part . '.sql.gz', "w");
|
||||
$zeile = getPseudoStatusline($part, $filedestination) . "\r\n" . $zeile;
|
||||
gzwrite($z, $zeile);
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose($z);
|
||||
$z = fopen($config['paths']['backup'] . $filedestination . '_part_' . $part . '.sql', "w");
|
||||
$zeile = getPseudoStatusline($part, $filedestination) . "\r\n" . $zeile;
|
||||
fwrite($z, $zeile);
|
||||
}
|
||||
$n = 0;
|
||||
}
|
||||
$filesize = 0;
|
||||
$splitable = false;
|
||||
}
|
||||
else // no, append to actual file
|
||||
{
|
||||
$filesize += strlen($zeile);
|
||||
if ($n > 200)
|
||||
{
|
||||
$n = 0;
|
||||
echo '<br />';
|
||||
}
|
||||
echo '.';
|
||||
if ($cps == 1) gzwrite($z, $zeile);
|
||||
else fwrite($z, $zeile);
|
||||
flush();
|
||||
}
|
||||
$n++;
|
||||
}
|
||||
$zeile = "\n-- EOB";
|
||||
if ($cps == 1)
|
||||
{
|
||||
gzwrite($z, $zeile);
|
||||
gzclose($z);
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite($z, $zeile);
|
||||
fclose($z);
|
||||
}
|
||||
|
||||
if ($cps == 1) gzclose($f);
|
||||
else fclose($f);
|
||||
echo '</span><h5>' . sprintf($lang['L_CONVERT_FINISHED'], $filedestination) . '</h5>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a dummy statusline.
|
||||
*
|
||||
* Used when converting a file, to create a legal MSD-Multipart-File.
|
||||
*
|
||||
* @param integer $part
|
||||
* @param string $db_name
|
||||
* @return string
|
||||
*/
|
||||
function getPseudoStatusline($part, $db_name)
|
||||
{
|
||||
if ($part > 1) echo '<br />Continue with part: ' . $part . '<br />';
|
||||
$ret = '-- Status:-1:-1:MP_' . ($part) . ':' . $db_name . ":php:converter2:converted:unknown:1:::latin1:EXTINFO\r\n" . "-- TABLE-INFO\r\n" . "-- TABLE|unknown|0|0|2009-01-24 20:39:39\r\n" . "-- EOF TABLE-INFO\r\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read information from all backup files in folder work/backup and return multidimensional array
|
||||
* containing all info.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getBackupfileInfo()
|
||||
{
|
||||
global $config;
|
||||
clearstatcache();
|
||||
$files = Array();
|
||||
$dh = opendir($config['paths']['backup']);
|
||||
while (false !== ($filename = readdir($dh)))
|
||||
{
|
||||
if ($filename != '.' && $filename != '..' && !is_dir($config['paths']['backup'] . $filename))
|
||||
{
|
||||
$files[]['name'] = $filename;
|
||||
}
|
||||
}
|
||||
$arrayindex = 0;
|
||||
$total_filesize = 0;
|
||||
$db_backups = array();
|
||||
$db_summary_anzahl = array();
|
||||
$db_summary_last = array();
|
||||
if (count($files) > 0)
|
||||
{
|
||||
for ($i = 0; $i < sizeof($files); $i++)
|
||||
{
|
||||
// filesize
|
||||
$size = filesize($config['paths']['backup'] . $files[$i]['name']);
|
||||
$file_datum = date("d\.m\.Y H:i", filemtime($config['paths']['backup'] . $files[$i]['name']));
|
||||
$statusline = ReadStatusline($files[$i]['name']);
|
||||
$backup_timestamp = GetTimestampFromFilename($files[$i]['name']);
|
||||
$pathinfo = pathinfo($files[$i]['name']);
|
||||
$file_extension = $pathinfo['extension'];
|
||||
if ($backup_timestamp == '') $backup_timestamp = $file_datum;
|
||||
$database_name = $statusline['dbname'];
|
||||
|
||||
// check for some special cases
|
||||
if ($database_name == 'unknown') $database_name = '~unknown'; // needed for sorting - place unknown files at the end
|
||||
if ($statusline['comment'] == 'converted') $database_name = '~converted'; // converted fiels
|
||||
|
||||
|
||||
//jetzt alle in ein Array packen
|
||||
if ($statusline['part'] == 'MP_0' || $statusline['part'] == '')
|
||||
{
|
||||
$db_backups[$arrayindex]['name'] = $files[$i]['name'];
|
||||
$db_backups[$arrayindex]['db'] = $database_name;
|
||||
$db_backups[$arrayindex]['extension'] = $file_extension;
|
||||
$db_backups[$arrayindex]['size'] = $size;
|
||||
$db_backups[$arrayindex]['date'] = $backup_timestamp;
|
||||
$db_backups[$arrayindex]['sort'] = getSortableDate($backup_timestamp);
|
||||
$db_backups[$arrayindex]['tables'] = $statusline['tables'];
|
||||
$db_backups[$arrayindex]['records'] = $statusline['records'];
|
||||
$db_backups[$arrayindex]['multipart'] = 0;
|
||||
$db_backups[$arrayindex]['comment'] = $statusline['comment'];
|
||||
$db_backups[$arrayindex]['script'] = ($statusline['script'] != '') ? $statusline['script'] . '(' . $statusline['scriptversion'] . ')' : '';
|
||||
$db_backups[$arrayindex]['charset'] = $statusline['charset'];
|
||||
$db_backups[$arrayindex]['mysqlversion'] = $statusline['mysqlversion'];
|
||||
if (!isset($db_summary_last[$database_name])) $db_summary_last[$database_name] = $backup_timestamp;
|
||||
$db_summary_anzahl[$database_name] = (isset($db_summary_anzahl[$database_name])) ? $db_summary_anzahl[$database_name] + 1 : 1;
|
||||
$db_summary_size[$database_name] = (isset($db_summary_size[$database_name])) ? $db_summary_size[$database_name] + $size : $size;
|
||||
if (getSortableDate($backup_timestamp) > getSortableDate($db_summary_last[$database_name])) $db_summary_last[$database_name] = $backup_timestamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
//v($statusline);
|
||||
//list multipart files only once but keep info how many files belong to this backup
|
||||
$done = 0;
|
||||
if (!isset($db_summary_size[$database_name])) {
|
||||
$db_summary_size[$database_name] = 0;
|
||||
}
|
||||
for ($j = 0; $j < $arrayindex; $j++)
|
||||
{
|
||||
if (isset($db_backups[$j]))
|
||||
{
|
||||
if (($db_backups[$j]['date'] == $backup_timestamp) && $db_backups[$j]['db'] == $database_name && $db_backups[$j]['extension'] == $file_extension)
|
||||
{
|
||||
$db_backups[$j]['mysqlversion'] = $statusline['mysqlversion'];
|
||||
$db_backups[$j]['multipart']++;
|
||||
$db_backups[$j]['size'] += $size; // calculate size for this multipart backup
|
||||
$db_summary_size[$database_name] += $size; // calculate total size for this database
|
||||
$done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($done == 1) $arrayindex--;
|
||||
|
||||
if ($done == 0)
|
||||
{
|
||||
//new entry for this backup with this timestamp
|
||||
$db_backups[$arrayindex]['name'] = $files[$i]['name'];
|
||||
$db_backups[$arrayindex]['db'] = $database_name;
|
||||
$db_backups[$arrayindex]['extension'] = $file_extension;
|
||||
$db_backups[$arrayindex]['size'] = $size;
|
||||
$db_backups[$arrayindex]['date'] = $backup_timestamp;
|
||||
$db_backups[$arrayindex]['sort'] = getSortableDate($backup_timestamp);
|
||||
$db_backups[$arrayindex]['tables'] = $statusline['tables'];
|
||||
$db_backups[$arrayindex]['records'] = $statusline['records'];
|
||||
$db_backups[$arrayindex]['multipart'] = 1;
|
||||
$db_backups[$arrayindex]['comment'] = $statusline['comment'];
|
||||
$db_backups[$arrayindex]['script'] = ($statusline['script'] != "") ? $statusline['script'] . "(" . $statusline['scriptversion'] . ")" : "";
|
||||
$db_backups[$arrayindex]['charset'] = $statusline['charset'];
|
||||
|
||||
if (!isset($db_summary_last[$database_name])) $db_summary_last[$database_name] = $backup_timestamp;
|
||||
$db_summary_anzahl[$database_name] = (isset($db_summary_anzahl[$database_name])) ? $db_summary_anzahl[$database_name] + 1 : 1;
|
||||
$db_summary_size[$database_name] = (isset($db_summary_size[$database_name])) ? $db_summary_size[$database_name] + $size : $size;
|
||||
if (getSortableDate($backup_timestamp) > getSortableDate($db_summary_last[$database_name])) $db_summary_last[$database_name] = $backup_timestamp;
|
||||
}
|
||||
}
|
||||
$arrayindex++;
|
||||
$total_filesize += $size; // calculate overall file size
|
||||
}
|
||||
}
|
||||
if ((isset($db_backups)) && (is_array($db_backups))) $db_backups = arfsort($db_backups, get_orderarray('sort,d|name,A'));
|
||||
// merge infos into one array
|
||||
$info = array();
|
||||
$info['filesize_total'] = $total_filesize; // total size of all files
|
||||
$info['files'] = $db_backups; // info per file
|
||||
unset($db_backups);
|
||||
$info['databases'] = array();
|
||||
foreach ($db_summary_anzahl as $db => $count)
|
||||
{
|
||||
$info['databases'][$db]['backup_count'] = $count;
|
||||
$info['databases'][$db]['backup_size_total'] = $db_summary_size[$db];
|
||||
$info['databases'][$db]['latest_backup_timestamp'] = $db_summary_last[$db];
|
||||
}
|
||||
return $info;
|
||||
}
|
||||
915
inc/functions/functions_global.php
Normale Datei
915
inc/functions/functions_global.php
Normale Datei
|
|
@ -0,0 +1,915 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of MySQLDumper released under the GNU/GPL 2 license
|
||||
* http://www.mysqldumper.net
|
||||
*
|
||||
* @package MySQLDumper
|
||||
* @version SVN: $rev: 1213 $
|
||||
* @author $Author$
|
||||
* @lastmodified $Date$
|
||||
*/
|
||||
if (!defined('MSD_VERSION'))
|
||||
die('No direct access.');
|
||||
/**
|
||||
* Build order array from string
|
||||
*
|
||||
* key1,type1|key2,type2| ...
|
||||
*
|
||||
* d= sort key as string descending
|
||||
* D= sort key as float ascending
|
||||
* a= sort key as string ascending
|
||||
* A= sort key as floatval ascending
|
||||
*
|
||||
* @param string $order
|
||||
* @return array order-array
|
||||
*/
|
||||
/**
|
||||
* Simple debug output for objects and arrays
|
||||
* @param mixed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
if (!function_exists('v')) {
|
||||
function v($t)
|
||||
{
|
||||
echo '<br />';
|
||||
if (is_array($t) || is_object($t)){
|
||||
echo '<pre style="font-size:12px;">';
|
||||
print_r($t);
|
||||
echo '</pre>';
|
||||
}else
|
||||
echo $t;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Detect server protocol
|
||||
*
|
||||
* @return string 'https://' || 'http://'
|
||||
*/
|
||||
function getServerProtocol()
|
||||
{
|
||||
return (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? 'https://' : 'http://';
|
||||
}
|
||||
/**
|
||||
* Build order array from string 'col1,A|col2,d' for function arfosort
|
||||
*
|
||||
* @param string $order Orderstring
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function get_orderarray($order)
|
||||
{
|
||||
$order_arr = array();
|
||||
$orders = explode('|', $order);
|
||||
foreach ($orders as $o){
|
||||
$d = explode(',', $o);
|
||||
if (isset($d[0]) && isset($d[1]))
|
||||
$order_arr[] = array($d[0], $d[1]);
|
||||
}
|
||||
return $order_arr;
|
||||
}
|
||||
/**
|
||||
* Order multidimensial array
|
||||
*
|
||||
* @param array $a Array to sort
|
||||
* @param string $fl Order-string to define what keys should be sortet in what direction
|
||||
*
|
||||
* @return array Sorted array
|
||||
*/
|
||||
function arfsort($a, $fl)
|
||||
{
|
||||
$GLOBALS['__ARFSORT_LIST__'] = $fl;
|
||||
usort($a, 'arfsort_func');
|
||||
return $a;
|
||||
}
|
||||
/**
|
||||
* Sort a multidimenional array no matter in which depth the key is
|
||||
*
|
||||
* @param array $a Array to sort
|
||||
* @param string $b Sortstring containing keys and kind of sorting
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function arfsort_func($a, $b)
|
||||
{
|
||||
foreach ($GLOBALS['__ARFSORT_LIST__'] as $f){
|
||||
if (isset($b[$f[0]]) && isset($a[$f[0]])){
|
||||
switch ($f[1]){ // switch on ascending or descending value
|
||||
case 'd':
|
||||
$strc = strcmp(strtolower($b[$f[0]]), strtolower($a[$f[0]]));
|
||||
if ($strc != 0)
|
||||
return $strc;
|
||||
break;
|
||||
case 'a':
|
||||
$strc = strcmp(strtolower($a[$f[0]]), strtolower($b[$f[0]]));
|
||||
if ($strc != 0)
|
||||
return $strc;
|
||||
break;
|
||||
case 'D':
|
||||
$strc = (floatval($b[$f[0]]) < floatval($a[$f[0]])) ? -1 : 1;
|
||||
if ($b[$f[0]] != $a[$f[0]])
|
||||
return $strc;
|
||||
break;
|
||||
case 'A':
|
||||
$strc = (floatval($b[$f[0]]) > floatval($a[$f[0]])) ? -1 : 1;
|
||||
if ($b[$f[0]] != $a[$f[0]])
|
||||
return $strc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Read table information about nr of records and more for given database name.
|
||||
* Return array with advsanced information.
|
||||
*
|
||||
* @param string $db The database name to read info from
|
||||
* @param string $table If set, only information for this table is filled
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getTableInfo($db, $table = '')
|
||||
{
|
||||
global $dbo, $config;
|
||||
$tableInfos=array();
|
||||
$res = $dbo->selectDb($db);
|
||||
if ($res){
|
||||
$query = 'SHOW TABLE STATUS FROM `' . $db . '`';
|
||||
if ($table > '') {
|
||||
$query .= ' LIKE \'' . $table . '\'';
|
||||
}
|
||||
$res = $dbo->query($query, MsdDbFactory::ARRAY_ASSOC);
|
||||
// init index if not set
|
||||
if (!isset($tableInfos[$db]))
|
||||
$tableInfos[$db] = array();
|
||||
if (!isset($tableInfos[$db]['tables']))
|
||||
$tableInfos[$db]['tables'] = array();
|
||||
$tableInfos[$db]['table_count'] = sizeof($res);
|
||||
$tableInfos[$db]['records_total'] = 0;
|
||||
$tableInfos[$db]['datasize_total'] = 0;
|
||||
$tableInfos[$db]['size_total'] = 0;
|
||||
if ($tableInfos[$db]['table_count'] > 0){
|
||||
for ($i = 0, $max = $tableInfos[$db]['table_count']; $i < $max; $i++){
|
||||
$row = $res[$i];
|
||||
$n = $row['Name'];
|
||||
if (!isset($tableInfos[$db]['tables'][$n]))
|
||||
$tableInfos[$db]['tables'][$row['Name']] = array();
|
||||
if (isset($row['Type']))
|
||||
$row['Engine'] = $row['Type'];
|
||||
$tableInfos[$db]['tables'][$n]['name'] = $row['Name'];
|
||||
$tableInfos[$db]['tables'][$n]['engine'] = $row['Engine'];
|
||||
$tableInfos[$db]['tables'][$n]['dump_structure'] = 1;
|
||||
$tableInfos[$db]['tables'][$n]['dump_records'] = 1;
|
||||
// if we have a VIEW or a table of Type MEMORY -> don't save records
|
||||
if (strtoupper($row['Comment']) == 'VIEW' || (isset($row['Engine']) && in_array(strtoupper($row['Engine']), array(
|
||||
'MEMORY')))){
|
||||
$tableInfos[$db]['tables'][$n]['dump_records'] = 0;
|
||||
}
|
||||
if (!isset($row['Update_time']))
|
||||
$row['Update_time'] = '';
|
||||
$tableInfos[$db]['tables'][$n]['update_time'] = $row['Update_time'];
|
||||
$tableInfos[$db]['tables'][$n]['data_free'] = isset($row['Data_free']) ? $row['Data_free'] : 0;
|
||||
$tableInfos[$db]['tables'][$n]['collation'] = isset($row['Collation']) ? $row['Collation'] : '';
|
||||
$tableInfos[$db]['tables'][$n]['comment'] = isset($row['Comment']) ? $row['Comment'] : '';
|
||||
$tableInfos[$db]['tables'][$n]['auto_increment'] = isset($row['Auto_increment']) ? $row['Auto_increment'] : '';
|
||||
$tableInfos[$db]['tables'][$n]['records'] = (int) $row['Rows'];
|
||||
$tableInfos[$db]['tables'][$n]['data_length'] = (float) $row['Data_length'];
|
||||
$tableInfos[$db]['tables'][$n]['index_length'] = $row['Index_length'];
|
||||
$tableInfos[$db]['records_total'] += (int) $row['Rows'];
|
||||
$tableInfos[$db]['datasize_total'] += (float) $row['Data_length'];
|
||||
$tableInfos[$db]['size_total'] += (float) $row['Data_length'] + (float) $row['Index_length'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $tableInfos;
|
||||
}
|
||||
/**
|
||||
* Returns microtime of now as float value
|
||||
*
|
||||
* @return float microtime
|
||||
*/
|
||||
function getMicrotime()
|
||||
{
|
||||
list ($usec, $sec) = explode(' ', microtime());
|
||||
return ((float) $usec + (float) $sec);
|
||||
}
|
||||
/**
|
||||
* Detect free diskspace
|
||||
*
|
||||
* @return string Space in human readable Bytes or message if not available
|
||||
*/
|
||||
function getFreeDiskSpace()
|
||||
{
|
||||
global $lang;
|
||||
$dfs = @diskfreespace("../");
|
||||
return ($dfs) ? byteOutput($dfs) : $lang['L_NOTAVAIL'];
|
||||
}
|
||||
/**
|
||||
* Extract timestamp informations from a filename and return formatted string YYYY.MM.DD HH:MM
|
||||
*
|
||||
* @param string $s Filename as input 'dbname_2009_10_18_16_22_part1_sql-gz'
|
||||
*
|
||||
* @return string Formated timestamp YYYY.MM.DD HH:MM
|
||||
*/
|
||||
function getTimestampFromFilename($s)
|
||||
{
|
||||
$i = strpos(strtolower($s), 'part');
|
||||
if ($i > 0)
|
||||
$s = substr($s, 0, $i - 1);
|
||||
$i = strpos(strtolower($s), 'crondump');
|
||||
if ($i > 0)
|
||||
$s = substr($s, 0, $i - 1);
|
||||
$i = strpos(strtolower($s), '.sql');
|
||||
if ($i > 0)
|
||||
$s = substr($s, 0, $i);
|
||||
$sp = explode('_', $s);
|
||||
$anz = count($sp) - 1;
|
||||
if (strtolower($sp[$anz]) == 'perl')
|
||||
$anz--;
|
||||
if ($anz > 4){
|
||||
return $sp[$anz - 2] . '.' . $sp[$anz - 3] . '.' . $sp[$anz - 4] . ' ' . $sp[$anz - 1] . ':' . $sp[$anz];
|
||||
}else{
|
||||
//no MySQLDumper file
|
||||
return '';
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Writes errors or notices to the corresponding error log
|
||||
*
|
||||
* @param string $db Affected database
|
||||
* @param string $sql The executed query
|
||||
* @param string $error The error message to log
|
||||
* @param int $art The kind of error (0=error, 1=notice)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function writeToErrorLog($db = '', $sql = '', $error = '', $art = 1)
|
||||
{
|
||||
global $config, $lang, $log;
|
||||
$sql = str_replace("\r", '', $sql);
|
||||
$sql = str_replace("\n\n", '<br>', $sql);
|
||||
$sql = str_replace("\n", '<br>', $sql);
|
||||
$sql = trim($sql);
|
||||
$error = str_replace("\r", '', $error);
|
||||
if ($art == 0) {
|
||||
$errormsg = $lang['L_ERROR'] . ': ' . $error;
|
||||
} else {
|
||||
$errormsg = $lang['L_NOTICE'] . ': ' . $error;
|
||||
}
|
||||
// append query if set
|
||||
if ($sql > '') {
|
||||
$errormsg .= '<br>SQL: ' . $sql;
|
||||
}
|
||||
$time = date('d.m.Y H:i:s') . ' ';
|
||||
if ($art == 0) {
|
||||
$_SESSION['log']['errors'][] = $time.$errormsg;
|
||||
} else {
|
||||
$_SESSION['log']['notices'][] = $time.$errormsg;
|
||||
}
|
||||
$log->write(Log::ERROR, $errormsg);
|
||||
}
|
||||
/**
|
||||
* Checks if the directories work, config, backup and log are writable
|
||||
* Returns concatenated string with warnings or empty string if every directory is writable
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function checkDirectories()
|
||||
{
|
||||
global $config, $lang;
|
||||
$warn = '';
|
||||
if (!is_writable($config['paths']['work']))
|
||||
$warn .= sprintf($lang['L_WRONG_RIGHTS'], $config['paths']['work'], '0777');
|
||||
if (!is_writable($config['paths']['config']))
|
||||
$warn .= sprintf($lang['L_WRONG_RIGHTS'], $config['paths']['config'], '0777');
|
||||
if (!is_writable($config['paths']['backup']))
|
||||
$warn .= sprintf($lang['L_WRONG_RIGHTS'], $config['paths']['backup'], '0777');
|
||||
if (!is_writable($config['paths']['log']))
|
||||
$warn .= sprintf($lang['L_WRONG_RIGHTS'], $config['paths']['log'], '0777');
|
||||
if ($warn != '')
|
||||
$warn = '<span class="warnung"><strong>' . $warn . '</strong></span>';
|
||||
return $warn;
|
||||
}
|
||||
/**
|
||||
* Deletes every table or view in a database
|
||||
*
|
||||
* @param string $dbn Databasename
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function truncateDb($dbn)
|
||||
{
|
||||
global $dbo;
|
||||
$t_sql = array();
|
||||
$dbo->query('SET FOREIGN_KEY_CHECKS=0', MsdDbFactory::SIMPLE);
|
||||
$res = $dbo->query('SHOW TABLE STATUS FROM `' . $dbn . '`', MsdDbFactory::ARRAY_ASSOC);
|
||||
foreach ($res as $row){
|
||||
if (substr(strtoupper($row['Comment']), 0, 4) == 'VIEW'){
|
||||
$t_sql[] = 'DROP VIEW `' . $dbn . '``' . $row['Name'] . '`';
|
||||
}else{
|
||||
$t_sql[] = 'DROP TABLE `' . $dbn . '`.`' . $row['Name'] . '`';
|
||||
}
|
||||
}
|
||||
if (sizeof($t_sql) > 0){
|
||||
for ($i = 0; $i < count($t_sql); $i++){
|
||||
try{
|
||||
$dbo->query($t_sql[$i]);
|
||||
}catch (Excption $e){
|
||||
//TODO create clean error handling depending on context
|
||||
writeToErrorLog($e->getMessage());
|
||||
die($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
$dbo->query('SET FOREIGN_KEY_CHECKS=1', MsdDbFactory::SIMPLE);
|
||||
}
|
||||
/**
|
||||
* Delete old backups from folder work/backup according to configuration
|
||||
*
|
||||
* @return string Outputstring with messages about deleted files
|
||||
*/
|
||||
function doAutoDelete()
|
||||
{
|
||||
global $config, $lang, $out;
|
||||
$out = '';
|
||||
if ($config['auto_delete']['max_backup_files'] > 0){
|
||||
//Files einlesen
|
||||
$dh = opendir($config['paths']['backup']);
|
||||
$files = array();
|
||||
// Build assoc Array $db=>$timestamp=>$filenames
|
||||
if (!function_exists('ReadStatusline'))
|
||||
include ('./inc/functions/functions_files.php');
|
||||
while (false !== ($filename = readdir($dh))){
|
||||
if ($filename != '.' && $filename != '..' && !is_dir($config['paths']['backup'] . $filename)){
|
||||
$statusline = readStatusline($filename);
|
||||
if ($statusline['dbname'] != 'unknown'){
|
||||
$dbName = $statusline['dbname'];
|
||||
$datum = substr($filename, strlen($dbName) + 1);
|
||||
$timestamp = substr($datum, 0, 16);
|
||||
if (!isset($files[$dbName]))
|
||||
$files[$dbName] = array();
|
||||
if (!isset($files[$dbName][$timestamp]))
|
||||
$files[$dbName][$timestamp] = array();
|
||||
$files[$dbName][$timestamp][] = $filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
$out = ''; // stores output messages
|
||||
// Backups per DB and Timestamp
|
||||
foreach ($files as $db => $val){
|
||||
if (sizeof($val) > $config['auto_delete']['max_backup_files']){
|
||||
$db_files = $val;
|
||||
krsort($db_files, SORT_STRING);
|
||||
//now latest backupfiles are on top -> delete all files with greater index
|
||||
$i = 0;
|
||||
foreach ($db_files as $timestamp => $filenames){
|
||||
if ($i >= $config['auto_delete']['max_backup_files']){
|
||||
// Backup too old -> delete files
|
||||
foreach ($filenames as $f){
|
||||
if ($out == '')
|
||||
$out .= $lang['L_FM_AUTODEL1'] . '<br />';
|
||||
if (@unlink('./' . $config['paths']['backup'] . $f)){
|
||||
$out .= '<span class="success">' . sprintf($lang['L_DELETE_FILE_SUCCESS'], $f) . '</span><br />';
|
||||
}else{
|
||||
$out .= $lang['L_ERROR'] . ': <p class="error">' . sprintf($lang['L_DELETE_FILE_ERROR'], $f) . '</p><br />';
|
||||
}
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
/**
|
||||
* Analyzes the first line of a MSD-Backup. Expects it as string parameter.
|
||||
*
|
||||
* @param string $line The statusline from the backup to analyze
|
||||
*
|
||||
* @return array Extracted information as array
|
||||
*/
|
||||
function readStatusline($filename)
|
||||
{
|
||||
global $config;
|
||||
/*AUFBAU der Statuszeile:
|
||||
-- Status:nr of tables:records:Multipart:Databasename:script:scriptversion:Comment:
|
||||
MySQL-Version:flags (unused):SQLCommandBeforeBackup:SQLCommandAfterBackup:Charset:EXTINFO
|
||||
*/
|
||||
$gz = substr($filename, -3) == '.gz' ? true : false;
|
||||
$fh = $gz ? gzopen($config['paths']['backup'] . $filename, 'r') : fopen($config['paths']['backup'] . $filename, 'r');
|
||||
if (!$fh){
|
||||
v(debug_backtrace());
|
||||
die();
|
||||
}
|
||||
$line = $gz ? gzgets($fh) : fgets($fh);
|
||||
$gz ? gzclose($fh) : fclose($fh);
|
||||
$statusline = array();
|
||||
$line = removeBom($line);
|
||||
if ((substr($line, 0, 8) != "# Status" && substr($line, 0, 9) != "-- Status") || substr($line, 0, 10) == '-- StatusC'){
|
||||
//Fremdfile
|
||||
$statusline['tables'] = -1;
|
||||
$statusline['records'] = -1;
|
||||
$statusline['part'] = 'MP_0';
|
||||
$statusline['dbname'] = 'unknown';
|
||||
$statusline['script'] = '';
|
||||
$statusline['scriptversion'] = '';
|
||||
$statusline['comment'] = '';
|
||||
$statusline['mysqlversion'] = 'unknown';
|
||||
$statusline['flags'] = '2222222';
|
||||
$statusline['sqlbefore'] = '';
|
||||
$statusline['sqlafter'] = '';
|
||||
$statusline['charset'] = '?';
|
||||
}else{
|
||||
// MySQLDumper-File - Informationen extrahieren
|
||||
$s = explode(':', $line);
|
||||
if (count($s) < 12){
|
||||
//fehlenden Elemente auffüllen
|
||||
$c = count($s);
|
||||
array_pop($s);
|
||||
for ($i = $c - 1; $i < 12; $i++){
|
||||
$s[] = '';
|
||||
}
|
||||
}
|
||||
$statusline['tables'] = $s[1];
|
||||
$statusline['records'] = $s[2];
|
||||
$statusline['part'] = ($s[3] == '' || $s[3] == 'MP_0') ? 'MP_0' : $s[3];
|
||||
$statusline['dbname'] = $s[4];
|
||||
$statusline['script'] = $s[5];
|
||||
$statusline['scriptversion'] = $s[6];
|
||||
$statusline['comment'] = $s[7];
|
||||
$statusline['mysqlversion'] = $s[8];
|
||||
if ((isset($s[12])) && trim($s[12]) != 'EXTINFO'){
|
||||
$statusline['charset'] = $s[12];
|
||||
}else{
|
||||
$statusline['charset'] = '?';
|
||||
}
|
||||
}
|
||||
return $statusline;
|
||||
}
|
||||
/**
|
||||
* Reads Head-Information about tables from MSD-Backup and returns it as array
|
||||
*
|
||||
* @param string $filename Filename of MSD-Backup to analyze
|
||||
*
|
||||
* @return array Detailed information about tables n MSD-Backup
|
||||
*/
|
||||
function getTableHeaderInfoFromBackup($filename)
|
||||
{
|
||||
global $config;
|
||||
// Get Tableinfo from file header
|
||||
$tabledata = array();
|
||||
$i = 0;
|
||||
$gz = substr($filename, -3) == '.gz' ? true : false;
|
||||
$fh = $gz ? gzopen($config['paths']['backup'] . $filename, 'r') : fopen($config['paths']['backup'] . $filename, 'r');
|
||||
$eof = false;
|
||||
WHILE (!$eof){
|
||||
$line = $gz ? gzgets($fh, 40960) : fgets($fh, 40960);
|
||||
$line = trim($line);
|
||||
if (substr($line, 0, 9) == '-- TABLE|'){
|
||||
$d = explode('|', $line);
|
||||
$tabledata[$i]['name'] = $d[1];
|
||||
$tabledata[$i]['records'] = $d[2];
|
||||
$tabledata[$i]['size'] = $d[3];
|
||||
$tabledata[$i]['update'] = $d[4];
|
||||
$tabledata[$i]['engine'] = isset($d[5]) ? $d[5] : '';
|
||||
$i++;
|
||||
}elseif (substr($line, 0, 6) == '-- EOF')
|
||||
$eof = true; // End of Table-Info - >done
|
||||
elseif (substr(strtolower($line), 0, 6) == 'create')
|
||||
$eof = true; // we have found the first CREATE-Query -> done
|
||||
}
|
||||
$gz ? gzclose($fh) : fclose($fh);
|
||||
return $tabledata;
|
||||
}
|
||||
/**
|
||||
* Calculate next Multipart-Filename
|
||||
*
|
||||
* @param string $filename The filename to calculate the next name from
|
||||
*
|
||||
* @return string Filename of next Multipart-File
|
||||
*/
|
||||
function getNextPart($filename)
|
||||
{
|
||||
$nf = explode('_', $filename);
|
||||
$i = array_search('part', $nf) + 1;
|
||||
$part = substr($nf[$i], 0, strpos($nf[$i], '.'));
|
||||
$ext = substr($nf[$i], strlen($part));
|
||||
$nf[$i] = ++$part . $ext;
|
||||
$filename = implode('_', $nf);
|
||||
return $filename;
|
||||
}
|
||||
/**
|
||||
* Formats seconds to human readable output
|
||||
*
|
||||
* @param integer $time Time in seconds
|
||||
*
|
||||
* @return string Time as human readable formatted string
|
||||
*/
|
||||
function getTimeFormat($time)
|
||||
{
|
||||
global $lang;
|
||||
$d = floor($time / 86400);
|
||||
$h = floor(($time - $d * 86400) / 3600);
|
||||
$m = floor(($time - $d * 86400 - $h * 3600) / 60);
|
||||
$s = $time - $d * 86400 - $h * 3600 - $m * 60;
|
||||
$ret = sprintf('%02d', $s) . ' ' . ($s == 1 ? $lang['L_SECOND'] : $lang['L_SECONDS']);
|
||||
if ($m > 0){
|
||||
$ret = $m . ' ' . ($m == 1 ? $lang['L_MINUTE'] : $lang['L_MINUTES']) . ' ' . $ret;
|
||||
}
|
||||
if ($h > 0){
|
||||
$ret = $h . ' ' . ($h == 1 ? $lang['L_HOUR'] : $lang['L_HOURS']) . ' ' . $ret;
|
||||
}
|
||||
if ($d > 0){
|
||||
$ret = $d . ' ' . ($d == 1 ? $lang['L_DAY'] : $lang['L_DAYS']) . ' ' . $ret;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
/**
|
||||
* Tests a ftp-connection and returns messages about uccess or failure
|
||||
*
|
||||
* @param integer $i The index of the connection profile to test
|
||||
*
|
||||
* @return array Array with messages
|
||||
*/
|
||||
function testFTP($i)
|
||||
{
|
||||
global $lang, $config;
|
||||
if (!isset($config['ftp'][$i]['timeout']))
|
||||
$config['ftp'][$i]['timeout'][$i] = 30;
|
||||
$ret = array();
|
||||
if ($config['ftp'][$i]['port'] == '' || $config['ftp'][$i]['port'][$i] == 0)
|
||||
$config['ftp'][$i]['port'] = 21;
|
||||
$pass = -1;
|
||||
if (!extension_loaded("ftp")){
|
||||
$ret[] = '<span class="error">' . $lang['L_NOFTPPOSSIBLE'] . '</span>';
|
||||
}else
|
||||
$pass = 0;
|
||||
if ($pass == 0){
|
||||
if ($config['ftp'][$i]['server'] == '' || $config['ftp'][$i]['user'] == ''){
|
||||
$ret[] = '<span class="error">' . $lang['L_WRONGCONNECTIONPARS'] . '</span>';
|
||||
}else
|
||||
$pass = 1;
|
||||
}
|
||||
if ($pass == 1){
|
||||
if ($config['ftp'][$i]['ssl'] == 0)
|
||||
$conn_id = @ftp_connect($config['ftp'][$i]['server'], $config['ftp'][$i]['port'], $config['ftp'][$i]['timeout']);
|
||||
else
|
||||
$conn_id = @ftp_ssl_connect($config['ftp'][$i]['server'], $config['ftp'][$i]['port'], $config['ftp'][$i]['timeout']);
|
||||
if (is_resource($conn_id)){
|
||||
$ret[] = sprintf($lang['L_FTP_CONNECTION_SUCCESS'], $config['ftp'][$i]['server'], $config['ftp'][$i]['port']);
|
||||
}else
|
||||
$ret[] = sprintf($lang['L_FTP_CONNECTION_ERROR'], $config['ftp'][$i]['server'], $config['ftp'][$i]['port']);
|
||||
if ($conn_id){
|
||||
$login_result = @ftp_login($conn_id, $config['ftp'][$i]['user'], $config['ftp'][$i]['pass']);
|
||||
if ($login_result)
|
||||
$ret[] = sprintf($lang['L_FTP_LOGIN_SUCCESS'], $config['ftp'][$i]['user']);
|
||||
else
|
||||
$ret[] = sprintf($lang['L_FTP_LOGIN_ERROR'], $config['ftp'][$i]['user']);
|
||||
}
|
||||
if ($conn_id && $login_result){
|
||||
$pass = 2;
|
||||
if ($config['ftp'][$i]['mode'] == 1){
|
||||
if (ftp_pasv($conn_id, true))
|
||||
$ret[] = $lang['L_FTP_PASV_SUCCESS'];
|
||||
else
|
||||
$ret[] = $lang['L_FTP_PASV_ERROR'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($pass == 2){
|
||||
$dirc = @ftp_chdir($conn_id, $config['ftp'][$i]['dir']);
|
||||
if (!$dirc){
|
||||
$ret[] = $lang['L_CHANGEDIR'] . ' \'' . $config['ftp'][$i]['dir'] . '\' -> <span class="error">' . $lang['L_CHANGEDIRERROR'] . '</span>';
|
||||
}else{
|
||||
$pass = 3;
|
||||
$ret[] = $lang['L_CHANGEDIR'] . ' \'' . $config['ftp'][$i]['dir'] . '\' -> <span class="success">' . $lang['L_OK'] . '</span>';
|
||||
}
|
||||
@ftp_close($conn_id);
|
||||
}
|
||||
if ($pass == 3)
|
||||
$ret[] = '<span class="success"><strong>' . $lang['L_FTP_OK'] . '</strong></span>';
|
||||
return implode('<br />', $ret);
|
||||
}
|
||||
/**
|
||||
* Returns list of configuration profiles as HTML-Optionlist
|
||||
*
|
||||
* @param string $selected_config The actual configuration to pre-select in option list
|
||||
*
|
||||
* @return string HTML-option-string
|
||||
*/
|
||||
function getConfigFilelist($selected_config)
|
||||
{
|
||||
$configs = getConfigFilenames();
|
||||
$options = Html::getOptionlist($configs, $selected_config);
|
||||
return $options;
|
||||
}
|
||||
/**
|
||||
* Returns list of installed themes as HTML-Optionlist
|
||||
*
|
||||
* @return string HTML-option-string
|
||||
*/
|
||||
function getThemes()
|
||||
{
|
||||
global $config;
|
||||
$themes = array();
|
||||
$dh = opendir($config['paths']['root'] . "css/");
|
||||
while (false !== ($filename = readdir($dh))){
|
||||
if ($filename != '.' && $filename != '..' && is_dir($config['paths']['root'] . 'css/' . $filename) && substr($filename, 0, 1) != '.' && substr($filename, 0, 1) != '_'){
|
||||
$themes[$filename] = $filename;
|
||||
}
|
||||
}
|
||||
@ksort($themes);
|
||||
$options = Html::getOptionlist($themes, $config['theme']);
|
||||
return $options;
|
||||
}
|
||||
/**
|
||||
* Detects all language-directories and builds HTML-Optionlist
|
||||
*
|
||||
* @return string HTML-option-string
|
||||
*/
|
||||
function getLanguageCombo()
|
||||
{
|
||||
global $config, $lang;
|
||||
$default = $config['language'];
|
||||
$dh = opendir('./language/');
|
||||
$r = "";
|
||||
$lang_files = array();
|
||||
while (false !== ($filename = readdir($dh))){
|
||||
if ($filename != '.' && $filename != '.svn' && $filename != '..' && $filename != 'flags' && is_dir('./language/' . $filename)){
|
||||
if (isset($lang[$filename]))
|
||||
$lang_files[$lang[$filename]] = $filename;
|
||||
}
|
||||
}
|
||||
@ksort($lang_files);
|
||||
foreach ($lang_files as $filename){
|
||||
$style = 'background:url(language/flags/width25/' . $filename . '.gif) 4px;background-repeat:no-repeat;padding:2px 6px 2px 36px !important;';
|
||||
$r .= '<option value="' . $filename . '" style="' . $style . '"';
|
||||
$r .= Html::getSelected($filename, $default);
|
||||
$r .= '>' . $lang[$filename] . '</option>' . "\n";
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
/**
|
||||
* Detects language subdirs and adds them to the global definition of $lang
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function getLanguageArray()
|
||||
{
|
||||
global $lang;
|
||||
$dh = opendir('./language/');
|
||||
if (isset($lang['languages']))
|
||||
unset($lang['languages']);
|
||||
$lang['languages'] = array();
|
||||
while (false !== ($filename = readdir($dh))){
|
||||
if ($filename != '.' && $filename != '.svn' && $filename != ".." && $filename != "flags" && is_dir('./language/' . $filename)){
|
||||
$lang['languages'][] = $filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets database and tablenames into backticks
|
||||
*
|
||||
* @param string $s Querystring
|
||||
*
|
||||
* @return string Querystring with backticks
|
||||
*/
|
||||
function setBackticks($s)
|
||||
{
|
||||
$klammerstart = $lastklammerstart = $end = 0;
|
||||
$inner_s_start = strpos($s, '(');
|
||||
$inner_s_end = strrpos($s, ')');
|
||||
$inner_s = substr($s, $inner_s_start + 1, $inner_s_end - (1 + $inner_s_start));
|
||||
$pieces = explode(',', $inner_s);
|
||||
for ($i = 0; $i < count($pieces); $i++){
|
||||
$r = trim($pieces[$i]);
|
||||
$klammerstart += substr_count($r, "(") - substr_count($r, ")");
|
||||
if ($i == count($pieces) - 1)
|
||||
$klammerstart += 1;
|
||||
if (substr(strtoupper($r), 0, 4) == "KEY " || substr(strtoupper($r), 0, 7) == "UNIQUE " || substr(strtoupper($r), 0, 12) == "PRIMARY KEY " || substr(strtoupper($r), 0, 13) == "FULLTEXT KEY "){
|
||||
//nur ein Key
|
||||
$end = 1;
|
||||
}else{
|
||||
if (substr($r, 0, 1) != '`' && substr($r, 0, 1) != '\'' && $klammerstart == 0 && $end == 0 && $lastklammerstart == 0){
|
||||
$pos = strpos($r, ' ');
|
||||
$r = '`' . substr($r, 0, $pos) . '`' . substr($r, $pos);
|
||||
}
|
||||
}
|
||||
$pieces[$i] = $r;
|
||||
$lastklammerstart = $klammerstart;
|
||||
}
|
||||
$back = substr($s, 0, $inner_s_start + 1) . implode(',', $pieces) . ');';
|
||||
return $back;
|
||||
}
|
||||
//
|
||||
/**
|
||||
* Returns the index of the selected value in an array
|
||||
*
|
||||
* @param array $arr The Array to get the index from
|
||||
* @param string $selected The value to find the index for
|
||||
*
|
||||
* @return mixed Found Index or false
|
||||
*/
|
||||
function getIndexFromValue($arr, $selected)
|
||||
{
|
||||
$ret = false; // return false if not found
|
||||
foreach ($arr as $key => $val){
|
||||
if (strtolower(substr($val, 0, strlen($selected))) == strtolower($selected)){
|
||||
$ret = $key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
/**
|
||||
* Checks if config is readable and loads it
|
||||
* Expects only the name of the configuration (not the path or complete filename)
|
||||
*
|
||||
* Returns true on success or false on failure
|
||||
*
|
||||
* @param string $file Name of configuration without extension
|
||||
* @param boolean $redirect_to_install Decide if user should be redirected to installation if config doesn't exist
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function getConfig($file = '', $redirect_to_install = true)
|
||||
{
|
||||
global $config, $databases;
|
||||
if (!isset($_SESSION['config_file']))
|
||||
$_SESSION['config_file'] = 'mysqldumper';
|
||||
if ($file == '')
|
||||
$file = $_SESSION['config_file'];
|
||||
$ret = false;
|
||||
// protect from including external files
|
||||
$search = array(':', 'http', 'ftp', ' ', '/', '\\');
|
||||
$replace = array('', '', '', '', '', '');
|
||||
$file = str_replace($search, $replace, $file);
|
||||
clearstatcache();
|
||||
if ($redirect_to_install && !is_readable('./' . $config['paths']['config'] . $file . '.php') && $file == 'mysqldumper'){
|
||||
header('Location: install.php');
|
||||
exit();
|
||||
}
|
||||
if (!is_readable('./' . $config['paths']['config'] . $file . '.php'))
|
||||
$file = 'mysqldumper';
|
||||
if (is_readable('./' . $config['paths']['config'] . $file . '.php')){
|
||||
$databases = array(); // reset databaselist - will be read from config file
|
||||
$c = implode('', file('./' . $config['paths']['config'] . $file . '.php'));
|
||||
$c = str_replace('<?php', '', $c);
|
||||
eval($c);
|
||||
$config['config_file'] = $file;
|
||||
$_SESSION['config_file'] = $file;
|
||||
$_SESSION['config'] = $config; // $config is defined in read file
|
||||
$_SESSION['databases'] = $databases; // $databases is defined in read file
|
||||
$config['files']['iconpath'] = './css/' . $config['theme'] . '/icons/';
|
||||
$ret = true;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
/**
|
||||
* Get all names of configuration files located in /work/config directory
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getConfigFilenames()
|
||||
{
|
||||
global $config;
|
||||
$configs = array();
|
||||
$dh = opendir('./' . $config['paths']['config']);
|
||||
while (false !== ($filename = readdir($dh))){
|
||||
if (substr($filename, -4) == '.php' && substr($filename, -9) != '.conf.php' && $filename != 'dbs_manual.php'){
|
||||
$index = substr($filename, 0, -4);
|
||||
$configs[$index] = $index;
|
||||
}
|
||||
}
|
||||
@ksort($configs);
|
||||
return $configs;
|
||||
}
|
||||
/**
|
||||
* Loads data from an external source via HTTP-socket
|
||||
*
|
||||
* Loads data from an external source $url given as URL
|
||||
* and returns the content as a binary string or false on connection error
|
||||
*
|
||||
* @param string $url URL to fetch
|
||||
*
|
||||
* @return string file data or false
|
||||
*/
|
||||
function getFileDataFromURL($url)
|
||||
{
|
||||
$url_parsed = parse_url($url);
|
||||
$data = false;
|
||||
$host = $url_parsed['host'];
|
||||
$port = isset($url_parsed['port']) ? intval($url_parsed['port']) : 80;
|
||||
if ($port == 0)
|
||||
$port = 80;
|
||||
$path = $url_parsed['path'];
|
||||
if (!isset($url_parsed['scheme']))
|
||||
$url_parsed['scheme'] = 'http';
|
||||
if (!isset($url_parsed['path']))
|
||||
$url_parsed['path'] = '/';
|
||||
if (isset($url_parsed['query']) && $url_parsed['query'] != '')
|
||||
$path .= '?' . $url_parsed['query'];
|
||||
$fp = @fsockopen($host, $port, $errno, $errstr, 10);
|
||||
if ($fp){
|
||||
$out = "GET $path HTTP/1.0\r\n";
|
||||
$out .= "Host: $host\r\n";
|
||||
$out .= 'Referer: ' . $url_parsed['scheme'] . '://' . $_SERVER['SERVER_NAME'] . $path . "\r\n";
|
||||
$out .= 'User-Agent: MySQLDumper ' . MSD_VERSION . "\r\n";
|
||||
$out .= "Connection: close\r\n\r\n";
|
||||
@fwrite($fp, $out);
|
||||
$body = false;
|
||||
$data = '';
|
||||
while (!feof($fp)){
|
||||
$s = fgets($fp, 1024);
|
||||
if ($body)
|
||||
$data .= $s;
|
||||
if ($s == "\r\n"){
|
||||
$body = true;
|
||||
}
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
/**
|
||||
* Recursevely detects differences of multidimensional arrays
|
||||
* and returns a new array containing all differences. Indexes that exists in both arrays are skipped.
|
||||
* (e.g. used to detect differences between the complete SESSION['log'] and the built log of a page-call
|
||||
* in ajax-functions to only return the last changes to the client)
|
||||
*
|
||||
* @param array $array1 Array1
|
||||
* @param array $array2 Array2
|
||||
*
|
||||
* @return array Array with differences
|
||||
*/
|
||||
function getArrayDiffAssocRecursive($array1, $array2)
|
||||
{
|
||||
foreach ($array1 as $key => $value){
|
||||
if (is_array($value)){
|
||||
if (!isset($array2[$key]))
|
||||
$difference[$key] = $value;
|
||||
elseif (!is_array($array2[$key]))
|
||||
$difference[$key] = $value;
|
||||
else{
|
||||
$new_diff = getArrayDiffAssocRecursive($value, $array2[$key]);
|
||||
if ($new_diff != FALSE)
|
||||
$difference[$key] = $new_diff;
|
||||
}
|
||||
}elseif (!isset($array2[$key]) || $array2[$key] != $value)
|
||||
$difference[$key] = $value;
|
||||
}
|
||||
return !isset($difference) ? 0 : $difference;
|
||||
}
|
||||
/**
|
||||
* Gets value in associative array by indexnr
|
||||
*
|
||||
* @param array $array
|
||||
* @param mixed $index Index
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getValueFromIndex($array, $index)
|
||||
{
|
||||
$array_keys = array_keys($array);
|
||||
if (isset($array_keys[$index]))
|
||||
return $array_keys[$index];
|
||||
else
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Gets the next key in an associative array and returns it.
|
||||
* If it was the last key return false
|
||||
*
|
||||
* @param array $array Array
|
||||
* @param string $key current Index
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function getNextKey($array, $key)
|
||||
{
|
||||
$array_keys = array_keys($array);
|
||||
$array_flip = array_flip($array_keys);
|
||||
$index = $array_flip[$key];
|
||||
$index++;
|
||||
if ($index < sizeof($array_keys))
|
||||
return $array_keys[$index];
|
||||
else
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Detect Byte Order Mark (BOM) and remove it if found
|
||||
*
|
||||
* @param string $str String
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function removeBom($str)
|
||||
{
|
||||
$bom = pack('CCC', 0xef, 0xbb, 0xbf);
|
||||
if (0 == strncmp($str, $bom, 3)){
|
||||
$str = substr($str, 3);
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
426
inc/functions/functions_restore.php
Normale Datei
426
inc/functions/functions_restore.php
Normale Datei
|
|
@ -0,0 +1,426 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of MySQLDumper released under the GNU/GPL 2 license
|
||||
* http://www.mysqldumper.net
|
||||
*
|
||||
* @package MySQLDumper
|
||||
* @version SVN: $rev: 1207 $
|
||||
* @author $Author$
|
||||
* @lastmodified $Date$
|
||||
*/
|
||||
if (!defined('MSD_VERSION')) die('No direct access.');
|
||||
/**
|
||||
* Reads next lines from file and extracts a complete SQL-Command
|
||||
*
|
||||
* @return string $sql_command The complete Query
|
||||
*/
|
||||
function getQueryFromFile($showErrors = true)
|
||||
{
|
||||
global $restore, $config, $databases, $lang, $dbo, $log;
|
||||
|
||||
//Init
|
||||
$complete_sql = '';
|
||||
$sqlparser_status = 0;
|
||||
$query_found = false;
|
||||
|
||||
//Parse
|
||||
WHILE (!$query_found && !$restore['fileEOF'] && !$restore['EOB'])
|
||||
{
|
||||
//get next line from file
|
||||
$zeile = ($restore['compressed']) ? gzgets($restore['filehandle']) : fgets($restore['filehandle']);
|
||||
// if we are at the beginning of a file look for BOM and remove it
|
||||
if ($restore['offset'] == 0) $zeile = removeBom($zeile);
|
||||
|
||||
// what kind of command did we read from the file?
|
||||
if ($sqlparser_status == 0)
|
||||
{
|
||||
|
||||
// build comparing line in uppercase
|
||||
$zeile2 = strtoupper(trim(substr($zeile, 0, 9)));
|
||||
// pre-build compare strings - so we need the CPU power only once :)
|
||||
$sub9 = substr($zeile2, 0, 9);
|
||||
$sub7 = substr($sub9, 0, 7);
|
||||
$sub6 = substr($sub7, 0, 6);
|
||||
$sub4 = substr($sub6, 0, 4);
|
||||
$sub3 = substr($sub4, 0, 3);
|
||||
$sub2 = substr($sub3, 0, 2);
|
||||
$sub1 = substr($sub2, 0, 1);
|
||||
|
||||
if ($sub7 == 'INSERT ')
|
||||
{
|
||||
$sqlparser_status = 3;
|
||||
$restore['actual_table'] = getTablename($zeile, $restore['actual_table']);
|
||||
}
|
||||
elseif ($sub7 == 'REPLACE')
|
||||
{
|
||||
$sqlparser_status = 8;
|
||||
$restore['actual_table'] = getTablename($zeile, $restore['actual_table']);
|
||||
}
|
||||
|
||||
// find statements ending with a colon
|
||||
elseif ($sub7 == 'LOCK TA') $sqlparser_status = 4;
|
||||
elseif ($sub6 == 'COMMIT') $sqlparser_status = 7;
|
||||
elseif (substr($sub6, 0, 5) == 'BEGIN') $sqlparser_status = 7;
|
||||
elseif ($sub9 == 'UNLOCK TA') $sqlparser_status = 4;
|
||||
elseif ($sub3 == 'SET') $sqlparser_status = 4;
|
||||
elseif ($sub6 == 'START ') $sqlparser_status = 4;
|
||||
elseif ($sub3 == '/*!') $sqlparser_status = 5; //MySQL-Condition oder Comment
|
||||
elseif ($sub9 == 'ALTER TAB') $sqlparser_status = 4; // Alter Table
|
||||
elseif ($sub9 == 'CREATE TA') $sqlparser_status = 2; //Create Table
|
||||
elseif ($sub9 == 'CREATE AL') $sqlparser_status = 2; //Create View
|
||||
elseif ($sub9 == 'CREATE IN') $sqlparser_status = 4; //Indexaction
|
||||
elseif ($sub7 == 'UPDATE ') $sqlparser_status = 4;
|
||||
elseif ($sub7 == 'SELECT ') $sqlparser_status = 4;
|
||||
|
||||
// divide comment from condition
|
||||
elseif (($sqlparser_status != 5) && ($sub2 == '/*')) $sqlparser_status = 6;
|
||||
|
||||
// delete actions
|
||||
elseif ($sub9 == 'DROP TABL') $sqlparser_status = 1;
|
||||
elseif ($sub9 == 'DROP VIEW') $sqlparser_status = 1;
|
||||
elseif ($sub7 == 'DELETE ') $sqlparser_status = 1;
|
||||
|
||||
// commands that mustn't be executed
|
||||
elseif ($sub9 == 'CREATE DA ') $sqlparser_status = 7;
|
||||
elseif ($sub9 == 'DROP DATA ') $sqlparser_status = 7;
|
||||
elseif ($sub3 == 'USE') $sqlparser_status = 7;
|
||||
|
||||
// end of a MySQLDumper-Dump reached?
|
||||
elseif ($sub6 == '-- EOB' || $sub4 == '# EO')
|
||||
{
|
||||
$restore['EOB'] = true;
|
||||
$restore['fileEOF'] = true;
|
||||
$zeile = '';
|
||||
$zeile2 = '';
|
||||
$query_found = true;
|
||||
}
|
||||
|
||||
// Comment?
|
||||
elseif ($sub2 == '--' || $sub1 == '#')
|
||||
{
|
||||
$zeile = '';
|
||||
$zeile2 = '';
|
||||
$sqlparser_status = 0;
|
||||
}
|
||||
|
||||
// continue extended Insert?
|
||||
if ($restore['extended_insert_flag'] == 1) $sqlparser_status = 3;
|
||||
if (($sqlparser_status == 0) && (trim($complete_sql) > '') && ($restore['extended_insert_flag'] == -1))
|
||||
{
|
||||
if ($showErrors)
|
||||
{
|
||||
// unknown command -> output debug information
|
||||
v($restore);
|
||||
echo "<br />Sql: " . htmlspecialchars($complete_sql);
|
||||
die('<br />' . $lang['L_UNKNOWN_SQLCOMMAND'] . ': ' . $zeile . '<br /><br />' . $complete_sql);
|
||||
}
|
||||
else
|
||||
return array(
|
||||
false,
|
||||
$complete_sql);
|
||||
}
|
||||
}
|
||||
|
||||
$last_char = substr(rtrim($zeile), -1);
|
||||
// retain new lines - otherwise keywords are glued together
|
||||
// e.g. 'null' and on next line 'check' would necome 'nullcheck'
|
||||
$complete_sql .= $zeile . "\n";
|
||||
|
||||
if ($sqlparser_status == 3 || $sqlparser_status == 8)
|
||||
{
|
||||
//INSERT or REPLACE
|
||||
if (isCompleteQuery($complete_sql))
|
||||
{
|
||||
$query_found = true;
|
||||
$complete_sql = trim($complete_sql);
|
||||
if (substr($complete_sql, -2) == '*/')
|
||||
{
|
||||
$complete_sql = deleteInlineComments($complete_sql);
|
||||
}
|
||||
|
||||
// end of extended insert found?
|
||||
if (substr($complete_sql, -2) == ');')
|
||||
{
|
||||
$restore['extended_insert_flag'] = -1;
|
||||
}
|
||||
|
||||
// if there is a ")," at end of line -> extended Insert-Modus -> set flag
|
||||
else
|
||||
if (substr($complete_sql, -2) == '),')
|
||||
{
|
||||
// letztes Komme gegen Semikolon tauschen
|
||||
$complete_sql = substr($complete_sql, 0, -1);
|
||||
$restore['extended_inserts'] = 1;
|
||||
$restore['extended_insert_flag'] = 1;
|
||||
}
|
||||
|
||||
$compare = substr(strtoupper($complete_sql), 0, 7);
|
||||
if (($compare != 'INSERT ' && $compare != 'REPLACE'))
|
||||
{
|
||||
// we do have extended inserts here -> prepend insert syntax
|
||||
// if we don't have it because of a page refresh -> get it
|
||||
if (!isset($restore['insert_syntax'])) {
|
||||
$restore['insert_syntax'] = Sql::getInsertSyntax(
|
||||
$dbo, $restore['actual_table']
|
||||
);
|
||||
}
|
||||
$complete_sql = $restore['insert_syntax'] . ' VALUES ' . $complete_sql;
|
||||
}
|
||||
else
|
||||
{
|
||||
// remember the INSERT syntax
|
||||
$ipos = strpos(strtoupper($complete_sql), ' VALUES');
|
||||
if (!$ipos === false) $restore['insert_syntax'] = substr($complete_sql, 0, $ipos);
|
||||
else
|
||||
{
|
||||
if ($sqlparser_status == 3) $restore['insert_syntax'] = 'INSERT INTO `' . $restore['actual_table'] . '`';
|
||||
else $restore['insert_syntax'] = 'REPLACE INTO `' . $restore['actual_table'] . '`';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
if ($sqlparser_status == 1)
|
||||
{
|
||||
// delete action
|
||||
if ($last_char == ';') $query_found = true;
|
||||
$restore['actual_table'] = getTablename($complete_sql);
|
||||
}
|
||||
|
||||
else
|
||||
if ($sqlparser_status == 2)
|
||||
{
|
||||
// Create-command is finished if there is a colon at the end of line
|
||||
if ($last_char == ';')
|
||||
{
|
||||
$restore['speed'] = $config['minspeed'];
|
||||
// Restore this table?
|
||||
$do_it = true;
|
||||
if (is_array($restore['tables_to_restore']))
|
||||
{
|
||||
$do_it = false;
|
||||
if (in_array($restore['actual_table'], $restore['tables_to_restore']))
|
||||
{
|
||||
$do_it = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we do a partial restore with selected tables and we already inserted all
|
||||
// of them and we now have a table we don't need to restore
|
||||
// -> we did all we need to do! Check and finish the process in that case
|
||||
// (we don't need to further walk through the file if all needed tables are done)
|
||||
if ($restore['table_ready'] == $restore['tables_total'])
|
||||
{
|
||||
$sqlparser_status = 0;
|
||||
$restore['EOB'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$tablename = getTablename($complete_sql);
|
||||
if ($do_it)
|
||||
{
|
||||
$complete_sql = getCorrectedCreateCommand($complete_sql);
|
||||
$restore['table_ready']++;
|
||||
}
|
||||
else
|
||||
$complete_sql = '';
|
||||
$restore['actual_table'] = $tablename;
|
||||
$query_found = true;
|
||||
$sqlparser_status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Index
|
||||
else
|
||||
if ($sqlparser_status == 4)
|
||||
{
|
||||
if ($last_char == ';')
|
||||
{
|
||||
$restore['speed'] = $config['minspeed'];
|
||||
$complete_sql = deleteInlineComments($complete_sql);
|
||||
$query_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Comment or condition
|
||||
else
|
||||
if ($sqlparser_status == 5)
|
||||
{
|
||||
$t = strrpos($zeile, '*/;');
|
||||
if (!$t === false)
|
||||
{
|
||||
$restore['speed'] = $config['minspeed'];
|
||||
$query_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// multiline-comment
|
||||
else
|
||||
if ($sqlparser_status == 6)
|
||||
{
|
||||
$t = strrpos($zeile, '*/');
|
||||
|
||||
if (!$t === false)
|
||||
{
|
||||
$complete_sql = '';
|
||||
$sqlparser_status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// commands that mustn't be executet
|
||||
else
|
||||
if ($sqlparser_status == 7)
|
||||
{
|
||||
if ($last_char == ';')
|
||||
{
|
||||
$restore['speed'] = $config['minspeed'];
|
||||
$complete_sql = '';
|
||||
$sqlparser_status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (($restore['compressed']) && (gzeof($restore['filehandle']))) $restore['fileEOF'] = true;
|
||||
elseif ((!$restore['compressed']) && (feof($restore['filehandle']))) $restore['fileEOF'] = true;
|
||||
}
|
||||
// if special tables are selected for restoring, check if this query belongs to them
|
||||
if (is_array($restore['tables_to_restore']) && !(in_array($restore['actual_table'], $restore['tables_to_restore'])))
|
||||
{
|
||||
$complete_sql = '';
|
||||
}
|
||||
//detect if a table is finished and write log message
|
||||
if ($sqlparser_status != 3 && $sqlparser_status != 8 && in_array($restore['last_parser_status'], array(
|
||||
3,
|
||||
8)))
|
||||
{
|
||||
if (isset($restore['records_inserted_table'][$restore['actual_table']]))
|
||||
{
|
||||
$message = sprintf($lang['L_RESTORE_TABLE'], $restore['actual_table']) . ': ';
|
||||
$message .= sprintf($lang['L_RECORDS_INSERTED'], String::formatNumber($restore['records_inserted_table'][$restore['actual_table']]));
|
||||
$log->write(Log::PHP, $message);
|
||||
}
|
||||
}
|
||||
$restore['last_parser_status'] = $sqlparser_status;
|
||||
$complete_sql = trim($complete_sql);
|
||||
return $complete_sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks SQL-Create-Query for VIEW-Syntax, substitutes the old DEFINER with the actual sql-user
|
||||
* and returns the corrected query.
|
||||
*
|
||||
* @param string $sql SQL-Create-Command
|
||||
* @return string
|
||||
**/
|
||||
function getCorrectedCreateCommand($sql)
|
||||
{
|
||||
global $config;
|
||||
if (strtoupper(substr($sql, 0, 16)) == 'CREATE ALGORITHM')
|
||||
{
|
||||
// It`s a VIEW. We need to substitute the original DEFINER with the actual MySQL-User
|
||||
$parts = explode(' ', $sql);
|
||||
for ($i = 0, $count = sizeof($parts); $i < $count; $i++)
|
||||
{
|
||||
if (strtoupper(substr($parts[$i], 0, 8)) == 'DEFINER=')
|
||||
{
|
||||
global $config;
|
||||
$parts[$i] = 'DEFINER=`' . $config['dbuser'] . '`@`' . $config['dbhost'] . '`';
|
||||
$sql = implode(' ', $parts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes inline-comments from a SQL-String
|
||||
*
|
||||
* @param string $sql SQL-Command
|
||||
*
|
||||
* @return string $sql The cleaned SQL-String
|
||||
**/
|
||||
function deleteInlineComments($sql)
|
||||
{
|
||||
$array = array();
|
||||
preg_match_all("/(\/\*(.+)\*\/)/U", $sql, $array);
|
||||
if (is_array($array[0]))
|
||||
{
|
||||
$sql = trim(str_replace($array[0], '', $sql));
|
||||
}
|
||||
//If there is only a colon left, it was a condition -> clear all
|
||||
if ($sql == ';') $sql = '';
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the tablename from a query
|
||||
*
|
||||
* @param string $sql SQL-Command
|
||||
* @param string $actual_table Tablename to look for if it is known
|
||||
* @return string The name of the table extracted from the Query
|
||||
**/
|
||||
|
||||
function getTablename($sql, $actual_table = '')
|
||||
{
|
||||
$t = substr($sql, 0, 150); // shorten string, the tablename will be in the first 150 chars
|
||||
|
||||
|
||||
// if we find the actual table in the string we got it -> return t without any further parsing
|
||||
if (!false === stripos($t . '` ', $actual_table)) return $t;
|
||||
if (!false === stripos($t . ' ', $actual_table)) return $t;
|
||||
|
||||
// remove all keywords until the tablename is in the front position
|
||||
$t = str_ireplace('DROP TABLE', '', $t);
|
||||
$t = str_ireplace('DROP VIEW', '', $t);
|
||||
$t = str_ireplace('CREATE TABLE', '', $t);
|
||||
$t = str_ireplace('INSERT INTO', '', $t);
|
||||
$t = str_ireplace('REPLACE INTO', '', $t);
|
||||
$t = str_ireplace('IF NOT EXISTS', '', $t);
|
||||
$t = str_ireplace('IF EXISTS', '', $t);
|
||||
if (substr(strtoupper($t), 0, 16) == 'CREATE ALGORITHM')
|
||||
{
|
||||
$pos = strpos($t, 'DEFINER VIEW ');
|
||||
$t = substr($t, $pos, strlen($t) - $pos);
|
||||
}
|
||||
$t = str_ireplace(';', ' ;', $t); // tricky -> insert space as delimiter
|
||||
$t = trim($t);
|
||||
|
||||
// now we simply can search for the first space or `
|
||||
$delimiter = substr($t, 0, 1);
|
||||
if ($delimiter != '`') $delimiter = ' ';
|
||||
$found = false;
|
||||
$position = 1;
|
||||
WHILE (!$found)
|
||||
{
|
||||
if (substr($t, $position, 1) == $delimiter) $found = true;
|
||||
if ($position >= strlen($t)) $found = true;
|
||||
$position++;
|
||||
}
|
||||
$t = substr($t, 0, $position);
|
||||
$t = trim(str_replace('`', '', $t));
|
||||
return $t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect if a SQL-Command is complete
|
||||
*
|
||||
* @param string $sql String to interpret as sql
|
||||
* @return boolean
|
||||
**/
|
||||
function isCompleteQuery($string)
|
||||
{
|
||||
$string = str_replace('\\\\', '', trim($string)); // trim and remove escaped backslashes
|
||||
$string = trim($string);
|
||||
$quotes = substr_count($string, '\'');
|
||||
$escaped_quotes = substr_count($string, '\\\'');
|
||||
if (($quotes - $escaped_quotes) % 2 == 0)
|
||||
{
|
||||
$compare = substr($string, -2);
|
||||
if ($compare == '*/') $compare = substr(deleteInlineComments($string), -2);
|
||||
if ($compare == ');') return true;
|
||||
if ($compare == '),') return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
403
inc/functions/functions_sql.php
Normale Datei
403
inc/functions/functions_sql.php
Normale Datei
|
|
@ -0,0 +1,403 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of MySQLDumper released under the GNU/GPL 2 license
|
||||
* http://www.mysqldumper.net
|
||||
*
|
||||
* @package MySQLDumper
|
||||
* @version SVN: $rev: 1207 $
|
||||
* @author $Author$
|
||||
* @lastmodified $Date$
|
||||
*/
|
||||
|
||||
if (!defined('MSD_VERSION')) die('No direct access.');
|
||||
|
||||
//SQL-Library laden
|
||||
include ('./inc/sqllib.php');
|
||||
|
||||
/**
|
||||
* Get sql-library as array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getSqlLibrary()
|
||||
{
|
||||
global $SQL_ARRAY, $config;
|
||||
$sf = './' . $config['paths']['config'] . 'sql_statements';
|
||||
if (!is_file($sf)) {
|
||||
$fp = fopen($sf, "w+");
|
||||
fclose($fp);
|
||||
@chmod($sf, 0777);
|
||||
}
|
||||
if (count($SQL_ARRAY) == 0 && filesize($sf) > 0) {
|
||||
$SQL_ARRAY = file($sf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a new query to the Sql-Library
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function saveQueryToSqlLibrary()
|
||||
{
|
||||
global $SQL_ARRAY, $config;
|
||||
$sf = './' . $config['paths']['config'] . 'sql_statements';
|
||||
$str = "";
|
||||
for ($i = 0; $i < count($SQL_ARRAY); $i++)
|
||||
{
|
||||
$str .= $SQL_ARRAY[$i];
|
||||
if (substr($str, -1) != "\n" && $i != (count($SQL_ARRAY) - 1)) $str .= "\n";
|
||||
|
||||
}
|
||||
if ($config['magic_quotes_gpc']) $str = stripslashes($str);
|
||||
$fp = fopen($sf, "wb");
|
||||
fwrite($fp, $str);
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of query nr $index from the Sql-Library.
|
||||
*
|
||||
* @param integer $index
|
||||
* @return string
|
||||
*/
|
||||
function getQueryNameFromSqlLibrary($index)
|
||||
{
|
||||
global $SQL_ARRAY;
|
||||
$s = explode('|', $SQL_ARRAY[$index]);
|
||||
return $s[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the query nr $index from the Sql-Library.
|
||||
*
|
||||
* @param integer $index
|
||||
* @return string
|
||||
*/
|
||||
function getQueryFromSqlLibrary($index)
|
||||
{
|
||||
global $SQL_ARRAY;
|
||||
if (!is_array($SQL_ARRAY)) getSqlLibrary();
|
||||
if (isset($SQL_ARRAY[$index]) && !empty($SQL_ARRAY[$index]))
|
||||
{
|
||||
$s = explode('|', $SQL_ARRAY[$index], 2);
|
||||
return (isset($s[1])) ? $s[1] : '';
|
||||
}
|
||||
else
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a html option list from the Sql-Library
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getSqlLibraryComboBox()
|
||||
{
|
||||
global $SQL_ARRAY, $tablename;
|
||||
$s = '';
|
||||
if (count($SQL_ARRAY) > 0)
|
||||
{
|
||||
$s = "\n\n" . '<select class="SQLCombo" name="sqlcombo" onchange="this.form.sqltextarea.value=this.options[this.selectedIndex].value;">' . "\n";
|
||||
$s .= '<option value=""';
|
||||
$s .= Html::getSelected(true, true);
|
||||
$s .= '>---</option>' . "\n";
|
||||
for ($i = 0; $i < count($SQL_ARRAY); $i++)
|
||||
{
|
||||
$s .= '<option value="' . htmlspecialchars(stripslashes(getQueryFromSqlLibrary($i))) . '">' . getQueryNameFromSqlLibrary($i) . '</option>' . "\n";
|
||||
}
|
||||
$s .= '</select>' . "\n\n";
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects if a query returns rows as result or just true or false
|
||||
* Used in SQLBrowser to decide wether a list of records must be shown
|
||||
*
|
||||
* @param $sql the query to discover
|
||||
* return bool
|
||||
**/
|
||||
function queryReturnsRecords($sql)
|
||||
{
|
||||
global $mysql_SQLhasRecords;
|
||||
$s = explode(' ', $sql);
|
||||
if (!is_array($s)) return false;
|
||||
return in_array(strtoupper($s[0]), $mysql_SQLhasRecords) ? true : false;
|
||||
}
|
||||
|
||||
function splitSQLStatements2Array($sql)
|
||||
{
|
||||
$z = 0;
|
||||
$sqlArr = array();
|
||||
$tmp = '';
|
||||
$sql = str_replace("\n", '', $sql);
|
||||
$l = strlen($sql);
|
||||
$inQuotes = false;
|
||||
for ($i = 0; $i < $l; $i++)
|
||||
{
|
||||
$tmp .= $sql[$i];
|
||||
if ($sql[$i] == "'" || $sql[$i] == '"') $inQuotes = !$inQuotes;
|
||||
if ($sql[$i] == ';' && $inQuotes == false)
|
||||
{
|
||||
$z++;
|
||||
$sqlArr[] = $tmp;
|
||||
$tmp = '';
|
||||
}
|
||||
}
|
||||
if (trim($tmp) != '') $sqlArr[] = $tmp;
|
||||
return $sqlArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build HTML-Selectbox from saved SQL-Commands
|
||||
*
|
||||
* @param string $when Before backup = 0, After Backup =1
|
||||
* @param integer $index Index of database
|
||||
* @return string HTML as string
|
||||
*/
|
||||
function getCommandDumpComboBox($when, $index, $db_name)
|
||||
{
|
||||
global $SQL_ARRAY, $databases, $lang;
|
||||
if (count($SQL_ARRAY) == 0)
|
||||
{
|
||||
if ($when == 0) $r = '<input type="hidden" name="command_before_' . $index . '" value="" />';
|
||||
else $r = '<input type="hidden" name="command_after_' . $index . '" value="" />';
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($when == 0)
|
||||
{
|
||||
$r = '<select class="SQLCombo select noleftmargin" name="command_before_' . $index . '" />';
|
||||
$csql = trim($databases[$db_name]['command_before_dump']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$r = '<select class="SQLCombo select noleftmargin" name="command_after_' . $index . '" />';
|
||||
$csql = trim($databases[$db_name]['command_after_dump']);
|
||||
}
|
||||
|
||||
$r .= '<option value=""' . Html::getSelected($csql, '') . ' /> </option>' . "\n";
|
||||
for ($i = 0; $i < count($SQL_ARRAY); $i++)
|
||||
{
|
||||
$s = trim(getQueryFromSqlLibrary($i));
|
||||
$r .= '<option value="' . $i . '"';
|
||||
$r .= Html::getSelected($s, $csql);
|
||||
$r .= '>' . getQueryNameFromSqlLibrary($i) . ' </option>' . "\n";
|
||||
}
|
||||
$r .= '</select>';
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the target tablename from a query
|
||||
*
|
||||
* @param string $q The query
|
||||
* @return string
|
||||
*/
|
||||
function extractTablenameFromSQL($q)
|
||||
{
|
||||
global $databases, $db, $dbid;
|
||||
$tablename = '';
|
||||
if (strlen($q) > 100) $q = substr($q, 0, 100);
|
||||
$p = trim($q);
|
||||
// if we get a list of tables - no current table is selected -> return ''
|
||||
if (strtoupper(substr($q, 0, 17)) == 'SHOW TABLE STATUS') return '';
|
||||
// check for SELECT-Statement to extract tablename after FROM
|
||||
if (strtoupper(substr($p, 0, 7)) == 'SELECT ')
|
||||
{
|
||||
$parts = array();
|
||||
$p = substr($p, strpos(strtoupper($p), 'FROM') + 5);
|
||||
$parts = explode(' ', $p);
|
||||
$p = $parts[0];
|
||||
}
|
||||
$suchen = array(
|
||||
|
||||
'SHOW ',
|
||||
'SELECT',
|
||||
'DROP',
|
||||
'INSERT',
|
||||
'UPDATE',
|
||||
'DELETE',
|
||||
'CREATE',
|
||||
'TABLE',
|
||||
'STATUS',
|
||||
'FROM',
|
||||
'*');
|
||||
$ersetzen = array(
|
||||
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'');
|
||||
$cleaned = trim(str_ireplace($suchen, $ersetzen, $p));
|
||||
$tablename = $cleaned;
|
||||
if (strpos($cleaned, ' ')) $tablename = substr($cleaned, 0, strpos($cleaned, ' '));
|
||||
$tablename = str_replace('`', '', $tablename); // remove backticks
|
||||
// take care of db-name.tablename
|
||||
if (strpos($tablename, '.'))
|
||||
{
|
||||
$p = explode('.', $tablename);
|
||||
$config['db_actual'] = $p[0];
|
||||
if (isset($_GET['tablename'])) unset($_GET['tablename']);
|
||||
$tablename = $p[1];
|
||||
}
|
||||
return $tablename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads extened MySQL field information
|
||||
*
|
||||
* Reads extened field information for each field of a MySQL table
|
||||
* and fills an array like
|
||||
* array(
|
||||
* [Fieldname][attribut]=value,
|
||||
* ['primary_key']=keys
|
||||
* )
|
||||
*
|
||||
* @param $db Database
|
||||
* @param $table Table
|
||||
* @return array Field infos
|
||||
*/
|
||||
function getExtendedFieldInfo($db, $table)
|
||||
{
|
||||
global $config, $dbo;
|
||||
$fields_infos = array();
|
||||
//$t = GetCreateTable($db, $table);
|
||||
$sqlf = "SHOW FULL FIELDS FROM `$db`.`$table`;";
|
||||
$res = $dbo->query($sqlf, MsdDbFactory::ARRAY_ASSOC);
|
||||
$num_fields = sizeof($res);
|
||||
$f = array(); //will hold all info
|
||||
for ($x = 0; $x < $num_fields; $x++)
|
||||
{
|
||||
$row = $res[$x]; //mysql_fetch_array($res, MYSQL_ASSOC);
|
||||
$i = $row['Field']; // define name of field as index of array
|
||||
//define field defaults - this way the index of the array is defined anyway
|
||||
$f[$i]['field'] = '';
|
||||
$f[$i]['collation'] = '';
|
||||
$f[$i]['comment'] = '';
|
||||
$f[$i]['type'] = '';
|
||||
$f[$i]['size'] = '';
|
||||
$f[$i]['attributes'] = '';
|
||||
$f[$i]['null'] = '';
|
||||
$f[$i]['default'] = '';
|
||||
$f[$i]['extra'] = '';
|
||||
$f[$i]['privileges'] = '';
|
||||
$f[$i]['key'] = $row['Key']; //array();
|
||||
|
||||
|
||||
if (isset($row['Collation'])) $f[$i]['collate'] = $row['Collation'];
|
||||
if (isset($row['COLLATE'])) $f[$i]['collate'] = $row['COLLATE']; // MySQL <4.1
|
||||
if (isset($row['Comment'])) $f[$i]['comment'] = $row['Comment'];
|
||||
if (isset($row['Type'])) $f[$i]['type'] = $row['Type'];
|
||||
if (isset($row['Field'])) $f[$i]['field'] = $row['Field'];
|
||||
$f[$i]['size'] = get_attribut_size_from_type($f[$i]['type']);
|
||||
// remove size from type for readability in output
|
||||
$f[$i]['type'] = str_replace('(' . $f[$i]['size'] . ')', '', $f[$i]['type']);
|
||||
// look for attributes, everthing behind the first space is an atribut
|
||||
$attributes = explode(' ', $f[$i]['type'], 2);
|
||||
if (isset($attributes[1]))
|
||||
{
|
||||
// we found attributes
|
||||
unset($attributes[0]); // delete type
|
||||
$f[$i]['attributes'] = trim(implode(' ', $attributes)); //merge all other attributes
|
||||
// remove attributes from type
|
||||
$f[$i]['type'] = trim(str_replace($f[$i]['attributes'], '', $f[$i]['type']));
|
||||
}
|
||||
if (isset($row['NULL'])) $f[$i]['null'] = $row['NULL'];
|
||||
if (isset($row['Null'])) $f[$i]['null'] = $row['Null'];
|
||||
if (isset($row['Default'])) $f[$i]['default'] = $row['Default'];
|
||||
if (isset($row['Extra'])) $f[$i]['extra'] = $row['Extra'];
|
||||
if (isset($row['Privileges'])) $f[$i]['privileges'] = $row['Privileges'];
|
||||
if (isset($row['privileges'])) $f[$i]['privileges'] = $row['privileges'];
|
||||
}
|
||||
|
||||
return $f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unique Identifier for a record in a table
|
||||
*
|
||||
* @param string $db Database
|
||||
* @param string $table Table
|
||||
* @param array &$record Complete records
|
||||
*
|
||||
* @return string Where-Condition to identify the record
|
||||
*/
|
||||
function getRecordIdentifier($db, $table, &$record)
|
||||
{
|
||||
global $table_infos;
|
||||
$where = '';
|
||||
|
||||
if (!isset($table_infos[$db]['tables'][$table]['keys']))
|
||||
{
|
||||
$table_infos = getTableInfo($db, $table);
|
||||
$keys = getKeys($db, $table);
|
||||
$table_infos[$db]['tables'][$table]['keys'] = $keys;
|
||||
}
|
||||
if (isset($table_infos[$db]['tables'][$table]['keys']['PRIMARY']))
|
||||
{
|
||||
// table has a primary key -> we can build the identifier by it
|
||||
foreach ($table_infos[$db]['tables'][$table]['keys']['PRIMARY'] as $column => $val)
|
||||
{
|
||||
$where .= $where > '' ? ' AND ' : '';
|
||||
$where .= '`' . $column . '` = \'' . $record[$column] . '\'';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// shame on the table design -> no key given -> build key from all values of record
|
||||
foreach ($record as $column => $val)
|
||||
{
|
||||
$where .= $where > '' ? ' AND ' : '';
|
||||
$where .= '`' . $column . '` = \'' . $record[$column] . '\'';
|
||||
}
|
||||
}
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Keys from a table and store them in an ass. array $array[Key-Name][column_name]=$keys
|
||||
*
|
||||
* @param string $db
|
||||
* @param string $table
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getKeys($db, $table)
|
||||
{
|
||||
global $dbo;
|
||||
$keys = array();
|
||||
$sql = 'SHOW KEYS FROM `' . $db . '`.`' . $table . '`';
|
||||
$res = $dbo->query($sql, MsdDbFactory::ARRAY_ASSOC);
|
||||
foreach ($res as $row)
|
||||
{
|
||||
$keys[$row['Key_name']][$row['Column_name']] = $row;
|
||||
}
|
||||
return $keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the part in brackets in a string, e.g. int(11) => 11
|
||||
*
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
function get_attribut_size_from_type($type)
|
||||
{
|
||||
$size = '';
|
||||
$matches = array();
|
||||
$pattern = '/\((\d.*?)\)/msi';
|
||||
preg_match($pattern, $type, $matches);
|
||||
if (isset($matches[1])) $size = $matches[1];
|
||||
return $size;
|
||||
}
|
||||
|
||||
Laden …
Tabelle hinzufügen
Einen Link hinzufügen
In neuem Issue referenzieren