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/Calendar/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

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

package ValidateDate;
use strict;
use Calendar::Date;
use Calendar::Event;

# Return date, start time, end time, end date, error message.
# If times are ok, error message is undef
# Date and times adjusted for user timezone, if set.
sub getAndValidateDateAndTimes {
    my $className = shift;
    my ($op) = @_;

    my ($startTime, $endTime, $endDate);

    my ($startHour, $startMinute, $endHour, $endMinute,
        $startAmOrPm, $endAmOrPm, $timePeriod) =
                $op->getParams (qw (StartHourPopup StartMinutePopup
                                    EndHourPopup   EndMinutePopup
                                    StartHourRadio EndHourRadio TimePeriod));

    my $i18n = $op->I18N;
    my $milTime;

    # If Time Period specified, start with the defined times
    if (defined $timePeriod and ($timePeriod ne '-')) {
        my ($name, $start, $end, $display) =
                                 $op->prefs->getTimePeriod ($timePeriod);
        ($startTime, $endTime) = ($start, $end);
    }

    # Otherwise, see if there is a normal time specified.
    else {
        undef $timePeriod;
        # Start/End times are in range [-1..23] for hours, [-1..55] for mins.
        if (defined ($startHour) and $startHour >= 0) {
            $startAmOrPm ||= '';    # undef if military time
            $endAmOrPm   ||= '';
            $milTime = !defined ($startAmOrPm);

            $startMinute = 0 unless ($startMinute and $startMinute >= 0);
            $startTime   = ($startHour + ($startAmOrPm =~ /pm/i ? 12 : 0)) * 60
                + $startMinute;

            if ($endHour < 0) {
                $endHour = $endMinute = undef;
            } else {
                $endMinute = 0 unless ($endMinute and $endMinute > 0);
                $endHour   = 0 unless ($endHour and $endHour > 0);
                $endTime   = ($endHour + ($endAmOrPm =~ /pm/i ? 12 : 0)) * 60
                    + $endMinute;
            }
        }
    }

    # Make sure times and dates make sense.
    my $errorMessage;

    # We don't check for start < end anymore; event could go to next day.
#   if (defined $startTime && defined $endTime) {
#       if ($startTime > $endTime) {
#           $errorMessage = '<br>';
#           $errorMessage .= $i18n->get ('<b>Start Time</b> cannot be later ' .
#                                       'than <b>End Time</b>');
#           $errorMessage .= '<br>';
#           $errorMessage .= "<blockquote><table>" .
#                            "<tr><td align='right'>" .
#                                     $i18n->get ('Start Time:') . '</td>' .
#                                "<td align='right'>" .
#                                 Event->getTimeString ($startTime, $milTime) .
#                                "</td>" .
#                            "<tr><td align='right'>" .
#                                     $i18n->get ('End Time:') . '</td>' .
#                                "<td align='right'>" .
#                                 Event->getTimeString ($endTime, $milTime) .
#                            '</td></tr></table></blockquote><br><hr>';
#       }
#   }

    # Get and validate the date
    my $date;
    my ($dateYear, $dateMonth, $dateDay) =
               $op->getParams (qw (DateYearPopup DateMonthPopup DateDayPopup));
    if (Date->valid ($dateYear, $dateMonth, $dateDay)) {
        $date = Date->new ($dateYear, $dateMonth, $dateDay);
    } else {
        $errorMessage .= '<br>' . $i18n->get ("Invalid <b>Date</b>: ") .
                         $i18n->get (Date->monthName ($dateMonth)) .
                         " $dateDay, $dateYear<br>";
    }

    my ($repeatType, $untilRadio, $untilYear, $untilMonth, $untilDay) =
            $op->getParams (qw (RepeatRadio RepeatUntilRadio UntilYearPopup
                                UntilMonthPopup UntilDayPopup));
    if ($repeatType && $repeatType !~ /none/i && $repeatType ne '') {
        if ($untilRadio ne ' ') {
            $endDate = Date->openFuture();
        } else {
            if (Date->valid ($untilYear, $untilMonth, $untilDay)) {
                $endDate = Date->new ($untilYear, $untilMonth, $untilDay);
            } else {
                $errorMessage .= '<br>' .
                      $i18n->get ('Invalid <b>Repeat Until</b> Date') . ': ' .
                          $i18n->get (Date->monthName ($untilMonth)) .
                          " $untilDay, $untilYear<br>";
            }
        }

        if ($endDate && $date && ($date > $endDate)) {
            $errorMessage .= '<br>' .
                             $i18n->get ('<b>Repeat Until Date</b> cannot ' .
                                         'be before the first date of the ' .
                                         'event.') . '<br>';
            $errorMessage .= '<br>' . $i18n->get ('Event Start Date:') . ' ' .
                                        $date->pretty ($i18n) . '<br>' .
                                      $i18n->get ('Repeat Until Date:') . ' ' .
                                        $endDate->pretty ($i18n);
        }
    }

    # Convert times and dates based on timezone; always store server time,
    # so server times are returned.
    # Date is always the date startTime is on.
    my $z;
    my $dateChange = 0;
    if (defined $startTime and $z = $op->prefs->Timezone) {
        $startTime -= $z * 60;
        $endTime   -= $z * 60 if (defined $endTime);

        # If start time is yesterday or tomorrow, adjust date
        if ($startTime < 0) {
            $date -= int ($startTime/-1440) + 1;     # 1440 = 24 * 60
            $dateChange = -1;
        } elsif ($startTime >= 24*60) {
            $date += int ($startTime/1440);
            $dateChange = 1;
        }

        $startTime %= 1440;

        if (defined $endTime) {
            $endTime %= 1440;
        }
    }

    # $dateChange is -1 if we moved to yesterday, +1 if we moved to tomorrow.
    return ($date, $startTime, $endTime, $timePeriod, $endDate, $dateChange,
            $errorMessage);
}

