|
Server : Apache/2.4.62 System : FreeBSD fbsdweb2.web.rcn.net 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64 User : www ( 80) PHP Version : 8.3.8 Disable Function : NONE Directory : /domains/compasssysweb/calendar/CalciumDir39/Operation/ |
Upload File : |
# Copyright 2002-2003, Fred Steinberg, Brown Bear Software
# Perform some maintenance on possibly broken databases.
package SysMaintenance;
use strict;
use CGI (':standard');
use vars ('@ISA');
@ISA = ('Operation');
sub perform {
my $self = shift;
my ($save, $cancel) = $self->getParams (qw (Save Cancel));
my $i18n = $self->I18N;
my $prefs = $self->prefs;
my $message;
if ($cancel or $self->calendarName) {
print redirect ($self->makeURL ({Op => 'SysAdminPage'}));
return;
}
if ($save) {
my %calFixes;
my @calendars = sort {lc($a) cmp lc($b)} MasterDB->getAllCalendars;
# First, if Calendar datafiles exist but calendar not in Master,
# add it to Master.
my $dataDir = Defines->baseDirectory . '/data';
opendir (DIR, $dataDir) or die "Error: Can't read dir: $dataDir: $!\n";
my @files = readdir(DIR);
closedir DIR;
my (%events, %prefs, %dbm);
foreach (@files) {
next unless /^(.*)\.(Events|Preferences|dbm)$/;
$events{$1}++ if ($2 eq 'Events');
$prefs{$1}++ if ($2 eq 'Preferences');
$dbm{$1}++ if ($2 eq 'dbm');
}
my $isDBM = Defines->databaseType eq 'DBM';
my @calNamesByFile;
if ($isDBM) {
@calNamesByFile = keys %dbm;
} else {
@calNamesByFile = keys %events;
}
my @reAddedCalendars;
foreach my $cal (sort @calNamesByFile) {
next if (!$isDBM and !$prefs{$cal});
next if (grep {$cal eq $_} @calendars);
push @reAddedCalendars, $cal;
MasterDB->_addNewCalendar ($cal);
}
# Next, ensure calendars listed in Master actually exist. If not,
# remove from Master list...
my (%calendars, @missingFiles);
foreach (@calendars) {
my $db = Database->new ($_);
if ($$db->{Imp}->dbExists) { # Danger Will Robinson!
$calendars{$_} = $db;
next;
}
# Datafiles do not exist
push @missingFiles, $_;
# MasterDB->deleteCalendar dies since files are gone; so, do
# what's in there here
AddIn->removeCalendarDir ($db);
# Delete entries in reminder file
if (Defines->mailEnabled) {
require Calendar::Mail::MailReminder;
MailReminder->deleteAllForCalendar ($_);
}
# Delete from Master list
my $incHash = MasterDB->new->getPreferences ('Includes');
delete $incHash->{$_};
MasterDB->new->setPreferences ({'Includes' => $incHash});
}
#...and remove missing cals from existing calendars' include lists
if (@missingFiles) {
while (my ($name, $db) = each %calendars) {
my $prefs = $db->getPreferences;
my $includes = $prefs->{Includes};
my $changed;
foreach (@missingFiles) {
if ($includes && defined $includes->{$_}) {
delete $includes->{$_};
$changed++;
}
}
$db->setPreferences ({Includes => $includes}) if ($changed);
}
}
@calendars = sort {lc($a) cmp lc($b)} keys %calendars;
# Check each database for events w/duplicate IDs; only can happen
# for repeaters.
foreach my $calName (@calendars) {
my $db = Database->new ($calName);
my $regHash = $db->getAllRegularEvents;
my $repeats = $db->getAllRepeatingEvents;
my %idMap;
foreach my $event (@$repeats) {
my $id = $event->id;
if (!$idMap{$id}) {
$idMap{$id} = $event;
} else {
my ($deleted, $date) = $db->getEventById ($id);
while ($deleted) {
$db->insertEvent ($deleted); # gets new id
$db->deleteEvent ('', $id, 'all');
$idMap{$deleted->id} = $deleted;
($deleted, $date) = $db->getEventById ($id);
}
$calFixes{$calName}++;
}
}
foreach my $date (keys %$regHash) {
foreach (@{$regHash->{$date}}) {
next unless ($idMap{$_->id});
# ID found, delete it, re-insert to get new ID
$db->deleteRegularEvent ($date, $_->id);
$db->insertEvent ($_, $date);
$calFixes{$calName}++;
}
}
}
# Set up message to display
$message = '';
if (@reAddedCalendars) {
$message = 'These calendars have data files, but were not in ' .
'the Master list. ' .
"They've been re-added.<br>";
$message .= join ', ', @reAddedCalendars;
$message = "<p>$message</p>";
}
if (@missingFiles) {
$message = 'These calendars were in the Master list, ' .
"but no data files were found. They've been
removed.<br>";
$message .= join ', ', @missingFiles;
$message = "<p>$message</p>";
}
while (my ($cal, $count) = each %calFixes) {
next unless $count;
$message .= "<p>$cal - fixed ID problem for $count events<br></p>";
}
$message = 'No problems found.' unless $message;
$message .= '<hr width="50%">';
}
# And display (or re-display) the form
print header;
print start_html ('-title' => $i18n->get ('System Maintenance'),
'-bgcolor' => 'white');
print GetHTML->SysAdminHeader ($i18n, 'System Maintenance', 1);
print '<center>';
print ("<br><b><big>$message</big></b>") if $message;
print h3 qq {<p>This will check your datafiles for possible problems, and
repair them.</p>};
print h3 qq {You normally shouldn't need to do this, unless instructed
to by tech support.}; # '
print qq {(But it won't hurt anything.)}; # '
print startform;
print submit (-name => 'Save',
-value => $i18n->get ('Check and Repair'));
print ' ';
print '</center>';
print '<hr>';
print submit (-name => 'Cancel',
-value => $i18n->get ('Back'));
print hidden (-name => 'Op', -value => __PACKAGE__);
print endform;
print end_html;
}
sub auditString {
my ($self, $short) = @_;
return unless $self->{audit_formsaved};
my $summary = $self->SUPER::auditString ($short);
return $summary;
}
# We need to do some special stuff for DBM files.
package Database;
sub deleteRegularEvent {
my ($self, $date, $id) = @_;
$$self->{'Imp'}->deleteRegularEvent ($date, $id);
}
package DB_DBM;
sub deleteRegularEvent {
my ($self, $date, $eventID) = @_;
$self->{db}->openDatabase ('readwrite');
my @eventList = $self->_getRegularEvents ($date);
my $i;
for ($i=0; $i<@eventList; $i++) {
last if ($eventList[$i]->id == $eventID);
}
# If we found it, delete it
if ($i < @eventList) {
splice @eventList, $i, 1;
$self->_setRegularEvents ($date, @eventList);
}
$self->{db}->closeDatabase;
}
package DB_Serialize;
sub deleteRegularEvent {
my ($self, $date, $id) = @_;
$self->deleteEvent ($date, $id);
}
1;