#!/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.10"; # 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 $ical_export_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 if ( ! check_perl_version( $perl_version, '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; if ($options{calendar_url} ne "") { $script_url = $options{calendar_url}; } else { $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()}; my $cookie_path = $q->url( -absolute => 1 ); $cookie_path =~ s/$name$//; $cookie_path =~ s/admin\/?$//; # This is better than using just '/' # 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 $ical_export_url ="$theme_url/ical"; # where icalendar .ics files are placed $ical_export_url =~ s/http:\/\//$options{ical_prefix}/; # replace with custom prefix $icons_url = "$theme_url/icons"; # where icons are $css_path = "$theme_url/plans.css"; # css file # globals from 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 .= "Set-Cookie; plans_sid=deleted; path=$cookie_path;\n"; } # 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 .= "Set-Cookie: plans_sid=".$session->id."; path=$cookie_path;\n"; } } 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") { my $html_output =<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 .= "Set-Cookie: plans_view=$view_cookie; path=$cookie_path;\n"; $cookie_header_text = $cookie_text; #$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 ( !$logged_in && $options{force_login} ) { $insert_text .= &forced_login(); } else { 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; my $current_calendar_subscribe_text =<$lang{subscribe_to_this_calendar} p1 chomp $current_calendar_subscribe_text; $current_calendar_subscribe_text = '' if ( $options{'ical_export'} ne "1" ); 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/; if ( !$logged_in && $options{force_login} ) { $html_output =~ s/###subscribe calendar link###//g; $html_output =~ s/###export calendar link###//; $html_output =~ s/###custom calendar link###//; } else { $html_output =~ s/###subscribe calendar link###/$current_calendar_subscribe_text/g; 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/###subscribe calendar link###//g; $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") { $return_text .=< p1 if ($options{disable_passwords} ne "1") { if ($options{anonymous_calendar_requests} ne "1" && $need_password) { $return_text .=<
    $lang{existing_cal_password2} p1 } $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 password, if necessary if ($options{anonymous_calendar_requests} eq "1") { my $t1 = $q->param('as'); my $t2 = $rightnow; if (abs($t1 - $t2) > 3600) { $cal_valid=0; } } else { 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_error0}"; } } #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 = ""; } my $edit_title = &escapequotes($current_event{title}); $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_block_merge = $q->param('evt_block_merge'); my $event_series_id = $q->param('series_id'); my $event_duration = 0; my $event_start_timestamp = 0; my $event_end_timestamp = 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'); $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 ($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_end_timestamp +=1 if ($event_start_timestamp == $event_end_timestamp); # give all events a duration of at least 1 second $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 ($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 "") { my %latest_event = $events{$latest_event_id}; if ($latest_event{cal_ids}[0] eq $current_cal_id && $latest_event{start} eq $event_start_timestamp && $latest_event{end} eq $event_end_timestamp && $latest_event{title} eq $event_title && $latest_event{details} eq $event_details && $latest_event{icon} eq $event_icon && $latest_event{bgcolor} eq $event_bgcolor && $latest_event{unit_number} eq $event_unit_number) { $event_valid = 0; push @{$results{messages}}, "[error]$lang{update_event_err12}"; } } else { # recurring event refresh protection is a little trickier. # it's currently not implemented } if ($add_edit_event eq "edit") { #check to make sure the event id matches some event in the data structure. It always should, but we check anyway. if (!defined $events{$event_id}) { $event_valid = 0; push @{$results{messages}}, "[error]$lang{update_event_err13}"; } } # properly format errors & warnings $message_results=""; if ($event_valid == 1) { $results{successful} = 1; #$debug_info .= "(add_update_event) event_id: $event_id\n"; unshift @evt_other_cal_ids, $current_cal_id; my %new_event = (recurring => $recurring_event, cal_ids => \@evt_other_cal_ids, start => $event_start_timestamp, end => $event_end_timestamp, all_day_event => $all_day_event, days => &calculate_event_days($event_start_timestamp, $event_end_timestamp), title => $event_title, details => $event_details, icon => $event_icon, bgcolor => $event_bgcolor, block_merge => $event_block_merge, unit_number => $event_unit_number, update_timestamp => $rightnow, existing_id => $event_id, recurrence_parms => \%recurrence_parms); if ($login_valid) { $results{text} .= &commit_event(\%new_event, \%input_parms); } elsif ($options{anonymous_events}) { # anonymous event -> update queue my $new_event_id = $max_action_id + int(rand(100)); # just in case several people decide to add something new at the same time. $new_event{id} = $new_event_id; #$debug_info .= "(add_edit_events) event cal id: $event_cal_id\n"; # add event to %events data structure $new_events{$new_event_id} = \%new_event; # notify email(s) if ($options{email_mode} > 0) { my $subj = $lang{notify_subj}; $subj =~ s/\$1/$script_url\/$name/; my $body = $lang{event_pending_notify}; $body =~ s/\$1/$events{$current_event_id}{title}/; $body =~ s/\$2/$calendars{$current_cal_id}{title}/; $body =~ s/\$3/$script_url\/$name?view_pending_event=1&pending_event_id=$new_event_id/; foreach $add_email (@{$current_calendar{add_emails}}) { push @{$results{messages}}, "[status]email notification sent to $add_email"; &send_email($add_email, $options{reply_address}, $options{reply_address}, $subj, $body); } } &add_action($new_event_id, "new_event"); $event_box_text .= &generate_event_details(\%new_event); $results{text} .= <$lang{update_event_add_pending_successful}

    $event_box_text p1 } } } return \%results; } #******************** end add_edit_event ***************************** sub commit_event() { # commit an add or update of an event my ($new_event_ref, $input_parms_ref) = @_; my $messages = ""; my $new_event_id; my %new_event = %{$new_event_ref}; my %input_parms = %{$input_parms_ref}; unless ($loaded_all_events eq "1") { &load_events("all"); &normalize_timezone(); } if ($add_edit_event eq "add") { # add a new event if ($new_event{'recurring'} eq "") { my $event_box_text = ""; $new_event_id = ++$max_event_id; $events{$new_event_id} = deep_copy(\%new_event); $events{$new_event_id}{id} = $new_event_id; &add_event($new_event_id); $event_box_text .= &generate_event_details($events{$new_event_id}); #temporarily offset event times by calendar gmtime diff $messages .= <$lang{update_event_add_successful}

    $event_box_text p1 } else { # recurring events loop #$debug_info .= "in commit_event recurring events loop!\n"; my %recurrence_parms = %{$new_event{'recurrence_parms'}}; my $new_series_id = ++$max_series_id; my $date_text = ""; my @recurring_events_timestamps = @{&calculate_recurring_events($new_event{'start'}, \%recurrence_parms)}; my @recurring_event_ids = (); foreach $recurring_event_start_timestamp (@recurring_events_timestamps) { my $new_event_id = ++$max_event_id; my $recurring_event_end_timestamp = $recurring_event_start_timestamp + $recurrence_parms{'duration'}; $events{$new_event_id} = deep_copy(\%new_event); $events{$new_event_id}{id} = $new_event_id; $events{$new_event_id}{series_id} = $new_series_id; $events{$new_event_id}{start} = $recurring_event_start_timestamp; $events{$new_event_id}{end} = $recurring_event_end_timestamp; $events{$new_event_id}{recurrence_parms} = []; push @recurring_event_ids, $new_event_id; my $date_range = &nice_date_range_format($recurring_event_start_timestamp, $recurring_event_end_timestamp, "-"); $date_text .= <$date_range p1 } &add_events(\@recurring_event_ids); $event_box_text .= &generate_event_details($events{$max_event_id}); $messages .= <$lang{update_event_add_successful_recurring}

      $date_text
    $event_box_text p1 } if ($options{email_mode} > 0) { my $subj = $lang{notify_subj}; $subj =~ s/\$1/$script_url\/$name/; my $body = $lang{event_add_notify}; $body =~ s/\$1/$new_event{title}/; $body =~ s/\$2/$calendars{$current_cal_id}{title}/; $body =~ s/\$3/$script_url\/$name?view_event=1&evt_id=$max_event_id/; foreach $add_email (@{$current_calendar{add_emails}}) { push @{$results{messages}}, "[status]email notification sent to $add_email"; &send_email($add_email, $options{reply_address}, $options{reply_address}, $subj, $body); } } } elsif ($add_edit_event eq "edit") { #if we need to replace an existing record my $event_id = $new_event{'existing_id'}; if ($new_event{'recurring'} eq "" || $input_parms{'update_all_in_series'} ne "1") { $events{$event_id} = deep_copy(\%new_event); $events{$event_id}{id} = $event_id; &update_event($event_id); $event_box_text .= &generate_event_details($events{$event_id}); $messages .= <$lang{update_event_update_successful}

    p1 } else { # update recurring events # get the ids of the events in the series. my @events_in_series; foreach $event_id (keys %events) { my %event = %{$events{$event_id}}; my $series_id = $event{series_id}; if ($series_id eq $q->param('series_id')) { push @events_in_series, $event_id; my @temp = gmtime($event{end}); ($recurring_event_start_timestamp, $recurring_event_end_timestamp) = ×tamp_from_datetime($temp[3],$temp[4],$temp[5]+1900,$input_parms{'event_days'},$input_parms{'event_start_time'},$input_parms{'event_end_time'},$input_parms{'all_day'}); $events{$event_id} = deep_copy(\%new_event); $events{$event_id}{id} = $event_id; $events{$event_id}{series_id} = $series_id; $events{$event_id}{start} = $recurring_event_start_timestamp; $events{$event_id}{end} = $recurring_event_end_timestamp; $events{$event_id}{recurrence_parms} = []; } } &update_events(\@events_in_series); $messages .= <$lang{update_event_update_successful_recurring}

    p1 } if ($options{email_mode} > 0) { my $subj = $lang{notify_subj}; $subj =~ s/\$1/$script_url\/$name/; my $body = ""; $body = $lang{event_update_notify}; $body =~ s/\$1/$new_event{title}/; $body =~ s/\$2/$calendars{$current_cal_id}{title}/; $body =~ s/\$3/$script_url\/$name?view_event=1&evt_id=$event_id/; foreach $email (@{$current_calendar{update_emails}}) { $debug_info .= "email notification sent to $email\n"; &send_email($email, $options{reply_address}, $options{reply_address}, $subj, $body); } } } return $messages; } sub common_javascript { my $logged_in_boolean = ($logged_in) ? "true":"false"; my $date_format = lc $current_calendar{date_format}; $return_string .=< $lang{custom_calendar_title}

    p1 foreach $cal_id (sort {$a <=> $b} keys %calendars) { $custom_form_text .=<$calendars{$cal_id}{title} p1 } $custom_form_text .=<

    p1 if ($display_type == 1) {$list_selected = "selected";} else {$cal_selected = "selected";} $custom_form_text .=< $lang{custom_calendar_display_type} p1 #list each month in the year $month_index=0; foreach $possible_month (@months) { if ($cal_start_month eq $month_index) { $custom_form_text .=<$possible_month p1 } else { $custom_form_text .=<$possible_month p1 } $month_index++; } $custom_form_text .=< $lang{controls_num_months}

    p1 $custom_form_text =~ s/\//\\\//g; $custom_form_text =~ s/\n/\\n/g; $custom_form_text =~ s/"/\\"/g; $return_string .=<'); doc.write('$lang{custom_calendar_title}<\\/title>'); doc.write('<base target=\\"'+main_window_name+'\\">'); doc.write('<link rel=\\"stylesheet\\" href=\\"$css_path\\" type=\\"text/css\\" media=screen>'); doc.write('<body>'); doc.write("$custom_form_text"); doc.write('<\\/body><\\/html>'); doc.close(); info_window.focus(); } p1 return $return_string; } #***********************end calendar_view_javascript************************" sub add_edit_events_javascript { $return_string=""; $return_string.=<<p1; var info_window_x = window_x()-$info_window_width; var info_window_y = window_y(); // color select stuff var cs0; function color_menu0_update(new_color) { //window.status = "updating! " + new_color; document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.options.length-1].value = new_color; document.add_event_form.evt_bgcolor.style.background = new_color; document.add_event_form.evt_bgcolor.style.color = compatible_textcolor(new_color); document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.options.length-1].style.color = compatible_textcolor(new_color); document.getElementById("custom_evt_color").style.background = new_color; } function do_on_load() { if (!document.add_event_form || !document.add_event_form.evt_bgcolor) return; // color select control cs0 = new color_select('cs0',document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.selectedIndex].value); cs0.change_update_function = "color_menu0_update"; // NOTE-there are no () cs0.hide_update_function = "color_menu0_update"; // NOTE-there are no () cs0.attach_to_element(document.getElementById("color_select_icon0")); cs0.setrgb("$current_event{bgcolor}"); cs0.update_color_box(); for (i=0; i<document.add_event_form.evt_bgcolor.options.length; i++) { document.add_event_form.evt_bgcolor[i].style.background = document.add_event_form.evt_bgcolor[i].value; document.add_event_form.evt_bgcolor[i].style.color = compatible_textcolor(document.add_event_form.evt_bgcolor[i].value); } // for some reason, calling this immediately doesn't always work - even if it's called after the page is loaded. // so, a 200 ms delay. setTimeout('update_bg_color_select_box()', 200); } function update_bg_color_select_box() { var add_event_form = document.getElementById("add_event_form"); // did the user just select custom? if (document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.selectedIndex].text == "custom") document.getElementById("color_select_icon0").style.visibility = "visible"; else document.getElementById("color_select_icon0").style.visibility = "hidden"; // take focus off the select (in IE, making a selection highlights it in blue, so you cannot see the actual color you picked. Removing focus makes this go away) document.add_event_form.dummy.style.display='inline'; document.add_event_form.dummy.select(); document.add_event_form.dummy.style.display='none'; //if (!add_event_form.evt_bgcolor) // return; //alert(add_event_form.evt_bgcolor[add_event_form.evt_bgcolor.selectedIndex].value); add_event_form.evt_bgcolor.style.background = add_event_form.evt_bgcolor[add_event_form.evt_bgcolor.selectedIndex].value //document.add_event_form.evt_title.select(); add_event_form.evt_bgcolor.style.color = compatible_textcolor(add_event_form.evt_bgcolor[add_event_form.evt_bgcolor.selectedIndex].value); } function update_preview_icon() { var icon_preview_area = document.getElementById("icon_preview") icon_name = document.add_event_form.evt_icon.options[document.add_event_form.evt_icon.selectedIndex].value icon_preview_area.innerHTML = "<img src=\\"$icons_url/" + icon_name + "_32x32.gif\\" border=\\"0\\" vspace=0 hspace=0>" if (!document.add_event_form.unit_number) return; var unit_number_preview_area = document.getElementById("unit_number_preview") // remove non-numeric text from the string var unit_number = document.add_event_form.unit_number.value; unit_number = unit_number.replace(/[^0-9]/g, ""); // this next part might be really clever or really stupid (using a regex for something like this). // regardless, it's only one line, and that's nice. var unit_number_graphic_string = unit_number.replace(/([0-9])/g, "<img src=\\"$graphics_url/unit_number_patch_\$1_20x13.gif\\" border=\\"0\\" vspace=0 hspace=0>"); unit_number_preview_area.innerHTML = unit_number_graphic_string; document.add_event_form.unit_number.value = unit_number; // it would be nice if we could do things with the DOM model, as opposed to innerHTML, but // that would be crazy cumbersome. The following is a non-working stab at it. Maybe useful someday. //preview_area.nodeValue = "unit num"; //preview_area.appendChild(document.createTextNode("unit <img name=\\"event_icon\\" src=\\"$icons_url/eagle_medal_32x32.gif\\" border=\\"0\\" vspace=0 hspace=0>")); } function all_day_event_toggle(value) { var el0 = document.getElementById("all_day_event_toggle0"); el0.style.display=""; if (value) el0.style.display="none"; } function preview_event() { info_window = this.open("", "info_window", "resizable=yes,status=yes,scrollbars=yes,width=300,height=200"); doc = info_window.document; doc.open('text/html'); doc.write('<html>'); doc.write('<title>$lang{event_preview_title}<\\/title>'); doc.write('<body bgcolor=\\"#ffffff\\" style=\\"font-family:arial,helvetica\\">'); doc.write('<font size=5><font color=\\"0049df\\">$lang{generating_preview}<\\/font>'); doc.write('<\\/body><\\/html>'); doc.close(); document.add_event_form.special_action.value = "preview_event"; document.add_event_form.target = "info_window"; document.add_event_form.submit(); document.add_event_form.special_action.value = ""; document.add_event_form.target = ""; info_window.focus(); } function recur_edit_toggle() { if (document.add_event_form.all_in_series.checked) { document.add_event_form.add_event_button.value="$lang{recurring_event_update_all1}"; document.add_event_form.del_event_button.value="$lang{recurring_event_delete_all1}"; } else { document.add_event_form.add_event_button.value="$lang{update_event}"; document.add_event_form.del_event_button.value="$lang{delete_event1}"; } } function preview_dates() { var i = 0; var j = 0; var info_window_x = window_x()-$info_window_width; var info_window_y = window_y(); var evt_start_date = document.add_event_form.evt_start_date.value; var evt_days = document.add_event_form.evt_days.value; var evt_start_time = document.add_event_form.evt_start_time.value; var evt_end_time = document.add_event_form.evt_end_time.value;; var recurring_event = ""; var every_x_days; var every_x_weeks; var recur_end_date; var recurrence_type = ""; var year_fit_type = ""; var weekday_of_month_type = ""; var custom_months_string = ""; if (document.add_event_form.recur_end_date) { every_x_days = document.add_event_form.every_x_days.value; every_x_weeks = document.add_event_form.every_x_weeks.value; recur_end_date = document.add_event_form.recur_end_date.value; if (document.add_event_form.recurring_event.checked) recurring_event = document.add_event_form.recurring_event.value; for (i=0; i<document.add_event_form.recurrence_type.length; i++) if (document.add_event_form.recurrence_type[i].checked) recurrence_type = document.add_event_form.recurrence_type[i].value; for (i=0; i<document.add_event_form.year_fit_type.length; i++) if (document.add_event_form.year_fit_type[i].checked) year_fit_type = document.add_event_form.year_fit_type[i].value; if (document.add_event_form.weekday_of_month_type.selectedIndex > -1) weekday_of_month_type = document.add_event_form.weekday_of_month_type.options[document.add_event_form.weekday_of_month_type.selectedIndex].value var selects = new Array(); var custom_months = ""; if (document.add_event_form.custom_months.selectedIndex > -1) for (j=0, i=document.add_event_form.custom_months.selectedIndex; i<document.add_event_form.custom_months.options.length;i++) if (document.add_event_form.custom_months.options[i].selected) custom_months_string +="&custom_months="+document.add_event_form.custom_months.options[i].value; } var URL_string="$script_url/$name?special_action=preview_date&evt_start_date="+evt_start_date+ "&cal_id="+document.add_event_form.cal_id.value+ "&recur_end_date="+recur_end_date+ "&recurring_event="+recurring_event+ "&recurrence_type="+recurrence_type+ "&year_fit_type="+year_fit_type+ "&every_x_days="+every_x_days+ "&every_x_weeks="+every_x_weeks+ "&evt_start_time="+evt_start_time+ "&evt_start_time="+evt_start_time+ "&weekday_of_month_type="+weekday_of_month_type+ custom_months_string+ "&evt_days="+evt_days; info_window = this.open("", "info_window", "resizable=yes,status=yes,scrollbars=yes,top="+info_window_y+",left="+info_window_x+",width=$info_window_width,height=$info_window_height"); doc = info_window.document; doc.open('text/html'); doc.write('<html>'); doc.write('<head>'); doc.write('<title>$lang{event_preview_computing}<\\/title>'); doc.write('<link rel=\\"stylesheet\\" href=\\"$css_path\\" type=\\"text/css\\" media=screen>'); doc.write('<\\/head>'); doc.write('<body style=\\"font-family:arial;\\">'); doc.write('$lang{event_preview_computing}'); doc.write('<\\/body><\\/html>'); doc.close(); info_window = this.open(URL_string, "info_window", "resizable=yes,status=yes,scrollbars=yes,top="+info_window_y+",left="+info_window_x+",width=$info_window_width,height=$info_window_height"); info_window.focus(); } p1 my @help_text_map = ("evt_cal_id", "evt_title", "evt_details", "help_evt_details", "recurring_event", "recurrence_type", "fit_into_year", "cal_password", "recurring_event_change_all"); my $help_text_javascript = ""; foreach $key (@help_text_map) { my $help_text=<<p1; <div class="help_box"> $lang{'help_'.$key} </div> p1 $help_text =~ s/\n/\\n/g; $help_text =~ s/"/\\"/g; $help_text =~ s/'/\\'/g; $help_text =~ s/\//\\\//g; $help_text_javascript .=<<p1; if (topic == "$key") help_text += "$help_text"; p1 } $return_string .=<<p1; function display_help(topic, title) { help_text = ""; $help_text_javascript if (help_text != "") { help_text = "<div class=\\"help_title\\">$lang{help_box_title} - "+title+"</div>" + help_text; show_help(); } } p1 return $return_string } #********************end add_edit_events_javascript********************** sub generate_users_javascript() { my ($cal_id) = @_; my $results = ""; foreach $user_id (keys %users) { my $valid_for_current_calendar = 0; foreach $cal_id (keys %{$users{$user_id}{calendars}}) { if ($cal_id eq $current_cal_id) { $valid_for_current_calendar = 1; last; } } next if ($valid_for_current_calendar == 0); #next if ($user_id eq ""); my %user = %{$users{$user_id}}; $results .=<<p1; users['$user_id'] = new User('$user_id','$user{name}'); p1 } return $results; } sub generate_pending_events_javascript() { my $results = ""; foreach $pending_event_id (sort {$new_events{$a}{update_timestamp} <=> $new_events{$b}{update_timestamp}} @pending_events_to_display) { my %pending_event = %{$new_events{$pending_event_id}}; my $title = $pending_event{title}; $title = &javascript_cleanup($title); $results .=<<p1; pending_events['$pending_event_id'] = new Event({'id':'$pending_event_id', 'title':'$title', 'icon':'$pending_event{icon}', 'start':$pending_event{start}, 'end':$pending_event{end}, 'timestamp':$pending_event{update_timestamp}}); p1 } return $results."\n"; } sub add_edit_calendars_javascript { my $return_string = ""; $return_string .= &generate_users_javascript($current_calendar{id}); $return_string.=<<p1; // override generic do_on_load method from plans.js function do_on_load() { update_remote_calendar_requests(); update_cal_color_select_box(); list_users(); if (document.getElementById("color_select_icon0")) { // color select controls cs0 = new color_select('cs0'); cs0.change_update_function = "color_menu0_update"; // NOTE-there are no () cs0.hide_update_function = "color_menu0_update"; // NOTE-there are no () cs0.attach_to_element(document.getElementById("color_select_icon0")); cs0.setrgb("$current_event{bgcolor}"); cs0.update_color_box(); cs1 = new color_select('cs1'); cs1.change_update_function = "color_menu1_update"; // NOTE-there are no () cs1.hide_update_function = "color_menu1_update"; // NOTE-there are no () cs1.attach_to_element(document.getElementById("color_select_icon1")); cs1.setrgb("$current_event{bgcolor}"); cs1.update_color_box(); } } function update_users() { if (!users || users.length == 0) return; } function set_merge_xml(merge_xml) { var results = merge_xml.match(/\\/remote_calendar>/g); //var num_merged_calendars = results.length; if (results) if (results.length > 1) document.getElementById("remote_background_calendars_status").innerHTML = results.length + " $lang{get_remote_calendar2_plural} $current_calendar{title}<br/>"; else document.getElementById("remote_background_calendars_status").innerHTML = results.length + " $lang{get_remote_calendar2_singular} $current_calendar{title}<br/>"; else document.getElementById("remote_background_calendars_status").innerHTML = "$lang{get_remote_calendar3}"; //for(var i =0; i < results.length; i++) // document.getElementById("remote_background_calendars_status").innerHTML +="calendar "+i+"<br/>"; document.update_cal_form.new_remote_calandars_xml.value = merge_xml; //alert (num_merged_calendars +" new calendars to merge!") //alert(merge_xml); } p1 my $popup_javascript_info = ""; if ($browser_type eq "IE") { $popup_javascript_info .=<<p1; <script type="text/javascript" ><!-- function do_onresize() { opener.info_window_width = document.body.clientWidth; opener.info_window_height = document.body.clientHeight; } //--> </script> p1 } else { $popup_javascript_info .=<<p1; <script type="text/javascript" ><!-- function do_onresize() { opener.info_window_width = this.outerWidth; opener.info_window_height = this.outerHeight; } //--> </script> p1 } $popup_javascript_info =~ s/\n/\\n/g; $popup_javascript_info =~ s/"/\\"/g; $popup_javascript_info =~ s/\//\\\//g; my $get_remote_calendars_html =<<p1; <br/> <form name="detect_remote_calendars" action="$script_url/$name" method="POST"> <input type="hidden" name="detect_remote_calendars" value="1"/> $lang{get_remote_calendars_url}<br/> <input name="remote_calendar_url" value="http://" style="width:90%;"> <br/> <input type="submit" value="Go!" style="width:5em;"> </form> p1 $get_remote_calendars_html =~ s/\n/\\n/g; $get_remote_calendars_html =~ s/"/\\"/g; $get_remote_calendars_html =~ s/\//\\\//g; $return_string.=<<p1; function get_remote_calendars() { info_window = this.open("", "info_window", "resizable=yes,status=yes,scrollbars=yes,top="+info_window_y+",left="+info_window_x+",width="+info_window_width+",height="+info_window_height); doc = info_window.document; doc.open('text/html'); doc.write('<html>'); doc.write('<title>$lang{get_remote_calendars}<\\/title>'); doc.write('<link rel=\\"stylesheet\\" href=\\"$css_path\\" type=\\"text/css\\" media=screen>'); doc.write('$popup_javascript_info'); doc.write('<body onResize=\\"javascript:do_onresize()\\">'); doc.write("<div class=\\"info_box\\" style=\\"padding:5px;\\"><br\\/>"); doc.write('$get_remote_calendars_html'); doc.write("<\\/div>"); doc.write('<\\/body><\\/html>'); doc.close(); info_window.focus(); } // color select stuff var cs0 = new color_select(); cs0.setrgb("$current_calendar{background_events_color}"); var cs1 = new color_select(); cs1.setrgb("$current_calendar{calendar_events_color}"); function color_menu0_update(new_color) { if (document.update_cal_form.background_events_display_style2.checked) { document.update_cal_form.background_events_color.value = new_color; document.getElementById("bg_preview_e1").style.background = new_color; document.getElementById("bg_preview_e2").style.background = new_color; } } function color_menu1_update(new_color) { //if (new_color == "#000000") return; if (document.getElementById("color_select_icon1").style.visibility != "visible") return; document.update_cal_form.calendar_events_color[document.update_cal_form.calendar_events_color.options.length-1].value = new_color; document.update_cal_form.calendar_events_color.style.background = new_color; document.getElementById("custom_evt_color").style.background = new_color; document.getElementById("preview_e1").style.background = new_color; document.getElementById("preview_e2").style.background = new_color; } function update_cal_color_select_box() { if (!document.update_cal_form) return; if (!document.update_cal_form.calendar_events_color) return; var current_color = document.update_cal_form.calendar_events_color[document.update_cal_form.calendar_events_color.selectedIndex].value; if (current_color == "") { document.getElementById('preview_e1').style.background = '#ffffcc'; document.getElementById('preview_e2').style.background = '#ccffcc'; document.getElementById("color_select_icon1").style.visibility = "hidden"; document.update_cal_form.calendar_events_color.style.background = "#ffffff"; return; } if (document.update_cal_form.calendar_events_color.selectedIndex == document.update_cal_form.calendar_events_color.options.length-1) { document.getElementById("color_select_icon1").style.visibility = "visible"; var current_custom_color = document.getElementById("custom_evt_color").value; document.getElementById("preview_e1").style.background = current_custom_color; document.getElementById("preview_e2").style.background = current_custom_color; document.update_cal_form.calendar_events_color.style.background = current_custom_color; return; } else { cs1.setrgb(current_color); document.getElementById("color_select_icon1").style.visibility = "hidden"; document.getElementById("preview_e1").style.background = current_color; document.getElementById("preview_e2").style.background = current_color; document.update_cal_form.calendar_events_color.style.background = current_color; // take focus off the select (in IE, making a selection highlights it in blue, so you cannot see the actual color you picked. Removing focus makes this go away) document.update_cal_form.dummy.style.display='inline'; document.update_cal_form.dummy.select(); document.update_cal_form.dummy.style.display='none'; } //document.add_event_form.evt_bgcolor.style.background = document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.selectedIndex].value //document.update_cal_form.evt_title.select(); } // end color_select stuff p1 $return_string.=<<p1; var info_window_x = window_x()-$info_window_width; var info_window_y = window_y() + 200; function show_help() { info_window = this.open("", "info_window", "resizable=yes,status=yes,scrollbars=yes,top="+info_window_y+",left="+info_window_x+",width="+info_window_width+",height="+info_window_height); doc = info_window.document; doc.open('text/html'); doc.write('<html>'); doc.write('<title>$lang{help_box_title}<\\/title>'); doc.write('<link rel=\\"stylesheet\\" href=\\"$css_path\\" type=\\"text/css\\" media=screen>'); doc.write('$popup_javascript_info'); doc.write('<body onResize=\\"javascript:do_onresize()\\">'); doc.write(help_text); doc.write('<\\/body><\\/html>'); doc.close(); info_window.focus(); } function preview_cal() { var cal_title = document.update_cal_form.cal_title.value var cal_link = document.update_cal_form.cal_link.value var cal_details = document.update_cal_form.cal_details.value; if (cal_title == "") { evt_label = "<span style=\\"color:#ff0000\\">$lang{preview_calendar_temp_title}<\\/span>"; add_disable = true; } // if (document.getElementById("preview_warning")) { document.getElementById("preview_warning").innerHTML=""; } info_window = this.open("", "info_window", "resizable=yes,status=yes,scrollbars=yes,top="+info_window_y+",left="+info_window_x+",width="+info_window_width+",height="+info_window_height); doc = info_window.document; doc.open('text/html'); doc.write('<html>'); doc.write('<title>$lang{preview_calendar_title}<\\/title>'); doc.write('<link rel=\\"stylesheet\\" href=\\"$css_path\\" type=\\"text/css\\" media=screen>'); doc.write('$popup_javascript_info'); doc.write('<body onResize=\\"javascript:do_onresize()\\">'); doc.write("<div class=\\"info_box\\" style=\\"padding:5px;\\"><br/><div style=\\"white-space:nowrap;\\"><span class=\\"cal_title\\">"); doc.write("<a target=\\"_blank\\" href=\\""+cal_link+"\\">"+cal_title+"<\\/a><\\/span><\\/div><br/><div>"+cal_details+"<\\/div><\\/div>"); doc.write('<\\/body><\\/html>'); doc.close(); info_window.focus(); } p1 my @help_text_map = ("title", "link", "details", "password", "new_password", "current_password", "change_password", "selectable_calendars", "background_calendars", "remote_background_calendars", "background_events_display_style", "events_display_style", "list_background_calendars_together", "default_number_of_months", "max_months", "gmtime_diff", "date_format", "week_start_day", "new_calendars_automatically_selectable", "allow_remote_calendar_requests", "remote_calendar_requests_password", "event_change_email", "popup_window_size", "custom_stylesheet", "custom_template", "add_user", "add_new_ical"); my $help_text_javascript = ""; foreach $key (@help_text_map) { my $help_text=<<p1; <div class="help_box"> $lang{'help_cal_'.$key} </div> p1 $help_text =~ s/\n/\\n/g; $help_text =~ s/"/\\"/g; $help_text =~ s/'/\\'/g; $help_text =~ s/\//\\\//g; $help_text =~ s/###css file###/$css_path/g; $help_text_javascript .=<<p1; if (topic == "$key") help_text += "$help_text"; p1 } $return_string .=<<p1; function display_help(topic, title) { help_text = ""; $help_text_javascript if (help_text != "") { help_text = "<div class=\\"help_title\\">$lang{help_box_title} - "+title+"</div>" + help_text; show_help(); } } p1 return $return_string } #********************end add_edit_calendars_javascript********************** sub generate_cal_details() { my ($calendar_ref) = @_; my %calendar = %{$calendar_ref}; my $results = <<p1; <div class="cal_title"> $calendar{title} </div> <div> $calendar{details} </div> p1 $writable{calendar_file} and $return_text .= <<p1; <div style="white-space:nowrap;"> <span class="small_note"> <a href="$script_url/$name?active_tab=2&add_edit_cal_action=edit&cal_id=$calendar{id}">$lang{calendar_add_edit}</a> </span> </div> p1 $return_text .= <<p1; <div style="white-space:nowrap;margin-top:2em;"> <span class="small_note"> $lang{calendar_direct_link}<br/> <a href="$script_url/$name?cal_id=$calendar{id}">$script_url/$name?cal_id=$calendar{id}</a> </span> </div> p1 return $results; } sub render_calendar { my $return_text = ""; my $week_events = {}; my $week_slots = {}; my $debug = 0; my @debug_events = ("105"); my $show_month_breaks = ($cal_num_months > 1 && $options{continuous_multimonth} ne '1' ? 1 : 0); my $cal_month_idx = 0; my $last_cal_month; my $is_first_cal_date = 1; my @use_other_month = (0, 1); my ($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year, $selected_events) = @_; #initialize loop variables my $cal_start_timestamp = timegm(0,0,0,1,$cal_start_month,$cal_start_year); my $cal_end_timestamp = find_end_of_month($cal_end_month, $cal_end_year); my $current_month = $cal_start_month; my $current_year = $cal_start_year; while ($current_year < $cal_end_year || ($current_year == $cal_end_year && $current_month <= $cal_end_month)) { $last_cal_month = ($current_year * 100 + $current_month) == ($cal_end_year * 100 + $cal_end_month); foreach $key (keys %week_events) {delete $week_events{$key};} foreach $key (keys %week_slots) {delete $week_slots{$key};} #for calendars with multiple months, display the name of each month above the calendar if ($show_month_breaks) { $return_text .=<<p1; <p class="cal_month_title" style="padding:5px;"> $months[$current_month] $current_year </p> p1 } #calculate where to start the calendar (first sunday) #first, calculate what day of the week this month begins on #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year); my $cal_month_start_date = timegm(0,0,0,1, $current_month, $current_year); my @cal_month_start_date_array = gmtime $cal_month_start_date; my $cal_start_day_offset = $cal_month_start_date_array[6] - $current_calendar{week_start_day}; $cal_start_day_offset += 7 if ($cal_start_day_offset < 0); my $cal_start_date = $cal_month_start_date - (86400 * $cal_start_day_offset); # in continuous_multimonth mode, skip first week if we already drew it in the previous iteration $cal_start_date = $cal_start_date + 604800 if (!$show_month_breaks && $cal_month_idx > 0 && $cal_start_day_offset != 0); # start with other_month if the first month does not start on the first day of the week (i.e there is an offset) @use_other_month = (1, 0) if (!$show_month_breaks && $cal_month_idx == 0 && $cal_start_day_offset != 0 && $current_month % 2); my @cal_start_date_array = gmtime $cal_start_date; my $cal_end_date = $cal_start_date + 86400*37; my $next_month = $current_month+1; if ($next_month == 12) {$next_month=0;} #cal_date keeps track of the date (in timestamp format) #as the calendar loop iterates through each day on the calendar page my $cal_date = $cal_start_date; my @cal_date_array = gmtime $cal_date; my %max_day_events; my %week_max_slots; #make a first pass through the month, assemble event week events structure: #week_events{week_index}{id} ={} #this hash has 4 keys--start_weekday, start_day, length and slot_order (slot_order will be calculated in the second pass) for ($l1=0;$cal_date_array[4] != $next_month;$l1++) { #each calendar has 5 or 6 weeks $week_start_timestamp = $cal_date; $week_end_timestamp = $week_start_timestamp + 604800; $max_day_events{$l1} = 0; @cal_date_array = gmtime $cal_date; foreach $event_id (keys %events) { $debug = 1 if ($debug == 1 && (&contains(\@debug_events, $event_id) || $debug_events[0] eq "all")); my %event = %{$events{$event_id}}; #$debug_info .= "checking event $event_id ($event{start}, $event{end})\n"; #$debug_info .= "checking event $event_id ($event{start} - $event{end}) against week $l1 ($week_start_timestamp - $week_end_timestamp)\n"; $debug_info .= "week $l1 checking event $event_id ($event{start}-$event{end}}) for overlap ($week_start_timestamp-$week_end_timestamp)\n" if ($debug && &contains(\@debug_events, $event_id)); if (&time_overlap($event{start}, $event{end}, $week_start_timestamp, $week_end_timestamp)) { $debug_info .= "week $l1 event $event_id overlaps\n" if ($debug); #$debug_info .= "event $event_id ($event{days} days) in week $l1\n"; #$debug_info .= "check passed!\n"; my @event_date_array = gmtime $event{start}; my @event_end_date_array = gmtime $event{end}; my $event_start_weekday = $event_date_array[6] - $current_calendar{week_start_day}; my $event_end_weekday = $event_end_date_array[6] - $current_calendar{week_start_day}; $event_start_weekday +=7 if ($event_start_weekday < 0); $event_end_weekday +=7 if ($event_end_weekday < 0); #$event_start_weekday = 0 if ($event_start_weekday < 0); #$event_end_weekday = 0 if ($event_end_weekday < 0); #$event_start_weekday = 6 if ($event_start_weekday > 6); #$event_end_weekday = 6 if ($event_end_weekday > 6); my $days_before_week_start = 0; my $days_after_week_end = 0; $debug_info .= "week $l1 event $event_id event_date_array[6]: $event_date_array[6]\n" if ($debug); $debug_info .= "week $l1 event $event_id event_end_date_array[6]: $event_end_date_array[6]\n" if ($debug); $debug_info .= "week $l1 event $event_id current_calendar{week_start_day}: $current_calendar{week_start_day}\n" if ($debug); $debug_info .= "week $l1 event $event_id event_start_weekday: $event_start_weekday event_end_weekday: $event_end_weekday\n" if ($debug); # the event might fall completely within the week boundary, or it # might overlap event begins or ends outside the week boundaries # (there are four possible cases): if ($event{start} < $week_start_timestamp && $event{end} > $week_end_timestamp) { # the event both starts and ends outside this week $debug_info .= "case 0\n" if ($debug); $week_events{$l1}{$event{id}}{start_weekday} = 0; $week_events{$l1}{$event{id}}{length} = 7; } elsif ($event{start} < $week_start_timestamp) { # the event starts before this week and ends within it $debug_info .= "case 1\n" if ($debug); #$days_before_week_start = int(($week_start_timestamp - $event{start})/86400); $week_events{$l1}{$event{id}}{start_weekday} = 0; #$week_events{$l1}{$event{id}}{length} = $event{days} - $days_before_week_start; $week_events{$l1}{$event{id}}{length} = $event_end_weekday+1; $debug_info .= "week $l1 event $event_id week_start_timestamp: $week_start_timestamp start: $event{start} start_wkday: $week_events{$l1}{$event{id}}{start_weekday} length: $week_events{$l1}{$event{id}}{length}\n" if ($debug); } elsif ($event{end} > $week_end_timestamp) { # the event starts within this week and ends after it $debug_info .= "case 2\n" if ($debug); $week_events{$l1}{$event{id}}{start_weekday} = $event_start_weekday; $week_events{$l1}{$event{id}}{length} = 7-$event_start_weekday; if ($debug == 1) { foreach $debug_event_id (@debug_events) { next if ($debug_event_id ne $event{id}); $debug_info .= "event $debug_event_id days: $events{$debug_event_id}{days} event_start_weekday: $event_start_weekday event_end_weekday: $event_end_weekday length: $week_events{$l1}{$debug_event_id}{length}\n"; } } } else { #the event begins and ends within the week $debug_info .= "case 3\n" if ($debug); $week_events{$l1}{$event{id}}{length} = $event{days}; $week_events{$l1}{$event{id}}{start_weekday} = $event_start_weekday; } if ($week_events{$l1}{$event{id}}{start_weekday} < 0) { $week_events{$l1}{$event{id}}{start_weekday} += 7; } elsif ($week_events{$l1}{$event{id}}{start_weekday} > 6) { $week_events{$l1}{$event{id}}{start_weekday} -= 7; } $week_events{$l1}{$event{id}}{length} = 7 if ($week_events{$l1}{$event{id}}{length} > 7); $debug_info .= "week $l1 event $event_id event_start_weekday: $week_events{$l1}{$event{id}}{start_weekday} length: $week_events{$l1}{$event{id}}{length}\n\n" if ($debug); } } $temp_debug_info = ""; $cal_date += 604800; # each day has at least two slots (the date, and a blank box beneath it) for ($l2=0;$l2<7;$l2++) { $week_slots{$l1}{$l2}{0}{width}=1; $week_slots{$l1}{$l2}{0}{depth}=1; $week_slots{$l1}{$l2}{1}{width}=1; $week_slots{$l1}{$l2}{1}{depth}=1; } if ($debug == 1) { foreach $debug_event_id (@debug_events) { $debug_info .= "event $debug_event_id length: $week_events{$l1}{$debug_event_id}{length} start: $events{$debug_event_id}{start}\n"; } } #order the week_events #fill in the %slots data structure: # $week_slots{week_index}{day_index}{slot_index} # $width = colspan # $depth = rowspan # $spacer = 1 if spacer slot. # @ids = event ids my $max_week_needed_slots = 0; my %max_day_needed_slots; # hey man, that's a sharp-lookin' sort you got there foreach $week_event_id (sort { return $week_events{$l1}{$b}{length} <=> $week_events{$l1}{$a}{length} if ($week_events{$l1}{$b}{length} != $week_events{$l1}{$a}{length}); return $events{$a}{title} cmp $events{$b}{title} if ($events{$b}{all_day_event} ne "" && $events{$a}{all_day_event} ne ""); return $events{$b}{all_day_event} cmp $events{$a}{all_day_event} if ($events{$b}{all_day_event} ne "" || $events{$a}{all_day_event} ne ""); return $events{$a}{start} <=> $events{$b}{start}; } keys %{$week_events{$l1}}) { #$debug = 0; #$debug = 1 if (&contains(\@debug_events, $week_event_id)); #$debug_info .= "week $l1 week_event $week_event_id length: $week_events{$l1}{$week_event_id}{length} start: $events{$week_event_id}{start}\n" if ($debug); $empty_slot = 0; #starting at 1 leaves a row of empty slots (row 0), where the calendar dates will go. for ($l4=1; $empty_slot != 1; $l4++) { $empty_slot = 1; #check each day of the week_event, to make sure the slot is empty for ($l2=0; $l2<$week_events{$l1}{$week_event_id}{length}; $l2++) { $day_index=$l2+$week_events{$l1}{$week_event_id}{start_weekday}; if (scalar @{$week_slots{$l1}{$day_index}{$l4}{ids}} > 0) { $empty_slot = 0; } } $slot_index=$l4; } #$debug_info .= "event $week_event_id start_wkday $week_events{$l1}{$week_event_id}{start_weekday} slot $slot_index length $week_events{$l1}{$week_event_id}{length}\n" if ($debug); #fill up $week_slots with the new event (extend horizontally) for ($l2=0; $l2<$week_events{$l1}{$week_event_id}{length}; $l2++) { #$slots_in_row{$l1}{$slot_index}++; $day_index = $l2+$week_events{$l1}{$week_event_id}{start_weekday}; push @{$week_slots{$l1}{$day_index}{$slot_index}{ids}}, $week_event_id; if ($l2==0) { # first slot gets the width $week_slots{$l1}{$day_index}{$slot_index}{width} = $week_events{$l1}{$week_event_id}{length};} else { # other slots get 0 for length (they get absorbed later) $week_slots{$l1}{$day_index}{$slot_index}{width} = 0;} $week_slots{$l1}{$day_index}{$slot_index}{depth} = 1; } #keep track of the maximum number of slots each week has if ($slot_index > $week_max_slots{$l1}) { $week_max_slots{$l1} = $slot_index; $max_day_events{$l1} = $slot_index; } } # give all blank slots width and depth of 1 for ($l2=0;$l2<7;$l2++) { for ($l3=1;$l3<$week_max_slots{$l1}+1;$l3++) { # for each slot if ($week_slots{$l1}{$l2}{$l3}{depth} eq "" || $week_slots{$l1}{$l2}{$l3}{width} eq "") { $week_slots{$l1}{$l2}{$l3}{width}=1; $week_slots{$l1}{$l2}{$l3}{depth}=1; } } } my $total_spacers=0; # insert spacer slots below multi-day events. for ($l3=1;$l3<$week_max_slots{$l1}+1;$l3++) { # for each slot my $inserted_spacers=0; for ($l2=0;$l2<7;$l2++) { if ($week_slots{$l1}{$l2}{$l3}{width} > 1) { #multi-day event, add spacers beneath # create spacer row if ($inserted_spacers == 0) { # move everything else down and increment the number of rows $week_max_slots{$l1}++; for ($l4=0;$l4<7;$l4++) { # insert blank slots for ($l5=$week_max_slots{$l1};$l5>$l3+1;$l5--) { # count backwards $week_slots{$l1}{$l4}{$l5} = &deep_copy($week_slots{$l1}{$l4}{$l5-1}); } $week_slots{$l1}{$l4}{$l3+1}{width} = 1; $week_slots{$l1}{$l4}{$l3+1}{depth} = 1; $week_slots{$l1}{$l4}{$l3+1}{spacer} = 0; $week_slots{$l1}{$l4}{$l3+1}{ids} = ""; } $inserted_spacers=1 } # insert spacers into previously created row. for ($l4=$l2;$l4<$l2+$week_slots{$l1}{$l2}{$l3}{width};$l4++) { $week_slots{$l1}{$l4}{$l3+1}{spacer}=1; #$debug_info .= "inserted spacer into row: ".($l3+1).", column $l4, event ".($week_slots{$l1}{$l4}{$l3}{ids}[0])."\n"; $total_spacers++; } #$debug_info .= "week $l1 day 0, slot 3: ".$week_slots{$l1}{0}{3}{ids}[0]."\n"; } } } #if ($l1 == 3) { #$debug_info .= "$total_spacers spacers inserted for week $l1.\n"; #$debug_info .= "week $l1 day 0, slot 3: ".$week_slots{$l1}{0}{3}{ids}[0]."\n"; #} #$debug_info .= "week $l1, event slots in row 1: $slots_in_row{$l1}{1}\n"; # calculate slots in each row: for ($l3=1;$l3<$week_max_slots{$l1};$l3++) { # for each slot if ((scalar @{$week_slots{$l1}{$l2}{$l3}{ids}}) > 0 ) { $slots_in_row{$l1}{$l3} += $week_slots{$l1}{$l2}{$l3}{width}; #$debug_info .= "event in row $l1. Incrementing slots_in_row {$l1} {$l3} to $slots_in_row{$l1}{$l3}\n"; } if ($week_slots{$l1}{$l2}{$l3}{spacer} == 1) { $slots_in_row{$l1}{$l3}++; #$debug_info .= "spacer in row $l1. Incrementing slots_in_row {$l1} {$l3} to $slots_in_row{$l1}{$l3}\n"; } } %max_day_needed_slots = (0=>$week_max_slots{$l1},1=>$week_max_slots{$l1},2=>$week_max_slots{$l1},3=>$week_max_slots{$l1},4=>$week_max_slots{$l1},5=>$week_max_slots{$l1},6=>$week_max_slots{$l1}); #$slots_in_row{$l1}{$slot_index}++; # extend event slots vertically. for ($l2=0;$l2<7;$l2++) { # for each day of the week for ($l3=1;$l3<$week_max_slots{$l1};$l3++) { # for each slot if (scalar @{$week_slots{$l1}{$l2}{$l3}{ids}} > 0 && $week_slots{$l1}{$l2}{$l3}{width} > 0) { # if this slot begins an event my $start_slot = $l3+1; for ($l4=$start_slot; $l4<$week_max_slots{$l1}+1; $l4++) { #$debug_info .= "checking slot $l4 below event slot ($l2, $l3)\n"; #if ($week_slots{$l1}{$l2}{$l4}{width} == 0) # {next;} if (scalar @{$week_slots{$l1}{$l2}{$l4}{ids}} > 0 && $week_slots{$l1}{$l2}{$l4}{width} eq $week_slots{$l1}{$l2}{$l3}{width}) { # another event below this one, with the same width. if ($l1 eq "3" && $debug) { $debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of another event below with the same width.\n";} #$debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of another event below with the same width.\n"; #$debug_info .= "same-width event slot below week $l1, slot ($l2, $l3)\n"; $week_slots{$l1}{$l2}{$l4}{width}=0; $week_slots{$l1}{$l2}{$l4}{depth}=0; $week_slots{$l1}{$l2}{$l3}{depth}++; push @{$week_slots{$l1}{$l2}{$l3}{ids}}, @{$week_slots{$l1}{$l2}{$l4}{ids}}; $max_day_needed_slots{$l2}--; #$slots_in_row{$l1}{$l4}--; } elsif ($week_slots{$l1}{$l2}{$l3}{width} == 1 && (scalar @{$week_slots{$l1}{$l2}{$l4}{ids}}) == 0 && $week_slots{$l1}{$l2}{$l4}{spacer} == 0) { # blank slot below 1-slot wide event slot if ($l1 eq "3" && $debug) { $debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of a blank slot below.\n";} #$debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of a blank slot below.\n"; #$debug_info .= "week $l1 slot ($l2, $l4) # ids:".scalar @{$week_slots{$l1}{$l2}{$l4}{ids}}."\n"; #$debug_info .= "blank slot below week $l1, slot ($l2, $l3)\n"; $week_slots{$l1}{$l2}{$l4}{width}=0; $week_slots{$l1}{$l2}{$l4}{depth}=0; $week_slots{$l1}{$l2}{$l3}{depth}++; $max_day_needed_slots{$l2}--; #$debug_info .= "week $l1, slot ($l2, $l3) depth: $week_slots{$l1}{$l2}{$l3}{depth} \n"; } else { $debug_info .= "week $l1 slot ($l2, $l4) occupied. Finished attempting to extend slot $l3\n" if ($debug); last; } } } } } #$debug_info .= "week $l1, event slots in row 1: $slots_in_row{$l1}{1}\n"; # extend blank slots vertically into other blank slots. for ($l2=0;$l2<7;$l2++) { # for each day of the week for ($l3=1;$l3<$week_max_slots{$l1};$l3++) { # for each slot next if (scalar @{$week_slots{$l1}{$l2}{$l3}{ids}} > 0); if ($week_slots{$l1}{$l2}{$l3}{width} > 0 && $week_slots{$l1}{$l2}{$l3}{spacer} == 0) { # if it's blank (but not a spacer) my $start_slot = $l3+1; for ($l4=$start_slot; $l4<$week_max_slots{$l1}+1; $l4++) { if ($week_slots{$l1}{$l2}{$l4}{width} == 1 && $week_slots{$l1}{$l2}{$l4}{spacer} == 0) { #$debug_info .= "blank slot below week $l1, slot ($l2, $l3)\n" if ($debug); $week_slots{$l1}{$l2}{$l4}{width}=0; $week_slots{$l1}{$l2}{$l4}{depth}=0; $week_slots{$l1}{$l2}{$l3}{depth}++; $max_day_needed_slots{$l2}--; } else { last; } } } } } #$debug_info .= "week $l1, event slots in row 1: $slots_in_row{$l1}{1}\n"; #$debug_info .= "week $l1 slot (4, 1) depth: $week_slots{$l1}{4}{1}{depth}\n"; # yet another pass. trim vertical depth and re-calculate max_slots # calculate trim my $trim = 0; #$debug_info .= "\n week $l1 max slots: $week_max_slots{$l1}\n"; #$debug_info .= "\nweek $l1, max_day_needed_slots: $max_day_needed_slots{0} $max_day_needed_slots{1} $max_day_needed_slots{2} $max_day_needed_slots{3} $max_day_needed_slots{4} $max_day_needed_slots{5} $max_day_needed_slots{6} $max_day_needed_slots{7}\n" if ($debug); $max_week_needed_slots = max(values %max_day_needed_slots); #$debug_info .= "week $l1 max_week_needed_slots: $max_week_needed_slots\n"; #if ($max_day_needed_slots >$max_week_needed_slots) # {$max_week_needed_slots = $max_day_needed_slots;} #$debug_info .= "max needed slots for week $l1, $max_week_needed_slots\n"; my $trim = $week_max_slots{$l1} - $max_week_needed_slots; # apply trim #$debug_info .= "trim for week $l1, $trim\n"; for ($l2=0;$l2<7;$l2++) { # for each day of the week for ($l3=$week_max_slots{$l1};$l3>0;$l3--) { # for each slot, counting backwards (upwards) if ($week_slots{$l1}{$l2}{$l3}{depth} > 0) { # blank or non-blank, with depth > 0 #$debug_info .= "trimming week $l1, slot ($l2, $l3) by $trim\n"; $week_slots{$l1}{$l2}{$l3}{depth} = $week_slots{$l1}{$l2}{$l3}{depth} - $trim; last; } } } $week_max_slots{$l1} = $week_max_slots{$l1} - $trim; } # repeat for next week # print day names if ($cal_month_idx == 0 || $show_month_breaks) { my @lowercase_day_names; foreach $day_name (@day_names) { push @lowercase_day_names, lc $day_name; } $return_text .=<<p1; <table class="calendar" summary=""> <tr> <td class="day_names $lowercase_day_names[0]">$weekday_sequence[0]</td> <td class="day_names $lowercase_day_names[1]">$weekday_sequence[1]</td> <td class="day_names $lowercase_day_names[2]">$weekday_sequence[2]</td> <td class="day_names $lowercase_day_names[3]">$weekday_sequence[3]</td> <td class="day_names $lowercase_day_names[4]">$weekday_sequence[4]</td> <td class="day_names $lowercase_day_names[5]">$weekday_sequence[5]</td> <td class="day_names $lowercase_day_names[6]">$weekday_sequence[6]</td> </tr> p1 } #cal_date keeps track of the date (in timestamp format) #as the calendar loop iterates through each day on the calendar page $cal_date = $cal_start_date; @cal_date_array = gmtime $cal_date; #locked and loaded, data structures assembled--now it's time to kick it, calendar-style. for ($l1=0;$cal_date_array[4] != $next_month; $l1++) { #each calendar has 5 or 6 weeks my $last_week=0; my $timestamp_next_week = $cal_date+604800; my @timestamp_next_week_array = gmtime $timestamp_next_week; my $week_date_index = $cal_date; # draw the table! for ($l3=0;$l3<$week_max_slots{$l1}+1;$l3++) { $return_text .="<tr id=\"week_$cal_date\">"; $week_date_index = $cal_date; for ($l2=0;$l2<7;$l2++) { # 7 days / week @cal_date_array = gmtime $week_date_index; my $td_class = "day ".lc($day_names[$l2]); $td_class .= " today" if ($cal_date_array[4] == $rightnow_month && $cal_date_array[3] == $rightnow_mday && $cal_date_array[5]+1900 == $rightnow_year); # display date numbers differently, depending on whether they are in the current month or not my $cal_month_name = ""; if ($show_month_breaks || $cal_num_months == 1) { $td_class .= " other_month" if ($cal_date_array[4] != $current_month); } else { $td_class .= " other_month_multi" if ($use_other_month[$cal_date_array[4] % 2]); $cal_month_name = $months[$cal_date_array[4]] if ($cal_date_array[3] == 1); } #if ($l2 == $week_events{$l1}{$week_slots{$l1}{$l2}{$l3}{id}}{start_weekday} && $week_events{$l1}{$week_slots{$l1}{$l2}{$l3}{id}}{start_weekday} ne "") if ($l3 == 0) { #if it's the top blank slot, put the date in there. $td_style="border-bottom-width:0px;"; #display the cell differently if it is today. if ($cal_date_array[4] == $rightnow_month && $cal_date_array[3] == $rightnow_mday && $cal_date_array[5]+1900 == $rightnow_year) { # offset the date number a few pixels # (so it will be in the center of the red circle) # offset a bit more for a double-digit day number. # small touches are the difference between good and great :) my $date_div_style = ""; $date_div_style = "text-indent: 11px;" if ($rightnow_mday > 10); $return_text .=<<p1; <td class="$td_class" style="$td_style" onmousedown="if (event.shiftKey) return show_day_contextmenu(event, $week_date_index); else return false;" oncontextmenu="return show_day_contextmenu(event, $week_date_index);"> <div class="date today" style="$date_div_style"><a id="today"></a>$cal_date_array[3] $cal_month_name</div> </td> p1 } else { $return_text .=<<p1; <td class="$td_class" style="$td_style" onmousedown="if (event.shiftKey) return show_day_contextmenu(event, $week_date_index); else return false;" oncontextmenu="return show_day_contextmenu(event, $week_date_index);"> <div class="date">$cal_date_array[3] $cal_month_name</div> </td> p1 } } elsif ($week_slots{$l1}{$l2}{$l3}{spacer} != 0) { # spacer slot my $spacer_class = "spacer"; if ($l3 == $week_max_slots{$l1}-1) { $spacer_class .= " bottom"; } $return_text .=<<p1; <td class="$td_class $spacer_class" style="$td_style" colspan=1 rowspan=1 onmousedown="if (event.shiftKey) return show_day_contextmenu(event, $week_date_index); else return false;" oncontextmenu="return show_day_contextmenu(event, $week_date_index);"> </td> p1 } elsif ($week_slots{$l1}{$l2}{$l3}{width} != 0) { # slot containing events $num_cols = $week_slots{$l1}{$l2}{$l3}{width}; $num_rows = $week_slots{$l1}{$l2}{$l3}{depth}; if (scalar @{$week_slots{$l1}{$l2}{$l3}{ids}} > 0) { $td_style="border-top-width:0px;border-bottom-width:0px;"; #($l2,$l3) $num_cols\lx$num_rows $return_text .=<<p1; <td class="$td_class" style="$td_style" colspan=$num_cols rowspan=$num_rows onmousedown="if (event.shiftKey) return show_day_contextmenu(event, $week_date_index); else return false;" oncontextmenu="return show_day_contextmenu(event, $week_date_index);"> p1 foreach $event_id (@{$week_slots{$l1}{$l2}{$l3}{ids}}) { my $multi_day_event = ($week_slots{$l1}{$l2}{$l3}{width} > 1) ? 1:0; my $background_event = (&contains($events{$event_id}{cal_ids}, $current_calendar{id})) ? 0:1; $return_text .= &display_calendar_event($event_id, $multi_day_event, $background_event) } $return_text .=<<p1; </td> p1 } elsif ($week_slots{$l1}{$l2}{$l3}{ids} eq "" && $week_slots{$l1}{$l2}{$l3}{width} > 0) { # blank slot $td_style="border-top-width:0px;border-bottom-width:0px;"; #($l2,$l3) blank $num_cols\lx$num_rows $return_text .=<<p1; <td class="$td_class" style="$td_style" colspan=$num_cols rowspan=$num_rows onmousedown="if (event.shiftKey) return show_day_contextmenu(event, $week_date_index); else return false;" oncontextmenu="return show_day_contextmenu(event, $week_date_index);"> </td> p1 } } $week_date_index += 86400; } # next day (first row) #right border $return_text .=<<p1; </tr> p1 } # event slot index # this little trick is the cat's pajamas. It's another row of # table cells that cause each calendar day to come down a little # bit below the lowest esvent. It makes the calendar look sharp. # Also, if the week has a small number of events, we expand the height of the bottom cell. # This makes all the calendar cells look square, which is the bee's knees. my $bottom_height_style = ""; if ($max_day_events{$l1} < 2) { my $height = (4-$max_day_events{$l1}) . "em"; # this algorithm was developed by guess & check #my $height = "100px"; # this algorithm was developed by guess & check $bottom_height_style = "line-height:$height;"; } $return_text .=<<p1; <tr style="$bottom_height_style"> p1 $week_date_index = $cal_date; for ($l2=0;$l2<7;$l2++) { #each week has 7 days(!) my $td_class = ""; @cal_date_array = gmtime $week_date_index; $td_class .= "day ".lc($day_names[$l2])." cell_bottom"; $td_class .= " today" if ($cal_date_array[4] == $rightnow_month && $cal_date_array[3] == $rightnow_mday && $cal_date_array[5]+1900 == $rightnow_year); if ($show_month_breaks || $cal_num_months == 1) { $td_class .= " other_month" if ($cal_date_array[4] != $current_month); } else { $td_class .= " other_month_multi" if ($use_other_month[$cal_date_array[4] % 2]); } $return_text .=<<p1; <td class="$td_class" style="line-height:5px;border-top-width:0px;$bottom_height_style" onmousedown="if (event.shiftKey) return show_day_contextmenu(event, $week_date_index); else return false;" oncontextmenu="return show_day_contextmenu(event, $week_date_index);"> </td> p1 $week_date_index+=86400; } $return_text .=<<p1; </tr> p1 $cal_date+=604800; @cal_date_array = gmtime $cal_date; } #close table tag for each month or only for last month on continuous_multimonth mode if ($show_month_breaks || $last_cal_month) { $return_text .=<<p1; </table> <br style="page-break-after:always;"> p1 } #increment to the next month--the method used #here is the most painless way of making #this work the right way in all cases. $current_month++; $cal_month_idx++; if ($current_month == 12) { $current_month=0; $current_year++; } } return $return_text; } #********************end render_calendar subroutine********************** sub background_event_colorize { my ($event_id, $calendar_id) = @_; my %event = %{$events{$event_id}}; my %calendar = %{$calendars{$calendar_id}}; my $event_bgcolor = $event{bgcolor}; if ($calendars{$event{cal_ids}[0]}{calendar_events_color} ne "") { $event_bgcolor = $calendars{$event{cal_ids}[0]}{calendar_events_color};} if ($calendar{background_events_display_style} eq "single_color") { $event_bgcolor = $calendar{background_events_color};} elsif ($calendar{background_events_display_style} eq "faded") { # create "faded" look for background event my $faded_color = $event_bgcolor; #convert rgb values from hex (00-FF) to decimal integer (0-255) my $r = hex substr $faded_color,1,2; my $g = hex substr $faded_color,3,2; my $b = hex substr $faded_color,5,2; #convert integer rgb values to hsv my @hsv_array = &rgb2hsv($r,$g,$b); #convert s and v from percentages to decimal $hsv_array[1] = $hsv_array[1]/100; $hsv_array[2] = $hsv_array[2]/100; #"fade" the color (decrease saturation) $hsv_array[1] = $hsv_array[1]/$calendar{background_events_fade_factor}; my @new_rgb_array = &hsv2rgb($hsv_array[0],$hsv_array[1],$hsv_array[2]); #convert back to hex $r = (sprintf ("%1.1X",$new_rgb_array[0])); $g = (sprintf ("%1.1X",$new_rgb_array[1])); $b = (sprintf ("%1.1X",$new_rgb_array[2])); $event_bgcolor = "#$r$g$b"; } return $event_bgcolor; } sub display_calendar_event { my ($event_id, $multi_day, $background_event) = @_; my %event = %{$events{$event_id}}; my $results = ""; my $event_bgcolor = $event{bgcolor}; # force white color if the background is dark my $textcolor_style = ""; my $r = hex substr $event_bgcolor,1,2; my $g = hex substr $event_bgcolor,3,2; my $b = hex substr $event_bgcolor,5,2; my $bright = ($r*299+$g*587+$b*114)/1000; $textcolor_style = "color:#fff" if ($bright < 128); $event_bgcolor = $current_calendar{calendar_events_color} if ($current_calendar{calendar_events_color} ne ""); my $event_box_class = "event_box"; # handle link my $event_link = "javascript:display_event('$event_id');"; $event_link = "$event{details}" if ($event{details_url} eq "1"); if ($background_event) { $event_box_class .= " background"; $event_bgcolor = &background_event_colorize($event_id, $current_calendar{id}); } # handle icon my $icon_text = ""; my $unit_icon_text = ""; if ($event{unit_number} ne "") { $unit_icon_text = $event{unit_number}." "; $unit_icon_text =~ s/(\d)/<img src="$graphics_url\/unit_number_patch_$1_16x10.gif" border="0" alt=\"\" vspace=0 hspace=0 style="vertical-align:middle;">/g; } my $link_style=""; if ($event{icon} ne "blank" && $event{icon} ne "") { $icon_text = <<p1; <img align="bottom" src = "$icons_url/$event{icon}_16x16.gif" style="margin-left:-22px;margin-right:5px;margin-bottom:-5px;" alt=""> p1 chomp $icon_text; $link_style="padding-left:29px"; } # context menu stuff my $event_context_menu_text="onmousedown=\"if (event.shiftKey) return show_event_contextmenu(event, $event_id, '$event_bgcolor', '$event{series_id}'); else return false; \" oncontextmenu=\"return show_event_contextmenu(event, $event_id, '$event_bgcolor', '$event{series_id}');\""; $event_context_menu_text = "" if ($event_id =~ /\D/); if ($multi_day == 0) { my $event_time = ""; if ($event{all_day_event} ne "1") { $event_time = &nice_time_range_format($event{start}, $event{end}); $event_time = "<span class=\"event_time\" style=\"$textcolor_style;\"> $event_time </span><br/>"; } my $temp_item_text = $calendar_item_template; $temp_item_text =~ s/###icon###/$icon_text$unit_icon_text/g; $temp_item_text =~ s/###title###/$event{title}/g; $temp_item_text =~ s/###time###/$event_time/g; my $calendar_title = $calendars{$event{cal_ids}[0]}{title}; $temp_item_text =~ s/###calendar title###/$calendar_title/g; $results .=<<p1; <a href="$event_link" class="$event_box_class" style="display:block;text-align:left;$link_style;background-color:$event_bgcolor;$textcolor_style;cursor:pointer;cursor:hand;" $event_context_menu_text> $temp_item_text</a> p1 } else { # multi-day-event # handle the case where an event is < 24 hours and crosses midnight. my $nudge_edge=""; my $event_time = ""; if ($event{all_day_event} ne "1") { if ($event{end} - $event{start} < 86400) { my $offset = 25; my $width = 50; $nudge_edge = "width:$width%;position:relative;left:$offset%;"; } $event_time = &nice_time_range_format($event{start}, $event{end}); $event_time = "<span class=\"event_time\" style=\"$textcolor_style;\"> $event_time </span>"; } if ($event{icon} ne "blank" && $event{icon} ne "") { $icon_text = <<p1; <img src="$icons_url/$event{icon}_16x16.gif" style="vertical-align:middle;margin-right:5px;" alt=""> p1 chomp $icon_text; } my $temp_item_text = $calendar_item_template; $temp_item_text =~ s/###icon###/$icon_text$unit_icon_text/g; $temp_item_text =~ s/###title###/$event{title}/g; $temp_item_text =~ s/###time###/$event_time/g; my $calendar_title = $calendars{$event{cal_ids}[0]}{title}; $temp_item_text =~ s/###calendar title###/$calendar_title/g; $results .=<<p1; <a href="$event_link" class="$event_box_class" style="display:block;text-align:center;background-color:$event_bgcolor;$textcolor_style;cursor:pointer;cursor:hand;$nudge_edge" $event_context_menu_text> $temp_item_text</a> p1 } } sub display_list_event { my ($event_id, $background_event, $sameday) = @_; my %event = %{$events{$event_id}}; my $results=""; @event_start_timestamp_array = gmtime $event{start}; my $date_string; my $weekday_string; if ($event{days} == 1) { #single-day event $date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3]"; $weekday_string = $day_names_abv[$event_start_timestamp_array[6]] } else { #multi-day event @event_end_timestamp_array = gmtime $event{end}; if ($event_start_timestamp_array[4] eq $event_end_timestamp_array[4]) { $date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3]-$event_end_timestamp_array[3]"; } else { $date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3] - $months_abv[$event_end_timestamp_array[4]] $event_end_timestamp_array[3]"; } $weekday_string = "$day_names_abv[$event_start_timestamp_array[6]]-$day_names_abv[$event_end_timestamp_array[6]]"; } # weekday abbreviations my $weekday_abv_string = $weekday_string; for ($l1=0;$l1<scalar @day_names;$l1++) { $weekday_abv_string =~ s/$day_names[$l1]/$day_names_abv[$l1]/g; } my $icon_text=""; my $unit_icon_text=""; if ($event{unit_number} ne "") { $icon_text = $event{unit_number}; $icon_text =~ s/(\d)/<img src="$graphics_url\/unit_number_patch_$1_16x10.gif" style=\"position:relative;top:5px;\" alt=\"\">/g; } if ($event{icon} eq "blank" || $event{icon} eq "") { $icon_text .= "$unit_icon_text"; } else { $icon_text .= "$unit_icon_text<img src = \"$icons_url/$event{icon}_16x16.gif\" style=\"position:relative;top:5px;\" alt=\"\">"; } my $event_bgcolor = $event{bgcolor}; if ($calendars{$event{cal_ids}[0]}{calendar_events_color} ne "") { $event_bgcolor = $calendars{$event{cal_ids}[0]}{calendar_events_color};} if ($background_event eq "1") { $event_bgcolor = &background_event_colorize($event_id, $current_calendar{id}); } my $event_context_menu_text="onmousedown=\"if (event.shiftKey) return show_event_contextmenu(event, $event{id}, '$event{bgcolor}', '$event{series_id}'); else return false;\" oncontextmenu=\"return show_event_contextmenu(event, $event{id}, '$event{bgcolor}', '$event{series_id}');\""; if ($event_id =~ /\D/) { $event_context_menu_text=""} my $day_context_menu_text = "onmousedown=\"if (event.shiftKey) return show_day_contextmenu(event, $event{start}); else return false;\" oncontextmenu=\"return show_day_contextmenu(event, $event{start});\""; # event time my $event_time = ""; if ($event{all_day_event} ne "1") { $event_time = &nice_time_range_format($event{start}, $event{end}); $event_time = "<span class=\"event_time\">$event_time</span>"; } my $event_link = "javascript:display_event('$event{id}');"; if ($event{details_url} eq "1") { $event_link = "$event{details}";} my $margin_top="7px"; $margin_top = "0" if ($sameday); my $temp_item_text = $list_item_template; $temp_item_text =~ s/###variable_margin###/$margin_top/g; $temp_item_text =~ s/###event_contextmenu###/$event_context_menu_text/g; $temp_item_text =~ s/###day_contextmenu###/$day_context_menu_text/g; $temp_item_text =~ s/###id###/$event_id/g; $temp_item_text =~ s/###bgcolor###/$event_bgcolor/g; $temp_item_text =~ s/###link###/$event_link/g; $temp_item_text =~ s/###details###/$event{details}/g; $temp_item_text =~ s/###icon###/$icon_text/g; $temp_item_text =~ s/###title###/$event{title}/g; $temp_item_text =~ s/###date###/$date_string/g; $temp_item_text =~ s/###weekday###/$weekday_string/g; $temp_item_text =~ s/###weekday_abv###/$weekday_abv_string/g; $temp_item_text =~ s/###time###/$event_time/g; $results .= $temp_item_text; $no_results .=<<p1; <li style="padding:0;margin:0;margin-top:$margin_top;"$event_context_menu_text> <span class="small_note" style="margin:0;border:0;vertical-align:middle;width:7em;white-space:nowrap;text-align:right;cursor:pointer;cursor:hand;" onclick="display_event('$event_id')" > $date_string </span> <a class="event_box" style="text-align:left;white-space:nowrap;background-color:$event_bgcolor;" href="$event_link"> $icon_text $event_time $event{title}</a> </li> p1 return $results; } sub render_list { my $return_text = ""; ($start_month, $start_year, $end_month, $end_year) = @_; #calculate where to start and end the list #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year); my $list_start_timestamp = timegm(0,0,0,1,$start_month,$start_year); my $list_end_timestamp = &find_end_of_month($end_month, $end_year); # loop through all the events. #Create an array of events which fall # within the current list view dates my @selected_cal_events; #and a funky data structure for the background calendars # each element of this hash will be an array. my $shared_cal_events={}; #empty hash foreach $event_id (keys %events) { if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$list_start_timestamp,$list_end_timestamp)) { my $event_in_current_calendar = 0; foreach $temp_cal_id (@{$events{$event_id}{cal_ids}}) { if ($temp_cal_id eq $current_cal_id) { push @selected_cal_events, $event_id;} foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) { if ($temp_cal_id eq $background_cal_id) { if ($current_calendar{list_background_calendars_together} eq "yes") { push @selected_cal_events, $event_id; } else { push @{$shared_cal_events{$background_cal_id}}, $event_id if (!&contains(\@selected_cal_events, $event_id)); } } } } } } # initialize loop variables $current_month = $start_month; $current_year = $start_year; $return_text .=<<p1; p1 while ($current_year < $end_year || ($current_year == $end_year && $current_month <= $end_month)) { my $current_month_start_timestamp = timegm(0,0,0,1,$current_month,$current_year); my $current_month_end_timestamp = &find_end_of_month($current_month, $current_year); $return_text .=<<p1; <div class="list_month_box"> p1 if ($cal_num_months> 1) { $return_text .=<<p1; $months[$current_month] $current_year p1 } if ($current_calendar{list_background_calendars_together} eq "yes") { $return_text .=<<p1; <ul class="list_cal_box" style="list-style-type:none;float:left;text-align:left;"> <div style="text-align:center;font-weight:bold;">$calendars{$current_cal_id}{title}</div> p1 #display events for selected calendar my $previous_event_id; foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @selected_cal_events) { my %event = %{$events{$event_id}}; if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) { my $background_event = ""; $background_event = "1" if ($event{cal_ids}[0] ne $current_cal_id); my @temp1 = gmtime($event{start}); my @temp2 = gmtime($events{$previous_event_id}{start}); my $sameday = ""; $sameday = "1" if ($temp1[3] == $temp2[3]); $return_text .= &display_list_event($event_id, $background_event, $sameday); $previous_event_id = $event_id; } } $return_text .=<<p1; </ul> p1 } else { $return_text .=<<p1; <ul class="list_cal_box" style="list-style-type:none;float:left;text-align:left;"> <li style="text-align:center;font-weight:bold;">$calendars{$current_cal_id}{title}</li> p1 #display events for selected calendar my $previous_event_id; foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @selected_cal_events) { my %event = %{$events{$event_id}}; if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) { my @temp1 = gmtime($event{start}); my @temp2 = gmtime($events{$previous_event_id}{start}); my $sameday = ""; $sameday = "1" if ($temp1[3] == $temp2[3]); $return_text .= &display_list_event($event_id,0,$sameday); $previous_event_id = $event_id; } } $return_text .=<<p1; </ul> p1 foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) { $return_text .=<<p1; <ul class="list_cal_box background" style="list-style-type:none;float:left;text-align:left;"> <li style="text-align:center;font-weight:bold;">$calendars{$background_cal_id}{title}</li> p1 #list events for that calendar my $previous_event_id; foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @{$shared_cal_events{$background_cal_id}}) { %event = %{$events{$event_id}}; if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$current_month_start_timestamp, $current_month_end_timestamp)) { my @temp1 = gmtime($event{start}); my @temp2 = gmtime($events{$previous_event_id}{start}); my $sameday = ""; $sameday = "1" if ($temp1[3] == $temp2[3]); $return_text .= &display_list_event($event_id,1,$sameday); $previous_event_id = $event_id; } } $return_text .=<<p1; </ul> <br style="clear:both;"/> <!--needed because IE sucks--> p1 } } $return_text .=<<p1; <br style="clear:both;"/> <!-- because IE sucks--> <br style="clear:both;"/> <!-- because IE sucks--> </div> <br style="clear:both;"/> <!-- because IE sucks--> <br style="clear:both;"/> <!-- because IE sucks--> p1 #increment to the next month--the method used #here is the most painless way of making #this work the right way in all cases. $current_month +=1; if ($current_month == 12) { $current_month=0; $current_year++; } } $return_text .=<<p1; p1 return $return_text; } #********************end generate_list subroutine********************** sub generate_event_details_javascript { my ($events_start_timestamp, $events_end_timestamp) = @_; my $return_string=""; my $num_events = 0; my $num_remote_events = 0; my $event_defs=""; my $remote_event_defs=""; $index=0; #loop through the events, check to see if they fall #within the current calendar month foreach $event_id (keys %events) { my %event = %{$events{$event_id}}; if (&time_overlap($event{start},$event{end},$events_start_timestamp,$events_end_timestamp)) { if ($event_id =~ /^r/) { $num_remote_events++; $remote_event_defs .= <<p1; remote_event_details["$event_id"] = new Object; remote_event_details["$event_id"].url = "$event{remote_calendar}{url}?view_event=1&evt_id=$event{remote_event_id}"; p1 } } } $return_string .=<<p1; var remote_event_details = new Array($num_remote_events); $remote_event_defs var event_details = new Array($num_events); $event_defs p1 return $return_string; } #********************end generate_event_details_javascript subroutine********************** sub pending_events_visible { # display pending events for this calendar? if ($options{pending_events_display} eq '0' || $options{pending_events_display} eq '1' || ($options{pending_events_display} eq '2' && $logged_in_as_current_cal_user) || # logged-in user of this calendar ($options{pending_events_display} eq '3' && $logged_in_as_current_cal_user) || # logged-in user of this calendar ($options{pending_events_display} eq '3' && $logged_in_as_current_cal_admin) || # logged-in admin of this calendar $logged_in_as_root # root ) {return 1}; return undef; } sub forced_login { my $results = ""; $results .= <<p1; <form name="forced_login_form" id="update_cal_form" action="" method="POST"> <input type="hidden" name="active_tab" value="$active_tab"> <input type="hidden" name="cal_id" value="$current_cal_id"/> <div class="info_box" style="clear:both;"> <p class="cal_title" style="text-align:center;"> $lang{login} </p> <div class="leftcol" style=""> <label class="required_field" for="cal_password">$lang{cal_password}</label> </div> <div class="rightcol" style="white-space:nowrap;"> <input type="password" name="cal_password" id="cal_password" size=12 /> <span class="small_note" ><a style="vertical-align:top;" href="javascript:display_help('current_password','$lang{cal_password}')">$lang{help_on_this}</a></span> </div> <div class="leftcol">   </div> <div class="rightcol" style="white-space:nowrap;"> <input type="submit" value="$lang{submit}"/> </div> <br style="clear:both;"/> </div> </form> p1 return $results; } sub generate_logged_in_stuff { # events & calendars pending approval, etc. my $results = ""; #if ($options{pending_events_display} > 1) #{ #} my $pending_events_text = ""; # display pending events for this calendar? #$debug_info .= "pending_events_visible: ".(&pending_events_visible)."\n"; if (&pending_events_visible) { foreach $new_event_id (keys %new_events) { push @pending_events_to_display, $new_event_id; } #$debug_info .= "scalar @ pending_events_to_display: ".(scalar @pending_events_to_display)."\n"; if (scalar @pending_events_to_display > 0) { $pending_events_text .= "<a href=\"javascript:approve_pending_events_toggle()\">"; $pending_events_text .= (scalar @pending_events_to_display)." "; if (scalar @pending_events_to_display == 1) { $pending_events_text .= $lang{pending_event1}; } else { $pending_events_text .= $lang{pending_event2}; } $pending_events_text .= "</a>"; } } # display pending events for other calendars? #if ($options{pending_events_display}) { #s} if ($pending_events_text ne "") { $results .= "$pending_events_text <div style=\"text-align:right;\" id=\"pending_events\"></div>"; } return $results; } sub csv_file_palm { ($start_month, $start_year, $end_month, $end_year) = @_; #calculate where to start and end the list #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year); my $list_start_timestamp = timegm(0,0,0,1,$start_month,$start_year); my $list_end_timestamp = &find_end_of_month($end_month, $end_year); #@cal_month_start_date_array = gmtime $cal_month_start_date; # loop through all the events. #Create an array of events which fall # within the current list view dates my @selected_cal_events; #and a funky data structure for the background calendars # each element of this hash will be an array. my $shared_cal_events={}; #empty hash foreach $event_id (keys %events) { if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$list_start_timestamp,$list_end_timestamp)) { my $event_in_current_calendar = 0; foreach $temp_cal_id (@{$events{$event_id}{cal_ids}}) { if ($temp_cal_id eq $current_cal_id) { push @selected_cal_events, $event_id;} foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) { if ($temp_cal_id eq $background_cal_id) { push @{$shared_cal_events{$background_cal_id}}, $event_id;} } } } } $html_output =<<p1; Cache-control: no-cache,no-store,private Content-disposition: filename="events.csv" Content-Type: text/csv; charset=$lang{charset}\n p1 #initialize loop variables #$current_timestamp = $list_start_timestamp; $current_month = $start_month; $current_year = $start_year; $html_output .=<<p1; CSV datebook: Category, Private, Description, Note, Event, Begin, End, Alarm, Advance, Advance Units, Repeat Type, Repeat Forever, Repeat End, Repeat Frequency, Repeat Day, Repeat Days, Week Start, Number of Exceptions, Exceptions p1 while ($current_year < $end_year || ($current_year == $end_year && $current_month <= $end_month)) { my $current_month_start_timestamp = timegm(0,0,0,1,$current_month,$current_year); my $current_month_end_timestamp = &find_end_of_month($current_month, $current_year); #display events for selected calendar foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @selected_cal_events) { my %event = %{$events{$event_id}}; if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) { my $csv_subject = "$event{title}"; @event_start_timestamp_array = gmtime $event{start}; my $csv_start_date = ($event_start_timestamp_array[5]+1900)." ".($event_start_timestamp_array[4]+1)." ".($event_start_timestamp_array[3]); my $csv_start_time = "$event_start_timestamp_array[2]:$event_start_timestamp_array[1]"; @event_end_timestamp_array = gmtime $event{end}; my $csv_end_date = ($event_end_timestamp_array[5]+1900)." ".($event_end_timestamp_array[4]+1)." ".($event_end_timestamp_array[3]); my $csv_end_time = "$event_end_timestamp_array[2]:$event_end_timestamp_array[1]"; my $csv_description = $event{details}; $csv_description =~ s/"/""/g; $csv_description =~ s/\n/\\n/g; if ($event{days} != 1) { @event_end_timestamp_array = gmtime $event{end}; $csv_end_date = ($event_end_timestamp_array[5]+1900)." ".($event_end_timestamp_array[4]+1)." ".($event_end_timestamp_array[3]); } $html_output .=<<p1; "$calendars{$current_cal_id}{title}","0","$csv_subject","$csv_description","1","$csv_start_date $csv_start_time","$csv_end_date $csv_end_time","0","0","0","0","1","$csv_end_date","0","0","0000000","0","0","" p1 } } foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) { #list events for that calendar foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @{$shared_cal_events{$background_cal_id}}) { my %event = %{$events{$event_id}}; if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$current_month_start_timestamp, $current_month_end_timestamp)) { my $csv_subject = "$event{title}"; @event_start_timestamp_array = gmtime $event{start}; my $csv_start_date = ($event_start_timestamp_array[5]+1900)." ".($event_start_timestamp_array[4]+1)." ".($event_start_timestamp_array[3]); my $csv_start_time = "$event_start_timestamp_array[2]:$event_start_timestamp_array[1]"; @event_end_timestamp_array = gmtime $event{end}; my $csv_end_date = ($event_end_timestamp_array[5]+1900)." ".($event_end_timestamp_array[4]+1)." ".($event_end_timestamp_array[3]); my $csv_end_time = "$event_end_timestamp_array[2]:$event_end_timestamp_array[1]"; my $csv_description = $event{details}; $csv_description =~ s/"/""/g; $csv_description =~ s/\n/\\n/g; $csv_description =~ s/"/""/g; $csv_description =~ s/\n/\\n/g; if ($event{days} != 1) { @event_end_timestamp_array = gmtime $event{end}; $csv_end_date = ($event_end_timestamp_array[5]+1900)." ".($event_end_timestamp_array[4]+1)." ".($event_end_timestamp_array[3]); } $html_output .=<<p1; "$calendars{$background_cal_id}{title}","0","$csv_subject","$csv_description","1","$csv_start_date $csv_start_time","$csv_end_date $csv_end_time","0","0","0","0","1","$csv_end_date","0","0","0000000","0","0","" p1 } } } #increment to the next month--the method used #here is the most painless way of making #this work the right way in all cases. $current_month +=1; if ($current_month == 12) { $current_month=0; $current_year++; } } $html_output .= $debug_info; print $html_output; } sub csv_file { ($start_month, $start_year, $end_month, $end_year) = @_; #calculate where to start and end the list #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year); my $list_start_timestamp = timegm(0,0,0,1,$start_month,$start_year); my $list_end_timestamp = &find_end_of_month($end_month, $end_year); #@cal_month_start_date_array = gmtime $cal_month_start_date; # loop through all the events. #Create an array of events which fall # within the current list view dates my @selected_cal_events; #and a funky data structure for the background calendars # each element of this hash will be an array. my $shared_cal_events={}; #empty hash foreach $event_id (keys %events) { if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$list_start_timestamp,$list_end_timestamp)) { my $event_in_current_calendar = 0; foreach $temp_cal_id (@{$events{$event_id}{cal_ids}}) { if ($temp_cal_id eq $current_cal_id) { push @selected_cal_events, $event_id;} foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) { if ($temp_cal_id eq $background_cal_id) { push @{$shared_cal_events{$background_cal_id}}, $event_id;} } } } } $html_output =<<p1; Cache-control: no-cache,no-store,private Content-disposition: filename="events.csv" Content-Type: text/plain; charset=$lang{charset}\n\n p1 #initialize loop variables #$current_timestamp = $list_start_timestamp; $current_month = $start_month; $current_year = $start_year; $html_output .=<<p1; "Subject","Start Date","Start Time","End Date","End Time","All day event","Reminder on/off","Reminder Date","Reminder Time","Meeting Organizer","Required Attendees","Optional Attendees","Meeting Resources","Billing Information","Categories","Description","Location","Mileage","Priority","Private","Sensitivity","Show time as" p1 while ($current_year < $end_year || ($current_year == $end_year && $current_month <= $end_month)) { my $current_month_start_timestamp = timegm(0,0,0,1,$current_month,$current_year); my $current_month_end_timestamp = &find_end_of_month($current_month, $current_year); #display events for selected calendar foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @selected_cal_events) { my %event = %{$events{$event_id}}; if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) { my $csv_subject = "$event{title} ($calendars{$current_cal_id}{title})"; @event_start_timestamp_array = gmtime $event{start}; my $csv_start_date = ($event_start_timestamp_array[4]+1)."/$event_start_timestamp_array[3]/".($event_start_timestamp_array[5]+1900); my $csv_start_time = ($event_start_timestamp_array[2]).":$event_start_timestamp_array[1]:".($event_start_timestamp_array[0]); @event_end_timestamp_array = gmtime $event{end}; my $csv_end_date = ($event_end_timestamp_array[4]+1)."/$event_end_timestamp_array[3]/".($event_end_timestamp_array[5]+1900); my $csv_end_time = ($event_end_timestamp_array[2]).":$event_end_timestamp_array[1]:".($event_end_timestamp_array[0]); my $csv_description = $event{details}; $csv_description =~ s/"/""/g; $csv_description =~ s/\n/\\n/g; if ($event{days} != 1) { @event_end_timestamp_array = gmtime $event{end}; $csv_end_date = ($event_end_timestamp_array[4]+1)."/$event_end_timestamp_array[3]/".($event_end_timestamp_array[5]+1900); } $html_output .=<<p1; "$csv_subject","$csv_start_date","$csv_start_time",$csv_end_date,"$csv_end_time","True","True","$csv_start_date","12:00:00 AM",,,,,,,"$csv_description",,,"Normal","False","Normal","1" p1 } } foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) { #list events for that calendar foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @{$shared_cal_events{$background_cal_id}}) { my %event = %{$events{$event_id}}; if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$current_month_start_timestamp, $current_month_end_timestamp)) { my $csv_subject = "$event{title} ($calendars{$background_cal_id}{title})"; @event_start_timestamp_array = gmtime $event{start}; my $csv_start_date = ($event_start_timestamp_array[4]+1)."/$event_start_timestamp_array[3]/".($event_start_timestamp_array[5]+1900); my $csv_start_time = ($event_start_timestamp_array[2]).":$event_start_timestamp_array[1]:".($event_start_timestamp_array[0]); @event_end_timestamp_array = gmtime $event{end}; my $csv_end_date = ($event_end_timestamp_array[4]+1)."/$event_end_timestamp_array[3]/".($event_end_timestamp_array[5]+1900); my $csv_end_time = ($event_end_timestamp_array[2]).":$event_end_timestamp_array[1]:".($event_end_timestamp_array[0]); my $csv_description = $event{details}; $csv_description =~ s/"/""/g; $csv_description =~ s/\n/\\n/g; $csv_description =~ s/"/""/g; $csv_description =~ s/\n/\\n/g; if ($event{days} != 1) { @event_end_timestamp_array = gmtime $event{end}; $csv_end_date = ($event_end_timestamp_array[4]+1)."/$event_end_timestamp_array[3]/".($event_end_timestamp_array[5]+1900); } $html_output .=<<p1; "$csv_subject","$csv_start_date","$csv_start_time",$csv_end_date,"$csv_end_time","True","True","$csv_start_date","12:00:00 AM",,,,,,,"$csv_description",,,"Normal","False","Normal","1" p1 } } } #increment to the next month--the method used #here is the most painless way of making #this work the right way in all cases. $current_month +=1; if ($current_month == 12) { $current_month=0; $current_year++; } } $html_output .= $debug_info; print $html_output; } sub vcalendar_export_cal { ($start_month, $start_year, $end_month, $end_year) = @_; #calculate where to start and end the list #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year); my $list_start_timestamp = timegm(0,0,0,1,$start_month,$start_year); my $list_end_timestamp = &find_end_of_month($end_month, $end_year); # loop through all the events. #Create an array of events which fall # within the current list view dates my @selected_cal_events; #and a funky data structure for the background calendars # each element of this hash will be an array. my $shared_cal_events={}; #empty hash foreach $event_id (keys %events) { if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$list_start_timestamp,$list_end_timestamp)) { my $event_in_current_calendar = 0; foreach $temp_cal_id (@{$events{$event_id}{cal_ids}}) { if ($temp_cal_id eq $current_cal_id) { push @selected_cal_events, $event_id;} foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) { if ($temp_cal_id eq $background_cal_id) { push @{$shared_cal_events{$background_cal_id}}, $event_id;} } } } } $html_output =<<p1; Cache-control: no-cache,no-store,private Content-disposition: filename="events.vcs" Content-Type: text/csv; charset=$lang{charset} BEGIN:VCALENDAR PRODID:-//Plans//EN VERSION:1.0 METHOD:PUBLISH p1 #initialize loop variables #$current_timestamp = $list_start_timestamp; $current_month = $start_month; $current_year = $start_year; while ($current_year < $end_year || ($current_year == $end_year && $current_month <= $end_month)) { my $current_month_start_timestamp = timegm(0,0,0,1,$current_month,$current_year); my $current_month_end_timestamp = &find_end_of_month($current_month, $current_year); #display events for selected calendar foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @selected_cal_events) { my %event = %{$events{$event_id}}; if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) { $html_output .= &event2vcal(\%event)."\n"; } } foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) { #list events for that calendar foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @{$shared_cal_events{$background_cal_id}}) { my %event = %{$events{$event_id}}; if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$current_month_start_timestamp, $current_month_end_timestamp)) { $html_output .= &event2vcal(\%event)."\n"; } } } #increment to the next month--the method used #here is the most painless way of making #this work the right way in all cases. $current_month +=1; if ($current_month == 12) { $current_month=0; $current_year++; } } $html_output .=<<p1; END:VCALENDAR p1 $html_output .= $debug_info; print $html_output; } sub ascii_text_cal { ($start_month, $start_year, $end_month, $end_year) = @_; #calculate where to start and end the list #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year); my $list_start_timestamp = timegm(0,0,0,1,$start_month,$start_year); my $list_end_timestamp = &find_end_of_month($end_month, $end_year); # loop through all the events. #Create an array of events which fall # within the current list view dates my @selected_cal_events; #and a funky data structure for the background calendars # each element of this hash will be an array. my $shared_cal_events={}; #empty hash foreach $event_id (keys %events) { if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$list_start_timestamp,$list_end_timestamp)) { my $done = 0; foreach $temp_cal_id (@{$events{$event_id}{cal_ids}}) { if ($temp_cal_id eq $current_cal_id) { push @selected_cal_events, $event_id;} foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) { if ($temp_cal_id eq $background_cal_id) { push @{$shared_cal_events{$background_cal_id}}, $event_id; $done = 1; last; } } if ($done == 1) {last;} } } } $html_output =<<p1; Cache-control: no-cache,no-store,private Content-Type: text/plain; charset=$lang{charset}\n\n p1 #initialize loop variables #$current_timestamp = $list_start_timestamp; $current_month = $start_month; $current_year = $start_year; while ($current_year < $end_year || ($current_year == $end_year && $current_month <= $end_month)) { my $current_month_start_timestamp = timegm(0,0,0,1,$current_month,$current_year); my $current_month_end_timestamp = &find_end_of_month($current_month,$current_year); $html_output .=<<p1; ******************************************* $months[$current_month] $current_year ******************************************* * $current_calendar{title} p1 #display events for selected calendar foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @selected_cal_events) { %event = %{$events{$event_id}}; if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) { @event_start_timestamp_array = gmtime $event{start}; my $event_time = ""; if ($event{days} == 1) { #single-day event $date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3] ".($event_start_timestamp_array[5]+1900); if ($event{all_day_event} ne "1") { $event_time = &nice_time_range_format($event{start}, $event{end}); $event_time = " ($event_time)"; } } else { #multi-day event $date_string = &nice_date_range_format($event{start}, $event{end}, "-")." ".($event_start_timestamp_array[5]+1900); } my $event_details = $event{details}; $event_details =~ s/\n[ \t\r\f]+/\n/g; chomp $event_details; #indent each line of the details $event_details =~ s/\n/\n /g; $html_output .=" $date_string$event_time: $event{title}\n"; if ($event_details ne "") { $html_output .= " $event_details\n"; } $html_output .= "\n"; } } foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) { $html_output .=<<p1; * $calendars{$background_cal_id}{title} p1 #list events for that calendar foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @{$shared_cal_events{$background_cal_id}}) { my %event = %{$events{$event_id}}; if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) { @event_start_timestamp_array = gmtime $event{start}; my $event_time = ""; if ($event{days} == 1) { #single-day event $date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3] ".($event_start_timestamp_array[5]+1900); if ($event{all_day_event} ne "1") { $event_time = &nice_time_range_format($event{start}, $event{end}); $event_time = " ($event_time)"; } } else { #multi-day event $date_string = &nice_date_range_format($event{start}, $event{end}, "-")." ".($event_start_timestamp_array[5]+1900); } my $event_details = $event{details}; $event_details =~ s/\n[ \t\r\f]+/\n/g; chomp $event_details; #indent each line of the details $event_details =~ s/\n/\n /g; $html_output .=" $date_string$event_time: $event{title}\n"; if ($event_details ne "") { $html_output .= " $event_details\n"; } $html_output .= "\n"; } } } #increment to the next month--the method used #here is the most painless way of making #this work the right way in all cases. $current_month +=1; if ($current_month == 12) { $current_month=0; $current_year++; } } $html_output .= $debug_info; print $html_output; } #********************end ascii_text_cal subroutine********************** sub ascii_text_event { my %current_event = %{$events{$current_event_id}}; $html_output =<<p1; Cache-control: no-cache,no-store,private Content-Type: text/plain; charset=$lang{charset}\n\n p1 my @event_start_timestamp_array = gmtime $current_event{start}; my $date_string=""; my $event_time = ""; if ($current_event{days} == 1) { #single-day event $date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3] ".($event_start_timestamp_array[5]+1900); if ($current_event{all_day_event} ne "1") { $event_time = &nice_time_range_format($current_event{start}, $current_event{end}); $event_time = "($event_time)"; } } else { #multi-day event $date_string = &nice_date_range_format($current_event{start}, $current_event{end}, "-")." ".($event_start_timestamp_array[5]+1900); } my $event_details = $current_event{details}; $event_details =~ s/\n\s+/\n/g; $event_details =~ s/\n{2,}/\n/g; chomp $event_details; #indent each line of the details $event_details =~ s/\n/\n /g; $html_output .=" $date_string$event_time: $current_event{title}\n"; if ($event_details ne "") { $html_output .= " $event_details\n\n"; } $html_output .= $debug_info; print $html_output; } #********************end ascii_text_event subroutine********************** sub icalendar_export_event { # only for 1 event # when exporting to outlook, plans uses the vcalendar standard. # (http://www.imc.org/rfc2445) # This standard is horribly supported by MS outlook (outlook 2000, at the # time of this writing. Outlook refuses to correctly interpret the # date-time strings in the following ways: # 1. If the date-time parameter does not specify a time (only a date), do you # think outlook sets its "all-day event" flag? Nope. It just assumes the # event occurs at 000000 hours (12 midnight). # 2. if no time zone is specified, the date-time string is supposed to be # interpreted as if it applied to the *current* timezone the user's computer # is in (according to the standard). Do you think outlook does this? Nope. # If no timezone is specified, outlook assumes the time zone is GMT. As if this # weren't enough, outlook "helpfully" adjusts the time to the user's time zone. # Depending on how far a user is from GMT, this may cause the day to change. # Since there's no way to predict what time zone a user is in, it is impossible # to compensate on the server side for outlook's stupidity. The workaround is # to generate event times for each event (even though this is misleading because # the events are all-day events), and force all the event times to 12 noon. # This puts them as far from the previous and next days as possible, giving the # least chance for outlook to screw up the day when it does its adjustment. my %current_event = %{$events{$current_event_id}}; my $ical_string = &event2ical(\%current_event); #Content-type: text/plain #Last-modified: Wed, 30 Jan 2002 22:43:12 GMT $html_output =<<p1; Content-type: text/x-vcalendar Content-disposition: filename="event.ics" BEGIN:VCALENDAR PRODID:-//Plans//EN VERSION:2.0 METHOD:PUBLISH $ical_string END:VCALENDAR p1 print $html_output; } #********************end vcalendar_export subroutine********************** sub vcalendar_export_event { # only for 1 event my %current_event = %{$events{$current_event_id}}; $vcal_string .= &event2vcal(\%current_event); #my $last_modified = &formatted_time($rightnow, "md mn yy hh:mm:ss GMT"); #Last-modified: $last_modified #Content-type: text/plain $html_output =<<p1; Content-type: text/vcs Content-disposition: filename="event.vcs" BEGIN:VCALENDAR PRODID:-//Plans//EN VERSION:1.0 METHOD:PUBLISH $vcal_string END:VCALENDAR p1 print $html_output; } #********************end vcalendar_export_event subroutine********************** sub calculate_recurring_events { my ($start_timestamp, $recurrence_parms_ref) = @_; my %recurrence_parms = %{$recurrence_parms_ref}; my @recurring_events_array = (); my @custom_months = @{$recurrence_parms{'custom_months'}}; my @timestamp_array = gmtime $start_timestamp; #$debug_info .= "start timestamp: $start_timestamp\n"; #foreach $custom_month (@custom_months) # {$debug_info .= "custom month: $custom_month\n";} #my $start_timestamp = $start_timestamp+50; #calculate the weekday_in_month_count for the start timestamp # (is it the first tuesday? second saturday? This is required for # things to work right. $real_year = 1900 + $timestamp_array[5]; $temp_start_timestamp = timegm(0,0,0,1,$timestamp_array[4],$real_year); #$debug_info .= "month_start_timestamp: $temp_start_timestamp\n"; @temp_start_timestamp_array = gmtime($temp_start_timestamp); # $debug_info .= <<p1; #start timestamp: $start_timestamp<br/> #end timestamp: $recurrence_parms{'recur_end_timestamp'}<br/> #the start timestamp ($months[$timestamp_array[4]] $timestamp_array[3], $real_year) <br/> #the temp start timestamp ($months[$temp_start_timestamp_array[4]] $temp_start_timestamp_array[3], $temp_start_timestamp_array[5]) <br/> #p1 my $weekday_in_month_count = 0; #figure out what weekday of the month the start timestamp is for (;$temp_start_timestamp < $start_timestamp;$temp_start_timestamp+=86400) { @temp_start_timestamp_array = gmtime($temp_start_timestamp); if ($temp_start_timestamp_array[6] == $timestamp_array[6]) { $weekday_in_month_count++; } } #this must be done, or the week-of-month recurring dates will be hosed #@temp_array = gmtime $start_timestamp; #my $current_month = $temp_array[4]; my $last_week=0; # set the start timestamp to a day boundary. my $boundary_timestamp = timegm(0,0,0,$timestamp_array[3],$timestamp_array[4],$real_year); my $timed_event_diff = $start_timestamp - $boundary_timestamp; $start_timestamp = $boundary_timestamp; #$debug_info .= "start timestamp (day boundary): $start_timestamp\n"; # The recurring event algorithm loops through each day in the timeframe # and tests its validity against the recurrence parameters. # These tests take the form of "assumed valid unless proven otherwise" # Doing it this way lets the various recurrence type tests operate # independently of each other, while looping only once through the timeframe for ($recur_timestamp = $start_timestamp; $recur_timestamp <= $recurrence_parms{'recur_end_timestamp'}; $recur_timestamp += 86400) { $last_week=0; my @recur_timestamp_array = gmtime $recur_timestamp; my $current_month = $recur_timestamp_array[4]; #look a week ahead, to see if the current weekday is the last one in the month my $recur_timestamp_next_week = $recur_timestamp+604800; my @recur_timestamp_next_week_array = gmtime $recur_timestamp_next_week; $last_week = 1 if ($current_month != $recur_timestamp_next_week_array[4]); $real_year = 1900 + $recur_timestamp_array[5]; $recur_timestamp_valid=1; if ($recurrence_parms{'recurrence_type'} eq "same_day_of_month") { $recur_timestamp_valid=0 if ($recur_timestamp_array[3] != $timestamp_array[3]); } elsif ($recurrence_parms{'recurrence_type'} eq "same_day_of_week") { if ($recur_timestamp_array[6] != $timestamp_array[6]) { $recur_timestamp_valid=0; } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_first_week") { $recur_timestamp_valid=0 if ($weekday_in_month_count != 0); } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_second_week") { $recur_timestamp_valid=0 if ($weekday_in_month_count != 1); } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_third_week") { $recur_timestamp_valid=0 if ($weekday_in_month_count != 2); } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_fourth_week") { $recur_timestamp_valid=0 if ($weekday_in_month_count != 3); } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_fifth_week") { $recur_timestamp_valid=0 if ($weekday_in_month_count != 4); } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_last_week") { if ($last_week != 1) { $recur_timestamp_valid=0; } else { #$debug_info .= "timestamp: $recur_timestamp\n"; #$debug_info .= "current month: $current_month\n"; #$debug_info .= "lookahead timestamp: $recur_timestamp_next_week\n"; #$debug_info .= "lookahead month: $recur_timestamp_next_week_array[4]\n"; } } } elsif ($recurrence_parms{'recurrence_type'} eq "every_x_days") { #$debug_info .= $q->param('every_x_days'); #$debug_info .= "\n"; $recur_timestamp_valid=0 if (($recur_timestamp - $start_timestamp) % (86400 * $recurrence_parms{'every_x_days'}) !=0); } elsif ($recurrence_parms{'recurrence_type'} eq "every_x_weeks") { #$debug_info .= ($q->param('every_x_weeks')."\n"); $recur_timestamp_valid=0 if (($recur_timestamp - $start_timestamp) % (86400 * 7 * $recurrence_parms{'every_x_weeks'}) !=0); } if ($recurrence_parms{'year_fit_type'} eq "custom_months") { my $month_valid=0; foreach $custom_month (@custom_months) { $month_valid=1 if ($custom_month == $recur_timestamp_array[4]); } $recur_timestamp_valid=0 if ($month_valid == 0); } if ($recur_timestamp_valid == 1) { push @recurring_events_array, $recur_timestamp+$timed_event_diff; my $real_year = $recur_timestamp_array[5]+1900; } #count how many of the event's weekdays we have come across in #each month. This is for validating events that occur on the #second tuesday, fifth monday, etc. if ($recur_timestamp_array[6] == $timestamp_array[6]) { $weekday_in_month_count++; } #reset week_in_month count if this is the last week in the month $weekday_in_month_count=0 if ($last_week == 1 && $recur_timestamp_array[6] == $timestamp_array[6]); } if (scalar @recurring_events_array == 0) { $debug_info .= "Error! No valid recurring event dates found!\n"; } #$debug_info .= "returning ".(scalar @recurring_events_array)." recurring events\n"; return \@recurring_events_array; } sub verify_date() { # $date is of the format similar to mm/dd/yy (or a permutation like dd/mm/yy) my ($date, $recurrence_parms_ref) = @_; my %recurrence_parms = %{$recurrence_parms_ref}; my $results=""; if ($date !~ /^(\w{1,2}\W\w{1,2}\W\w{2,4}|\w{1,2}\W\w{2,4}\W\w{1,2}|\w{2,4}\W\w{1,2}\W\w{1,2})$/) { $lang{date_verify_err0} =~ s/###date###/$date/; $lang{date_verify_err0} =~ s/###format###/$current_calendar{date_format}/; $results .= $lang{date_verify_err0}."\n"; } if ($recurrence_parms{'recurrence_type'} eq "every_x_days") { if ($recurrence_parms{'every_x_days'} == 0) { $results .= $lang{date_verify_err7}."\n"}; } elsif ($recurrence_parms{'recurrence_type'} eq "every_x_weeks") { if ($recurrence_parms{'every_x_weeks'} == 0) { $results .= $lang{date_verify_err8}."\n"}; } if ($date eq "") { $results .= $lang{date_verify_err1}."\n"; } my ($mon, $day, $year) = &format2mdy($date, $current_calendar{date_format}); if ($mon < 1 || $mon > 12) { $lang{date_verify_err4} =~ s/###month###/$mon/; $results .= $lang{date_verify_err4}."\n"; } $mon --; # convert month to 0-11 format if ($day < 1 || $day > 31) { $lang{date_verify_err5} =~ s/###day###/$day/; $results .= $lang{date_verify_err5}."\n"; } if ($year < 100) {$year+=2000;} if ($year < 1902 || $year > 2037) { $lang{date_verify_err6} =~ s/###year###/$year/; $results .= $lang{date_verify_err6}."\n"; } return $results; } sub verify_time { my ($time) = @_; my $results=""; if($options{twentyfour_hour_format}) { if ($time !~ /(\d+):(\d+)/) { $lang{time_verify_err0} =~ s/\{0\}/$time/; $results .= $lang{time_verify_err0}; } else { my $hours = $1; my $minutes = $2; if ($hours > 23 || $hours < 0){ $lang{time_verify_err1} =~ s/\{0\}/$hours/; $results .= $lang{time_verify_err1}; } if ($minutes > 59 || $minutes < 0){ $lang{time_verify_err2} =~ s/\{0\}/$minutes/; $results .= $lang{time_verify_err2}; } } } else { if ($time !~ /(\d+):(\d+)\s*($lang{am}|$lang{pm})/) { $lang{time_verify_err0} =~ s/\{0\}/$time/; $results .= $lang{time_verify_err0}; } else { my $hours = $1; my $minutes = $2; my $ampm = $3; if ($hours > 12 || $hours < 0) { $lang{time_verify_err1} =~ s/\{0\}/$hours/; $results .= $lang{time_verify_err1}; } if ($minutes > 60 || $minutes < 0) { $lang{time_verify_err2} =~ s/\{0\}/$minutes/; $results .= $lang{time_verify_err2}; } } } return $results; } sub preview_date { my $html_output .=<<p1; Cache-control: no-cache,no-store,private Content-Type: text/html; charset=$lang{charset}\n <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="pragma" content="no-cache"> <link rel="stylesheet" href="$css_path" type="text/css" media=screen> <title>$lang{date_preview_title}
    $lang{date_preview_title} p1 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'); $recurrence_parms{'recur_end_timestamp'} = 0; my @custom_months = $q->param('custom_months'); #my @custom_months = split(/\D+/, $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; my $recurring_event = $q->param('recurring_event'); my $event_start_date = $q->param('evt_start_date'); my $recur_end_date = $q->param('recur_end_date'); my $event_days = $q->param('evt_days'); my $event_start_time = $q->param('evt_start_time'); my $event_end_time = $q->param('evt_end_time'); my $all_day_event = $q->param('all_day_event'); #my $event_cal_id = $current_cal_id; #my %current_calendar = %{$calendars{$event_cal_id}}; my $date_valid = &verify_date($event_start_date); if ($event_days eq "") { $date_valid = $lang{date_verify_err2}; } if ($event_days =~ m/\D/ || $event_days <= 0) { my $temp = $lang{date_verify_err3}; $temp =~ s/\$1/$event_days/; $date_valid = $temp; } if ($recurring_event) { my $temp .= &verify_date($recurrence_parms{'recur_end_date'}, \%recurrence_parms); if ($temp ne "") { $date_valid .= "\n$lang{date_verify_for_recurring_end_date}\n

    $temp

    "; } } if ($date_valid eq "") { my ($start_mon, $start_mday, $start_year) = &format2mdy($event_start_date, $current_calendar{date_format}); my ($recur_end_mon, $recur_end_mday, $recur_end_year) = &format2mdy($recurrence_parms{'recur_end_date'}, $current_calendar{date_format}); $start_mon--; $recur_end_mon--; #calculate start timestamp #$event_start_timestamp = timegm(0,0,0,$start_mday,$start_mon,$start_year); #$debug_info .= "(preview_date) start_mday: $start_mday\n"; #$debug_info .= "(preview_date) start_mon: $start_mon\n"; #$debug_info .= "(preview_date) start_year: $start_year\n"; #$debug_info .= "(preview_date) event_days: $event_days\n"; #$debug_info .= "(preview_date) event_start_time: $event_start_time\n"; #$debug_info .= "(preview_date) event_end_time: $event_end_time\n"; #$debug_info .= "(preview_date) all_day_event: $all_day_event\n"; my ($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); @timestamp_array = gmtime $event_start_timestamp; my $real_year = $timestamp_array[5]+1900; if ($recurring_event == 1) { #calculate end timestamp $recurrence_parms{'recur_end_timestamp'} = timegm(0,0,0,$recur_end_mday,$recur_end_mon,$recur_end_year); $html_output .= <$lang{date_preview_recurring_event_falls_on}

    p1 my @recurring_events_array = @{&calculate_recurring_events($event_start_timestamp, \%recurrence_parms)}; foreach $recurring_event_timestamp (@recurring_events_array) { $timestamp1 = $recurring_event_timestamp; $timestamp2 = $recurring_event_timestamp + 86400 * ($event_days-1); if ($timestamp1 == $timestamp2) {$timestamp2++;} $date_range = &nice_date_range_format($timestamp1, $timestamp2, "-"); $html_output .= <$date_range

    p1 } } else { my $date = ""; $timestamp1 = $event_start_timestamp; $timestamp2 = $event_start_timestamp + 86400 * ($event_days-1); if ($timestamp1 == $timestamp2) {$timestamp2++;} $date_range = &nice_date_range_format($timestamp1, $timestamp2, "-"); $html_output .= <$lang{date_preview_this_event_falls_on}

    $date_range

    p1 } } else { $date_valid =~ s/\n//g; $html_output .= "

    $date_valid

    "; } $html_output .=< p1 #$html_output .="$debug_info"; $debug_info =~ s/\n//g; $html_output .=< p1 print $html_output; } # end preview date subroutine sub validate_event { my $results = ""; my $event_title = $q->param('evt_title'); my $all_day_event = $q->param('all_day_event'); my $event_start_date = $q->param('evt_start_date'); my $event_start_time = $q->param('evt_start_time'); my $event_end_time = $q->param('evt_end_time'); my $event_days = $q->param('evt_days'); my $date_valid = &verify_date($event_start_date); if ($date_valid eq "") { if ($all_day_event ne "1") { my $verify_time_results = &verify_time($event_start_time); if ($verify_time_results ne "") { my @sub_results = split("\n", $verify_time_results); foreach $sub_result (@sub_results) { $date_valid .= "[error]$lang{update_event_err14} $sub_result
    "; } } my $verify_time_results = &verify_time($event_end_time); if ($verify_time_results ne "") { my @sub_results = split("\n", $verify_time_results); foreach $sub_result (@sub_results) { $date_valid .= "[error]$lang{update_event_err15} $sub_result
    "; } } } } if ($event_title eq "") { $date_valid = $lang{update_event_err4}; } if ($event_days eq "") { $date_valid = $lang{date_verify_err2}; } if ($event_days =~ m/\D/ || $event_days <= 0) { my $temp = $lang{date_verify_err3}; $temp =~ s/\$1/$event_days/; $date_valid = $temp; } if ($date_valid eq "") { $results .= </g; $date_valid =~ s/"/\\"/g; $date_valid =~ s/'/\\'/g; $results .= </g; $debug_info =~ s/"/\\"/g; $debug_info =~ s/'/\\'/g; $results =~ s/###debug_info###/$debug_info/; print < $q->param('evt_title'), details => $q->param('evt_details'), cal_id => $current_cal_id, icon => $q->param('evt_icon'), bgcolor => $q->param('evt_bgcolor'), start => "", end => "", unit_number => $q->param('unit_number')}, 1); my $html_output .=< $lang{event_preview_title} $lang{event_preview_title} $event_info $debug_info p1 print $html_output; } # preview_event sub view_event { #$debug_info .= "(view_event) event $current_event{id} start: $current_event{start} \n" if ($current_event{id} eq "1815"); my %current_event = %{$events{$current_event_id}}; my $event_info = &generate_event_details(\%current_event); $debug_info =~ s/\n/\n/g; my $html_output .=< $current_event{title} $event_info $debug_info p1 print $html_output; } # view_event sub view_pending_event { my ($pending_event_ref) = @_; my %pending_event = %{$pending_event_ref}; $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 $event_info = &generate_event_details(\%pending_event); $debug_info =~ s/\n/\n/g; my $html_output .=< $current_event{title} $event_info $debug_info p1 print $html_output; } # view_pending_event sub email_reminder_prompt { my %current_event = %{$events{$current_event_id}}; my %previous_current_calendar = %current_calendar; %current_calendar = %{$calendars{$current_event{cal_ids}[0]}}; $date_string = &nice_date_range_format($current_event{start}, $current_event{end}, " - "); %current_calendar = %previous_current_calendar; my $title = "$current_event{title}$lang{email_reminder_title}"; my $results .=< p1 my $html_output .=<\n/g; $html_output .=< $lang{get_remote_calendars} $popup_javascript_info

    p1 # $html_output .=<
    $debug_info
    p1 print $html_output; } sub remote_calendar_request() { my $html_output .=<param('cal_id'); $results .=<$plans_version p1 #$debug_info .= "remote calendar request!"; # if the client requests a list of all calendars that are publically share-able. if ($q->param('get_public_calendars') eq "1") { foreach $cal_id (keys %calendars) { if ($calendars{$cal_id}{allow_remote_calendar_requests}) { my $temp=$calendars{$cal_id}{remote_calendar_requests_require_password}; $results .=<$cal_id$calendars{$cal_id}{title}$temp p1 } } } else { # return xml data for the events. my @current_cal_ids = (); my @temp = split (",",$current_cal_ids_string); my $cal_id_valid=1; foreach $cal_id (@temp) { if ($cal_id !~ /\D/) { push @current_cal_ids, $cal_id; } else { $cal_id_valid=0; $results .= "Invalid calendar ID: $cal_id"; last; } } if ($cal_id_valid) { foreach $current_cal_id (@current_cal_ids) { $results .=<$current_cal_id$calendars{$current_cal_id}{title}$calendars{$current_cal_id}{gmtime_diff} p1 } foreach $current_cal_id (@current_cal_ids) { foreach $event_id (keys %events) { my $event_in_current_calendar = 0; foreach $temp_cal_id (@{$events{$event_id}{cal_ids}}) { if ($temp_cal_id eq $current_cal_id) { $event_in_current_calendar = 1; last; } } next if ($event_in_current_calendar == 0); my $xml_data = &event2xml($events{$event_id}); $results .=<Script Name:
    $name

    p1 if ($options{email_mode} && !$writable{email_reminders_datafile}) { $results .=<Warning: The email reminders data file: $options{email_reminders_datafile} is not writable. This will cause some email functions to be disabled or not work correctly.
    p1 } if ($options{data_storage_mode} == 0 && !$writable{calendars_file}) { $results .=<Warning: The calendars data file: $options{calendars_file} is not writable. The add/edit calendars tab won't appear unless this file is writable.
    p1 } if ($options{data_storage_mode} == 0 && !$writable{pending_actions_file}) { $results .=<Warning: The pending actions data file: $options{pending_actions_file} is not writable. The add/edit calendars tab won't appear unless this file is writable.
    p1 } if ($options{data_storage_mode} == 0 && !$writable{events_file}) { $results .=<Warning: The events data file: $options{events_file} is not writable. The add/edit events tab won't appear unless this file is writable.
    p1 } my $cwd = `pwd`; $results .=<Plans version: $plans_version
    Perl version: $perl_version
    script name: $name
    script file path: $cwd
    script url path: $script_url

    Theme url: $theme_url
    graphics url: $graphics_url
    icons url: $icons_url

    Options:
    p1 # blank out options that we don't want public delete $options{db_name}; delete $options{db_hostname}; delete $options{db_username}; delete $options{db_password_file}; delete $options{mysql_password}; delete $options{salt}; foreach $option (keys %options) { $results .=<$option: $options{$option}
    p1 } return $results; } # end diagnostic subroutine sub assemble_icon_menus() { # this function extracts a data structure for the icon menus from the xml definition my ($data)= @_; # first, get the menuitems my @new_menuitems=(); my @menuitems = &xml_extract($data, "menuitem", 0); if (scalar @menuitems == 0) { $debug_info .= "Warning. There's a menu with no menuitems. This may be caused by an older version of Perl ( < 5.6).\n"; $debug_info .= "$data"; } else { foreach my $menuitem (@menuitems) { #$debug_info .= "menuitem: $menuitem->{data} ($menuitem->{position})
    "; my $icon_name = $menuitem->{attributes}{"value"}; my $icon_description = $menuitem->{data}; $icon_description = &encode($icon_description); $new_menuitems[$menuitem->{position}] = [$icon_name,$icon_description]; #$new_menuitems[$menuitem->{position}] = "name,description"; } } # then get the submenus my @submenus = &xml_extract($data, "menu", 0); foreach $submenu (@submenus) { my $temp = $submenu->{data}; my $temp2 = $submenu->{attributes}{name}; my @submenuitems = assemble_icon_menus($temp); #$debug_info .= "submenu: $temp2 ($submenu->{position})
    "; $new_menuitems[$submenu->{position}] = [$temp2, \@submenuitems]; } return @new_menuitems; } #******************** end assemble_icon_menus ********************** sub generate_flat_icon_menus { my ($icons_list, $selected_icon) = @_; my $return_text=""; #$debug_info .= "selected icon: $selected_icon
    "; my $indent = " "; for ($l1=0;$l1<$index_number;$l1++) { $indent .= " "; } foreach $icon_ref (@{$icons_list}) { my $identifier = @{$icon_ref}[1]; if ($identifier =~ /ARRAY/) { # if it's a submenu $icon_menu_index_number++; my $submenu_name = @{$icon_ref}[0]; #$debug_info .= "submenu $submenu_name
    "; $return_text .= < p1 $return_text .= &generate_flat_icon_menus(@{$icon_ref}[1], $selected_icon); $return_text .= < p1 } else { # if it's a menu item my $icon_filename = @{$icon_ref}[0]; my $icon_name = @{$icon_ref}[1]; $icon_name = &decode($icon_name); #$debug_info .= "icon name: $icon_name
    "; #$debug_info .= "icon filename: $icon_filename
    "; #$debug_info .= "
    "; if ($icon_filename eq $selected_icon) { $return_text .= <$icon_name p1 } else { $return_text .= <$icon_name p1 } } } return $return_text; } #******************** end generate_flat_icon_menus ********************** sub get_upcoming_events() { my $days_before = $q->param('days_before')+0; my $days_after = $q->param('days_after')+0; my $background_calendars_mode = $q->param('background_calendars_mode'); my $upcoming_events_id = $q->param('upcoming_events_id'); my $results = ""; my $start = $rightnow - $days_before*86400; my $end = $rightnow + $days_after*86400; #$debug_info .= "start: $start\n"; #$debug_info .= "end: $end\n"; #$debug_info .= (scalar keys %events)." events\n"; # clear events %events = (); #$debug_info .= (scalar keys %events)." events\n"; my @cal_ids = split(',',$q->param('cal_ids')); #$debug_info .= "cal_ids[0]: $cal_ids[0]\n"; #$debug_info .= "cal_ids[1]: $cal_ids[1]\n"; #&load_events("all"); #$debug_info .= (scalar keys %events)." events\n"; #$results .= &common_javascript(); my $date_format = lc $current_calendar{date_format}; $results .= "date_format = '$date_format';\n"; my %all_calendar_ids; foreach $calendar_id (@cal_ids) { next if ($calendars{$calendar_id}{id} eq ""); foreach $local_background_calendar_id (keys %{$calendars{$calendar_id}{local_background_calendars}}) { $all_calendar_ids{$local_background_calendar_id} = 1; } $all_calendar_ids{$calendar_id} = 1; } foreach $calendar_id (keys %all_calendar_ids) { $results .= "calendars['$calendar_id'] = new Calendar({".&calendar2javascript($calendars{$calendar_id})."});\n"; } my @temp; if ($background_calendars_mode ne "none") { @temp = keys %all_calendar_ids; } else { @temp = @cal_ids; } &load_events($start, $end, \@temp); &normalize_timezone; $results .= "all_calendars = new Array('".(join "','", keys %all_calendar_ids)."');\n"; foreach $event_id (keys %events) { $results .= "upcoming_events['$event_id'] = new Event({".&event2javascript($events{$event_id})."});\n"; $results .= "upcoming_events_order.push('$event_id'); \n"; } if ($debug_info ne "") { $debug_info = &javascript_cleanup($debug_info); #$debug_info = "debug_info = '$debug_info';\n"; $results .= "if ($upcoming_events_id.debug) debug('$debug_info');\n"; } $results .= "$upcoming_events_id.plans_theme_url='$theme_url';\n"; $results .= "$upcoming_events_id.show();\n"; my $nice_expires = $rightnow + $options{upcoming_events_cache_seconds}; $nice_expires = uc &formatted_time($nice_expires, "mn/md/yy hh:mm:ss AMPM"); my $cache_line = "Cache-control: no-cache,no-store,private"; $cache_line = "Cache-Control: max-age=$options{upcoming_events_cache_seconds};\nExpires: $nice_expires;" if ($options{upcoming_events_cache_seconds} > 0); my $html_output .=<$lang{export} $lang{these_events_to} p1 } sub add_edit_user() { my $results = ""; my $status = 1; my $id = $q->param('user_id'); my $name = $q->param('name'); my $notes = $q->param('notes'); my $password = $q->param('password'); my $new_password = $q->param('new_password'); my $repeat_password = $q->param('repeat_password'); my $delete_flag = $q->param('delete'); #$results .= "add/edit user!"; #$debug_info .= "cal_password: ".$q->param('cal_password')."\n"; #$debug_info .= "logged_in_as_root: $logged_in_as_root\n"; #$debug_info .= "logged_in_as_current_cal_admin: $logged_in_as_current_cal_admin\n"; $results .= "success = false;"; my $login_valid = 0; # validate password if ($logged_in_as_root) { # plans 'root' password $login_valid = 1;} elsif ($logged_in_as_current_cal_admin) { # current calendar admin $login_valid = 1;} #$debug_info .= "login_valid: $login_valid\n"; if (!$login_valid) { if ($delete_flag eq "1") { $results .= "messages = '$lang{user_not_deleted}';";} else { $results .= "messages = '$lang{user_not_added}';";} } else { # delete? if ($delete_flag eq "1") { my $temp = $lang{user_deleted}; $temp =~ s/\$1/$users{$id}{name}/; $results .= "messages = '$temps';"; delete $user{calendars}{$calendar_id}; #$debug_info .= "user $user_id, ".(scalar keys %{$user{calendars}})." calendars\n"; if (scalar keys %{$user{calendars}} == 0) { delete $users{$user_id}; } &update_user($user_id); &delete_user($id); $results .= "success = true;"; $results .= "users = new Array();"; $results .= &generate_users_javascript(); } else { # add or update? if ($id eq "") { # add $password = crypt($password, $options{salt}); my $new_id = $max_user_id+1; my %cal_refs; $cal_refs{$current_cal_id}{edit_events} = 1; $users{$new_id} = {id => $new_id, name => $name, notes => $notes, password => $password, calendars => \%cal_refs }; &add_user($new_id); $results .= "success = true;"; $results .= "users = new Array();"; $results .= &generate_users_javascript(); $results .= "messages += '$lang{user_added}';"; } else { # update $password = crypt($password, $options{salt}); my %cal_refs; $cal_refs{$current_cal_id}{edit_events} = 1; $users{$id} = {id => $id, name => $name, notes => $notes, password => $password, calendars => \%cal_refs }; &update_user($id); $results .= "success = true;"; $results .= "users = new Array();"; $results .= &generate_users_javascript(); $results .= "messages += '$lang{user_updated}';"; } } } $results .= "messages += '###debug_info###';"; $debug_info =~ s/\//\\\//g; $debug_info =~ s/\n//g; $debug_info =~ s/"/\\"/g; $debug_info =~ s/'/\\'/g; $results =~ s/###debug_info###/$debug_info/; print <param('ical_url')); my $results = ""; if (!$logged_in_as_root) { $results .= "messages = 'You must be logged in to add an iCal!';"; $results .= "var successful = false;"; } else { # try getting the URL my $url_results = &get_remote_file($ical_url); $debug_info .= $url_results; if ($url_results eq "404 not found!" || $url_results =~ /cannot connect/i) { $results .= "messages = 'iCal calendar not added! (invalid url)';"; $results .= "var successful = false;"; } else { my %new_calendar = &deep_copy(\%default_cal); my $new_cal_id = $max_cal_id + 1; $new_calendar{id} = $new_cal_id; $new_calendar{title} = "($ical_url)"; $new_calendar{type} = "ical"; $new_calendar{url} = $ical_url; $calendars{$new_cal_id} = &deep_copy(\%new_calendar); &add_calendars([$new_calendar{id}]); $results .= "messages = 'iCal calendar ($ical_url) added!';"; $results .= "success = true;"; } } $debug_info =~ s/\//\\\//g; $debug_info =~ s/\n//g; $debug_info =~ s/"/\\"/g; $debug_info =~ s/'/\\'/g; #$results .= "\ndebug_info: $debug_info"; print <id."', null, '$cookie_path');"; } elsif( $q->param('logout') eq "1") { $results .= "logged_in = false;"; $results .= "messages = get_lang('logged_in2')+'
    ###debug_info###';"; } else { $results .= "logged_in = false;"; $results .= "messages = get_lang('logged_in3')+'
    ###debug_info###';"; } $debug_info =~ s/\//\\\//g; $debug_info =~ s/\n//g; $debug_info =~ s/"/\\"/g; $debug_info =~ s/'/\\'/g; $results =~ s/###debug_info###/$debug_info/; print <param('approve'); my $delete = $q->param('delete'); my $results = ""; my $messages = ""; if ($logged_in_as_root || $logged_in_as_current_cal_admin) { $add_edit_event = "add"; $approve =~ s/[^(\d|,)]//g; $approve =~ s/[^(\d|,)]//g; my @events_to_approve = split(',', $q->param('approve')); my @events_to_delete = split(',', $q->param('delete')); foreach $event_to_approve (@events_to_approve) { &commit_event($new_events{$event_to_approve}); my $temp = $lang{pending_event_approved}; $temp =~ s/\$1/$event_to_approve/; $messages .= "$temp\n"; } foreach $event_to_delete (@events_to_delete) { my $temp = $lang{pending_event_deleted}; $temp =~ s/\$1/$event_to_delete/; $messages .= "$temp\n"; } push @events_to_delete, @events_to_approve; &delete_pending_actions(\@events_to_delete); $debug_info =~ s/\//\\\//g; $debug_info =~ s/\n//g; $debug_info =~ s/"/\\"/g; $debug_info =~ s/'/\\'/g; if ($debug_info != "") {$messages = "Debug info: $debug_info";} $messages =~ s/\//\\\//g; $messages =~ s/\n//g; $messages =~ s/"/\\"/g; $messages =~ s/'/\\'/g; #$results .= "messages = '$messages';\n"; $results .= "window.location='$script_url/$name?messages=".&encode($messages)."';"; #$results .= "alert(\"window.location=$script_url/$name&messages=".&encode($messages)."\");"; } else { $results .= "messages = '$lang{invalid_password}';update_messages();"; $results .= "cal_password = '';"; } print < $b} keys %calendars) { my %calendar = %{$calendars{$calendar_id}}; $results .= "calendars[$calendar_id] = new Object;"; $results .= "calendars[$calendar_id].users = new Array();"; foreach $user_ref (@{$calendar{users}}) { my %user = %{$user_ref}; $results .= "calendars[$calendar_id].users[$user{id}] = new Object;"; } } return $results; } sub api_add_delete_events() { my $results = ""; #$debug_info .= "(api_add_delete_events) before add_edit_events $events{159}{start} - $events{159}{end}\n"; my %add_edit_events_results = %{&add_edit_events()}; #$debug_info .= "(api_add_delete_events) after add_edit_events $events{159}{start} - $events{159}{end}\n"; if ($api_output_format eq "javascript") { if ($add_edit_events_results{success} eq "1") { $results .= "success=true;\n"; } else { $results .= "success=false;\n"; } my $messages = ""; foreach $results_message (@{$add_edit_events_results{messages}}) { $messages .= &javascript_cleanup($results_message); } $debug_info = &javascript_cleanup($debug_info); $debug_info =~ s/\\n//g; $rightnow_messages = "messages='$debug_info\\n$messages';\n"; $results .= $rightnow_messages; $results .= "update_messages(messages);"; $results .= "dialog_box.close();"; if ($add_edit_events_results{success} eq "1") { $results .= "window.location='$script_url/$name?messages=".&encode($messages)."';"; } } print </g; $html_output .=< Plans error! Plans error:
    $error_info

    Diagnostic information:
    $diagnostic_results p1 if ($debug_info ne "") { $debug_info =~ s/\n/
    /g; $html_output .=< Debug info:
    $debug_info p1 } $html_output .=< p1 print $html_output; exit(0); }