# Assumes start < end for both
sub _timeConflict {
    my ($start, $end, $start2, $end2, $separation) = @_;
    return 0 unless defined $start;

    $end  = $start  if !defined $end;
    $end2 = $start2 if !defined $end2;

    $end  += 1440 if ($end < $start); # ends on next day
    $end2 += 1440 if ($end2 < $start2);

    return 0 if (defined ($end)  and ($end + $separation <= $start2));
    return 0 if (defined ($end2) and ($start >= $end2 + $separation));
    return 1;
}


# Check for future limit, return a VD object
sub futureCheck {
    my $className = shift;
    my ($prefs, $date, $endDate, $ignoreLimit) = @_;

    my $self = {};
    bless $self, $className;

    # return right away if we can
    return $self unless $prefs->FutureLimit;
    return $self if ($prefs->FutureLimit =~ /allow/i);
    return $self if ($ignoreLimit and ($prefs->FutureLimit =~ /warn/i));

    my $futureDate = Date->new;
    my $amount = ($prefs->FutureLimitAmount || 0) + 0;

    my $units = '';
    if ($prefs->FutureLimitUnits =~ /(day|week|month|year)/i) {
        $units = $1;
    }
    ($units =~ /day/i   and $futureDate->addDays   ($amount)) or
    ($units =~ /week/i  and $futureDate->addWeeks  ($amount)) or
    ($units =~ /month/i and $futureDate->addMonths ($amount)) or
    ($units =~ /year/i  and $futureDate->addYears  ($amount));

    $self->{error}++
        if ($date > $futureDate or ($endDate and $endDate > $futureDate));

    $self->{amount}    = $amount;
    $self->{units}     = $units;
    $self->{isWarning} = $prefs->FutureLimit =~ /warn/i;
    $self;
}

sub isBad {
    my $self = shift;
    exists $self->{error} and $self->{error};
}
sub isWarning {
    my $self = shift;
    $self->{isWarning};
}
sub futureMessage {
    my $self = shift;
    my ($op, $calendarName, $i18n) = @_;
    my $message = '<br><b>' .
                  $i18n->get ('The date is too far in the future!') .
                  '</b><br><br>&nbsp;&nbsp; ' .
                  $i18n->get ('Calendar') . ": $calendarName<br><br>" .
                  '&nbsp;&nbsp;' .
                  $i18n->get ("Sorry, the calendar is set to not permit you " .
                              " to add or edit events that far in the future.")
                . '<br><br>&nbsp;&nbsp;(' .
                  $i18n->get ('The maximum is:') . " $self->{amount} " .
                  $i18n->get ($self->{amount} == 1 ? $self->{units}
                                                   : $self->{units} . 's')
                . ')<br><br><hr>';

    if ($self->{isWarning}) {
        my $href = $op->makeURL ({%{$op->{params}},
                                  IgnoreFutureLimit => 1});
        $message .= "<a href=$href>" . $i18n->get ('Add it anyway') .
            "</a><br>";
    }
    $message;
}

