X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=src%2FPVE%2FCalendarEvent.pm;h=3c08eb06899d2f2134eee74f84a6239df802353c;hp=d235e0460d8c70e54568e504710183ad739690a2;hb=e97f807c388c10250f442b1f16c5315df2ffc2af;hpb=2244b2711aa451e6731a0f7faac6072bb3b114f8 diff --git a/src/PVE/CalendarEvent.pm b/src/PVE/CalendarEvent.pm index d235e04..3c08eb0 100644 --- a/src/PVE/CalendarEvent.pm +++ b/src/PVE/CalendarEvent.pm @@ -4,6 +4,8 @@ use strict; use warnings; use Data::Dumper; use Time::Local; +use PVE::JSONSchema; +use PVE::Tools qw(trim); # Note: This class implements a parser/utils for systemd like calender exents # Date specification is currently not implemented @@ -18,11 +20,29 @@ my $dow_names = { sat => 6, }; +PVE::JSONSchema::register_format('pve-calendar-event', \&pve_verify_calendar_event); +sub pve_verify_calendar_event { + my ($text, $noerr) = @_; + + eval { parse_calendar_event($text); }; + if (my $err = $@) { + return undef if $noerr; + die "invalid calendar event '$text' - $err\n"; + } + return $text; +} + # The parser. # returns a $calspec hash which can be passed to compute_next_event() sub parse_calendar_event { my ($event) = @_; + $event = trim($event); + + if ($event eq '') { + die "unable to parse calendar event - event is empty\n"; + } + my $parse_single_timespec = sub { my ($p, $max, $matchall_ref, $res_hash) = @_; @@ -42,6 +62,7 @@ sub parse_calendar_event { $$matchall_ref = 1; } else { $start = int($start); + die "value '$start' out of range\n" if $start >= $max; $res_hash->{$start} = 1; } } @@ -107,8 +128,12 @@ sub parse_calendar_event { if ($time_spec =~ m/^($chars+):($chars+)$/) { my ($p1, $p2) = ($1, $2); - $parse_single_timespec->($p1, 24, \$matchall_hours, $hours_hash); - $parse_single_timespec->($p2, 60, \$matchall_minutes, $minutes_hash); + foreach my $p (split(',', $p1)) { + $parse_single_timespec->($p, 24, \$matchall_hours, $hours_hash); + } + foreach my $p (split(',', $p2)) { + $parse_single_timespec->($p, 60, \$matchall_minutes, $minutes_hash); + } } elsif ($time_spec =~ m/^($chars)+$/) { # minutes only $matchall_hours = 1; foreach my $p (split(',', $time_spec)) { @@ -124,13 +149,13 @@ sub parse_calendar_event { if ($matchall_hours) { $h = '*'; } else { - $h = [ sort keys %$hours_hash ]; + $h = [ sort { $a <=> $b } keys %$hours_hash ]; } if ($matchall_minutes) { $m = '*'; } else { - $m = [ sort keys %$minutes_hash ]; + $m = [ sort { $a <=> $b } keys %$minutes_hash ]; } return { h => $h, m => $m, dow => [ sort keys %$dow_hash ]}; @@ -152,9 +177,13 @@ sub compute_next_event { if ($utc) { (undef, $min, $hour, $mday, $mon, $year, $wday) = gmtime($last); + # gmtime and timegm interpret two-digit years differently + $year += 1900; $startofday = timegm(0, 0, 0, $mday, $mon, $year); } else { (undef, $min, $hour, $mday, $mon, $year, $wday) = localtime($last); + # localtime and timelocal interpret two-digit years differently + $year += 1900; $startofday = timelocal(0, 0, 0, $mday, $mon, $year); }