From 44a53ee05b406262cb467c6a8e07b91ead38fa5b Mon Sep 17 00:00:00 2001 From: Klaus Leithoff Date: Thu, 27 Aug 2009 12:46:12 +0000 Subject: [PATCH] backup housekeeping feature from H.J.Tappe together with a feature to backup egroupware the files - tree from Christian Fueller; The File-backup feature is testet against relatively small eGroupware Instances; It requires ZipArchive (If you dont have that, the backup should run, but without backup of files); AND if you enable it backup takes a) more time to run and restore b) way more space, so you should enable housekeeping --- admin/inc/class.admin_db_backup.inc.php | 59 ++-- phpgwapi/inc/class.db_backup.inc.php | 345 ++++++++++++++++++++++- setup/db_backup.php | 60 +++- setup/inc/class.setup_cmd_config.inc.php | 2 + setup/inc/class.setup_detection.inc.php | 18 ++ setup/lang/egw_de.lang | 8 + setup/lang/egw_en.lang | 8 + setup/templates/default/db_backup.tpl | 21 ++ 8 files changed, 474 insertions(+), 47 deletions(-) diff --git a/admin/inc/class.admin_db_backup.inc.php b/admin/inc/class.admin_db_backup.inc.php index fc81f21d15..cf904b9355 100644 --- a/admin/inc/class.admin_db_backup.inc.php +++ b/admin/inc/class.admin_db_backup.inc.php @@ -12,43 +12,46 @@ /* $Id$ */ - class admin_db_backup - { - var $public_functions = array( - 'do_backup' => true, - 'index' => true, - ); - var $db_backup; - - function admin_db_backup() - { - } - - /** - * Method for sheduled backups, called via asynservice - */ - function do_backup() - { + class admin_db_backup + { + var $public_functions = array( + 'do_backup' => true, + 'index' => true, + ); + var $db_backup; + + function admin_db_backup() + { + } + + /** + * Method for sheduled backups, called via asynservice + */ + function do_backup() + { $this->db_backup =& CreateObject('phpgwapi.db_backup'); if ($f = $this->db_backup->fopen_backup()) { $this->db_backup->backup($f); - fclose($f); + if(is_resource($f)) + fclose($f); + /* Remove old backups. */ + $this->db_backup->housekeeping(); } - } + } - /** - * includes setup's db_backup to display/access it inside admin - */ - function index() - { - $tpl_root = EGW_SERVER_ROOT.'/setup/templates/default'; + /** + * includes setup's db_backup to display/access it inside admin + */ + function index() + { + $tpl_root = EGW_SERVER_ROOT.'/setup/templates/default'; $self = $GLOBALS['egw']->link('/index.php',array('menuaction'=>'admin.admin_db_backup.index')); $GLOBALS['egw']->translation->add_app('setup'); - + include EGW_SERVER_ROOT.'/setup/db_backup.php'; $GLOBALS['egw']->common->egw_footer(); - } - } \ No newline at end of file + } + } diff --git a/phpgwapi/inc/class.db_backup.inc.php b/phpgwapi/inc/class.db_backup.inc.php index 4fae4a9f7f..2dada198bb 100644 --- a/phpgwapi/inc/class.db_backup.inc.php +++ b/phpgwapi/inc/class.db_backup.inc.php @@ -20,6 +20,10 @@ class db_backup * replaces backslashes, used in cvs_split */ const BACKSLASH_TOKEN = '##!!**bAcKsLaSh**!!##'; + /** + * Configuration table. + */ + const TABLE = 'egw_config'; /** * Reference to schema_proc * @@ -47,6 +51,7 @@ class db_backup 'egw_sessions','egw_app_sessions','phpgw_sessions','phpgw_app_sessions', // eGW's session-tables 'phpgw_anglemail', // email's cache 'egw_felamimail_cache','egw_felamimail_folderstatus','phpgw_felamimail_cache','phpgw_felamimail_folderstatus', // felamimail's cache + 'egw_phpfreechat', // as of the fieldnames of the table a restore would fail within egroupware, and chatcontent is of no particular intrest ); /** * regular expression to identify system-tables => ignored for schema+backup @@ -55,12 +60,30 @@ class db_backup */ var $system_tables = false; /** - * regurar expression to identify eGW tables => if set only they are used + * Regular expression to identify eGW tables => if set only they are used * * @var string|boolean */ var $egw_tables = false; - + /** + * Backup directory. + * + * @var string + */ + var $backup_dir; + /** + * Minimum number of backup files to keep. Zero for: Disable cleanup. + * + * @var integer + */ + var $backup_mincount; + /** + * Backup Files config value, will be overwritten by the availability of the ZibArchive libraries + * + * @var boolean + */ + var $backup_files = false ; + /** * Constructor */ @@ -93,6 +116,12 @@ class db_backup $this->db->next_record(); $this->backup_dir = $this->db->f(0).'/db_backup'; } + $this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='files_dir'",__LINE__,__FILE__); + $this->db->next_record(); + if (!($this->files_dir = $this->db->f(0))) + { + error_log(__METHOD__."->"."No files Directory set/found"); + } $this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='system_charset'",__LINE__,__FILE__); $this->db->next_record(); $this->charset = $this->db->f(0); @@ -104,6 +133,14 @@ class db_backup } $this->db->select($GLOBALS['egw_setup']->applications_table,'app_version',array('app_name'=>'phpgwapi'),__LINE__,__FILE__); $this->api_version = $this->db->next_record() ? $this->db->f(0) : false; + /* Backup settings */ + $this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='backup_mincount'",__LINE__,__FILE__); + $this->db->next_record(); + $this->backup_mincount = $this->db->f(0); + // backup files too + $this->db->query("SELECT config_value FROM {$GLOBALS['egw_setup']->config_table} WHERE config_app='phpgwapi' AND config_name='backup_files'",__LINE__,__FILE__); + $this->db->next_record(); + $this->backup_files = (bool)$this->db->f(0); } if (!$this->charset) $this->charset = 'iso-8859-1'; } @@ -114,10 +151,23 @@ class db_backup { $this->backup_dir = $GLOBALS['egw_info']['server']['files_dir'].'/db_backup'; } + $this->files_dir = $GLOBALS['egw_info']['server']['files_dir']; + $this->backup_mincount = $GLOBALS['egw_info']['server']['backup_mincount']; + $this->backup_files = $GLOBALS['egw_info']['server']['backup_files']; $this->charset = $GLOBALS['egw']->translation->charset(); $this->api_version = $GLOBALS['egw_info']['apps']['phpgwapi']['version']; } + // Set a default value if not set. + if (!isset($this->backup_mincount)) + { + $this->backup_mincount = 0; // Disabled if not set + } + if (!isset($this->backup_files)) + { + $this->backup_files = false; // Disabled if not set + } + if (!is_dir($this->backup_dir) && is_writable(dirname($this->backup_dir))) { mkdir($this->backup_dir); @@ -137,42 +187,154 @@ class db_backup * * @param $name=false string/boolean filename to use, or false for the default one * @param $reading=false opening for reading ('rb') or writing ('wb') - * @return string/resource error-msg of file-handle + * @return string/resource/zip error-msg of file-handle */ function fopen_backup($name=false,$reading=false) { + //echo "function fopen_backup($name,$reading)
"; // ! if (!$name) { + //echo '-> !$name
'; // ! if (!$this->backup_dir || !is_writable($this->backup_dir)) { + //echo ' -> !$this->backup_dir || !is_writable($this->backup_dir)
'; // ! return lang("backupdir '%1' is not writeable by the webserver",$this->backup_dir); } $name = $this->backup_dir.'/db_backup-'.date('YmdHi'); } else // remove the extension, to use the correct wrapper based on the extension { + //echo '-> else
'; // ! $name = preg_replace('/\.(bz2|gz)$/i','',$name); } $mode = $reading ? 'rb' : 'wb'; - - if (!($f = @fopen($file = "compress.bzip2://$name.bz2",$mode)) && - !($f = @fopen($file = "compress.zlib://$name.gz",$mode)) && - !($f = @fopen($file = "zlib:$name.gz",$mode)) && // php < 4.3 - !($f = @fopen($file = $name,$mode))) + list( , $type) = explode('.', basename($name)); + if($type == 'zip' && $reading && $this->backup_files) { - $lang_mode = $reading ? lang('reading') : lang('writing'); - return lang("Cant open '%1' for %2",$name,$lang_mode); + //echo '-> $type == "zip" && $reading
'; // ! + if(!class_exists('ZipArchive', false)) + { + $this->backup_files = false; + //echo ' -> (new ZipArchive) == NULL
'; // ! + return lang("Cant open $name, needs ZipArchive")."
"; + } + if(!($f = fopen($name, $mode))) + { + //echo ' -> !($f = fopen($name, $mode))
'; // ! + $lang_mode = $reading ? lang("reading") : lang("writing"); + return lang("Cant open '%1' for %2", $name, $lang_mode)."
"; + } + return $f; + } + if(class_exists('ZipArchive', false) && !$reading && $this->backup_files) + { + //echo '-> (new ZipArchive) != NULL && !$reading; '.$name.'
'; // ! + if(!($f = fopen($name, $mode))) + { + //echo ' -> !($f = fopen($name, $mode))
'; // ! + $lang_mode = $reading ? lang("reading") : lang("writing"); + return lang("Cant open '%1' for %2", $name, $lang_mode)."
"; + } + return $f; + } + if(!($f = fopen("compress.bzip2://$name.bz2", $mode))) + { + //echo '-> !($f = fopen("compress.bzip2://$name.bz2", $mode))
'; // ! + $lang_mode = $reading ? lang("reading") : lang("writing"); + return lang("Cant open '%1' for %2", $name, $lang_mode)."
"; } return $f; } + /** + * Remove old backups, leaving at least + * backup_mincount backup files in place. Only backup files with + * the regular name scheme are taken into account. + * + * @param files_return Fills a given array of file names to display (if given). + */ + function housekeeping(&$files_return = false) + { + /* Stop housekeeping in case it is disabled. */ + if ($this->backup_mincount == 0) + { + return; + } + /* Search the backup directory for matching files. */ + $handle = @opendir($this->backup_dir); + $files = array(); + while($handle && ($file = readdir($handle))) + { + /* Filter for only the files with the regular name (un-renamed). + * Leave special backup files (renamed) in place. + * Note that this also excludes "." and "..". + */ + if (preg_match("/^db_backup-[0-9]{12}(\.bz2|\.gz|\.zip|)$/",$file)) + { + $files[filectime($this->backup_dir.'/'.$file)] = $file; + } + } + if ($handle) closedir($handle); + + /* Sort the files by ctime. */ + krsort($files); + $count = 0; + foreach($files as $ctime => $file) + { + if ($count >= $this->backup_mincount)// + { + $ret = unlink($this->backup_dir.'/'.$file); + if (($ret) && (is_array($files_return))) + { + array_push($files_return, $file); + } + } + $count ++; + } + } + + /** + * Save the housekeeping configuration in the database and update the local variables. + * + * @param mincount Minimum number of backups to keep. + */ + function saveConfig($config_values) + { + if (!is_array($config_values)) + { + error_log(__METHOD__." unable to save backup config values, wrong type of parameter passed."); + return false; + } + //_debug_array($config_values); + $minCount = $config_values['backup_mincount']; + $backupFiles = (int)$config_values['backup_files']; + /* minCount */ + $this->db->insert( + self::TABLE, + array( + 'config_value' => $minCount, + ), + array( + 'config_app' => 'phpgwapi', + 'config_name' => 'backup_mincount', + ), + __LINE__, + __FILE__); + /* backup files flag */ + $this->db->insert(self::TABLE,array('config_value' => $backupFiles),array('config_app' => 'phpgwapi','config_name' => 'backup_files'),__LINE__,__FILE__); + $this->backup_mincount = $minCount; + $this->backup_files = (bool)$backupFiles; + // Update session cache + $GLOBALS['egw']->invalidate_session_cache(); + } + /** * Backup all data in the form of a (compressed) csv file * * @param resource $f file opened with fopen for reading * @param boolean $convert_to_system_charset=false convert the restored data to the selected system-charset */ - function restore($f,$convert_to_system_charset=false) + function restore($f,$convert_to_system_charset=false,$filename) { @set_time_limit(0); ini_set('auto_detect_line_endings',true); @@ -189,7 +351,37 @@ class db_backup } $this->schema_proc->DropTable($table); } - + // it could be an old backup + list( , $type) = explode('.', basename($filename)); + $dir = $this->files_dir; // $GLOBALS['egw_info']['server']['files_dir']; + // we may have to clean up old backup - left overs + if (is_dir($dir.'/database_backup')) + { + remove_dir_content($dir.'/database_backup/'); + rmdir($dir.'/database_backup'); + } + + $list = array(); + $name = ""; + $zip = NULL; + $_f = NULL; + if($type == 'zip') + { + $zip = new ZipArchive; + if(($zip->open($filename)) !== TRUE) + { + return "Cant open '$filename' for reading
"; + } + $this->remove_dir_content($dir); // removes the files-dir + $zip->extractTo($dir); + $_f = $f; + $list = $this->get_file_list($dir.'/database_backup/'); + $name = $dir.'/database_backup/'.basename($list[0]); + if(!($f = fopen($name, 'rb'))) + { + return "Cant open $name for reading
"; + } + } $table = False; $n = 0; while(!feof($f)) @@ -273,6 +465,11 @@ class db_backup echo 'data=
'.print_r($data,true)."
\n"; $import = false; } + if (in_array($table,$this->exclude_tables)) + { + echo '