# ----------------------------------------------------------------------------
# Pass operation and event ID of event we're modifying, if we're modifying
# one. (undef otherwise)
sub timeConflict {
    my $className = shift;
    my ($db, $prefs, $date, $startTime, $endTime,
        $oldEventID, $ignoreTimeConflicts) = @_;

    my $self = {};
    bless $self, $className;

    # return right away if we can
    return $self unless defined $startTime;
    return $self if ($prefs->TimeConflicts =~ /allow/i);
    return $self if ($ignoreTimeConflicts and
                     ($prefs->TimeConflicts =~ /warn/i));

    my $separation = $prefs->TimeSeparation || 0;

    # these are used for display only; convert for timezone
    my $offset = $prefs->Timezone || 0;
    $self->{startTime}  = $startTime + $offset * 60;
    $self->{endTime}    = $endTime   + $offset * 60
        if (defined $endTime);
    foreach (qw /startTime endTime/) {
        next unless (defined $self->{$_});
        $self->{$_} %= 1440;               # 1440 = 24 * 60
#         if ($self->{$_} < 0) {
#             $self->{$_} += 24*60;
#         } elsif ($self->{$_} >= 24*60) {
#             $self->{$_} -= 24*60;
#         }
    }

    $self->{oldEventID} = $oldEventID;
    $self->{separation} = $separation;
    $self->{date}       = $date;

    # Get possibly conflicting events
    my @events = $db->getApplicableEvents ($date, $prefs,
                                           'yesterday,noadjust');

    foreach my $event (@events) {
        # don't check against ourself if we're editing an event
        next if ((defined $oldEventID) and ($event->id == $oldEventID));

        my ($start, $end);
        # if stored as period, get time as defined by the period
        if (my $period = $event->timePeriod) {
            my $thePrefs = $prefs;
            if (my $incFrom = $event->includedFrom) {
                $thePrefs = Preferences->new ($incFrom);
            }
            my ($name, $s, $e, $disp) = $thePrefs->getTimePeriod ($period);
            ($start, $end) = ($s, $e);
        }
        # otherwise, get start/end stored w/event
        else {
            ($start, $end) = ($event->startTime, $event->endTime);
        }

        # if from yesterday, adjust start time to midnight today
        my $isYesterday;
        if (defined $end and $end < $start and
            $event->Date and $event->Date != $date) {
            $start = 0;
            $isYesterday = 1;
        }

        if (_timeConflict ($start, $end, $startTime, $endTime, $separation)) {
            $self->{error}++;
            $self->{isWarning} = $prefs->TimeConflicts =~ /warn/i;
            $self->{event} = $event;
            $self->{prevNextString} = 'on the previous day'
                if ($isYesterday);
            return $self;
        }
    }

    # If we extend into next day...
    if (defined $endTime and $endTime < $startTime) {
        $startTime = 0;
        my @tomorrow = $db->getApplicableEvents ($date + 1, $prefs,
                                                 'noadjust');

        foreach my $event (@tomorrow) {
            # don't check against ourself if we're editing an event
            next if ((defined $oldEventID) and ($event->id == $oldEventID));

            if (_timeConflict ($event->startTime, $event->endTime,
                               $startTime, $endTime, $separation)) {
                $self->{error}++;
                $self->{isWarning} = $prefs->TimeConflicts =~ /warn/i;
                $self->{event} = $event;
                $self->{prevNextString} = 'on the next day';
                return $self;
            }
        }
    }

    return $self unless $separation;

    # if no conflict so far, and a separation is specified, and it offsets
    # into the prev/next day, we need to check yesterday (or tomorrow). (Of
    # course an event can run from 12:01-23:59, so we might need to check
    # both ends.)
    my ($previousDay, $nextDay);
    if (($startTime - $separation) < 0) {
        $previousDay = $date - 1;
    }
    if ($endTime and ($endTime + $separation) > 1440) {
        $nextDay = $date + 1;                            # 1440 = 24*60
    }
    return $self unless ($previousDay or $nextDay);

    if ($previousDay) {
        my @events = $db->getApplicableEvents ($previousDay, $prefs,
                                               'noadjust');
        my $startx = $startTime + 1440;
        my $endx   = $endTime ? $endTime + 1440 : undef;
        foreach my $event (@events) {
            if (_timeConflict ($event->startTime, $event->endTime,
                               $startx, $endx, $separation)) {
                $self->{error}++;
                $self->{isWarning} = $prefs->TimeConflicts =~ /warn/i;
                $self->{prevNextString} = 'on the previous day';
                return $self;
            }
        }
    }

    if ($nextDay) {
        my @events = $db->getApplicableEvents ($nextDay, $prefs, 'noadjust');
        my $startx = $startTime - 1440;
        my $endx   = $endTime ? $endTime - 1440 : undef;
        foreach my $event (@events) {
            if (_timeConflict ($event->startTime, $event->endTime,
                               $startx, $endx, $separation)) {
                $self->{error}++;
                $self->{isWarning} = $prefs->TimeConflicts =~ /warn/i;
                $self->{prevNextString} = 'on the next day';
                return $self;
            }
        }
    }
    return $self;
}

