#!/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 if ($path ne "") { chdir $path; push @INC,$path; } # finished discovering name # some global variables (more further down) local $debug_info; local $plans_version = "5.6.5"; # version local $perl_version = (sprintf ("%vd",$^V)); local $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 $event_details_template; local %calendars; local %current_cal; local %latest_cal; local %latest_new_cal; local $max_cal_id = 0; local $max_new_cal_id = 0; local $max_series_id = 0; local %events; local %current_event; local %latest_event; local $max_event_id = 0; local %text; local $default_template_file = ""; local $theme_path = ""; local $choose_themes = ""; local $graphics_path = ""; local $icons_path = ""; local $input_cal_id_valid = 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) # check for required modules. my $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/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 (-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 (-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";} # get the language file, if one is defined if (defined $language_file) { $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;} } else { $fatal_error=1; $error_info .= "No language file defined in plans.config!\n"; } # check for perl version my $temp = substr($perl_version,0,3); if ($temp < 5.6) { $fatal_error=1; $error_info .= "Your version of perl ($perl_version) is too old! Plans requires perl version 5.6 or better.\n"; } if ($fatal_error == 1) # print error and bail out { &fatal_error(); } # init cgi stuff $q = new CGI; $script_url = $q->url(-path_info>=1); $script_url =~ /(.*)\//; # remove trailing / and all text after $script_url = $1; # remove trailing / and all text after # check if data files or tables are present &check_data(); # fatal error? Print error and bail out if ($fatal_error == 1) {&fatal_error();} if ($choose_themes) { $theme_url=$q->param('theme_url'); $theme_path=$theme_url; } if ($theme_path eq "") {$theme_path = "$script_url/theme";} $graphics_path ="$theme_path/graphics"; # where misc. graphics are $icons_path = "$theme_path/icons"; # where icons are $css_path = "$theme_path/plans.css"; # css file # globals for http parameters my $active_tab = $q->param('active_tab'); my $add_edit_cal_action = $q->param('add_edit_cal_action'); local $current_cal_id = $q->param('cal_id'); $current_cal_id = 0 if ($current_cal_id eq "" || $current_cal_id =~ /\D/); my $add_edit_event = $q->param('add_edit_event'); local $current_event_id = $q->param('evt_id'); local $cal_num_months = $q->param('cal_num_months'); local $cal_start_month = $q->param('cal_start_month'); local $cal_start_year = $q->param('cal_start_year'); my $special_action = $q->param('special_action'); local $cal_or_list = $q->param('cal_or_list'); # 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 $recur_end_timestamp; # load calendar data &load_calendars(); foreach $cal_id (keys %calendars) { if ($cal_id eq $current_cal_id && $cal_id ne "") {$input_cal_id_valid = 1;} } if (!$input_cal_id_valid) { $current_cal_id=0; #$q->param(-name=>'cal_id',-values=>[0]); } # make all calendars selectable by default foreach $cal_id (keys %calendars) {$default_cal{selectable_calendars}{$cal_id} = 1;} %current_cal = %{$calendars{$current_cal_id}}; # time-related globals $rightnow = time() + 3600 * $current_cal{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; # custom stylesheet? if ($current_cal{custom_stylesheet} ne "") { $css_path = "http://$current_cal{custom_stylesheet}"; } # if this is a custom calendar request, shoehorn the request parameters in if ($q->param('custom_calendar') == 1) { $current_cal_id = $q->param('custom_calendar_calendar'); @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_cal = %{$calendars{$current_cal_id}}; } # make sure we can select the current calendar #$current_cal{selectable_calendars}{$current_cal_id} = 1; # set info window height & width my ($info_window_width, $info_window_height) = split("x", $current_cal{info_window_size}); # rotate weekday_sequence by the offset defined in the week start day. for ($l1=0;$l1 < $current_cal{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) { if ($temp_line !~ /\w/) # skip any blank lines {next;} $temp_line =~ s/^\s+//; my ($hex_color) = split (/\s/, $temp_line); push @event_bgcolors, $hex_color; } my $template_html; #load template my $custom_template_file_found=1; if ($current_cal{custom_template} ne "") # custom template { $template_html = &get_remote_file("$current_cal{custom_template}"); if ($template_html !~ /###/) { $custom_template_file_found=0; $lang{custom_template_fail} =~ s/###template###/$current_cal{custom_template}/; $debug_info .= "$lang{custom_template_fail}\n"; } } if ($current_cal{custom_template} eq "" || $custom_template_file_found ==0) { if (!(-e "$default_template_file")) { $fatal_error=1; $lang{default_template_fail} =~ s/###template###/$default_template_file/; $debug_info .= "$lang{default_template_fail}\n"; &fatal_error(); } else { open (FH, "$default_template_file") || ($debug_info .="
Unable to open default template file $default_template_file for reading
"); flock FH,2; @template_lines=; close FH; $template_html = join "", @template_lines; } } # separate the main calendar template and the event details template $event_details_template = $template_html; $template_html =~ s/<\/html>.+/<\/html>/s; $template_html =~ s/.+<\/event_details>//s; # needed in case the event details aren't at the bottom of the html. It happens. if ($event_details_template =~ // && $event_details_template =~ /<\/event_details>/) { $event_details_template =~ s/.*//s; $event_details_template =~ s/<\/event_details>.+//s; } else { $debug_info .= "Warning! No event details template found. (The template file doesn't contain <event_details>...</event_details>\n"; $event_details_template = ""; } if($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###//; } #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 the input is greater than the number of tabs, things look goofy if ($q->param('active_tab') > 2 || $q->param('active_tab') eq "") { $active_tab = 0; } #if no month is selected, use the current month if ($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; } if ($cal_num_months eq "" || $cal_num_months > $current_cal{max_number_of_months}) { $cal_num_months = "$current_cal{default_number_of_months}"; } if ($cal_num_months eq "" || $cal_num_months > $current_cal{max_number_of_months}) { $cal_num_months = 1; } #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_cal{local_background_calendars}}) {push @temp_calendars, $local_background_calendar;} &load_events($cal_start_timestamp, $cal_end_timestamp, \@temp_calendars); if ($current_event_id ne "") { &load_event($current_event_id); %current_event = %{$events{$current_event_id}}; } #calculate next and previous start months & years $previous_cal_start_month=$cal_start_month-$cal_num_months; $previous_cal_start_year=$cal_start_year; if ($previous_cal_start_month < 0) { $previous_cal_start_month +=12; $previous_cal_start_year--; } if ($cal_num_months > 1) { $prev_string = $lang{previous_months}; $prev_string =~ s/###num###/$cal_num_months/; } else { $prev_string = $lang{previous_month}; } $next_cal_start_month=$cal_start_month+$cal_num_months; $next_cal_start_year=$cal_start_year; if ($next_cal_start_month > 11) { $next_cal_start_month -= 12; $next_cal_start_year++; } if ($cal_num_months > 1) { $next_string = $lang{next_months}; $next_string =~ s/###num###/$cal_num_months/; } else { $next_string = $lang{next_month}; } $consistent_parameter_string=""; &make_consistent ("cal_id"); &make_consistent ("cal_start_month"); &make_consistent ("cal_start_year"); &make_consistent ("cal_num_months"); &make_consistent ("cal_or_list"); &make_consistent ("theme_url"); if ($q->param('diagnostic_mode') eq "1") { &diagnostic_mode(); exit(0); } if ($q->param('remote_calendar_request') eq "1") { &remote_calendar_request(); 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); } } if ($q->param('export_event') eq "1") { if ($q->param('export_type') eq "ascii_text") { &ascii_text_event(); exit(0); } elsif ($q->param('export_type') eq "vcalendar") { #&csv_file($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year); &vcalendar_export(); exit(0); } } elsif ($q->param('view_event') eq "1") { &view_event(); exit(0); } elsif ($q->param('email_reminder') eq "1") { &email_reminder_prompt(); exit(0); } elsif ($q->param('email_reminder_confirm') eq "1") { &email_reminder_confirm(); exit(0); } elsif ($special_action eq "preview_event") { &preview_event(); exit(0); } elsif ($special_action eq "preview_date") { &preview_date(); exit(0); } $html_output .=< p1 chomp $insert_text; $html_output =~ s/###javascript stuff###/$insert_text/; #default page &display_default(); exit(0); sub display_default { chomp $insert_text; $html_output =~ s/###css file###/$css_path/g; # tab menu stuff $menu_tabs[0] = {status => "inactive", html => "$tab_text[0]"}; $menu_tabs[1] = {status => "inactive", html => "$tab_text[1]"}; $menu_tabs[2] = {status => "inactive", html => "$tab_text[2]"}; $menu_tabs[$active_tab]{status} ="active"; $menu_tabs[2]{html} = "$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###//; } else { $html_output =~ s/###tab menu stuff###/$insert_text/; } $insert_text =""; #invisible html for context menu $insert_text .=<
p1 #main box stuff $insert_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_cal{selectable_calendars}}; if (scalar keys %{$current_cal{selectable_calendars}} > 0) { $cal_controls_text .=< p1 #list each calendar for the user to select foreach $selectable_calendar_id (sort {$a <=> $b} keys %{$current_cal{selectable_calendars}}) { my $selected =""; $selected =" selected" if ($selectable_calendar_id eq $current_cal{id}); $selectable_calendar_id=~ s/\D//g; #$debug_info .= "calendar id: -$selectable_calendar_id-\n "; $cal_controls_text .=<$calendars{$selectable_calendar_id}{title} p1 } $cal_controls_text .=< p1 } else { $cal_controls_text .=<$current_cal{title} p1 } $cal_controls_text .=< p1 if ($cal_or_list eq "list") {$list_selected = "selected";} else {$cal_selected = "selected";} $cal_controls_text .=< $lang{controls_display_label}
p1 $cal_controls_text .=< p1 if ($q->param('custom_calendar') == 1) { $html_output =~ s/###calendar controls###//g; } else { $html_output =~ s/###calendar controls###/$cal_controls_text/g; } $insert_text .= &do_calendar_list_view(); #select event range $cal_month_start_date = timegm(0,0,0,1,$cal_start_month,$cal_start_year); @cal_month_start_date_array = gmtime $cal_month_start_date; $events_start_timestamp = $cal_month_start_date - 604800; # +7 day margin $events_end_timestamp = &find_end_of_month($cal_end_month, $cal_end_year) + 604800; # +7 day margin #now that we have selected the appropriate events, we can #generate the corresponding javascript and calendar view #and insert/add it to the html output. $common_javascript = &common_javascript(); $page_javascript = &calendar_view_javascript($events_start_timestamp, $events_end_timestamp); #display browser-appropriate javascript if ($browser_type eq "IE") {$browser_javascript = &IE_javascript();} else {$browser_javascript = &NS6_javascript();} #replace javascript placeholders with actual html/javascript code $html_output =~ s/###common javascript###/$common_javascript/; $html_output =~ s/###page-specific javascript###/$page_javascript/; $html_output =~ s/###browser-specific javascript###/$browser_javascript/; my $temp1 .=<$prev_string p1 my $temp2 .=<$next_string p1 $html_output =~ s/###previous month link###/$temp1/g; $html_output =~ s/###next month link###/$temp2/g; } elsif ($active_tab eq "1") #the second tab is the add/edit events view { $html_output =~ s/###calendar controls###//; $insert_text .=< p1 $insert_text .= &add_edit_events(); $insert_text .=< p1 #generate javascript for add/edit events page $common_javascript = &common_javascript(); $page_javascript = &add_edit_events_javascript(); #display browser-appropriate javascript if ($browser_type eq "IE") {$browser_javascript = &IE_javascript();} else {$browser_javascript = &NS6_javascript();} #replace javascript placeholders with actual html/javascript code $html_output =~ s/###common javascript###/$common_javascript/; $html_output =~ s/###page-specific javascript###/$page_javascript/; $html_output =~ s/###browser-specific javascript###/$browser_javascript/; # sneak in the color select javascript before all other javascript. my $temp =< p1 $html_output =~ s/(
$lang{tab2_select_a_calendar}

$add_edit_string

$lang{fields_text1} $lang{fields_text2} $lang{fields_text3}

$lang{help_on_this}  

 
$lang{choose_password}   $lang{help_on_this}
$lang{repeat_password}
 
 
$lang{preview_warning}

p1 } $return_text .=< p1 } else #a user added/edited/deleted an 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"); my $del_valid=1; #check password. $input_password = crypt($q->param('cal_password'), substr($q->param('cal_password'), 0, 2)); if ($input_password ne $current_cal{password} && $input_password ne $master_password) { $del_valid=0; push @results_messages, "$lang{update_cal_error1}$current_cal{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; foreach $event_id (keys %events) { if ($events{$event_id}{cal_id} eq $cal_id) {push @deleted_event_ids, $event_id;} } &delete_events(\@deleted_event_ids); # next, delete the calendar in question &delete_calendar($cal_id); # finally, delete any references in other calendars (background calendars) my @cals_to_update; foreach $calendar_id (sort {$a <=> $b} keys %calendars) { 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_cal{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"; } #$event_action_results = join "\n", @messages; $cal_del_results = "
    $cal_del_results
