2004-10-16 01:06:34 +02:00
< ? php
2008-08-20 08:04:28 +02:00
/**
2016-05-01 17:56:49 +02:00
* EGroupware Setup - DB backup and restore
2008-08-20 08:04:28 +02:00
*
* @ link http :// www . egroupware . org
* @ package setup
* @ author Ralf Becker < RalfBecker - AT - outdoor - training . de >
* @ license http :// opensource . org / licenses / gpl - license . php GPL - GNU General Public License
* @ version $Id $
*/
2016-02-20 21:27:17 +01:00
use EGroupware\Api ;
2016-05-01 17:56:49 +02:00
use EGroupware\Api\Framework ;
use EGroupware\Api\Egw ;
use EGroupware\Api\Vfs ;
2016-02-20 21:27:17 +01:00
2018-04-11 15:13:21 +02:00
if ( ! is_object ( @ $GLOBALS [ 'egw' ])) // called from outside EGw ==> setup
2008-08-20 08:04:28 +02:00
{
include ( './inc/functions.inc.php' );
@ set_time_limit ( 0 );
// Check header and authentication
if ( ! $GLOBALS [ 'egw_setup' ] -> auth ( 'Config' ))
2004-10-16 01:06:34 +02:00
{
2008-08-20 08:04:28 +02:00
Header ( 'Location: index.php' );
2004-10-16 01:06:34 +02:00
exit ;
}
2008-08-20 08:04:28 +02:00
// Does not return unless user is authorized
$GLOBALS [ 'egw_setup' ] -> loaddb ();
$tpl_root = $GLOBALS [ 'egw_setup' ] -> html -> setup_tpl_dir ( 'setup' );
$self = 'db_backup.php' ;
2011-01-20 23:17:06 +01:00
$is_setup = true ;
2008-08-20 08:04:28 +02:00
}
2016-02-20 21:27:17 +01:00
$db_backup = new Api\Db\Backup ();
2016-05-09 11:15:48 +02:00
$asyncservice = new Api\Asyncservice ();
2008-08-20 08:04:28 +02:00
// download a backup, has to be before any output !!!
2021-10-06 16:07:47 +02:00
if ( ! empty ( $_POST [ 'download' ]))
2008-08-20 08:04:28 +02:00
{
2019-02-12 22:13:45 +01:00
$file = key ( $_POST [ 'download' ]);
2008-08-20 08:04:28 +02:00
$file = $db_backup -> backup_dir . '/' . basename ( $file ); // basename to now allow to change the dir
2022-05-05 12:47:31 +02:00
// FIRST: switch off zlib.output_compression, as this would limit downloads in size to memory_limit
ini_set ( 'zlib.output_compression' , 0 );
// SECOND: end all active output buffering
while ( ob_end_clean ()) {}
2016-05-01 17:56:49 +02:00
Api\Header\Content :: type ( basename ( $file ));
2011-02-25 14:13:40 +01:00
readfile ( $file );
2008-08-20 08:04:28 +02:00
exit ;
}
2016-05-01 17:56:49 +02:00
$setup_tpl = new Framework\Template ( $tpl_root );
2008-08-20 08:04:28 +02:00
$setup_tpl -> set_file ( array (
'T_head' => 'head.tpl' ,
'T_footer' => 'footer.tpl' ,
'T_db_backup' => 'db_backup.tpl' ,
));
2016-05-01 17:56:49 +02:00
$setup_tpl -> set_var ( 'hidden_vars' , Api\Html :: input_hidden ( 'csrf_token' , Api\Csrf :: token ( __FILE__ )));
2014-05-01 08:26:09 +02:00
// check CSRF token for POST requests with any content (setup uses empty POST to call it's modules!)
if ( $_SERVER [ 'REQUEST_METHOD' ] == 'POST' && $_POST )
{
2016-03-05 15:02:13 +01:00
Api\Csrf :: validate ( $_POST [ 'csrf_token' ], __FILE__ );
2014-05-01 08:26:09 +02:00
}
2008-08-20 08:04:28 +02:00
$setup_tpl -> set_block ( 'T_db_backup' , 'schedule_row' , 'schedule_rows' );
$setup_tpl -> set_block ( 'T_db_backup' , 'set_row' , 'set_rows' );
$setup_tpl -> set_var ( 'stage_title' , $stage_title = lang ( 'DB backup and restore' ));
$setup_tpl -> set_var ( 'stage_desc' , lang ( 'This program lets you backup your database, schedule a backup or restore it.' ));
$setup_tpl -> set_var ( 'error_msg' , '' );
$bgcolor = array ( '#DDDDDD' , '#EEEEEE' );
if ( is_object ( $GLOBALS [ 'egw_setup' ] -> html ))
{
$GLOBALS [ 'egw_setup' ] -> html -> show_header ( $stage_title , False , 'config' , $GLOBALS [ 'egw_setup' ] -> ConfigDomain . '(' . $GLOBALS [ 'egw_domain' ][ $GLOBALS [ 'egw_setup' ] -> ConfigDomain ][ 'db_type' ] . ')' );
}
else
{
$setup_tpl -> set_block ( 'T_db_backup' , 'setup_header' );
$setup_tpl -> set_var ( 'setup_header' , '' );
$GLOBALS [ 'egw_info' ][ 'flags' ][ 'app_header' ] = $stage_title ;
2016-05-14 21:26:36 +02:00
echo $GLOBALS [ 'egw' ] -> framework -> header ();
echo $GLOBALS [ 'egw' ] -> framework -> navbar ();
2010-08-15 17:46:23 +02:00
$run_in_egw = true ;
2008-08-20 08:04:28 +02:00
}
2009-08-27 14:46:12 +02:00
// save backup housekeeping settings
if ( $_POST [ 'save_backup_settings' ])
{
$matches = array ();
2020-05-12 17:30:55 +02:00
preg_match ( '/^\d*$/' , $_POST [ 'backup_mincount' ], $matches );
$minCount = ( int ) $matches [ 0 ];
2011-01-20 23:17:06 +01:00
$filesBackup = $_POST [ 'backup_files' ] === 'backup_files' ;
2020-05-12 17:30:55 +02:00
if ( empty ( $minCount ) && $matches [ 0 ] != '0' )
2009-08-27 14:46:12 +02:00
{
2009-08-27 15:14:54 +02:00
$minCount = 0 ;
2009-08-27 14:46:12 +02:00
$setup_tpl -> set_var ( 'error_msg' , htmlspecialchars ( lang ( " '%1' must be integer " , lang ( " backup min count " ))));
}
2011-01-20 23:17:06 +01:00
$db_backup -> saveConfig ( $minCount , $is_setup ? ( boolean ) $filesBackup : null );
if ( is_int ( $minCount ) && $minCount > 0 )
2009-08-27 15:14:54 +02:00
{
2009-08-27 14:46:12 +02:00
$cleaned_files = array ();
/* Remove old backups. */
2009-08-28 13:46:07 +02:00
$db_backup -> housekeeping ( $cleaned_files );
2009-08-27 14:46:12 +02:00
foreach ( $cleaned_files as $file )
{
echo '<div align="center">' . lang ( 'entry has been deleted sucessfully' ) . ': ' . $file . " </div> \n " ;
}
}
}
2012-03-27 13:20:08 +02:00
if ( $_POST [ 'mount' ])
{
2016-05-01 17:56:49 +02:00
Vfs :: $is_root = true ;
2012-03-27 13:20:08 +02:00
echo '<div align="center">' .
2016-05-01 17:56:49 +02:00
( Vfs :: mount ( 'filesystem://default' . $db_backup -> backup_dir . '?group=Admins&mode=070' , '/backup' , false ) ?
2012-03-27 13:20:08 +02:00
lang ( 'Backup directory %1 mounted as %2' , $db_backup -> backup_dir , '/backup' ) :
lang ( 'Failed to mount Backup directory!' )) .
" </div> \n " ;
2016-05-01 17:56:49 +02:00
Vfs :: $is_root = false ;
2012-03-27 13:20:08 +02:00
}
2008-08-20 08:04:28 +02:00
// create a backup now
if ( $_POST [ 'backup' ])
{
if ( is_resource ( $f = $db_backup -> fopen_backup ()))
2004-10-16 01:06:34 +02:00
{
2019-02-18 13:41:42 +01:00
echo '<p align="center">' . lang ( 'backup started, this might take a few minutes ...' ) . " </p> \n " ;
$starttime = microtime ( true );
2008-08-20 08:04:28 +02:00
$db_backup -> backup ( $f );
2009-08-27 14:46:12 +02:00
if ( is_resource ( $f ))
fclose ( $f );
2019-02-18 13:41:42 +01:00
$setup_tpl -> set_var ( 'error_msg' , lang ( 'backup finished' ) . ': ' . number_format ( microtime ( true ) - $starttime , 1 ) . 's' );
2009-08-27 14:46:12 +02:00
/* Remove old backups. */
$cleaned_files = array ();
2009-08-28 13:46:07 +02:00
$db_backup -> housekeeping ( $cleaned_files );
2009-08-27 14:46:12 +02:00
foreach ( $cleaned_files as $file )
{
echo '<div align="center">' . lang ( 'entry has been deleted sucessfully' ) . ': ' . $file . " </div> \n " ;
}
2004-10-16 01:06:34 +02:00
}
else
{
2008-08-20 08:04:28 +02:00
$setup_tpl -> set_var ( 'error_msg' , $f );
2004-10-16 01:06:34 +02:00
}
2008-08-20 08:04:28 +02:00
}
$setup_tpl -> set_var ( 'backup_now_button' , '<input type="submit" name="backup" title="' . htmlspecialchars ( lang ( " back's up your DB now, this might take a few minutes " )) . '" value="' . htmlspecialchars ( lang ( 'backup now' )) . '" />' );
$setup_tpl -> set_var ( 'upload' , '<input type="file" name="uploaded" /> ' .
'<input type="submit" name="upload" value="' . htmlspecialchars ( lang ( 'upload backup' )) . '" title="' . htmlspecialchars ( lang ( " uploads a backup to the backup-dir, from where you can restore it " )) . '" />' );
2009-08-27 14:46:12 +02:00
$setup_tpl -> set_var ( 'backup_mincount' , '<input type="text" name="backup_mincount" value="' . $db_backup -> backup_mincount . '" size="3" maxlength="3"/>' );
2011-01-20 23:17:06 +01:00
$setup_tpl -> set_var ( 'backup_files' , '<input type="checkbox" name="backup_files" value="backup_files"' .
( $db_backup -> backup_files ? ' checked="true"' : '' ) .
// do NOT allow to change "backup files" outside of setup
( $is_setup ? '' : ' disabled="true" title="' . htmlspecialchars ( lang ( 'Can only be change via Setup!' )) . '"' ) . '/>' );
2009-08-27 14:46:12 +02:00
$setup_tpl -> set_var ( 'backup_save_settings' , '<input type="submit" name="save_backup_settings" value="' . htmlspecialchars ( lang ( 'save' )) . '" />' );
2012-03-27 13:20:08 +02:00
$setup_tpl -> set_var ( 'backup_mount' , '<input type="submit" name="mount" value="' . htmlspecialchars ( lang ( 'Mount backup directory to %1' , '/backup' )) . '" />' );
2004-10-16 01:06:34 +02:00
2008-08-20 08:04:28 +02:00
if ( $_POST [ 'upload' ] && is_array ( $_FILES [ 'uploaded' ]) && ! $_FILES [ 'uploaded' ][ 'error' ] &&
is_uploaded_file ( $_FILES [ 'uploaded' ][ 'tmp_name' ]))
{
move_uploaded_file ( $_FILES [ 'uploaded' ][ 'tmp_name' ], $db_backup -> backup_dir . '/' . $_FILES [ 'uploaded' ][ 'name' ]);
2004-10-26 14:59:15 +02:00
2014-10-30 16:18:59 +01:00
$md5 = ', md5=' . md5_file ( $db_backup -> backup_dir . '/' . $_FILES [ 'uploaded' ][ 'name' ]);
$md5 .= ', sha1=' . sha1_file ( $db_backup -> backup_dir . '/' . $_FILES [ 'uploaded' ][ 'name' ]);
2008-08-20 08:04:28 +02:00
$setup_tpl -> set_var ( 'error_msg' , lang ( " succesfully uploaded file %1 " , $_FILES [ 'uploaded' ][ 'name' ] . ', ' .
2021-04-01 14:34:19 +02:00
sprintf ( '%3.1f MB (%d)' , $_FILES [ 'uploaded' ][ 'size' ] / ( 1024 * 1024 ), $_FILES [ 'uploaded' ][ 'size' ]) . $md5 ));
2008-08-20 08:04:28 +02:00
}
// delete a backup
2021-10-06 16:07:47 +02:00
if ( ! empty ( $_POST [ 'delete' ]))
2008-08-20 08:04:28 +02:00
{
2019-02-12 22:13:45 +01:00
$file = key ( $_POST [ 'delete' ]);
2008-08-20 08:04:28 +02:00
$file = $db_backup -> backup_dir . '/' . basename ( $file ); // basename to not allow to change the dir
if ( unlink ( $file )) $setup_tpl -> set_var ( 'error_msg' , lang ( " backup '%1' deleted " , $file ));
}
// rename a backup
2021-10-06 16:07:47 +02:00
if ( ! empty ( $_POST [ 'rename' ]))
2008-08-20 08:04:28 +02:00
{
2019-02-12 22:13:45 +01:00
$file = key ( $_POST [ 'rename' ]);
2008-08-20 08:04:28 +02:00
$new_name = $_POST [ 'new_name' ][ $file ];
if ( ! empty ( $new_name ))
2004-10-16 01:06:34 +02:00
{
2009-08-27 14:46:12 +02:00
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 ;
2004-10-22 11:22:29 +02:00
$file = $db_backup -> backup_dir . '/' . basename ( $file ); // basename to not allow to change the dir
2008-08-20 08:04:28 +02:00
$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 ;
if ( rename ( $file , $new_file )) $setup_tpl -> set_var ( 'error_msg' , lang ( " backup '%1' renamed to '%2' " , basename ( $file ), basename ( $new_file )));
}
}
// restore a backup
2021-10-06 16:07:47 +02:00
if ( ! empty ( $_POST [ 'restore' ]))
2008-08-20 08:04:28 +02:00
{
2019-02-12 22:13:45 +01:00
$file = key ( $_POST [ 'restore' ]);
2008-08-20 08:04:28 +02:00
$file = $db_backup -> backup_dir . '/' . basename ( $file ); // basename to not allow to change the dir
if ( is_resource ( $f = $db_backup -> fopen_backup ( $file , true )))
2004-10-16 01:06:34 +02:00
{
2008-08-20 08:04:28 +02:00
echo '<p align="center">' . lang ( 'restore started, this might take a few minutes ...' ) . " </p> \n " . str_repeat ( ' ' , 4096 );
2012-06-10 14:38:35 +02:00
$start = time ();
2010-08-19 10:07:06 +02:00
$db_backup -> restore ( $f , true , $file ); // allways convert to current system charset on restore
2012-06-10 14:38:35 +02:00
$setup_tpl -> set_var ( 'error_msg' , lang ( " backup '%1' restored " , $file ) . ' (' . ( time () - $start ) . ' s)' );
2010-08-15 17:46:23 +02:00
if ( $run_in_egw )
{
// updating the backup
$cmd = new setup_cmd_update ( $GLOBALS [ 'egw' ] -> session -> account_domain ,
$GLOBALS [ 'egw_info' ][ 'server' ][ 'header_admin_user' ] = 'admin' ,
$GLOBALS [ 'egw_info' ][ 'server' ][ 'header_admin_password' ] = uniqid ( 'pw' , true ), false , true );
echo $cmd -> run () . " \n " ;
2016-05-01 17:56:49 +02:00
echo '<h3>' . lang ( 'You should %1log out%2 and in again, to update your current session!' , '<a href="' . Egw :: link ( '/logout.php' ) . '" target="_parent">' , '</a>' ) . " </h3> \n " ;
2010-08-15 17:46:23 +02:00
}
2004-10-16 01:06:34 +02:00
}
2008-08-20 08:04:28 +02:00
else
2004-10-16 01:06:34 +02:00
{
2008-08-20 08:04:28 +02:00
$setup_tpl -> set_var ( 'error_msg' , $f );
}
}
// create a new scheduled backup
2021-10-06 16:07:47 +02:00
if ( ! empty ( $_POST [ 'schedule' ]))
2008-08-20 08:04:28 +02:00
{
$asyncservice -> set_timer ( $_POST [ 'times' ], 'db_backup-' . implode ( ':' , $_POST [ 'times' ]), 'admin.admin_db_backup.do_backup' , '' );
}
// cancel a scheduled backup
2021-10-06 16:07:47 +02:00
if ( ! empty ( $_POST [ 'cancel' ]) && is_array ( $_POST [ 'cancel' ]))
2008-08-20 08:04:28 +02:00
{
2019-02-12 22:13:45 +01:00
$id = key ( $_POST [ 'cancel' ]);
2008-08-20 08:04:28 +02:00
$asyncservice -> cancel_timer ( $id );
}
// list scheduled backups
if (( $jobs = $asyncservice -> read ( 'db_backup-%' )))
{
foreach ( $jobs as $job )
2004-10-16 01:06:34 +02:00
{
2008-08-20 08:04:28 +02:00
$setup_tpl -> set_var ( $job [ 'times' ]);
$setup_tpl -> set_var ( 'next_run' , date ( 'Y-m-d H:i' , $job [ 'next' ]));
$setup_tpl -> set_var ( 'actions' , '<input type="submit" name="cancel[' . $job [ 'id' ] . ']" value="' . htmlspecialchars ( lang ( 'delete' )) . '" />' );
$setup_tpl -> parse ( 'schedule_rows' , 'schedule_row' , true );
}
}
// input-fields to create a new scheduled backup
foreach ( $times = array ( 'year' => '*' , 'month' => '*' , 'day' => '*' , 'dow' => '2-6' , 'hour' => 3 , 'min' => 0 ) as $name => $default )
{
$setup_tpl -> set_var ( $name , '<input name="times[' . $name . ']" size="5" value="' . $default . '" />' );
}
$setup_tpl -> set_var ( 'next_run' , ' ' );
$setup_tpl -> set_var ( 'actions' , '<input type="submit" name="schedule" value="' . htmlspecialchars ( lang ( 'schedule' )) . '" />' );
$setup_tpl -> parse ( 'schedule_rows' , 'schedule_row' , true );
// listing the availible backup sets
$setup_tpl -> set_var ( 'backup_dir' , $db_backup -> backup_dir );
$setup_tpl -> set_var ( 'set_rows' , '' );
$handle = @ opendir ( $db_backup -> backup_dir );
$files = array ();
while ( $handle && ( $file = readdir ( $handle )))
{
if ( $file != '.' && $file != '..' )
2004-10-16 01:06:34 +02:00
{
2010-04-20 16:06:26 +02:00
$files [ $file ] = filectime ( $db_backup -> backup_dir . '/' . $file );
2004-10-16 01:06:34 +02:00
}
2008-08-20 08:04:28 +02:00
}
if ( $handle ) closedir ( $handle );
2004-10-16 01:06:34 +02:00
2010-04-20 16:06:26 +02:00
arsort ( $files );
foreach ( $files as $file => $ctime )
2008-08-20 08:04:28 +02:00
{
$size = filesize ( $db_backup -> backup_dir . '/' . $file );
2004-10-16 01:06:34 +02:00
$setup_tpl -> set_var ( array (
2008-08-20 08:04:28 +02:00
'filename' => $file ,
2010-04-20 16:06:26 +02:00
'mod' => date ( 'Y-m-d H:i' , $ctime ),
2021-04-01 14:34:19 +02:00
'size' => sprintf ( '%3.1f MB (%d)' , $size / ( 1024 * 1024 ), $size ),
2008-08-20 08:04:28 +02:00
'actions' => '<input type="submit" name="download[' . $file . ']" value="' . htmlspecialchars ( lang ( 'download' )) . '" /> ' . " \n " .
'<input type="submit" name="delete[' . $file . ']" value="' . htmlspecialchars ( lang ( 'delete' )) . '" onclick="return confirm(\'' .
htmlspecialchars ( lang ( 'Confirm to delete this backup?' )) . '\');" /> ' . " \n " .
'<input name="new_name[' . $file . ']" value="" size="15" /><input type="submit" name="rename[' . $file . ']" value="' . htmlspecialchars ( lang ( 'rename' )) . '" /> ' . " \n " .
'<input type="submit" name="restore[' . $file . ']" value="' . htmlspecialchars ( lang ( 'restore' )) . '" onclick="return confirm(\'' .
htmlspecialchars ( lang ( 'Restoring a backup will delete/replace all content in your database. Are you sure?' )) . '\');" />' ,
2004-10-16 01:06:34 +02:00
));
2008-08-20 08:04:28 +02:00
$setup_tpl -> parse ( 'set_rows' , 'set_row' , true );
}
$setup_tpl -> set_var ( array (
'lang_scheduled_backups' => lang ( 'scheduled backups' ),
'lang_year' => lang ( 'year' ),
'lang_month' => lang ( 'month' ),
'lang_day' => lang ( 'day' ),
'lang_dow' => lang ( 'day of week<br />(0-6, 0=sunday)' ),
'lang_hour' => lang ( 'hour (0-24)' ),
'lang_minute' => lang ( 'minute' ),
'lang_next_run' => lang ( 'next run' ),
'lang_actions' => lang ( 'actions' ),
'lang_backup_sets' => lang ( 'backup sets' ),
2009-08-27 14:46:12 +02:00
'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)' ),
2008-08-20 08:04:28 +02:00
'lang_filename' => lang ( 'filename' ),
'lang_date' => lang ( 'created' ),
2010-04-20 16:06:26 +02:00
'lang_mod' => lang ( 'modified' ),
2008-08-20 08:04:28 +02:00
'lang_size' => lang ( 'size' ),
));
$setup_tpl -> set_var ( 'self' , $self );
$setup_tpl -> pparse ( 'out' , 'T_db_backup' );
2010-08-15 17:46:23 +02:00
if ( $run_in_egw )
{
2016-05-14 21:26:36 +02:00
echo $GLOBALS [ 'egw' ] -> framework -> footer ();
2010-08-15 17:46:23 +02:00
}
else
2008-08-20 08:04:28 +02:00
{
$GLOBALS [ 'egw_setup' ] -> html -> show_footer ();
2022-05-05 12:47:31 +02:00
}