# Pass CalName if a multi-cal op
sub conflictMessage {
    my $self = shift;
    my ($op, $calName) = @_;

    my $prefs = $op->prefs;
    my $i18n  = $op->I18N;

    my $prevNext = $self->{prevNextString} || '';
    $prevNext = $i18n->get ($prevNext) if $prevNext;

    my $military = $prefs->MilitaryTime;
    my $start  = Event->getTimeString ($self->{startTime}, $military);
    my $end    = defined $self->{endTime} ?
                     Event->getTimeString ($self->{endTime}, $military) : '';
    my ($evStart, $evEnd) = $self->{event}->getDisplayTime ($prefs->Timezone);
    my $evDate = $self->{event}->getDisplayDate ($self->{date},
                                                 $prefs->Timezone);
    my $timeString2 = Event->getTimeString ($evStart, $military);
      $timeString2 .= ' - ' . Event->getTimeString ($evEnd, $military)
          if (defined $evEnd);
    $timeString2 .= ' (' . $evDate->pretty ($i18n) . ')'
        if ($evDate != $self->{date});

    my ($string, $string2, $addOrChange);
    if (defined $self->{oldEventID}) { # then we're replacing or copying
        $string = $i18n->get ('The time of the edited event ' .
                              'conflicts with an existing event.');
        $string2 = $i18n->get ('Edited Event Time');
        $addOrChange = $i18n->get ('Change or copy it anyway');
    } else {
        $string = $i18n->get ('The time of the new event ' .
                              'conflicts with an existing event.');
        $string2 = $i18n->get ('New Event Time');
        $addOrChange = $i18n->get ('Add it anyway');
    }

    my $whichCalendar = '';
    if ($calName) {
        $whichCalendar = '<tr><td align="right">' .
                         $i18n->get ("Calendar Name") . ':' .
                         "</td><td>$calName</td></tr>";
    }

    my $date = $self->{date}->pretty ($i18n);
    my $category = $self->{event}->category;
    if (defined $category) {
        $category = '<td align="right">' .
                    $i18n->get ('Conflicting Category') . ':</td>' .
                    "<td><i>$category</i></td>";
    } else {
        $category = '<td>&nbsp</td>';
    }

    my $text;
    if ($self->{event}->isTentative and
        !$op->permission->permitted ($op->getUsername, 'Edit')) {
        $text = $i18n->get ('Conflicting Event is Pending Approval');
    } else {
        $text = $self->{event}->text;
    }

    my $conflictMessage = '<br><b>' . $i18n->get ('Times conflict!') . '</b>' .
                        "<br><br>&nbsp;&nbsp; $string<br><br>" .
                        "<blockquote><table>" .
                            "<tr><td align='right'>" . $i18n->get ('Date:') .
                                "</td><td><b>$date</b></td></tr>" .
                            "<tr><td align='right'>$string2:</td>" .
                                   '<td><b>' . $start .
                                       ($end && " - $end") .
                                       '</b></td></tr>' .
                                "<tr><td align='right'>" .
                                   $i18n->get('Conflicting Event Time') . ':' .
                                    "</td><td><b>" . $timeString2 .
                                        '<small><small> ' . $prevNext .
                                            '</small></small></b></td></tr>' .
                                $whichCalendar .
                                "<tr><td align='right'>" .
                                   $i18n->get('Conflicting Event Text') . ':' .
                                    "</td><td><i>$text</i></td></tr>" .
                                "<tr>$category</tr>" .
                            '</table></blockquote>';

    if ($self->{separation}) {
        $conflictMessage .= '<br>(' .
                             $i18n->get ('Note: Event Separation is in effect')
                             . ": $self->{separation} "
                             . $i18n->get ('minutes') . ')';
    }
    $conflictMessage .= '<br><br><hr>';
    if (!defined ($calName) and $self->{isWarning}) {
        my $href = $op->makeURL ({%{$op->{params}}, IgnoreTimeConflict => 1});
        $conflictMessage .= "<a href=$href>" . $i18n->get ($addOrChange) .
                            "</a><br>";
    }
    return $conflictMessage;
}

1;

Anon7 - 2021