#!/usr/bin/perl # before anything else, the script needs to find out its own name # # some servers (notably IIS on windows) don't set the cwd to the script's # directory before executing it. So we get that information # from $0 (the full name & path of the script). BEGIN{($_=$0)=~s![\\/][^\\/]+$!!;push@INC,$_} $name = $0; $name =~ s/.+\/?.+\///; # for unix $name =~ s/.+\\.+\\//; # for windows $path = $0; $path =~ s/(.+\/).+/$1/g; # for unix $path =~ s/(.+\\).+/$1/g; # for windows # The "use Cwd" method would be nice, but it doesn't work with # some versions of IIS/ActivePerl #use Cwd; #$path = cwd; if ($path ne "") { chdir $path; push @INC,$path; } # finished discovering name #use Data::Dumper; # some global variables (more further down) local $plans_version = "7.7.7"; # version local $debug_info; local %options; local $perl_version = (sprintf ("%vd",$^V)); #local $options{data_storage_mode}; local $fatal_error = 0; # fatal errors cause plans to abort and print an error message to the browser local $error_info = ""; local $html_output; local $script_url = ""; local $messages = ""; # formatted in plain text with newlines. Converted to html at display time. local $template_html; local $local_template_file = 0; # tells whether the template was loaded via a filesystem open or through a http request. local $event_details_template; local $list_item_template; local $calendar_item_template; local $upcoming_item_template; local %calendars; local %current_calendar; local %latest_calendar; local %new_calendars; local $normalized_timezone = 0; local $normalized_timezone_pending_events = 0; # used when adding new entries local $max_cal_id = 0; local $max_event_id = 0; local $max_series_id = 0; local $max_user_id = 0; local $max_action_id = 0; # used to protect against refreshes local $latest_cal_id = 0; local $latest_event_id = 0; local $latest_new_cal_id = 0; local $latest_new_event_id = 0; local $session; local %users; my $profile; local $logged_in = 0; local $logged_in_as_root = 0; local $logged_in_as_current_cal_user = 0; local $logged_in_as_current_cal_admin = 0; local $lg_name = ""; local $lg_password = ""; local %events; local %new_events; local @pending_events_to_display; local %text; local %cookie_parms; local $cookie_text = ""; local $cookie_header_text = ""; local $max_remote_event_id = 0; local $options{default_template_path} = ""; local $theme_url = ""; local $options{choose_themes} = ""; local $graphics_url = ""; local $icons_url = ""; local $input_cal_id_valid = 0; local $options{right_click_menus_enabled} = 0; local %cal_options; local $rightnow; local @months; local @months_abv; local @day_names; local $loaded_all_events; # flag used to avoid calling load_events("all") twice # not needed for calendars (we always load all calendars) local @disabled_tabs; # check for required modules. my $module_found=0; foreach $temp_path (@INC) { if (-e "$temp_path/plans_config.pl") { $module_found=1;} } if ($module_found == 0) { $fatal_error=1; $error_info .= "Unable to locate plans_config.pl! It should be in the same directory as plans.cgi!\n"; } else {require "plans_config.pl";} $module_found=0; foreach $temp_path (@INC) { if (-e "$temp_path/CGI") { $module_found=1;} } if ($module_found == 0) { $fatal_error=1; $error_info .= "unable to locate required module CGI!\n"; } else { use CGI;} $module_found=0; foreach $temp_path (@INC) { if (-e "$temp_path/CGI/Session") { $module_found=1;} } if ($options{sessions} eq "1") { if ($module_found == 0) { $fatal_error = 1; $error_info .= "unable to locate required module CGI::Session!\n"; } else { require CGI::Session;} } $module_found=0; foreach $temp_path (@INC) { if (-e "$temp_path/CGI/Carp.pm") { $module_found=1;} } if ($module_found == 0) { $fatal_error=1; $error_info .= "unable to locate required module CGI::Carp!\n"; } else { use CGI::Carp qw/fatalsToBrowser/;} $module_found=0; foreach $temp_path (@INC) { if (-e "$temp_path/Time") { $module_found=1;} } if ($module_found == 0) { $fatal_error=1; $error_info .= "unable to locate required module Time.pm!\n"; } else { use Time::Local;} $module_found=0; foreach $temp_path (@INC) { if (-e "$temp_path/IO.pm") { $module_found=1;} } if ($module_found == 0) { $fatal_error=1; $error_info .= "unable to locate required module IO.pm!\n"; } else { use IO::Socket;} if ($fatal_error == 1) { # print error and bail out &fatal_error(); } $module_found=0; foreach $temp_path (@INC) { if (-r "$temp_path/plans_lib.pl") { $module_found=1;} } if ($module_found == 0) { $fatal_error=1; $error_info .= "Unable to locate plans_lib.pl! It should be in the same directory as plans.cgi!\n"; } else {require "plans_lib.pl";} # multi-language stuff if (defined $options{language_files}) { my @language_files = split(',', $options{language_files}); # pull in language files foreach $language_file (@language_files) { $module_found=0; foreach $temp_path (@INC) { if (-r "$temp_path/$language_file") { $module_found=1;} } if ($module_found == 0) { $fatal_error=1; $error_info .= "Unable to locate language file $language_file! It should be in the same directory as plans.cgi!\n"; } else {require $language_file;} } # create a javascript file with language strings open (FH, "$options{default_theme_path}/$options{js_language_file}") || {$debug_info.= "unable to open file $options{default_theme_path}/$options{js_language_file}\n"}; flock FH,2; my $first_lang_line=; close FH; if ($options{generate_js_lang} eq "1" || $first_lang_line !~ /$plans_version/) { my $lang_string = ""; $lang_string .= "//$plans_version\n"; $lang_string .= "var plans_lang = new Array();\n"; # generate %lang keys foreach $lang_key (keys %lang) { if (ref $lang{$lang_key} eq "ARRAY") { $lang_string .= "plans_lang['$lang_key']=new Array("; my $first = 1; foreach $key (@{$lang{$lang_key}}) { if (!$first) {$lang_string .= ',';} if ($first) {$first = 0;} my $lang_val = &js_string($key); $lang_string .= "'$lang_val'"; } $lang_string .= ");\n"; } else { my $lang_val = &js_string($lang{$lang_key}); $lang_string .= "plans_lang['$lang_key']='$lang_val';\n" } } open (FH, ">$options{default_theme_path}/$options{js_language_file}") || {$debug_info .= "unable to open file $options{default_theme_path}/$options{js_language_file} for writing!\n"}; flock FH,2; print FH $lang_string; close FH; } } else { $fatal_error=1; $error_info .= "No language files defined in plans.config!\n"; } # check for perl version my $temp = substr($perl_version,0,3); if ($temp < 5.6) { $fatal_error=1; $error_info .= "Your version of perl ($perl_version) is too old! Plans requires perl version 5.6 or better.\n"; } if ($fatal_error == 1) { # print error and bail out &fatal_error(); } # init cgi stuff $q = new CGI; $script_url = $q->url(-path_info>=1); $script_url =~ /(.*)\//; # remove trailing / and all text after $script_url = $1; # remove trailing / and all text after %cookie_parms = %{&extract_cookie_parms()}; # check if data files or tables are present &check_data(); # fatal error? Print error and bail out if ($fatal_error == 1) { &fatal_error();} if ($theme_url eq "") { # not defined in config file $theme_url = "$script_url/theme"; } if ($options{choose_themes}) { $chosen_url = $q->param('theme_url'); $chosen_url = $cookie_parms{'theme_url'} if ($chosen_url eq ""); $theme_url = $chosen_url if ($chosen_url ne ""); } $graphics_url ="$theme_url/graphics"; # where misc. graphics are $icons_url = "$theme_url/icons"; # where icons are $css_path = "$theme_url/plans.css"; # css file # globals for http parameters my $active_tab = $q->param('active_tab') + 0; # +0 ensures numericity $active_tab = 0 if ($active_tab > scalar @{$lang{tab_text}} - 1); my $api_output_format = $q->param('output_format'); my $api_command = $q->param('api_command'); my $add_edit_cal_action = $q->param('add_edit_cal_action'); $add_edit_cal_action = "" if (!&contains(["add", "edit", "view_pending"],$add_edit_cal_action)); # validate my $add_edit_event = $q->param('add_edit_event'); $add_edit_event = "" if (!&contains(["add", "edit"],$add_edit_event)); # validate local $current_event_id = $q->param('evt_id'); $current_event_id = "" if ($current_event_id !~ /^R?\d+$/); # validate local $pending_event_id = $q->param('pending_event_id'); $pending_event_id = "" if ($pending_event_id !~ /^R?\d+$/); # validate local $cal_start_month = $q->param('cal_start_month') + 0; # +0 ensures numericity local $cal_start_year = $q->param('cal_start_year') + 0; # +0 ensures numericity local $cal_num_months = $q->param('cal_num_months') + 0; # +0 ensures numericity # if view parameters not supplied in http request, check cookie $cal_start_month = $cookie_parms{'cal_start_month'} if ($q->param('cal_start_month') eq ""); $cal_start_year = $cookie_parms{'cal_start_year'} if ($cal_start_year == 0); $cal_num_months = $cookie_parms{'cal_num_months'} if ($cal_num_months == 0); my $special_action = $q->param('special_action'); # needs no validation - never used in output local $display_type = $q->param('display_type') + 0; # +0 ensures numericity $display_type = $cookie_parms{'display_type'} if ($q->param('display_type') eq ""); $messages = $q->param('messages') if ($q->param('messages') ne ""); # other globals my $event_start_date; my $event_start_timestamp; my $event_days; my $start_mday; my $start_mon; my $start_year; my @timestamp_array; my $prev_month_link = ""; my $next_month_link = ""; # load calendar data &load_calendars(); &load_users(); &load_actions(); local $current_cal_id = 0; if ($q->param('cal_id') eq "") { $current_cal_id = $cookie_parms{'cal_id'} if ($current_cal_id == 0); } else { $current_cal_id = $q->param('cal_id'); } $current_cal_id += 0; # +0 ensures numericity # if calendar id not supplied, but evt_id is supplied (like when viewing an event) use that event's calendar as the current calendar #if ($current_event_id ne "") #{ # &load_event($current_event_id); # # my %temp_current_event = %{$events{$current_event_id}}; # if ($current_cal_id eq "") # { # $current_cal_id = $temp_current_event{cal_ids}[0]; # } #} foreach $cal_id (keys %calendars) { if ($cal_id eq $current_cal_id) { $input_cal_id_valid = 1;} } if ($current_cal_id eq "") { $input_cal_id_valid = 0;} if ($current_cal_id =~ /\D/) { $input_cal_id_valid = 0;} $current_cal_id = 0 if ($current_event_id eq "" && !$input_cal_id_valid); # make all calendars selectable by default foreach $cal_id (keys %calendars) { $default_cal{selectable_calendars}{$cal_id} = 1;} %current_calendar = %{$calendars{$current_cal_id}}; # time-related globals $rightnow = time() + 3600 * $current_calendar{gmtime_diff}; @rightnow_array = gmtime $rightnow; $rightnow_year = $rightnow_array[5]+1900; $rightnow_month = $rightnow_array[4]; $rightnow_mday = $rightnow_array[3]; $next_year = $rightnow_year+1; $rightnow_description = formatted_time($rightnow, "hh:mm:ss mn md yy"); @weekday_sequence = @day_names; # session stuff if ($options{sessions} eq "1") { #$lg_name = $q->param('lg_name'); $lg_name = $current_cal_id; $lg_password = $q->param('cal_password'); &delete_old_sessions(1); # in days #$debug_info .= "plans_sid (cookie): ".$q->cookie("plans_sid")."\n"; my $current_session_id = $q->cookie("plans_sid") || undef; $session = new CGI::Session(undef, $current_session_id, {Directory=>$options{sessions_directory}}); $session->expire("+1d"); #$debug_info .= "current_session_id: $current_session_id\n"; # log out? if ($q->param('logout') eq "1") { $session->delete(); $cookie_text .= " plans_sid=deleted;"; } # try to match session with user id. (If this fails, it's not really a session.) my $results = &init_session($q, $session); $profile = $session->param("~profile"); if (defined $profile->{calendar_permissions}) { $logged_in = 1; $cookie_text .= " plans_sid=".$session->id.";"; } } if ($options{sessions} eq "1") { $logged_in_as_root = ($profile->{calendar_permissions}->{0}->{admin} eq "1") ? 1:0; $logged_in_as_current_cal_user = ($profile->{calendar_permissions}->{$current_cal_id}->{user} ne "") ? 1:0; $logged_in_as_current_cal_admin = ($profile->{calendar_permissions}->{$current_cal_id}->{admin} ne "") ? 1:0; } elsif ($q->param('cal_password') ne "") { $logged_in_as_root = ($calendars{0}{password} eq crypt($q->param('cal_password'), $options{salt})) ? 1:0; $logged_in_as_current_cal_admin = ($current_calendar{password} eq crypt($q->param('cal_password'), $options{salt})) ? 1:0; foreach $user_id (keys %users) { my %user = %{$users{$user_id}}; my %user_calendars = %{$user{calendars}}; foreach $user_cal_id (keys %user_calendars) { if ($user_cal_id eq $current_cal_id && $user{calendars}{$user_cal_id}{edit_events} eq "1" && $user{password} eq crypt($q->param('cal_password'), $options{salt})) { $logged_in_as_current_cal_user = 1; last; } last if ($logged_in_as_current_cal_user == 1); } last if ($logged_in_as_current_cal_user == 1); } } $logged_in_as_current_cal_user = 0 if (!$options{users}) ; #$debug_info .= "init_session results: $results\n"; #$debug_info .= "logged-in: ".$session->param("~logged-in")."\n"; #$debug_info .= "session id: ".$session->id."\n"; #$debug_info .= "profile user_id: ".$profile->{calendar_permissions}->{$current_cal_id}."\n"; #$debug_info .= "options{sessions}: $options{sessions}\n"; #$debug_info .= "logged_in_as_root: $logged_in_as_root\n"; #$debug_info .= "logged_in_as_current_cal_user: $logged_in_as_current_cal_user\n"; #$debug_info .= "logged_in_as_current_cal_admin: $logged_in_as_current_cal_admin\n"; #$debug_info .= "current_calendar{password}: $current_calendar{password}\n"; #$debug_info .= ($profile->{calendar_permissions}->{$current_cal_id}->{admin})."\n"; # custom stylesheet? if ($current_calendar{custom_stylesheet} ne "") { $css_path = "http://$current_calendar{custom_stylesheet}"; } # if this is a custom calendar request, shoehorn the request parameters in if ($q->param('custom_calendar') eq "1") { $current_cal_id = $q->param('custom_calendar_calendar') + 0; @custom_calendar_backgound_calendars = $q->param('custom_calendar_background_calendars'); foreach $local_background_calendar (keys %{$calendars{$current_cal_id}{local_background_calendars}}) { delete $calendars{$current_cal_id}{local_background_calendars}{$local_background_calendar};} foreach $local_background_calendar (@custom_calendar_backgound_calendars) { $calendars{$current_cal_id}{local_background_calendars}{$local_background_calendar} = 1;} %current_calendar = %{$calendars{$current_cal_id}}; } # make sure we can select the current calendar #$current_calendar{selectable_calendars}{$current_cal_id} = 1; # set info window height & width $current_calendar{info_window_size} ="400x400" if ($current_calendar{info_window_size} eq ""); # default my ($info_window_width, $info_window_height) = split("x", $current_calendar{info_window_size}); # rotate weekday_sequence by the offset defined in the week start day. for ($l1=0;$l1 < $current_calendar{week_start_day};$l1++) { push @weekday_sequence, (shift @weekday_sequence);} # load background_colors my @temp_lines = split ("\n", $event_background_colors); foreach $temp_line (@temp_lines) { next if ($temp_line !~ /\w/); # skip any blank lines $temp_line =~ s/^\s+//; my ($hex_color, $hex_color_title) = split (/,*\s+/, $temp_line, 2); $hex_color_title = " " if ($hex_color_title eq ""); push @event_bgcolors, {color => $hex_color, title => $hex_color_title}; } #evaluate browser type and version $_ = $ENV{HTTP_USER_AGENT}; if (/Mozilla/) { if (/Opera.([0-9\.]+)/) { $browser_type = 'Opera'; $browser_version=$1;} elsif (/MSIE.([0-9.]+)/) { $browser_type = 'IE'; $browser_version = $1;} elsif (/Mozilla\/([0-9\.]+)/) {$browser_type = 'Mozilla'; $browser_version=$1; if (($browser_version<5) || (/Netscape/)) {$browser_type = "Netscape";} } if (/\)[^0-9.]+[0-9]*[\/\ ]([0-9.]+)/) {$browser_version=$1;} } elsif (/(\w+)\/([0-9\.]+)/) {$browser_type = $1; $browser_version = $2} #evaluate, transform, tweak, adjust, modify input values #$debug_info .= "browser type: $browser_type
"; #if no month is selected, use the current month if ($cal_start_month eq "" && $q->param('cal_start_month') eq "") { $cal_start_month = $rightnow_month; #$cal_start_month = 2; } #if the input year is out of range use the current year if (($cal_start_year+0) < 1902 || ($cal_start_year+0)> 2037) { $cal_start_year = $rightnow_year; } $cal_num_months = $current_calendar{default_number_of_months} if ($cal_num_months < 1); $cal_num_months = $current_calendar{default_number_of_months} if ($cal_num_months > $current_calendar{max_number_of_months}); $cal_num_months = 1 if ($cal_num_months > $current_calendar{max_number_of_months}); $cal_num_months = 1 if ($cal_num_months == 0); #calculate calendar end month and year $cal_end_month = $cal_start_month; $cal_end_year = $cal_start_year; for ($l1=1;$l1<$cal_num_months;$l1++) { $cal_end_month++; if ($cal_end_month == 12) { $cal_end_month=0; $cal_end_year++; } } #check to make sure num_months+cal_start_date doesn't go out of bounds if ($cal_end_year < 1902 || $cal_end_year> 2037) { $cal_end_year = $cal_start_year; $cal_end_month = $cal_start_month; $cal_num_months = 1; } # time window for loading events my $cal_start_timestamp = timegm(0,0,0,1,$cal_start_month,$cal_start_year) - 2592000; my $cal_end_timestamp = timegm(0,0,0,1,$cal_end_month,$cal_end_year) + 5184000; if ($q->param('cal_start_timestamp') ne "" && $q->param('cal_start_timestamp') !~ /\D/) { $cal_start_timestamp = $q->param('cal_start_timestamp');} if ($q->param('cal_end_timestamp') ne "" && $q->param('cal_end_timestamp') !~ /\D/) { $cal_end_timestamp = $q->param('cal_end_timestamp');} #$debug_info .="start: $cal_start_timestamp\nend: $cal_end_timestamp\nrightnow: $rightnow\n"; # load event data, for main calendar and its background calendars my @temp_calendars = ($current_cal_id); foreach $local_background_calendar (keys %{$current_calendar{local_background_calendars}}) { push @temp_calendars, $local_background_calendar;} my $initial_load_events = 1; $initial_load_events = 0 if ($q->param('get_upcoming_events') eq "1"); &load_events($cal_start_timestamp, $cal_end_timestamp, \@temp_calendars) if ($initial_load_events == 1); if ($current_event_id ne "") { &load_event($current_event_id); } # load events from remote background calendars if (scalar keys %{$current_calendar{remote_background_calendars}} > 0) { $remote_calendars_status=""; my $temp = scalar keys %{$current_calendar{remote_background_calendars}}; foreach $remote_calendar_id (keys %{$current_calendar{remote_background_calendars}}) { # pull in remote calendar name my $remote_calendar_url = $current_calendar{remote_background_calendars}{$remote_calendar_id}{url}; $remote_calendar_complete_url = $remote_calendar_url; #$debug_info .= "remote calendar: $remote_calendar_complete_url\n"; $remote_calendar_complete_url .= "?remote_calendar_request=1&cal_id=$current_calendar{remote_background_calendars}{$remote_calendar_id}{remote_id}&cal_start_year=$cal_start_year&cal_start_month=$cal_start_month&num_months=$cal_num_months"; #$debug_info .= "remote calendar url: $remote_calendar_complete_url\n"; my $xml_results = &get_remote_file($remote_calendar_complete_url); if ($xml_results =~ //) { $xml_results =~ s//>/g; #$debug_info .= "Error fetching remote calendar: $xml_results\n"; } else { my %remote_calendar = %{&xml2hash($xml_results)}; my $remote_cal_title = $remote_calendar{'xml'}{calendar}{title}; my $remote_cal_gmtime_diff = $remote_calendar{'xml'}{calendar}{gmtime_diff}; #$debug_info .= "remote_cal_gmtime_diff: $remote_cal_gmtime_diff\n"; #my $temp = $xml_results; #$temp=~ s/>/>/g; #$temp=~ s/ 1) { $prev_string = $lang{previous_months}; $prev_string =~ s/###num###/$cal_num_months/; } else { $prev_string = $lang{previous_month}; } # calculate next X months range. my $next_cal_start_month = $cal_start_month + $cal_num_months; my $next_cal_start_year = $cal_start_year; if ($next_cal_start_month > 11) { $next_cal_start_year = $cal_start_year + int(abs($cal_num_months + $cal_start_month) / 12); $next_cal_start_month = abs($cal_start_month + $cal_num_months) % 12; } # singular or plural? if ($cal_num_months > 1) { $next_string = $lang{next_months}; $next_string =~ s/###num###/$cal_num_months/; } else { $next_string = $lang{next_month}; } if ($q->param('diagnostic_mode') eq "1") { my $diagnostic_results = &diagnostic_info; $html_output = < Diagnostic mode

