|
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 2003-2003, Fred Steinberg, Brown Bear Software
# Operation::MultiCal - Operation that deals with multiple calendars
package Operation::MultiCal;
use strict;
use vars ('@ISA');
@ISA = ('Operation');
sub new {
my $class = shift;
my $self = $class->SUPER::new (@_);
bless $self, $class;
}
sub groupName {
my $self = shift;
defined $self->{params} ? $self->{params}->{Group} : undef;
}
# goob = Group Out Of Band
sub goob {
my $self = shift;
defined $self->{params} ? $self->{params}->{GOOB} : undef;
}
sub goobLabel {
my $self = shift;
return unless $self->goob;
return $self->I18N->get ('for all calendars')
if ($self->goob eq 'all');
return $self->I18N->get ('for calendars not in any group')
if ($self->goob eq 'nogroup');
}
sub isMultiCal {
my $self = shift;
return (defined ($self->groupName) or $self->goob);
}
sub isSystemOp {
my $self = shift;
return undef if ($self->isMultiCal or $self->calendarName);
return 1;
}
sub cgi {
my $self = shift;
$self->{_CGI} ||= CGI->new;
return $self->{_CGI};
}
sub hiddenParams {
my $self = shift;
my $cgi = $self->cgi;
my $x = $cgi->hidden (-name => 'Op', -value => $self->opName);
$x .= $cgi->hidden (-name => 'CalendarName',
-value => $self->calendarName)
if $self->calendarName;
$x .= $cgi->hidden (-name => 'Group', -value => $self->groupName)
if $self->groupName;
$x .= $cgi->hidden (-name => 'GOOB', -value => $self->goob)
if $self->goob;
return $x;
}
# Anybody must be allowed to do MultiCal operations; must check perms when
# listing calendars, and then on a save too.
sub authenticate {
my $self = shift;
return 1 if ($self->isMultiCal);
return $self->SUPER::authenticate (@_);
}
sub makeURL {
my ($self, $params) = @_;
$params->{Group} = $self->groupName;
$params->{GOOB} = $self->goob;
return $self->SUPER::makeURL ($params);
}
# Return ref to list; which calendars from list have been selected
# (If not doing multi cals, return ref to list of single cal)
# If Master, ref to empty list
sub whichCalendars {
my $self = shift;
return $self->{WhichCalendars} if defined ($self->{WhichCalendars});
my @cals;
if ($self->isMultiCal) {
@cals = $self->cgi->param ('WhichCalendars');
} else {
@cals = ($self->calendarName);
}
$self->{WhichCalendars} = \@cals;
}
# Return ref to list of selected cals, and a preferences obj.
sub getCalsAndPrefs {
my $self = shift;
my $calendars = $self->whichCalendars;
my $preferences = $self->isMultiCal ? Preferences->new ($calendars->[0])
: $self->prefs;
return ($calendars, $preferences);
}
sub dbByName {
my ($self, $calName) = @_;
return MasterDB->new if (!defined $calName);
$self->{_DatabaseHash} ||= {};
$self->{_DatabaseHash}->{$calName} ||= Database->new ($calName);
return $self->{_DatabaseHash}->{$calName};
}
# Return list of which selected calendars we _don't_ have specified
# permissions in
sub checkPermissions {
my ($self, $username, $level) = @_;
my @noPerms;
my $calendars = $self->whichCalendars;
foreach (@$calendars) {
my $db = $self->dbByName ($_);
push @noPerms, $_
unless (Permissions->new ($db)->permitted ($username, $level));
}
return @noPerms;
}
sub relevantCalendars {
my $self = shift;
my %args = (@_);
my $group = $args{group} || $self->groupName;
my $goob = $args{goob} || $self->goob || '';
my $cals = [];
if ($goob eq 'all') { # all calendars
$cals = [MasterDB->getAllCalendars];
} elsif ($goob eq 'nogroup') {
my $ig;
($ig, $cals) = MasterDB->getCalendarsInGroup;
} elsif ($group) {
my $ig;
($cals, $ig) = MasterDB->getCalendarsInGroup ($group);
}
return $cals;
}
# HTML control to select one or more calendars
# Return HTML, or ('', 'error message') if no cals available
sub calendarSelector {
my $self = shift;
my %args = (@_);
my $cgi = $args{cgi} || $self->cgi;
my $i18n = $args{i18n} || $self->I18N;
my $user = $args{user} || $self->getUsername;
my $cals = $self->relevantCalendars;
my @theCals = sort {lc ($a) cmp lc ($b)}
grep {Permissions->new ($self->dbByName ($_))
->permitted ($user, 'Admin')}
@{$cals};
if (!@theCals) {
my $html = '<center><p>';
$html .= $cgi->font ({-color => 'red'}, $i18n->get ('Warning: '));
$html .= $i18n->get ("you don't have permission to edit any " .
'calendars in this group.') . '</p></center>';
return ('', $html);
}
my $whichCals = $cgi->scrolling_list (-name => 'WhichCalendars',
-Values => \@theCals,
-size => 5,
-multiple => 'true');
my $getPrefs = $cgi->submit (-name => 'GetPrefs',
-value => $i18n->get ('Get Settings')) .
'<br><small>' .
$i18n->get ('(Only if a single calendar is selected)') .
'</small>';
my $html = $cgi->table ({width => '90%',
align => 'center'},
$cgi->Tr ({-align => 'center'},
[$cgi->td ($i18n->get ('Apply changes to which ' .
'calendars:')),
$cgi->td ($whichCals),
$cgi->td ($getPrefs),
$cgi->td ('<hr width="75%">')]));
return $html;
}
# Return undef if ok, message otherwise
sub adminChecks {
my $self = shift;
my %args = (@_);
my $save = $args{save} || $self->getParams (qw (Save));
my $getPrefs = $args{getPrefs} || $self->getParams (qw (GetPrefs));
my $user = $args{user} || $self->getUsername;
my $i18n = $self->I18N;
if ($self->isMultiCal) {
my $calendars = $self->whichCalendars;
if ($save or $getPrefs) {
# Make sure we've got at least 1 calendar selected.
if (!@$calendars) {
$self->{audit_error} = 'no calendar selected';
return $i18n->get ('Error: no calendars selected.');
}
}
if ($getPrefs) {
if (@$calendars != 1) {
my $message = $i18n->get ('Must select exactly one calendar ' .
'to get settings.');
$self->{audit_error} = 'single calendar not selected';
return $message;
}
}
}
# If saving, (re)check permissions for all selected calendars
if ($save) {
my @noPerms = $self->checkPermissions ($user, 'Admin');
if (@noPerms) {
my $mess;
if (@noPerms > 1) {
$mess= $i18n->get ('Error - no Admin permission for ' .
'calendars: ');
} else {
$mess= $i18n->get ('Error - no Admin permission for ' .
'calendar: ');
}
$mess .= join ',', sort {lc ($a) cmp lc ($b)} @noPerms;
return $mess;
}
}
return undef;
}
# HTML control for "change"/"ignore" toggle
sub groupToggle {
my $self = shift;
return '' unless $self->isMultiCal;
my %args = (name => undef,
bg => undef,
@_);
my $i18n = $self->I18N;
my $cgi = $self->cgi;
my $name = $args{name} || 'unnamed';
my $labels = {change => $i18n->get ('Change'),
ignore => $i18n->get ('Ignore')};
$name = $self->getOnChangeName ($name);
return $cgi->td ({-align => 'center',
-bgcolor => $args{bg}},
$cgi->popup_menu (-name => $name,
-values => ['ignore', 'change'],
-override => 1,
-labels => $labels));
}
sub getOnChange {
my ($self, $name) = @_;
my $n = $self->getOnChangeName ($name);
return "this.form.${n}.value='change'";
}
sub getOnChangeName {
my ($self, $name) = @_;
return "x${name}Toggle"; # JS doesn't like names that start with digits?
}
sub setAllJavascript {
my $self = shift;
return ('', '') unless ($self->isMultiCal);
my $i18n = $self->I18N;
my $cgi = $self->cgi;
my $jsRow = $cgi->font ({-size => -2},
$i18n->get ('Set all:') . ' <nobr>"' .
$cgi->a ({-href =>
"javascript:SetGroupToggle ('change')"},
$i18n->get ('Change')) . '" "' .
$cgi->a ({-href =>
"javascript:SetGroupToggle ('ignore')"},
$i18n->get ('Ignore')) . '"</nobr>');
my $script = q {
<SCRIPT LANGUAGE="JavaScript">
<!--
function SetGroupToggle (setTo) {
theform=document.forms[0];
for (i=0; i<theform.elements.length; i++) {
if (theform.elements[i].name.search ('Toggle\$') != -1) {
theform.elements[i].value = setTo;
}
}
}
//-->
</SCRIPT>
}; # '
return ($script, $jsRow);
}
# Remove ignored items from the prefs hash that's passed in.
# Return list of items that are _not_ ignored
sub removeIgnoredPrefs {
my $self = shift;
my %args = (map => {},
prefs => {},
@_);
my @notIgnored;
foreach my $name (keys %{$args{map}}) {
my $n = $self->getOnChangeName ($name);
if ($self->{params}->{$n} eq 'ignore') {
foreach my $pref (@{$args{map}->{$name}}) {
delete $args{prefs}->{$pref};
}
} else {
push @notIgnored, $name;
}
}
return @notIgnored;
}
# Return message to display after multi-cal modification
sub getModifyMessage {
my $self = shift;
return unless $self->isMultiCal;
my %args = (cals => [],
mods => [],
labels => {},
@_);
my $i18n = $self->I18N;
my $message = (@{$args{cals}} > 1 ? $i18n->get ('Calendars')
: $i18n->get ('Calendar'));
$message .= ': ' . join (', ', @{$args{cals}});
$message .= '<br>';
my $which = join (', ', map {$args{labels}->{$_} || $_} @{$args{mods}});
$message .= $i18n->get ("Changed Settings: ") .
($which || $i18n->get ('none - all ignored!'));
return $message;
}
sub helpNotes {
my $self = shift;
return '' unless ($self->isMultiCal);
my $i18n = $self->I18N;
my $html = $i18n->get ('MultiCal_HelpString');
return $html unless ($html eq 'MultiCal_HelpString');
$html = '<br><b>To change settings for multiple calendars:</b>';
$html .= '<ul>';
$html .= q {<li>Select one or more calendars in the list at top.
(Control-click to choose multiple calendars.)</li>};
$html .= q {<li>Make the changes you want</li>};
$html .= q {<li>Be sure the selection at far left is set to 'Change';
any item with 'Ignore' will not be modified.</li>};
$html .= q {<li>Press the 'Save' button</li>};
$html .= '</ul>';
$html .= q {<b>You can also view the current settings for a single
calendar</b>};
$html .= '<ul>';
$html .= q {<li>Select one - and only one - calendar from the list.</li>};
$html .= q {<li>Press the 'Get Settings' button.</li>};
$html .= q {<li>You can then use those settings for modifications in
that - or other - calendars.</li>};
$html .= '</ul>';
return "<small>$html</small>";
}
# Auditing
# See if we want to be audited, then create an audit obj and do it.
# This works on security classes (View, Add, Edit, Admin). Particular
# operations can override the auditType method for special case auditing (e.g.
# user login)
sub audit {
my $self = shift;
my $type = $self->auditType;
my @auditTypes;
my @cals = @{$self->whichCalendars};
push @cals, undef unless @cals; # If Master, need undef
foreach my $cal (@cals) {
my $db = $self->dbByName ($cal);
@auditTypes = $db->getAuditing ($type);
next unless @auditTypes;
$self->currentCal ($cal);
my @auditObjs = map {AuditFactory->create ($_)} @auditTypes;
foreach (@auditObjs) {
$_->perform ($self, $db);
}
}
}
# Subclasses redefine this for custom Audit Strings
sub basicAuditString {
my ($self, $short) = @_; # 'short' ignored in this default version
my ($sec, $min, $hour, $mday, $mon, $year, @etc) = localtime (time);
my $date = sprintf '%d/%.2d/%.2d %.2d:%.2d:%.2d',
$year+1900, $mon+1, $mday, $hour, $min, $sec;
my $calName = $self->currentCal;
return "$date " .
"$ENV{REMOTE_ADDR} " .
($self->getUsername || '-') . ' ' .
($calName || '-') . ' ' .
ref ($self);
}
sub auditString {
my ($self, $short) = @_;
return unless $self->{audit_formsaved};
my $line = $self->basicAuditString ($short);
my $cal = $self->currentCal;
$cal = MasterDB->new->name unless (defined $cal);
my $old = $self->{audit_info}->{$cal};
my $new = Preferences->new ($cal);
my $info;
foreach (sort keys %$old) {
my $orig = $old->{$_} || 0;
my $gnu = $new->{$_} || 0;
next if ($orig eq $gnu);
my $item = "$_: $orig -> $gnu";
if ($short) {
$item = "[$item]";
} else {
$item = "\n $item";
}
$info .= $item;
}
return unless $info; # don't report if nothing changed
return $line . $info;
}
# Auditing Stuff
# Bit of a hack so we can avoid passing it around (for auditing mostly)
sub currentCal {
my ($self, $calName) = @_;
$self->{CurrentCalendar} = $calName if (defined $calName);
$self->{CurrentCalendar};
}
sub saveForAuditing {
my ($self, $calName, $newPrefs) = @_;
my $prefs = $self->dbByName ($calName)->getPreferences;
my %orig;
foreach (keys %$newPrefs) {
next if (($newPrefs->{$_} || '') eq ($prefs->$_() || ''));
$orig{$_} = $prefs->$_();
}
$calName = MasterDB->new->name unless (defined $calName);
$self->{audit_info}->{$calName} = \%orig;
}
1;