initial commit of file from CVS for smeserver-userpanels on Sat Sep 7 21:13:20 AEST 2024
This commit is contained in:
552
root/etc/e-smith/web/functions/userpanel-userbackup
Normal file
552
root/etc/e-smith/web/functions/userpanel-userbackup
Normal file
@@ -0,0 +1,552 @@
|
||||
#!/usr/bin/perl -wT
|
||||
#----------------------------------------------------------------------
|
||||
# heading : Your Settings
|
||||
# description : Data Backup
|
||||
# longdesc : backup user data
|
||||
# navigation : 100 200
|
||||
#
|
||||
# Copyright (c) 2001 Mitel Networks Corporation
|
||||
# 2002-5 Stephen Noble <support@dungog.net>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
package esmith;
|
||||
|
||||
use strict;
|
||||
use CGI ':all';
|
||||
use CGI::Carp qw(fatalsToBrowser);
|
||||
|
||||
use esmith::cgi;
|
||||
use esmith::config;
|
||||
use esmith::util;
|
||||
use esmith::db;
|
||||
use esmith::lockfile;
|
||||
|
||||
sub showInitial ($$);
|
||||
sub performAndShowResult ($);
|
||||
sub desktopBackup ();
|
||||
sub desktopRestore ();
|
||||
sub desktopVerify ();
|
||||
sub performDesktopRestore ($);
|
||||
sub performDesktopVerify ($);
|
||||
sub performDiskUsage ($);
|
||||
|
||||
BEGIN
|
||||
{
|
||||
# Clear PATH and related environment variables so that calls to
|
||||
# external programs do not cause results to be tainted. See
|
||||
# "perlsec" manual page for details.
|
||||
|
||||
$ENV {'PATH'} = '';
|
||||
$ENV {'SHELL'} = '/bin/bash';
|
||||
delete $ENV {'ENV'};
|
||||
}
|
||||
|
||||
esmith::util::setRealToEffective ();
|
||||
|
||||
my %conf;
|
||||
tie %conf, 'esmith::config';
|
||||
|
||||
my %accounts;
|
||||
tie %accounts, 'esmith::config', '/home/e-smith/db/accounts';
|
||||
|
||||
my $acctName = $ENV{'REMOTE_USER'};
|
||||
|
||||
if ($acctName =~ /^([a-z][\-\_\.a-z0-9]*)$/)
|
||||
{
|
||||
$acctName = $1;
|
||||
}
|
||||
|
||||
my @directories = ("/home/e-smith/files/users/$acctName/");
|
||||
|
||||
|
||||
# Unbuffer standard output so that files and directories are listed as
|
||||
# they are restored
|
||||
$| = 1;
|
||||
|
||||
# Store away current gid of 'www' group.
|
||||
my $www_gid = getgrnam("www");
|
||||
|
||||
#------------------------------------------------------------
|
||||
# examine state parameter and display the appropriate form
|
||||
#------------------------------------------------------------
|
||||
|
||||
my $q = new CGI;
|
||||
|
||||
if (! grep (/^state$/, $q->param))
|
||||
{
|
||||
showInitial ($q, '');
|
||||
}
|
||||
elsif ($q->param ('state') eq "perform")
|
||||
{
|
||||
performAndShowResult ($q);
|
||||
}
|
||||
elsif ($q->param ('state') eq "desktop-restore")
|
||||
{
|
||||
performDesktopRestore($q);
|
||||
}
|
||||
elsif ($q->param ('state') eq "desktop-verify")
|
||||
{
|
||||
performDesktopVerify($q);
|
||||
}
|
||||
elsif ($q->param ('state') eq "diskUsage")
|
||||
{
|
||||
performDiskUsage ($q);
|
||||
}
|
||||
else
|
||||
{
|
||||
esmith::cgi::genStateError ($q, \%conf);
|
||||
}
|
||||
|
||||
exit (0);
|
||||
|
||||
#------------------------------------------------------------
|
||||
# subroutine to display initial form
|
||||
#------------------------------------------------------------
|
||||
|
||||
sub showInitial ($$)
|
||||
{
|
||||
my ($q, $msg) = @_;
|
||||
|
||||
if ($msg eq '')
|
||||
{
|
||||
esmith::cgi::genHeaderNonCacheable ($q, \%conf,
|
||||
'Backup or restore user data');
|
||||
}
|
||||
else
|
||||
{
|
||||
esmith::cgi::genHeaderNonCacheable
|
||||
($q, \%conf, 'Operation status report');
|
||||
|
||||
print $q->p ($msg);
|
||||
print $q->hr;
|
||||
}
|
||||
|
||||
|
||||
print $q->p (
|
||||
"This page allows you to create a copy of <b>your "
|
||||
. "own</b> user data files, from your home directory "
|
||||
. "and downloads it to your local desktop via your web "
|
||||
. "browser. The Verify desktop backup file option can be used to\n"
|
||||
. "view a list of files in a desktop backup file.\n");
|
||||
|
||||
print $q->p ($q->a ({href => $q->url (-absolute => 1) . "?state=diskUsage"},
|
||||
'Click here'),
|
||||
'to check/refresh the disk usage for this user shown below, it may take
|
||||
a minute the first time but should be faster afterwards.');
|
||||
|
||||
#show usage
|
||||
if ( -e "/tmp/du-$acctName" )
|
||||
{
|
||||
my $du = '0';
|
||||
|
||||
open (INF,"/tmp/du-$acctName")
|
||||
or die ("can't open du to read: $1. ");
|
||||
|
||||
while (<INF>)
|
||||
{
|
||||
($du, undef) = split(/\t/, $_);
|
||||
}
|
||||
close INF;
|
||||
|
||||
print $q->p ("When last checked with the link above your configuration "
|
||||
. "and data files totaled <b>$du</b>. Your backup will be compressed to approx. "
|
||||
. "half that size.\n");
|
||||
}
|
||||
|
||||
my %labels = (
|
||||
"desktop-backup" => "Backup to desktop",
|
||||
"desktop-restore" => "Restore from desktop",
|
||||
"desktop-verify" => "Verify desktop backup file",
|
||||
);
|
||||
|
||||
my @labels = (
|
||||
'desktop-backup',
|
||||
'desktop-restore',
|
||||
'desktop-verify',
|
||||
);
|
||||
|
||||
my $default_action = 'desktop-backup';
|
||||
|
||||
print $q->startform (-method => 'POST',
|
||||
-action => $q->url (-absolute => 1));
|
||||
|
||||
print $q->table ({border => 0, cellspacing => 0, cellpadding => 4});
|
||||
|
||||
print $q->Tr (esmith::cgi::genWidgetRow($q,"Select an action",
|
||||
$q->popup_menu (-name => 'function',
|
||||
-values => [ @labels ],
|
||||
-default => $default_action,
|
||||
-labels => \%labels)));
|
||||
|
||||
print "</table>\n";
|
||||
|
||||
print '<p>';
|
||||
|
||||
print $q->Tr (
|
||||
esmith::cgi::genButtonRow(
|
||||
$q,
|
||||
$q->submit (-name => 'action', -value => 'Perform')
|
||||
)
|
||||
);
|
||||
|
||||
print $q->hidden (
|
||||
-name => 'state',
|
||||
-override => 1,
|
||||
-default => 'perform'
|
||||
);
|
||||
|
||||
print $q->endform;
|
||||
|
||||
# print $q->p ($q->hr, $q->font ({size => "-1"}, "www.dungog.net/sme"));
|
||||
esmith::cgi::genFooter($q);
|
||||
|
||||
|
||||
print '</FONT>';
|
||||
print '</DIV>';
|
||||
print $q->end_html;
|
||||
}
|
||||
|
||||
sub performAndShowResult ($)
|
||||
{
|
||||
my ($q) = @_;
|
||||
|
||||
my $function = $q->param ('function');
|
||||
|
||||
if ($function eq 'refresh')
|
||||
{
|
||||
showInitial ($q, '');
|
||||
}
|
||||
elsif ($function eq 'desktop-backup')
|
||||
{
|
||||
desktopBackup();
|
||||
}
|
||||
elsif ($function eq 'desktop-restore')
|
||||
{
|
||||
desktopRestore();
|
||||
}
|
||||
elsif ($function eq 'desktop-verify')
|
||||
{
|
||||
desktopVerify();
|
||||
}
|
||||
else
|
||||
{
|
||||
# Unknown function - refresh the screen anyway
|
||||
showInitial ($q, 'unknown');
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
esmith::cgi::genHeaderNonCacheable ($q, \%conf,
|
||||
'X Backup or restore server data');
|
||||
print $q->p ( $function );
|
||||
esmith::cgi::genFooter ($q);
|
||||
}
|
||||
|
||||
sub desktopBackup ()
|
||||
{
|
||||
|
||||
my $directories = $q->param ('directories');
|
||||
|
||||
# Generate a header that will trigger a download and send data as
|
||||
# an octet stream.
|
||||
|
||||
print "Expires: 0\n";
|
||||
print "Content-type: application/octet-stream\n";
|
||||
print "Content-disposition: inline; filename=$acctName.tgz\n";
|
||||
print "\n";
|
||||
|
||||
open(RD,
|
||||
"/bin/tar --directory / --create @directories --file=-"
|
||||
. " | /usr/bin/gzip |");
|
||||
|
||||
while (<RD>)
|
||||
{
|
||||
print;
|
||||
}
|
||||
|
||||
close RD;
|
||||
}
|
||||
|
||||
sub desktopRestore ()
|
||||
{
|
||||
esmith::cgi::genHeaderNonCacheable ($q, \%conf,
|
||||
'Restore server configuration');
|
||||
|
||||
print $q->p (
|
||||
"This process will upload a SME Server "
|
||||
. " backup file from your "
|
||||
. "local desktop to your server and "
|
||||
. "restore the configuration and user data files.\n");
|
||||
|
||||
print $q->p (
|
||||
"Be very sure you are uploading the correct file, "
|
||||
. "files with the same name will be overwritten.\n");
|
||||
|
||||
print $q->start_multipart_form(
|
||||
-method => 'POST',
|
||||
-action => $q->url (-absolute => 1));
|
||||
|
||||
print $q->table (
|
||||
{border => 0, cellspacing => 0, cellpadding => 4},
|
||||
|
||||
esmith::cgi::genWidgetRow(
|
||||
$q,
|
||||
"Backup file to restore from",
|
||||
$q->filefield(
|
||||
-name => 'backupFile',
|
||||
-default => "$acctName.tgz",
|
||||
-size => 32)),
|
||||
|
||||
esmith::cgi::genButtonRow(
|
||||
$q,
|
||||
$q->submit(
|
||||
-name => 'action',
|
||||
-value => 'Restore')));
|
||||
|
||||
print $q->hidden(
|
||||
-name => 'state',
|
||||
-override => 1,
|
||||
-default => 'desktop-restore');
|
||||
|
||||
print $q->endform;
|
||||
|
||||
esmith::cgi::genFooter ($q);
|
||||
}
|
||||
|
||||
sub desktopVerify ()
|
||||
{
|
||||
esmith::cgi::genHeaderNonCacheable ($q, \%conf,
|
||||
'Verify desktop backup file');
|
||||
|
||||
print $q->p (
|
||||
"This option will display the names of all files\n"
|
||||
. "in a previously created desktop backup file. You\n"
|
||||
. "can use this option to verify the contents of the\n"
|
||||
. "backup file.\n"
|
||||
);
|
||||
|
||||
print $q->start_multipart_form(
|
||||
-method => 'POST',
|
||||
-action => $q->url (-absolute => 1)
|
||||
);
|
||||
|
||||
print $q->table (
|
||||
{border => 0, cellspacing => 0, cellpadding => 4},
|
||||
|
||||
esmith::cgi::genWidgetRow(
|
||||
$q,
|
||||
"Select backup file",
|
||||
$q->filefield(
|
||||
-name => 'backupFile',
|
||||
-default => "$acctName.tgz",
|
||||
-size => 32
|
||||
)
|
||||
),
|
||||
|
||||
esmith::cgi::genButtonRow(
|
||||
$q,
|
||||
$q->submit(
|
||||
-name => 'action',
|
||||
-value => 'Verify'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
print $q->hidden(
|
||||
-name => 'state',
|
||||
-override => 1,
|
||||
-default => 'desktop-verify'
|
||||
);
|
||||
|
||||
print $q->endform;
|
||||
|
||||
esmith::cgi::genFooter ($q);
|
||||
}
|
||||
|
||||
sub performDesktopRestore ($)
|
||||
{
|
||||
my ($q) = @_;
|
||||
|
||||
# Need to validate this here: $q->param ('backupFile');
|
||||
my $lock_file = "/var/lock/subsys/e-smith-restore";
|
||||
my $file_handle = &esmith::lockfile::LockFileOrReturn($lock_file);
|
||||
|
||||
unless ($file_handle)
|
||||
{
|
||||
esmith::cgi::genHeaderNonCacheable(
|
||||
$q,
|
||||
\%conf,
|
||||
"Unable to proceed with restore of server configuration"
|
||||
);
|
||||
|
||||
print $q->p (
|
||||
$q->b (
|
||||
"Another restore is in progress.",
|
||||
"Please try again later."
|
||||
)
|
||||
);
|
||||
|
||||
esmith::cgi::genFooter ($q);
|
||||
return;
|
||||
}
|
||||
|
||||
# no need to reboot after restoring users data
|
||||
#db_set_prop(\%restore, 'restore', 'state', 'running');
|
||||
#db_set_prop(\%restore, 'restore', 'start', time);
|
||||
#db_set_prop(\%conf, 'bootstrap-console', 'Run', 'yes');
|
||||
|
||||
if (open(RD, "-|"))
|
||||
{
|
||||
|
||||
#----------------------------------------
|
||||
# restore system from uploaded backup file
|
||||
#----------------------------------------
|
||||
|
||||
esmith::cgi::genHeaderNonCacheable ($q, \%conf, "Restore in progress");
|
||||
|
||||
print $q->p ("The following files and directories have been restored:");
|
||||
|
||||
print "<UL>";
|
||||
my $complete = 0;
|
||||
while (<RD>)
|
||||
{
|
||||
print "<li>$_</li>\n";
|
||||
}
|
||||
|
||||
print "</UL>";
|
||||
my $message;
|
||||
if (!close RD)
|
||||
{
|
||||
$message = "Restore failed! " .
|
||||
"There was an error in reading the backup file";
|
||||
}
|
||||
else
|
||||
{
|
||||
$message = "Restore complete";
|
||||
}
|
||||
|
||||
#db_set_prop(\%restore, 'restore', 'state', 'complete');
|
||||
#db_set_prop(\%restore, 'restore', 'finish', time);
|
||||
|
||||
&esmith::lockfile::UnlockFile($file_handle);
|
||||
|
||||
print $q->p ($q->b ($message));
|
||||
|
||||
esmith::cgi::genFooter ($q);
|
||||
}
|
||||
else
|
||||
{
|
||||
select(STDOUT);
|
||||
$| = 1;
|
||||
|
||||
my $backupFile = $q->param ('backupFile');
|
||||
|
||||
my $decodeCommand = ( $backupFile =~ /\.bak$/ ) ?
|
||||
"|/usr/bin/uudecode -o /dev/stdout" :
|
||||
"|/usr/bin/gzip -d";
|
||||
|
||||
open(WR,
|
||||
$decodeCommand
|
||||
. " | /bin/tar --directory / --extract --verbose --file=-"
|
||||
) || die ("Could not execute backup pipeline: $!\n");
|
||||
|
||||
while (<$backupFile>)
|
||||
{
|
||||
print WR;
|
||||
}
|
||||
|
||||
close WR || die("Could not decode backup file: $!\n");
|
||||
exit(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub performDesktopVerify ($)
|
||||
{
|
||||
my ($q) = @_;
|
||||
|
||||
if (open(RD, "-|"))
|
||||
{
|
||||
esmith::cgi::genHeaderNonCacheable ($q,
|
||||
\%conf, "Verify desktop backup file");
|
||||
|
||||
print $q->p
|
||||
("The following files are contained in the backup file:");
|
||||
|
||||
print "<UL>";
|
||||
|
||||
my $complete = 0;
|
||||
while (<RD>)
|
||||
{
|
||||
#$complete++ if /etc\/smbpasswd/;
|
||||
print "<li>$_</li>\n";
|
||||
}
|
||||
|
||||
print "</UL>";
|
||||
my $status = close RD ?
|
||||
($complete ?
|
||||
"Verify complete" :
|
||||
"End of list")
|
||||
: "There was an error in reading the backup file";
|
||||
print $q->p ($q->b ($status));
|
||||
|
||||
esmith::cgi::genFooter ($q);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
select(STDOUT);
|
||||
$| = 1;
|
||||
|
||||
my $backupFile = $q->param ('backupFile');
|
||||
|
||||
my $decodeCommand = ( $backupFile =~ /\.bak$/ ) ?
|
||||
"|/usr/bin/uudecode -o /dev/stdout" :
|
||||
"|/usr/bin/gzip -d";
|
||||
|
||||
open(WR,
|
||||
$decodeCommand
|
||||
. " | /bin/tar --directory / --list --file=-"
|
||||
) || die ("Could not decode backup file: $!\n");
|
||||
|
||||
while (<$backupFile>)
|
||||
{
|
||||
print WR;
|
||||
}
|
||||
|
||||
close WR;
|
||||
exit 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub performDiskUsage ($)
|
||||
{
|
||||
my ($q) = @_;
|
||||
my $acctName = $ENV{'REMOTE_USER'};
|
||||
|
||||
if ($acctName =~ /^([a-z][\-a-z0-9]*)$/)
|
||||
{
|
||||
$acctName = $1;
|
||||
}
|
||||
|
||||
system ("/sbin/e-smith/signal-event", "calc-du", "$acctName") == 0
|
||||
or die ("Error occurred while calculating disk usage.\n");
|
||||
|
||||
showInitial ($q, "");
|
||||
}
|
Reference in New Issue
Block a user