"; } else #the user added/updated an calendar { &load_new_calendars(); #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 $new_calendars_automatically_selectable = $q->param('new_calendars_automatically_selectable'); 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 $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 $preload_event_details = $q->param('preload_event_details'); 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; } $new_calendars_automatically_selectable = "no" if ($new_calendars_automatically_selectable ne "yes"); $preload_event_details = "no" if ($preload_event_details ne "yes"); 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)\/(mm|dd|yy)\/(mm|dd|yy)$/ ) { $cal_valid=0; push @results_messages, $lang{update_cal_error6_5}; } if ($add_edit_cal_action eq "edit") { #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 $input_password = crypt($cal_password, substr($cal_password, 0, 2)); if ($input_password ne $calendars{$cal_id}{password} && $input_password ne $master_password) { $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, substr($new_cal_password, 0, 2)); } } if ($cal_valid == 1) { # make new 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}{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}{preload_event_details} = $preload_event_details; $calendars{$cal_id}{info_window_size} = $info_window_size; $calendars{$cal_id}{custom_template} = $custom_template; $calendars{$cal_id}{custom_stylesheet} = $custom_stylesheet; # 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;} # 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;} # make sure the calendar can select itself. if (scalar keys %{$calendars{$cal_id}{selectable_calendars}} > 0) {$calendars{$cal_id}{selectable_calendars}{$cal_id} = 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 #if we need to create a completely new record { #check new password 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, substr($new_cal_password, 0, 2)); } my $new_cal_id; if ($cal_valid == 1) { $new_cal_id = $max_new_cal_id + 1; $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}{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; # 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) { if ($new_calendars{$new_cal_id}{title} eq $latest_new_cal{title} && $new_calendars{$new_cal_id}{details} eq $latest_new_cal{details} && $new_calendars{$new_cal_id}{link} eq $latest_new_cal{link}) { $cal_valid = 0; push @results_messages, $lang{update_cal_dup}; } } if ($cal_valid == 1) #all checks successful, add calendar! { &add_new_calendar($new_cal_id); my $new_cal_details = &generate_cal_details($new_calendars{$new_cal_id}); $new_cal_details =~ s///; $new_cal_details =~ s/Link directly.+<\/a>//s; $cal_add_results .= <