'.lang("Table %1 is excluded from backup and restore. Data will not be restored.",$table)."

\n"; + $import = false; // dont restore data of excluded tables + } if ($import) { if (count($data) == count($cols)) { @@ -312,8 +509,35 @@ class db_backup 'config_name' => 'system_charset', ),__LINE__,__FILE__); } + // zip? + if($type == 'zip') + { + fclose($f); + $f = $save_f; + unlink($name); + rmdir($dir.'/database_backup'); + } $this->db->transaction_commit(); } + + /** + * Removes a dir, no matter whether it is empty or full + * + * @param strin $dir + */ + function remove_dir_content($dir) + { + $list = scandir($dir); + while($file = $list[0]) + { + if(is_dir($file) && $file != '.' && $file != '..') + $this->remove_dir_content($dir.'/'.$file); + if(is_file($file) && $file != '.' && $file != '..') + unlink($dir.'/'.$file); + array_shift($list); + } + //rmdir($dir); // dont remove own dir + } /** * Split one line of a csv file into an array and does all unescaping @@ -391,8 +615,35 @@ class db_backup */ function backup($f) { + //echo "function backup($f)
"; // ! @set_time_limit(0); + $dir = $this->files_dir; // $GLOBALS['egw_info']['server']['files_dir']; + // we may have to clean up old backup - left overs + if (is_dir($dir.'/database_backup')) + { + remove_dir_content($dir.'/database_backup/'); + rmdir($dir.'/database_backup'); + } + $file_list = $this->get_file_list($dir); + $name = $this->backup_dir.'/db_backup-'.date('YmdHi'); + $filename = $name.'.zip'; + $zippresent = false; + if(class_exists('ZipArchive') && $this->backup_files) + { + $zip = new ZipArchive; + if(is_object($zip)) + { + $zippresent = true; + //echo '-> is_object($zip); '.$filename.'
'; // ! + $res = $zip->open($filename, ZIPARCHIVE::CREATE); + if($res !== TRUE) + { + //echo ' -> !$res
'; // ! + return "Cant open '$filename'
"; + } + } + } fwrite($f,"eGroupWare backup from ".date('Y-m-d H:i:s')."\n\n"); fwrite($f,"version: $this->api_version\n\n"); @@ -422,7 +673,7 @@ class db_backup $first_row = true; $this->db->select($table,'*',false,__LINE__,__FILE__); - while(($row = $this->db->row(true))) + while($row = $this->db->row(true)) { if ($first_row) { @@ -433,9 +684,77 @@ class db_backup fwrite($f,implode(',',$row)."\n"); } } + // save files + if(!$zippresent) // save without files (why ever it works only right without '!'...) + { + echo '
'."No file backup, needs ZipArchive or disabled
".'
'; + fclose($f); + if (file_exists($name)) unlink($name); + return TRUE; + } + //echo $name.'
'; + $zip->addFile($name, 'database_backup/'.basename($name)); + $count = 1; + foreach($file_list as $num => $file) + { + //echo substr($file,strlen($dir)+1).'
'; + //echo $file.'
'; + $zip->addFile($file,substr($file,strlen($dir)+1));//,substr($file); + if(($count++) == 100) { // the file descriptor limit + $zip->close(); + if($zip = new ZipArchive()) { + $zip->open($filename); + $count =0; + } + } + } + $zip->close(); + fclose($f); + unlink($name); return true; } + /** + * gets a list of all files on $f + * + * @param string file $f + * [@param int $cnt] + * [@param string $path_name] + * + * @return array (list of files) + */ + function get_file_list($f, $cnt = 0, $path_name = "") + { + //chdir($f); + //echo "Processing $f
"; + if ($path_name =='') $path_name = $f; + $tlist = scandir($f); + $list = array(); + $i = $cnt; + while($file = $tlist[0]) // remove all '.' and '..' and transfer to $list + { + if($file == '.' || $file == '..') + { + array_shift($tlist); + } + else + { + if(is_dir($f.'/'.$file)) + { + $nlist = $this->get_file_list($f.'/'.$file, $i); + $list += $nlist; + $i += count($nlist); + array_shift($tlist); + } + else + { + $list[$i++] = $path_name.'/'.array_shift($tlist); + } + } + } + return $list; + } + /** * Backup all schemas in the form of a setup/tables_current.inc.php file * diff --git a/setup/db_backup.php b/setup/db_backup.php index 5af8627a3b..896a8a4419 100644 --- a/setup/db_backup.php +++ b/setup/db_backup.php @@ -36,14 +36,15 @@ if ($_POST['download']) { list($file) = each($_POST['download']); $file = $db_backup->backup_dir.'/'.basename($file); // basename to now allow to change the dir - + ob_end_clean(); $browser = CreateObject('phpgwapi.browser'); $browser->content_header(basename($file)); - fpassthru($f = fopen($file,'rb')); + $f = fopen($file,'rb'); + fpassthru($f); fclose($f); exit; } - $setup_tpl = CreateObject('phpgwapi.Template',$tpl_root); +$setup_tpl = CreateObject('phpgwapi.Template',$tpl_root); $setup_tpl->set_file(array( 'T_head' => 'head.tpl', 'T_footer' => 'footer.tpl', @@ -70,6 +71,35 @@ else $GLOBALS['egw']->common->phpgw_header(); parse_navbar(); } +// save backup housekeeping settings +if ($_POST['save_backup_settings']) +{ + $matches = array(); + preg_match('/^[1-9][0-9]*$/', $_POST['backup_mincount'], $matches); + $minCount = $matches[0]; + $filesBackup =false; + if ($_POST['backup_files']==='backup_files') $filesBackup = true; + if (empty($minCount)) + { + $setup_tpl->set_var('error_msg',htmlspecialchars(lang("'%1' must be integer", lang("backup min count")))); + } + else + { + $configValues = array( + 'backup_mincount'=>$minCount, + 'backup_files' =>$filesBackup, + ); + $db_backup->saveConfig($configValues); + + $cleaned_files = array(); + /* Remove old backups. */ + $db_backup->housekeeping(&$cleaned_files); + foreach ($cleaned_files as $file) + { + echo '
'.lang('entry has been deleted sucessfully').': '.$file."
\n"; + } + } +} // create a backup now if($_POST['backup']) { @@ -77,8 +107,17 @@ if($_POST['backup']) { echo '

