KGRKJGETMRETU895U-589TY5MIGM5JGB5SDFESFREWTGR54TY
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 :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /domains/compasssysweb/calendar/CalciumDir39/Operation/EventNew.pm
# Copyright 1999-2003, Fred Steinberg, Brown Bear Software

# Create a New Event

package EventNew;
use strict;
use CGI;

use Calendar::Date;
use Calendar::GetHTML;
use Calendar::ValidateDate;

use vars ('@ISA');
@ISA = ('Operation');

sub perform {
    my $self = shift;
    my ($date, $eventText, $popupText, $export,
        $border, $bgColor, $fgColor, $category,
        $mailTo, $mailCC, $mailBCC, $mailText,
        $reminderTime, $reminderTime2, $reminderAddress,
        $ignoreConflict, $ignoreFuture, $editedEventID, $copying,
        $singleInstanceOfRepeater,
        $displayCal, $viewCal, $displayDate) =
                        $self->getParams (qw (Date EventText PopupText
                                              ExportPopup BorderCheckbox
                                              BackgroundColor ForegroundColor
                                              Category
                                              MailTo MailCC MailBCC
                                              MailComments MailReminder
                                              MailReminder2 ReminderAddress
                                              IgnoreTimeConflict
                                              IgnoreFutureLimit
                                              OldEventID CopyEvent
                                              SingleRepeatingInstance
                                              DisplayCal ViewCal DisplayDate));

    my $cgi = CGI->new;
    my @whichCals = $cgi->param ('WhichCalendars');
    push @whichCals, $self->calendarName unless @whichCals;

    if ($cgi->param ('Cancel')) {
        $self->{audit_formcancelled}++;
        my $theUrl = $cgi->param ('NextOp');
        print $self->redir ($theUrl);
        return;
    }

    my $action = $editedEventID ? 'Replacing' : 'Adding New';

    if ($copying) {
        $action = 'Copying';
        undef $editedEventID;
    }

    # If multi-cal enabled, ensure at least 1 calendar selected
    if ($self->getParams ('MultiCalDisplayed') and
        !$cgi->param ('WhichCalendars')) {
        my $errorMessage = $self->I18N->get ('You must select at least ' .
                                             'one calendar') . '<br>';
        $self->_errorPage ($action, $errorMessage);
        $self->{audit_error} = 'no calendar specified';
        return;
    }

    my ($eventDate, $startTime, $endTime, $timePeriod, $endDate, $dateChange,
        $errorMessage) = ValidateDate->getAndValidateDateAndTimes ($self);

    my $localDate = $eventDate - $dateChange;

    # Check for event in the past
    if ($self->prefs->NoPastEditing and $localDate < Date->new) {
        $self->_errorPage ($action,
                           $self->I18N->get ('Cannot add past event!') .
                           '<br><br>' .
                           $self->I18N->get ('This calendar does not allow ' .
                                             'creating or editing events '   .
                                             "before today's date.") .
                           '<br>');
        $self->{audit_error} = 'past event';
        return;
    }

    # Strip leading/trailing spaces from strings coming from text fields
    foreach ($eventText, $popupText, $bgColor, $fgColor,
             $mailTo, $mailCC, $mailBCC, $mailText) {
        next unless defined;
        s/^\s+//;
        s/\s+$//;
    }

    unless ($eventText) {
        $self->_errorPage ($action,
                           $self->I18N->get ('You cannot create a blank event')
                           . '<br>');
        $self->{audit_error} = 'blank event';
        return;
    }

    if ($errorMessage) {
        $self->_errorPage ($action, $errorMessage);
        $self->{audit_error} = 'bad date or time';
        return;
    }

    # if reminders specified, must have email address
    if (($reminderTime or $reminderTime2) and !$reminderAddress) {
        $self->_errorPage ($action,
                           $self->I18N->get ('You must specify an email '  .
                                             'address if Email Reminders ' .
                                             'are specified.')
                           . '<br>');
        $self->{audit_error} = 'reminder w/no address';
        return;
    }

    my ($link, $popup);

    # If the popup looks like a URL, we call it a link. Otherwise, a popup!
    # Note that this is not a very good test. But probably good enough.
    # (Basically, anything that is www.x.x, or starts http:, mailto:, ftp:,
    # etc.)
    ($popup, $link) = Event->textToPopupOrLink ($popupText);

    foreach ($bgColor, $fgColor) {
        next unless defined;
        s/\s*default\s*//i;         # If colors are 'Default', get rid of 'em
        s/\W//g;                    # And ensure there's nothing silly going on
        $_ = ('#' . $_) if /^\d+$/; # And prepend numerics with the #
    }

    $category = undef if ($category and $category eq '-');

    my ($repeatObject);

    my ($repeatType) = $self->getParams ('RepeatRadio');

    # Handle repeat stuff, maybe
    if (!$repeatType || $repeatType =~ /none/i || $repeatType eq '') {
        $repeatObject = undef;
    } else {
        my ($frequency, $period, $monthWeek, $monthMonth,
            $untilRadio, $untilYear, $untilMonth, $untilDay, $skipWeekends) =
                   $self->getParams (qw (Frequency Period MonthWeek MonthMonth
                                         RepeatUntilRadio UntilYearPopup
                                         UntilMonthPopup UntilDayPopup
                                         SkipWeekends));
        if ($repeatType =~ /ByWeek/i) {
            $period = $frequency = undef;
        } else {    # it must be Repeat Every Third Day type
            $monthWeek = $monthMonth = undef;
        }
        $repeatObject = RepeatInfo->new ($eventDate, $endDate,
                                         $period, $frequency,
                                         $monthWeek, $monthMonth,
                                         $skipWeekends);
        # If we got here from modifing a repeating event, check for exclusions
        my ($exclusionString) = $self->getParams ('ExcludedDates');
        if ($exclusionString) {
            my @excludedDates;
            my @excludedStrings = split /\s/, $exclusionString;
            foreach my $excludedDate (@excludedStrings) {
                push @excludedDates, Date->new ($excludedDate);
            }
            $repeatObject->exclusionList (\@excludedDates);
        }

        # if date was changed by timezone offset, and we're repeating by
        # particular days of the week, adjust the days. Yow!
        if ($dateChange and ref ($repeatObject->period)) {
            foreach my $day (@{$repeatObject->period}) {
                $day += $dateChange;     # 1-7
                if ($day < 1 or $day > 7) {
                    $day = $day % 7;
                    $day ||= 7;
                }
            }
        }
    }

    my $reminders = ($reminderTime || '') . ' ' . ($reminderTime2 || '');
    $reminders =~ s/^\s//;
    $reminders =~ s/\s$//;
    $reminderAddress = undef unless $reminders; # since it has a default

    # make the new event
    my $newEvent = Event->new ('text'       => $eventText,
                               'link'       => $link,
                               'popup'      => $popup,
                               'export'     => $export,
                               'startTime'  => $startTime,
                               'endTime'    => $endTime,
                               'timePeriod' => $timePeriod,
                               'repeatInfo' => $repeatObject,
                               'drawBorder' => $border,
                               'owner'      => $self->getUsername,
                               'bgColor'    => $bgColor,
                               'fgColor'    => $fgColor,
                               'category'   => $category,
                               'mailTo'     => $mailTo,
                               'mailCC'     => $mailCC,
                               'mailBCC'    => $mailBCC,
                               'mailText'   => $mailText,
                               'reminderTo' => $reminderAddress,
                               'reminderTimes' => $reminders);

    # if modifying or copying, copy subscribers
    my ($subscribers) = $self->getParams ('Subscribers');
    $newEvent->subscriptions ($subscribers) if ($subscribers);

    if (@whichCals > 1) {
        my @badFuture;
        foreach my $thisCal (@whichCals) {
            my $prefs = Preferences->new ($thisCal);
            my $vd = ValidateDate->futureCheck ($prefs, $eventDate,
                                                $endDate, $ignoreFuture);
            push @badFuture, $thisCal if $vd->isBad;
        }
        if (@badFuture) {
            $self->_errorPage ($action, "Sorry, the event is too far in the
                                        future for these calendars: " .
                                        join (', ', @badFuture));
            $self->{audit_error} = 'future limit';
            return;
        }
    } else {
        my $thisCal = $whichCals[0];
        my $prefs = Preferences->new ($thisCal);
        my $vd = ValidateDate->futureCheck ($prefs, $eventDate,
                                            $endDate, $ignoreFuture);
        if ($vd->isBad) {
            $self->_errorPage ($action, $vd->futureMessage ($self, $thisCal,
                                                            $self->I18N),
                               $vd->isWarning);
            $self->{audit_error} = 'future limit';
            return;
        }
    }

    # Make sure repeating stuff actually makes sense
    if ($repeatObject) {
        my $instances = $repeatObject->nextNOccurrences ($newEvent, 1,
                                                         $eventDate,
                                                         $self->prefs);
        unless (keys %$instances) {
            $self->_errorPage ($action,
                               $self->I18N->get ('The specified repeat ' .
                                                 'options don\'t define ' .
                                                 'any actual instances.'));
            $self->{audit_error} = 'repeating w/no instances';
            return;
        }
    }

    # If we're checking Time Conflicts and adding a repeating event, we
    # have to check on every occurrence. Ugh! Don't do "forever", though;
    # only check max of 5 years into the future.
    my $prefs = $self->prefs;
    if ($repeatObject and defined $startTime and
        $prefs->TimeConflicts !~ /allow/i) {
        my $occurences = {};
        my $endDate = $repeatObject->endDate;
        if ($repeatObject->startDate->deltaDays ($endDate) > 365*5) {
            $endDate = $repeatObject->startDate + 365*5;
        }
        $newEvent->addToDateHash ($occurences, $repeatObject->startDate,
                                  $endDate, $self->prefs);
        my (%prefs, %dbs);
        foreach my $thisCal (@whichCals) {
            $prefs{$thisCal} = Preferences->new ($thisCal);
            $dbs{$thisCal}   = Database->new ($thisCal);
        }
        foreach my $date (sort {Date->new($a) <=> Date->new($b)}
                          keys %$occurences) {
            my $dobj = Date->new ($date);
            foreach my $thisCal (@whichCals) {
                my $tc = ValidateDate->timeConflict ($dbs{$thisCal},
                                                     $prefs{$thisCal},
                                                     $dobj, $startTime,
                                                     $endTime, $editedEventID,
                                                     $ignoreConflict);
                if ($tc->isBad) {
                    $errorMessage = $tc->conflictMessage ($self,
                                                          @whichCals == 1
                                                                 ? undef
                                                                 : $thisCal);
                    $self->_errorPage ($action, $errorMessage, $tc->isWarning);
                    $self->{audit_error} = 'time conflict';
                    return;
                }
            }
        }
    } else {
        foreach my $thisCal (@whichCals) {
            my $db    = Database->new ($thisCal);
            my $prefs = Preferences->new ($thisCal);
            my $tc = ValidateDate->timeConflict ($db, $prefs, $eventDate,
                                                 $startTime, $endTime,
                                                 $editedEventID,
                                                 $ignoreConflict);
            if ($tc->isBad) {
                $errorMessage = $tc->conflictMessage ($self,
                                                      @whichCals == 1
                                                          ? undef
                                                          : $thisCal);
                $self->_errorPage ($action, $errorMessage, $tc->isWarning);
                $self->{audit_error} = 'time conflict';
                return;
            }
        }
    }

    # keep track of things in case we're auditing
    $self->{audit_calendars} = [sort {lc($a) cmp lc($b)} @whichCals];
    $self->{audit_event}     = $newEvent;
    $self->{audit_eventDate} = $eventDate;

    # Stick it in the database(s)
    foreach my $thisCal (@whichCals) {
        my $db = Database->new ($thisCal);

        # Set "tentative" flag
        if (Preferences->new ($thisCal)->TentativeSubmit and
            !Permissions->new ($db)->permitted ($self->getUsername, 'Edit')) {
            $newEvent->isTentative (1);
            $self->{audit_tentative} = $thisCal;
        } else {
            $newEvent->isTentative (0);
            $self->{audit_tentative} = undef;
        }

        if (defined $editedEventID and !$copying
            and !$singleInstanceOfRepeater) {
            $newEvent->id ($editedEventID);
            # (already deleted in EventReplace.pm)
            $db->replaceEvent ($newEvent, $eventDate, 'noDelete');
        } else {
            $db->insertEvent ($newEvent, $eventDate);
        }

        # Do auditing for `other' calendars
        if ($thisCal ne $self->calendarName) {
            my @auditTypes = $db->getAuditing ('Add');
            foreach (@auditTypes) {
                AuditFactory->create ($_)->perform ($self, $db);
            }
        }
    }

    # maybe send email notifications
    if ($mailTo or $mailCC or $mailBCC) {
        require Calendar::Mail::MailNotifier;
        MailNotifier->send ($self, $newEvent, $eventDate, $editedEventID);
    }
    # maybe remember to remind
    if (Defines->mailEnabled and $reminders) {
        require Calendar::Mail::MailReminder;
        MailReminder->add ($newEvent, $self->calendarName, $eventDate);
    }

    my $showDate;
    if (defined ($editedEventID)) {
        $showDate = $displayDate ? Date->new ($displayDate) : $eventDate;
    } else {
        $showDate = $newEvent->getDisplayDate ($eventDate,
                                               $self->prefs->Timezone);
    }

    # And redirect to the page to display.
    my $theURL;
    my $nextOp = $cgi->param ('NextOp');
    if ($nextOp ne 'ShowDay') {
        $theURL = $nextOp;
    } else {
        $theURL = $self->makeURL ({Op      => 'ShowDay',
                                   Date    => $showDate,
                                   CalendarName => $displayCal,
                                   ViewCal      => $viewCal,
                                   Splunge => time}); # needed as workaround
    }
    print $self->redir ($theURL);
}