Plans Diagnostic information

$diagnostic_results

Debug info:

$debug_info
p1 print $html_output; exit(0); } if ($q->param('detect_remote_calendars') eq "1") { &detect_remote_calendars(); exit(0); } if ($q->param('remote_calendar_request') eq "1") { &remote_calendar_request(); exit(0); } if ($q->param('add_edit_user') eq "1") { &add_edit_user(); exit(0); } if ($q->param('add_new_ical') eq "1") { &add_new_ical(); exit(0); } if ($q->param('js_login') eq "1") { &js_login(); exit(0); } if ($q->param('manage_pending_events') eq "1") { &manage_pending_events(); exit(0); } if ($q->param('export_calendar') eq "1") { if ($q->param('export_type') eq "ascii_text") { &ascii_text_cal($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year); exit(0); } elsif ($q->param('export_type') eq "csv_file") { &csv_file($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year); exit(0); } elsif ($q->param('export_type') eq "csv_file_palm") { &csv_file_palm($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year); exit(0); } elsif ($q->param('export_type') eq "vcalendar") { &vcalendar_export_cal($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year); exit(0); } elsif ($q->param('export_type') eq "icalendar") { &icalendar_export_cal($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year); exit(0); } } if ($q->param('export_event') eq "1") { if ($q->param('export_type') eq "ascii_text") { &ascii_text_event(); exit(0); } elsif ($q->param('export_type') eq "icalendar") { &icalendar_export_event(); exit(0); } elsif ($q->param('export_type') eq "vcalendar") { &vcalendar_export_event(); exit(0); } } elsif ($q->param('get_upcoming_events') eq "1") { &get_upcoming_events(); exit(0); } elsif ($api_command ne "") { if ($api_command eq "delete_event") { &api_add_delete_events(); exit(0); } } elsif ($q->param('view_event') eq "1") { &load_templates(); &view_event(); exit(0); } elsif ($q->param('view_pending_event') eq "1") { &load_templates(); my %pending_event = %{$new_events{$pending_event_id}}; &view_pending_event(\%pending_event); exit(0); } elsif ($q->param('email_reminder') eq "1") { &load_templates(); &email_reminder_prompt(); exit(0); } elsif ($q->param('email_reminder_confirm') eq "1") { &load_templates(); &email_reminder_confirm(); exit(0); } elsif ($special_action eq "preview_event") { &load_templates(); &preview_event(); exit(0); } elsif ($special_action eq "preview_date") { &load_templates(); &preview_date(); exit(0); } elsif ($q->param('validate_event') eq "1") { &validate_event(); exit(0); } #load templates &load_templates(); # ssi-style includes in the template if ($local_template_file) { my $new_html = $template_html; $template_html =~ s/###include\s+(.+)###/&load_file($1)/ge; #while ($new_html =~ s/###include\s+(.+)###//g) if(0) { my $include_file=$1; if (-e $include_file) { open (FH, "$include_file") || ($debug_info .="
unable to open include file $include_file for reading
"); flock FH,2; my @include_lines=; close FH; $include_html = join "", @include_lines; } $template_html =~ s/###include\s+(.+)###/$include_html/; } } if($options{choose_themes}) { my $theme_file="choose_theme.html"; my $theme_html=""; if (-e $theme_file) { open (FH, "$theme_file") || ($debug_info .="
unable to open theme file $theme_file for reading
"); flock FH,2; my @theme_lines=; close FH; $theme_html = join "", @theme_lines; } $template_html =~ s/###choose theme###/$theme_html/; } else { $template_html =~ s/###choose theme###//; } my $view_cookie = &xml_store($cal_start_month, "cal_start_month"); $view_cookie .= &xml_store($cal_start_year, "cal_start_year"); $view_cookie .= &xml_store($cal_num_months, "cal_num_months"); $view_cookie .= &xml_store($current_cal_id, "cal_id"); $view_cookie .= &xml_store($display_type, "display_type"); $cookie_text .= " plans_view=$view_cookie;"; $cookie_header_text = "Set-Cookie:$cookie_text path=/;\n"; #$debug_info .= "cookie: $cookie_header_text\n"; $html_output .=< p1 chomp $insert_text; $html_output =~ s/###javascript stuff###/$insert_text/; # sneak in the color select javascript before all other javascript. my $temp =< p1 $html_output =~ s/( "inactive", html => "$lang{tab_text}[0]"}; $menu_tabs[1] = {status => "inactive", html => "$lang{tab_text}[1]"}; $menu_tabs[2] = {status => "inactive", html => "$lang{tab_text}[2]"}; $menu_tabs[$active_tab]{status} ="active"; $menu_tabs[2]{html} = "$lang{tab_text}[2]"; $insert_text =<
p1 # this kludge sucks! if ($browser_type eq "IE") { $tab_vert_offset=4;} else { $tab_vert_offset=0;} #lay out the actual menu tabs for ($l1=0;$l1       $$menu_tab{html}       p1 $noinsert_text .=<$$menu_tab{html}       p1 } $insert_text .=< p1 chomp $insert_text; if ($q->param('custom_calendar') == 1) { $html_output =~ s/###tab menu stuff###//g; } else { $html_output =~ s/###tab menu stuff###/$insert_text/g; } $insert_text =""; #invisible html for context menu $insert_text .=<
p1 #main box stuff $insert_text .=<$prev_string p1 $next_month_link .=<$next_string p1 my $cal_controls_text =<
$lang{controls_start_month}:
$lang{controls_num_months}
p1 $cal_controls_text .=< $lang{controls_calendar_label}
p1 my $num_selectable_calendars = scalar keys %{$current_calendar{selectable_calendars}}; my @selectable_calendars; if ($options{all_calendars_selectable}) { @selectable_calendars = keys %calendars; } else { @selectable_calendars = keys %{$current_calendar{selectable_calendars}}; unshift @selectable_calendars, $current_cal_id if (!&contains(\@selectable_calendars, $current_cal_id)); } if (scalar @selectable_calendars > 1) { $cal_controls_text .=< p1 #list each calendar for the user to select my %explicit_calendar_order; if ($options{calendar_select_order} ne "alpha" && $options{calendar_select_order} ne "") { my @cal_order_ids = split(',',$options{calendar_select_order}); my $cal_order_index = 0; foreach $selectable_calendar_id (@selectable_calendars) { $explicit_calendar_order{"$selectable_calendar_id"} = 9999999; } foreach $cal_order_id (@cal_order_ids) { next if ($cal_order_id eq ""); $explicit_calendar_order{"$cal_order_id"} = $cal_order_index; $cal_order_index++; } } foreach $selectable_calendar_id (sort { if ($options{calendar_select_order} eq "alpha") { return lc $calendars{$a}{title} cmp lc $calendars{$b}{title}; } elsif ($options{calendar_select_order} ne "") { return $explicit_calendar_order{"$a"} <=> $explicit_calendar_order{"$b"} || lc $calendars{$a}{title} cmp lc $calendars{$b}{title};} else { return $a <=> $b;} } @selectable_calendars) { my $selected =""; $selected =" selected" if ($selectable_calendar_id eq $current_calendar{id}); $selectable_calendar_id=~ s/\D//g; $cal_controls_text .=<$calendars{$selectable_calendar_id}{title} p1 } $cal_controls_text .=< p1 } else { $cal_controls_text .=<$current_calendar{title} p1 } $cal_controls_text .=< p1 $cal_controls_text .=< $lang{controls_display_label}
p1 $insert_text .= &add_edit_events_interface(); $insert_text .=< p1 } else { my %results = %{&add_edit_events()}; my $results_html = ""; foreach $results_message (@{$results{messages}}) { $results_message =~ s/\[warning\](.*)/$1<\/span>/i; $results_message =~ s/\[error\](.*)/$1<\/span>/i; $results_message =~ s/\[status\](.*)/$1<\/span>/i; $results_html .= "
  • $results_message
  • \n"; } $insert_text .= "
      $results_html
    $results{text}
    "; } #generate javascript for add/edit events page $page_javascript .= &add_edit_events_javascript(); } elsif ($active_tab eq "2") { #the third tab is for calendar information $html_output =~ s/###calendar controls###//; if ($add_edit_cal_action eq "") { # calendar management view $num_new_calendars = scalar keys %new_calendars; if ($num_new_calendars == 0) { $new_calendars_info = $lang{tab2_no_new_calendars}; } else { $new_calendars_info = $lang{tab2_some_new_calendars}; $new_calendars_info =~ s/###num###/$num_new_calendars/; } $insert_text .=<
    p1 $insert_text .= &add_edit_calendars(); $insert_text .=< p1 } elsif ($add_edit_cal_action eq "view_pending") { #view/approve/reject new pending calendars $insert_text .= &view_pending_calendars(); } #generate javascript for calendar info page $page_javascript.= &add_edit_calendars_javascript(); } #done with main active tab stuff (the stuff that's different depending #on which tab is active. The following stuff is the same regardless #of which tab is active. $html_output =~ s/###calendar area###/$insert_text/g; $html_output =~ s/###version###/$plans_version/g; my $add_event_to_current_cal_text =<$lang{add_event_to_this_calendar} p1 chomp $add_event_to_current_cal_text; my $current_calendar_options_text =<$lang{edit_calendar_options} p1 chomp $current_calendar_options_text; if ($active_tab eq "0") { $html_output =~ s/###add event to current calendar link###/$add_event_to_current_cal_text/; $html_output =~ s/###edit calendar options link###/$current_calendar_options_text/; my $temp = &export_calendar_link(); $html_output =~ s/###export calendar link###/$temp/; my $custom_calendar_link =<$lang{make_custom_calendar} p1 chomp $custom_calendar_link; $html_output =~ s/###custom calendar link###/$custom_calendar_link/; #$debug_info .= "custom calendar link: $custom_calendar_link\n"; } else { $html_output =~ s/###add event to current calendar link###//; $html_output =~ s/###edit calendar options link###//; $html_output =~ s/###custom calendar link###//; $html_output =~ s/###export calendar link###//; } # pending event stuff my $plans_messages_style = ($messages eq "")? "": " style=\"display:block;\""; my $messages_text = "
    $messages
    "; $html_output =~ s/###messages###/$messages_text/; my $logged_in_text = &generate_logged_in_stuff(); if ($logged_in_text ne "") { $logged_in_text = < $logged_in_text
    p1 } $html_output =~ s/###logged-in stuff###/$logged_in_text/; $common_javascript .= &generate_pending_events_javascript() if (&pending_events_visible); $common_javascript .= &common_javascript(); #replace javascript placeholders with actual html/javascript code $html_output =~ s/###page-specific javascript###/\n$page_javascript/; $html_output =~ s/###common javascript###/\n$common_javascript/; $debug_info = "$error_info$debug_info"; if ($debug_info =~ /\S/) { $debug_info =~ s/\n/\n/g; $debug_info = < Error, Warnings, & Debug Messages:
    $debug_info <\/div> p1 } $html_output =~ s/###debug stuff###/$debug_info/g; $html_output =~ s/###cookie_text###/$cookie_header_text/; print $html_output; } #********************end default view code***************************** sub add_edit_calendars { my $temp=""; $html_output =~ s//\n$temp\n/; my $return_text = ""; if ($q->param('update_cal_button') eq "" && $q->param('del_cal_button') eq "") { #add/edit calendar main screen $add_edit_string = $lang{add_new_calendar}; #generate html for blank (default) calendar preview window $cal_details = $new_calendar_default_details; $shared_cal_select_size = scalar keys %calendars; $cal_link="http://"; if ($add_edit_cal_action ne "edit") { %current_calendar = %default_cal;} $add_edit_string = "$lang{edit_calendar} ($current_calendar{title})" if ($add_edit_cal_action eq "edit"); my %checked; $checked{list_background_calendars_together} = " checked" if ($current_calendar{list_background_calendars_together} eq "yes"); $checked{background_events_display_style1} = " checked" if ($current_calendar{background_events_display_style} eq "normal"); $checked{background_events_display_style2} = " checked" if ($current_calendar{background_events_display_style} eq "single_color"); $checked{background_events_display_style3} = " checked" if ($current_calendar{background_events_display_style} eq "faded"); $current_calendar{custom_stylesheet} = "http://$current_calendar{custom_stylesheet}"; $current_calendar{custom_template} = "http://$current_calendar{custom_template}"; $cal_details =~ s//>/g; $return_text .=<

    $add_edit_string

    $lang{fields_text1} $lang{fields_text2} $lang{fields_text3}
    $lang{add_edit_calendars_tab0} $lang{add_edit_calendars_tab1} $lang{add_edit_calendars_tab2} $lang{add_edit_calendars_tab3} p1 if ($options{users} eq "1") { $return_text .=<$lang{add_edit_calendars_tab4} p1 } $return_text .=<

    $lang{help_on_this}  

     
    p1 if ($options{all_calendars_selectable} eq "1") { $return_text.=<$lang{selectable_calendars1}
    ($lang{selectable_calendars3})
      p1 } else { if (scalar (keys %calendars) > 1 || $add_edit_cal_action ne "edit") { $return_text .=<$lang{selectable_calendars1}
    $lang{selectable_calendars2} $lang{help_on_this} $lang{help_on_this}
    p1 } } $return_text .=<

    $lang{help_on_this}

     

    $lang{help_on_this}
    $lang{popup_window_size2} $lang{help_on_this}

    p1 if ($options{users} eq "1") { $return_text .=<

    $lang{help_on_this} p1 } else { $return_text .=<$lang{no_users_on_add} p1 } $return_text .=< p1 } $return_text .=<

    p1 my $need_password = 1; $need_password = 0 if ($options{disable_passwords} eq "1"); $need_password = 0 if ($logged_in_as_root || $logged_in_as_current_cal_admin); if ($add_edit_cal_action eq "edit") { if ($need_password eq "1") { $return_text .=<

    $lang{help_on_this}
    $lang{new_password}
    $lang{repeat_new_password}
    p1 } elsif ($options{disable_passwords} ne "1") { $return_text .=<  
    $lang{no_password_needed}
    p1 } $return_text .=<  
     
    $lang{preview_warning}

    $lang{del_cal_button3}


    p1 } elsif ($add_edit_cal_action eq "add") { if ($options{disable_passwords} ne "1") { $return_text .=<
    $lang{choose_password}   $lang{help_on_this}
    $lang{repeat_password}
    p1 } $return_text .=<  
     
    $lang{preview_warning}

    p1 } $return_text .=< p1 } else { #a user added/edited/deleted a calendar--do checks and perform resulting action my @results_messages; my $cal_id = $current_cal_id; # need to validate cal id for add/edit my $cal_valid = 1; if ($q->param('del_cal_button') ne "") { #delete calendar &load_events("all"); &normalize_timezone(); my $del_valid=1; #check password. if ($options{disable_passwords} ne "1" && !$logged_in_as_root && !$logged_in_as_current_cal_admin) { $del_valid=0; push @results_messages, "$lang{update_cal_error1}$current_calendar{title}"; } # prevent delete of primary calendar if ($cal_id eq "0") { $del_valid=0; push @results_messages, $lang{update_cal_error2}; } if ($del_valid == 1) { #actually delete the calendar. # first, delete all its events my @deleted_event_ids; my @updated_event_ids; foreach $event_id (keys %events) { # if the event is only on one calendar, delete it if (scalar@{$events{$event_id}{cal_ids}} == 1) { if ($events{$event_id}{cal_ids}[0] eq $cal_id) { push @deleted_event_ids, $event_id;} else {next;} } else { # otherwise, just remove that calendar from its cal_ids my $index=0; foreach $temp_cal_id (@{$events{$event_id}{cal_ids}}) { if ($temp_cal_id eq $cal_id) { break; } $index++; } splice @{$events{$event_id}{cal_ids}}, $index, 1; { push @updated_event_ids, $event_id;} } } &delete_events(\@deleted_event_ids); &update_events(\@updated_event_ids); # next, delete the calendar in question &delete_calendar($cal_id); # redundant in flat-file mode, needed for sql mode # finally, delete any references in other calendars (background calendars) my @cals_to_update; foreach $calendar_id (sort {$a <=> $b} keys %calendars) { #$debug_info .= "calendar $calendar_id\n"; if ($calendars{$calendar_id}{local_background_calendars}{$cal_id} eq "1") { delete $calendars{$calendar_id}{local_background_calendars}{$cal_id}; push @cals_to_update, $calendar_id; } if ($calendars{$calendar_id}{selectable_calendars}{$cal_id} eq "1") { delete $calendars{$calendar_id}{selectable_calendars}{$cal_id}; push @cals_to_update, $calendar_id; } } &update_calendars(\@cals_to_update); my $temp = $lang{update_cal_error3}; $temp =~ s/###title###/$current_calendar{title}/; push @results_messages, $temp; } # properly format errors, warnings my @messages = split ("\n",$cal_del_results); $cal_del_results=""; foreach $message (@messages) { $message =~ s/(.*$lang{Warning})/$1<\/span>/i; $message =~ s/(.*$lang{Error})/$1<\/span>/i; $cal_del_results .= "$message
    \n"; } #$results{text} = join "\n", @messages; $cal_del_results = "
      $cal_del_results
    "; } else { #the user added/updated a calendar #check all input fields for validity my $cal_title = $q->param('cal_title'); my $cal_link = $q->param('cal_link'); my $cal_details = $q->param('cal_details'); my @local_background_calendars = $q->param('background_calendars'); my @selectable_calendars = $q->param('selectable_calendars'); my $list_background_calendars_together = $q->param('list_background_calendars_together'); my $background_events_display_style = $q->param('background_events_display_style'); my $background_events_fade_factor = $q->param('background_events_fade_factor'); my $background_events_color = $q->param('background_events_color'); my $new_calendars_automatically_selectable = "y" if ($q->param('new_calendars_automatically_selectable') =~ "y"); my $allow_remote_calendar_requests = $q->param('allow_remote_calendar_requests'); my $remote_calendar_requests_require_password = $q->param('remote_calendar_requests_require_password'); my $remote_calendar_requests_password = $q->param('remote_calendar_requests_password'); my $new_remote_calandars_xml = $q->param('new_remote_calandars_xml'); my $calendar_events_color = $q->param('calendar_events_color'); my $default_number_of_months = $q->param('default_number_of_months'); my $max_number_of_months = $q->param('max_months'); my $gmtime_diff = $q->param('gmtime_diff'); my $date_format = $q->param('date_format'); $date_format = lc $date_format; my $week_start_day = $q->param('week_start_day'); my $event_change_email = $q->param('event_change_email'); my $info_window_size = $q->param('popup_window_size'); if ($info_window_size !~ /^\d{1,}x\d{1,}$/) { $cal_valid=0; my $temp=$lang{update_cal_error4}; $temp =~ s/###size###/$info_window_size/; push @results_messages, $temp; } my $custom_template = $q->param('custom_template'); $custom_template =~ s/http:\/\///g; my $custom_stylesheet = $q->param('custom_stylesheet'); $custom_stylesheet =~ s/http:\/\///g; my $cal_password = $q->param('cal_password'); my $new_cal_password = $q->param('new_cal_password'); my $repeat_new_cal_password = $q->param('repeat_new_cal_password'); $cal_title =~ s/\r//g; # some browsers sneak these in $cal_link =~ s/\r//g; # some browsers sneak these in $cal_details =~ s/\r//g; # some browsers sneak these in #check for required fields if ($cal_title eq "") { $cal_valid=0; push @results_messages, $lang{update_cal_error5}; } #strip all html from label field if ($cal_title =~ m/<(.*)>/) { push @results_messages, $lang{update_cal_error6}; $cal_title =~ s/<(.*)>//g; } $cal_link =~ s/http:\/\///g; #strip http:// from link field #check for date format if ($date_format !~ /^(mm|dd|yy)\W(mm|dd|yy)\W(mm|dd|yy)$/ ) { $cal_valid=0; push @results_messages, $lang{update_cal_error6_5}; } if ($add_edit_cal_action eq "edit") { if ($options{disable_passwords} ne "1") { #this action is an edit of an existing calendar, so we need to make a replacement. if (!(defined $calendars{$cal_id})) { $cal_valid=0; push @results_messages, $lang{update_cal_error7}; } else { #check password if ($options{disable_passwords} ne "1" && !$logged_in_as_root && !$logged_in_as_current_cal_admin) { $cal_valid=0; push @results_messages, "$lang{update_cal_error1} $calendars{$cal_id}{title}"; } } #check for new password if ($new_cal_password ne "" || $repeat_new_cal_password ne "") { if ($new_cal_password ne $repeat_new_cal_password) { $cal_valid=0; push @results_messages, $lang{update_cal_error8}; } else { $calendars{$cal_id}{password} = crypt($new_cal_password, $options{salt}); } } } # check for gmtime_diff field if ($options{force_single_timezone} eq "1" && $cal_id ne "0") { $gmtime_diff = $calendars{0}{gmtime_diff} } # encrypt remote calendar password $remote_calendar_requests_password = crypt($remote_calendar_requests_password, $options{salt}); if ($cal_valid == 1) { # update calendar record my $xml_data = ""; $calendars{$cal_id}{title} = $cal_title; $calendars{$cal_id}{details} = $cal_details; $calendars{$cal_id}{link} = $cal_link; $calendars{$cal_id}{new_calendars_automatically_selectable} = $new_calendars_automatically_selectable; $calendars{$cal_id}{list_background_calendars_together} = $list_background_calendars_together; $calendars{$cal_id}{calendar_events_color} = $calendar_events_color; $calendars{$cal_id}{background_events_display_style} = $background_events_display_style; $calendars{$cal_id}{background_events_fade_factor} = $background_events_fade_factor; $calendars{$cal_id}{background_events_color} = $background_events_color; $calendars{$cal_id}{default_number_of_months} = $default_number_of_months; $calendars{$cal_id}{max_number_of_months} = $max_number_of_months; $calendars{$cal_id}{gmtime_diff} = $gmtime_diff; $calendars{$cal_id}{date_format} = $date_format; $calendars{$cal_id}{week_start_day} = $week_start_day; $calendars{$cal_id}{event_change_email} = $event_change_email; $calendars{$cal_id}{info_window_size} = $info_window_size; $calendars{$cal_id}{custom_template} = $custom_template; $calendars{$cal_id}{custom_stylesheet} = $custom_stylesheet; $calendars{$cal_id}{allow_remote_calendar_requests} = $allow_remote_calendar_requests; $calendars{$cal_id}{remote_calendar_requests_require_password} = $remote_calendar_requests_require_password; $calendars{$cal_id}{remote_calendar_requests_password} = $remote_calendar_requests_password; # update local background calendars foreach $local_background_calendar (keys %{$calendars{$cal_id}{local_background_calendars}}) { delete $calendars{$cal_id}{local_background_calendars}{$local_background_calendar}; } foreach $local_background_calendar (@local_background_calendars) { $calendars{$cal_id}{local_background_calendars}{$local_background_calendar} = 1; } #$debug_info .= "new remote calendars xml: $new_remote_calandars_xml\n"; #delete existing remote background calendars foreach $current_remote_calendar_id (keys %{$current_calendar{remote_background_calendars}}) { if ($q->param("delete_remote_calendar_$current_remote_calendar_id") ne "") { my $temp = $lang{get_remote_calendar5}; $temp =~ s/###remote url###/$current_calendar{remote_background_calendars}{$current_remote_calendar_id}{url}/g; $temp =~ s/###remote id###/$current_calendar{remote_background_calendars}{$current_remote_calendar_id}{remote_id}/g; push @results_messages, $temp; delete $calendars{$current_cal_id}{remote_background_calendars}{$current_remote_calendar_id}; } } # update remote background calendars unless ($new_remote_calandars_xml eq "") { my %new_remote_calendars = %{&xml2hash($new_remote_calandars_xml)}; #$debug_info .= "$new_remote_calendars{remote_calendars}{remote_calendar}\n"; my $new_remote_cal_id = &max(keys %{$calendars{$cal_id}{remote_background_calendars}}) + 1; #$debug_info .= (scalar keys %{$calendars{$cal_id}{remote_background_calendars}})." remote calendars already\n"; #$debug_info .= "new_remote_cal_id: $new_remote_cal_id\n"; if ($new_remote_calendars{remote_calendars}{remote_calendar} =~ /array/i) { # multiple remote background calendars foreach $temp (@{$new_remote_calendars{remote_calendars}{remote_calendar}}) { my %new_remote_calendar = %{$temp}; $found=0; foreach $current_remote_calendar_id (keys %{$current_calendar{remote_background_calendars}}) { #$debug_info .= "comparing $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{url} with $new_remote_calendar{url}\n"; $found=1 if ($current_calendar{remote_background_calendars}{$current_remote_calendar_id}{url} eq $new_remote_calendar{url} && $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{type} eq $new_remote_calendar{type} && $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{version} eq $new_remote_calendar{version} && $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{password} eq $new_remote_calendar{password} && $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{remote_id} eq $new_remote_calendar{remote_id}); } if ($found==0) { $calendars{$cal_id}{remote_background_calendars}{$new_remote_cal_id}{url} = $new_remote_calendar{url}; $calendars{$cal_id}{remote_background_calendars}{$new_remote_cal_id}{type} = $new_remote_calendar{type}; $calendars{$cal_id}{remote_background_calendars}{$new_remote_cal_id}{version} = $new_remote_calendar{version}; $calendars{$cal_id}{remote_background_calendars}{$new_remote_cal_id}{password} = $new_remote_calendar{password}; $calendars{$cal_id}{remote_background_calendars}{$new_remote_cal_id}{remote_id} = $new_remote_calendar{remote_id}; $new_remote_cal_id++; } else { my $temp = $lang{get_remote_calendar4}; $temp =~ s/###remote url###/$new_remote_calendar{url}/g; $temp =~ s/###remote id###/$new_remote_calendar{remote_id}/g; push @results_messages, $temp; } #$debug_info .= "remote calendar: $new_remote_calendar{url}\n"; #$debug_info .= "type: $new_remote_calendar{type}\n"; } } else { # single remote background calendar # check against existing remote background calendars. my %new_remote_calendar = %{$new_remote_calendars{remote_calendars}{remote_calendar}}; $found=0; foreach $current_remote_calendar_id (keys %{$current_calendar{remote_background_calendars}}) { #$debug_info .= "comparing $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{url} with $new_remote_calendar{url}\n"; if ($current_calendar{remote_background_calendars}{$current_remote_calendar_id}{url} eq $new_remote_calendar{url} && $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{type} eq $new_remote_calendar{type} && $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{version} eq $new_remote_calendar{version} && $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{password} eq $new_remote_calendar{password} && $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{remote_id} eq $new_remote_calendar{remote_id}) { $found=1; } } if ($found==0) { $calendars{$cal_id}{remote_background_calendars}{$new_remote_cal_id}{url} = $new_remote_calendar{url}; $calendars{$cal_id}{remote_background_calendars}{$new_remote_cal_id}{type} = $new_remote_calendar{type}; $calendars{$cal_id}{remote_background_calendars}{$new_remote_cal_id}{version} = $new_remote_calendar{version}; $calendars{$cal_id}{remote_background_calendars}{$new_remote_cal_id}{password} = $new_remote_calendar{password}; $calendars{$cal_id}{remote_background_calendars}{$new_remote_cal_id}{remote_id} = $new_remote_calendar{remote_id}; } else { my $temp = $lang{get_remote_calendar4}; $temp =~ s/###remote url###/$new_remote_calendar{url}/g; $temp =~ s/###remote id###/$new_remote_calendar{remote_id}/g; push @results_messages, $temp; } } } #$calendars{$cal_id}{remote_background_calendars} = $remote_calendar_requests_password; # update selectable calendars foreach $selectable_calendar (keys %{$calendars{$cal_id}{selectable_calendars}}) { delete $calendars{$cal_id}{selectable_calendars}{$selectable_calendar}; } foreach $selectable_calendar (@selectable_calendars) { $calendars{$cal_id}{selectable_calendars}{$selectable_calendar} = 1; } } if ($cal_valid == 1) { #all checks successful, add/update calendar! &update_calendar($cal_id); push @results_messages, "$calendars{$current_cal_id}{title} $lang{update_cal_success}"; } else { $cal_add_results .= $lang{update_cal_failure}; } } else { # add new calendar #check new password if ($options{disable_passwords} ne "1") { if ($new_cal_password ne $repeat_new_cal_password) { $cal_valid=0; push @results_messages, $lang{update_cal_error9}; } elsif ($new_cal_password eq "" || $repeat_new_cal_password eq "" ) { $cal_valid=0; push @results_messages, $lang{update_cal_error10}; } else { $input_password = crypt($new_cal_password, $options{salt}); } } my $new_cal_id; if ($cal_valid == 1) { $new_cal_id = $max_action_id + int(rand(100)); # just in case several people decide to add something new at the same time. $new_calendars{$new_cal_id}{id} = $new_cal_id; $new_calendars{$new_cal_id}{title} = $cal_title; $new_calendars{$new_cal_id}{details} = $cal_details; $new_calendars{$new_cal_id}{link} = $cal_link; $new_calendars{$new_cal_id}{list_background_calendars_together} = $list_background_calendars_together; $new_calendars{$new_cal_id}{calendar_events_color} = $calendar_events_color; $new_calendars{$new_cal_id}{background_events_fade_factor} = $background_events_fade_factor; $new_calendars{$new_cal_id}{background_events_color} = $background_events_color; $new_calendars{$new_cal_id}{default_number_of_months} = $default_number_of_months; $new_calendars{$new_cal_id}{max_number_of_months} = $max_number_of_months; $new_calendars{$new_cal_id}{gmtime_diff} = $gmtime_diff; $new_calendars{$new_cal_id}{date_format} = $date_format; $new_calendars{$new_cal_id}{week_start_day} = $week_start_day; $new_calendars{$new_cal_id}{info_window_size} = $info_window_size; $new_calendars{$new_cal_id}{custom_template} = $custom_template; $new_calendars{$new_cal_id}{custom_stylesheet} = $custom_stylesheet; $new_calendars{$new_cal_id}{password} = $input_password; $new_calendars{$new_cal_id}{update_timestamp} = $rightnow; $new_calendars{$new_cal_id}{allow_remote_calendar_requests} = $allow_remote_calendar_requests; $new_calendars{$new_cal_id}{remote_calendar_requests_require_password} = $remote_calendar_requests_require_password; $new_calendars{$new_cal_id}{remote_calendar_requests_password} = $remote_calendar_requests_password; # local background calendars foreach $local_background_calendar (@local_background_calendars) { $new_calendars{$new_cal_id}{local_background_calendars}{$local_background_calendar} = 1; } # selectable calendars foreach $selectable_calendar (@selectable_calendars) { $new_calendars{$new_cal_id}{selectable_calendars}{$selectable_calendar} = 1; } } # check for refreshes! if ($cal_valid == 1) { my %latest_new_calendar = $new_calendars{$latest_new_cal_id}; if ($new_calendars{$new_cal_id}{title} eq $latest_new_calendar{title} && $new_calendars{$new_cal_id}{details} eq $latest_new_calendar{details} && $new_calendars{$new_cal_id}{link} eq $latest_new_calendar{link}) { $cal_valid = 0; push @results_messages, $lang{update_cal_dup}; } } if ($cal_valid == 1) { #all checks successful, add calendar! &add_action($new_cal_id, "new_calendar"); my $new_cal_details = &generate_cal_details($new_calendars{$new_cal_id}); $new_cal_details =~ s///; $new_cal_details =~ s/Link directly.+<\/a>//s; if ($options{new_calendar_request_notify} ne "") { my $body = <$lang{add_cal_success3} p1 &send_email($options{new_calendar_request_notify}, $options{reply_address}, $options{reply_address}, $lang{add_cal_email_notify2}, $body); } my $temp = $lang{add_cal_success1}; # add successful $temp = $lang{add_cal_success4} if ($add_edit_cal_action eq "edit"); # update successful $cal_add_results .= <

    $temp

    $new_cal_details

    $lang{add_cal_success2}

    p1 } else { push @results_messages, $lang{add_cal_fail1}; } } } # properly format errors & warnings my $message_results=""; foreach $results_message (@results_messages) { $results_message =~ s/(.*$lang{Warning})/$1<\/span>/i; $results_message =~ s/(.*$lang{Error})/$1<\/span>/i; $message_results .= "
  • $results_message
  • \n"; } $cal_add_results = "
      $message_results
    $cal_add_results"; } $return_text .=< $cal_add_results $cal_del_results p1 return $return_text; } #********************end add_edit_calendars code***************************** sub view_pending_calendars { my $return_text = ""; if ($q->param('approve_cal_button') eq "") { #view pending calendars main screen $cal_details =""; $shared_cal_select_size = scalar keys %calendars; $return_text.=< $lang{view_pending_calendars1}

    p1 if (scalar keys %new_calendars == 0) { $return_text.=< $lang{view_pending_calendars2}

    p1 } else { $return_text.=< p1 foreach $new_cal_id (keys %new_calendars) { my $new_cal_details = &generate_cal_details($new_calendars{$new_cal_id}); $new_cal_details =~ s///; $new_cal_details =~ s/Link directly.+<\/a>//s; #Link directly to this calendar:
    #$script_url/$name?cal_id=$calendar{id} $return_text.=< $new_cal_details

    $lang{view_pending_calendars3}

    $lang{view_pending_calendars4}

    p1 } $return_text.=<
    p1 } } else { #view pending calendars approve/delete results screen my @pending_calendars_to_delete; my @calendars_to_add; my @calendars_to_update; $cal_details =""; $shared_cal_select_size = scalar keys %calendars; $return_text.=< $lang{view_pending_calendars6}

    p1 #check password $input_password = crypt($q->param('main_password'), $options{salt}); if ($options{disable_passwords} ne "1") { if ($input_password ne $master_password) { $return_text .=<
  • $lang{view_pending_calendars7}
  • p1 return $return_text; } } #go through each new calendar in the new calendars file--take appropriate action foreach $new_cal_id (keys %new_calendars) { my $new_cal_details = &generate_cal_details($new_calendars{$new_cal_id}); if ($q->param("new_cal_$new_cal_id") eq "approve") { $max_cal_id+=1; #calculate new id # for the new calendar foreach $cal_id (keys %calendars) { if ($calendars{$cal_id}{new_calendars_automatically_selectable} =~ "y") { $calendars{$cal_id}{selectable_calendars}{$max_cal_id} = 1; push @calendars_to_update, $cal_id; } } $calendars{$max_cal_id} = $new_calendars{$new_cal_id}; $calendars{$max_cal_id}{id} = $max_cal_id; # make sure the calendar can select itself. $calendars{$max_cal_id}{selectable_calendars}{$max_cal_id} = 1 if (scalar keys %{$calendars{$max_cal_id}{selectable_calendars}} > 0); delete $new_calendars{$new_cal_id}; push @pending_calendars_to_delete, $new_cal_id; push @calendars_to_add, $max_cal_id; $approve_or_delete_result = $lang{view_pending_calendars8}; } elsif ($q->param("new_cal_$new_cal_id") eq "delete") { delete $new_calendars{$new_cal_id}; push @pending_calendars_to_delete, $new_cal_id; $approve_or_delete_result = $lang{view_pending_calendars9}; } else { $approve_or_delete_result = $lang{view_pending_calendars10}; } $new_cal_details =~ s///; $new_cal_details =~ s/Link directly.+<\/a>//s; $return_text .= <
    $new_cal_details

    $approve_or_delete_result
    p1 } &delete_pending_actions(\@pending_calendars_to_delete); &add_calendars(\@calendars_to_add); &update_calendars(\@calendars_to_update); } $return_text.=< p1 return $return_text; } #********************end view_pending_calendars code***************************** sub do_calendar_list_view() { my $return_text = ""; if ($cal_num_months> 1) { $cal_title_string .=< $prev_month_link $cal_title_string $next_month_link
    p1 if ($display_type == 1) { #list view $return_text .= &render_list($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year); } else { #calendar view $return_text .= &render_calendar($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year); } $return_text .=< p1 return $return_text; } ###############end do_calendar_list_view ################### sub add_edit_events_interface() { my $temp=""; $html_output =~ s//\n$temp\n/; my $return_text = ""; $add_edit_event = "add" if ($add_edit_event eq ""); $add_edit_string = $lang{add_or_edit1}; $event_details =""; $event_start_date = $current_calendar{date_format}; if ($q->param('add_date_timestamp')+0 == 0) { # no date supplied--generic add event # no date supplied--generic add event if ($cal_start_year ne "") { $event_start_date =~ s/yy/$cal_start_year/; } else { $event_start_date =~ s/yy/$rightnow_year/; } } else { # add event on a particular date -- calculate date my @event_start_date_array = gmtime $q->param('add_date_timestamp'); my $mm = $event_start_date_array[4]+1; my $md = $event_start_date_array[3]; my $yy = $event_start_date_array[5]+1900; $event_start_date =~ s/mm/$mm/; $event_start_date =~ s/dd/$md/; $event_start_date =~ s/yy/$yy/; } my $recur_end_date = $current_calendar{date_format}; $recur_end_date =~ s/mm/12/; $recur_end_date =~ s/dd/31/; $recur_end_date =~ s/yy/$rightnow_year/; $event_days = "1"; $event_icon = "blank"; my %current_event; my $unit_number_text = ""; my $event_unit_number = ""; $add_edit_string = $lang{add_or_edit2} if ($add_edit_event eq "edit"); if ($current_event_id ne "") { #select the appropriate event to edit %current_event = %{$events{$current_event_id}}; @current_cal_ids = @{$current_event{cal_ids}}; %current_calendar = %{$calendars{$current_cal_ids[0]}}; #$cal_title=$calendars{$current_event{cal_id}}{title}; $event_name = $current_event{title}; $event_details = $current_event{details}; $event_start_date = $current_calendar{date_format}; my @temp_date = gmtime($current_event{start}); $temp_date[5] += 1900; $temp_date[4] += 1; $event_start_date =~ s/mm/$temp_date[4]/; $event_start_date =~ s/dd/$temp_date[3]/; $event_start_date =~ s/yy/$temp_date[5]/; $event_days=$current_event{days}; $event_icon = $current_event{icon}; $event_bgcolor = $current_event{bgcolor}; $event_unit_number = $current_event{unit_number}; $unit_number_text = $event_unit_number; $unit_number_text =~ s/(\d)//g; } $return_text .=< $add_edit_string

    $lang{fields_text1} $lang{fields_text2} $lang{fields_text3}
    p1 my @selectable_cal_ids; if ($options{all_calendars_selectable}) { @selectable_cal_ids = keys %calendars; } else { @selectable_cal_ids = keys %{$current_calendar{selectable_calendars}}; push @selectable_cal_ids, $current_cal_id; } my %evt_calendar = %{$calendars{$current_cal_id}}; %evt_calendar = %{$calendars{$current_event{cal_ids}[0]}} if ($add_edit_event eq "edit"); if ($add_edit_event eq "edit" || scalar @selectable_cal_ids == 0) { # force event calendar $return_text .=<
    $lang{event_calendar}
    $evt_calendar{title}
    p1 } else { # user can select event calendar $return_text .=< $lang{event_calendar}
    p1 foreach $cal_ref_id (sort {$calendars{$a}{title} cmp $calendars{$b}{title}} @selectable_cal_ids) { my $selected = ""; next if ($cal_ref_id eq $evt_calendar{id}); foreach $selected_cal_id (@{$events{$current_event_id}{cal_ids}}) { if ($cal_ref_id eq $selected_cal_id) { $selected = " selected"; last; } } $return_text .=<$calendars{$cal_ref_id}{title} p1 } $return_text .=< $lang{help_on_this}
    p1 } my $all_day_event_checked = ""; if ($options{new_events_all_day}) { $all_day_event_checked = "checked";} my $event_start_time = $options{default_event_start_time}; my $event_end_time = $options{default_event_end_time}; if ($current_event_id ne "") { $all_day_event_checked = "checked"; $all_day_event_checked = "" if ($current_event{all_day_event} ne "1"); $event_start_time = &formatted_time($current_event{start},"hh:mm ampm"); $event_end_time = &formatted_time($current_event{end},"hh:mm ampm"); $event_end_time = "" if ($current_event{no_end_time} eq "1"); } my $all_day_event_toggle0_style = "display:none;"; if ($all_day_event_checked ne "checked") { $all_day_event_toggle0_style = ""; } $return_text .=<

    $lang{help_on_this}  
    p1 $return_text .=<
    event icon
    p1 if ($options{unit_number_icons} == 1) { $return_text .=< $unit_number_text
    p1 } $return_text .=< p1 $return_text .=<
    p1 } $return_text .=<
    $lang{recurring_event_edit1}
    $lang{recurring_event_change_all2}
    p1 } else { $return_text .=< p1 } else { $return_text .=< $lang{help_on_this}  
    $lang{recurrence_type}
    $lang{help_on_this}
    $lang{same_day_of_month}
    $lang{same_weekday} $lang{of_the_month}
    p1 my $temp =< p1 $lang{every_x_days} =~ s/###x###/$temp/; $return_text .=< $lang{every_x_days}
    p1 my $temp =< p1 $lang{every_x_weeks} =~ s/###x###/$temp/; $return_text .=< $lang{every_x_weeks}
    $lang{fit_into_year}
    $lang{help_on_this}
    $lang{every_momth}
    $lang{certain_months1}
    $lang{certain_months2}

    p1 } $return_text .=<
    $lang{preview_event1}

    $lang{preview_event2}

    $lang{preview_dates1}

    $lang{preview_dates2}

    p1 my $need_password = 1; $need_password = 0 if ($options{disable_passwords} eq "1"); $need_password = 0 if ($logged_in_as_root || $logged_in_as_current_cal_admin || $logged_in_as_current_cal_user); if ($need_password == 1) { $return_text .=<
    p1 } else { $return_text .=<  
    $lang{no_password_needed}
    p1 } if ($add_edit_event eq "edit") { $return_text .=<  
    $lang{add_event2_update}
    $lang{delete_event2}
    p1 } else { $return_text .=<  

    $lang{add_event2}


    p1 } $return_text .=< p1 } sub add_edit_events { $event_details_template =~ s/###export event link###/$lang{event_details_export_disable}/g; $event_details_template =~ s/###edit event link###/$lang{event_details_edit_disable}/g; $event_details_template =~ s/###email reminder link###/$lang{event_email_reminder_disable}/g; my %results; my $recurring_event = $q->param('recurring_event'); my $all_in_series = $q->param('all_in_series'); # load (reload) all events (we have to write events beyond the default time window) if ($options{data_storage_mode} == 0) { unless ($loaded_all_events eq "1") { &load_events("all"); &normalize_timezone(); } } my $login_valid = 0; if ($options{disable_passwords} eq "1") { $login_valid = 1 } elsif ($current_cal_id ne "") { #$debug_info .= "current_cal_id: $current_cal_id\n"; if ($options{multi_calendar_event_mode} == 0 || $options{multi_calendar_event_mode} == 1) { # only the event's calendar's user or the root user are allowed $login_valid = 1 if ($logged_in_as_root || $logged_in_as_current_cal_admin || $logged_in_as_current_cal_user); # current calendar user } elsif ($options{multi_calendar_event_mode} == 2) { # any of the event's calendars' users or the root user are allowed if ($logged_in_as_root || $logged_in_as_current_cal_admin || $logged_in_as_current_cal_user) { # current calendar user $login_valid = 1; } else { my $cal_password_valid = 0; foreach $cal_id (@evt_other_cal_ids) { my $temp = $cal_id; $cal_password_valid = 1 if ($profile->{calendar_permissions}->{$cal_id}->{admin} eq "1"); # shared calendar admin $cal_password_valid = 1 if ($profile->{calendar_permissions}->{$cal_id}->{user} ne ""); # shared calendar user } $login_valid = 1 if ($cal_password_valid == 1); } } } if ($q->param('del_event_button') ne "" || $api_command eq "delete_event") { $del_valid = 1; #delete event. if ($login_valid == 0) { $del_valid = 0; push @{$results{messages}}, "[error]$lang{update_event_err1} '$current_calendar{title}'"; } if (!defined $events{$current_event_id}) { $del_valid=0; push @{$results{messages}}, "[error]$lang{update_event_err2}"; } if ($del_valid == 1) { #actually delete the event(s). if ($all_in_series ne "1") { my $subj = $lang{notify_subj}; $subj =~ s/\$1/$script_url\/$name/; my $body = $lang{event_delete_notify}; $body =~ s/\$1/$events{$current_event_id}{title}/; $body =~ s/\$2/$calendars{$current_cal_id}{title}/; foreach $email (@{$current_calendar{delete_emails}}) { #$debug_info .= "email notification sent to $email\n"; &send_email($email, $options{reply_address}, $options{reply_address}, $subj, $body) if ($options{email_mode} > 0); } &delete_event($current_event_id); push @{$results{messages}}, "[status]$lang{update_event_delete_successful}"; } else { # get the ids of the events in the series. my @events_in_series = &get_events_in_series($q->param('series_id')); &normalize_timezone(); &delete_events(\@events_in_series); push @{$results{messages}}, "[status]$lang{update_event_delete_successful_recurring}"; } $results{success} = 1; } else { $results{success} = 0; } } else { # not a delete if (!$login_valid) { if ($options{anonymous_events}) { my $temp = $lang{update_event_err16}; $temp =~ s/###calendar###/$current_calendar{title}<\/b>/g; push @{$results{messages}}, ("[error]".$temp); } else { push @{$results{messages}}, "[error]".($lang{update_event_err1}."'".$current_calendar{title}."'"); } } #check all input fields for validity my $event_valid = 1; my $event_id = $q->param('evt_id'); # only if editing. #my $event_cal_id = $current_cal_id; my @evt_other_cal_ids; @evt_other_cal_ids = $q->param('evt_other_cal_ids') if ($options{multi_calendar_event_mode} > 0); my $event_cal_password = $q->param('cal_password'); my $event_title = $q->param('evt_title'); my $event_icon = $q->param('evt_icon'); my $event_details = $q->param('evt_details'); my $event_unit_number = $q->param('unit_number'); my $event_bgcolor = $q->param('evt_bgcolor'); my $event_series_id = $q->param('series_id'); my $event_duration = 0; my $event_start_timestamp = 0; my $event_end_timestamp = 0; #my $event_start_time_offset = 0; $recur_end_date = $q->param('recur_end_date'); my $all_day_event = $q->param('all_day_event'); my $no_end_time = ""; my $event_start_time = $q->param('evt_start_time'); my $event_end_time = $q->param('evt_end_time'); $event_start_date = $q->param('evt_start_date'); my $event_days = $q->param('evt_days'); my %recurrence_parms; $recurrence_parms{'recurrence_type'} = $q->param('recurrence_type'); $recurrence_parms{'weekday_of_month_type'} = $q->param('weekday_of_month_type'); $recurrence_parms{'every_x_days'} = $q->param('every_x_days'); $recurrence_parms{'every_x_weeks'} = $q->param('every_x_weeks'); $recurrence_parms{'year_fit_type'} = $q->param('year_fit_type'); $recurrence_parms{'recur_end_date'} = $q->param('recur_end_date'); my @custom_months = $q->param('custom_months'); #$debug_info .= (scalar @custom_months)." custom months\n"; #$debug_info .= "q->param('custom_months'): ".$q->param('custom_months')."\n"; $recurrence_parms{'custom_months'} = \@custom_months; $recurrence_parms{'recur_end_timestamp'} = 0; my %input_parms; # parms that are input by the user, but not stored as final event data $input_parms{'update_all_in_series'} = $q->param('all_in_series'); $input_parms{'event_days'} = $event_days; $input_parms{'event_start_time'} = $event_start_time; $input_parms{'event_end_time'} = $event_end_time; $input_parms{'all_day'} = $all_day_event; # Check data for legitimacy. # some of these checks might be a bit redundant. if ($current_cal_id eq "") { $event_valid = 0; push @{$results{messages}}, "[error]".$lang{update_event_err3}; } if ($event_title eq "") { $event_valid = 0; push @{$results{messages}}, "[error]".$lang{update_event_err4}; } if ($event_icon eq "") { $event_valid = 0; push @{$results{messages}}, "[error]".$lang{update_event_err5}; } $event_title =~ s/\r//g; # some browsers sneak these in $event_details =~ s/\r//g; # some browsers sneak these in #strip html if ($event_title =~ m/<(.*)>/) { my $temp = $event_title; $temp =~ s//>/g; push @{$results{messages}}, "[warning]".$lang{update_event_err7}; $event_title =~ s/<(.*)>//g; } # strip out all non-numeric information from unit number my $unit_number = $event_unit_number; $unit_number =~ s/\D//g; #check event calendar name against existing calendars if (!defined == $calendars{$current_cal_id}) { $event_valid = 0; push @{$results{messages}}, "[error]".$lang{update_event_err8}; } $event_valid = 0 if ($login_valid == 0 && !$options{anonymous_events}); #push @{$results{messages}}, "[error]".$lang{update_event_err1}."'".$current_calendar{title}."'"; # check dates if ($event_valid == 1) { my $verify_date_results = &verify_date($event_start_date); if ($verify_date_results ne "") { $event_valid = 0; my @sub_results = split("\n", $verify_date_results); foreach $sub_result (@sub_results) { push @{$results{messages}}, "[error]$lang{update_event_err9} $sub_result"; } if ($event_days eq "") { push @{$results{messages}}, "[error]$lang{update_event_err9}$lang{date_verify_err2}"; } if ($event_days =~ m/\D/ || $event_days <= 0) { my $temp = $lang{date_verify_err3}; $temp =~ s/\$1/$event_days/; push @{$results{messages}}, "[error]$lang{update_event_err9}$temp"; } } } # check recurring "repeat until" date if ($event_valid == 1) { if ($recurring_event ne "" && $add_edit_event eq "add") { my $verify_date_results = &verify_date($recurrence_parms{'recur_end_date'}, \%recurrence_parms); if ($verify_date_results ne "") { $event_valid = 0; my @sub_results = split("\n", $verify_date_results); foreach $sub_result (@sub_results) { push @{$results{messages}}, "[error]$lang{update_event_err10} $sub_result"; } } } } # check time if ($event_valid == 1 && $all_day_event ne "1") { my $verify_time_results = &verify_time($event_start_time); if ($verify_time_results ne "") { $event_valid = 0; my @sub_results = split("\n", $verify_time_results); foreach $sub_result (@sub_results) { push @{$results{messages}}, "[error]$lang{update_event_err14} $sub_result"; } } if ($event_end_time ne "") { my $verify_time_results = &verify_time($event_end_time); if ($verify_time_results ne "") { $event_valid = 0; my @sub_results = split("\n", $verify_time_results); foreach $sub_result (@sub_results) { push @{$results{messages}}, "[error]$lang{update_event_err15} $sub_result"; } } } } if ($event_valid == 1) { my ($start_mon, $start_mday, $start_year) = &format2mdy($event_start_date, $current_calendar{date_format}); $start_mon--; # convert month to 0-11 format #$debug_info .= "(add_edit_event) start_mday: $start_mday\n"; #$debug_info .= "(add_edit_event) start_mon: $start_mon\n"; #$debug_info .= "(add_edit_event) start_year: $start_year\n"; #$debug_info .= "(add_edit_event) event_days: $event_days\n"; #$debug_info .= "(add_edit_event) event_start_time: $event_start_time\n"; #$debug_info .= "(add_edit_event) event_end_time: $event_end_time\n"; #$debug_info .= "(add_edit_event) all_day_event: $all_day_event\n"; ($event_start_timestamp, $event_end_timestamp) = ×tamp_from_datetime($start_mday,$start_mon,$start_year,$event_days,$event_start_time,$event_end_time,$all_day_event); $event_duration = $event_end_timestamp - $event_start_timestamp; $no_end_time = 1 if ($event_duration == 1); $recurrence_parms{'duration'} = $event_duration if ($recurring_event ne ""); #if ($event_start_timestamp == $event_end_timestamp) # {$event_end_timestamp +=1;} # give all events a duration of at least 1 second if ($recurring_event ne "" && $add_edit_event eq "add") { my ($recur_end_mon, $recur_end_mday, $recur_end_year) = &format2mdy($recurrence_parms{'recur_end_date'}, $current_calendar{date_format}); $recur_end_mon--; $recurrence_parms{'recur_end_timestamp'} = timegm(0,0,0,$recur_end_mday,$recur_end_mon,$recur_end_year); } # display warning if start timestamp is before present date if ($event_start_timestamp < $rightnow-86400) { push @{$results{messages}}, "[warning]$lang{update_event_err11}"; } } # check for refreshes! if ($recurring_event eq "") { #$debug_info .= "comparing $latest