$lang{add_cal_success1}

$new_cal_details

$lang{add_cal_success2}

p1 close FH; } else { push @results_messages, "Calendar not added!"; } } close FH; } # 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'), substr($q->param('main_password'), 0, 2)); { 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") { #calculate new id # for the new calendar $max_cal_id+=1; 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. if (scalar keys %{$calendars{$max_cal_id}{selectable_calendars}} > 0) {$calendars{$max_cal_id}{selectable_calendars}{$max_cal_id} = 1;} 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_calendars(\@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 = ""; my $temp1=""; my $temp2=""; if ($q->param('custom_calendar') != 1) { $temp1 .=<$prev_string p1 $temp2 .=<$next_string p1 } if ($cal_num_months> 1) { $cal_title_string .=< $temp1 $cal_title_string $temp2
    p1 if ($cal_or_list eq "list") #list view { $return_text .= &generate_list($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year); } else #calendar view { $return_text .= &generate_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() { my $temp=""; $html_output =~ s//\n$temp\n/; my $return_text = ""; $add_edit_event = "add" if ($add_edit_event eq ""); if ($q->param('add_event_button') eq "" && $q->param('del_event_button') eq "") #add event main screen { $add_edit_string = $lang{add_or_edit1}; $event_details =""; $event_start_date = $current_cal{date_format}; if ($q->param('add_date_timestamp') eq "" || $q->param('add_date_timestamp') =~ /\D/) # 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/; } $recur_end_date = $current_cal{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=""; if ($add_edit_event eq "add") { $event_unit_number = ""; } elsif ($add_edit_event eq "edit") { $add_edit_string = $lang{add_or_edit2}; #select the appropriate event to edit %current_event = %{$events{$q->param('evt_id')}}; $current_cal_id=$current_event{cal_id}; %current_cal = %{$calendars{$current_event{cal_id}}}; $cal_title=$calendars{$current_event{cal_id}}{title}; $event_name=$current_event{title}; $event_details=$current_event{details}; $event_start_date = $current_cal{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 if ($add_edit_event eq "edit" || scalar keys %{$current_cal{selectable_calendars}} == 0) # force event calendar { $return_text .=<
    $lang{event_calendar}
    $current_cal{title}
    p1 } else # user can select event calendar { $return_text .=< $lang{event_calendar}
    $lang{help_on_this}

    $lang{help_on_this}  
    p1 $return_text .=<
    event icon
    p1 if ($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 $return_text .=<
    p1 if ($q->param('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 } else #a user added/edited/deleted an event--do checks and perform resulting action { my @results_messages; my $recurring_event = $q->param('recurring_event'); my $recurring_event_change_all = $q->param('recurring_event_change_all'); #$debug_info .= "recurring_event_change_all: $recurring_event_change_all\n"; if ($q->param('evt_cal_id') ne "") { %current_cal =%{$calendars{$q->param('evt_cal_id')}}; } # load (reload) all events (we have to write the # entire data file, and we might not have loaded all events already) if ($data_storage_mode == 0 ) # flat text files {&load_events("all");} if ($q->param('del_event_button') ne "") { #delete event. $del_valid=1; #check password. $input_password = crypt($q->param('evt_cal_password'), substr($q->param('evt_cal_password'), 0, 2)); if ($input_password ne $calendars{$current_event{cal_id}}{password} && $input_password ne $master_password) { $del_valid=0; push @results_messages, ($lang{update_event_err1}.$calendars{$current_event{cal_id}}{title}); } if (! defined $events{$current_event_id}) { $del_valid=0; push @results_messages, $lang{update_event_err2}; } if ($del_valid == 1) { #actually delete the event(s). if ($recurring_event eq "" || $recurring_event_change_all ne "1") { &delete_event($current_event_id); $event_action_results .= <$lang{update_event_delete_successful}

    p1 } else { # get the ids of the events in the series. my @events_in_series; foreach $event_id (keys %events) { my %event = %{$events{$event_id}}; if ($event{series_id} eq $q->param('series_id')) { push @events_in_series, $event_id; } } &delete_events(\@events_in_series); $event_action_results .= <$lang{update_event_delete_successful_recurring}

    p1 } } else { 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"; } $event_action_results = "
      $message_results
    $event_action_results"; } } else { #check all input fields for validity my $event_valid = 1; my $event_id = $q->param('evt_id'); # only if editing. my $event_cal_id = $q->param('evt_cal_id'); my $event_cal_password = $q->param('evt_cal_password'); my $event_title = $q->param('evt_title'); my $event_icon = $q->param('evt_icon'); my $event_details = $q->param('evt_details'); my $event_unit_number = $q->param('unit_number'); my $event_bgcolor = $q->param('evt_bgcolor'); my $event_series_id = $q->param('series_id'); $recur_end_date = $q->param('recur_end_date'); my $recur_end_timestamp = 0; $event_start_date = $q->param('evt_start_date'); $event_days = $q->param('evt_days'); # Check data for legitimacy. # some of these checks might be a bit redundant. if ($event_cal_id eq "") { $event_valid=0; push @results_messages, $lang{update_event_err3}; } if ($event_title eq "") { $event_valid=0; push @results_messages, $lang{update_event_err4}; } if ($event_icon eq "") { $event_valid=0; push @results_messages, $lang{update_event_err5}; } if ($event_cal_password eq "") { $event_valid=0; push @results_messages, $lang{update_event_err6}; } $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, $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{$event_cal_id}) { $event_valid=0; push @results_messages, $lang{update_event_err8}; } else { #check password $input_password = crypt($event_cal_password, substr($event_cal_password, 0, 2)); my $temp=$q->param("evt_cal_id"); if ($temp eq "" || $input_password ne $calendars{$temp}{password} && $input_password ne $master_password) { $event_valid=0; push @results_messages, ($lang{update_event_err1}."".$current_cal{title}.""); } } # check dates if ($event_valid == 1) { my $results = &verify_date_input_new($event_start_date, $event_days); if ($results ne "") { $event_valid=0; $results =~ s/(.+?)\n/
  • $1<\/li>\n/g; push @results_messages, "$lang{update_event_err9}
      $results
    " } } # check recurring dates if ($event_valid == 1) { @custom_months = $q->param('custom_months'); if ($recurring_event ne "" && $add_edit_event eq "add") { $results = &verify_date_input_new($recur_end_date, 1); if ($results ne "") { $event_valid=0; $results =~ s/(.+?)\n/
  • $1<\/li>\n/g; push @results_messages, "$lang{update_event_err10}
      $results
    " } } } if ($event_valid == 1) { my ($start_mon, $start_mday, $start_year) = &format2mdy($event_start_date, $current_cal{date_format}); $start_mon--; # convert month to 0-11 format $event_start_timestamp = timegm(0,0,0,$start_mday,$start_mon,$start_year); $event_end_timestamp = $event_start_timestamp + ($event_days * 86400) - 1; #if ($event_start_timestamp == $event_end_timestamp) # {$event_end_timestamp +=1;} # give all events a duration of at least 1 second if ($recurring_event ne "" && $add_edit_event eq "add") { my ($recur_end_mon, $recur_end_mday, $recur_end_year) = &format2mdy($recur_end_date, $current_cal{date_format}); $recur_end_mon--; $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, $lang{update_event_err11}; } } # check for refreshes! if ($recurring_event eq "") { if ($latest_event{cal_id} eq $event_cal_id && $latest_event{start} eq $event_start_timestamp && $latest_event{end} eq $event_end_timestamp && $latest_event{days} eq $event_days && $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, $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, $lang{update_event_err13}; } } # properly format errors & warnings $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"; } $event_action_results = "
      $message_results
    $event_action_results"; @results_message=(); if ($event_valid == 1) { #all checks successful, add/update event! $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/###delete event link###/$lang{event_details_delete_disable}/g; $event_details_template =~ s/###email reminder link###/$lang{event_email_reminder_disable}/g; if ($add_edit_event eq "add") # add a new event { if ($recurring_event eq "") { my $new_event_id = $max_event_id + 1; # add event to %events data structure $events{$new_event_id} = {id => $new_event_id, cal_id => $event_cal_id, start => $event_start_timestamp, end => $event_end_timestamp, days => $event_days, title => $event_title, details => $event_details, icon => $event_icon, bgcolor => $event_bgcolor, unit_number => $event_unit_number, update_timestamp => $rightnow}; &add_event($new_event_id); $event_box_text .= &generate_event_details($events{$new_event_id}); $event_action_results .= <$lang{update_event_add_successful}

    $event_box_text p1 } else # recurring events loop { &load_events("all") unless $loaded_all_events; $new_series_id = $max_series_id + 1; my $date_text=""; my @recurring_events_timestamps = @{&calculate_recurring_events($event_start_timestamp,$recur_end_timestamp)}; my @recurring_event_ids = (); foreach $recurring_event_start_timestamp (@recurring_events_timestamps) { $max_event_id += 1; my $new_event_id = $max_event_id; my $recurring_event_end_timestamp = $recurring_event_start_timestamp + ($event_days-1) * 86400; $recurring_event_end_timestamp = $recurring_event_start_timestamp + ($event_days * 86400) - 1; #if ($recurring_event_end_timestamp == $recurring_event_start_timestamp) # {$recurring_event_end_timestamp +=1;} # give all events a duration of at least 1 second $events{$new_event_id} = {id => $new_event_id, cal_id => $event_cal_id, start => $recurring_event_start_timestamp, end => $recurring_event_end_timestamp, days => $event_days, series_id => $new_series_id, title => $event_title, details => $event_details, icon => $event_icon, bgcolor => $event_bgcolor, unit_number => $event_unit_number, update_timestamp => $rightnow}; 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}); $event_action_results .= <$lang{update_event_add_successful_recurring}

      $date_text
    $event_box_text p1 } } elsif ($add_edit_event eq "edit") #if we need to replace an existing record { &load_events("all") unless $loaded_all_events; if ($recurring_event eq "" || $recurring_event_change_all ne "1") { $events{$event_id} = {id => $event_id, cal_id => $event_cal_id, start => $event_start_timestamp, end => $event_end_timestamp, days => $event_days, series_id => $event_series_id, title => $event_title, details => $event_details, icon => $event_icon, bgcolor => $event_bgcolor, unit_number => $event_unit_number, update_timestamp => $rightnow}; &update_event($event_id); $event_box_text .= &generate_event_details($events{$event_id}); $event_action_results .= <$lang{update_event_update_successful}

    p1 } else # update recurring events { #$debug_info .= "updating recurring event series\n"; # get the ids of the events in the series. my @events_in_series; foreach $event_id (keys %events) { my %event = %{$events{$event_id}}; #$debug_info .= "checking event $event_id series id $event{series_id} against ".$q->param('series_id')."\n"; if ($event{series_id} eq $q->param('series_id')) { #$debug_info .= "event in series: $event_id\n"; push @events_in_series, $event_id; $events{$event_id} = {id => $event_id, cal_id => $event_cal_id, start => $event{start}, end => $event{end}, days => $event{days}, series_id => $event{series_id}, title => $event_title, details => $event_details, icon => $event_icon, bgcolor => $event_bgcolor, unit_number => $event_unit_number, update_timestamp => $rightnow}; } } &update_events(\@events_in_series); $event_action_results .= <$lang{update_event_update_successful_recurring}

    p1 } } } } } $return_text .=< $event_action_results p1 return $return_text; } #******************** end add_edit_events ***************************** sub IE_javascript { my $return_string=""; $return_string .=<
    $lang{context_menu_edit_event}
    $lang{context_menu_delete_event}
    p1 $event_contextmenu_text = '' unless $writable{events_file}; $event_contextmenu_text =~ s/\//\\\//g; $event_contextmenu_text =~ s/\n/\\n/g; $event_contextmenu_text =~ s/"/\\"/g; $return_string .= <
    $lang{add_event_on_this_day}
    p1 $day_contextmenu_text = '' unless $writable{events_file}; $day_contextmenu_text =~ s/\//\\\//g; $day_contextmenu_text =~ s/\n/\\n/g; $day_contextmenu_text =~ s/"/\\"/g; $return_string .= < $lang{delete_event}

    $lang{password}: p1 $delete_event_text =~ s/\//\\\//g; $delete_event_text =~ s/\n/\\n/g; $delete_event_text =~ s/"/\\"/g; $return_string .= <'); doc.write('$lang{delete_event}<\\/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("$delete_event_text"); doc.write('<input type=\\"hidden\\" name=\\"evt_id\\" value=\\"'+active_event_id+'\\">'); doc.write('<br><input type=\\"submit\\" value= \\"Delete\\">'); doc.write('<\\/form><\\/div>'); doc.write('<\\/body><\\/html>'); doc.close(); info_window.focus(); } function docjslib_getRealLeft(imgElem) { xPos = imgElem.offsetLeft; tempEl = imgElem.offsetParent; //alert("element " + imgElem.id + "\\nparent "+ tempEl.id); //alert("element " + imgElem + "\\nparent "+ tempEl); while (tempEl != null) { xPos += tempEl.offsetLeft; tempEl = tempEl.offsetParent; } return xPos; } function docjslib_getRealTop(imgElem) { yPos = imgElem.offsetTop; tempEl = imgElem.offsetParent; while (tempEl != null) { yPos += tempEl.offsetTop; tempEl = tempEl.offsetParent; } return yPos; } function removename(el, name) { var i, curList, newList; // Remove the given class name from the className property of the element. newList = new Array(); curList = el.className.split(" "); for (i = 0; i < curList.length; i++) if (curList[i] != name) newList.push(curList[i]); el.className = newList.join(" "); } p1 return $return_string; } #********************end common_javascript ********************** sub calendar_view_javascript { my ($events_start_timestamp, $events_end_timestamp) = @_; my $return_string=""; # generate pre-formatted html for each day-zoom view for each day on the # current calendar. This routine is a good example of one of the choices # made in the design of this site--gaining client-side processor cycles # at the expense of bandwidth. It would be possible to send the event details # in a javascript array or hash, and have the client's browser dynamically # genearate the appropriate html. But it should be much faster to perform # this operation on the server and simply ship html to the client. The idea is # to make the javascript processing as simple as possible, becuase javascript # is sloooow. And even with all that extra html text, each page should still be # less than 100k (not counting images) #generate pre-formatted html for each event view if ($current_cal{preload_event_details} =~ /y/) { $return_string .= &generate_event_details_javascript($events_start_timestamp, $events_end_timestamp); } $return_string .=<<p1; var current_cell_id = -1; //line globals var num_lines=3; var source_x1=0; var source_y1=0; var target_obj=null; var line_color="\#000000"; var result=""; function do_on_load() { } function blink(el, times, onoff) { if (times==0) { if (onoff == 0 && document.getElementById(el).className.match(/blink/)) removename (document.getElementById(el),"blink"); if (onoff == 1 && !document.getElementById(el).className.match(/blink/)) document.getElementById(el).className += " blink"; return; } if (document.getElementById(el).className.match(/blink/)) removename (document.getElementById(el),"blink"); else document.getElementById(el).className += " blink"; setTimeout("blink('"+el+"',"+(times-1)+", "+onoff+")", 100); } function custom_calendar() { var info_window_x = window_x()-400; var info_window_y = window_y(); p1 $custom_form_text .=<<p1; <div class="cal_title"> $lang{custom_calendar_title} </div> <form action="$script_url/$name" method=POST> <input type="hidden" name="custom_calendar" value="1"> <input type="hidden" name="theme_url" value="$theme_url"> <label for="custom_calendar_calendar" class="required_field"> $lang{custom_calendar_choose_calendar} </label> <br/> <select id="custom_calendar_calendar" name="custom_calendar_calendar"> p1 foreach $cal_id (sort {$a <=> $b} keys %calendars) { $custom_form_text .=<<p1; <option value = "$cal_id">$calendars{$cal_id}{title} p1 } $custom_form_text .=<<p1; </select> <br/><br/> <label for="custom_calendar_background_calendars" class="optional_field"> $lang{custom_calendar_choose_bg_calendar} </label> <br/> <select id="custom_calendar_background_calendars" name="custom_calendar_background_calendars" multiple size=6> p1 foreach $cal_id (sort {$a <=> $b} keys %calendars) { $custom_form_text .=<<p1; <option value = "$cal_id">$calendars{$cal_id}{title} p1 } $custom_form_text .=<<p1; </select> <br/><br/> p1 if ($cal_or_list eq "list") {$list_selected = "selected";} else {$cal_selected = "selected";} $custom_form_text .=<<p1; <label for="cal_or_list" class="required_field"> $lang{custom_calendar_cal_or_list} </label> <select id="cal_or_list" name="cal_or_list"> <option value="calendar" $cal_selected>$lang{controls_calendar} <option value="list" $list_selected>$lang{controls_list} </select> <br/><br/> <label for="cal_start_month" class="required_field"> $lang{custom_calendar_time_range} </label> <table class="layout"> <tr><td nowrap align=right> $lang{controls_start_month} </td><td nowrap> <select id="cal_start_month" name="cal_start_month"> p1 #list each month in the year $month_index=0; foreach $possible_month (@months) { if ($cal_start_month eq $month_index) { $custom_form_text .=<<p1; <option value="$month_index" selected>$possible_month p1 } else { $custom_form_text .=<<p1; <option value="$month_index">$possible_month p1 } $month_index++; } $custom_form_text .=<<p1; </select> <input name="cal_start_year" value = "$cal_start_year" size=4> </td></tr> <tr><td nowrap align=left colspan=2> $lang{controls_num_months} <input name="cal_num_months" value = "$cal_num_months" size=3> </td></tr> </table> <br><br> <input type=submit value = "$lang{custom_calendar_make_calendar}"> p1 $custom_form_text =~ s/\//\\\//g; $custom_form_text =~ s/\n/\\n/g; $custom_form_text =~ s/"/\\"/g; $return_string .=<<p1; info_window = this.open("", "info_window", "resizable=yes,status=yes,scrollbars=yes,top="+info_window_y+",left="+info_window_x+",width=400,height=500"); doc = info_window.document; doc.open('text/html'); doc.write('<html>'); doc.write('<title>$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(); } function display_event(evt_id) { p1 # Here's another rare occurrence where Mozilla and IE 6+ are incompatible. # normally, this would be taken care of in the NS_javascript and IE_javascript # subroutines, but this is a special case. The javascript here is being stored # inside another javascript string, to be written to the details window if # an event is called. It's not being stored in perl at all, really. It just # looks that way. my $javascript_info = ""; if ($browser_type eq "IE") { $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 { $javascript_info .=<<p1; <script type="text/javascript" ><!-- function do_onresize() { opener.info_window_width = this.outerWidth; opener.info_window_height = this.outerHeight; } //--> </script> p1 } $javascript_info =~ s/\//\\\//g; $javascript_info =~ s/\n/\\n/g; $javascript_info =~ s/"/\\"/g; $return_string .=<<p1; var info_window_x = window_x()-$info_window_width; var info_window_y = window_y(); p1 if ($current_cal{preload_event_details} =~ /y/) { $return_string .=<<p1; var detail_string = event_details[evt_id].text; 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_details}<\\/title>'); doc.write('<base target=\\"'+main_window_name+'\\">'); doc.write('<\\/head>'); doc.write('<link rel=stylesheet href=\\"$css_path\\" type="text/css\\" media=screen>'); doc.write('$javascript_info'); doc.write('<body class=\\"event_details_body\\" onResize=\\"javascript:do_onresize()\\">'); doc.write(detail_string); doc.write('<\\/body><\\/html>'); doc.close(); p1 } else { $return_string .=<<p1; var URL_string="$script_url/$name?view_event=1&evt_id="+evt_id; 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); p1 } $return_string .=<<p1; info_window.focus(); } p1 return $return_string; } #***********************end calendar_view_javascript************************" sub add_edit_events_javascript { $return_string=""; my $javascript_info = ""; if ($browser_type eq "IE") { $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 { $javascript_info .=<<p1; <script type="text/javascript" ><!-- function do_onresize() { opener.info_window_width = this.outerWidth; opener.info_window_height = this.outerHeight; } //--> </script> p1 } $javascript_info =~ s/\n/\\n/g; $javascript_info =~ s/"/\\"/g; $javascript_info =~ s/\//\\\//g; $return_string.=<<p1; var help_text=""; var info_window_x = window_x()-$info_window_width; var info_window_y = window_y(); // color select stuff var cs0 = new color_select(); cs0.setrgb("$current_event{bgcolor}"); // hook up the color select to the appropriate browser events. cs_hookup(); function cs_init() { cs0.sv_image="$graphics_path/sv_blend.png"; // initial values for position var temp = document.getElementById("color_select_icon0"); cs0.x = docjslib_getRealLeft(temp); cs0.y = docjslib_getRealTop(temp) + 22; // attach the page elements to the appropriate color select handles. cs0.color_select_box = document.getElementById("color_select_box0"); cs0.h_select_box = document.getElementById("h_select_box0"); cs0.sv_select_box = document.getElementById("sv_select_box0"); cs0.sv_select_box_bg = document.getElementById("sv_select_box_bg0"); cs0.color_box = document.getElementById("color_box0"); cs0.color_value_box = document.getElementById("color_value_box0"); cs0.hue_cursor = document.getElementById("hue_cursor0"); cs0.sv_crosshair_horiz_cursor = document.getElementById("sv_crosshair_horiz_cursor0"); cs0.sv_crosshair_vert_cursor = document.getElementById("sv_crosshair_vert_cursor0"); cs0.update_function = "color_menu0_update"; // NOTE-there are no () cs0.update_color_box(); //cs0.sethsv(); //alert ("cs init done!"); } function color_menu0_update(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.getElementById("custom_evt_color").style.background = new_color; } function do_on_load() { if (!document.add_event_form.evt_bgcolor) return; 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; update_bg_color_select_box(); } 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('$javascript_info'); doc.write('<body onResize=\\"javascript:do_onresize()\\">'); doc.write(help_text); doc.write('<\\/body><\\/html>'); doc.close(); info_window.focus(); } function update_bg_color_select_box() { // 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.focus(); document.add_event_form.dummy.style.display='none'; if (!document.add_event_form.evt_bgcolor) return; document.add_event_form.evt_bgcolor.style.background = document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.selectedIndex].value //document.add_event_form.evt_title.focus(); } 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_path/" + 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_path/unit_number_patch_\$1_20x13.gif\\" border=\\"0\\" vspace=0 hspace=0>"); unit_num