'.lang('backup started, this might take a few minutes ...')."

\n".str_repeat(' ',4096); $db_backup->backup($f); - fclose($f); + if(is_resource($f)) + fclose($f); $setup_tpl->set_var('error_msg',lang('backup finished')); + + /* Remove old backups. */ + $cleaned_files = array(); + $db_backup->housekeeping(&$cleaned_files); + foreach ($cleaned_files as $file) + { + echo '
'.lang('entry has been deleted sucessfully').': '.$file."
\n"; + } } else { @@ -88,6 +127,9 @@ if($_POST['backup']) $setup_tpl->set_var('backup_now_button',''); $setup_tpl->set_var('upload','  '. ''); +$setup_tpl->set_var('backup_mincount',''); +$setup_tpl->set_var('backup_files','backup_files ? 'checked':'').'/>'); +$setup_tpl->set_var('backup_save_settings',''); if ($_POST['upload'] && is_array($_FILES['uploaded']) && !$_FILES['uploaded']['error'] && is_uploaded_file($_FILES['uploaded']['tmp_name'])) @@ -116,6 +158,9 @@ if ($_POST['rename']) $new_name = $_POST['new_name'][$file]; if (!empty($new_name)) { + list($ending) = array_reverse(explode('.', $file)); + list($new_ending, $has_ending) = array_reverse(explode('.', $new_name)); + if(!$has_ending || $new_ending != $ending) $new_name .= '.'.$ending; $file = $db_backup->backup_dir.'/'.basename($file); // basename to not allow to change the dir $ext = preg_match('/(\.gz|\.bz2)+$/i',$file,$matches) ? $matches[1] : ''; $new_file = $db_backup->backup_dir.'/'.preg_replace('/(\.gz|\.bz2)+$/i','',basename($new_name)).$ext; @@ -131,8 +176,7 @@ if ($_POST['restore']) if (is_resource($f = $db_backup->fopen_backup($file,true))) { echo '