sub _errorPage {
    my ($self, $action, $message, $isWarning) = @_;
    my $title = ($isWarning ? "Warning while $action Event"
                            : "Error $action Event");
    GetHTML->errorPage ($self->I18N,
                        header    => $self->I18N->get ($title),
                        message   => $message,
                        isWarning => $isWarning);
    return;
}

# Override audit, since we need to handle special AddTentative case
sub auditType {
    my $self = shift;
    my $type = $self->{audit_tentative} ? 'AddTentative' : 'Add';
    return $type;
}

sub auditString {
    my ($self, $short) = @_;
    return if $self->{audit_formcancelled};

    my $line = $self->SUPER::auditString ($short);
    return ($line . ' ERROR - ' . $self->{audit_error})
        if $self->{audit_error};

    my $event = $self->{audit_event};

    if ($short) {
        my $text;
        if ($event) {
            $text = $event->text;
            $text =~ s/\n/\\n/g;
            $text = $self->{audit_eventDate} . ' ' . $text;
            $text .= ' [tentative]' if $self->{audit_tentative};
        } else {
            $text = 'ERROR - ' . $self->{audit_error};
        }
        return $line . ' ' . $text;
    }

    my ($text, $extra);
    ($text     = $event->text)                        =~ s/
//g;
    ($extra    = $event->popup || $event->link || '') =~ s/
//g;
    $extra = "Popup text: $extra" if ($event->popup);
    $extra = "URL:\t$extra"       if ($event->link);

    # make a string
    my $message;
    if ($self->{audit_calendars} and @{$self->{audit_calendars}} > 1) {
        $message = "Calendar Names:\t" .
                   join (', ', @{$self->{audit_calendars}}) . "\n";
    } else {
        $message = "Calendar Name:\t" . $self->calendarName . "\n";
    }
    $message .= "Date:\t$self->{audit_eventDate}\n";
    if (defined $event->startTime) {
        $message .= "Time:\t" . $event->getTimeString ('both', $self->prefs)
                    . "\n";
    }

    $message .= "Type:\t" . $event->export . "\n\n";

    $message .= "Text:\t$text\n" . $extra . "\n\n";

    $message .= "Category:  \t" . $event->category . "\n"
        if defined $event->category;

    $message .= "Border:    \t" . ($event->drawBorder ? 'yes' : 'no') . "\n";
    $message .= "Foreground:\t" . ($event->fgColor || 'Default')      . "\n" .
                "Background:\t" . ($event->bgColor || 'Default')      . "\n";

    if ($event->isRepeating) {
        my $rep = $event->repeatInfo;
        $message .= "\nThis is a Repeating Event\n";
        $message .= "Start Date:\t" .  $rep->startDate . "\n";
        $message .= "End Date:  \t" . ($rep->endDate == Date->openFuture ?
                                                      'None' : $rep->endDate);
        $message .= "\n";
        if ($rep->period) {
            $message .= 'Every ';
            # period is either single amount, or ref to list of days of week
            if (!ref ($rep->period)) {
                my $period = $rep->period;
                $period = 'day' if ($period eq 'dayBanner');
                if ($rep->frequency == 1) {
                    $message .= $period . "\n";
                } else {
                    $message .= $rep->frequency . ' ' . $period . "s\n";
                }
            }
            else {
                my @days = map {Date->dayName ($_)} @{$rep->period};
                my @nth = (' ', 'st', 'nd', 'rd', 'th');
                my $nth = ' ';
                if ($rep->frequency > 1) {
                    $nth = $nth[$rep->frequency];
                    $nth = 'th' unless defined ($nth);
                    $nth = $rep->frequency . $nth . ' ';
                }
                $message .= $nth . (join ', ', @days) . "\n";
            }
        } else {
            my %text = (1 => '1st',
                        2 => '2nd',
                        3 => '3rd',
                        4 => '4th',
                        5 => 'last',
                        6 => 'fifth (if there is a fifth)');
            my $mw = join ', ', map {$text{$_}} @{$rep->monthWeek};

            my $day = Date->dayName ($rep->monthDay);
            my $mm = ($rep->monthMonth || 1) != 1 ? ' ' . $rep->monthMonth
                                                  : '';
            $message .= "$mw $day of every$mm month\n";
        }
        $message .= "  (Skip Weekends)\n" if $rep->skipWeekends;
    }

    my $tent = '';
    if ($self->{audit_tentative}) {
        my $owner = $event->owner || 'an anonymous user';
        $tent .= "A Event requiring approval was added by $owner.\n";
        $tent .= "Calendar: " . $self->{audit_tentative} . "\n\n";
        my $url = $self->makeURL ({FullURL      => 1,
                                   CalendarName => $self->{audit_tentative},
                                   Op           => 'ApproveEvents'});
        $tent .= "Follow this link for the approval form:\n    $url\n\n\n";
    }

    return $tent . $message . "\n\n$line";
}

1;

Anon7 - 2021