'.lang('restore started, this might take a few minutes ...')."

\n".str_repeat(' ',4096); - $db_backup->restore($f); - fclose($f); + $db_backup->restore($f, FALSE, $file); $setup_tpl->set_var('error_msg',lang("backup '%1' restored",$file)); } else @@ -214,6 +258,10 @@ $setup_tpl->set_var(array( 'lang_next_run' => lang('next run'), 'lang_actions' => lang('actions'), 'lang_backup_sets' => lang('backup sets'), + 'lang_backup_cleanup' => lang('backup housekeeping'), + 'lang_backup_mincount' => lang('min backup count'), + 'lang_backup_files_info' => lang('backup files (needs ZipArchive)'), + 'lang_backup_files' => lang('check to backup and restore the files directory (may use a lot of space, make sure to configure housekeeping accordingly)'), 'lang_filename' => lang('filename'), 'lang_date' => lang('created'), 'lang_size' => lang('size'), diff --git a/setup/inc/class.setup_cmd_config.inc.php b/setup/inc/class.setup_cmd_config.inc.php index 41a92e227b..667af306bd 100644 --- a/setup/inc/class.setup_cmd_config.inc.php +++ b/setup/inc/class.setup_cmd_config.inc.php @@ -351,6 +351,8 @@ class setup_cmd_config extends setup_cmd // some extra defaults for non-cli operation $defaults['files_dir'] = '/var/lib/egroupware/$domain/files'; $defaults['backup_dir'] = '/var/lib/egroupware/$domain/backup'; + $defaults['backup_mincount'] = 0; + $defaults['backup_files'] = false; $defaults['temp_dir'] = '/tmp'; $defaults['webserver_url'] = '/egroupware'; $defaults['smtp_server'] = $defaults['mail_server'] = 'localhost'; diff --git a/setup/inc/class.setup_detection.inc.php b/setup/inc/class.setup_detection.inc.php index e141c04a1d..87ae54ebf6 100755 --- a/setup/inc/class.setup_detection.inc.php +++ b/setup/inc/class.setup_detection.inc.php @@ -389,6 +389,24 @@ class setup_detection ),__LINE__,__FILE__); } } + if (isset($config['backup_mincount'])) + { + $GLOBALS['egw_setup']->db->insert($GLOBALS['egw_setup']->config_table,array( + 'config_value' => $config['backup_mincount'], + ),array( + 'config_app' => 'phpgwapi', + 'config_name' => 'backup_mincount', + ),__LINE__,__FILE__); + } + if (isset($config['backup_files'])) + { + $GLOBALS['egw_setup']->db->insert($GLOBALS['egw_setup']->config_table,array( + 'config_value' => (int)$config['backup_files'], + ),array( + 'config_app' => 'phpgwapi', + 'config_name' => 'backup_files', + ),__LINE__,__FILE__); + }; if (!$this->check_dir($config['backup_dir'],$error_msg,true)) { $config_errors[] = lang("Your backup directory '%1' %2",$config['backup_dir'],$error_msg); diff --git a/setup/lang/egw_de.lang b/setup/lang/egw_de.lang index 1dcec8e09a..c4e098165a 100644 --- a/setup/lang/egw_de.lang +++ b/setup/lang/egw_de.lang @@ -10,6 +10,7 @@ %1, %2 or %3 the configuration file. setup de %1, %2 oder %3 der Konfigurationsdatei. '%1' is no valid domain name! setup de '%1' ist kein gültiger Domainname! '%1' is not allowed as %2. arguments of option %3 !!! setup de '%1' ist nicht erlaubt als %2. Parameter für die Option %3 !!! +'%1' must be integer setup de %1 muß ein Integer-Wert sein. (searching accounts and changing passwords) setup de Benutzerkonten suchen und Passwörter ändern) *** do not update your database via setup, as the update might be interrupted by the max_execution_time, which leaves your db in an unrecoverable state (your data is lost) !!! setup de *** Updaten Sie NICHT Ihre Datenbank via Setup, da das Update von der max_execution_time (max. Ausführungszeit für Skripte) unterbrochen werden kann. Ihre Datenbank ist dann in einem nicht mehr wiederherstellbaren Zustand (Ihre Daten sind VERLOREN)!!! *** you have to do the changes manualy in your php.ini (usualy in /etc on linux) in order to get egw fully working !!! setup de *** Sie müssen die Änderungen manuell in Ihrer php.ini Datei (üblicherweise in /etc unter Linux) durchführen, um eGroupWare vollständig/fehlerfrei ausführen zu können!!! @@ -88,7 +89,10 @@ backup '%1' renamed to '%2' setup de Datensicherung '%1' nach '%2' umbenannt backup '%1' restored setup de Datensicherung '%1' zurückgesichert backup and restore setup de Datensicherung und Wiederherstellung backup failed setup de Datensicherung fehlgeschlagen +backup files (needs ziparchive) setup de Datensicherung der eGroupware Dateiumgebung (files Verzeichnis) (benötigt die PHP Bibliothek ZipArchive) backup finished setup de Datensicherung beendet +backup housekeeping setup de Backups mit Standard-Namen können automatisch aufgeräumt werden. Umbenannte Backup-Dateien werden nie aufgeräumt werden. +backup min count setup de Min. Anzahl der Backups backup now setup de jetzt sichern backup sets setup de Datensicherungen backup skipped! setup de Datensicherung ausgelassen! @@ -122,6 +126,7 @@ charsets used by the different languages setup de Zeichensätze die von den vers check can only be performed, if called via a webserver, as the user-id/-name of the webserver is not known. setup de Dieser Test kann nur durchgeführt werden, wenn der Aufruf über den Webserver erfolgt, da Benutzer-Id und -name des Webservers nicht bekannt sind. check installation setup de Installation überprüfen check ip address of all sessions setup de IP Adresse bei allen Sessions überprüfen +check to backup and restore the files directory (may use a lot of space, make sure to configure housekeeping accordingly) setup de anhaken, um das Backup und Restore der Dateiumgebung (Datei-Verzeichnis) zu aktivieren. (diese Option kann grosse Mengen an Festplatten-Speicherpatz verbrauchen; stellen Sie sicher dass das Housekeeping entsprechend konfiguriert ist.) checking extension %1 is loaded or loadable setup de Überprüfe ob die Erweiterung %1 geladen oder ladbar ist checking file-permissions of %1 for %2 %3: %4 setup de Überprüfe Datei Zugriffsrechte von %1 für %2 %3: %4 checking for gd support... setup de Überprüfe die GD Unterstützung... @@ -181,6 +186,7 @@ database setup de Datenbank database instance (egw domain) setup de Datenbankinstanz (eGW Domain) database is version %1 and up to date. setup de Datenbank ist Version %1 und aktuell. database successfully converted from '%1' to '%2' setup de Datenbank erfolgreich von "%1" nach "%2" konvertiert +datebase %1 droped. setup de Datenbank %1 gelöscht. datetime port.
if using port 13, please set firewall rules appropriately before submitting this page.
(port: 13 / host: 129.6.15.28) setup de Port für Datum/Zeitabfragen
Wenn der Port 13 verwendet wird, bitte VOR dem Absenden die Firewallregeln dementsprechend setzen.
(Port 13/Host: 129.6.15.28) day setup de Tag day of week
(0-6, 0=sunday) setup de Wochentag
(0-6, 0=Sonntag) @@ -255,6 +261,7 @@ enter your http proxy server setup de HTTP-Proxy-Server enter your http proxy server password setup de Passwort des HTTP-Proxy-Servers enter your http proxy server port setup de Port des HTTP-Proxy-Servers enter your http proxy server username setup de Benutzername des HTTP-Proxy-Servers +error dropping user! setup de Fehler beim Löschen des Benutzers! error in admin-creation !!! setup de Fehler beim Anlegen des Admin-Kontos !!! error in group-creation !!! setup de Fehler beim Anlegen der Gruppen !!! export has been completed! setup de Export ist abgeschlossen! @@ -365,6 +372,7 @@ mcrypt mode (default cbc) setup de MCrypt-Modus (Vorgabe CBC) mcrypt settings (requires mcrypt php extension) setup de MCrypt-Einstellungen (benötigt die mcrypt Erweiterung von PHP) memory_limit is set to less than %1: some applications of egroupware need more than the recommend 8m, expect occasional failures setup de memory_limit (maximale Speicher für ein Skript) ist auf weniger als %1 gesetzt: einige eGroupWare Anwendungen benötigen mehr als die empfohlenen 8M. Sie müssen mit gelegentlichen Fehlern rechnen. migration between egroupware account repositories setup de Migration zwischen versch. Orten zur Speicherung von eGroupWare Benutzern +min backup count setup de Min. Anzahl gehaltener Backups (null: alle / kein Limit) minimum account id (e.g. 500 or 100, etc.) setup de Minimum für Benutzer-ID (z.B. 500 oder 100) minute setup de Minute missing or uncomplete mailserver configuration setup de Fehlende oder nicht komplette Mailserver Konfiguration diff --git a/setup/lang/egw_en.lang b/setup/lang/egw_en.lang index 9d95a70953..d0ea8ad9f3 100644 --- a/setup/lang/egw_en.lang +++ b/setup/lang/egw_en.lang @@ -10,6 +10,7 @@ %1, %2 or %3 the configuration file. setup en %1, %2 or %3 the configuration file. '%1' is no valid domain name! setup en '%1' is no valid domain name! '%1' is not allowed as %2. arguments of option %3 !!! setup en '%1' is not allowed as %2. arguments of option %3 !!! +'%1' must be integer setup en %1 must be an integer value. (searching accounts and changing passwords) setup en (searching accounts and changing passwords) *** do not update your database via setup, as the update might be interrupted by the max_execution_time, which leaves your db in an unrecoverable state (your data is lost) !!! setup en *** Do NOT update your database via setup, as the update might be interrupted by the max_execution_time, which leaves your DB in an unrecoverable state (your data is lost) !!! *** you have to do the changes manualy in your php.ini (usualy in /etc on linux) in order to get egw fully working !!! setup en *** You have to do the changes manualy in your php.ini (usualy in /etc on linux) in order to get eGW fully working !!! @@ -88,7 +89,10 @@ backup '%1' renamed to '%2' setup en backup '%1' renamed to '%2' backup '%1' restored setup en backup '%1' restored backup and restore setup en backup and restore backup failed setup en Backup failed +backup files (needs ziparchive) setup en backup files (needs ZipArchive) backup finished setup en backup finished +backup housekeeping setup en Backups with a standard name can be cleaned up automatically. Rename backup files to exclude them from cleanup. +backup min count setup en Minumum number of backups backup now setup en backup now backup sets setup en backup sets backup skipped! setup en Backup skipped! @@ -122,6 +126,7 @@ charsets used by the different languages setup en charsets used by the different check can only be performed, if called via a webserver, as the user-id/-name of the webserver is not known. setup en Check can only be performed, if called via a webserver, as the user-id/-name of the webserver is not known. check installation setup en Check installation check ip address of all sessions setup en check ip address of all sessions +check to backup and restore the files directory (may use a lot of space, make sure to configure housekeeping accordingly) setup en check to backup and restore the files directory (may use a lot of space, make sure to configure housekeeping accordingly) checking extension %1 is loaded or loadable setup en Checking extension %1 is loaded or loadable checking file-permissions of %1 for %2 %3: %4 setup en Checking file-permissions of %1 for %2 %3: %4 checking for gd support... setup en Checking for GD support... @@ -181,6 +186,7 @@ database setup en Database database instance (egw domain) setup en Database instance (eGW domain) database is version %1 and up to date. setup en database is version %1 and up to date. database successfully converted from '%1' to '%2' setup en Database successfully converted from '%1' to '%2' +datebase %1 droped. setup en Datebase %1 droped. datetime port.
if using port 13, please set firewall rules appropriately before submitting this page.
(port: 13 / host: 129.6.15.28) setup en Datetime port.
If using port 13, please set firewall rules appropriately before submitting this page.
(Port: 13 / Host: 129.6.15.28) day setup en day day of week
(0-6, 0=sunday) setup en day of week
(0-6, 0=sunday) @@ -253,6 +259,7 @@ enter your http proxy server setup en Enter your HTTP proxy server enter your http proxy server password setup en Enter your HTTP proxy server password enter your http proxy server port setup en Enter your HTTP proxy server port enter your http proxy server username setup en Enter your HTTP proxy server username +error dropping user! setup en Error dropping User! error in admin-creation !!! setup en Error in admin-creation !!! error in group-creation !!! setup en Error in group-creation !!! export has been completed! setup en Export has been completed! @@ -363,6 +370,7 @@ mcrypt mode (default cbc) setup en Mcrypt mode (default CBC) mcrypt settings (requires mcrypt php extension) setup en Mcrypt Settings (requires mcrypt PHP extension) memory_limit is set to less than %1: some applications of egroupware need more than the recommend 8m, expect occasional failures setup en memory_limit is set to less than %1: some applications of eGroupWare need more than the recommend 8M, expect occasional failures migration between egroupware account repositories setup en Migration between eGroupWare account repositories +min backup count setup en Number of backups to keep at least (zero: all / no limit) minimum account id (e.g. 500 or 100, etc.) setup en Minimum account id (e.g. 500 or 100, etc.) minute setup en minute missing or uncomplete mailserver configuration setup en Missing or uncomplete mailserver configuration diff --git a/setup/templates/default/db_backup.tpl b/setup/templates/default/db_backup.tpl index e07c1282a6..6414061a0a 100644 --- a/setup/templates/default/db_backup.tpl +++ b/setup/templates/default/db_backup.tpl @@ -59,6 +59,27 @@ {upload} + + + {lang_backup_cleanup} + + + {lang_backup_mincount} {backup_mincount} + + + + + {lang_backup_files_info} + + + {lang_backup_files} {backup_files} + + + + + {backup_save_settings} + +