3 # before anything else, the script needs to find out its own name
5 # some servers (notably IIS on windows) don't set the cwd to the script's
6 # directory before executing it. So we get that information
7 # from $0 (the full name & path of the script).
8 BEGIN{($_=$0)=~s![\\/][^\\/]+$!!;push@INC,$_}
11 $name =~ s/.+\/?.+\///; # for unix
12 $name =~ s/.+\\.+\\//; # for windows
14 $path =~ s/(.+\/).+/$1/g
; # for unix
15 $path =~ s/(.+\\).+/$1/g; # for windows
17 # The "use Cwd" method would be nice, but it doesn't work with
18 # some versions of IIS/ActivePerl
26 # finished discovering name
30 # some global variables (more further down)
31 local $plans_version = "7.9.7"; # version
34 local $perl_version = (sprintf ("%vd",$^V
));
35 #local $options{data_storage_mode};
36 local $fatal_error = 0; # fatal errors cause plans to abort and print an error message to the browser
37 local $error_info = "";
39 local $script_url = "";
40 local $messages = ""; # formatted in plain text with newlines. Converted to html at display time.
43 local $local_template_file = 0; # tells whether the template was loaded via a filesystem open or through a http request.
44 local $event_details_template;
45 local $list_item_template;
46 local $calendar_item_template;
47 local $upcoming_item_template;
50 local %current_calendar;
51 local %latest_calendar;
53 local $normalized_timezone = 0;
54 local $normalized_timezone_pending_events = 0;
56 # used when adding new entries
57 local $max_cal_id = 0;
58 local $max_event_id = 0;
59 local $max_series_id = 0;
60 local $max_user_id = 0;
61 local $max_action_id = 0;
63 # used to protect against refreshes
64 local $latest_cal_id = 0;
65 local $latest_event_id = 0;
66 local $latest_new_cal_id = 0;
67 local $latest_new_event_id = 0;
73 local $logged_in_as_root = 0;
74 local $logged_in_as_current_cal_user = 0;
75 local $logged_in_as_current_cal_admin = 0;
78 local $lg_password = "";
82 local @pending_events_to_display;
86 local $cookie_text = "";
87 local $cookie_header_text = "";
88 local $max_remote_event_id = 0;
90 local $options{default_template_path
} = "";
91 local $theme_url = "";
92 local $options{choose_themes
} = "";
93 local $graphics_url = "";
94 local $ical_export_url = "";
95 local $icons_url = "";
96 local $input_cal_id_valid = 0;
97 local $options{right_click_menus_enabled
} = 0;
104 local $loaded_all_events; # flag used to avoid calling load_events("all") twice
105 # not needed for calendars (we always load all calendars)
107 local @disabled_tabs;
109 # check for required modules.
112 foreach $temp_path (@INC) {
113 if (-e
"$temp_path/plans_config.pl") {
116 if ($module_found == 0) {
118 $error_info .= "Unable to locate <b>plans_config.pl</b>! It should be in the same directory as plans.cgi!\n";
119 } else {require "plans_config.pl";}
124 foreach $temp_path (@INC) {
125 if (-e
"$temp_path/CGI") {
129 if ($module_found == 0) {
131 $error_info .= "unable to locate required module <b>CGI</b>!\n";
136 foreach $temp_path (@INC) {
137 if (-e
"$temp_path/CGI/Session") {
141 if ($options{sessions
} eq "1") {
142 if ($module_found == 0) {
145 $error_info .= "unable to locate required module <b>CGI::Session</b>!\n";
147 require CGI
::Session
;}
151 foreach $temp_path (@INC) {
152 if (-e
"$temp_path/CGI/Carp.pm") {
156 if ($module_found == 0) {
158 $error_info .= "unable to locate required module <b>CGI::Carp</b>!\n";
160 use CGI
::Carp qw
/fatalsToBrowser/;}
163 foreach $temp_path (@INC) {
164 if (-e
"$temp_path/Time") {
168 if ($module_found == 0) {
170 $error_info .= "unable to locate required module <b>Time.pm</b>!\n";
175 foreach $temp_path (@INC) {
176 if (-e
"$temp_path/IO.pm") {
179 if ($module_found == 0) {
181 $error_info .= "unable to locate required module <b>IO.pm</b>!\n";
185 if ($fatal_error == 1) { # print error and bail out
191 foreach $temp_path (@INC) {
192 if (-r
"$temp_path/plans_lib.pl") {
195 if ($module_found == 0) {
197 $error_info .= "Unable to locate <b>plans_lib.pl</b>! It should be in the same directory as plans.cgi!\n";
198 } else {require "plans_lib.pl";}
200 # multi-language stuff
201 if (defined $options{language_files
}) {
202 my @language_files = split(',', $options{language_files
});
204 # pull in language files
205 foreach $language_file (@language_files) {
208 foreach $temp_path (@INC) {
209 if (-r
"$temp_path/$language_file") {
212 if ($module_found == 0) {
214 $error_info .= "Unable to locate language file <b>$language_file</b>! It should be in the same directory as plans.cgi!\n";
215 } else {require $language_file;}
218 # create a javascript file with language strings
219 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"};
221 my $first_lang_line=<FH
>;
224 if ($options{generate_js_lang
} eq "1" || $first_lang_line !~ /$plans_version/) {
225 my $lang_string = "";
226 $lang_string .= "//$plans_version\n";
227 $lang_string .= "var plans_lang = new Array();\n";
229 # generate %lang keys
230 foreach $lang_key (keys %lang) {
231 if (ref $lang{$lang_key} eq "ARRAY") {
232 $lang_string .= "plans_lang['$lang_key']=new Array(";
234 foreach $key (@
{$lang{$lang_key}}) {
235 if (!$first) {$lang_string .= ',';}
236 if ($first) {$first = 0;}
238 my $lang_val = &js_string
($key);
239 $lang_string .= "'$lang_val'";
241 $lang_string .= ");\n";
244 my $lang_val = &js_string
($lang{$lang_key});
246 $lang_string .= "plans_lang['$lang_key']='$lang_val';\n"
250 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"};
252 print FH
$lang_string;
257 $error_info .= "No language files defined in plans.config!\n";
260 # check for perl version
261 my $temp = substr($perl_version,0,3);
264 $error_info .= "Your version of perl ($perl_version) is too old! Plans requires perl version 5.6 or better.\n";
267 if ($fatal_error == 1) { # print error and bail out
274 if ($options{calendar_url
} ne "") {
275 $script_url = $options{calendar_url
};
277 $script_url = $q->url(-path_info
>=1);
279 $script_url =~ /(.*)\//; # remove trailing / and all text after
280 $script_url = $1; # remove trailing / and all text after
282 %cookie_parms = %{&extract_cookie_parms
()};
283 my $cookie_path = $q->url( -absolute
=> 1 );
284 $cookie_path =~ s/$name$//;
285 $cookie_path =~ s/admin\/?$//; # This is better than using just '/'
287 # check if data files or tables are present
290 # fatal error? Print error and bail out
291 if ($fatal_error == 1) {
295 if ($theme_url eq "") { # not defined in config file
296 $theme_url = "$script_url/theme";
299 if ($options{choose_themes}) {
300 $chosen_url = $q->param('theme_url
');
301 $chosen_url = $cookie_parms{'theme_url
'} if ($chosen_url eq "");
302 $theme_url = $chosen_url if ($chosen_url ne "");
305 $graphics_url ="$theme_url/graphics"; # where misc. graphics are
306 $ical_export_url ="$theme_url/ical"; # where icalendar .ics files are placed
307 $icons_url = "$theme_url/icons"; # where icons are
308 $css_path = "$theme_url/plans.css"; # css file
311 # globals from http parameters
312 my $active_tab = $q->param('active_tab
') + 0; # +0 ensures numericity
313 $active_tab = 0 if ($active_tab > scalar @{$lang{tab_text}} - 1);
315 my $api_output_format = $q->param('output_format
');
316 my $api_command = $q->param('api_command
');
318 my $add_edit_cal_action = $q->param('add_edit_cal_action
');
319 $add_edit_cal_action = "" if (!&contains(["add", "edit", "view_pending"],$add_edit_cal_action)); # validate
321 my $add_edit_event = $q->param('add_edit_event
');
322 $add_edit_event = "" if (!&contains(["add", "edit"],$add_edit_event)); # validate
324 local $current_event_id = $q->param('evt_id
');
325 $current_event_id = "" if ($current_event_id !~ /^R?\d+$/); # validate
327 local $current_event_ids = $q->param('evt_ids
');
328 $current_event_ids = "" if ($current_event_ids !~ /^R?[\d,\,]+$/); # validate
330 local $pending_event_id = $q->param('pending_event_id
');
331 $pending_event_id = "" if ($pending_event_id !~ /^R?\d+$/); # validate
333 local $cal_start_month = $q->param('cal_start_month
') + 0; # +0 ensures numericity
334 local $cal_start_year = $q->param('cal_start_year
') + 0; # +0 ensures numericity
335 local $cal_num_months = $q->param('cal_num_months
') + 0; # +0 ensures numericity
337 # if view parameters not supplied in http request, check cookie
338 $cal_start_month = $cookie_parms{'cal_start_month
'} if ($q->param('cal_start_month
') eq "");
339 $cal_start_year = $cookie_parms{'cal_start_year
'} if ($cal_start_year == 0);
340 $cal_num_months = $cookie_parms{'cal_num_months
'} if ($cal_num_months == 0);
342 my $special_action = $q->param('special_action
'); # needs no validation - never used in output
344 local $display_type = $q->param('display_type
') + 0; # +0 ensures numericity
345 $display_type = $cookie_parms{'display_type
'} if ($q->param('display_type
') eq "");
348 $messages = $q->param('messages
') if ($q->param('messages
') ne "");
352 my $event_start_date;
353 my $event_start_timestamp;
360 my $prev_month_link = "";
361 my $next_month_link = "";
368 local $current_cal_id = 0;
370 if ($q->param('cal_id
') eq "") {
371 $current_cal_id = $cookie_parms{'cal_id
'} if ($current_cal_id == 0);
373 $current_cal_id = $q->param('cal_id
');
375 $current_cal_id += 0; # +0 ensures numericity
377 # if calendar id not supplied, but evt_id is supplied (like when viewing an event) use that event's calendar as the current calendar
378 #if ($current_event_id ne "")
380 # &load_event($current_event_id);
382 # my %temp_current_event = %{$events{$current_event_id}};
383 # if ($current_cal_id eq "")
385 # $current_cal_id = $temp_current_event{cal_ids}[0];
389 foreach $cal_id (keys %calendars) {
390 if ($cal_id eq $current_cal_id) {
391 $input_cal_id_valid = 1;}
394 if ($current_cal_id eq "") {
395 $input_cal_id_valid = 0;}
397 if ($current_cal_id =~ /\D/) {
398 $input_cal_id_valid = 0;}
400 $current_cal_id = 0 if ($current_event_id eq "" && !$input_cal_id_valid);
402 # make all calendars selectable by default
403 foreach $cal_id (keys %calendars) {
404 $default_cal{selectable_calendars
}{$cal_id} = 1;}
406 %current_calendar = %{$calendars{$current_cal_id}};
408 # time-related globals
409 $rightnow = time() + 3600 * $current_calendar{gmtime_diff
};
410 @rightnow_array = gmtime $rightnow;
411 $rightnow_year = $rightnow_array[5]+1900;
412 $rightnow_month = $rightnow_array[4];
413 $rightnow_mday = $rightnow_array[3];
414 $next_year = $rightnow_year+1;
415 $rightnow_description = formatted_time
($rightnow, "hh:mm:ss mn md yy");
417 @weekday_sequence = @day_names;
421 if ($options{sessions
} eq "1") {
422 #$lg_name = $q->param('lg_name');
423 $lg_name = $current_cal_id;
424 $lg_password = $q->param('cal_password');
426 &delete_old_sessions
(1); # in days
428 #$debug_info .= "plans_sid (cookie): ".$q->cookie("plans_sid")."\n";
430 my $current_session_id = $q->cookie("plans_sid") || undef;
433 $session = new CGI
::Session
(undef, $current_session_id, {Directory
=>$options{sessions_directory
}});
434 $session->expire("+1d");
436 #$debug_info .= "current_session_id: $current_session_id\n";
439 if ($q->param('logout') eq "1") {
441 $cookie_text .= "Set-Cookie; plans_sid=deleted; path=$cookie_path;\n";
444 # try to match session with user id. (If this fails, it's not really a session.)
445 my $results = &init_session
($q, $session);
446 $profile = $session->param("~profile");
448 if (defined $profile->{calendar_permissions
}) {
450 $cookie_text .= "Set-Cookie: plans_sid=".$session->id."; path=$cookie_path;\n";
454 if ($options{sessions
} eq "1") {
455 $logged_in_as_root = ($profile->{calendar_permissions
}->{0}->{admin
} eq "1") ?
1:0;
456 $logged_in_as_current_cal_user = ($profile->{calendar_permissions
}->{$current_cal_id}->{user
} ne "") ?
1:0;
457 $logged_in_as_current_cal_admin = ($profile->{calendar_permissions
}->{$current_cal_id}->{admin
} ne "") ?
1:0;
458 } elsif ($q->param('cal_password') ne "") {
459 $logged_in_as_root = ($calendars{0}{password
} eq crypt($q->param('cal_password'), $options{salt
})) ?
1:0;
460 $logged_in_as_current_cal_admin = ($current_calendar{password
} eq crypt($q->param('cal_password'), $options{salt
})) ?
1:0;
462 foreach $user_id (keys %users) {
463 my %user = %{$users{$user_id}};
464 my %user_calendars = %{$user{calendars
}};
465 foreach $user_cal_id (keys %user_calendars) {
466 if ($user_cal_id eq $current_cal_id && $user{calendars
}{$user_cal_id}{edit_events
} eq "1" &&
467 $user{password
} eq crypt($q->param('cal_password'), $options{salt
})) {
468 $logged_in_as_current_cal_user = 1;
471 last if ($logged_in_as_current_cal_user == 1);
473 last if ($logged_in_as_current_cal_user == 1);
477 $logged_in_as_current_cal_user = 0 if (!$options{users
}) ;
479 #$debug_info .= "init_session results: $results\n";
480 #$debug_info .= "logged-in: ".$session->param("~logged-in")."\n";
481 #$debug_info .= "session id: ".$session->id."\n";
482 #$debug_info .= "profile user_id: ".$profile->{calendar_permissions}->{$current_cal_id}."\n";
484 #$debug_info .= "options{sessions}: $options{sessions}\n";
485 #$debug_info .= "logged_in_as_root: $logged_in_as_root\n";
486 #$debug_info .= "logged_in_as_current_cal_user: $logged_in_as_current_cal_user\n";
487 #$debug_info .= "logged_in_as_current_cal_admin: $logged_in_as_current_cal_admin\n";
488 #$debug_info .= "current_calendar{password}: $current_calendar{password}\n";
489 #$debug_info .= ($profile->{calendar_permissions}->{$current_cal_id}->{admin})."\n";
493 if ($current_calendar{custom_stylesheet
} ne "") {
494 $css_path = "http://$current_calendar{custom_stylesheet}";
497 # if this is a custom calendar request, shoehorn the request parameters in
498 if ($q->param('custom_calendar') eq "1") {
499 $current_cal_id = $q->param('custom_calendar_calendar') + 0;
500 @custom_calendar_backgound_calendars = $q->param('custom_calendar_background_calendars');
502 foreach $local_background_calendar (keys %{$calendars{$current_cal_id}{local_background_calendars
}}) {
503 delete $calendars{$current_cal_id}{local_background_calendars
}{$local_background_calendar};}
505 foreach $local_background_calendar (@custom_calendar_backgound_calendars) {
506 $calendars{$current_cal_id}{local_background_calendars
}{$local_background_calendar} = 1;}
508 %current_calendar = %{$calendars{$current_cal_id}};
514 # make sure we can select the current calendar
515 #$current_calendar{selectable_calendars}{$current_cal_id} = 1;
518 # set info window height & width
519 $current_calendar{info_window_size
} ="400x400" if ($current_calendar{info_window_size
} eq ""); # default
520 my ($info_window_width, $info_window_height) = split("x", $current_calendar{info_window_size
});
523 # rotate weekday_sequence by the offset defined in the week start day.
524 for ($l1=0;$l1 < $current_calendar{week_start_day
};$l1++) {
525 push @weekday_sequence, (shift @weekday_sequence);}
529 # load background_colors
530 my @temp_lines = split ("\n", $event_background_colors);
532 foreach $temp_line (@temp_lines) {
533 next if ($temp_line !~ /\w/); # skip any blank lines
535 $temp_line =~ s/^\s+//;
536 my ($hex_color, $hex_color_title) = split (/,*\s+/, $temp_line, 2);
537 $hex_color_title = " " if ($hex_color_title eq "");
539 push @event_bgcolors, {color
=> $hex_color, title
=> $hex_color_title};
543 #evaluate browser type and version
544 $_ = $ENV{HTTP_USER_AGENT
};
547 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;
548 if (($browser_version<5) || (/Netscape/)) {$browser_type = "Netscape";} }
549 if (/\)[^0-9.]+[0-9]*[\/\
]([0-9.]+)/) {$browser_version=$1;}
550 } elsif (/(\w+)\/([0-9\
.]+)/) {$browser_type = $1; $browser_version = $2}
552 #evaluate, transform, tweak, adjust, modify input values
553 #$debug_info .= "browser type: $browser_type<br/>";
557 #if no month is selected, use the current month
558 if ($cal_start_month eq "" && $q->param('cal_start_month') eq "") {
559 $cal_start_month = $rightnow_month;
560 #$cal_start_month = 2;
563 #if the input year is out of range use the current year
564 if (($cal_start_year+0) < 1902 || ($cal_start_year+0)> 2037) {
565 $cal_start_year = $rightnow_year;
568 $cal_num_months = $current_calendar{default_number_of_months
} if ($cal_num_months < 1);
569 $cal_num_months = $current_calendar{default_number_of_months
} if ($cal_num_months > $current_calendar{max_number_of_months
});
570 $cal_num_months = 1 if ($cal_num_months > $current_calendar{max_number_of_months
});
571 $cal_num_months = 1 if ($cal_num_months == 0);
574 #calculate calendar end month and year
575 $cal_end_month = $cal_start_month;
576 $cal_end_year = $cal_start_year;
577 for ($l1=1;$l1<$cal_num_months;$l1++) {
579 if ($cal_end_month == 12) {
585 #check to make sure num_months+cal_start_date doesn't go out of bounds
586 if ($cal_end_year < 1902 || $cal_end_year> 2037) {
587 $cal_end_year = $cal_start_year;
588 $cal_end_month = $cal_start_month;
592 # time window for loading events
594 my $cal_start_timestamp = timegm
(0,0,0,1,$cal_start_month,$cal_start_year) - 2592000;
595 my $cal_end_timestamp = timegm
(0,0,0,1,$cal_end_month,$cal_end_year) + 5184000;
596 if ($q->param('cal_start_timestamp') ne "" && $q->param('cal_start_timestamp') !~ /\D/) {
597 $cal_start_timestamp = $q->param('cal_start_timestamp');}
598 if ($q->param('cal_end_timestamp') ne "" && $q->param('cal_end_timestamp') !~ /\D/) {
599 $cal_end_timestamp = $q->param('cal_end_timestamp');}
602 #$debug_info .="start: $cal_start_timestamp\nend: $cal_end_timestamp\nrightnow: $rightnow\n";
604 # load event data, for main calendar and its background calendars
605 my @temp_calendars = ($current_cal_id);
606 foreach $local_background_calendar (keys %{$current_calendar{local_background_calendars
}}) {
607 push @temp_calendars, $local_background_calendar;
610 my $initial_load_events = 1;
611 $initial_load_events = 0 if ($q->param('get_upcoming_events') eq "1");
613 &load_events
($cal_start_timestamp, $cal_end_timestamp, \
@temp_calendars) if ($initial_load_events == 1);
617 if ($current_event_id ne "") {
618 &load_event
($current_event_id);
622 # load events from remote background calendars
624 if (scalar keys %{$current_calendar{remote_background_calendars
}} > 0) {
625 $remote_calendars_status="";
626 my $temp = scalar keys %{$current_calendar{remote_background_calendars
}};
627 foreach $remote_calendar_id (keys %{$current_calendar{remote_background_calendars
}}) {
628 # pull in remote calendar name
629 my $remote_calendar_url = $current_calendar{remote_background_calendars
}{$remote_calendar_id}{url
};
630 $remote_calendar_complete_url = $remote_calendar_url;
631 #$debug_info .= "remote calendar: $remote_calendar_complete_url\n";
633 $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";
634 #$debug_info .= "remote calendar url: $remote_calendar_complete_url\n";
636 my $xml_results = &get_remote_file
($remote_calendar_complete_url);
638 if ($xml_results =~ /<error>/) {
639 $xml_results =~ s/</</g;
640 $xml_results =~ s/>/>/g;
642 #$debug_info .= "Error fetching remote calendar: $xml_results\n";
644 my %remote_calendar = %{&xml2hash
($xml_results)};
646 my $remote_cal_title = $remote_calendar{'xml'}{calendar
}{title
};
647 my $remote_cal_gmtime_diff = $remote_calendar{'xml'}{calendar
}{gmtime_diff
};
649 #$debug_info .= "remote_cal_gmtime_diff: $remote_cal_gmtime_diff\n";
650 #my $temp = $xml_results;
653 #$debug_info .= "xml results: $temp\n";
655 &load_remote_events
($xml_results, $remote_calendar_id, $remote_cal_gmtime_diff);
660 # this should be done after all $current_cal_id is calculated and events are loaded.
661 &normalize_timezone
();
662 &normalize_timezone_pending_events
();
667 # calculate previous X months range.
668 my $previous_cal_start_month = $cal_start_month - $cal_num_months;
669 my $previous_cal_start_year = $cal_start_year;
670 if ($previous_cal_start_month < 0) {
671 $previous_cal_start_year = $cal_start_year - 1 - int(abs($cal_num_months - $cal_start_month) / 12);
672 $previous_cal_start_month = 12 - abs($previous_cal_start_month) % 12;
675 # for the case when num_months = 12 and start_month=0
676 if ($previous_cal_start_month == 12) {
677 $previous_cal_start_month=0;
678 $previous_cal_start_year++;
682 # singular or plural?
683 if ($cal_num_months > 1) {
684 $prev_string = $lang{previous_months
};
685 $prev_string =~ s/###num###/$cal_num_months/;
687 $prev_string = $lang{previous_month
};
691 # calculate next X months range.
692 my $next_cal_start_month = $cal_start_month + $cal_num_months;
693 my $next_cal_start_year = $cal_start_year;
694 if ($next_cal_start_month > 11) {
695 $next_cal_start_year = $cal_start_year + int(abs($cal_num_months + $cal_start_month) / 12);
696 $next_cal_start_month = abs($cal_start_month + $cal_num_months) % 12;
700 # singular or plural?
701 if ($cal_num_months > 1) {
702 $next_string = $lang{next_months
};
703 $next_string =~ s/###num###/$cal_num_months/;
705 $next_string = $lang{next_month
};
711 if ($q->param('diagnostic_mode') eq "1") {
712 my $diagnostic_results = &diagnostic_info
;
716 Cache-control: no-cache,no-store,private
717 Content-Type: text/html; charset=$lang{charset}\n
718 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
722 <title>Diagnostic mode</title>
724 <body style="font-family: arial;">
727 <h2>Plans Diagnostic information</h2>
732 <b
>Debug info
:</b><br/>
733 <div style
="color=:#0000ff;">
746 if ($q->param('detect_remote_calendars') eq "1") {
747 &detect_remote_calendars
();
751 if ($q->param('remote_calendar_request') eq "1") {
752 &remote_calendar_request
();
756 if ($q->param('add_edit_user') eq "1") {
760 if ($q->param('add_new_ical') eq "1") {
765 if ($q->param('js_login') eq "1") {
770 if ($q->param('manage_pending_events') eq "1") {
771 &manage_pending_events
();
775 if ($q->param('export_calendar') eq "1") {
776 if ($q->param('export_type') eq "ascii_text") {
777 &ascii_text_cal
($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year);
779 } elsif ($q->param('export_type') eq "csv_file") {
780 &csv_file
($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year);
782 } elsif ($q->param('export_type') eq "csv_file_palm") {
783 &csv_file_palm
($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year);
785 } elsif ($q->param('export_type') eq "vcalendar") {
786 &vcalendar_export_cal
($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year);
788 } elsif ($q->param('export_type') eq "icalendar") {
790 my $html_output =<<p1;
791 Cache-control: no-cache,no-store,private
792 Content-disposition: filename="events.ics"
793 Content-Type: text/calendar; charset=$lang{charset}
797 $html_output .= &icalendar_export_cal($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year);
803 if ($q->param('export_event') eq "1") {
804 if ($q->param('export_type') eq "ascii_text") {
807 } elsif ($q->param('export_type') eq "icalendar") {
808 &icalendar_export_event();
810 } elsif ($q->param('export_type') eq "vcalendar") {
811 &vcalendar_export_event();
814 } elsif ($q->param('get_upcoming_events') eq "1") {
815 &get_upcoming_events();
817 } elsif ($api_command ne "") {
818 if ($api_command eq "delete_event") {
819 &api_add_delete_events();
822 } elsif ($q->param('view_event') eq "1") {
826 } elsif ($q->param('view_events') eq "1") {
830 } elsif ($q->param('view_pending_event') eq "1") {
832 my %pending_event = %{$new_events{$pending_event_id}};
833 &view_pending_event(\%pending_event);
835 } elsif ($q->param('email_reminder') eq "1") {
837 &email_reminder_prompt();
839 } elsif ($q->param('email_reminder_confirm') eq "1") {
841 &email_reminder_confirm();
843 } elsif ($special_action eq "preview_event") {
847 } elsif ($special_action eq "preview_date") {
851 } elsif ($q->param('validate_event') eq "1") {
862 # ssi-style includes in the template
863 if ($local_template_file) {
864 my $new_html = $template_html;
866 $template_html =~ s/###include\s+(.+)###/&load_file($1)/ge;
868 #while ($new_html =~ s/###include\s+(.+)###//g)
871 if (-e $include_file) {
872 open (FH, "$include_file") || ($debug_info .="<br/>unable to open include file $include_file for reading<br/>");
874 my @include_lines=<FH>;
876 $include_html = join "", @include_lines;
878 $template_html =~ s/###include\s+(.+)###/$include_html/;
885 if($options{choose_themes}) {
886 my $theme_file="choose_theme.html";
888 if (-e $theme_file) {
889 open (FH, "$theme_file") || ($debug_info .="<br/>unable to open theme file $theme_file for reading<br/>");
891 my @theme_lines=<FH>;
893 $theme_html = join "", @theme_lines;
895 $template_html =~ s/###choose theme###/$theme_html/;
897 $template_html =~ s/###choose theme###//;
903 my $view_cookie = &xml_store($cal_start_month, "cal_start_month");
904 $view_cookie .= &xml_store($cal_start_year, "cal_start_year");
905 $view_cookie .= &xml_store($cal_num_months, "cal_num_months");
906 $view_cookie .= &xml_store($current_cal_id, "cal_id");
907 $view_cookie .= &xml_store($display_type, "display_type");
909 $cookie_text .= "Set-Cookie: plans_view=$view_cookie; path=$cookie_path;\n";
910 $cookie_header_text = $cookie_text;
912 #$debug_info .= "cookie: $cookie_header_text\n";
915 Cache
-control
: no-cache
,no-store
,private
916 Content
-Type
: text
/html
; charset
=$lang{charset
}
923 $html_output =~ s/###current calendar title###/$current_calendar{title}/g;
924 $html_output =~ s/###current calendar details###/$current_calendar{details}/g;
925 $html_output =~ s/###calendar\{(\d+)\}\{(.+?)\}###/$calendars{$1}{$2} if ($2 ne 'admin_password')/ge;
926 $html_output =~ s/###event\{(\d+)\}\{(.+?)\}###/$events{$1}{$2}/ge;
929 <script type="text/javascript" src="$theme_url/plans.js"></script>
930 <script type="text/javascript" src="$theme_url/plans_lang.js"></script>
931 <script type="text/javascript" ><!--
933 //###common javascript###
934 //###page-specific javascript###
939 $html_output =~ s/###javascript stuff###/$insert_text/;
941 # sneak in the color select javascript before all other javascript.
943 <script type
="text/javascript" src
="$theme_url/lpd.js"></script
>
944 <script type
="text/javascript" src
="$theme_url/color_select.js"></script
>
946 $html_output =~ s/(<script)/$temp$1/;
957 sub display_default
{
958 my $common_javascript = "";
959 my $page_javascript = "";
960 my $browser_javascript = "";
963 $html_output =~ s/###css file###/$css_path/g;
966 $menu_tabs[0] = {status
=> "inactive",
967 html
=> "<a href=\"$script_url/$name?active_tab=0\">$lang{tab_text}[0]</a>"};
968 $menu_tabs[1] = {status
=> "inactive",
969 html
=> "<a href=\"$script_url/$name?active_tab=1\">$lang{tab_text}[1]</a>"};
970 $menu_tabs[2] = {status
=> "inactive",
971 html
=> "<a href=\"$script_url/$name?active_tab=2\">$lang{tab_text}[2]</a>"};
973 $menu_tabs[$active_tab]{status
} ="active";
975 $menu_tabs[2]{html
} = "<a href=\"$script_url/$name?active_tab=2\">$lang{tab_text}[2]</a>";
979 <div style="padding:0px;margin:0px;margin-left:20px;white-space:nowrap;">
983 if ($browser_type eq "IE") {
984 $tab_vert_offset=4;} else {
987 #lay out the actual menu tabs
988 for ($l1=0;$l1<scalar @{$lang{tab_text}};$l1++) {
989 if (&contains (\@disabled_tabs, $l1)) {
991 $menu_tab = $menu_tabs[$l1];
996 if ($$menu_tab{status} eq "active") {
997 $style="top:".($tab_vert_offset-3)."px;padding-top:5px;padding-bottom:5px;margin-top:0;height:2em;";
999 $style="top:".($tab_vert_offset-3)."px;padding-top:3px;padding-bottom:4px;margin-top:1px;height:2em;";
1001 $insert_text .=<<p1;
1002 <span
class="$$menu_tab{status}_tab" style
="position:relative;border-bottom-width:0px;padding-top:5px;margin-bottom:0;margin-left:5px;margin-right:2px;white-space:nowrap;text-align:center;$style">  
;  
;  
; $$menu_tab{html
}  
;  
;  
; </span
>
1005 $noinsert_text .=<<p1;
1006 <span class="$$menu_tab{status}_tab" style="position:relative;$style">$$menu_tab{html} </span>
1010 $insert_text .=<<p1;
1016 if ($q->param('custom_calendar') == 1) {
1017 $html_output =~ s/###tab menu stuff###//g;
1019 $html_output =~ s/###tab menu stuff###/$insert_text/g;
1025 #invisible html for context menu
1026 $insert_text .=<<p1;
1027 <div id="contextmenu" class="contextmenu" style="visibility:hidden;">
1032 $insert_text .=<<p1;
1035 # finished displaying tab menus, now display the appropriate stuff for the selected tab
1037 if ($active_tab eq "0") { # tab 1 = main calendar view
1040 $prev_month_link .=<<p1;
1041 <a class="prev_next" href="$script_url/$name?cal_id=$current_cal_id&cal_start_month=$previous_cal_start_month&cal_start_year=$previous_cal_start_year">$prev_string</a>
1043 $next_month_link .=<<p1;
1044 <a
class="prev_next" href
="$script_url/$name?cal_id=$current_cal_id&cal_start_month=$next_cal_start_month&cal_start_year=$next_cal_start_year">$next_string</a
>
1048 my $cal_controls_text =<<p1;
1049 <div class="calendar_controls">
1050 <form name="tab0_form" action="$script_url/$name" method="get">
1052 <div style="float:right;margin:5px;padding:2px;vertical-align:middle;">
1053 <input id="controls_submit_button" type="submit" value="$lang{controls_change}"/>
1056 <div style="margin:5px;padding:2px;text-align:right;float:right;">
1057 $lang{controls_start_month}:
1058 <select name="cal_start_month" onChange="blink('controls_submit_button', 3, 0);">
1060 #list each month in the year
1062 foreach $possible_month (@months) {
1063 if ($cal_start_month eq $month_index) {
1064 $cal_controls_text .=<<p1;
1065 <option value
="$month_index" selected
>$possible_month
1068 $cal_controls_text .=<<p1;
1069 <option value="$month_index">$possible_month
1074 $cal_controls_text .=<<p1;
1076 <input name
="cal_start_year" value
= "$cal_start_year" size
=4 onChange
="blink('controls_submit_button', 3, 0);"/><br/>
1077 $lang{controls_num_months
}
1078 <input name
="cal_num_months" value
= "$cal_num_months" size
=3 onChange
="blink('controls_submit_button', 3, 0);"/>
1081 $cal_controls_text .=<<p1;
1082 <div class="calendar_select" style="margin:5px;padding:2px;float:left;text-align:left;">
1083 $lang{controls_calendar_label}<br/>
1086 my $num_selectable_calendars = scalar keys %{$current_calendar{selectable_calendars}};
1088 my @selectable_calendars;
1089 if ($options{all_calendars_selectable}) {
1090 @selectable_calendars = keys %calendars;
1092 @selectable_calendars = keys %{$current_calendar{selectable_calendars}};
1093 unshift @selectable_calendars, $current_cal_id if (!&contains(\@selectable_calendars, $current_cal_id));
1097 if (scalar @selectable_calendars > 1) {
1098 $cal_controls_text .=<<p1;
1099 <select id
="cal_id" name
="cal_id" onChange
="blink('controls_submit_button', 3, 0);">
1103 #list each calendar for the user to select
1104 my %explicit_calendar_order;
1105 if ($options{calendar_select_order
} ne "alpha" && $options{calendar_select_order
} ne "") {
1106 my @cal_order_ids = split(',',$options{calendar_select_order
});
1107 my $cal_order_index = 0;
1109 foreach $selectable_calendar_id (@selectable_calendars) {
1110 $explicit_calendar_order{"$selectable_calendar_id"} = 9999999;
1114 foreach $cal_order_id (@cal_order_ids) {
1115 next if ($cal_order_id eq "");
1117 $explicit_calendar_order{"$cal_order_id"} = $cal_order_index;
1122 foreach $selectable_calendar_id (sort {
1123 if ($options{calendar_select_order
} eq "alpha") {
1124 return lc $calendars{$a}{title
} cmp lc $calendars{$b}{title
};
1125 } elsif ($options{calendar_select_order
} ne "") {
1126 return $explicit_calendar_order{"$a"} <=> $explicit_calendar_order{"$b"} || lc $calendars{$a}{title
} cmp lc $calendars{$b}{title
};} else {
1129 } @selectable_calendars) {
1131 $selected =" selected" if ($selectable_calendar_id eq $current_calendar{id
});
1132 $selectable_calendar_id=~ s/\D//g;
1134 $cal_controls_text .=<<p1;
1135 <option value = "$selectable_calendar_id"$selected>$calendars{$selectable_calendar_id}{title}
1139 $cal_controls_text .=<<p1;
1143 $cal_controls_text .=<<p1;
1144 <span style="font-weight:bold;">$current_calendar{title}</span>
1145 <input type="hidden" name="cal_id" value="$current_calendar{id}"/>
1148 $cal_controls_text .=<<p1;
1153 $cal_controls_text .=<<p1;
1154 <div style="margin:5px;padding:2px;float:left;text-align:left;">
1155 $lang{controls_display_label}<br/>
1156 <select name="display_type" onChange="blink('controls_submit_button', 3, 0);">
1158 #foreach $possible_display_type (@{$options{display_types}})
1159 for (my $l1=0;$l1<scalar @{$options{display_types}};$l1++) {
1160 if ($options{display_types}[$l1] ne "1") {
1164 if ($l1 eq $display_type) {
1165 $selected = "selected";}
1167 $cal_controls_text .=<<p1;
1168 <option value
="$l1" $selected>$lang{controls_display_type
}[$l1]
1171 $cal_controls_text .=<<p1;
1178 $cal_controls_text .=<<p1;
1179 <br style
="clear:both;"/>
1183 if ($q->param('custom_calendar') == 1) {
1184 $html_output =~ s/###calendar controls###//g;
1186 $html_output =~ s/###calendar controls###/$cal_controls_text/g;
1189 if ( !$logged_in && $options{force_login
} ) {
1190 $insert_text .= &forced_login
();
1192 $insert_text .= &do_calendar_list_view
();
1197 $cal_month_start_date = timegm
(0,0,0,1,$cal_start_month,$cal_start_year);
1198 @cal_month_start_date_array = gmtime $cal_month_start_date;
1200 $events_start_timestamp = $cal_month_start_date - 604800; # +7 day margin
1201 $events_end_timestamp = &find_end_of_month
($cal_end_month, $cal_end_year) + 604800; # +7 day margin
1203 #now that we have selected the appropriate events, we can
1204 #generate the corresponding javascript and calendar view
1205 #and insert/add it to the html output.
1206 $page_javascript .= &calendar_view_javascript
($events_start_timestamp, $events_end_timestamp);
1208 #replace javascript placeholders with actual html/javascript code
1210 $html_output =~ s/###previous month link###/$prev_month_link/g;
1211 $html_output =~ s/###next month link###/$next_month_link/g;
1213 } elsif ($active_tab eq "1") { #the second tab is the add/edit events view
1214 $html_output =~ s/###calendar controls###//;
1216 if ( !$logged_in && $options{force_login
} ) {
1217 $insert_text .= &forced_login
();
1219 my $edit_event_id = "";
1220 $edit_event_id = $current_event_id if ($add_edit_event eq "edit");
1222 if ($q->param('add_event_button') eq "" && $q->param('del_event_button') eq "") { #add event main screen
1224 $add_edit_event = "add" if ($add_edit_event eq "");
1226 $insert_text .=<<p1;
1227 <form id="add_event_form" name="add_event_form" action="$script_url/$name" method="POST" onsubmit="return validate_event();">
1228 <input type="hidden" name="active_tab" value="1"/>
1229 <input type="hidden" name="special_action" value=""/>
1230 <input type="hidden" name="add_edit_event" value="$add_edit_event"/>
1231 <input type="hidden" name="evt_id" value="$edit_event_id"/>
1233 $insert_text .= &add_edit_events_interface();
1234 $insert_text .=<<p1;
1238 my %results = %{&add_edit_events
()};
1239 my $results_html = "";
1241 foreach $results_message (@
{$results{messages
}}) {
1242 $results_message =~ s/\[warning\](.*)/<span class="warning">$1<\/span
>/i
;
1243 $results_message =~ s/\[error\](.*)/<span class="error">$1<\/span
>/i
;
1244 $results_message =~ s/\[status\](.*)/<span class="status">$1<\/span
>/i
;
1245 $results_html .= "<li>$results_message</li>\n";
1248 $insert_text .= "<div style=\"text-align:left;\"><ul style=\"font-size:small;\">$results_html</ul>$results{text}</div>";
1252 #generate javascript for add/edit events page
1253 $page_javascript .= &add_edit_events_javascript
();
1255 } elsif ($active_tab eq "2") { #the third tab is for calendar information
1257 $html_output =~ s/###calendar controls###//;
1259 if ( !$logged_in && $options{force_login
} ) {
1260 $insert_text .= &forced_login
();
1262 if ($add_edit_cal_action eq "") { # calendar management view
1263 $num_new_calendars = scalar keys %new_calendars;
1265 if ($num_new_calendars == 0) {
1266 $new_calendars_info = $lang{tab2_no_new_calendars
};
1268 $new_calendars_info = $lang{tab2_some_new_calendars
};
1269 $new_calendars_info =~ s/###num###/$num_new_calendars/;
1272 $insert_text .=<<p1;
1274 <div class="info_box" style="margin-top:20px;float:left;padding-left:20px;padding-right:20px;text-align:left;">
1276 <form name="view_cal_form" action="$script_url/$name" method="GET">
1277 <input type="hidden" name = "active_tab" value="2"/>
1278 <input type="hidden" name = "add_edit_cal_action" value="edit"/>
1280 <select name="cal_id" id="cal_id">
1282 foreach $cal_id (sort {$a <=> $b} keys %calendars) {
1284 if ($cal_id eq $current_cal_id) {
1285 #$debug_info .= "$cal_id<br/>";
1286 $selected=" selected";
1288 $insert_text .=<<p1;
1289 <option value
= "$cal_id"$selected>$calendars{$cal_id}{title
}
1293 $insert_text .=<<p1;
1297 $writable{calendars_file} and $insert_text .=<<p1;
1298 <a href
="javascript:document.view_cal_form.submit();">$lang{tab2_edit_delete
}</a
>
1300 if ($writable{pending_actions_file
}) {
1301 $insert_text .=<<p1;
1304 <div class="info_box" style="float:left;clear:left;width:90%;margin-top:20px;padding-left:20px;padding-right:20px;text-align:left;">
1307 <li><a href="$script_url/$name?active_tab=2&add_edit_cal_action=add">$lang{add_new_calendar}</a></li>
1310 if ($options{ical_import} eq "1") {
1311 $insert_text .=<<p1;
1312 <li
><a id
="add_new_ical_link" href
="javascript:add_new_ical();">$lang{add_new_ical_calendar
}</a
>
1313 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('add_new_ical','$lang{add_new_ical_calendar}')">$lang{help_on_this
}</a></span
>
1321 $insert_text .=<<p1;
1322 <li><a href="$script_url/$name?active_tab=2&add_edit_cal_action=view_pending">$lang{tab2_view_new_calendars}</a> $new_calendars_info</li>
1327 <br style="clear:both;"/>
1332 } elsif($add_edit_cal_action eq "add" || $add_edit_cal_action eq "edit") { #add/edit calendars
1334 $insert_text .=<<p1;
1335 <form id
="update_cal_form" name
="update_cal_form" action
="$script_url/$name" method
="POST" onsubmit
="return validate_calendar();">
1336 <input type
="hidden" name
="cal_id" value
="$current_cal_id"/>
1338 $insert_text .= &add_edit_calendars
();
1339 $insert_text .=<<p1;
1342 } elsif ($add_edit_cal_action eq "view_pending") { #view/approve/reject new pending calendars
1344 $insert_text .= &view_pending_calendars();
1348 #generate javascript for calendar info page
1349 $page_javascript.= &add_edit_calendars_javascript();
1354 #done with main active tab stuff (the stuff that's different depending
1355 #on which tab is active. The following stuff is the same regardless
1356 #of which tab is active.
1358 $html_output =~ s/###calendar area###/$insert_text/g;
1359 $html_output =~ s/###version###/$plans_version/g;
1362 my $add_event_to_current_cal_text =<<p1;
1363 <a target
= "_self" href
="$script_url/$name?active_tab=1&cal_id=$current_cal_id">$lang{add_event_to_this_calendar
}</a
>
1365 chomp $add_event_to_current_cal_text;
1367 my $current_calendar_options_text =<<p1;
1368 <a target="_self" href="$script_url/$name?active_tab=2&cal_id=$current_cal_id&add_edit_cal_action=edit">$lang{edit_calendar_options}</a>
1370 chomp $current_calendar_options_text;
1372 my $current_calendar_subscribe_text =<<p1;
1373 <a target
="_new" href
="$ical_export_url/plans_calendar_$current_calendar{id}.ics">$lang{subscribe_to_this_calendar
}</a
>
1375 chomp $current_calendar_subscribe_text;
1378 if ($active_tab eq "0") {
1379 $html_output =~ s/###add event to current calendar link###/$add_event_to_current_cal_text/;
1380 $html_output =~ s/###edit calendar options link###/$current_calendar_options_text/;
1382 if ( !$logged_in && $options{force_login
} ) {
1383 $html_output =~ s/###subscribe calendar link###//g;
1384 $html_output =~ s/###export calendar link###//;
1385 $html_output =~ s/###custom calendar link###//;
1387 $html_output =~ s/###subscribe calendar link###/$current_calendar_subscribe_text/g;
1388 my $temp = &export_calendar_link
();
1389 $html_output =~ s/###export calendar link###/$temp/;
1391 my $custom_calendar_link =<<p1;
1392 <a href="javascript:custom_calendar()">$lang{make_custom_calendar}</a>
1394 chomp $custom_calendar_link;
1395 $html_output =~ s/###custom calendar link###/$custom_calendar_link/;
1397 #$debug_info .= "custom calendar link: $custom_calendar_link\n";
1400 $html_output =~ s/###subscribe calendar link###//g;
1401 $html_output =~ s/###add event to current calendar link###//;
1402 $html_output =~ s/###edit calendar options link###//;
1403 $html_output =~ s/###custom calendar link###//;
1404 $html_output =~ s/###export calendar link###//;
1408 # pending event stuff
1409 my $plans_messages_style = ($messages eq "")? "": " style=\"display:block;\"";
1410 my $messages_text = "<div id=\"plans_messages\"$plans_messages_style>$messages</div>";
1411 $html_output =~ s/###messages###/$messages_text/;
1413 my $logged_in_text = &generate_logged_in_stuff();
1415 if ($logged_in_text ne "") {
1416 $logged_in_text = <<p1;
1417 <div id
="logged_in_stuff">
1423 $html_output =~ s/###logged-in stuff###/$logged_in_text/;
1426 $common_javascript .= &generate_pending_events_javascript
() if (&pending_events_visible
);
1427 $common_javascript .= &common_javascript
();
1430 #replace javascript placeholders with actual html/javascript code
1431 $html_output =~ s/###page-specific javascript###/\n$page_javascript/;
1432 $html_output =~ s/###common javascript###/\n$common_javascript/;
1435 $debug_info = "$error_info$debug_info";
1437 if ($debug_info =~ /\S/) {
1438 $debug_info =~ s/\n/<br\/>\n/g
;
1440 <div style="width:100%;padding:10px;margin:10px;border:solid 1px #000;background-color:#fff;">
1441 <b>Error, Warnings, & Debug Messages:</b><br/>
1446 $html_output =~ s/###debug stuff###/$debug_info/g;
1447 $html_output =~ s/###cookie_text###/$cookie_header_text/;
1451 } #********************end default view code*****************************
1453 sub add_edit_calendars {
1454 my $temp="<link rel=\"stylesheet\" href=\"$theme_url/color_select.css\" type=\"text/css\">";
1455 $html_output =~ s/<head>/<head>\n$temp\n/;
1457 my $return_text = "";
1459 if ($q->param('update_cal_button') eq "" && $q->param('del_cal_button') eq "") { #add/edit calendar main screen
1461 $add_edit_string = $lang{add_new_calendar};
1462 #generate html for blank (default) calendar preview window
1464 $cal_details = $new_calendar_default_details;
1465 $shared_cal_select_size = scalar keys %calendars;
1466 $cal_link="http://";
1468 if ($add_edit_cal_action ne "edit") {
1469 %current_calendar = %default_cal;}
1471 $add_edit_string = "$lang{edit_calendar} ($current_calendar{title})" if ($add_edit_cal_action eq "edit");
1474 $checked{list_background_calendars_together} = " checked" if ($current_calendar{list_background_calendars_together} eq "yes");
1475 $checked{background_events_display_style1} = " checked" if ($current_calendar{background_events_display_style} eq "normal");
1476 $checked{background_events_display_style2} = " checked" if ($current_calendar{background_events_display_style} eq "single_color");
1477 $checked{background_events_display_style3} = " checked" if ($current_calendar{background_events_display_style} eq "faded");
1479 $current_calendar{custom_stylesheet} = "http://$current_calendar{custom_stylesheet}";
1480 $current_calendar{custom_template} = "http://$current_calendar{custom_template}";
1482 $cal_details =~ s/</</g;
1483 $cal_details =~ s/>/>/g;
1485 $return_text .=<<p1;
1487 <input type
="hidden" name
="active_tab" value
="2"/>
1488 <input type
="hidden" name
="add_edit_cal_action" value
="$add_edit_cal_action"/>
1489 <input type
="hidden" name
="new_remote_calandars_xml" value
=""/>
1491 <p
class="cal_title" style
="text-align:center;">
1495 <div
class="info_box" style
="text-align:center;margin-bottom:2em;float:left;">
1496 <span
class="optional_field">$lang{fields_text1
} <span
class="required_field">$lang{fields_text2
}</span> $lang{fields_text3}</span
>
1499 <div style
="width:90%;text-align:left;white-space:nowrap;clear:left;">
1500 <a id
="tab0" href
="javascript:tab_show(0)" class="info_box_tab active">$lang{add_edit_calendars_tab0
}</a
>
1501 <a id
="tab1" href
="javascript:tab_show(1)" class="info_box_tab">$lang{add_edit_calendars_tab1
}</a
>
1502 <a id
="tab2" href
="javascript:tab_show(2)" class="info_box_tab">$lang{add_edit_calendars_tab2
}</a
>
1503 <a id
="tab3" href
="javascript:tab_show(3)" class="info_box_tab">$lang{add_edit_calendars_tab3
}</a
>
1505 if ($options{users
} eq "1") {
1506 $return_text .=<<p1;
1507 <a id="tab4" href="javascript:tab_show(4)" class="info_box_tab">$lang{add_edit_calendars_tab4}</a>
1511 $return_text .=<<p1;
1514 <div id
="tab_area0" class="info_box" style
="width:100%;position:relative;z-index:101;padding-top:20px;">
1517 <div
class="leftcol" style
="">
1518 <label
class="required_field" for="cal_title">$lang{calendar_title
}</label
>
1520 <div
class="rightcol" style
="white-space:nowrap;">
1521 <input id
="cal_title" name
="cal_title" style
="width:50%;" value
= "$current_calendar{title}"/>
1522 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('title','$lang{calendar_title}')">$lang{help_on_this
}</a></span
>
1525 <div
class="leftcol" style
="">
1526 <label
class="optional_field" for="cal_link">$lang{calendar_link
}</label
>
1528 <div
class="rightcol" style
="white-space:nowrap;">
1529 <input id
="cal_link" name
="cal_link" style
="width:50%;" value
= "$current_calendar{link}"/>
1530 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('link','$lang{calendar_link}')">$lang{help_on_this
}</a></span
>
1533 <div
class="leftcol" style
="">
1534 <label
class="optional_field" for="cal_details">$lang{calendar_details
}</label
>
1536 <span
class="small_note" style
="vertical-align:top;" ><a href
="javascript:display_help('details','$lang{calendar_details}')">$lang{help_on_this
}</a> </span
>
1538 <div
class="rightcol" style
="white-space:nowrap;">
1539 <textarea name
="cal_details" id
="cal_details" rows
=10 cols
=0 style
="width:100%;">
1540 $current_calendar{details
}
1545 <div style
="clear:both;text-align:center;padding-top:20px;padding-bottom:20px;">
1546 <b
><a href
="javascript:preview_cal()">$lang{preview_calendar_details
}</a></b
>
1549 <br style
="clear:both;"/> 
;
1552 <div id
="tab_area1" class="info_box" style
="width:100%;display:none;position:relative;z-index:101;padding-top:20px;">
1553 <div style
="float:left;width:45%;text-align:left;">
1558 <div
class="lite_box">
1560 if (scalar (keys %calendars) > 1 || $add_edit_cal_action ne "edit") {
1561 $return_text .=<<p1;
1562 <label class="optional_field" style="float:left;" for="background_calendars">$lang{background_calendars3}
1563 <span class="small_note" ><a href="javascript:display_help('background_calendars','$lang{background_calendars3}')">$lang{help_on_this}</a></span>
1564 <br/><span class="small_note">$lang{background_calendars2}</span>
1566 <select multiple size=8 style="display:block;clear:left;" name="background_calendars" id="background_calendars">
1569 foreach $cal_id (sort {$a <=> $b} keys %calendars) {
1570 #don't display a choice for the calendar currently being edited
1571 if ($cal_id eq $current_calendar{id}) {
1574 #$debug_info .= "$current_calendar{title} local_background_calendars{$cal_id} = $current_calendar{local_background_calendars}{$cal_id}\n";
1577 if ($current_calendar{local_background_calendars}{$cal_id} eq "1") {
1578 $selected = " selected";}
1580 $return_text .=<<p1;
1581 <option value
= "$cal_id"$selected>$calendars{$cal_id}{title
}
1585 $return_text .=<<p1;
1590 $return_text .=<<p1;
1592 <div
class="lite_box">
1593 <label
class="optional_field" style
="float:left;" for="remote_background_calendars">$lang{remote_background_calendars1
}</label
>
1594  
;<span
class="small_note" ><a href
="javascript:display_help('remote_background_calendars','$lang{remote_background_calendars1}')">$lang{help_on_this
}</a></span
>
1596 my $remote_calendars_status = $lang{remote_background_calendars_none
};
1598 if (scalar keys %{$current_calendar{remote_background_calendars
}} > 0) {
1599 $remote_calendars_status="";
1600 my $temp = scalar keys %{$current_calendar{remote_background_calendars
}};
1601 if ($temp>4) {$temp=4};
1602 $temp = ($temp * 20)."px";
1604 $return_text .=<<p1;
1605 <div class="scroll_surround" style="height:$temp;white-space:nowrap;">
1607 foreach $remote_calendar_id (keys %{$current_calendar{remote_background_calendars}}) {
1608 # pull in remote calendar name
1609 my $remote_calendar_url = $current_calendar{remote_background_calendars}{$remote_calendar_id}{url};
1610 $remote_calendar_complete_url = $remote_calendar_url;
1612 $remote_calendar_complete_url .= "?remote_calendar_request=1&cal_id=$current_calendar{remote_background_calendars}{$remote_calendar_id}{remote_id}&cal_start_year=1971&cal_start_month=0&num_months=1";
1613 my $xml_results = &get_remote_file($remote_calendar_complete_url);
1615 if ($xml_results =~ /<error>/) {
1616 $xml_results =~ s/</</g;
1617 $xml_results =~ s/>/>/g;
1619 $debug_info .= "Error fetching remote calendar: $xml_results\n";
1621 my %remote_calendars = %{&xml2hash($xml_results)};
1623 my $remote_cal_title = $remote_calendars{'xml'}{calendar}{title};
1625 $return_text .=<<p1;
1626 <a target
="_blank" href
="$remote_calendar_url?cal_id=$current_calendar{remote_background_calendars}{$remote_calendar_id}{remote_id}" style
="font-size:small;">$remote_cal_title</a
>
1627  
; 
; 
; 
;
1628 (<input type
="checkbox" name
="delete_remote_calendar_$remote_calendar_id" style
="margin-top:0;margin-bottom:0;padding:0;vertical-align:bottom;" value
="y"/>$lang{get_remote_calendar3
})
1634 $return_text .=<<p1;
1638 $return_text .=<<p1;
1639 <div id
="remote_background_calendars_status" class="small_note">$remote_calendars_status</div
>
1640 <div
class="small_note"><a href
="javascript:get_remote_calendars();">$lang{get_remote_calendars
}</a></div
>
1642 $return_text .=<<p1;
1643 </div> <!-- end border div -->
1649 if ($current_calendar{allow_remote_calendar_requests} =~ /y/) {
1652 if ($current_calendar{remote_calendar_requests_require_password} =~ /y/) {
1654 $temp3="$current_calendar{remote_calendar_requests_password}";
1657 $return_text .=<<p1;
1658 <div
class="lite_box">
1659 <input type
="checkbox" id
="allow_remote_calendar_requests" name
="allow_remote_calendar_requests" value
="yes" $temp1 onclick
="update_remote_calendar_requests()"/>
1660 <label
class="optional_field" for="allow_remote_calendar_requests">$lang{allow_remote_calendar_requests
}</label
>
1661 <br
/><span class="small_note" ><a style="vertical-align:top;" href="javascript:display_help('allow_remote_calendar_requests','$lang{allow_remote_calendar_requests}')">$lang{help_on_this}</a></span
>
1663 <input type
="checkbox" id
="remote_calendar_requests_require_password" name
="remote_calendar_requests_require_password" value
="yes" $temp2 onclick
="update_remote_calendar_requests()"/>
1664 <label
class="optional_field" for="remote_calendar_requests_password">$lang{remote_calendar_requests_password1
}</label
>
1665 <input type
="password" id
="remote_calendar_requests_password" name
="remote_calendar_requests_password" value
="$temp3"/>
1666 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('remote_calendar_requests_password','$lang{remote_calendar_requests_password1}')">$lang{help_on_this
}</a></span
>
1675 </div
> <!-- end left column
-->
1676 <div style
="float:left;width:45%;text-align:left;">
1678 <div
class="lite_box">
1680 if ($options{all_calendars_selectable
} eq "1") {
1682 <label class="optional_field" style="float:left;">$lang{selectable_calendars1}</label>
1683 <br/><span class="small_note">($lang{selectable_calendars3})</span>
1684 <br style="clear:both;"/>
1688 if (scalar (keys %calendars) > 1 || $add_edit_cal_action ne "edit") {
1689 $return_text .=<<p1;
1690 <label
class="optional_field" style
="float:left;" for="selectable_calendars">$lang{selectable_calendars1
}
1691 <br
/><span class="small_note">$lang{selectable_calendars2}</span
>
1692 <span
class="small_note" style
="margin-left:1em;white-space:nowrap;"><a href
="javascript:display_help('selectable_calendars','$lang{selectable_calendars1}')">$lang{help_on_this
}</a></span
>
1694 <select multiple size
=8 style
="display:block;clear:left;" name
="selectable_calendars" id
="selectable_calendars">
1696 foreach $cal_id (sort {$a <=> $b} keys %calendars) {
1697 #don't display a choice for the calendar currently being edited
1698 next if ($cal_id eq $current_calendar{id
});
1702 if ($current_calendar{selectable_calendars
}{$cal_id} eq "1" || $add_edit_cal_action eq "add") {
1703 $selected = " selected";}
1705 $return_text .=<<p1;
1706 <option value = "$cal_id"$selected>$calendars{$cal_id}{title}
1709 $return_text .=<<p1;
1714 if ($options{new_calendars_automatically_selectable
} eq "1") {
1716 if ($current_calendar{new_calendars_automatically_selectable
} =~ /y/) {
1718 $return_text .=<<p1;
1719 <div style="margin-top:2ex;">
1720 <input type="checkbox" id="new_calendars_automatically_selectable" name="new_calendars_automatically_selectable" value="y" $temp/>
1721 <label class="optional_field" for="new_calendars_automatically_selectable">$lang{new_calendars_automatically_selectable}</label>
1722 <span class="small_note" ><a style="vertical-align:top;" href="javascript:display_help('new_calendars_automatically_selectable','$lang{new_calendars_automatically_selectable}')">$lang{help_on_this}</a></span>
1728 $return_text .=<<p1;
1731 <div
class="lite_box">
1732 <input type
="checkbox" id
="list_background_calendars_together" name
="list_background_calendars_together" value
= "yes" $checked{list_background_calendars_together
}/>
1733 <label
class="optional_field" for="list_background_calendars_together">$lang{bg_events_display_style8
}</label
>
1734 <br
/><span class="small_note" ><a style="vertical-align:top;" href="javascript:display_help('list_background_calendars_together','$lang{bg_events_display_style8}')">$lang{help_on_this}</a></span
>
1737 </div
> <!--end right column
-->
1739 <br style
="clear:both;"/> 
;
1745 <div id
="tab_area2" class="info_box" style
="width:100%;display:none;position:relative;z-index:101;padding-top:20px;">
1747 <div style
="float:left;width:45%;text-align:left;">
1748 <div
class="lite_box">
1750 <div
class="optional_field">
1751 $lang{cal_events_display_style1
}
1752 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('events_display_style','$lang{bg_events_display_style1}')">$lang{help_on_this
}</a></span
>
1755 <div style
="clear:left;margin-top:2em;">
1756 <label
class="optional_field" for="cal_events_display_style2">$lang{cal_events_display_style2
}</label
>
1757 <input name
="dummy" value
="" size
=1 style
="display:none;">
1758 <select id
="calendar_events_color" name
="calendar_events_color" value
= "" style
="margin-left:27px;width:10ex;" onChange
="update_cal_color_select_box();" onKeyPress
="if (event.keyCode == 13){return false;}">
1759 <option value
="" style
="background-color:#fff;">none
</option
>
1762 #update_bg_color_select_box()cs1.setrgb(this.value);
1764 foreach $temp (@event_bgcolors) {
1765 %possible_bgcolor = %{$temp};
1767 if ($possible_bgcolor{color
} eq "$current_calendar{calendar_events_color}") { #default
1769 $selected=" selected";
1771 my $description = "";
1772 $description = $possible_bgcolor{title
} if ($options{show_event_background_color_descriptions
});
1774 $return_text .=<<p1;
1775 <option value = "$possible_bgcolor{color}" style="background-color:$possible_bgcolor{color};"$selected>$description
1779 my $color_select_icon_style="visibility:hidden;";
1780 if ($custom_color == 1 && $current_calendar{calendar_events_color} ne "") {
1781 $color_select_icon_style="";
1782 $return_text .=<<p1;
1783 <option id
="custom_evt_color" value
= "$current_calendar{calendar_events_color}" selected style
="background-color:$current_calendar{calendar_events_color};">$lang{event_background_colorcustom
}
1786 $return_text .=<<p1;
1787 <option id="custom_evt_color" value="#ffffff" style="background-color:#fff;">$lang{event_background_colorcustom}
1791 $return_text .=<<p1;
1796 <span id
="color_select_icon1" class="color_select_icon" style
="$color_select_icon_style vertical-align:top;background-image:url($graphics_url/color_select_icon.gif);" onclick
="cs1.attach_to_element(this);cs1.toggle_color_select();"> 
; 
; 
; 
;</span
>
1800 </div
> <!-- end left column
-->
1802 <div style
="float:left;width:45%;text-align:left;">
1806 <div
class="lite_box">
1807 <div
class="optional_field">
1808 $lang{bg_events_display_style1
}
1809 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('background_events_display_style','$lang{bg_events_display_style1}')">$lang{help_on_this
}</a></span
>
1812 <div style
="clear:left;margin-top:1em;" onClick
="document.update_cal_form.background_events_display_style[0].checked=true;document.getElementById('bg_preview_e1').style.background = '#ffffcc';document.getElementById('bg_preview_e2').style.background = '#ccffff';document.update_cal_form.background_events_color.value = '';">
1813 <input type
="radio" id
="background_events_display_style1" name
="background_events_display_style" value
= "normal" $checked{background_events_display_style1
}/>
1814 <label
class="optional_field" for="background_events_display_style1">$lang{bg_events_display_style2
}</label
>
1817 <div style
="clear:left;margin-top:2em;" onClick
="document.update_cal_form.background_events_display_style[1].checked=true;">
1818 <input type
="radio" id
="background_events_display_style2" name
="background_events_display_style" value
= "single_color" $checked{background_events_display_style2
}/>
1819 <label
class="optional_field" for="background_events_display_style2">$lang{bg_events_display_style3
}</label
>
1820 <input id
="background_events_color" name
="background_events_color" value
= "$current_calendar{background_events_color}" style
="margin-left:27px;width:10ex;" onChange
="cs0.setrgb(this.value);" onKeyPress
="if (event.keyCode == 13){return false;}">
1821 <span id
="color_select_icon0" class="color_select_icon" style
="vertical-align:top;background-image:url($graphics_url/color_select_icon.gif);" onClick
="cs0.attach_to_element(this);cs0.toggle_color_select();"> 
; 
; 
; 
;</span
>
1824 <div style
="clear:left;margin-top:2em;" onClick
="document.update_cal_form.background_events_display_style[2].checked=true;fade_preview();document.update_cal_form.background_events_color.value = ''">
1825 <input type
="radio" id
="background_events_display_style3" name
="background_events_display_style" value
= "faded" $checked{background_events_display_style3
}/>
1826 <label
class="optional_field" for="background_events_display_style3">$lang{bg_events_display_style4
}</label
>
1827 <select id
="background_events_fade_factor" name
="background_events_fade_factor" onChange
="fade_preview();">
1829 for ($i=1;$i<8;$i++) {
1831 $selected = " selected" if ($i eq $current_calendar{background_events_fade_factor
});
1832 $return_text .=<<p1;
1833 <option value="$i"$selected>$i\l0\% faded
1837 $return_text .=<<p1;
1844 </div
> <!-- end right column
-->
1848 <div
class="lite_box" style
="clear:both;">
1849 <div style
="text-align:center;margin-top:20px;" class="optional_field">$lang{bg_events_display_style5
}</div
>
1850 <table
class="calendar" summary
="">
1851 <tr
><td
class="day" style
="border-bottom-width:0;">
1852 <span
class="this_month">1</span
>
1853 </td
><td
class="day" style
="border-bottom-width:0;">
1856 <tr
><td
class="day" style
="border-top-width:0;border-bottom-width:0;">
1857 <a id
="preview_e1" class="event_box" href
="" style
="display:block;background-color:#ffffcc;">
1858 $lang{bg_events_display_style6
}
1860 </td
><td
class="day" style
="border-top-width:0;border-bottom-width:0;">
1861 <a id
="bg_preview_e1" class="event_box background" style
="display:block;background-color:#ffffcc;" href
="">
1862 $lang{bg_events_display_style7
}
1864 <a id
="preview_e2" class="event_box" href
="" style
="display:block;background-color:#ccffcc;">
1865 $lang{bg_events_display_style6
}
1868 <tr
><td
class="day" colspan
=2 style
="border-top-width:0;">
1869 <a id
="bg_preview_e2" class="event_box background" style
="display:block;background-color:#ccffff;text-align:center;">
1870 $lang{bg_events_display_style7
}
1877 <div
class="lite_box" style
="clear:both;">
1880 <div
class="leftcol" style
="">
1881 <label
class="optional_field" for="custom_stylesheet">$lang{custom_stylesheet
}</label
>
1883 <div
class="rightcol" style
="white-space:nowrap;">
1884 <input id
="custom_stylesheet" name
="custom_stylesheet" style
="width:80%;" value
= "$current_calendar{custom_stylesheet}"/>
1885 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('custom_stylesheet','$lang{custom_stylesheet}')">$lang{help_on_this
}</a></span
>
1888 <div
class="leftcol" style
="margin-bottom:0;">
1889 <label
class="optional_field" for="custom_template">$lang{custom_template
}</label
>
1891 <div
class="rightcol" style
="white-space:nowrap;margin-bottom:0;">
1892 <input id
="custom_template" name
="custom_template" style
="width:80%;" value
= "$current_calendar{custom_template}"/>
1893 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('custom_template','$lang{custom_template}')">$lang{help_on_this
}</a></span
>
1895 <br style
="clear:both;"/> 
;
1900 <br style
="clear:both;"/> 
;
1902 </div
> <!-- end tab_area2
-->
1906 <div id
="tab_area3" class="info_box" style
="width:100%;display:none;position:relative;z-index:101;padding-top:20px;">
1908 <div
class="leftcol" style
="">
1909 <label
class="optional_field" for="default_number_of_months">$lang{default_number_of_months
}</label
>
1911 <div
class="rightcol" style
="white-space:nowrap;">
1912 <input id
="default_number_of_months" name
="default_number_of_months" value
= "$current_calendar{default_number_of_months}" style
="width:5ex;vertical-align:bottom;"/>
1913 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('default_number_of_months','$lang{default_number_of_months}')">$lang{help_on_this
}</a></span
>
1915 <br style
="line-height:0px;height:0px;clear:both;"/>
1917 <div
class="leftcol" style
="margin-bottom:5ex;">
1918 <label
class="optional_field" for="max_months">$lang{max_months
}</label
>
1920 <div
class="rightcol" style
="white-space:nowrap;">
1921 <input id
="max_months" name
="max_months" style
="width:5ex;" value
= "$current_calendar{max_number_of_months}"/>
1922 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('max_months','$lang{max_months}')">$lang{help_on_this
}</a></span
>
1924 <br style
="line-height:0px;height:0px;clear:both;"/>
1927 if ($options{force_single_timezone
} ne "1" || $current_calendar{id
} eq "0") {
1928 $return_text .=<<p1;
1929 <div class="leftcol" style="">
1930 <label class="optional_field" for="gmtime_diff">$lang{timezone_offset}</label>
1932 <div class="rightcol" style="white-space:nowrap;">
1933 <input id="gmtime_diff" name="gmtime_diff" style="width:5ex;" value = "$current_calendar{gmtime_diff}"/>
1934 <span class="small_note" ><a style="vertical-align:top;" href="javascript:display_help('gmtime_diff','$lang{timezone_offset}')">$lang{help_on_this}</a></span>
1936 <br style="line-height:0px;height:0px;clear:both;"/>
1940 $return_text .=<<p1;
1942 <div
class="leftcol" style
="">
1943 <label
class="optional_field" for="date_format">$lang{date_format
}</label
>
1945 <div
class="rightcol" style
="white-space:nowrap;">
1946 <input id
="date_format" name
="date_format" style
="width:10ex" value
= "$current_calendar{date_format}"/>
1947 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('date_format','$lang{date_format}')">$lang{help_on_this
}</a></span
>
1949 <br style
="line-height:0px;height:0px;clear:both;"/>
1951 <div
class="leftcol" style
="margin-bottom:5ex;">
1952 <label
class="optional_field" for="week_start_day">$lang{week_start_day
}</label
>
1954 <div
class="rightcol" style
="white-space:nowrap;">
1955 <select id
="week_start_day" name
="week_start_day">
1958 for ($i=0;$i<7;$i++) {
1960 $selected = " selected" if ($i eq $current_calendar{week_start_day
});
1961 $return_text .=<<p1;
1962 <option value="$i"$selected>$day_names[$i]
1966 $return_text .=<<p1;
1968 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('week_start_day','$lang{week_start_day}')">$lang{help_on_this
}</a></span
>
1970 <br style
="line-height:0px;height:0px;clear:both;"/>
1972 <div
class="leftcol" style
="margin-bottom:0;">
1973 <label
class="optional_field" for="event_change_email">$lang{event_change_email
}</label
>
1975 <div
class="rightcol" style
="white-space:nowrap;">
1976 <input id
="event_change_email" name
="event_change_email" value
="$current_calendar{event_change_email}"/>
1977 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('event_change_email','$lang{event_change_email}')">$lang{help_on_this
}</a></span
>
1980 <div
class="leftcol" style
="margin-bottom:0;">
1981 <label
class="optional_field" for="popup_window_size">$lang{popup_window_size1
}</label
>
1983 <div
class="rightcol" style
="white-space:nowrap;margin-bottom:0;">
1984 <input id
="popup_window_size" name
="popup_window_size" style
="width:12ex;" value
="$current_calendar{info_window_size}"/>
1985 <span
class="small_note" style
="vertical-align:top;">$lang{popup_window_size2
}</span
>
1986 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('popup_window_size','$lang{popup_window_size1}')">$lang{help_on_this
}</a></span
>
1989 <br style
="line-height:0px;height:0px;clear:both;"/>
1994 if ($options{users
} eq "1") {
1995 $return_text .=<<p1;
1996 <div id="tab_area4" class="info_box" style="width:100%;display:none;position:relative;z-index:101;padding-top:20px;text-align:left;">
1999 if ($add_edit_cal_action eq "edit") {
2001 $return_text .=<<p1;
2002 <div id
="select_users">
2006 #if (document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.selectedIndex].text == "custom")
2009 $return_text .=<<p1;
2010 <span id="add_user_link">
2011 <a href="javascript:add_edit_user();">$lang{add_user}</a>
2014 <span class="small_note" >
2015 <a href="javascript:display_help('add_user','$lang{add_user} ')">$lang{help_on_this}</a>
2021 $return_text .=<<p1;
2022 <div
class="optional_field">$lang{no_users_on_add
}</div
>
2025 $return_text .=<<p1;
2030 $return_text .=<<p1;
2031 <br style
="line-height:0px;height:0px;clear:both;"/>
2032 <br style
="line-height:0px;height:0px;clear:both;"/>
2035 <div
class="info_box" style
="width:100%;margin-top:40px;">
2036 <br style
="clear:both;"/>
2040 my $need_password = 1;
2041 $need_password = 0 if ($options{disable_passwords
} eq "1");
2042 $need_password = 0 if ($logged_in_as_root || $logged_in_as_current_cal_admin);
2044 if ($add_edit_cal_action eq "edit") {
2045 if ($need_password eq "1") {
2046 $return_text .=<<p1;
2047 <div class="leftcol" style="clear:both;white-space:nowrap;clear:both;margin-bottom:3ex;">
2048 <label class="required_field" for="cal_password">$lang{cal_password}</label>
2051 <div class="rightcol" style="white-space:nowrap;">
2052 <input type="password" name="cal_password" id="cal_password" size=12 />
2053 <span class="small_note" ><a style="vertical-align:top;" href="javascript:display_help('current_password','$lang{cal_password}')">$lang{help_on_this}</a></span>
2056 <div class="leftcol" style="white-space:nowrap;">
2057 <label class="optional_field" for="cal_password">$lang{change_password}</label>
2059 <span class="small_note" ><a href="javascript:display_help('change_password','$lang{change_password}')">$lang{help_on_this}</a></span>
2062 <div class="rightcol" style="white-space:nowrap;">
2063 <input type="password" name="new_cal_password" id="new_cal_password" size=12 />
2064 <span class="small_note" style="vertical-align:top;">$lang{new_password} </span>
2066 <input type="password" name="repeat_new_cal_password" size=12 />
2067 <span class="small_note" style="vertical-align:top;">$lang{repeat_new_password}</span>
2070 } elsif ($options{disable_passwords} ne "1") {
2071 $return_text .=<<p1;
2072 <div
class="leftcol">
2075 <div
class="rightcol" style
="white-space:nowrap;">
2076 $lang{no_password_needed
}
2081 $return_text .=<<p1;
2082 <div class="leftcol">
2085 <div class="rightcol" style="white-space:nowrap;">
2086 <input name="update_cal_button" type=submit value = "$lang{update_cal_button}"/>
2089 <div class="leftcol">
2092 <div class="rightcol" style="white-space:nowrap;">
2093 <span class="info_box_text small_note" id="preview_warning">$lang{preview_warning}</span>
2096 <br style="clear:both;"/>
2099 <div style="float:left;text-align:left;">
2100 <input name="del_cal_button" class="delete_button" type="submit" value = "$lang{del_cal_button1}"
2101 onclick="return confirm('$lang{del_cal_button2}');" />
2102 <div id="delete_note">
2103 <span class="small_note">
2104 $lang{del_cal_button3}
2109 <br style="clear:both;">
2110 <br style="clear:both;">
2113 } elsif ($add_edit_cal_action eq "add") {
2114 $return_text .=<<p1;
2115 <input id
="as" name
="as" type
="hidden" value
=""/>
2116 <div id
="rt" style
="display:none;">$rightnow</div
>
2119 if ($options{disable_passwords
} ne "1") {
2121 if ($options{anonymous_calendar_requests
} ne "1" && $need_password) {
2122 $return_text .=<<p1;
2123 <div class="leftcol" style="clear:both;white-space:nowrap;clear:both;margin-bottom:3ex;">
2124 <label class="required_field" for="cal_password">$lang{existing_cal_password1}</label>
2125 <br/>$lang{existing_cal_password2}
2128 <div class="rightcol" style="white-space:nowrap;">
2129 <input type="password" name="cal_password" id="cal_password" size=12 />
2130 <span class="small_note" ><a style="vertical-align:top;" href="javascript:display_help('current_password','$lang{cal_password}')">$lang{help_on_this}</a></span>
2135 $return_text .=<<p1;
2136 <div
class="leftcol" style
="white-space:nowrap;">
2137 <label
class="required_field" for="new_cal_password">$lang{cal_password
}</label
>
2139 <div
class="rightcol" style
="white-space:nowrap;">
2140 <input type
="password" name
="new_cal_password" id
="new_cal_password" size
=12 />
2141 <span
class="small_note" style
="vertical-align:top;">$lang{choose_password
} </span
> 
;
2142 <span
class="small_note" style
="vertical-align:top;"><a href
="javascript:display_help('new_password','$lang{choose_password}')">$lang{help_on_this
}</a></span
>
2145 <input type
="password" name
="repeat_new_cal_password" size
=12 />
2146 <span
class="small_note" style
="vertical-align:top;">$lang{repeat_password
} </span
>
2151 $return_text .=<<p1;
2152 <div class="leftcol">
2155 <div class="rightcol" style="white-space:nowrap;">
2156 <input name="update_cal_button" type="submit" value = "$lang{add_calendar}"/>
2159 <div class="leftcol">
2162 <div class="rightcol" style="white-space:nowrap;">
2163 <span class="info_box_text small_note" id="preview_warning">$lang{preview_warning}</span>
2166 <br style="clear:both;"/>
2170 $return_text .=<<p1;
2173 } else { #a user added/edited/deleted a calendar--do checks and perform resulting action
2174 my @results_messages;
2175 my $cal_id = $current_cal_id; # need to validate cal id for add/edit
2178 if ($q->param('del_cal_button') ne "") {
2181 &load_events
("all");
2182 &normalize_timezone
();
2188 if ($options{disable_passwords
} ne "1" && !$logged_in_as_root && !$logged_in_as_current_cal_admin) {
2190 push @results_messages, "$lang{update_cal_error1}<b>$current_calendar{title}</b>";
2193 # prevent delete of primary calendar
2194 if ($cal_id eq "0") {
2196 push @results_messages, $lang{update_cal_error2
};
2199 if ($del_valid == 1) { #actually delete the calendar.
2200 # first, delete all its events
2201 my @deleted_event_ids;
2202 my @updated_event_ids;
2203 foreach $event_id (keys %events) {
2204 # if the event is only on one calendar, delete it
2205 if (scalar@
{$events{$event_id}{cal_ids
}} == 1) {
2206 if ($events{$event_id}{cal_ids
}[0] eq $cal_id) {
2207 push @deleted_event_ids, $event_id;}
2209 } else { # otherwise, just remove that calendar from its cal_ids
2211 foreach $temp_cal_id (@
{$events{$event_id}{cal_ids
}}) {
2212 if ($temp_cal_id eq $cal_id) {
2217 splice @
{$events{$event_id}{cal_ids
}}, $index, 1; {
2218 push @updated_event_ids, $event_id;}
2221 &delete_events
(\
@deleted_event_ids);
2222 &update_events
(\
@updated_event_ids);
2224 # next, delete the calendar in question
2225 &delete_calendar
($cal_id); # redundant in flat-file mode, needed for sql mode
2227 # finally, delete any references in other calendars (background calendars)
2229 foreach $calendar_id (sort {$a <=> $b} keys %calendars) {
2230 #$debug_info .= "calendar $calendar_id\n";
2231 if ($calendars{$calendar_id}{local_background_calendars
}{$cal_id} eq "1") {
2232 delete $calendars{$calendar_id}{local_background_calendars
}{$cal_id};
2233 push @cals_to_update, $calendar_id;
2235 if ($calendars{$calendar_id}{selectable_calendars
}{$cal_id} eq "1") {
2236 delete $calendars{$calendar_id}{selectable_calendars
}{$cal_id};
2237 push @cals_to_update, $calendar_id;
2240 &update_calendars
(\
@cals_to_update);
2242 my $temp = $lang{update_cal_error3
};
2243 $temp =~ s/###title###/$current_calendar{title}/;
2244 push @results_messages, $temp;
2247 # properly format errors, warnings
2248 my @messages = split ("\n",$cal_del_results);
2249 $cal_del_results="";
2251 foreach $message (@messages) {
2252 $message =~ s/(.*$lang{Warning})/<span class="warning">$1<\/span
>/i
;
2253 $message =~ s/(.*$lang{Error})/<span class="error">$1<\/span
>/i
;
2254 $cal_del_results .= "$message<br/>\n";
2257 #$results{text} = join "\n", @messages;
2258 $cal_del_results = "<ul style=\"font-size:small;\">$cal_del_results</ul>";
2260 } else { #the user added/updated a calendar
2262 #check all input fields for validity
2263 my $cal_title = $q->param('cal_title');
2264 my $cal_link = $q->param('cal_link');
2265 my $cal_details = $q->param('cal_details');
2267 my @local_background_calendars = $q->param('background_calendars');
2268 my @selectable_calendars = $q->param('selectable_calendars');
2269 my $list_background_calendars_together = $q->param('list_background_calendars_together');
2270 my $background_events_display_style = $q->param('background_events_display_style');
2271 my $background_events_fade_factor = $q->param('background_events_fade_factor');
2272 my $background_events_color = $q->param('background_events_color');
2273 my $new_calendars_automatically_selectable = "y" if ($q->param('new_calendars_automatically_selectable') =~ "y");
2275 my $allow_remote_calendar_requests = $q->param('allow_remote_calendar_requests');
2276 my $remote_calendar_requests_require_password = $q->param('remote_calendar_requests_require_password');
2277 my $remote_calendar_requests_password = $q->param('remote_calendar_requests_password');
2279 my $new_remote_calandars_xml = $q->param('new_remote_calandars_xml');
2280 my $calendar_events_color = $q->param('calendar_events_color');
2282 my $default_number_of_months = $q->param('default_number_of_months');
2283 my $max_number_of_months = $q->param('max_months');
2284 my $gmtime_diff = $q->param('gmtime_diff');
2285 my $date_format = $q->param('date_format');
2286 $date_format = lc $date_format;
2287 my $week_start_day = $q->param('week_start_day');
2288 my $event_change_email = $q->param('event_change_email');
2289 my $info_window_size = $q->param('popup_window_size');
2291 if ($info_window_size !~ /^\d{1,}x\d{1,}$/) {
2293 my $temp=$lang{update_cal_error4
};
2294 $temp =~ s/###size###/$info_window_size/;
2295 push @results_messages, $temp;
2298 my $custom_template = $q->param('custom_template');
2299 $custom_template =~ s/http:\/\///g;
2301 my $custom_stylesheet = $q->param('custom_stylesheet');
2302 $custom_stylesheet =~ s/http:\/\///g;
2304 my $cal_password = $q->param('cal_password');
2305 my $new_cal_password = $q->param('new_cal_password');
2306 my $repeat_new_cal_password = $q->param('repeat_new_cal_password');
2308 $cal_title =~ s/\r//g; # some browsers sneak these in
2309 $cal_link =~ s/\r//g; # some browsers sneak these in
2310 $cal_details =~ s/\r//g; # some browsers sneak these in
2313 #check for required fields
2314 if ($cal_title eq "") {
2316 push @results_messages, $lang{update_cal_error5
};
2319 #strip all html from label field
2320 if ($cal_title =~ m/<(.*)>/) {
2321 push @results_messages, $lang{update_cal_error6
};
2322 $cal_title =~ s/<(.*)>//g;
2325 $cal_link =~ s/http:\/\///g; #strip http:// from link field
2327 #check for date format
2328 if ($date_format !~ /^(mm|dd|yy)\W(mm|dd|yy)\W(mm|dd|yy)$/ ) {
2330 push @results_messages, $lang{update_cal_error6_5
};
2333 if ($add_edit_cal_action eq "edit") {
2334 if ($options{disable_passwords
} ne "1") {
2335 #this action is an edit of an existing calendar, so we need to make a replacement.
2336 if (!(defined $calendars{$cal_id})) {
2338 push @results_messages, $lang{update_cal_error7
};
2339 } else { #check password
2340 if ($options{disable_passwords
} ne "1" && !$logged_in_as_root && !$logged_in_as_current_cal_admin) {
2342 push @results_messages, "$lang{update_cal_error1} <b>$calendars{$cal_id}{title}</b>";
2346 #check for new password
2347 if ($new_cal_password ne "" || $repeat_new_cal_password ne "") {
2348 if ($new_cal_password ne $repeat_new_cal_password) {
2350 push @results_messages, $lang{update_cal_error8
};
2352 $calendars{$cal_id}{password
} = crypt($new_cal_password, $options{salt
});
2357 # check for gmtime_diff field
2358 if ($options{force_single_timezone
} eq "1" && $cal_id ne "0") {
2359 $gmtime_diff = $calendars{0}{gmtime_diff
}
2362 # encrypt remote calendar password
2363 $remote_calendar_requests_password = crypt($remote_calendar_requests_password, $options{salt
});
2365 if ($cal_valid == 1) { # update calendar record
2367 $calendars{$cal_id}{title
} = $cal_title;
2368 $calendars{$cal_id}{details
} = $cal_details;
2369 $calendars{$cal_id}{link} = $cal_link;
2370 $calendars{$cal_id}{new_calendars_automatically_selectable
} = $new_calendars_automatically_selectable;
2371 $calendars{$cal_id}{list_background_calendars_together
} = $list_background_calendars_together;
2372 $calendars{$cal_id}{calendar_events_color
} = $calendar_events_color;
2373 $calendars{$cal_id}{background_events_display_style
} = $background_events_display_style;
2374 $calendars{$cal_id}{background_events_fade_factor
} = $background_events_fade_factor;
2375 $calendars{$cal_id}{background_events_color
} = $background_events_color;
2376 $calendars{$cal_id}{default_number_of_months
} = $default_number_of_months;
2377 $calendars{$cal_id}{max_number_of_months
} = $max_number_of_months;
2378 $calendars{$cal_id}{gmtime_diff
} = $gmtime_diff;
2379 $calendars{$cal_id}{date_format
} = $date_format;
2380 $calendars{$cal_id}{week_start_day
} = $week_start_day;
2381 $calendars{$cal_id}{event_change_email
} = $event_change_email;
2382 $calendars{$cal_id}{info_window_size
} = $info_window_size;
2383 $calendars{$cal_id}{custom_template
} = $custom_template;
2384 $calendars{$cal_id}{custom_stylesheet
} = $custom_stylesheet;
2385 $calendars{$cal_id}{allow_remote_calendar_requests
} = $allow_remote_calendar_requests;
2386 $calendars{$cal_id}{remote_calendar_requests_require_password
} = $remote_calendar_requests_require_password;
2387 $calendars{$cal_id}{remote_calendar_requests_password
} = $remote_calendar_requests_password;
2389 # update local background calendars
2390 foreach $local_background_calendar (keys %{$calendars{$cal_id}{local_background_calendars
}}) {
2391 delete $calendars{$cal_id}{local_background_calendars
}{$local_background_calendar};
2394 foreach $local_background_calendar (@local_background_calendars) {
2395 $calendars{$cal_id}{local_background_calendars
}{$local_background_calendar} = 1;
2398 #$debug_info .= "new remote calendars xml: $new_remote_calandars_xml\n";
2400 #delete existing remote background calendars
2401 foreach $current_remote_calendar_id (keys %{$current_calendar{remote_background_calendars
}}) {
2402 if ($q->param("delete_remote_calendar_$current_remote_calendar_id") ne "") {
2403 my $temp = $lang{get_remote_calendar5
};
2404 $temp =~ s/###remote url###/$current_calendar{remote_background_calendars}{$current_remote_calendar_id}{url}/g;
2405 $temp =~ s/###remote id###/$current_calendar{remote_background_calendars}{$current_remote_calendar_id}{remote_id}/g;
2406 push @results_messages, $temp;
2408 delete $calendars{$current_cal_id}{remote_background_calendars
}{$current_remote_calendar_id};
2412 # update remote background calendars
2413 unless ($new_remote_calandars_xml eq "") {
2414 my %new_remote_calendars = %{&xml2hash
($new_remote_calandars_xml)};
2415 #$debug_info .= "$new_remote_calendars{remote_calendars}{remote_calendar}\n";
2417 my $new_remote_cal_id = &max
(keys %{$calendars{$cal_id}{remote_background_calendars
}}) + 1;
2418 #$debug_info .= (scalar keys %{$calendars{$cal_id}{remote_background_calendars}})." remote calendars already\n";
2419 #$debug_info .= "new_remote_cal_id: $new_remote_cal_id\n";
2421 if ($new_remote_calendars{remote_calendars
}{remote_calendar
} =~ /array/i) { # multiple remote background calendars
2422 foreach $temp (@
{$new_remote_calendars{remote_calendars
}{remote_calendar
}}) {
2423 my %new_remote_calendar = %{$temp};
2426 foreach $current_remote_calendar_id (keys %{$current_calendar{remote_background_calendars
}}) {
2427 #$debug_info .= "comparing $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{url} with $new_remote_calendar{url}\n";
2428 $found=1 if ($current_calendar{remote_background_calendars
}{$current_remote_calendar_id}{url
} eq $new_remote_calendar{url
} &&
2429 $current_calendar{remote_background_calendars
}{$current_remote_calendar_id}{type
} eq $new_remote_calendar{type
} &&
2430 $current_calendar{remote_background_calendars
}{$current_remote_calendar_id}{version
} eq $new_remote_calendar{version
} &&
2431 $current_calendar{remote_background_calendars
}{$current_remote_calendar_id}{password
} eq $new_remote_calendar{password
} &&
2432 $current_calendar{remote_background_calendars
}{$current_remote_calendar_id}{remote_id
} eq $new_remote_calendar{remote_id
});
2436 $calendars{$cal_id}{remote_background_calendars
}{$new_remote_cal_id}{url
} = $new_remote_calendar{url
};
2437 $calendars{$cal_id}{remote_background_calendars
}{$new_remote_cal_id}{type
} = $new_remote_calendar{type
};
2438 $calendars{$cal_id}{remote_background_calendars
}{$new_remote_cal_id}{version
} = $new_remote_calendar{version
};
2439 $calendars{$cal_id}{remote_background_calendars
}{$new_remote_cal_id}{password
} = $new_remote_calendar{password
};
2440 $calendars{$cal_id}{remote_background_calendars
}{$new_remote_cal_id}{remote_id
} = $new_remote_calendar{remote_id
};
2441 $new_remote_cal_id++;
2443 my $temp = $lang{get_remote_calendar4
};
2444 $temp =~ s/###remote url###/$new_remote_calendar{url}/g;
2445 $temp =~ s/###remote id###/$new_remote_calendar{remote_id}/g;
2446 push @results_messages, $temp;
2449 #$debug_info .= "remote calendar: $new_remote_calendar{url}\n";
2450 #$debug_info .= "type: $new_remote_calendar{type}\n";
2452 } else { # single remote background calendar
2454 # check against existing remote background calendars.
2455 my %new_remote_calendar = %{$new_remote_calendars{remote_calendars
}{remote_calendar
}};
2458 foreach $current_remote_calendar_id (keys %{$current_calendar{remote_background_calendars
}}) {
2459 #$debug_info .= "comparing $current_calendar{remote_background_calendars}{$current_remote_calendar_id}{url} with $new_remote_calendar{url}\n";
2460 if ($current_calendar{remote_background_calendars
}{$current_remote_calendar_id}{url
} eq $new_remote_calendar{url
} &&
2461 $current_calendar{remote_background_calendars
}{$current_remote_calendar_id}{type
} eq $new_remote_calendar{type
} &&
2462 $current_calendar{remote_background_calendars
}{$current_remote_calendar_id}{version
} eq $new_remote_calendar{version
} &&
2463 $current_calendar{remote_background_calendars
}{$current_remote_calendar_id}{password
} eq $new_remote_calendar{password
} &&
2464 $current_calendar{remote_background_calendars
}{$current_remote_calendar_id}{remote_id
} eq $new_remote_calendar{remote_id
}) {
2470 $calendars{$cal_id}{remote_background_calendars
}{$new_remote_cal_id}{url
} = $new_remote_calendar{url
};
2471 $calendars{$cal_id}{remote_background_calendars
}{$new_remote_cal_id}{type
} = $new_remote_calendar{type
};
2472 $calendars{$cal_id}{remote_background_calendars
}{$new_remote_cal_id}{version
} = $new_remote_calendar{version
};
2473 $calendars{$cal_id}{remote_background_calendars
}{$new_remote_cal_id}{password
} = $new_remote_calendar{password
};
2474 $calendars{$cal_id}{remote_background_calendars
}{$new_remote_cal_id}{remote_id
} = $new_remote_calendar{remote_id
};
2476 my $temp = $lang{get_remote_calendar4
};
2477 $temp =~ s/###remote url###/$new_remote_calendar{url}/g;
2478 $temp =~ s/###remote id###/$new_remote_calendar{remote_id}/g;
2479 push @results_messages, $temp;
2484 #$calendars{$cal_id}{remote_background_calendars} = $remote_calendar_requests_password;
2486 # update selectable calendars
2487 foreach $selectable_calendar (keys %{$calendars{$cal_id}{selectable_calendars
}}) {
2488 delete $calendars{$cal_id}{selectable_calendars
}{$selectable_calendar};
2490 foreach $selectable_calendar (@selectable_calendars) {
2491 $calendars{$cal_id}{selectable_calendars
}{$selectable_calendar} = 1;
2495 if ($cal_valid == 1) { #all checks successful, add/update calendar!
2496 &update_calendar
($cal_id);
2497 push @results_messages, "<b>$calendars{$current_cal_id}{title}</b> $lang{update_cal_success}";
2499 $cal_add_results .= $lang{update_cal_failure
};
2501 } else { # add new calendar
2503 # check password, if necessary
2504 if ($options{anonymous_calendar_requests
} eq "1") {
2505 my $t1 = $q->param('as');
2507 if (abs($t1 - $t2) > 3600) {
2512 if ($options{disable_passwords
} ne "1" && !$logged_in_as_root && !$logged_in_as_current_cal_admin) {
2514 push @results_messages, "$lang{update_cal_error0}";
2519 if ($options{disable_passwords
} ne "1") {
2520 if ($new_cal_password ne $repeat_new_cal_password) {
2522 push @results_messages, $lang{update_cal_error9
};
2523 } elsif ($new_cal_password eq "" || $repeat_new_cal_password eq "" ) {
2525 push @results_messages, $lang{update_cal_error10
};
2527 $input_password = crypt($new_cal_password, $options{salt
});
2533 if ($cal_valid == 1) {
2534 $new_cal_id = $max_action_id + int(rand(100)); # just in case several people decide to add something new at the same time.
2536 $new_calendars{$new_cal_id}{id
} = $new_cal_id;
2537 $new_calendars{$new_cal_id}{title
} = $cal_title;
2538 $new_calendars{$new_cal_id}{details
} = $cal_details;
2539 $new_calendars{$new_cal_id}{link} = $cal_link;
2540 $new_calendars{$new_cal_id}{list_background_calendars_together
} = $list_background_calendars_together;
2541 $new_calendars{$new_cal_id}{calendar_events_color
} = $calendar_events_color;
2542 $new_calendars{$new_cal_id}{background_events_fade_factor
} = $background_events_fade_factor;
2543 $new_calendars{$new_cal_id}{background_events_color
} = $background_events_color;
2544 $new_calendars{$new_cal_id}{default_number_of_months
} = $default_number_of_months;
2545 $new_calendars{$new_cal_id}{max_number_of_months
} = $max_number_of_months;
2546 $new_calendars{$new_cal_id}{gmtime_diff
} = $gmtime_diff;
2547 $new_calendars{$new_cal_id}{date_format
} = $date_format;
2548 $new_calendars{$new_cal_id}{week_start_day
} = $week_start_day;
2549 $new_calendars{$new_cal_id}{info_window_size
} = $info_window_size;
2550 $new_calendars{$new_cal_id}{custom_template
} = $custom_template;
2551 $new_calendars{$new_cal_id}{custom_stylesheet
} = $custom_stylesheet;
2552 $new_calendars{$new_cal_id}{password
} = $input_password;
2553 $new_calendars{$new_cal_id}{update_timestamp
} = $rightnow;
2554 $new_calendars{$new_cal_id}{allow_remote_calendar_requests
} = $allow_remote_calendar_requests;
2555 $new_calendars{$new_cal_id}{remote_calendar_requests_require_password
} = $remote_calendar_requests_require_password;
2556 $new_calendars{$new_cal_id}{remote_calendar_requests_password
} = $remote_calendar_requests_password;
2558 # local background calendars
2559 foreach $local_background_calendar (@local_background_calendars) {
2560 $new_calendars{$new_cal_id}{local_background_calendars
}{$local_background_calendar} = 1;
2563 # selectable calendars
2564 foreach $selectable_calendar (@selectable_calendars) {
2565 $new_calendars{$new_cal_id}{selectable_calendars
}{$selectable_calendar} = 1;
2569 # check for refreshes!
2570 if ($cal_valid == 1) {
2571 my %latest_new_calendar = $new_calendars{$latest_new_cal_id};
2572 if ($new_calendars{$new_cal_id}{title
} eq $latest_new_calendar{title
} &&
2573 $new_calendars{$new_cal_id}{details
} eq $latest_new_calendar{details
} &&
2574 $new_calendars{$new_cal_id}{link} eq $latest_new_calendar{link}) {
2576 push @results_messages, $lang{update_cal_dup
};
2580 if ($cal_valid == 1) { #all checks successful, add calendar!
2581 &add_action
($new_cal_id, "new_calendar");
2583 my $new_cal_details = &generate_cal_details
($new_calendars{$new_cal_id});
2584 $new_cal_details =~ s/<a.+Delete this.+<\/a>//;
2585 $new_cal_details =~ s/Link directly.+<\/a>//s
;
2587 if ($options{new_calendar_request_notify
} ne "") {
2589 $lang{add_cal_email_notify1}
2593 <a href="$script_url/$name?active_tab=2&add_edit_cal_action=view_pending">$lang{add_cal_success3}</a>
2596 &send_email($options{new_calendar_request_notify}, $options{reply_address}, $options{reply_address}, $lang{add_cal_email_notify2}, $body);
2599 my $temp = $lang{add_cal_success1}; # add successful
2600 $temp = $lang{add_cal_success4} if ($add_edit_cal_action eq "edit"); # update successful
2602 $cal_add_results .= <<p1;
2603 <div style
="text-align:left;">
2604 <p style
="font-weight:bold;">
2608 <div
class="info_box">
2612 <p style
="margin-top:1em;">
2613 $lang{add_cal_success2
}
2617 <li
><a href
="$script_url/$name?active_tab=2&add_edit_cal_action=view_pending">$lang{add_cal_success3
}</a
>
2622 push @results_messages, $lang{add_cal_fail1
};
2626 # properly format errors & warnings
2627 my $message_results="";
2628 foreach $results_message (@results_messages) {
2629 $results_message =~ s/(.*$lang{Warning})/<span class="warning">$1<\/span
>/i
;
2630 $results_message =~ s/(.*$lang{Error})/<span class="error">$1<\/span
>/i
;
2631 $message_results .= "<li>$results_message</li>\n";
2634 $cal_add_results = "<ul style=\"font-size:small;\">$message_results</ul>$cal_add_results";
2637 $return_text .=<<p1;
2638 <div style="text-align:left;">
2643 return $return_text;
2644 } #********************end add_edit_calendars code*****************************
2647 sub view_pending_calendars {
2648 my $return_text = "";
2650 if ($q->param('approve_cal_button') eq "") { #view pending calendars main screen
2653 $shared_cal_select_size = scalar keys %calendars;
2656 <p
class="cal_title">
2657 $lang{view_pending_calendars1
}
2662 if (scalar keys %new_calendars == 0) {
2664 <p class="optional_field">
2665 $lang{view_pending_calendars2
}
2670 <form name="pending_calendars_form" action="">
2671 <input type="hidden" name="active_tab" value="2">
2672 <input type="hidden" name="add_edit_cal_action" value="view_pending">
2675 foreach $new_cal_id (keys %new_calendars) {
2676 my $new_cal_details = &generate_cal_details($new_calendars{$new_cal_id});
2677 $new_cal_details =~ s/<a.+Delete this.+<\/a>//;
2678 $new_cal_details =~ s/Link directly.+<\/a>//s;
2679 #Link directly to this calendar:<br/>
2680 #<a href="$script_url/$name?cal_id=$calendar{id}">$script_url/$name?cal_id=$calendar{id}</a>
2685 <div
class="info_box" style
="float:left;text-align:left;width:40%;margin:10px;clear:both;">
2688 <div style
="float:left;text-align:left;margin:10px;">
2690 <input type
="radio" name
="new_cal_$new_cal_id" value
="approve"/><span class="optional_field">$lang{view_pending_calendars3}</span
><br
/><br/>
2691 <input type
="radio" name
="new_cal_$new_cal_id" value
="delete"/><span class="optional_field">$lang{view_pending_calendars4}</span
><br
/>
2693 <br style
="clear:both;"/>
2697 <div style="clear:both;">
2699 <label for="main_password" class="optional_field">
2700 $calendars{0}{title} Password:
2702 <input type=password id="main_password" name = "main_password" size=10>
2704 <input type=submit name="approve_cal_button" value = "$lang{view_pending_calendars5}">
2710 } else { #view pending calendars approve/delete results screen
2712 my @pending_calendars_to_delete;
2713 my @calendars_to_add;
2714 my @calendars_to_update;
2717 $shared_cal_select_size = scalar keys %calendars;
2720 <p
class="cal_title">
2721 $lang{view_pending_calendars6
}
2726 $input_password = crypt($q->param('main_password'), $options{salt
});
2728 if ($options{disable_passwords
} ne "1") {
2729 if ($input_password ne $master_password) {
2730 $return_text .=<<p1;
2732 <li>$lang{view_pending_calendars7}</li>
2735 return $return_text;
2739 #go through each new calendar in the new calendars file--take appropriate action
2740 foreach $new_cal_id (keys %new_calendars) {
2741 my $new_cal_details = &generate_cal_details($new_calendars{$new_cal_id});
2743 if ($q->param("new_cal_$new_cal_id") eq "approve") {
2744 $max_cal_id+=1; #calculate new id # for the new calendar
2746 foreach $cal_id (keys %calendars) {
2747 if ($calendars{$cal_id}{new_calendars_automatically_selectable} =~ "y") {
2748 $calendars{$cal_id}{selectable_calendars}{$max_cal_id} = 1;
2749 push @calendars_to_update, $cal_id;
2753 $calendars{$max_cal_id} = $new_calendars{$new_cal_id};
2754 $calendars{$max_cal_id}{id} = $max_cal_id;
2756 # make sure the calendar can select itself.
2757 $calendars{$max_cal_id}{selectable_calendars}{$max_cal_id} = 1 if (scalar keys %{$calendars{$max_cal_id}{selectable_calendars}} > 0);
2759 delete $new_calendars{$new_cal_id};
2760 push @pending_calendars_to_delete, $new_cal_id;
2761 push @calendars_to_add, $max_cal_id;
2763 $approve_or_delete_result = $lang{view_pending_calendars8};
2764 } elsif ($q->param("new_cal_$new_cal_id") eq "delete") {
2765 delete $new_calendars{$new_cal_id};
2766 push @pending_calendars_to_delete, $new_cal_id;
2767 $approve_or_delete_result = $lang{view_pending_calendars9};
2769 $approve_or_delete_result = $lang{view_pending_calendars10};
2773 $new_cal_details =~ s/<a.+Delete this.+<\/a>//;
2774 $new_cal_details =~ s/Link directly.+<\/a>//s;
2776 $return_text .= <<p1;
2777 <div style
="float:left;clear:left;width:90%;">
2778 <div
class="info_box" style
="text-align:left;width:40%;margin:10px;clear:both;float:left;">
2781 <div style
="text-align:left;margin:10px;float:left;">
2783 $approve_or_delete_result
2789 &delete_pending_actions
(\
@pending_calendars_to_delete);
2790 &add_calendars
(\
@calendars_to_add);
2791 &update_calendars
(\
@calendars_to_update);
2795 <br style="clear:both;"/>
2798 return $return_text;
2800 } #********************end view_pending_calendars code*****************************
2803 sub do_calendar_list_view() {
2804 my $return_text = "";
2806 if ($cal_num_months> 1) {
2807 $cal_title_string .=<<p1;
2808 $months[$cal_start_month] $cal_start_year - $months[$cal_end_month] $cal_end_year
2811 $cal_title_string .=<<p1;
2812 $months[$cal_start_month] $cal_start_year
2816 # previous and next month(s) link
2817 $return_text .=<<p1;
2818 <div style
="text-align:center;white-space:nowrap;">
2820 <span
class="cal_title" style
="margin-left:3em;margin-right:3em;">
2827 <div style
="clear:both;margin:auto;">
2830 if ($display_type == 1) { #list view
2832 $return_text .= &render_list
($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year);
2833 } else { #calendar view
2835 $return_text .= &render_calendar
($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year);
2837 $return_text .=<<p1;
2841 return $return_text;
2843 } ###############end do_calendar_list_view ###################
2846 sub add_edit_events_interface() {
2847 my $temp="<link rel=\"stylesheet\" href=\"$theme_url/color_select.css\" type=\"text/css\">";
2848 $html_output =~ s/<head>/<head>\n$temp\n/;
2850 my $return_text = "";
2851 $add_edit_event = "add" if ($add_edit_event eq "");
2853 $add_edit_string = $lang{add_or_edit1};
2856 $event_start_date = $current_calendar{date_format};
2858 if ($q->param('add_date_timestamp')+0 == 0) { # no date supplied--generic add event
2859 # no date supplied--generic add event
2860 if ($cal_start_year ne "") {
2861 $event_start_date =~ s/yy/$cal_start_year/;
2863 $event_start_date =~ s/yy/$rightnow_year/;
2865 } else { # add event on a particular date -- calculate date
2866 my @event_start_date_array = gmtime $q->param('add_date_timestamp');
2867 my $mm = $event_start_date_array[4]+1;
2868 my $md = $event_start_date_array[3];
2869 my $yy = $event_start_date_array[5]+1900;
2871 $event_start_date =~ s/mm/$mm/;
2872 $event_start_date =~ s/dd/$md/;
2873 $event_start_date =~ s/yy/$yy/;
2876 my $recur_end_date = $current_calendar{date_format};
2877 $recur_end_date =~ s/mm/12/;
2878 $recur_end_date =~ s/dd/31/;
2879 $recur_end_date =~ s/yy/$rightnow_year/;
2882 $event_icon = "blank";
2885 my $unit_number_text = "";
2886 my $event_unit_number = "";
2888 $add_edit_string = $lang{add_or_edit2} if ($add_edit_event eq "edit");
2890 if ($current_event_id ne "") {
2891 #select the appropriate event to edit
2892 %current_event = %{$events{$current_event_id}};
2893 @current_cal_ids = @{$current_event{cal_ids}};
2894 %current_calendar = %{$calendars{$current_cal_ids[0]}};
2895 #$cal_title=$calendars{$current_event{cal_id}}{title};
2897 $event_name = $current_event{title};
2898 $event_details = $current_event{details};
2900 $event_start_date = $current_calendar{date_format};
2901 my @temp_date = gmtime($current_event{start});
2902 $temp_date[5] += 1900;
2905 $event_start_date =~ s/mm/$temp_date[4]/;
2906 $event_start_date =~ s/dd/$temp_date[3]/;
2907 $event_start_date =~ s/yy/$temp_date[5]/;
2909 $event_days=$current_event{days};
2910 $event_icon = $current_event{icon};
2911 $event_bgcolor = $current_event{bgcolor};
2912 $event_unit_number = $current_event{unit_number};
2913 $unit_number_text = $event_unit_number;
2914 $unit_number_text =~ s/(\d)/<img src="$graphics_url\/unit_number_patch_$1_16x10.gif" alt="" border="0" vspace=0 hspace=0>/g;
2917 $return_text .=<<p1;
2918 <p
class="cal_title" style
="text-align:center;">
2922 <div
class="info_box" style
="text-align:center;margin-bottom:2em;float:left;">
2923 <span
class="optional_field">$lang{fields_text1
} <span
class="required_field">$lang{fields_text2
}</span> $lang{fields_text3}</span
>
2926 <div style
="clear:both;width:90%;text-align:left;white-space:nowrap;clear:left;">
2927 <a id
="tab0" href
="javascript:tab_show(0)" class="info_box_tab active">$lang{add_edit_events_tab0
}</a
>
2928 <a id
="tab1" href
="javascript:tab_show(1)" class="info_box_tab">$lang{add_edit_events_tab1
}</a
>
2931 <div id
="tab_area0" class="info_box" style
="width:100%;position:relative;z-index:101;padding-top:1em;margin-bottom:1em;">
2933 my @selectable_cal_ids;
2935 if ($options{all_calendars_selectable
}) {
2936 @selectable_cal_ids = keys %calendars;
2938 @selectable_cal_ids = keys %{$current_calendar{selectable_calendars
}};
2939 push @selectable_cal_ids, $current_cal_id;
2942 my %evt_calendar = %{$calendars{$current_cal_id}};
2943 %evt_calendar = %{$calendars{$current_event{cal_ids
}[0]}} if ($add_edit_event eq "edit");
2945 if ($add_edit_event eq "edit" || scalar @selectable_cal_ids == 0) { # force event calendar
2946 $return_text .=<<p1;
2947 <input type="hidden" name="cal_id" value="$evt_calendar{id}">
2948 <div class="leftcol">
2949 <span class="optional_field">$lang{event_calendar}</span>
2951 <div class="rightcol" style="padding-left:.5em;">
2952 $evt_calendar{title}
2955 } else { # user can select event calendar
2956 $return_text .=<<p1;
2957 <div
class="leftcol">
2958 <span
class="required_field">$lang{event_calendar
}</span
>
2960 <div
class="rightcol">
2961 <select name
="cal_id" id
="cal_id">
2964 foreach $cal_ref_id (sort {$calendars{$a}{title
} cmp $calendars{$b}{title
}} @selectable_cal_ids) {
2966 $selected = " selected" if ($cal_ref_id eq $evt_calendar{id
});
2967 $return_text .=<<p1;
2968 <option value = "$cal_ref_id"$selected>$calendars{$cal_ref_id}{title}
2972 $return_text .=<<p1;
2974 <span
class="small_note"><a href
="javascript:display_help('evt_cal_id','$lang{event_calendar}')">$lang{help_on_this
}</a></span
>
2978 if ($options{allow_merge_blocking
}) {
2980 my $block_merge_checked = ($current_event{block_merge
} eq "1") ?
" checked" : "";
2982 $return_text .=<<p1;
2983 <input type="checkbox" name="evt_block_merge" id=evt_"block_merge" value="1"$block_merge_checked/>
2984 <span class="optional_field">$lang{block_merge}</span>
2989 $return_text .=<<p1;
2993 if ($options{multi_calendar_event_mode
} > 0 && $add_edit_event eq "edit") {
2994 $return_text .=<<p1;
2995 <div class="leftcol">
2996 <span class="optional_field">$lang{event_other_calendars}</span>
2998 <div class="rightcol" style="padding-left:.5em;">
2999 <select multiple name="evt_other_cal_ids">
3002 foreach $cal_ref_id (sort {$calendars{$a}{title} cmp $calendars{$b}{title}} @selectable_cal_ids) {
3004 next if ($cal_ref_id eq $evt_calendar{id});
3006 foreach $selected_cal_id (@{$events{$current_event_id}{cal_ids}}) {
3007 if ($cal_ref_id eq $selected_cal_id) {
3008 $selected = " selected";
3013 $return_text .=<<p1;
3014 <option value
= "$cal_ref_id"$selected>$calendars{$cal_ref_id}{title
}
3018 $return_text .=<<p1;
3020 <span class="small_note"><a href="javascript:display_help('evt_other_cal_ids','$lang{event_other_calendars}')">$lang{help_on_this}</a></span>
3025 my $all_day_event_checked = "";
3027 if ($options{new_events_all_day}) {
3028 $all_day_event_checked = "checked";}
3030 my $event_start_time = $options{default_event_start_time};
3031 my $event_end_time = $options{default_event_end_time};
3033 if ($current_event_id ne "") {
3034 $all_day_event_checked = "checked";
3035 $all_day_event_checked = "" if ($current_event{all_day_event} ne "1");
3036 $event_start_time = &formatted_time($current_event{start},"hh:mm ampm");
3037 $event_end_time = &formatted_time($current_event{end},"hh:mm ampm");
3038 $event_end_time = "" if ($current_event{no_end_time} eq "1");
3043 my $all_day_event_toggle0_style = "display:none;";
3044 if ($all_day_event_checked ne "checked") {
3045 $all_day_event_toggle0_style = "";
3048 my $edit_title = &escapequotes($current_event{title});
3049 $return_text .=<<p1;
3050 <div
class="leftcol" style
="">
3051 <label
class="required_field" for="evt_title">$lang{event_title
}</label
>
3053 <div
class="rightcol" style
="white-space:nowrap;">
3054 <input id
="evt_title" name
="evt_title" style
="width:50%;" value
= "$edit_title">
3055 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('evt_title','$lang{event_title}')">$lang{help_on_this
}</a></span
>
3058 <div
class="leftcol" style
="">
3059 <label
class="optional_field" for="evt_details">$lang{event_details
}</label
>
3061 <span
class="small_note" style
="vertical-align:top;" ><a href
="javascript:display_help('evt_details','$lang{event_details}')">$lang{help_on_this
}</a> </span
>
3063 <div
class="rightcol" style
="white-space:nowrap;">
3064 <textarea name
="evt_details" id
="evt_details" rows
=10 cols
=0 style
="width:100%;">$current_event{details
}</textarea
>
3067 <div
class="leftcol" style
="margin-bottom:0;">
3068 <label
class="required_field" for="evt_start_date">$lang{event_start
}</label
>
3070 <div
class="rightcol" style
="margin-bottom:0;white-space:nowrap;">
3071 <input id
="evt_start_date" name
="evt_start_date" style
="width:7em;" value
= "$event_start_date" onchange
="validate_event_date();">
3072 <span id
="evt_start_date_warning" class="small_note"></span
>
3075 <div
class="leftcol" style
="">
3076 <label
class="required_field" for="evt_days">$lang{event_length
}</label
>
3078 <div
class="rightcol" style
="white-space:nowrap;">
3079 <input id
="evt_days" name
="evt_days" style
="width:2em;" value
= "$event_days">
3080 <input type
="checkbox" id
="all_day_event" name
="all_day_event" value
="1"$all_day_event_checked onChange
="all_day_event_toggle(this.checked);">
3081 <label
class="optional_field" for="all_day_event">$lang{all_day_event
}</label
>
3084 <div id
="all_day_event_toggle0" style
="$all_day_event_toggle0_style">
3085 <div
class="leftcol" style
="margin-bottom:0;">
3086 <label
class="required_field" for="evt_start_time">$lang{event_start_time
}</label
>
3088 <div
class="rightcol" style
="margin-bottom:0;white-space:nowrap;">
3089 <input id
="evt_start_time" name
="evt_start_time" style
="width:7em;" value
= "$event_start_time">
3091 <div
class="leftcol" style
="margin-bottom:0;">
3092 <label
class="optional_field" for="evt_end_time">$lang{event_end_time
}</label
>
3094 <div
class="rightcol" style
="margin-bottom:0;white-space:nowrap;">
3095 <input id
="evt_end_time" name
="evt_end_time" style
="width:7em;" value
= "$event_end_time">
3100 $return_text .=<<p1;
3101 <div style="float:right;width:20%;">
3102 <div class="icon_preview_box" style="float:left;">
3103 <div id="icon_preview" style="text-align:center;">
3104 <img src="$icons_url/$event_icon\l_32x32.gif" alt='event icon' border="0" vspace=0 hspace=0>
3107 if ($options{unit_number_icons} == 1) {
3108 $return_text .=<<p1;
3109 <div id
="unit_number_preview" style
="margin:3px;">
3114 $return_text .=<<p1;
3120 $return_text .=<<p1;
3121 <div
class="leftcol" style
="margin-bottom:0;">
3122 <label
class="optional_field" for="evt_icon">$lang{event_icon
}</label
>
3124 <div
class="rightcol" style
="margin-bottom:0;white-space:nowrap;width:auto;">
3125 <select name
="evt_icon" id
="evt_icon" onChange
="update_preview_icon()">
3127 @icon_menus_data = &assemble_icon_menus
($event_icons_menu);
3128 $icon_menu_index_number = 0;
3129 $return_text .= &generate_flat_icon_menus
(\
@icon_menus_data, $event_icon);
3131 $return_text .=<<p1;
3135 if ($options{unit_number_icons} == 1) {
3136 $return_text .=<<p1;
3137 <div
class="leftcol" style
="margin-bottom:0;">
3138 <label
class="optional_field" for="unit_number">$lang{event_unit_number
} </label
>
3140 <div
class="rightcol" style
="margin-bottom:0;white-space:nowrap;width:40%">
3141 <input id
="unit_number" name
="unit_number" style
="width:6ex;" value
= "$event_unit_number" onKeyUp
="update_preview_icon()">
3146 $return_text .=<<p1;
3147 <div class="leftcol" style="">
3148 <label class="optional_field" for="cal_details">$lang{event_background_color}</label>
3150 <div class="rightcol" style="white-space:nowrap;width:40%;">
3151 <input name="dummy" value="" size=1 style="display:none;">
3152 <select name="evt_bgcolor" onchange="update_bg_color_select_box()" style="width:7em;">
3154 my $custom_color = 1;
3156 foreach $temp (@event_bgcolors) {
3157 %possible_bgcolor = %{$temp};
3159 if ($possible_bgcolor{color} eq "$event_bgcolor") { # default
3161 $selected = " selected";
3163 my $description = "";
3164 $description = $possible_bgcolor{title} if ($options{show_event_background_color_descriptions});
3166 $return_text .=<<p1;
3167 <option value
= "$possible_bgcolor{color}" $selected>$description
3171 my $color_select_icon_style="visibility:hidden;";
3172 if ($custom_color == 1 && $add_edit_event eq "edit") {
3173 $color_select_icon_style = "";
3174 $return_text .=<<p1;
3175 <option id="custom_evt_color" value = "$event_bgcolor" selected>$lang{event_background_colorcustom}
3178 $return_text .=<<p1;
3179 <option id
="custom_evt_color" value
= "#ffffff">$lang{event_background_colorcustom
}
3184 $return_text .=<<p1;
3186 <span id="color_select_icon0" class="color_select_icon" style="$color_select_icon_style vertical-align:top;background-image:url($graphics_url/color_select_icon.gif);" onClick="cs0.toggle_color_select();"> </span>
3189 <br style="clear:both;"/>
3190 <br style="clear:both;"/>
3196 <div id="tab_area1" class="info_box" style="width:100%;display:none;position:relative;z-index:101;padding-top:1em;text-align:left;">
3199 if ($add_edit_event eq "edit") {
3200 if ($current_event{series_id} ne "") {
3201 $return_text .=<<p1;
3202 <input type
="hidden" name
="recurring_event" value
="1">
3203 <input type
="hidden" name
="series_id" value
="$current_event{series_id}">
3205 <div style
="text-align:center;">
3206 $lang{recurring_event_edit1
}
3209 <div
class="leftcol" style
="margin-bottom:1em;">
3210 <span
class="small_note"><a href
="javascript:display_help('recurring_event_change_all','$lang{recurring_event_change_all1}')">$lang{help_on_this
}</a> </span
>
3212 <div
class="rightcol" style
="margin-bottom:1em;white-space:nowrap;">
3213 <input type
="checkbox" name
="all_in_series" value
="1" onClick
="recur_edit_toggle()">
3214 <label
class="optional_field">$lang{recurring_event_change_all1
}</label
>
3215 <div
class="small_note style="margin
-left
:17px
;"">$lang{recurring_event_change_all2
}</div
>
3219 $return_text .=<<p1;
3220 $lang{recurrence_not_allowed}
3223 $return_text .=<<p1;
3224 <br style
="clear:both;"/>
3228 $return_text .=<<p1;
3229 <div class="leftcol" style="margin-bottom:1em;">
3230 <span class="small_note"><a href="javascript:display_help('recurring_event','$lang{recurring_event}')">$lang{help_on_this}</a> </span>
3232 <div class="rightcol" style="margin-bottom:1em;white-space:nowrap;">
3233 <input type="checkbox" name="recurring_event" value="1" onclick="javascript:recur_toggle();">
3234 <label class="optional_field">$lang{recurring_event}</label>
3237 <div class="leftcol" style="margin-bottom:1em;vertical-align:middle;">
3238 <span class="fit_event">
3239 <i>$lang{recurrence_type}</i><br/>
3240 <span class="small_note"><a href="javascript:display_help('recurrence_type','$lang{recurrence_type}')">$lang{help_on_this}</a></span>
3243 <div class="rightcol" style="margin-bottom:1em;white-space:nowrap;">
3244 <input type="radio" name="recurrence_type" value="same_day_of_month" disabled checked onclick="recurrence_type_update()">
3245 <span class="optional_field">$lang{same_day_of_month}</span>
3247 <input type="radio" name="recurrence_type" value="same_day_of_week" disabled onclick="recurrence_type_update()">
3248 <span class="optional_field">
3251 <select name = "weekday_of_month_type" disabled>
3252 <option value = "every_week">$lang{on_every_week}
3253 <option value = "only_first_week">$lang{on_first_week}
3254 <option value = "only_second_week">$lang{on_second_week}
3255 <option value = "only_third_week">$lang{on_third_week}
3256 <option value = "only_fourth_week">$lang{on_fourth_week}
3257 <option value = "only_fifth_week">$lang{on_fifth_week}
3258 <option value = "only_last_week">$lang{on_last_week}
3259 </select> $lang{of_the_month}
3262 <span class="optional_field">
3266 <input name
= "every_x_days" disabled
/ value
="1" style
="width:2em;">
3268 $lang{every_x_days
} =~ s/###x###/$temp/;
3270 $return_text .=<<p1;
3271 <input type="radio" name="recurrence_type" value="every_x_days" disabled onclick="recurrence_type_update()">
3276 <span class="optional_field">
3279 <input name
= "every_x_weeks" disabled
/ value
="1" style
="width:2em;">
3281 $lang{every_x_weeks
} =~ s/###x###/$temp/;
3283 $return_text .=<<p1;
3284 <input type="radio" name="recurrence_type" value="every_x_weeks" disabled onclick="recurrence_type_update()">
3285 $lang{every_x_weeks}
3292 <div class="leftcol" style="">
3293 <span class="fit_event">
3294 <i>$lang{fit_into_year}</i><br/>
3295 <span class="small_note"><a href="javascript:display_help('fit_into_year','$lang{fit_into_year}')">$lang{help_on_this}</a></span>
3298 <div class="rightcol" style="white-space:nowrap;">
3299 <input type="radio" name="year_fit_type" value="every_month" checked disabled onclick="document.add_event_form.custom_months.disabled=true">
3300 <span class="optional_field">
3304 <div style="float:left;">
3305 <input type="radio" name="year_fit_type" value="custom_months" disabled onclick="document.add_event_form.custom_months.disabled=false">
3306 <span class="optional_field">$lang{certain_months1} </span>
3308 <span class="small_note">$lang{certain_months2}</span>
3311 <div style="float:left;">
3312 <select multiple name = "custom_months" size=4 disabled>
3315 for ($l1=0;$l1<scalar @months;$l1++) {
3316 $return_text .=<<p1;
3317 <option value
= $l1>$months[$l1]
3321 $return_text .=<<p1;
3327 <div class="leftcol" style="">
3328 <label class="required_field">$lang{recurring_event_ends}</label>
3330 <div class="rightcol" style="white-space:nowrap;">
3331 <input name="recur_end_date" size=12 value="$recur_end_date" disabled>
3334 <br style="clear:both;"/>
3338 $return_text .=<<p1;
3341 <div style
="margin-top:1em;margin-bottom:1em;float:left;width:48%;text-align:center;font-weight:bold;">
3342 <a href
="javascript:preview_event()">$lang{preview_event1
}</a
>
3343 <p
class="small_note active_tab_text">
3344 $lang{preview_event2
}
3348 <div style
="margin-top:1em;margin-bottom:1em;float:left;width:48%;text-align:center;font-weight:bold;">
3349 <a href
="javascript:preview_dates()">$lang{preview_dates1
}</a
>
3350 <p
class="small_note active_tab_text">
3351 $lang{preview_dates2
}
3355 <div
class="info_box" style
="clear:both;">
3357 my $need_password = 1;
3358 $need_password = 0 if ($options{disable_passwords
} eq "1");
3359 $need_password = 0 if ($logged_in_as_root || $logged_in_as_current_cal_admin || $logged_in_as_current_cal_user);
3361 if ($need_password == 1) {
3362 $return_text .=<<p1;
3363 <div class="leftcol" style="">
3364 <label class="required_field" for="cal_password">$lang{cal_password}</label>
3366 <div class="rightcol" style="white-space:nowrap;">
3367 <input type="password" id="cal_password" name="cal_password" style="width:30%;">
3368 <span class="small_note" style="vertical-align:top;" ><a href="javascript:display_help('cal_password','$lang{cal_password}')">$lang{help_on_this}</a> </span>
3372 $return_text .=<<p1;
3373 <div
class="leftcol">
3376 <div
class="rightcol" style
="white-space:nowrap;">
3377 $lang{no_password_needed
}
3385 if ($add_edit_event eq "edit") {
3386 $return_text .=<<p1;
3387 <div class="leftcol" style="">
3390 <div class="rightcol" style="white-space:nowrap;">
3391 <input name="add_event_button" type="submit" value = "$lang{update_event}">
3392 <div class="small_note">$lang{add_event2_update}</div>
3396 <div style="text-align:left;">
3397 <input name="del_event_button" class="delete_button" type="submit" value = "$lang{delete_event1}">
3398 <div class="small_note">$lang{delete_event2}</div>
3403 $return_text .=<<p1;
3404 <div
class="leftcol" style
="">
3407 <div
class="rightcol" style
="white-space:nowrap;">
3408 <input name
="add_event_button" type
="submit" value
= "$lang{add_event1}">
3410 <span id
="preview_note" class="small_note">
3415 <br style
="clear:both;"/>
3416 <br style
="clear:both;"/>
3419 $return_text .=<<p1;
3425 sub add_edit_events {
3426 $event_details_template =~ s/###export event link###/$lang{event_details_export_disable}/g;
3427 $event_details_template =~ s/###edit event link###/$lang{event_details_edit_disable}/g;
3428 $event_details_template =~ s/###email reminder link###/$lang{event_email_reminder_disable}/g;
3432 my $recurring_event = $q->param('recurring_event');
3433 my $all_in_series = $q->param('all_in_series');
3435 # load (reload) all events (we have to write events beyond the default time window)
3436 if ($options{data_storage_mode} == 0) {
3437 unless ($loaded_all_events eq "1") {
3438 &load_events("all");
3439 &normalize_timezone();
3443 my $login_valid = 0;
3445 if ($options{disable_passwords} eq "1") {
3447 } elsif ($current_cal_id ne "") {
3448 #$debug_info .= "current_cal_id: $current_cal_id\n";
3449 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
3450 $login_valid = 1 if ($logged_in_as_root || $logged_in_as_current_cal_admin || $logged_in_as_current_cal_user); # current calendar user
3451 } elsif ($options{multi_calendar_event_mode} == 2) { # any of the event's calendars' users or the root user are allowed
3452 if ($logged_in_as_root || $logged_in_as_current_cal_admin || $logged_in_as_current_cal_user) { # current calendar user
3455 my $cal_password_valid = 0;
3456 foreach $cal_id (@evt_other_cal_ids) {
3458 $cal_password_valid = 1 if ($profile->{calendar_permissions}->{$cal_id}->{admin} eq "1"); # shared calendar admin
3459 $cal_password_valid = 1 if ($profile->{calendar_permissions}->{$cal_id}->{user} ne ""); # shared calendar user
3461 $login_valid = 1 if ($cal_password_valid == 1);
3468 if ($q->param('del_event_button') ne "" || $api_command eq "delete_event") {
3469 $del_valid = 1; #delete event.
3471 if ($login_valid == 0) {
3473 push @{$results{messages}}, "[error]$lang{update_event_err1} '$current_calendar{title}'";
3476 if (!defined $events{$current_event_id}) {
3478 push @{$results{messages}}, "[error]$lang{update_event_err2}";
3481 if ($del_valid == 1) { #actually delete the event(s).
3482 if ($all_in_series ne "1") {
3483 my $subj = $lang{notify_subj};
3484 $subj =~ s/\$1/$script_url\/$name/;
3486 my $body = $lang{event_delete_notify};
3487 $body =~ s/\$1/$events{$current_event_id}{title}/;
3488 $body =~ s/\$2/$calendars{$current_cal_id}{title}/;
3490 foreach $email (@{$current_calendar{delete_emails}}) {
3491 #$debug_info .= "email notification sent to $email\n";
3492 &send_email($email, $options{reply_address}, $options{reply_address}, $subj, $body) if ($options{email_mode} > 0);
3495 &delete_event($current_event_id);
3496 push @{$results{messages}}, "[status]$lang{update_event_delete_successful}";
3499 # get the ids of the events in the series.
3500 my @events_in_series = &get_events_in_series($q->param('series_id'));
3501 &normalize_timezone();
3502 &delete_events(\@events_in_series);
3503 push @{$results{messages}}, "[status]$lang{update_event_delete_successful_recurring}";
3505 $results{success} = 1;
3507 $results{success} = 0;
3509 } else { # not a delete
3510 if (!$login_valid) {
3511 if ($options{anonymous_events}) {
3512 my $temp = $lang{update_event_err16};
3513 $temp =~ s/###calendar###/<b>$current_calendar{title}<\/b>/g;
3514 push @{$results{messages}}, ("[error]".$temp);
3516 push @{$results{messages}}, "[error]".($lang{update_event_err1}."'".$current_calendar{title}."'");
3520 #check all input fields for validity
3521 my $event_valid = 1;
3522 my $event_id = $q->param('evt_id'); # only if editing.
3523 #my $event_cal_id = $current_cal_id;
3525 my @evt_other_cal_ids;
3526 @evt_other_cal_ids = $q->param('evt_other_cal_ids') if ($options{multi_calendar_event_mode} > 0);
3528 my $event_cal_password = $q->param('cal_password');
3529 my $event_title = $q->param('evt_title');
3530 my $event_icon = $q->param('evt_icon');
3531 my $event_details = $q->param('evt_details');
3532 my $event_unit_number = $q->param('unit_number');
3533 my $event_bgcolor = $q->param('evt_bgcolor');
3534 my $event_block_merge = $q->param('evt_block_merge');
3535 my $event_series_id = $q->param('series_id');
3537 my $event_duration = 0;
3538 my $event_start_timestamp = 0;
3539 my $event_end_timestamp = 0;
3541 $recur_end_date = $q->param('recur_end_date');
3542 my $all_day_event = $q->param('all_day_event');
3543 my $no_end_time = "";
3544 my $event_start_time = $q->param('evt_start_time');
3545 my $event_end_time = $q->param('evt_end_time');
3546 $event_start_date = $q->param('evt_start_date');
3547 my $event_days = $q->param('evt_days');
3549 my %recurrence_parms;
3550 $recurrence_parms{'recurrence_type'} = $q->param('recurrence_type');
3551 $recurrence_parms{'weekday_of_month_type'} = $q->param('weekday_of_month_type');
3552 $recurrence_parms{'every_x_days'} = $q->param('every_x_days');
3553 $recurrence_parms{'every_x_weeks'} = $q->param('every_x_weeks');
3554 $recurrence_parms{'year_fit_type'} = $q->param('year_fit_type');
3555 $recurrence_parms{'recur_end_date'} = $q->param('recur_end_date');
3556 my @custom_months = $q->param('custom_months');
3557 $recurrence_parms{'custom_months'} = \@custom_months;
3558 $recurrence_parms{'recur_end_timestamp'} = 0;
3560 my %input_parms; # parms that are input by the user, but not stored as final event data
3561 $input_parms{'update_all_in_series'} = $q->param('all_in_series');
3562 $input_parms{'event_days'} = $event_days;
3563 $input_parms{'event_start_time'} = $event_start_time;
3564 $input_parms{'event_end_time'} = $event_end_time;
3565 $input_parms{'all_day'} = $all_day_event;
3567 # Check data for legitimacy.
3568 # some of these checks might be a bit redundant.
3569 if ($current_cal_id eq "") {
3571 push @{$results{messages}}, "[error]".$lang{update_event_err3};
3573 if ($event_title eq "") {
3575 push @{$results{messages}}, "[error]".$lang{update_event_err4};
3577 if ($event_icon eq "") {
3579 push @{$results{messages}}, "[error]".$lang{update_event_err5};
3582 $event_title =~ s/\r//g; # some browsers sneak these in
3583 $event_details =~ s/\r//g; # some browsers sneak these in
3586 if ($event_title =~ m/<(.*)>/) {
3587 my $temp = $event_title;
3588 $temp =~ s/</</g;
3589 $temp =~ s/>/>/g;
3590 push @{$results{messages}}, "[warning]".$lang{update_event_err7};
3591 $event_title =~ s/<(.*)>//g;
3594 # strip out all non-numeric information from unit number
3595 my $unit_number = $event_unit_number;
3596 $unit_number =~ s/\D//g;
3598 #check event calendar name against existing calendars
3599 if (!defined == $calendars{$current_cal_id}) {
3601 push @{$results{messages}}, "[error]".$lang{update_event_err8};
3604 $event_valid = 0 if ($login_valid == 0 && !$options{anonymous_events});
3606 #push @{$results{messages}}, "[error]".$lang{update_event_err1}."'".$current_calendar{title}."'";
3609 if ($event_valid == 1) {
3610 my $verify_date_results = &verify_date($event_start_date);
3611 if ($verify_date_results ne "") {
3613 my @sub_results = split("\n", $verify_date_results);
3614 foreach $sub_result (@sub_results) {
3615 push @{$results{messages}}, "[error]$lang{update_event_err9} $sub_result";
3618 if ($event_days eq "") {
3619 push @{$results{messages}}, "[error]$lang{update_event_err9}$lang{date_verify_err2}";
3622 if ($event_days =~ m/\D/ || $event_days <= 0) {
3623 my $temp = $lang{date_verify_err3};
3624 $temp =~ s/\$1/$event_days/;
3625 push @{$results{messages}}, "[error]$lang{update_event_err9}$temp";
3630 # check recurring "repeat until" date
3631 if ($event_valid == 1) {
3632 if ($recurring_event ne "" && $add_edit_event eq "add") {
3633 my $verify_date_results = &verify_date($recurrence_parms{'recur_end_date'}, \%recurrence_parms);
3634 if ($verify_date_results ne "") {
3636 my @sub_results = split("\n", $verify_date_results);
3637 foreach $sub_result (@sub_results) {
3638 push @{$results{messages}}, "[error]$lang{update_event_err10} $sub_result";
3645 if ($event_valid == 1 && $all_day_event ne "1") {
3646 my $verify_time_results = &verify_time($event_start_time);
3647 if ($verify_time_results ne "") {
3649 my @sub_results = split("\n", $verify_time_results);
3650 foreach $sub_result (@sub_results) {
3651 push @{$results{messages}}, "[error]$lang{update_event_err14} $sub_result";
3655 if ($event_end_time ne "") {
3656 my $verify_time_results = &verify_time($event_end_time);
3657 if ($verify_time_results ne "") {
3659 my @sub_results = split("\n", $verify_time_results);
3660 foreach $sub_result (@sub_results) {
3661 push @{$results{messages}}, "[error]$lang{update_event_err15} $sub_result";
3667 if ($event_valid == 1) {
3668 my ($start_mon, $start_mday, $start_year) = &format2mdy($event_start_date, $current_calendar{date_format});
3669 $start_mon--; # convert month to 0-11 format
3671 ($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);
3673 $event_end_timestamp +=1 if ($event_start_timestamp == $event_end_timestamp); # give all events a duration of at least 1 second
3675 $event_duration = $event_end_timestamp - $event_start_timestamp;
3676 $no_end_time = 1 if ($event_duration == 1);
3678 $recurrence_parms{'duration'} = $event_duration if ($recurring_event ne "");
3680 if ($recurring_event ne "" && $add_edit_event eq "add") {
3681 my ($recur_end_mon, $recur_end_mday, $recur_end_year) = &format2mdy($recurrence_parms{'recur_end_date'}, $current_calendar{date_format});
3683 $recurrence_parms{'recur_end_timestamp'} = timegm(0,0,0,$recur_end_mday,$recur_end_mon,$recur_end_year);
3686 # display warning if start timestamp is before present date
3687 if ($event_start_timestamp < $rightnow-86400) {
3688 push @{$results{messages}}, "[warning]$lang{update_event_err11}";
3692 # check for refreshes!
3693 if ($recurring_event eq "") {
3694 my %latest_event = $events{$latest_event_id};
3696 if ($latest_event{cal_ids}[0] eq $current_cal_id &&
3697 $latest_event{start} eq $event_start_timestamp &&
3698 $latest_event{end} eq $event_end_timestamp &&
3699 $latest_event{title} eq $event_title &&
3700 $latest_event{details} eq $event_details &&
3701 $latest_event{icon} eq $event_icon &&
3702 $latest_event{bgcolor} eq $event_bgcolor &&
3703 $latest_event{unit_number} eq $event_unit_number) {
3705 push @{$results{messages}}, "[error]$lang{update_event_err12}";
3707 } else { # recurring event refresh protection is a little trickier.
3708 # it's currently not implemented
3711 if ($add_edit_event eq "edit") {
3712 #check to make sure the event id matches some event in the data structure. It always should, but we check anyway.
3713 if (!defined $events{$event_id}) {
3715 push @{$results{messages}}, "[error]$lang{update_event_err13}";
3719 # properly format errors & warnings
3720 $message_results="";
3722 if ($event_valid == 1) {
3723 $results{successful} = 1;
3724 #$debug_info .= "(add_update_event) event_id: $event_id\n";
3725 unshift @evt_other_cal_ids, $current_cal_id;
3727 my %new_event = (recurring => $recurring_event,
3728 cal_ids => \@evt_other_cal_ids,
3729 start => $event_start_timestamp,
3730 end => $event_end_timestamp,
3731 all_day_event => $all_day_event,
3732 days => &calculate_event_days($event_start_timestamp, $event_end_timestamp),
3733 title => $event_title,
3734 details => $event_details,
3735 icon => $event_icon,
3736 bgcolor => $event_bgcolor,
3737 block_merge => $event_block_merge,
3738 unit_number => $event_unit_number,
3739 update_timestamp => $rightnow,
3740 existing_id => $event_id,
3741 recurrence_parms => \%recurrence_parms);
3744 $results{text} .= &commit_event(\%new_event, \%input_parms);
3745 } elsif ($options{anonymous_events}) { # anonymous event -> update queue
3746 my $new_event_id = $max_action_id + int(rand(100)); # just in case several people decide to add something new at the same time.
3747 $new_event{id} = $new_event_id;
3748 #$debug_info .= "(add_edit_events) event cal id: $event_cal_id\n";
3749 # add event to %events data structure
3750 $new_events{$new_event_id} = \%new_event;
3753 if ($options{email_mode} > 0) {
3754 my $subj = $lang{notify_subj};
3755 $subj =~ s/\$1/$script_url\/$name/;
3757 my $body = $lang{event_pending_notify};
3758 $body =~ s/\$1/$events{$current_event_id}{title}/;
3759 $body =~ s/\$2/$calendars{$current_cal_id}{title}/;
3760 $body =~ s/\$3/$script_url\/$name?view_pending_event=1&pending_event_id=$new_event_id/;
3762 foreach $add_email (@{$current_calendar{add_emails}}) {
3763 push @{$results{messages}}, "[status]email notification sent to $add_email";
3764 &send_email($add_email, $options{reply_address}, $options{reply_address}, $subj, $body);
3768 &add_action($new_event_id, "new_event");
3769 $event_box_text .= &generate_event_details(\%new_event);
3771 $results{text} .= <<p1;
3772 <p style
="font-weight:bold;">$lang{update_event_add_pending_successful
}</p
>
3775 <li
><a href
="$script_url/$name?active_tab=1">$lang{update_event_add_successful_add_new
}</a
></li
>
3784 } #******************** end add_edit_event *****************************
3787 sub commit_event
() { # commit an add or update of an event
3788 my ($new_event_ref, $input_parms_ref) = @_;
3793 my %new_event = %{$new_event_ref};
3794 my %input_parms = %{$input_parms_ref};
3796 unless ($loaded_all_events eq "1") {
3797 &load_events
("all");
3798 &normalize_timezone
();
3801 if ($add_edit_event eq "add") { # add a new event
3802 if ($new_event{'recurring'} eq "") {
3803 my $event_box_text = "";
3804 $new_event_id = ++$max_event_id;
3806 $events{$new_event_id} = deep_copy
(\
%new_event);
3807 $events{$new_event_id}{id
} = $new_event_id;
3809 &add_event
($new_event_id);
3810 $event_box_text .= &generate_event_details
($events{$new_event_id});
3812 #temporarily offset event times by calendar gmtime diff
3815 <p style
="font-weight:bold;">$lang{update_event_add_successful
}</p
>
3818 <li
><a href
="$script_url/$name?active_tab=1">$lang{update_event_add_successful_add_new
}</a
></li
>
3821 } else { # recurring events loop
3822 #$debug_info .= "in commit_event recurring events loop!\n";
3823 my %recurrence_parms = %{$new_event{'recurrence_parms'}};
3825 my $new_series_id = ++$max_series_id;
3829 my @recurring_events_timestamps = @
{&calculate_recurring_events
($new_event{'start'}, \
%recurrence_parms)};
3831 my @recurring_event_ids = ();
3832 foreach $recurring_event_start_timestamp (@recurring_events_timestamps) {
3833 my $new_event_id = ++$max_event_id;
3834 my $recurring_event_end_timestamp = $recurring_event_start_timestamp + $recurrence_parms{'duration'};
3836 $events{$new_event_id} = deep_copy
(\
%new_event);
3837 $events{$new_event_id}{id
} = $new_event_id;
3838 $events{$new_event_id}{series_id
} = $new_series_id;
3839 $events{$new_event_id}{start
} = $recurring_event_start_timestamp;
3840 $events{$new_event_id}{end
} = $recurring_event_end_timestamp;
3841 $events{$new_event_id}{recurrence_parms
} = [];
3843 push @recurring_event_ids, $new_event_id;
3845 my $date_range = &nice_date_range_format
($recurring_event_start_timestamp, $recurring_event_end_timestamp, "-");
3848 <li>$date_range</li>
3852 &add_events(\@recurring_event_ids);
3854 $event_box_text .= &generate_event_details($events{$max_event_id});
3857 <p style
="font-weight:bold;">$lang{update_event_add_successful_recurring
}</p
>
3863 <li
><a href
="$script_url/$name?active_tab=1">$lang{update_event_add_successful_add_new
}</a
></li
>
3864 <li
><a href
="$script_url/$name?active_tab=0">$lang{update_event_back_to_calendar
}</a
></li
>
3868 if ($options{email_mode
} > 0) {
3869 my $subj = $lang{notify_subj
};
3870 $subj =~ s/\$1/$script_url\/$name/;
3872 my $body = $lang{event_add_notify
};
3873 $body =~ s/\$1/$new_event{title}/;
3874 $body =~ s/\$2/$calendars{$current_cal_id}{title}/;
3875 $body =~ s/\$3/$script_url\/$name?view_event
=1&evt_id
=$max_event_id/;
3877 foreach $add_email (@
{$current_calendar{add_emails
}}) {
3878 push @
{$results{messages
}}, "[status]email notification sent to $add_email";
3879 &send_email
($add_email, $options{reply_address
}, $options{reply_address
}, $subj, $body);
3882 } elsif ($add_edit_event eq "edit") { #if we need to replace an existing record
3883 my $event_id = $new_event{'existing_id'};
3885 if ($new_event{'recurring'} eq "" || $input_parms{'update_all_in_series'} ne "1") {
3886 $events{$event_id} = deep_copy
(\
%new_event);
3887 $events{$event_id}{id
} = $event_id;
3889 &update_event
($event_id);
3891 $event_box_text .= &generate_event_details
($events{$event_id});
3894 <p style
="font-weight:bold;">$lang{update_event_update_successful
}</p
>
3896 } else { # update recurring events
3897 # get the ids of the events in the series.
3898 my @events_in_series;
3899 foreach $event_id (keys %events) {
3900 my %event = %{$events{$event_id}};
3901 my $series_id = $event{series_id
};
3902 if ($series_id eq $q->param('series_id')) {
3903 push @events_in_series, $event_id;
3904 my @temp = gmtime($event{end
});
3906 ($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'});
3908 $events{$event_id} = deep_copy
(\
%new_event);
3909 $events{$event_id}{id
} = $event_id;
3910 $events{$event_id}{series_id
} = $series_id;
3911 $events{$event_id}{start
} = $recurring_event_start_timestamp;
3912 $events{$event_id}{end
} = $recurring_event_end_timestamp;
3913 $events{$event_id}{recurrence_parms
} = [];
3916 &update_events
(\
@events_in_series);
3919 <p style
="font-weight:bold;">$lang{update_event_update_successful_recurring
}</p
>
3923 if ($options{email_mode
} > 0) {
3924 my $subj = $lang{notify_subj
};
3925 $subj =~ s/\$1/$script_url\/$name/;
3928 $body = $lang{event_update_notify
};
3929 $body =~ s/\$1/$new_event{title}/;
3930 $body =~ s/\$2/$calendars{$current_cal_id}{title}/;
3931 $body =~ s/\$3/$script_url\/$name?view_event
=1&evt_id
=$event_id/;
3933 foreach $email (@
{$current_calendar{update_emails
}}) {
3934 $debug_info .= "email notification sent to $email\n";
3935 &send_email
($email, $options{reply_address
}, $options{reply_address
}, $subj, $body);
3947 sub common_javascript
{
3948 my $logged_in_boolean = ($logged_in) ?
"true":"false";
3949 my $date_format = lc $current_calendar{date_format
};
3950 $return_string .=<<p1;
3951 info_window_width = $info_window_width;
3952 info_window_height = $info_window_height;
3954 plans_url = '$script_url/$name';
3955 theme_url = '$theme_url';
3956 css_path = '$css_path';
3957 date_format = '$date_format';
3958 current_calendar_id = '$current_calendar{id}';
3959 logged_in = $logged_in_boolean;
3961 if (window.name == "")
3962 window.name="cal_mainwindow";
3964 var main_window_name = window.name
3966 plans_options['right_click_menus_enabled'] = $options{right_click_menus_enabled};
3967 plans_options['disable_passwords'] = $options{disable_passwords};
3968 plans_options['sessions'] = $options{sessions};
3971 return $return_string;
3972 } #********************end common_javascript **********************
3975 sub calendar_view_javascript {
3976 my ($events_start_timestamp, $events_end_timestamp) = @_;
3977 my $return_string="";
3979 # generate pre-formatted html for each event details pop-up on the
3980 # current calendar. This routine is a good example of one of the choices
3981 # made in the design of this site--gaining client-side processor cycles
3982 # at the expense of bandwidth. It would be possible to send the event details
3983 # in a javascript array or hash, and have the client's browser dynamically
3984 # genearate the appropriate html. But it should be much faster to perform
3985 # this operation on the server and simply ship html to the client. The idea is
3986 # to make the javascript processing as simple as possible, becuase javascript
3987 # is sloooow. And even with all that extra html text, each page should still be
3988 # less than 100k (not counting images)
3990 #generate pre-formatted html for each event view
3991 $return_string .= &generate_event_details_javascript($events_start_timestamp, $events_end_timestamp);
3994 $return_string .=<<p1;
3996 function custom_calendar
() {
3998 var info_window_x
= window_x
()-400;
3999 var info_window_y
= window_y
();
4002 $custom_form_text .=<<p1;
4003 <div class="cal_title">
4004 $lang{custom_calendar_title}
4007 <form action="$script_url/$name" method="POST">
4008 <input type="hidden" name="custom_calendar" value="1">
4010 <label for="custom_calendar_calendar" class="required_field">
4011 $lang{custom_calendar_choose_calendar}
4014 <select id="custom_calendar_calendar" name="custom_calendar_calendar">
4017 foreach $cal_id (sort {$a <=> $b} keys %calendars) {
4018 $custom_form_text .=<<p1;
4019 <option value
= "$cal_id">$calendars{$cal_id}{title
}
4023 $custom_form_text .=<<p1;
4026 <label for="custom_calendar_background_calendars" class="optional_field">
4027 $lang{custom_calendar_choose_bg_calendar}
4031 <select id="custom_calendar_background_calendars" name="custom_calendar_background_calendars" multiple size=6>
4034 foreach $cal_id (sort {$a <=> $b} keys %calendars) {
4035 $custom_form_text .=<<p1;
4036 <option value
= "$cal_id">$calendars{$cal_id}{title
}
4040 $custom_form_text .=<<p1;
4045 if ($display_type == 1) {$list_selected = "selected";} else {$cal_selected = "selected";}
4047 $custom_form_text .=<<p1;
4048 <label
for="display_type" class="required_field">
4049 $lang{custom_calendar_display_type
}
4051 <select name
="display_type" onChange
="blink('controls_submit_button', 3, 0);">
4054 #foreach $possible_display_type (@{$options{display_types}})
4055 for (my $l1=0;$l1<scalar @
{$options{display_types
}};$l1++) {
4056 if ($options{display_types
}[$l1] ne "1") {
4060 if ($l1 eq $display_type) {
4061 $selected = "selected";}
4063 $custom_form_text .=<<p1;
4064 <option value="$l1" $selected>$lang{controls_display_type}[$l1]
4067 $custom_form_text .=<<p1;
4071 <label
for="cal_start_month" class="required_field">
4072 $lang{custom_calendar_time_range
}
4075 <table
class="layout" summary
="">
4076 <tr
><td nowrap align
=right
>
4078 $lang{controls_start_month
}
4080 <select id
="cal_start_month" name
="cal_start_month">
4082 #list each month in the year
4084 foreach $possible_month (@months) {
4085 if ($cal_start_month eq $month_index) {
4086 $custom_form_text .=<<p1;
4087 <option value="$month_index" selected>$possible_month
4090 $custom_form_text .=<<p1;
4091 <option value
="$month_index">$possible_month
4096 $custom_form_text .=<<p1;
4098 <input name="cal_start_year" value = "$cal_start_year" size=4>
4100 <tr><td nowrap align=left colspan=2>
4102 $lang{controls_num_months}
4103 <input name="cal_num_months" value = "$cal_num_months" size=3>
4109 <input type=submit value = "$lang{custom_calendar_make_calendar}">
4111 $custom_form_text =~ s/\//\\\//g;
4112 $custom_form_text =~ s/\n/\\n/g;
4113 $custom_form_text =~ s/"/\\"/g;
4115 $return_string .=<<p1;
4116 info_window
= this
.open("", "info_window", "resizable=yes,status=yes,scrollbars=yes,top="+info_window_y
+",left="+info_window_x
+",width=400,height=500");
4117 doc
= info_window
.document
;
4118 doc
.open('text/html');
4119 doc
.write('<html>');
4120 doc
.write('<title>$lang{custom_calendar_title}<\\/title>');
4121 doc
.write('<base target=\\"'+main_window_name
+'\\">');
4122 doc
.write('<link rel=\\"stylesheet\\" href=\\"$css_path\\" type=\\"text/css\\" media=screen>');
4123 doc
.write('<body>');
4124 doc
.write("$custom_form_text");
4125 doc
.write('<\\/body><\\/html>');
4127 info_window
.focus
();
4131 return $return_string;
4132 } #***********************end calendar_view_javascript************************"
4138 sub add_edit_events_javascript
{
4141 $return_string.=<<p1;
4142 var info_window_x = window_x()-$info_window_width;
4143 var info_window_y = window_y();
4145 // color select stuff
4148 function color_menu0_update(new_color) {
4149 //window.status = "updating! " + new_color;
4150 document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.options.length-1].value = new_color;
4151 document.add_event_form.evt_bgcolor.style.background = new_color;
4152 document.add_event_form.evt_bgcolor.style.color = compatible_textcolor(new_color);
4153 document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.options.length-1].style.color = compatible_textcolor(new_color);
4155 document.getElementById("custom_evt_color").style.background = new_color;
4158 function do_on_load() {
4159 if (!document.add_event_form || !document.add_event_form.evt_bgcolor)
4162 // color select control
4163 cs0 = new color_select('cs0',document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.selectedIndex].value);
4165 cs0.change_update_function = "color_menu0_update"; // NOTE-there are no ()
4166 cs0.hide_update_function = "color_menu0_update"; // NOTE-there are no ()
4167 cs0.attach_to_element(document.getElementById("color_select_icon0"));
4168 cs0.setrgb("$current_event{bgcolor}");
4169 cs0.update_color_box();
4171 for (i=0; i<document.add_event_form.evt_bgcolor.options.length; i++) {
4172 document.add_event_form.evt_bgcolor[i].style.background = document.add_event_form.evt_bgcolor[i].value;
4173 document.add_event_form.evt_bgcolor[i].style.color = compatible_textcolor(document.add_event_form.evt_bgcolor[i].value);
4176 // for some reason, calling this immediately doesn't always work - even if it's called after the page is loaded.
4177 // so, a 200 ms delay.
4178 setTimeout('update_bg_color_select_box()', 200);
4183 function update_bg_color_select_box() {
4184 var add_event_form = document.getElementById("add_event_form");
4186 // did the user just select custom?
4187 if (document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.selectedIndex].text == "custom")
4188 document.getElementById("color_select_icon0").style.visibility = "visible";
4190 document.getElementById("color_select_icon0").style.visibility = "hidden";
4192 // 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)
4193 document.add_event_form.dummy.style.display='inline';
4194 document.add_event_form.dummy.select();
4195 document.add_event_form.dummy.style.display='none';
4197 //if (!add_event_form.evt_bgcolor)
4200 //alert(add_event_form.evt_bgcolor[add_event_form.evt_bgcolor.selectedIndex].value);
4202 add_event_form.evt_bgcolor.style.background = add_event_form.evt_bgcolor[add_event_form.evt_bgcolor.selectedIndex].value
4203 //document.add_event_form.evt_title.select();
4205 add_event_form.evt_bgcolor.style.color = compatible_textcolor(add_event_form.evt_bgcolor[add_event_form.evt_bgcolor.selectedIndex].value);
4209 function update_preview_icon() {
4210 var icon_preview_area = document.getElementById("icon_preview")
4212 icon_name = document.add_event_form.evt_icon.options[document.add_event_form.evt_icon.selectedIndex].value
4213 icon_preview_area.innerHTML = "<img src=\\"$icons_url/" + icon_name + "_32x32.gif\\" border=\\"0\\" vspace=0 hspace=0>"
4215 if (!document.add_event_form.unit_number)
4218 var unit_number_preview_area = document.getElementById("unit_number_preview")
4220 // remove non-numeric text from the string
4221 var unit_number = document.add_event_form.unit_number.value;
4222 unit_number = unit_number.replace(/[^0-9]/g, "");
4224 // this next part might be really clever or really stupid (using a regex for something like this).
4225 // regardless, it's only one line, and that's nice.
4226 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>");
4227 unit_number_preview_area.innerHTML = unit_number_graphic_string;
4228 document.add_event_form.unit_number.value = unit_number;
4230 // it would be nice if we could do things with the DOM model, as opposed to innerHTML, but
4231 // that would be crazy cumbersome. The following is a non-working stab at it. Maybe useful someday.
4232 //preview_area.nodeValue = "unit num";
4233 //preview_area.appendChild(document.createTextNode("unit <img name=\\"event_icon\\" src=\\"$icons_url/eagle_medal_32x32.gif\\" border=\\"0\\" vspace=0 hspace=0>"));
4238 function all_day_event_toggle(value) {
4239 var el0 = document.getElementById("all_day_event_toggle0");
4240 el0.style.display="";
4243 el0.style.display="none";
4247 function preview_event() {
4248 info_window = this.open("", "info_window", "resizable=yes,status=yes,scrollbars=yes,width=300,height=200");
4249 doc = info_window.document;
4250 doc.open('text/html');
4251 doc.write('<html>');
4252 doc.write('<title>$lang{event_preview_title}<\\/title>');
4253 doc.write('<body bgcolor=\\"#ffffff\\" style=\\"font-family:arial,helvetica\\">');
4254 doc.write('<font size=5><font color=\\"0049df\\">$lang{generating_preview}<\\/font>');
4255 doc.write('<\\/body><\\/html>');
4258 document.add_event_form.special_action.value = "preview_event";
4259 document.add_event_form.target = "info_window";
4260 document.add_event_form.submit();
4261 document.add_event_form.special_action.value = "";
4262 document.add_event_form.target = "";
4264 info_window.focus();
4268 function recur_edit_toggle() {
4269 if (document.add_event_form.all_in_series.checked) {
4270 document.add_event_form.add_event_button.value="$lang{recurring_event_update_all1}";
4271 document.add_event_form.del_event_button.value="$lang{recurring_event_delete_all1}";
4273 document.add_event_form.add_event_button.value="$lang{update_event}";
4274 document.add_event_form.del_event_button.value="$lang{delete_event1}";
4279 function preview_dates() {
4282 var info_window_x = window_x()-$info_window_width;
4283 var info_window_y = window_y();
4285 var evt_start_date = document.add_event_form.evt_start_date.value;
4286 var evt_days = document.add_event_form.evt_days.value;
4287 var evt_start_time = document.add_event_form.evt_start_time.value;
4288 var evt_end_time = document.add_event_form.evt_end_time.value;;
4289 var recurring_event = "";
4293 var recurrence_type = "";
4294 var year_fit_type = "";
4295 var weekday_of_month_type = "";
4296 var custom_months_string = "";
4298 if (document.add_event_form.recur_end_date) {
4299 every_x_days = document.add_event_form.every_x_days.value;
4300 every_x_weeks = document.add_event_form.every_x_weeks.value;
4301 recur_end_date = document.add_event_form.recur_end_date.value;
4303 if (document.add_event_form.recurring_event.checked)
4304 recurring_event = document.add_event_form.recurring_event.value;
4306 for (i=0; i<document.add_event_form.recurrence_type.length; i++)
4307 if (document.add_event_form.recurrence_type[i].checked)
4308 recurrence_type = document.add_event_form.recurrence_type[i].value;
4310 for (i=0; i<document.add_event_form.year_fit_type.length; i++)
4311 if (document.add_event_form.year_fit_type[i].checked)
4312 year_fit_type = document.add_event_form.year_fit_type[i].value;
4314 if (document.add_event_form.weekday_of_month_type.selectedIndex > -1)
4315 weekday_of_month_type = document.add_event_form.weekday_of_month_type.options[document.add_event_form.weekday_of_month_type.selectedIndex].value
4317 var selects = new Array();
4318 var custom_months = "";
4320 if (document.add_event_form.custom_months.selectedIndex > -1)
4321 for (j=0, i=document.add_event_form.custom_months.selectedIndex; i<document.add_event_form.custom_months.options.length;i++)
4322 if (document.add_event_form.custom_months.options[i].selected)
4323 custom_months_string +="&custom_months="+document.add_event_form.custom_months.options[i].value;
4327 var URL_string="$script_url/$name?special_action=preview_date&evt_start_date="+evt_start_date+
4328 "&cal_id="+document.add_event_form.cal_id.value+
4329 "&recur_end_date="+recur_end_date+
4330 "&recurring_event="+recurring_event+
4331 "&recurrence_type="+recurrence_type+
4332 "&year_fit_type="+year_fit_type+
4333 "&every_x_days="+every_x_days+
4334 "&every_x_weeks="+every_x_weeks+
4335 "&evt_start_time="+evt_start_time+
4336 "&evt_start_time="+evt_start_time+
4337 "&weekday_of_month_type="+weekday_of_month_type+
4338 custom_months_string+
4339 "&evt_days="+evt_days;
4341 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");
4342 doc = info_window.document;
4343 doc.open('text/html');
4344 doc.write('<html>');
4345 doc.write('<head>');
4346 doc.write('<title>$lang{event_preview_computing}<\\/title>');
4347 doc.write('<link rel=\\"stylesheet\\" href=\\"$css_path\\" type=\\"text/css\\" media=screen>');
4348 doc.write('<\\/head>');
4349 doc.write('<body style=\\"font-family:arial;\\">');
4350 doc.write('$lang{event_preview_computing}');
4351 doc.write('<\\/body><\\/html>');
4354 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");
4355 info_window.focus();
4360 my @help_text_map = ("evt_cal_id",
4368 "recurring_event_change_all");
4370 my $help_text_javascript = "";
4371 foreach $key (@help_text_map) {
4373 <div
class="help_box">
4377 $help_text =~ s/\n/\\n/g;
4378 $help_text =~ s/"/\\"/g;
4379 $help_text =~ s/'/\\'/g;
4380 $help_text =~ s/\//\\\
//g;
4383 $help_text_javascript .=<<p1;
4384 if (topic == "$key")
4385 help_text += "$help_text";
4390 $return_string .=<<p1;
4391 function display_help
(topic
, title
) {
4393 $help_text_javascript
4394 if (help_text
!= "") {
4395 help_text
= "<div class=\\"help_title
\\">$lang{help_box_title} - "+title
+"</div>" + help_text
;
4402 return $return_string
4403 } #********************end add_edit_events_javascript**********************
4408 sub generate_users_javascript
() {
4411 foreach $user_id (keys %users) {
4412 my $valid_for_current_calendar = 0;
4414 foreach $cal_id (keys %{$users{$user_id}{calendars
}}) {
4415 if ($cal_id eq $current_cal_id) {
4416 $valid_for_current_calendar = 1;
4421 next if ($valid_for_current_calendar == 0);
4422 #next if ($user_id eq "");
4424 my %user = %{$users{$user_id}};
4426 users['$user_id'] = new User('$user_id','$user{name}');
4432 sub generate_pending_events_javascript() {
4434 foreach $pending_event_id (sort {$new_events{$a}{update_timestamp} <=> $new_events{$b}{update_timestamp}} @pending_events_to_display) {
4435 my %pending_event = %{$new_events{$pending_event_id}};
4436 my $title = $pending_event{title};
4437 $title = &javascript_cleanup($title);
4440 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
}});
4443 return $results."\n";
4448 sub add_edit_calendars_javascript
{
4449 my $return_string = "";
4451 $return_string .= &generate_users_javascript
($current_calendar{id
});
4453 $return_string.=<<p1;
4454 // override generic do_on_load method from plans.js
4455 function do_on_load() {
4456 update_remote_calendar_requests();
4457 update_cal_color_select_box();
4460 if (document.getElementById("color_select_icon0")) {
4461 // color select controls
4462 cs0 = new color_select('cs0');
4463 cs0.change_update_function = "color_menu0_update"; // NOTE-there are no ()
4464 cs0.hide_update_function = "color_menu0_update"; // NOTE-there are no ()
4465 cs0.attach_to_element(document.getElementById("color_select_icon0"));
4466 cs0.setrgb("$current_event{bgcolor}");
4467 cs0.update_color_box();
4469 cs1 = new color_select('cs1');
4470 cs1.change_update_function = "color_menu1_update"; // NOTE-there are no ()
4471 cs1.hide_update_function = "color_menu1_update"; // NOTE-there are no ()
4472 cs1.attach_to_element(document.getElementById("color_select_icon1"));
4473 cs1.setrgb("$current_event{bgcolor}");
4474 cs1.update_color_box();
4479 function update_users() {
4480 if (!users || users.length == 0) return;
4485 function set_merge_xml(merge_xml) {
4486 var results = merge_xml.match(/\\/remote_calendar>/g);
4487 //var num_merged_calendars = results.length;
4490 if (results.length > 1)
4491 document.getElementById("remote_background_calendars_status").innerHTML = results.length + " $lang{get_remote_calendar2_plural} $current_calendar{title}<br/>"; else
4492 document.getElementById("remote_background_calendars_status").innerHTML = results.length + " $lang{get_remote_calendar2_singular} $current_calendar{title}<br/>";
4494 document.getElementById("remote_background_calendars_status").innerHTML = "$lang{get_remote_calendar3}";
4496 //for(var i =0; i < results.length; i++)
4497 // document.getElementById("remote_background_calendars_status").innerHTML +="calendar "+i+"<br/>";
4500 document.update_cal_form.new_remote_calandars_xml.value = merge_xml;
4501 //alert (num_merged_calendars +" new calendars to merge!")
4508 my $popup_javascript_info = "";
4509 if ($browser_type eq "IE") {
4510 $popup_javascript_info .=<<p1;
4511 <script type
="text/javascript" ><!--
4512 function do_onresize
() {
4513 opener
.info_window_width
= document
.body
.clientWidth
;
4514 opener
.info_window_height
= document
.body
.clientHeight
;
4520 $popup_javascript_info .=<<p1;
4521 <script type="text/javascript" ><!--
4522 function do_onresize() {
4523 opener.info_window_width = this.outerWidth;
4524 opener.info_window_height = this.outerHeight;
4531 $popup_javascript_info =~ s/\n/\\n/g;
4532 $popup_javascript_info =~ s/"/\\"/g;
4533 $popup_javascript_info =~ s/\//\\\//g;
4536 my $get_remote_calendars_html =<<p1;
4538 <form name
="detect_remote_calendars" action
="$script_url/$name" method
="POST">
4539 <input type
="hidden" name
="detect_remote_calendars" value
="1"/>
4540 $lang{get_remote_calendars_url
}<br
/>
4541 <input name
="remote_calendar_url" value
="http://" style
="width:90%;">
4543 <input type
="submit" value
="Go!" style
="width:5em;">
4546 $get_remote_calendars_html =~ s/\n/\\n/g;
4547 $get_remote_calendars_html =~ s/"/\\"/g;
4548 $get_remote_calendars_html =~ s/\//\\\
//g;
4550 $return_string.=<<p1;
4551 function get_remote_calendars() {
4552 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);
4554 doc = info_window.document;
4555 doc.open('text/html');
4556 doc.write('<html>');
4557 doc.write('<title>$lang{get_remote_calendars}<\\/title>');
4558 doc.write('<link rel=\\"stylesheet\\" href=\\"$css_path\\" type=\\"text/css\\" media=screen>');
4559 doc.write('$popup_javascript_info');
4560 doc.write('<body onResize=\\"javascript:do_onresize()\\">');
4561 doc.write("<div class=\\"info_box\\" style=\\"padding:5px;\\"><br\\/>");
4562 doc.write('$get_remote_calendars_html');
4563 doc.write("<\\/div>");
4564 doc.write('<\\/body><\\/html>');
4566 info_window.focus();
4571 // color select stuff
4572 var cs0 = new color_select();
4573 cs0.setrgb("$current_calendar{background_events_color}");
4575 var cs1 = new color_select();
4576 cs1.setrgb("$current_calendar{calendar_events_color}");
4579 function color_menu0_update(new_color) {
4580 if (document.update_cal_form.background_events_display_style2.checked) {
4581 document.update_cal_form.background_events_color.value = new_color;
4582 document.getElementById("bg_preview_e1").style.background = new_color;
4583 document.getElementById("bg_preview_e2").style.background = new_color;
4587 function color_menu1_update(new_color) {
4588 //if (new_color == "#000000") return;
4589 if (document.getElementById("color_select_icon1").style.visibility != "visible") return;
4591 document.update_cal_form.calendar_events_color[document.update_cal_form.calendar_events_color.options.length-1].value = new_color;
4592 document.update_cal_form.calendar_events_color.style.background = new_color;
4593 document.getElementById("custom_evt_color").style.background = new_color;
4594 document.getElementById("preview_e1").style.background = new_color;
4595 document.getElementById("preview_e2").style.background = new_color;
4599 function update_cal_color_select_box() {
4600 if (!document.update_cal_form) return;
4601 if (!document.update_cal_form.calendar_events_color) return;
4603 var current_color = document.update_cal_form.calendar_events_color[document.update_cal_form.calendar_events_color.selectedIndex].value;
4605 if (current_color == "") {
4606 document.getElementById('preview_e1').style.background = '#ffffcc';
4607 document.getElementById('preview_e2').style.background = '#ccffcc';
4608 document.getElementById("color_select_icon1").style.visibility = "hidden";
4609 document.update_cal_form.calendar_events_color.style.background = "#ffffff";
4613 if (document.update_cal_form.calendar_events_color.selectedIndex == document.update_cal_form.calendar_events_color.options.length-1) {
4614 document.getElementById("color_select_icon1").style.visibility = "visible";
4616 var current_custom_color = document.getElementById("custom_evt_color").value;
4617 document.getElementById("preview_e1").style.background = current_custom_color;
4618 document.getElementById("preview_e2").style.background = current_custom_color;
4619 document.update_cal_form.calendar_events_color.style.background = current_custom_color;
4622 cs1.setrgb(current_color);
4624 document.getElementById("color_select_icon1").style.visibility = "hidden";
4625 document.getElementById("preview_e1").style.background = current_color;
4626 document.getElementById("preview_e2").style.background = current_color;
4627 document.update_cal_form.calendar_events_color.style.background = current_color;
4629 // 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)
4630 document.update_cal_form.dummy.style.display='inline';
4631 document.update_cal_form.dummy.select();
4632 document.update_cal_form.dummy.style.display='none';
4635 //document.add_event_form.evt_bgcolor.style.background = document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.selectedIndex].value
4638 //document.update_cal_form.evt_title.select();
4641 // end color_select stuff
4644 $return_string.=<<p1;
4645 var info_window_x
= window_x
()-$info_window_width;
4646 var info_window_y
= window_y
() + 200;
4648 function show_help
() {
4649 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
);
4651 doc
= info_window
.document
;
4652 doc
.open('text/html');
4653 doc
.write('<html>');
4654 doc
.write('<title>$lang{help_box_title}<\\/title>');
4655 doc
.write('<link rel=\\"stylesheet\\" href=\\"$css_path\\" type=\\"text/css\\" media=screen>');
4656 doc
.write('$popup_javascript_info');
4658 doc
.write('<body onResize=\\"javascript:do_onresize()\\">');
4659 doc
.write(help_text
);
4660 doc
.write('<\\/body><\\/html>');
4662 info_window
.focus
();
4665 function preview_cal
() {
4666 var cal_title
= document
.update_cal_form
.cal_title
.value
4667 var cal_link
= document
.update_cal_form
.cal_link
.value
4668 var cal_details
= document
.update_cal_form
.cal_details
.value
;
4670 if (cal_title
== "") {
4671 evt_label
= "<span style=\\"color
:#ff0000\\">$lang{preview_calendar_temp_title}<\\/span>";
4676 if (document
.getElementById
("preview_warning")) {
4677 document
.getElementById
("preview_warning").innerHTML
="";
4680 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
);
4682 doc
= info_window
.document
;
4683 doc
.open('text/html');
4684 doc
.write('<html>');
4685 doc
.write('<title>$lang{preview_calendar_title}<\\/title>');
4686 doc
.write('<link rel=\\"stylesheet\\" href=\\"$css_path\\" type=\\"text/css\\" media=screen>');
4687 doc
.write('$popup_javascript_info');
4689 doc
.write('<body onResize=\\"javascript:do_onresize()\\">');
4690 doc
.write("<div class=\\"info_box
\\" style=\\"padding
:5px
;\\"><br/><div style=\\"white
-space
:nowrap
;\\"><span class=\\"cal_title
\\">");
4691 doc
.write("<a target=\\"_blank
\\" href=\\""+cal_link+"\\">"+cal_title
+"<\\/a><\\/span><\\/div><br/><div>"+cal_details
+"<\\/div><\\/div>");
4692 doc
.write('<\\/body><\\/html>');
4694 info_window
.focus
();
4698 my @help_text_map = ("title",
4705 "selectable_calendars",
4706 "background_calendars",
4707 "remote_background_calendars",
4708 "background_events_display_style",
4709 "events_display_style",
4710 "list_background_calendars_together",
4711 "default_number_of_months",
4716 "new_calendars_automatically_selectable",
4717 "allow_remote_calendar_requests",
4718 "remote_calendar_requests_password",
4719 "event_change_email",
4720 "popup_window_size",
4721 "custom_stylesheet",
4726 my $help_text_javascript = "";
4727 foreach $key (@help_text_map) {
4729 <div class="help_box">
4730 $lang{'help_cal_'.$key}
4733 $help_text =~ s/\n/\\n/g;
4734 $help_text =~ s/"/\\"/g;
4735 $help_text =~ s/'/\\'/g;
4736 $help_text =~ s/\//\\\//g;
4737 $help_text =~ s/###css file###/$css_path/g;
4739 $help_text_javascript .=<<p1;
4740 if (topic
== "$key")
4741 help_text
+= "$help_text";
4745 $return_string .=<<p1;
4746 function display_help(topic, title) {
4748 $help_text_javascript
4749 if (help_text != "") {
4750 help_text = "<div class=\\"help_title\\">$lang{help_box_title} - "+title+"</div>" + help_text;
4757 return $return_string
4758 } #********************end add_edit_calendars_javascript**********************
4761 sub generate_cal_details()
4763 my ($calendar_ref) = @_;
4765 my %calendar = %{$calendar_ref};
4768 <div
class="cal_title">
4777 $writable{calendar_file
} and $return_text .= <<p1;
4778 <div style="white-space:nowrap;">
4779 <span class="small_note">
4780 <a href="$script_url/$name?active_tab=2&add_edit_cal_action=edit&cal_id=$calendar{id}">$lang{calendar_add_edit}</a>
4785 $return_text .= <<p1;
4786 <div style
="white-space:nowrap;margin-top:2em;">
4787 <span
class="small_note">
4788 $lang{calendar_direct_link
}<br
/>
4789 <a href
="$script_url/$name?cal_id=$calendar{id}">$script_url/$name?cal_id
=$calendar{id
}</a
>
4799 sub render_calendar
{
4800 my $return_text = "";
4801 my $week_events = {};
4802 my $week_slots = {};
4804 my @debug_events = ("105");
4806 my $show_month_breaks = ($cal_num_months > 1 && $options{continuous_multimonth
} ne '1' ?
1 : 0);
4808 my $cal_month_idx = 0;
4810 my $is_first_cal_date = 1;
4811 my @use_other_month = (0, 1);
4813 my ($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year, $selected_events) = @_;
4814 #initialize loop variables
4815 my $cal_start_timestamp = timegm
(0,0,0,1,$cal_start_month,$cal_start_year);
4816 my $cal_end_timestamp = find_end_of_month
($cal_end_month, $cal_end_year);
4818 my $current_month = $cal_start_month;
4819 my $current_year = $cal_start_year;
4821 while ($current_year < $cal_end_year || ($current_year == $cal_end_year && $current_month <= $cal_end_month)) {
4822 $last_cal_month = ($current_year * 100 + $current_month) == ($cal_end_year * 100 + $cal_end_month);
4824 foreach $key (keys %week_events) {delete $week_events{$key};}
4825 foreach $key (keys %week_slots) {delete $week_slots{$key};}
4827 #for calendars with multiple months, display the name of each month above the calendar
4828 if ($show_month_breaks) {
4829 $return_text .=<<p1;
4830 <p class="cal_month_title" style
="padding:5px;">
4831 $months[$current_month] $current_year
4835 #calculate where to start the calendar (first sunday)
4836 #first, calculate what day of the week this month begins on
4838 #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year);
4840 my $cal_month_start_date = timegm
(0,0,0,1, $current_month, $current_year);
4841 my @cal_month_start_date_array = gmtime $cal_month_start_date;
4843 my $cal_start_day_offset = $cal_month_start_date_array[6] - $current_calendar{week_start_day
};
4844 $cal_start_day_offset += 7 if ($cal_start_day_offset < 0);
4846 my $cal_start_date = $cal_month_start_date - (86400 * $cal_start_day_offset);
4848 # in continuous_multimonth mode, skip first week if we already drew it in the previous iteration
4849 $cal_start_date = $cal_start_date + 604800 if (!$show_month_breaks && $cal_month_idx > 0 && $cal_start_day_offset != 0);
4851 # start with other_month if the first month does not start on the first day of the week (i.e there is an offset)
4852 @use_other_month = (1, 0) if (!$show_month_breaks && $cal_month_idx == 0 && $cal_start_day_offset != 0 && $current_month % 2);
4854 my @cal_start_date_array = gmtime $cal_start_date;
4856 my $cal_end_date = $cal_start_date + 86400*37;
4858 my $next_month = $current_month+1;
4859 if ($next_month == 12) {$next_month=0;}
4861 #cal_date keeps track of the date (in timestamp format)
4862 #as the calendar loop iterates through each day on the calendar page
4863 my $cal_date = $cal_start_date;
4864 my @cal_date_array = gmtime $cal_date;
4869 #make a first pass through the month, assemble event week events structure:
4870 #week_events{week_index}{id} ={}
4871 #this hash has 4 keys--start_weekday, start_day, length and slot_order (slot_order will be calculated in the second pass)
4872 for ($l1=0;$cal_date_array[4] != $next_month;$l1++) { #each calendar has 5 or 6 weeks
4873 $week_start_timestamp = $cal_date;
4874 $week_end_timestamp = $week_start_timestamp + 604800;
4875 $max_day_events{$l1} = 0;
4877 @cal_date_array = gmtime $cal_date;
4878 foreach $event_id (keys %events) {
4879 $debug = 1 if ($debug == 1 && (&contains
(\
@debug_events, $event_id) || $debug_events[0] eq "all"));
4881 my %event = %{$events{$event_id}};
4883 #$debug_info .= "checking event $event_id ($event{start}, $event{end})\n";
4884 #$debug_info .= "checking event $event_id ($event{start} - $event{end}) against week $l1 ($week_start_timestamp - $week_end_timestamp)\n";
4885 $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));
4887 if (&time_overlap
($event{start
}, $event{end
}, $week_start_timestamp, $week_end_timestamp)) {
4888 $debug_info .= "week $l1 event $event_id overlaps\n" if ($debug);
4890 #$debug_info .= "event $event_id ($event{days} days) in week $l1\n";
4891 #$debug_info .= "check passed!\n";
4893 my @event_date_array = gmtime $event{start
};
4894 my @event_end_date_array = gmtime $event{end
};
4895 my $event_start_weekday = $event_date_array[6] - $current_calendar{week_start_day
};
4896 my $event_end_weekday = $event_end_date_array[6] - $current_calendar{week_start_day
};
4898 $event_start_weekday +=7 if ($event_start_weekday < 0);
4899 $event_end_weekday +=7 if ($event_end_weekday < 0);
4901 #$event_start_weekday = 0 if ($event_start_weekday < 0);
4902 #$event_end_weekday = 0 if ($event_end_weekday < 0);
4903 #$event_start_weekday = 6 if ($event_start_weekday > 6);
4904 #$event_end_weekday = 6 if ($event_end_weekday > 6);
4906 my $days_before_week_start = 0;
4907 my $days_after_week_end = 0;
4909 $debug_info .= "week $l1 event $event_id event_date_array[6]: $event_date_array[6]\n" if ($debug);
4910 $debug_info .= "week $l1 event $event_id event_end_date_array[6]: $event_end_date_array[6]\n" if ($debug);
4911 $debug_info .= "week $l1 event $event_id current_calendar{week_start_day}: $current_calendar{week_start_day}\n" if ($debug);
4912 $debug_info .= "week $l1 event $event_id event_start_weekday: $event_start_weekday event_end_weekday: $event_end_weekday\n" if ($debug);
4914 # the event might fall completely within the week boundary, or it
4915 # might overlap event begins or ends outside the week boundaries
4916 # (there are four possible cases):
4917 if ($event{start
} < $week_start_timestamp && $event{end
} > $week_end_timestamp) { # the event both starts and ends outside this week
4918 $debug_info .= "case 0\n" if ($debug);
4919 $week_events{$l1}{$event{id
}}{start_weekday
} = 0;
4920 $week_events{$l1}{$event{id
}}{length} = 7;
4921 } elsif ($event{start
} < $week_start_timestamp) { # the event starts before this week and ends within it
4922 $debug_info .= "case 1\n" if ($debug);
4923 #$days_before_week_start = int(($week_start_timestamp - $event{start})/86400);
4924 $week_events{$l1}{$event{id
}}{start_weekday
} = 0;
4925 #$week_events{$l1}{$event{id}}{length} = $event{days} - $days_before_week_start;
4926 $week_events{$l1}{$event{id
}}{length} = $event_end_weekday+1;
4927 $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);
4928 } elsif ($event{end
} > $week_end_timestamp) { # the event starts within this week and ends after it
4929 $debug_info .= "case 2\n" if ($debug);
4930 $week_events{$l1}{$event{id
}}{start_weekday
} = $event_start_weekday;
4931 $week_events{$l1}{$event{id
}}{length} = 7-$event_start_weekday;
4933 foreach $debug_event_id (@debug_events) {
4934 next if ($debug_event_id ne $event{id
});
4935 $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";
4938 } else { #the event begins and ends within the week
4939 $debug_info .= "case 3\n" if ($debug);
4940 $week_events{$l1}{$event{id
}}{length} = $event{days
};
4941 $week_events{$l1}{$event{id
}}{start_weekday
} = $event_start_weekday;
4944 if ($week_events{$l1}{$event{id
}}{start_weekday
} < 0) {
4945 $week_events{$l1}{$event{id
}}{start_weekday
} += 7;
4946 } elsif ($week_events{$l1}{$event{id
}}{start_weekday
} > 6) {
4947 $week_events{$l1}{$event{id
}}{start_weekday
} -= 7;
4949 $week_events{$l1}{$event{id
}}{length} = 7 if ($week_events{$l1}{$event{id
}}{length} > 7);
4951 $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);
4955 $temp_debug_info = "";
4956 $cal_date += 604800;
4958 # each day has at least two slots (the date, and a blank box beneath it)
4959 for ($l2=0;$l2<7;$l2++) {
4960 $week_slots{$l1}{$l2}{0}{width
}=1;
4961 $week_slots{$l1}{$l2}{0}{depth
}=1;
4962 $week_slots{$l1}{$l2}{1}{width
}=1;
4963 $week_slots{$l1}{$l2}{1}{depth
}=1;
4967 foreach $debug_event_id (@debug_events) {
4968 $debug_info .= "event $debug_event_id length: $week_events{$l1}{$debug_event_id}{length} start: $events{$debug_event_id}{start}\n";
4972 #order the week_events
4973 #fill in the %slots data structure:
4974 # $week_slots{week_index}{day_index}{slot_index}
4977 # $spacer = 1 if spacer slot.
4981 my $max_week_needed_slots = 0;
4982 my %max_day_needed_slots;
4984 # hey man, that's a sharp-lookin' sort you got there
4985 foreach $week_event_id (sort {
4986 return $week_events{$l1}{$b}{length} <=> $week_events{$l1}{$a}{length}
4987 if ($week_events{$l1}{$b}{length} != $week_events{$l1}{$a}{length});
4989 return $events{$a}{title
} cmp $events{$b}{title
}
4990 if ($events{$b}{all_day_event
} ne "" && $events{$a}{all_day_event
} ne "");
4992 return $events{$b}{all_day_event
} cmp $events{$a}{all_day_event
}
4993 if ($events{$b}{all_day_event
} ne "" || $events{$a}{all_day_event
} ne "");
4995 return $events{$a}{start
} <=> $events{$b}{start
};
4997 keys %{$week_events{$l1}})
5000 #$debug = 1 if (&contains(\@debug_events, $week_event_id));
5002 #$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);
5006 #starting at 1 leaves a row of empty slots (row 0), where the calendar dates will go.
5007 for ($l4=1; $empty_slot != 1; $l4++) {
5009 #check each day of the week_event, to make sure the slot is empty
5010 for ($l2=0; $l2<$week_events{$l1}{$week_event_id}{length}; $l2++) {
5011 $day_index=$l2+$week_events{$l1}{$week_event_id}{start_weekday
};
5013 if (scalar @
{$week_slots{$l1}{$day_index}{$l4}{ids
}} > 0) {
5020 #$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);
5022 #fill up $week_slots with the new event (extend horizontally)
5023 for ($l2=0; $l2<$week_events{$l1}{$week_event_id}{length}; $l2++) {
5024 #$slots_in_row{$l1}{$slot_index}++;
5026 $day_index = $l2+$week_events{$l1}{$week_event_id}{start_weekday
};
5027 push @
{$week_slots{$l1}{$day_index}{$slot_index}{ids
}}, $week_event_id;
5029 if ($l2==0) { # first slot gets the width
5030 $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)
5031 $week_slots{$l1}{$day_index}{$slot_index}{width
} = 0;}
5032 $week_slots{$l1}{$day_index}{$slot_index}{depth
} = 1;
5035 #keep track of the maximum number of slots each week has
5036 if ($slot_index > $week_max_slots{$l1}) {
5037 $week_max_slots{$l1} = $slot_index;
5038 $max_day_events{$l1} = $slot_index;
5042 # give all blank slots width and depth of 1
5043 for ($l2=0;$l2<7;$l2++) {
5044 for ($l3=1;$l3<$week_max_slots{$l1}+1;$l3++) { # for each slot
5045 if ($week_slots{$l1}{$l2}{$l3}{depth
} eq "" || $week_slots{$l1}{$l2}{$l3}{width
} eq "") {
5046 $week_slots{$l1}{$l2}{$l3}{width
}=1;
5047 $week_slots{$l1}{$l2}{$l3}{depth
}=1;
5052 my $total_spacers=0;
5053 # insert spacer slots below multi-day events.
5054 for ($l3=1;$l3<$week_max_slots{$l1}+1;$l3++) { # for each slot
5055 my $inserted_spacers=0;
5056 for ($l2=0;$l2<7;$l2++) {
5057 if ($week_slots{$l1}{$l2}{$l3}{width
} > 1) { #multi-day event, add spacers beneath
5059 if ($inserted_spacers == 0) {
5060 # move everything else down and increment the number of rows
5061 $week_max_slots{$l1}++;
5062 for ($l4=0;$l4<7;$l4++) { # insert blank slots
5063 for ($l5=$week_max_slots{$l1};$l5>$l3+1;$l5--) { # count backwards
5064 $week_slots{$l1}{$l4}{$l5} = &deep_copy
($week_slots{$l1}{$l4}{$l5-1});
5066 $week_slots{$l1}{$l4}{$l3+1}{width
} = 1;
5067 $week_slots{$l1}{$l4}{$l3+1}{depth
} = 1;
5068 $week_slots{$l1}{$l4}{$l3+1}{spacer
} = 0;
5069 $week_slots{$l1}{$l4}{$l3+1}{ids
} = "";
5074 # insert spacers into previously created row.
5075 for ($l4=$l2;$l4<$l2+$week_slots{$l1}{$l2}{$l3}{width
};$l4++) {
5076 $week_slots{$l1}{$l4}{$l3+1}{spacer
}=1;
5077 #$debug_info .= "inserted spacer into row: ".($l3+1).", column $l4, event ".($week_slots{$l1}{$l4}{$l3}{ids}[0])."\n";
5080 #$debug_info .= "week $l1 day 0, slot 3: ".$week_slots{$l1}{0}{3}{ids}[0]."\n";
5087 #$debug_info .= "$total_spacers spacers inserted for week $l1.\n";
5088 #$debug_info .= "week $l1 day 0, slot 3: ".$week_slots{$l1}{0}{3}{ids}[0]."\n";
5091 #$debug_info .= "week $l1, event slots in row 1: $slots_in_row{$l1}{1}\n";
5093 # calculate slots in each row:
5094 for ($l3=1;$l3<$week_max_slots{$l1};$l3++) { # for each slot
5095 if ((scalar @
{$week_slots{$l1}{$l2}{$l3}{ids
}}) > 0 ) {
5096 $slots_in_row{$l1}{$l3} += $week_slots{$l1}{$l2}{$l3}{width
};
5097 #$debug_info .= "event in row $l1. Incrementing slots_in_row {$l1} {$l3} to $slots_in_row{$l1}{$l3}\n";
5099 if ($week_slots{$l1}{$l2}{$l3}{spacer
} == 1) {
5100 $slots_in_row{$l1}{$l3}++;
5101 #$debug_info .= "spacer in row $l1. Incrementing slots_in_row {$l1} {$l3} to $slots_in_row{$l1}{$l3}\n";
5105 %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});
5108 #$slots_in_row{$l1}{$slot_index}++;
5110 # extend event slots vertically.
5111 for ($l2=0;$l2<7;$l2++) { # for each day of the week
5112 for ($l3=1;$l3<$week_max_slots{$l1};$l3++) { # for each slot
5113 if (scalar @
{$week_slots{$l1}{$l2}{$l3}{ids
}} > 0 && $week_slots{$l1}{$l2}{$l3}{width
} > 0) { # if this slot begins an event
5114 my $start_slot = $l3+1;
5115 for ($l4=$start_slot; $l4<$week_max_slots{$l1}+1; $l4++) {
5116 #$debug_info .= "checking slot $l4 below event slot ($l2, $l3)\n";
5117 #if ($week_slots{$l1}{$l2}{$l4}{width} == 0)
5120 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.
5121 if ($l1 eq "3" && $debug) {
5122 $debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of another event below with the same width.\n";}
5123 #$debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of another event below with the same width.\n";
5124 #$debug_info .= "same-width event slot below week $l1, slot ($l2, $l3)\n";
5125 $week_slots{$l1}{$l2}{$l4}{width
}=0;
5126 $week_slots{$l1}{$l2}{$l4}{depth
}=0;
5127 $week_slots{$l1}{$l2}{$l3}{depth
}++;
5128 push @
{$week_slots{$l1}{$l2}{$l3}{ids
}}, @
{$week_slots{$l1}{$l2}{$l4}{ids
}};
5130 $max_day_needed_slots{$l2}--;
5131 #$slots_in_row{$l1}{$l4}--;
5133 } 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
5134 if ($l1 eq "3" && $debug) {
5135 $debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of a blank slot below.\n";}
5136 #$debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of a blank slot below.\n";
5137 #$debug_info .= "week $l1 slot ($l2, $l4) # ids:".scalar @{$week_slots{$l1}{$l2}{$l4}{ids}}."\n";
5138 #$debug_info .= "blank slot below week $l1, slot ($l2, $l3)\n";
5139 $week_slots{$l1}{$l2}{$l4}{width
}=0;
5140 $week_slots{$l1}{$l2}{$l4}{depth
}=0;
5141 $week_slots{$l1}{$l2}{$l3}{depth
}++;
5142 $max_day_needed_slots{$l2}--;
5143 #$debug_info .= "week $l1, slot ($l2, $l3) depth: $week_slots{$l1}{$l2}{$l3}{depth} \n";
5145 $debug_info .= "week $l1 slot ($l2, $l4) occupied. Finished attempting to extend slot $l3\n" if ($debug);
5152 #$debug_info .= "week $l1, event slots in row 1: $slots_in_row{$l1}{1}\n";
5154 # extend blank slots vertically into other blank slots.
5155 for ($l2=0;$l2<7;$l2++) { # for each day of the week
5157 for ($l3=1;$l3<$week_max_slots{$l1};$l3++) { # for each slot
5159 next if (scalar @
{$week_slots{$l1}{$l2}{$l3}{ids
}} > 0);
5161 if ($week_slots{$l1}{$l2}{$l3}{width
} > 0 && $week_slots{$l1}{$l2}{$l3}{spacer
} == 0) { # if it's blank (but not a spacer)
5163 my $start_slot = $l3+1;
5164 for ($l4=$start_slot; $l4<$week_max_slots{$l1}+1; $l4++) {
5165 if ($week_slots{$l1}{$l2}{$l4}{width
} == 1 && $week_slots{$l1}{$l2}{$l4}{spacer
} == 0) {
5166 #$debug_info .= "blank slot below week $l1, slot ($l2, $l3)\n" if ($debug);
5167 $week_slots{$l1}{$l2}{$l4}{width
}=0;
5168 $week_slots{$l1}{$l2}{$l4}{depth
}=0;
5169 $week_slots{$l1}{$l2}{$l3}{depth
}++;
5170 $max_day_needed_slots{$l2}--;
5178 #$debug_info .= "week $l1, event slots in row 1: $slots_in_row{$l1}{1}\n";
5179 #$debug_info .= "week $l1 slot (4, 1) depth: $week_slots{$l1}{4}{1}{depth}\n";
5181 # yet another pass. trim vertical depth and re-calculate max_slots
5185 #$debug_info .= "\n week $l1 max slots: $week_max_slots{$l1}\n";
5188 #$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);
5190 $max_week_needed_slots = max
(values %max_day_needed_slots);
5191 #$debug_info .= "week $l1 max_week_needed_slots: $max_week_needed_slots\n";
5193 #if ($max_day_needed_slots >$max_week_needed_slots)
5194 # {$max_week_needed_slots = $max_day_needed_slots;}
5195 #$debug_info .= "max needed slots for week $l1, $max_week_needed_slots\n";
5197 my $trim = $week_max_slots{$l1} - $max_week_needed_slots;
5200 #$debug_info .= "trim for week $l1, $trim\n";
5201 for ($l2=0;$l2<7;$l2++) { # for each day of the week
5203 for ($l3=$week_max_slots{$l1};$l3>0;$l3--) { # for each slot, counting backwards (upwards)
5205 if ($week_slots{$l1}{$l2}{$l3}{depth
} > 0) { # blank or non-blank, with depth > 0
5207 #$debug_info .= "trimming week $l1, slot ($l2, $l3) by $trim\n";
5208 $week_slots{$l1}{$l2}{$l3}{depth
} = $week_slots{$l1}{$l2}{$l3}{depth
} - $trim;
5214 $week_max_slots{$l1} = $week_max_slots{$l1} - $trim;
5216 } # repeat for next week
5219 if ($cal_month_idx == 0 || $show_month_breaks) {
5220 my @lowercase_day_names;
5221 foreach $day_name (@day_names) {
5222 push @lowercase_day_names, lc $day_name;
5225 $return_text .=<<p1;
5226 <table class="calendar" summary="">
5228 <td class="day_names $lowercase_day_names[0]">$weekday_sequence[0]</td>
5229 <td class="day_names $lowercase_day_names[1]">$weekday_sequence[1]</td>
5230 <td class="day_names $lowercase_day_names[2]">$weekday_sequence[2]</td>
5231 <td class="day_names $lowercase_day_names[3]">$weekday_sequence[3]</td>
5232 <td class="day_names $lowercase_day_names[4]">$weekday_sequence[4]</td>
5233 <td class="day_names $lowercase_day_names[5]">$weekday_sequence[5]</td>
5234 <td class="day_names $lowercase_day_names[6]">$weekday_sequence[6]</td>
5239 #cal_date keeps track of the date (in timestamp format)
5240 #as the calendar loop iterates through each day on the calendar page
5241 $cal_date = $cal_start_date;
5242 @cal_date_array = gmtime $cal_date;
5244 #locked and loaded, data structures assembled--now it's time to kick it, calendar-style.
5245 for ($l1=0;$cal_date_array[4] != $next_month; $l1++) { #each calendar has 5 or 6 weeks
5248 my $timestamp_next_week = $cal_date+604800;
5249 my @timestamp_next_week_array = gmtime $timestamp_next_week;
5251 my $week_date_index = $cal_date;
5254 for ($l3=0;$l3<$week_max_slots{$l1}+1;$l3++) {
5255 $return_text .="<tr id=\"week_$cal_date\">";
5257 $week_date_index = $cal_date;
5258 for ($l2=0;$l2<7;$l2++) { # 7 days / week
5260 @cal_date_array = gmtime $week_date_index;
5261 my $td_class = "day ".lc($day_names[$l2]);
5262 $td_class .= " today" if ($cal_date_array[4] == $rightnow_month &&
5263 $cal_date_array[3] == $rightnow_mday &&
5264 $cal_date_array[5]+1900 == $rightnow_year);
5266 # display date numbers differently, depending on whether they are in the current month or not
5267 my $cal_month_name = "";
5268 if ($show_month_breaks || $cal_num_months == 1) {
5269 $td_class .= " other_month" if ($cal_date_array[4] != $current_month);
5271 $td_class .= " other_month_multi" if ($use_other_month[$cal_date_array[4] % 2]);
5272 $cal_month_name = $months[$cal_date_array[4]] if ($cal_date_array[3] == 1);
5275 #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 "")
5277 if ($l3 == 0) { #if it's the top blank slot, put the date in there.
5279 $td_style="border-bottom-width:0px;";
5281 #display the cell differently if it is today.
5282 if ($cal_date_array[4] == $rightnow_month &&
5283 $cal_date_array[3] == $rightnow_mday &&
5284 $cal_date_array[5]+1900 == $rightnow_year) {
5285 # offset the date number a few pixels
5286 # (so it will be in the center of the red circle)
5287 # offset a bit more for a double-digit day number.
5288 # small touches are the difference between good and great :)
5290 my $date_div_style = "";
5291 $date_div_style = "text-indent: 11px;" if ($rightnow_mday > 10);
5293 $return_text .=<<p1;
5294 <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);">
5295 <div
class="date today" style
="$date_div_style"><a id
="today"></a>$cal_date_array[3] $cal_month_name</div
>
5299 $return_text .=<<p1;
5300 <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);">
5301 <div class="date">$cal_date_array[3] $cal_month_name</div>
5305 } elsif ($week_slots{$l1}{$l2}{$l3}{spacer} != 0) { # spacer slot
5307 my $spacer_class = "spacer";
5308 if ($l3 == $week_max_slots{$l1}-1) {
5309 $spacer_class .= " bottom";
5311 $return_text .=<<p1;
5312 <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);">
5315 } elsif ($week_slots{$l1}{$l2}{$l3}{width
} != 0) { # slot containing events
5317 $num_cols = $week_slots{$l1}{$l2}{$l3}{width
};
5318 $num_rows = $week_slots{$l1}{$l2}{$l3}{depth
};
5320 if (scalar @
{$week_slots{$l1}{$l2}{$l3}{ids
}} > 0) {
5322 $td_style="border-top-width:0px;border-bottom-width:0px;";
5324 for ( my $j = 0; $j < @
{$week_slots{$l1}{$l2}{$l3}{ids
}}; $j++ ) {
5325 if( $j < ( @
{$week_slots{$l1}{$l2}{$l3}{ids
}} - 1 ) ) {
5326 $event_id_list .= "'" . @
{$week_slots{$l1}{$l2}{$l3}{ids
}}[$j] . "'" . ",";
5328 $event_id_list .= "'" . @
{$week_slots{$l1}{$l2}{$l3}{ids
}}[$j] . "'";
5331 my $events_link = "javascript:display_events($event_id_list);";
5333 #($l2,$l3) $num_cols\lx$num_rows
5334 $return_text .=<<p1;
5335 <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);">
5336 <a href="$events_link" class="event_box" style="display:block;text-align:center;cursor:pointer;cursor:hand;"><span class="event_time" style=";"> ALL<br></a>
5339 foreach $event_id (@{$week_slots{$l1}{$l2}{$l3}{ids}}) {
5340 my $multi_day_event = ($week_slots{$l1}{$l2}{$l3}{width} > 1) ? 1:0;
5342 my $background_event = (&contains($events{$event_id}{cal_ids}, $current_calendar{id})) ? 0:1;
5344 $return_text .= &display_calendar_event($event_id, $multi_day_event, $background_event)
5347 $return_text .=<<p1;
5350 } elsif ($week_slots{$l1}{$l2}{$l3}{ids
} eq "" && $week_slots{$l1}{$l2}{$l3}{width
} > 0) { # blank slot
5352 $td_style="border-top-width:0px;border-bottom-width:0px;";
5354 #($l2,$l3) blank $num_cols\lx$num_rows
5355 $return_text .=<<p1;
5356 <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);">
5361 $week_date_index += 86400;
5362 } # next day (first row)
5365 $return_text .=<<p1;
5368 } # event slot index
5371 # this little trick is the cat's pajamas. It's another row of
5372 # table cells that cause each calendar day to come down a little
5373 # bit below the lowest esvent. It makes the calendar look sharp.
5375 # Also, if the week has a small number of events, we expand the height of the bottom cell.
5376 # This makes all the calendar cells look square, which is the bee's knees.
5378 my $bottom_height_style = "";
5379 if ($max_day_events{$l1} < 2) {
5380 my $height = (4-$max_day_events{$l1}) . "em"; # this algorithm was developed by guess & check
5381 #my $height = "100px"; # this algorithm was developed by guess & check
5382 $bottom_height_style = "line-height:$height;";
5384 $return_text .=<<p1;
5385 <tr style="$bottom_height_style">
5387 $week_date_index = $cal_date;
5388 for ($l2=0;$l2<7;$l2++) { #each week has 7 days(!)
5391 @cal_date_array = gmtime $week_date_index;
5392 $td_class .= "day ".lc($day_names[$l2])." cell_bottom";
5394 $td_class .= " today" if ($cal_date_array[4] == $rightnow_month &&
5395 $cal_date_array[3] == $rightnow_mday &&
5396 $cal_date_array[5]+1900 == $rightnow_year);
5398 if ($show_month_breaks || $cal_num_months == 1) {
5399 $td_class .= " other_month" if ($cal_date_array[4] != $current_month);
5401 $td_class .= " other_month_multi" if ($use_other_month[$cal_date_array[4] % 2]);
5404 $return_text .=<<p1;
5405 <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
>
5407 $week_date_index+=86400;
5409 $return_text .=<<p1;
5413 @cal_date_array = gmtime $cal_date;
5416 #close table tag for each month or only for last month on continuous_multimonth mode
5417 if ($show_month_breaks || $last_cal_month) {
5418 $return_text .=<<p1;
5420 <br style
="page-break-after:always;">
5424 #increment to the next month--the method used
5425 #here is the most painless way of making
5426 #this work the right way in all cases.
5430 if ($current_month == 12) {
5436 return $return_text;
5437 } #********************end render_calendar subroutine**********************
5440 sub background_event_colorize
{
5441 my ($event_id, $calendar_id) = @_;
5443 my %event = %{$events{$event_id}};
5444 my %calendar = %{$calendars{$calendar_id}};
5445 my $event_bgcolor = $event{bgcolor
};
5448 if ($calendars{$event{cal_ids
}[0]}{calendar_events_color
} ne "") {
5449 $event_bgcolor = $calendars{$event{cal_ids
}[0]}{calendar_events_color
};}
5452 if ($calendar{background_events_display_style
} eq "single_color") {
5453 $event_bgcolor = $calendar{background_events_color
};} elsif ($calendar{background_events_display_style
} eq "faded") {
5454 # create "faded" look for background event
5455 my $faded_color = $event_bgcolor;
5457 #convert rgb values from hex (00-FF) to decimal integer (0-255)
5458 my $r = hex substr $faded_color,1,2;
5459 my $g = hex substr $faded_color,3,2;
5460 my $b = hex substr $faded_color,5,2;
5462 #convert integer rgb values to hsv
5463 my @hsv_array = &rgb2hsv
($r,$g,$b);
5465 #convert s and v from percentages to decimal
5466 $hsv_array[1] = $hsv_array[1]/100;
5467 $hsv_array[2] = $hsv_array[2]/100;
5469 #"fade" the color (decrease saturation)
5470 $hsv_array[1] = $hsv_array[1]/$calendar{background_events_fade_factor
};
5472 my @new_rgb_array = &hsv2rgb
($hsv_array[0],$hsv_array[1],$hsv_array[2]);
5474 #convert back to hex
5475 $r = (sprintf ("%1.1X",$new_rgb_array[0]));
5476 $g = (sprintf ("%1.1X",$new_rgb_array[1]));
5477 $b = (sprintf ("%1.1X",$new_rgb_array[2]));
5479 $event_bgcolor = "#$r$g$b";
5482 return $event_bgcolor;
5487 sub display_calendar_event
{
5488 my ($event_id, $multi_day, $background_event) = @_;
5489 my %event = %{$events{$event_id}};
5492 my $event_bgcolor = $event{bgcolor
};
5494 # force white color if the background is dark
5495 my $textcolor_style = "";
5496 my $r = hex substr $event_bgcolor,1,2;
5497 my $g = hex substr $event_bgcolor,3,2;
5498 my $b = hex substr $event_bgcolor,5,2;
5499 my $bright = ($r*299+$g*587+$b*114)/1000;
5500 $textcolor_style = "color:#fff" if ($bright < 128);
5502 $event_bgcolor = $current_calendar{calendar_events_color
} if ($current_calendar{calendar_events_color
} ne "");
5504 my $event_box_class = "event_box";
5507 my $event_link = "javascript:display_event('$event_id');";
5508 $event_link = "$event{details}" if ($event{details_url
} eq "1");
5510 if ($background_event) {
5511 $event_box_class .= " background";
5512 $event_bgcolor = &background_event_colorize
($event_id, $current_calendar{id
});
5517 my $unit_icon_text = "";
5518 if ($event{unit_number
} ne "") {
5519 $unit_icon_text = $event{unit_number
}." ";
5520 $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;
5524 if ($event{icon} ne "blank
" && $event{icon} ne "") {
5526 <img align="bottom
" src = "$icons_url/$event{icon
}_16x16
.gif
" style="margin
-left
:-22px
;margin
-right
:5px
;margin
-bottom
:-5px
;" alt="">
5529 $link_style="padding
-left
:29px
";
5532 # context menu stuff
5533 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}');\"";
5534 $event_context_menu_text = "" if ($event_id =~ /\D/);
5536 if ($multi_day == 0) {
5537 my $event_time = "";
5538 if ($event{all_day_event} ne "1") {
5539 $event_time = &nice_time_range_format($event{start}, $event{end});
5540 $event_time = "<span
class=\"event_time
\" style
=\"$textcolor_style;\"> $event_time </span><br/>";
5544 my $temp_item_text = $calendar_item_template;
5545 $temp_item_text =~ s/###icon###/$icon_text$unit_icon_text/g;
5546 $temp_item_text =~ s/###title###/$event{title}/g;
5547 $temp_item_text =~ s/###time###/$event_time/g;
5548 my $calendar_title = $calendars{$event{cal_ids}[0]}{title};
5549 $temp_item_text =~ s/###calendar title###/$calendar_title/g;
5552 <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>
5556 } else { # multi-day-event
5558 # handle the case where an event is < 24 hours and crosses midnight.
5560 my $event_time = "";
5562 if ($event{all_day_event} ne "1") {
5563 if ($event{end} - $event{start} < 86400) {
5566 $nudge_edge = "width
:$width%;position
:relative
;left
:$offset%;";
5569 $event_time = &nice_time_range_format($event{start}, $event{end});
5570 $event_time = "<span
class=\"event_time
\" style
=\"$textcolor_style;\"> $event_time </span
>";
5573 if ($event{icon} ne "blank
" && $event{icon} ne "") {
5575 <img src="$icons_url/$event{icon
}_16x16
.gif
" style="vertical
-align
:middle
;margin
-right
:5px
;" alt="">
5580 my $temp_item_text = $calendar_item_template;
5581 $temp_item_text =~ s/###icon###/$icon_text$unit_icon_text/g;
5582 $temp_item_text =~ s/###title###/$event{title}/g;
5583 $temp_item_text =~ s/###time###/$event_time/g;
5584 my $calendar_title = $calendars{$event{cal_ids}[0]}{title};
5585 $temp_item_text =~ s/###calendar title###/$calendar_title/g;
5588 <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>
5597 sub display_list_event {
5598 my ($event_id, $background_event, $sameday) = @_;
5599 my %event = %{$events{$event_id}};
5602 @event_start_timestamp_array = gmtime $event{start};
5607 if ($event{days} == 1) {
5609 $date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3]";
5610 $weekday_string = $day_names_abv[$event_start_timestamp_array[6]]
5611 } else { #multi-day event
5613 @event_end_timestamp_array = gmtime $event{end};
5614 if ($event_start_timestamp_array[4] eq $event_end_timestamp_array[4]) {
5615 $date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3]-$event_end_timestamp_array[3]";
5617 $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]";
5619 $weekday_string = "$day_names_abv[$event_start_timestamp_array[6]]-$day_names_abv[$event_end_timestamp_array[6]]";
5622 # weekday abbreviations
5623 my $weekday_abv_string = $weekday_string;
5624 for ($l1=0;$l1<scalar @day_names;$l1++) {
5625 $weekday_abv_string =~ s/$day_names[$l1]/$day_names_abv[$l1]/g;
5629 my $unit_icon_text="";
5630 if ($event{unit_number} ne "") {
5631 $icon_text = $event{unit_number};
5632 $icon_text =~ s/(\d)/<img src="$graphics_url\/unit_number_patch_$1_16x10.gif" style
=\"position
:relative
;top
:5px
;\" alt
=\"\">/g
;
5635 if ($event{icon
} eq "blank" || $event{icon
} eq "") {
5636 $icon_text .= "$unit_icon_text";
5638 $icon_text .= "$unit_icon_text<img src = \"$icons_url/$event{icon}_16x16.gif\" style=\"position:relative;top:5px;\" alt=\"\">";
5641 my $event_bgcolor = $event{bgcolor
};
5643 if ($calendars{$event{cal_ids
}[0]}{calendar_events_color
} ne "") {
5644 $event_bgcolor = $calendars{$event{cal_ids
}[0]}{calendar_events_color
};}
5646 if ($background_event eq "1") {
5647 $event_bgcolor = &background_event_colorize
($event_id, $current_calendar{id
});
5651 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}');\"";
5652 if ($event_id =~ /\D/) {
5653 $event_context_menu_text=""}
5655 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});\"";
5658 my $event_time = "";
5659 if ($event{all_day_event
} ne "1") {
5660 $event_time = &nice_time_range_format
($event{start
}, $event{end
});
5661 $event_time = "<span class=\"event_time\">$event_time</span>";
5664 my $event_link = "javascript:display_event('$event{id}');";
5665 if ($event{details_url
} eq "1") {
5666 $event_link = "$event{details}";}
5668 my $margin_top="7px";
5669 $margin_top = "0" if ($sameday);
5672 my $temp_item_text = $list_item_template;
5675 $temp_item_text =~ s/###variable_margin###/$margin_top/g;
5676 $temp_item_text =~ s/###event_contextmenu###/$event_context_menu_text/g;
5677 $temp_item_text =~ s/###day_contextmenu###/$day_context_menu_text/g;
5678 $temp_item_text =~ s/###id###/$event_id/g;
5679 $temp_item_text =~ s/###bgcolor###/$event_bgcolor/g;
5680 $temp_item_text =~ s/###link###/$event_link/g;
5681 $temp_item_text =~ s/###details###/$event{details}/g;
5682 $temp_item_text =~ s/###icon###/$icon_text/g;
5683 $temp_item_text =~ s/###title###/$event{title}/g;
5684 $temp_item_text .= qq!<br
><pre
>$event{details
}</pre
><hr
>!;
5685 $temp_item_text =~ s/###date###/$date_string/g;
5686 $temp_item_text =~ s/###weekday###/$weekday_string/g;
5687 $temp_item_text =~ s/###weekday_abv###/$weekday_abv_string/g;
5688 $temp_item_text =~ s/###time###/$event_time/g;
5691 $results .= $temp_item_text;
5694 <li style="padding:0;margin:0;margin-top:$margin_top;"$event_context_menu_text>
5695 <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>
5696 <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>
5709 my $return_text = "";
5710 ($start_month, $start_year, $end_month, $end_year) = @_;
5712 #calculate where to start and end the list
5714 #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year);
5715 my $list_start_timestamp = timegm(0,0,0,1,$start_month,$start_year);
5716 my $list_end_timestamp = &find_end_of_month($end_month, $end_year);
5718 # loop through all the events.
5720 #Create an array of events which fall
5721 # within the current list view dates
5722 my @selected_cal_events;
5724 #and a funky data structure for the background calendars
5725 # each element of this hash will be an array.
5726 my $shared_cal_events={}; #empty hash
5728 foreach $event_id (keys %events) {
5729 if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$list_start_timestamp,$list_end_timestamp)) {
5730 my $event_in_current_calendar = 0;
5732 foreach $temp_cal_id (@{$events{$event_id}{cal_ids}}) {
5733 if ($temp_cal_id eq $current_cal_id) {
5734 push @selected_cal_events, $event_id;}
5736 foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) {
5737 if ($temp_cal_id eq $background_cal_id) {
5738 if ($current_calendar{list_background_calendars_together} eq "yes") {
5739 push @selected_cal_events, $event_id;
5741 push @{$shared_cal_events{$background_cal_id}}, $event_id if (!&contains(\@selected_cal_events, $event_id));
5749 # initialize loop variables
5750 $current_month = $start_month;
5751 $current_year = $start_year;
5753 $return_text .=<<p1;
5756 while ($current_year < $end_year || ($current_year == $end_year && $current_month <= $end_month)) {
5757 my $current_month_start_timestamp = timegm
(0,0,0,1,$current_month,$current_year);
5758 my $current_month_end_timestamp = &find_end_of_month
($current_month, $current_year);
5760 $return_text .=<<p1;
5761 <div class="list_month_box">
5764 if ($cal_num_months> 1) {
5765 $return_text .=<<p1;
5766 $months[$current_month] $current_year
5770 if ($current_calendar{list_background_calendars_together
} eq "yes") {
5771 $return_text .=<<p1;
5772 <ul class="list_cal_box" style="list-style-type:none;float:left;text-align:left;">
5773 <div style="text-align:center;font-weight:bold;">$calendars{$current_cal_id}{title}</div>
5775 #display events for selected calendar
5776 my $previous_event_id;
5777 foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @selected_cal_events) {
5778 my %event = %{$events{$event_id}};
5779 if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) {
5780 my $background_event = "";
5781 $background_event = "1" if ($event{cal_ids}[0] ne $current_cal_id);
5783 my @temp1 = gmtime($event{start});
5784 my @temp2 = gmtime($events{$previous_event_id}{start});
5787 $sameday = "1" if ($temp1[3] == $temp2[3]);
5789 $return_text .= &display_list_event($event_id, $background_event, $sameday);
5790 $previous_event_id = $event_id;
5793 $return_text .=<<p1;
5797 $return_text .=<<p1;
5798 <ul class="list_cal_box" style="list-style-type:none;float:left;text-align:left;">
5799 <li style="text-align:center;font-weight:bold;">$calendars{$current_cal_id}{title}</li>
5801 #display events for selected calendar
5802 my $previous_event_id;
5804 foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @selected_cal_events) {
5805 my %event = %{$events{$event_id}};
5806 if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) {
5807 my @temp1 = gmtime($event{start});
5808 my @temp2 = gmtime($events{$previous_event_id}{start});
5811 $sameday = "1" if ($temp1[3] == $temp2[3]);
5813 $return_text .= &display_list_event($event_id,0,$sameday);
5814 $previous_event_id = $event_id;
5817 $return_text .=<<p1;
5821 foreach $background_cal_id (keys %{$current_calendar{local_background_calendars
}}) {
5822 $return_text .=<<p1;
5823 <ul class="list_cal_box background" style="list-style-type:none;float:left;text-align:left;">
5824 <li style="text-align:center;font-weight:bold;">$calendars{$background_cal_id}{title}</li>
5826 #list events for that calendar
5827 my $previous_event_id;
5828 foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @{$shared_cal_events{$background_cal_id}}) {
5830 %event = %{$events{$event_id}};
5831 if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$current_month_start_timestamp, $current_month_end_timestamp)) {
5832 my @temp1 = gmtime($event{start});
5833 my @temp2 = gmtime($events{$previous_event_id}{start});
5836 $sameday = "1" if ($temp1[3] == $temp2[3]);
5838 $return_text .= &display_list_event($event_id,1,$sameday);
5839 $previous_event_id = $event_id;
5843 $return_text .=<<p1;
5845 <br style
="clear:both;"/> <!--needed because IE sucks
-->
5850 $return_text .=<<p1;
5851 <br style="clear:both;"/> <!-- because IE sucks-->
5852 <br style="clear:both;"/> <!-- because IE sucks-->
5854 <br style="clear:both;"/> <!-- because IE sucks-->
5855 <br style="clear:both;"/> <!-- because IE sucks-->
5858 #increment to the next month--the method used
5859 #here is the most painless way of making
5860 #this work the right way in all cases.
5862 if ($current_month == 12) {
5868 $return_text .=<<p1;
5870 return $return_text;
5872 } #********************end generate_list subroutine**********************
5875 sub generate_event_details_javascript
{
5876 my ($events_start_timestamp, $events_end_timestamp) = @_;
5878 my $return_string="";
5881 my $num_remote_events = 0;
5883 my $remote_event_defs="";
5887 #loop through the events, check to see if they fall
5888 #within the current calendar month
5889 foreach $event_id (keys %events) {
5890 my %event = %{$events{$event_id}};
5891 if (&time_overlap
($event{start
},$event{end
},$events_start_timestamp,$events_end_timestamp)) {
5893 if ($event_id =~ /^r/) {
5894 $num_remote_events++;
5895 $remote_event_defs .= <<p1;
5896 remote_event_details["$event_id"] = new Object;
5897 remote_event_details["$event_id"].url = "$event{remote_calendar}{url}?view_event=1&evt_id=$event{remote_event_id}";
5904 $return_string .=<<p1;
5905 var remote_event_details
= new Array
($num_remote_events);
5907 var event_details
= new Array
($num_events);
5910 return $return_string;
5912 } #********************end generate_event_details_javascript subroutine**********************
5916 sub pending_events_visible
{
5917 # display pending events for this calendar?
5918 if ($options{pending_events_display
} eq '0' || $options{pending_events_display
} eq '1' ||
5919 ($options{pending_events_display
} eq '2' && $logged_in_as_current_cal_user) || # logged-in user of this calendar
5920 ($options{pending_events_display
} eq '3' && $logged_in_as_current_cal_user) || # logged-in user of this calendar
5921 ($options{pending_events_display
} eq '3' && $logged_in_as_current_cal_admin) || # logged-in admin of this calendar
5922 $logged_in_as_root # root
5932 <form name="forced_login_form" id="update_cal_form" action="" method="POST">
5933 <input type="hidden" name="active_tab" value="$active_tab">
5934 <input type="hidden" name="cal_id" value="$current_cal_id"/>
5935 <div class="info_box" style="clear:both;">
5936 <p class="cal_title" style
="text-align:center;">
5939 <div
class="leftcol" style
="">
5940 <label
class="required_field" for="cal_password">$lang{cal_password
}</label
>
5943 <div
class="rightcol" style
="white-space:nowrap;">
5944 <input type
="password" name
="cal_password" id
="cal_password" size
=12 />
5945 <span
class="small_note" ><a style
="vertical-align:top;" href
="javascript:display_help('current_password','$lang{cal_password}')">$lang{help_on_this
}</a></span
>
5948 <div
class="leftcol">
5951 <div
class="rightcol" style
="white-space:nowrap;">
5952 <input type
="submit" value
="$lang{submit}"/>
5954 <br style
="clear:both;"/>
5962 sub generate_logged_in_stuff
{
5963 # events & calendars pending approval, etc.
5967 #if ($options{pending_events_display} > 1)
5971 my $pending_events_text = "";
5972 # display pending events for this calendar?
5973 #$debug_info .= "pending_events_visible: ".(&pending_events_visible)."\n";
5975 if (&pending_events_visible
) {
5976 foreach $new_event_id (keys %new_events) {
5977 push @pending_events_to_display, $new_event_id;
5980 #$debug_info .= "scalar @ pending_events_to_display: ".(scalar @pending_events_to_display)."\n";
5982 if (scalar @pending_events_to_display > 0) {
5983 $pending_events_text .= "<a href=\"javascript:approve_pending_events_toggle()\">";
5984 $pending_events_text .= (scalar @pending_events_to_display)." ";
5986 if (scalar @pending_events_to_display == 1) {
5987 $pending_events_text .= $lang{pending_event1
};
5989 $pending_events_text .= $lang{pending_event2
};
5991 $pending_events_text .= "</a>";
5995 # display pending events for other calendars?
5996 #if ($options{pending_events_display}) {
5999 if ($pending_events_text ne "") {
6000 $results .= "$pending_events_text <div style=\"text-align:right;\" id=\"pending_events\"></div>";
6012 ($start_month, $start_year, $end_month, $end_year) = @_;
6014 #calculate where to start and end the list
6016 #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year);
6017 my $list_start_timestamp = timegm
(0,0,0,1,$start_month,$start_year);
6018 my $list_end_timestamp = &find_end_of_month
($end_month, $end_year);
6020 #@cal_month_start_date_array = gmtime $cal_month_start_date;
6022 # loop through all the events.
6024 #Create an array of events which fall
6025 # within the current list view dates
6026 my @selected_cal_events;
6028 #and a funky data structure for the background calendars
6029 # each element of this hash will be an array.
6030 my $shared_cal_events={}; #empty hash
6032 foreach $event_id (keys %events) {
6033 if (&time_overlap
($events{$event_id}{start
},$events{$event_id}{end
},$list_start_timestamp,$list_end_timestamp)) {
6034 my $event_in_current_calendar = 0;
6036 foreach $temp_cal_id (@
{$events{$event_id}{cal_ids
}}) {
6037 if ($temp_cal_id eq $current_cal_id) {
6038 push @selected_cal_events, $event_id;}
6039 foreach $background_cal_id (keys %{$current_calendar{local_background_calendars
}}) {
6040 if ($temp_cal_id eq $background_cal_id) {
6041 push @
{$shared_cal_events{$background_cal_id}}, $event_id;}
6048 Cache-control: no-cache,no-store,private
6049 Content-disposition: filename="events.csv"
6050 Content-Type: text/csv; charset=$lang{charset}\n
6052 #initialize loop variables
6053 #$current_timestamp = $list_start_timestamp;
6054 $current_month = $start_month;
6055 $current_year = $start_year;
6057 $html_output .=<<p1;
6058 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
6062 while ($current_year < $end_year || ($current_year == $end_year && $current_month <= $end_month)) {
6063 my $current_month_start_timestamp = timegm
(0,0,0,1,$current_month,$current_year);
6064 my $current_month_end_timestamp = &find_end_of_month
($current_month, $current_year);
6065 #display events for selected calendar
6066 foreach $event_id (sort {$events{$a}{start
} <=> $events{$b}{start
}} @selected_cal_events) {
6067 my %event = %{$events{$event_id}};
6069 if (&time_overlap
($event{start
},$event{end
},$current_month_start_timestamp, $current_month_end_timestamp)) {
6070 my $csv_subject = "$event{title}";
6072 @event_start_timestamp_array = gmtime $event{start
};
6073 my $csv_start_date = ($event_start_timestamp_array[5]+1900)." ".($event_start_timestamp_array[4]+1)." ".($event_start_timestamp_array[3]);
6074 my $csv_start_time = "$event_start_timestamp_array[2]:$event_start_timestamp_array[1]";
6076 @event_end_timestamp_array = gmtime $event{end
};
6077 my $csv_end_date = ($event_end_timestamp_array[5]+1900)." ".($event_end_timestamp_array[4]+1)." ".($event_end_timestamp_array[3]);
6078 my $csv_end_time = "$event_end_timestamp_array[2]:$event_end_timestamp_array[1]";
6080 my $csv_description = $event{details
};
6081 $csv_description =~ s/"/""/g;
6082 $csv_description =~ s/\n/\\n/g;
6084 if ($event{days
} != 1) {
6085 @event_end_timestamp_array = gmtime $event{end
};
6086 $csv_end_date = ($event_end_timestamp_array[5]+1900)." ".($event_end_timestamp_array[4]+1)." ".($event_end_timestamp_array[3]);
6089 $html_output .=<<p1;
6090 "$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",""
6094 foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) {
6095 #list events for that calendar
6096 foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @{$shared_cal_events{$background_cal_id}}) {
6097 my %event = %{$events{$event_id}};
6099 if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$current_month_start_timestamp, $current_month_end_timestamp)) {
6100 my $csv_subject = "$event{title}";
6102 @event_start_timestamp_array = gmtime $event{start};
6103 my $csv_start_date = ($event_start_timestamp_array[5]+1900)." ".($event_start_timestamp_array[4]+1)." ".($event_start_timestamp_array[3]);
6104 my $csv_start_time = "$event_start_timestamp_array[2]:$event_start_timestamp_array[1]";
6106 @event_end_timestamp_array = gmtime $event{end};
6107 my $csv_end_date = ($event_end_timestamp_array[5]+1900)." ".($event_end_timestamp_array[4]+1)." ".($event_end_timestamp_array[3]);
6108 my $csv_end_time = "$event_end_timestamp_array[2]:$event_end_timestamp_array[1]";
6110 my $csv_description = $event{details};
6111 $csv_description =~ s/"/""/g;
6112 $csv_description =~ s/\n/\\n/g;
6114 $csv_description =~ s/"/""/g;
6115 $csv_description =~ s/\n/\\n/g;
6118 if ($event{days} != 1) {
6119 @event_end_timestamp_array = gmtime $event{end};
6120 $csv_end_date = ($event_end_timestamp_array[5]+1900)." ".($event_end_timestamp_array[4]+1)." ".($event_end_timestamp_array[3]);
6123 $html_output .=<<p1;
6124 "$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",""
6130 #increment to the next month--the method used
6131 #here is the most painless way of making
6132 #this work the right way in all cases.
6134 if ($current_month == 12) {
6140 $html_output .= $debug_info;
6149 ($start_month, $start_year, $end_month, $end_year) = @_;
6151 #calculate where to start and end the list
6153 #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year);
6154 my $list_start_timestamp = timegm
(0,0,0,1,$start_month,$start_year);
6155 my $list_end_timestamp = &find_end_of_month
($end_month, $end_year);
6157 #@cal_month_start_date_array = gmtime $cal_month_start_date;
6159 # loop through all the events.
6161 #Create an array of events which fall
6162 # within the current list view dates
6163 my @selected_cal_events;
6165 #and a funky data structure for the background calendars
6166 # each element of this hash will be an array.
6167 my $shared_cal_events={}; #empty hash
6169 foreach $event_id (keys %events) {
6170 if (&time_overlap
($events{$event_id}{start
},$events{$event_id}{end
},$list_start_timestamp,$list_end_timestamp)) {
6171 my $event_in_current_calendar = 0;
6173 foreach $temp_cal_id (@
{$events{$event_id}{cal_ids
}}) {
6174 if ($temp_cal_id eq $current_cal_id) {
6175 push @selected_cal_events, $event_id;}
6176 foreach $background_cal_id (keys %{$current_calendar{local_background_calendars
}}) {
6177 if ($temp_cal_id eq $background_cal_id) {
6178 push @
{$shared_cal_events{$background_cal_id}}, $event_id;}
6185 Cache-control: no-cache,no-store,private
6186 Content-disposition: filename="events.csv"
6187 Content-Type: text/plain; charset=$lang{charset}\n\n
6189 #initialize loop variables
6190 #$current_timestamp = $list_start_timestamp;
6191 $current_month = $start_month;
6192 $current_year = $start_year;
6194 $html_output .=<<p1;
6195 "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"
6199 while ($current_year < $end_year || ($current_year == $end_year && $current_month <= $end_month)) {
6200 my $current_month_start_timestamp = timegm
(0,0,0,1,$current_month,$current_year);
6201 my $current_month_end_timestamp = &find_end_of_month
($current_month, $current_year);
6202 #display events for selected calendar
6203 foreach $event_id (sort {$events{$a}{start
} <=> $events{$b}{start
}} @selected_cal_events) {
6204 my %event = %{$events{$event_id}};
6206 if (&time_overlap
($event{start
},$event{end
},$current_month_start_timestamp, $current_month_end_timestamp)) {
6207 my $csv_subject = "$event{title} ($calendars{$current_cal_id}{title})";
6209 @event_start_timestamp_array = gmtime $event{start
};
6210 my $csv_start_date = ($event_start_timestamp_array[4]+1)."/$event_start_timestamp_array[3]/".($event_start_timestamp_array[5]+1900);
6211 my $csv_start_time = ($event_start_timestamp_array[2]).":$event_start_timestamp_array[1]:".($event_start_timestamp_array[0]);
6213 @event_end_timestamp_array = gmtime $event{end
};
6214 my $csv_end_date = ($event_end_timestamp_array[4]+1)."/$event_end_timestamp_array[3]/".($event_end_timestamp_array[5]+1900);
6215 my $csv_end_time = ($event_end_timestamp_array[2]).":$event_end_timestamp_array[1]:".($event_end_timestamp_array[0]);
6217 my $csv_description = $event{details
};
6218 $csv_description =~ s/"/""/g;
6219 $csv_description =~ s/\n/\\n/g;
6221 if ($event{days
} != 1) {
6222 @event_end_timestamp_array = gmtime $event{end
};
6223 $csv_end_date = ($event_end_timestamp_array[4]+1)."/$event_end_timestamp_array[3]/".($event_end_timestamp_array[5]+1900);
6226 $html_output .=<<p1;
6227 "$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"
6231 foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) {
6232 #list events for that calendar
6233 foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @{$shared_cal_events{$background_cal_id}}) {
6234 my %event = %{$events{$event_id}};
6236 if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$current_month_start_timestamp, $current_month_end_timestamp)) {
6237 my $csv_subject = "$event{title} ($calendars{$background_cal_id}{title})";
6239 @event_start_timestamp_array = gmtime $event{start};
6240 my $csv_start_date = ($event_start_timestamp_array[4]+1)."/$event_start_timestamp_array[3]/".($event_start_timestamp_array[5]+1900);
6241 my $csv_start_time = ($event_start_timestamp_array[2]).":$event_start_timestamp_array[1]:".($event_start_timestamp_array[0]);
6243 @event_end_timestamp_array = gmtime $event{end};
6244 my $csv_end_date = ($event_end_timestamp_array[4]+1)."/$event_end_timestamp_array[3]/".($event_end_timestamp_array[5]+1900);
6245 my $csv_end_time = ($event_end_timestamp_array[2]).":$event_end_timestamp_array[1]:".($event_end_timestamp_array[0]);
6247 my $csv_description = $event{details};
6248 $csv_description =~ s/"/""/g;
6249 $csv_description =~ s/\n/\\n/g;
6251 $csv_description =~ s/"/""/g;
6252 $csv_description =~ s/\n/\\n/g;
6255 if ($event{days} != 1) {
6256 @event_end_timestamp_array = gmtime $event{end};
6257 $csv_end_date = ($event_end_timestamp_array[4]+1)."/$event_end_timestamp_array[3]/".($event_end_timestamp_array[5]+1900);
6260 $html_output .=<<p1;
6261 "$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"
6267 #increment to the next month--the method used
6268 #here is the most painless way of making
6269 #this work the right way in all cases.
6271 if ($current_month == 12) {
6277 $html_output .= $debug_info;
6284 sub vcalendar_export_cal
{
6285 ($start_month, $start_year, $end_month, $end_year) = @_;
6287 #calculate where to start and end the list
6289 #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year);
6290 my $list_start_timestamp = timegm
(0,0,0,1,$start_month,$start_year);
6291 my $list_end_timestamp = &find_end_of_month
($end_month, $end_year);
6293 # loop through all the events.
6295 #Create an array of events which fall
6296 # within the current list view dates
6297 my @selected_cal_events;
6299 #and a funky data structure for the background calendars
6300 # each element of this hash will be an array.
6301 my $shared_cal_events={}; #empty hash
6303 foreach $event_id (keys %events) {
6304 if (&time_overlap
($events{$event_id}{start
},$events{$event_id}{end
},$list_start_timestamp,$list_end_timestamp)) {
6305 my $event_in_current_calendar = 0;
6307 foreach $temp_cal_id (@
{$events{$event_id}{cal_ids
}}) {
6308 if ($temp_cal_id eq $current_cal_id) {
6309 push @selected_cal_events, $event_id;}
6310 foreach $background_cal_id (keys %{$current_calendar{local_background_calendars
}}) {
6311 if ($temp_cal_id eq $background_cal_id) {
6312 push @
{$shared_cal_events{$background_cal_id}}, $event_id;}
6321 Cache-control: no-cache,no-store,private
6322 Content-disposition: filename="events.vcs"
6323 Content-Type: text/csv; charset=$lang{charset}
6330 #initialize loop variables
6331 #$current_timestamp = $list_start_timestamp;
6332 $current_month = $start_month;
6333 $current_year = $start_year;
6336 while ($current_year < $end_year || ($current_year == $end_year && $current_month <= $end_month)) {
6337 my $current_month_start_timestamp = timegm(0,0,0,1,$current_month,$current_year);
6338 my $current_month_end_timestamp = &find_end_of_month($current_month, $current_year);
6339 #display events for selected calendar
6340 foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @selected_cal_events) {
6341 my %event = %{$events{$event_id}};
6343 if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) {
6344 $html_output .= &event2vcal(\%event)."\n";
6347 foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) {
6348 #list events for that calendar
6349 foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @{$shared_cal_events{$background_cal_id}}) {
6350 my %event = %{$events{$event_id}};
6352 if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$current_month_start_timestamp, $current_month_end_timestamp)) {
6353 $html_output .= &event2vcal(\%event)."\n";
6358 #increment to the next month--the method used
6359 #here is the most painless way of making
6360 #this work the right way in all cases.
6362 if ($current_month == 12) {
6369 $html_output .=<<p1;
6373 $html_output .= $debug_info;
6380 sub ascii_text_cal
{
6381 ($start_month, $start_year, $end_month, $end_year) = @_;
6383 #calculate where to start and end the list
6385 #format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year);
6386 my $list_start_timestamp = timegm
(0,0,0,1,$start_month,$start_year);
6387 my $list_end_timestamp = &find_end_of_month
($end_month, $end_year);
6389 # loop through all the events.
6391 #Create an array of events which fall
6392 # within the current list view dates
6393 my @selected_cal_events;
6395 #and a funky data structure for the background calendars
6396 # each element of this hash will be an array.
6397 my $shared_cal_events={}; #empty hash
6399 foreach $event_id (keys %events) {
6400 if (&time_overlap
($events{$event_id}{start
},$events{$event_id}{end
},$list_start_timestamp,$list_end_timestamp)) {
6402 foreach $temp_cal_id (@
{$events{$event_id}{cal_ids
}}) {
6403 if ($temp_cal_id eq $current_cal_id) {
6404 push @selected_cal_events, $event_id;}
6405 foreach $background_cal_id (keys %{$current_calendar{local_background_calendars
}}) {
6406 if ($temp_cal_id eq $background_cal_id) {
6407 push @
{$shared_cal_events{$background_cal_id}}, $event_id;
6412 if ($done == 1) {last;}
6418 Cache-control: no-cache,no-store,private
6419 Content-Type: text/plain; charset=$lang{charset}\n\n
6421 #initialize loop variables
6422 #$current_timestamp = $list_start_timestamp;
6424 $current_month = $start_month;
6425 $current_year = $start_year;
6427 while ($current_year < $end_year || ($current_year == $end_year && $current_month <= $end_month)) {
6428 my $current_month_start_timestamp = timegm(0,0,0,1,$current_month,$current_year);
6429 my $current_month_end_timestamp = &find_end_of_month($current_month,$current_year);
6431 $html_output .=<<p1;
6433 *******************************************
6434 $months[$current_month] $current_year
6435 *******************************************
6437 * $current_calendar{title
}
6439 #display events for selected calendar
6440 foreach $event_id (sort {$events{$a}{start
} <=> $events{$b}{start
}} @selected_cal_events) {
6441 %event = %{$events{$event_id}};
6443 if (&time_overlap
($event{start
},$event{end
},$current_month_start_timestamp, $current_month_end_timestamp)) {
6444 @event_start_timestamp_array = gmtime $event{start
};
6445 my $event_time = "";
6446 if ($event{days
} == 1) {
6448 $date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3] ".($event_start_timestamp_array[5]+1900);
6449 if ($event{all_day_event
} ne "1") {
6450 $event_time = &nice_time_range_format
($event{start
}, $event{end
});
6451 $event_time = " ($event_time)";
6453 } else { #multi-day event
6455 $date_string = &nice_date_range_format
($event{start
}, $event{end
}, "-")." ".($event_start_timestamp_array[5]+1900);
6457 my $event_details = $event{details
};
6458 $event_details =~ s/\n[ \t\r\f]+/\n/g;
6459 chomp $event_details;
6461 #indent each line of the details
6462 $event_details =~ s/\n/\n /g;
6465 $html_output .=" $date_string$event_time: $event{title}\n";
6466 if ($event_details ne "") {
6467 $html_output .= " $event_details\n";
6469 $html_output .= "\n";
6473 foreach $background_cal_id (keys %{$current_calendar{local_background_calendars
}}) {
6474 $html_output .=<<p1;
6475 * $calendars{$background_cal_id}{title}
6477 #list events for that calendar
6478 foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @{$shared_cal_events{$background_cal_id}}) {
6479 my %event = %{$events{$event_id}};
6481 if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) {
6482 @event_start_timestamp_array = gmtime $event{start};
6483 my $event_time = "";
6484 if ($event{days} == 1) {
6486 $date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3] ".($event_start_timestamp_array[5]+1900);
6487 if ($event{all_day_event} ne "1") {
6488 $event_time = &nice_time_range_format($event{start}, $event{end});
6489 $event_time = " ($event_time)";
6491 } else { #multi-day event
6493 $date_string = &nice_date_range_format($event{start}, $event{end}, "-")." ".($event_start_timestamp_array[5]+1900);
6495 my $event_details = $event{details};
6496 $event_details =~ s/\n[ \t\r\f]+/\n/g;
6497 chomp $event_details;
6499 #indent each line of the details
6500 $event_details =~ s/\n/\n /g;
6503 $html_output .=" $date_string$event_time: $event{title}\n";
6504 if ($event_details ne "") {
6505 $html_output .= " $event_details\n";
6507 $html_output .= "\n";
6512 #increment to the next month--the method used
6513 #here is the most painless way of making
6514 #this work the right way in all cases.
6516 if ($current_month == 12) {
6521 $html_output .= $debug_info;
6524 } #********************end ascii_text_cal subroutine**********************
6526 sub ascii_text_event {
6527 my %current_event = %{$events{$current_event_id}};
6530 Cache
-control
: no-cache
,no-store
,private
6531 Content
-Type
: text
/plain
; charset
=$lang{charset
}\n\n
6535 my @event_start_timestamp_array = gmtime $current_event{start
};
6538 my $event_time = "";
6539 if ($current_event{days
} == 1) {
6541 $date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3] ".($event_start_timestamp_array[5]+1900);
6542 if ($current_event{all_day_event
} ne "1") {
6543 $event_time = &nice_time_range_format
($current_event{start
}, $current_event{end
});
6544 $event_time = "($event_time)";
6546 } else { #multi-day event
6548 $date_string = &nice_date_range_format
($current_event{start
}, $current_event{end
}, "-")." ".($event_start_timestamp_array[5]+1900);
6550 my $event_details = $current_event{details
};
6551 $event_details =~ s/\n\s+/\n/g;
6552 $event_details =~ s/\n{2,}/\n/g;
6553 chomp $event_details;
6555 #indent each line of the details
6556 $event_details =~ s/\n/\n /g;
6559 $html_output .=" $date_string$event_time: $current_event{title}\n";
6560 if ($event_details ne "") {
6561 $html_output .= " $event_details\n\n";
6563 $html_output .= $debug_info;
6566 } #********************end ascii_text_event subroutine**********************
6570 sub icalendar_export_event
{ # only for 1 event
6572 # when exporting to outlook, plans uses the vcalendar standard.
6573 # (http://www.imc.org/rfc2445)
6574 # This standard is horribly supported by MS outlook (outlook 2000, at the
6575 # time of this writing. Outlook refuses to correctly interpret the
6576 # date-time strings in the following ways:
6578 # 1. If the date-time parameter does not specify a time (only a date), do you
6579 # think outlook sets its "all-day event" flag? Nope. It just assumes the
6580 # event occurs at 000000 hours (12 midnight).
6582 # 2. if no time zone is specified, the date-time string is supposed to be
6583 # interpreted as if it applied to the *current* timezone the user's computer
6584 # is in (according to the standard). Do you think outlook does this? Nope.
6585 # If no timezone is specified, outlook assumes the time zone is GMT. As if this
6586 # weren't enough, outlook "helpfully" adjusts the time to the user's time zone.
6587 # Depending on how far a user is from GMT, this may cause the day to change.
6589 # Since there's no way to predict what time zone a user is in, it is impossible
6590 # to compensate on the server side for outlook's stupidity. The workaround is
6591 # to generate event times for each event (even though this is misleading because
6592 # the events are all-day events), and force all the event times to 12 noon.
6593 # This puts them as far from the previous and next days as possible, giving the
6594 # least chance for outlook to screw up the day when it does its adjustment.
6596 my %current_event = %{$events{$current_event_id}};
6598 my $ical_string = &event2ical
(\
%current_event);
6600 #Content-type: text/plain
6601 #Last-modified: Wed, 30 Jan 2002 22:43:12 GMT
6603 Content-type: text/x-vcalendar
6604 Content-disposition: filename="event.ics"
6616 } #********************end vcalendar_export subroutine**********************
6623 sub vcalendar_export_event { # only for 1 event
6625 my %current_event = %{$events{$current_event_id}};
6627 $vcal_string .= &event2vcal(\%current_event);
6629 #my $last_modified = &formatted_time($rightnow, "md mn yy hh:mm:ss GMT");
6630 #Last-modified: $last_modified
6632 #Content-type: text/plain
6634 Content
-type
: text
/vcs
6635 Content
-disposition
: filename
="event.vcs"
6647 } #********************end vcalendar_export_event subroutine**********************
6651 sub calculate_recurring_events
{
6652 my ($start_timestamp, $recurrence_parms_ref) = @_;
6654 my %recurrence_parms = %{$recurrence_parms_ref};
6655 my @recurring_events_array = ();
6656 my @custom_months = @
{$recurrence_parms{'custom_months'}};
6658 my @timestamp_array = gmtime $start_timestamp;
6660 #$debug_info .= "start timestamp: $start_timestamp\n";
6661 #foreach $custom_month (@custom_months)
6662 # {$debug_info .= "custom month: $custom_month\n";}
6664 #my $start_timestamp = $start_timestamp+50;
6665 #calculate the weekday_in_month_count for the start timestamp
6666 # (is it the first tuesday? second saturday? This is required for
6667 # things to work right.
6669 $real_year = 1900 + $timestamp_array[5];
6670 $temp_start_timestamp = timegm
(0,0,0,1,$timestamp_array[4],$real_year);
6671 #$debug_info .= "month_start_timestamp: $temp_start_timestamp\n";
6672 @temp_start_timestamp_array = gmtime($temp_start_timestamp);
6674 # $debug_info .= <<p1;
6675 #start timestamp: $start_timestamp<br/>
6676 #end timestamp: $recurrence_parms{'recur_end_timestamp'}<br/>
6677 #the start timestamp ($months[$timestamp_array[4]] $timestamp_array[3], $real_year) <br/>
6678 #the temp start timestamp ($months[$temp_start_timestamp_array[4]] $temp_start_timestamp_array[3], $temp_start_timestamp_array[5]) <br/>
6681 my $weekday_in_month_count = 0;
6682 #figure out what weekday of the month the start timestamp is
6683 for (;$temp_start_timestamp < $start_timestamp;$temp_start_timestamp+=86400) {
6684 @temp_start_timestamp_array = gmtime($temp_start_timestamp);
6685 if ($temp_start_timestamp_array[6] == $timestamp_array[6]) {
6686 $weekday_in_month_count++;
6690 #this must be done, or the week-of-month recurring dates will be hosed
6691 #@temp_array = gmtime $start_timestamp;
6692 #my $current_month = $temp_array[4];
6696 # set the start timestamp to a day boundary.
6697 my $boundary_timestamp = timegm
(0,0,0,$timestamp_array[3],$timestamp_array[4],$real_year);
6699 my $timed_event_diff = $start_timestamp - $boundary_timestamp;
6700 $start_timestamp = $boundary_timestamp;
6702 #$debug_info .= "start timestamp (day boundary): $start_timestamp\n";
6706 # The recurring event algorithm loops through each day in the timeframe
6707 # and tests its validity against the recurrence parameters.
6709 # These tests take the form of "assumed valid unless proven otherwise"
6710 # Doing it this way lets the various recurrence type tests operate
6711 # independently of each other, while looping only once through the timeframe
6713 for ($recur_timestamp = $start_timestamp; $recur_timestamp <= $recurrence_parms{'recur_end_timestamp'}; $recur_timestamp += 86400) {
6715 my @recur_timestamp_array = gmtime $recur_timestamp;
6716 my $current_month = $recur_timestamp_array[4];
6718 #look a week ahead, to see if the current weekday is the last one in the month
6719 my $recur_timestamp_next_week = $recur_timestamp+604800;
6720 my @recur_timestamp_next_week_array = gmtime $recur_timestamp_next_week;
6722 $last_week = 1 if ($current_month != $recur_timestamp_next_week_array[4]);
6724 $real_year = 1900 + $recur_timestamp_array[5];
6726 $recur_timestamp_valid=1;
6727 if ($recurrence_parms{'recurrence_type'} eq "same_day_of_month") {
6728 $recur_timestamp_valid=0 if ($recur_timestamp_array[3] != $timestamp_array[3]);
6729 } elsif ($recurrence_parms{'recurrence_type'} eq "same_day_of_week") {
6730 if ($recur_timestamp_array[6] != $timestamp_array[6]) {
6731 $recur_timestamp_valid=0;
6732 } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_first_week") {
6733 $recur_timestamp_valid=0 if ($weekday_in_month_count != 0);
6734 } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_second_week") {
6735 $recur_timestamp_valid=0 if ($weekday_in_month_count != 1);
6736 } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_third_week") {
6737 $recur_timestamp_valid=0 if ($weekday_in_month_count != 2);
6738 } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_fourth_week") {
6739 $recur_timestamp_valid=0 if ($weekday_in_month_count != 3);
6740 } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_fifth_week") {
6741 $recur_timestamp_valid=0 if ($weekday_in_month_count != 4);
6742 } elsif ($recurrence_parms{'weekday_of_month_type'} eq "only_last_week") {
6743 if ($last_week != 1) {
6744 $recur_timestamp_valid=0;
6746 #$debug_info .= "timestamp: $recur_timestamp\n";
6747 #$debug_info .= "current month: $current_month\n";
6748 #$debug_info .= "lookahead timestamp: $recur_timestamp_next_week\n";
6749 #$debug_info .= "lookahead month: $recur_timestamp_next_week_array[4]\n";
6752 } elsif ($recurrence_parms{'recurrence_type'} eq "every_x_days") {
6753 #$debug_info .= $q->param('every_x_days');
6754 #$debug_info .= "\n";
6755 $recur_timestamp_valid=0 if (($recur_timestamp - $start_timestamp) % (86400 * $recurrence_parms{'every_x_days'}) !=0);
6756 } elsif ($recurrence_parms{'recurrence_type'} eq "every_x_weeks") {
6757 #$debug_info .= ($q->param('every_x_weeks')."\n");
6758 $recur_timestamp_valid=0 if (($recur_timestamp - $start_timestamp) % (86400 * 7 * $recurrence_parms{'every_x_weeks'}) !=0);
6761 if ($recurrence_parms{'year_fit_type'} eq "custom_months") {
6763 foreach $custom_month (@custom_months) {
6764 $month_valid=1 if ($custom_month == $recur_timestamp_array[4]);
6766 $recur_timestamp_valid=0 if ($month_valid == 0);
6769 if ($recur_timestamp_valid == 1) {
6770 push @recurring_events_array, $recur_timestamp+$timed_event_diff;
6771 my $real_year = $recur_timestamp_array[5]+1900;
6774 #count how many of the event's weekdays we have come across in
6775 #each month. This is for validating events that occur on the
6776 #second tuesday, fifth monday, etc.
6777 if ($recur_timestamp_array[6] == $timestamp_array[6]) {
6778 $weekday_in_month_count++;
6781 #reset week_in_month count if this is the last week in the month
6782 $weekday_in_month_count=0 if ($last_week == 1 && $recur_timestamp_array[6] == $timestamp_array[6]);
6785 if (scalar @recurring_events_array == 0) {
6786 $debug_info .= "Error! No valid recurring event dates found!\n";
6789 #$debug_info .= "returning ".(scalar @recurring_events_array)." recurring events\n";
6791 return \
@recurring_events_array;
6796 # $date is of the format similar to mm/dd/yy (or a permutation like dd/mm/yy)
6797 my ($date, $recurrence_parms_ref) = @_;
6798 my %recurrence_parms = %{$recurrence_parms_ref};
6802 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})$/) {
6803 $lang{date_verify_err0
} =~ s/###date###/$date/;
6804 $lang{date_verify_err0
} =~ s/###format###/$current_calendar{date_format}/;
6805 $results .= $lang{date_verify_err0
}."\n";
6808 if ($recurrence_parms{'recurrence_type'} eq "every_x_days") {
6809 if ($recurrence_parms{'every_x_days'} == 0) {
6810 $results .= $lang{date_verify_err7
}."\n"};
6811 } elsif ($recurrence_parms{'recurrence_type'} eq "every_x_weeks") {
6812 if ($recurrence_parms{'every_x_weeks'} == 0) {
6813 $results .= $lang{date_verify_err8
}."\n"};
6819 $results .= $lang{date_verify_err1
}."\n";
6822 my ($mon, $day, $year) = &format2mdy
($date, $current_calendar{date_format
});
6824 if ($mon < 1 || $mon > 12) {
6825 $lang{date_verify_err4
} =~ s/###month###/$mon/;
6826 $results .= $lang{date_verify_err4
}."\n";
6829 $mon --; # convert month to 0-11 format
6831 if ($day < 1 || $day > 31) {
6832 $lang{date_verify_err5
} =~ s/###day###/$day/;
6833 $results .= $lang{date_verify_err5
}."\n";
6836 if ($year < 100) {$year+=2000;}
6838 if ($year < 1902 || $year > 2037) {
6839 $lang{date_verify_err6
} =~ s/###year###/$year/;
6840 $results .= $lang{date_verify_err6
}."\n";
6850 if($options{twentyfour_hour_format
}) {
6851 if ($time !~ /(\d+):(\d+)/) {
6852 $lang{time_verify_err0
} =~ s/\{0\}/$time/;
6853 $results .= $lang{time_verify_err0
};
6857 if ($hours > 23 || $hours < 0){
6858 $lang{time_verify_err1
} =~ s/\{0\}/$hours/;
6859 $results .= $lang{time_verify_err1
};
6862 if ($minutes > 59 || $minutes < 0){
6863 $lang{time_verify_err2
} =~ s/\{0\}/$minutes/;
6864 $results .= $lang{time_verify_err2
};
6869 if ($time !~ /(\d+):(\d+)\s*($lang{am}|$lang{pm})/) {
6870 $lang{time_verify_err0
} =~ s/\{0\}/$time/;
6871 $results .= $lang{time_verify_err0
};
6877 if ($hours > 12 || $hours < 0) {
6878 $lang{time_verify_err1
} =~ s/\{0\}/$hours/;
6879 $results .= $lang{time_verify_err1
};
6882 if ($minutes > 60 || $minutes < 0) {
6883 $lang{time_verify_err2
} =~ s/\{0\}/$minutes/;
6884 $results .= $lang{time_verify_err2
};
6895 my $html_output .=<<p1;
6896 Cache-control: no-cache,no-store,private
6897 Content-Type: text/html; charset=$lang{charset}\n
6898 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
6902 <meta http-equiv="pragma" content="no-cache">
6903 <link rel="stylesheet" href="$css_path" type="text/css" media=screen>
6904 <title>$lang{date_preview_title}</title>
6908 <div class="info_box">
6909 <span class="cal_title">
6910 $lang{date_preview_title}
6914 my %recurrence_parms;
6915 $recurrence_parms{'recurrence_type'} = $q->param('recurrence_type');
6916 $recurrence_parms{'weekday_of_month_type'} = $q->param('weekday_of_month_type');
6917 $recurrence_parms{'every_x_days'} = $q->param('every_x_days');
6918 $recurrence_parms{'every_x_weeks'} = $q->param('every_x_weeks');
6919 $recurrence_parms{'year_fit_type'} = $q->param('year_fit_type');
6920 $recurrence_parms{'recur_end_date'} = $q->param('recur_end_date');
6921 $recurrence_parms{'recur_end_timestamp'} = 0;
6923 my @custom_months = $q->param('custom_months');
6925 #my @custom_months = split(/\D+/, $q->param('custom_months'));
6926 #$debug_info .= (scalar @custom_months)." custom months\n";
6927 #$debug_info .= "q->param('custom_months'): ".$q->param('custom_months')."\n";
6929 $recurrence_parms{'custom_months'} = \@custom_months;
6931 my $recurring_event = $q->param('recurring_event');
6932 my $event_start_date = $q->param('evt_start_date');
6933 my $recur_end_date = $q->param('recur_end_date');
6934 my $event_days = $q->param('evt_days');
6935 my $event_start_time = $q->param('evt_start_time');
6936 my $event_end_time = $q->param('evt_end_time');
6937 my $all_day_event = $q->param('all_day_event');
6939 #my $event_cal_id = $current_cal_id;
6940 #my %current_calendar = %{$calendars{$event_cal_id}};
6942 my $date_valid = &verify_date($event_start_date);
6944 if ($event_days eq "") {
6945 $date_valid = $lang{date_verify_err2};
6947 if ($event_days =~ m/\D/ || $event_days <= 0) {
6948 my $temp = $lang{date_verify_err3};
6949 $temp =~ s/\$1/$event_days/;
6950 $date_valid = $temp;
6954 if ($recurring_event) {
6955 my $temp .= &verify_date($recurrence_parms{'recur_end_date'}, \%recurrence_parms);
6957 $date_valid .= "\n$lang{date_verify_for_recurring_end_date}\n<p style
=\"margin
:0;padding
-left
:1em
;\">$temp</p
>";
6961 if ($date_valid eq "") {
6962 my ($start_mon, $start_mday, $start_year) = &format2mdy($event_start_date, $current_calendar{date_format});
6963 my ($recur_end_mon, $recur_end_mday, $recur_end_year) = &format2mdy($recurrence_parms{'recur_end_date'}, $current_calendar{date_format});
6967 #calculate start timestamp
6968 #$event_start_timestamp = timegm(0,0,0,$start_mday,$start_mon,$start_year);
6970 #$debug_info .= "(preview_date
) start_mday
: $start_mday\n";
6971 #$debug_info .= "(preview_date
) start_mon
: $start_mon\n";
6972 #$debug_info .= "(preview_date
) start_year
: $start_year\n";
6973 #$debug_info .= "(preview_date
) event_days
: $event_days\n";
6974 #$debug_info .= "(preview_date
) event_start_time
: $event_start_time\n";
6975 #$debug_info .= "(preview_date
) event_end_time
: $event_end_time\n";
6976 #$debug_info .= "(preview_date
) all_day_event
: $all_day_event\n";
6978 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);
6981 @timestamp_array = gmtime $event_start_timestamp;
6982 my $real_year = $timestamp_array[5]+1900;
6984 if ($recurring_event == 1) {
6985 #calculate end timestamp
6986 $recurrence_parms{'recur_end_timestamp'} = timegm(0,0,0,$recur_end_mday,$recur_end_mon,$recur_end_year);
6988 $html_output .= <<p1;
6989 <p>$lang{date_preview_recurring_event_falls_on
}</p
>
6992 my @recurring_events_array = @
{&calculate_recurring_events
($event_start_timestamp, \
%recurrence_parms)};
6993 foreach $recurring_event_timestamp (@recurring_events_array) {
6994 $timestamp1 = $recurring_event_timestamp;
6995 $timestamp2 = $recurring_event_timestamp + 86400 * ($event_days-1);
6996 if ($timestamp1 == $timestamp2) {$timestamp2++;}
6998 $date_range = &nice_date_range_format
($timestamp1, $timestamp2, "-");
6999 $html_output .= <<p1;
7000 <p style
="font-weight:bold;">$date_range</p
>
7007 $timestamp1 = $event_start_timestamp;
7008 $timestamp2 = $event_start_timestamp + 86400 * ($event_days-1);
7009 if ($timestamp1 == $timestamp2) {$timestamp2++;}
7010 $date_range = &nice_date_range_format
($timestamp1, $timestamp2, "-");
7012 $html_output .= <<p1;
7013 <p>$lang{date_preview_this_event_falls_on
}</p
>
7014 <p style
="font-weight:bold;">
7021 $date_valid =~ s/\n/<br\/>/g
;
7022 $html_output .= "<p>$date_valid</p>";
7027 $html_output .=<<p1;
7031 #$html_output .="$debug_info";
7032 $debug_info =~ s/\n/<br\/>/g;
7034 $html_output .=<<p1;
7041 } # end preview date subroutine
7045 sub validate_event
{
7047 my $event_title = $q->param('evt_title');
7048 my $all_day_event = $q->param('all_day_event');
7049 my $event_start_date = $q->param('evt_start_date');
7050 my $event_start_time = $q->param('evt_start_time');
7051 my $event_end_time = $q->param('evt_end_time');
7052 my $event_days = $q->param('evt_days');
7054 my $date_valid = &verify_date
($event_start_date);
7056 if ($date_valid eq "") {
7057 if ($all_day_event ne "1") {
7058 my $verify_time_results = &verify_time
($event_start_time);
7059 if ($verify_time_results ne "") {
7060 my @sub_results = split("\n", $verify_time_results);
7061 foreach $sub_result (@sub_results) {
7062 $date_valid .= "[error]$lang{update_event_err14} $sub_result<br/>";
7066 my $verify_time_results = &verify_time
($event_end_time);
7067 if ($verify_time_results ne "") {
7068 my @sub_results = split("\n", $verify_time_results);
7069 foreach $sub_result (@sub_results) {
7070 $date_valid .= "[error]$lang{update_event_err15} $sub_result<br/>";
7077 if ($event_title eq "") {
7078 $date_valid = $lang{update_event_err4
};
7081 if ($event_days eq "") {
7082 $date_valid = $lang{date_verify_err2
};
7085 if ($event_days =~ m/\D/ || $event_days <= 0) {
7086 my $temp = $lang{date_verify_err3
};
7087 $temp =~ s/\$1/$event_days/;
7088 $date_valid = $temp;
7091 if ($date_valid eq "") {
7097 $date_valid =~ s/\//\\\//g;
7098 $date_valid =~ s/\n/<br\/>/g;
7099 $date_valid =~ s/"/\\"/g;
7100 $date_valid =~ s/'/\\'/g;
7104 messages
= '$date_valid';
7109 $debug_info =~ s/\//\\\
//g;
7110 $debug_info =~ s/\n/<br\/>/g
;
7111 $debug_info =~ s/"/\\"/g;
7112 $debug_info =~ s/'/\\'/g;
7113 $results =~ s/###debug_info###/$debug_info/;
7116 Cache-control: no-cache,no-store,private
7117 Content-Type: text/html; charset=iso-8859-1\n
7137 $event_details_template =~ s/###export event link###/$lang{event_details_export_disable}/g;
7138 $event_details_template =~ s/###edit event link###/$lang{event_details_edit_disable}/g;
7139 $event_details_template =~ s/###email reminder link###/$lang{event_email_reminder_disable}/g;
7141 my $event_info = &generate_event_details({title => $q->param('evt_title'),
7142 details => $q->param('evt_details'),
7143 cal_id => $current_cal_id,
7144 icon => $q->param('evt_icon'),
7145 bgcolor => $q->param('evt_bgcolor'),
7148 unit_number => $q->param('unit_number')}, 1);
7150 my $html_output .=<<p1;
7151 Cache
-control
: no-cache
,no-store
,private
7152 Content
-Type
: text
/html
; charset
=$lang{charset
}\n
7153 <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN">
7157 <meta http
-equiv
="pragma" content
="no-cache">
7158 <link rel
="stylesheet" href
="$css_path" type
="text/css" media
=screen
>
7159 <title
>$lang{event_preview_title
}</title
>
7162 <span
class="cal_title">
7163 $lang{event_preview_title
}
7175 #$debug_info .= "(view_event) event $current_event{id} start: $current_event{start} \n" if ($current_event{id} eq "1815");
7176 my %current_event = %{$events{$current_event_id}};
7178 my $event_info = &generate_event_details
(\
%current_event);
7179 $debug_info =~ s/\n/<br\/>\n/g
;
7181 my $html_output .=<<p1;
7182 Cache-control: no-cache,no-store,private
7183 Content-Type: text/html; charset=$lang{charset}\n
7184 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
7188 <meta http-equiv="pragma" content="no-cache">
7189 <link rel="stylesheet" href="$css_path" type="text/css" media=screen>
7190 <script type="text/javascript" src="$theme_url/lpd.js"></script>
7191 <script type="text/javascript" src="$theme_url/plans.js"></script>
7192 <script type="text/javascript" src="$theme_url/plans_lang.js"></script>
7193 <title>$current_event{title}</title>
7195 <body onResize="do_onresize()">
7207 #$debug_info .= "(view_event) event $current_event{id} start: $current_event{start} \n" if ($current_event{id} eq "1815");
7209 my @event_id_arr = split (',', $current_event_ids);
7211 my $html_output .=<<p1;
7212 Cache
-control
: no-cache
,no-store
,private
7213 Content
-Type
: text
/html
; charset
=$lang{charset
}\n
7214 <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN">
7218 <meta http
-equiv
="pragma" content
="no-cache">
7219 <link rel
="stylesheet" href
="$css_path" type
="text/css" media
=screen
> <script type
="text/javascript" src
="$theme_url/lpd.js"></script
> <script type
="text/javascript" src
="$theme_url/plans.js"></script> <script type="text/javascript
" src="$theme_url/plans_lang.js"></script
>
7220 <title
>@current_event_ids</title
>
7222 <body onResize
="do_onresize()">
7225 foreach my $current_event_id ( @event_id_arr ) {
7226 my %current_event = %{$events{$current_event_id}};
7228 my $event_info = &generate_events_details
(\
%current_event);
7229 $debug_info =~ s/\n/<br\/>\n/g
;
7230 $html_output .=<<p2;
7236 $html_output .=<<p3;
7244 sub view_pending_event
{
7245 my ($pending_event_ref) = @_;
7246 my %pending_event = %{$pending_event_ref};
7248 $event_details_template =~ s/###export event link###/$lang{event_details_export_disable}/g;
7249 $event_details_template =~ s/###edit event link###/$lang{event_details_edit_disable}/g;
7250 $event_details_template =~ s/###email reminder link###/$lang{event_email_reminder_disable}/g;
7253 my $event_info = &generate_event_details
(\
%pending_event);
7254 $debug_info =~ s/\n/<br\/>\n/g
;
7256 my $html_output .=<<p1;
7257 Cache-control: no-cache,no-store,private
7258 Content-Type: text/html; charset=$lang{charset}\n
7259 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
7263 <meta http-equiv="pragma" content="no-cache">
7264 <link rel="stylesheet" href="$css_path" type="text/css" media=screen>
7265 <script type="text/javascript" src="$theme_url/lpd.js"></script>
7266 <script type="text/javascript" src="$theme_url/plans.js"></script>
7267 <script type="text/javascript" src="$theme_url/plans_lang.js"></script>
7269 <title>$current_event{title}</title>
7271 <body onResize="do_onresize()">
7280 } # view_pending_event
7283 sub email_reminder_prompt {
7284 my %current_event = %{$events{$current_event_id}};
7285 my %previous_current_calendar = %current_calendar;
7286 %current_calendar = %{$calendars{$current_event{cal_ids}[0]}};
7287 $date_string = &nice_date_range_format($current_event{start}, $current_event{end}, " - ");
7288 %current_calendar = %previous_current_calendar;
7291 my $title = "<title>$current_event{title}$lang{email_reminder_title}</title>";
7294 <script type
="text/javascript" ><!--
7295 var clicked
= false
;
7297 function address_focus
() {
7299 document
.email_reminder_submit
.email_address
.value
= "";
7306 <div
class="event_details" style
="background-color:$current_event{bgcolor};text-align:left;">
7308 $current_event{title
}
7310 $lang{email_reminder_text1
}
7311 <br
/><span class="date">$date_string</span
>
7313 <br
/><br/>$lang{email_reminder_text2
}
7316 <form name
="email_reminder_submit" action
="$script_url/$name" method
="POST">
7317 <input type
="hidden" name
="evt_id" value
="$current_event{id}"/>
7318 <input type
="hidden" name
="email_reminder_confirm" value
="1"/>
7319 <input name
="email_address" style
="width:90%;" value
="your_email\@address.com"/ onfocus
="address_focus()">
7321 <select name
="reminder_time">
7322 <option value
="604800, $lang{email_reminder_option1}">$lang{email_reminder_option1
}</option
>
7323 <option value
="172800, $lang{email_reminder_option2}">$lang{email_reminder_option2
}</option
>
7324 <option value
="86400, $lang{email_reminder_option3}">$lang{email_reminder_option3
}</option
>
7325 <option value
="3600, $lang{email_reminder_option4}">$lang{email_reminder_option4
}</option
>
7326 <option value
="1800, $lang{email_reminder_option5}">$lang{email_reminder_option5
}</option
>
7327 <option value
="900, $lang{email_reminder_option6}">$lang{email_reminder_option6
}</option
>
7329 $lang{email_reminder_text3
}
7331 $lang{email_reminder_text7
}
7332 <textarea name
="extra_text" style
="width:90%" rows
="4">
7335 <input type
="checkbox" name
="send_test_now" value
="1"> $lang{email_reminder_text4
}
7339 if ($current_event{series_id
} ne "") {
7341 <input type="checkbox" name="all_in_series" value="1"/> $lang{email_reminder_text6}
7346 <input type
="submit" value
="$lang{email_reminder_text5}"/>
7352 $template_html =~ s/<title>.*<\/title>/$title/s
;
7353 $template_html =~ s/<body.*>.*<\/body>/$results/s
;
7354 $template_html =~ s/###css file###/$css_path/g;
7357 Cache-control: no-cache,no-store,private
7358 Content-Type: text/html; charset=$lang{charset}\n
7359 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
7362 } # email_reminder_prompt
7365 sub email_reminder_confirm {
7366 my %current_event = %{$events{$current_event_id}};
7368 my $reminder_results = "";
7369 my $to_address = $q->param('email_address');
7370 my $extra_text = $q->param('extra_text');
7371 $to_address =~ s/\s//g;
7372 $to_address =~ s/;/,/g;
7375 my ($reminder_seconds, $reminder_time) = split(/, ?/,$q->param('reminder_time'));
7376 $reminder_time = lc $reminder_time;
7378 my $email_valid = &validate_emails($to_address);
7380 if ($email_valid ne "") {
7381 $reminder_results = $lang{email_reminder_invalid_address};
7382 $reminder_results =~ s/###address###/$email_valid/g;
7384 my @event_reminder_ids = ($current_event{id});
7385 my @future_event_reminder_ids;
7386 if ($q->param('all_in_series') ne "") {
7387 @event_reminder_ids = &get_events_in_series($current_event{series_id});
7388 &normalize_timezone();
7391 foreach $event_reminder_id (@event_reminder_ids) {
7392 if ($events{$event_reminder_id}{start} > $rightnow) {
7393 push @future_event_reminder_ids, $event_reminder_id;
7397 foreach $event_reminder_id (@future_event_reminder_ids) {
7398 # assemble email reminder xml
7399 my $reminder_xml = "";
7400 $reminder_xml .= &xml_store($event_reminder_id, "evt_id").
7401 &xml_store($reminder_seconds, "before").
7402 &xml_store($to_address, "email_address").
7403 &xml_store($extra_text, "extra_text").
7404 &xml_store("$script_url/$name", "script_url").
7405 &xml_store($rightnow, "timestamp");
7406 $reminder_xml = "<email_reminder>$reminder_xml</email_reminder>\n";
7408 # write email reminder to file
7409 open (FH, ">>$options{email_reminders_datafile}") || ($debug_info .="<br/>Unable to open email reminders data file $options{email_reminders_datafile} for writing<br/>");
7410 print FH $reminder_xml;
7414 my $test_reminder_results = "";
7415 if ($q->param('send_test_now') == 1) {
7416 my $reminder_text = $lang{email_reminder_test_text};
7417 $reminder_text =~ s/###reminder_time###/$reminder_time/g;
7419 my $date_string = &nice_date_range_format($current_event{start}, $current_event{end}, " - ");
7421 my $event_time = "";
7422 if ($current_event{all_day_event} ne "1") {
7423 $event_time = &nice_time_range_format($current_event{start}, $current_event{end});
7425 $reminder_text =~ s/###time###/$event_time/g;
7426 $reminder_text =~ s/###title###/$current_event{title}/g;
7427 $reminder_text =~ s/###date###/$date_string/g;
7428 $reminder_text =~ s/###extra text###/$extra_text/g;
7429 $reminder_text =~ s/###details###/$current_event{details}/g;
7430 $reminder_text =~ s/###link###/$script_url\/$name?view_event=1&evt_id=$current_event{id}/g;
7432 #$debug_info .= "$reminder_text\n";
7434 $test_reminder_results = &send_email_reminder(\%current_event, $to_address, $reminder_text);
7435 if ($test_reminder_results eq "1") {
7436 $test_reminder_results = $lang{email_reminder_test_success};
7437 $test_reminder_results =~ s/###address###/$to_address/g;
7439 $test_reminder_results = $lang{email_reminder_test_fail};
7440 $test_reminder_results =~ s/###results###/$test_reminder_results/g;
7444 $lang{email_reminder_results1} =~ s/###address###/$to_address/g;
7445 $lang{email_reminder_results1} =~ s/###reminder time###/$reminder_time/g;
7447 if ($q->param('send_test_now') == 1) {
7448 $lang{email_reminder_results1} .= $lang{email_reminder_results3}} else {
7449 $lang{email_reminder_results1} .= $lang{email_reminder_results2}}
7452 $reminder_results = <<p1;
7453 $lang{email_reminder_results1
}
7455 $test_reminder_results
7459 $debug_info =~ s/\n/<br\/>\n/g
;
7461 my $html_output .=<<p1;
7462 Cache-control: no-cache,no-store,private
7463 Content-Type: text/html; charset=$lang{charset}\n
7464 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
7468 <meta http-equiv="pragma" content="no-cache">
7469 <link rel="stylesheet" href="$css_path" type="text/css" media=screen>
7470 <title>$current_event{title}$lang{email_reminder_title}</title>
7474 <div class="event_details" style="background-color:$current_event{bgcolor};text-align:left;">
7475 <p style
="margin-top:20px;margin-bottom:20px;">
7485 } # email_reminder_confirm
7487 sub detect_remote_calendars
() {
7488 my $remote_calendar_url = $q->param('remote_calendar_url');
7489 $remote_calendar_url =~ s/\?.+//;
7490 #$debug_info .= "url: $remote_calendar_url\n";
7492 $remote_calendar_url .= "/" if ($remote_calendar_url !~ /\
.cgi
$/);
7493 $remote_calendar_base_url = $remote_calendar_url;
7494 $remote_calendar_url .= "?remote_calendar_request=1&get_public_calendars=1";
7495 #$debug_info .= "remote_calendar_url: $remote_calendar_url\n";
7497 my $xml_results = &get_remote_file
($remote_calendar_url);
7499 #$debug_info .= "xml results: ".&xml2html($xml_results)."\n";
7500 #$results =~ s/>/>/g;
7501 #$results =~ s/</</g;
7503 my %remote_calendars = %{&xml2hash
($xml_results)};
7505 my @public_calendars;
7507 if (ref $remote_calendars{'xml'}{public_calendar
} eq "ARRAY") {
7508 #$debug_info .= "found remote calendars!\n";
7509 @public_calendars = @
{$remote_calendars{'xml'}{public_calendar
}};
7511 #$debug_info .= "found remote calendar: $remote_calendars{'xml'}{public_calendar})\n";
7512 #$debug_info .= "found remote calendar: ".&xml2html($remote_calendars{'xml'}{public_calendar})."\n";
7513 push @public_calendars, $remote_calendars{'xml'}{public_calendar
};
7516 $remote_calendar_info .= <<p1;
7517 <p style
="clear:both;">
7518 $lang{detect_remote_calendars1
} <a target
="_blank" href
="$remote_calendar_base_url">$remote_calendar_base_url</a
>:
7520 <div style
="float:left;width:95%;border:solid 1px #000;">
7521 <form name
="cal_merge_form">
7526 foreach $temp (@public_calendars) {
7527 my %public_calendar = %{$temp};
7528 my $list_class="list_odd";
7530 my $merge_xml = <<p1;
7532 <type>plans</type><version>$remote_calendars{'xml'}{'plans_version'}</version>
7533 <url>$remote_calendar_base_url</url>
7534 <remote_id>$public_calendar{id}</remote_id>
7535 <password>###password###</password>
7539 #$merge_xml =~ s/\//\\\//g;
7540 $merge_xml =~ s/\n//g;
7541 $merge_xml =~ s/"/\\"/g;
7544 if ($index%2 == 0) {
7545 $list_class="list_even"}
7547 $remote_calendar_info .= <<p1;
7548 <div
class="$list_class" style
="float:left;clear:left;width:100%;">
7550 #$remote_calendar_info .= "public calendar: ".$remote_calendars{'xml'}{public_calendar}."<br/>";
7551 $remote_calendar_info .= <<p1;
7552 <div style="float:left;font-weight:bold;padding:3px;white-space:nowrap;">$public_calendar{title}</div>
7555 $remote_calendar_info .= <<p1;
7556 <div style
="float:left;padding:3px;white-space:nowrap;">$lang{detect_remote_calendars2
}<input type
="checkbox" id
="remote_cal_$index" name
="remote_cal_$index" value
= "$merge_xml">
7558 if ($public_calendar{requires_password
} ne "") {
7559 $remote_calendar_info .= <<p1;
7560 <span style="margin-left:1em;white-space:nowrap;">($lang{detect_remote_calendars3}): <input id="password_$index" name="password_$index" style="width:6em;"></span>
7563 $remote_calendar_info .= <<p1;
7568 $remote_calendar_info .= <<p1;
7573 $remote_calendar_info .= <<p1;
7579 $remote_calendar_info .= <<p1;
7580 <p style
="clear:both;padding-top:1em;"><a href
="javascript:merge_selected()">$lang{detect_remote_calendars4
}</a></p>
7584 $remote_calendar_info .= <<p1;
7585 <p style
="clear:both;padding-top:1em;">$lang{detect_remote_calendars5
}</p
>
7589 #<br style="clear:both;"/>
7590 #<br style="clear:both;"/>
7593 #my $temp_xml_results = $xml_results;
7594 #$temp_xml_results =~ s/>/>/g;
7595 #$temp_xml_results =~ s/</</g;
7596 #$debug_info .= $temp_xml_results;
7599 my $popup_javascript_info = "";
7601 $popup_javascript_info .=<<p1;
7602 <script type="text/javascript" ><!--
7605 if ($browser_type eq "IE") {
7606 $popup_javascript_info .=<<p1;
7607 function do_onresize
() {
7608 opener
.info_window_width
= document
.body
.clientWidth
;
7609 opener
.info_window_height
= document
.body
.clientHeight
;
7613 $popup_javascript_info .=<<p1;
7614 function do_onresize() {
7615 opener.info_window_width = this.outerWidth;
7616 opener.info_window_height = this.outerHeight;
7621 $popup_javascript_info .=<<p1;
7622 function opener_test
() {
7623 //alert
("about to test opener " + opener
.info_window_width
);
7627 function merge_selected
() {
7630 while (document
.getElementById
("remote_cal_"+l1
)) {
7631 var el
= document
.getElementById
("remote_cal_"+l1
);
7635 if (document
.getElementById
("password_"+l1
))
7636 temp
= el
.value
.replace
(/###password###/, document
.getElementById
("password_"+l1
).value
); else
7637 temp
= el
.value
.replace
(/###password###/, "");
7643 if (merge_xml
!= "")
7644 opener
.set_merge_xml
("<remote_calendars>"+merge_xml
+"</remote_calendars>");
7654 my $html_output .=<<p1;
7655 Cache-control: no-cache,no-store,private
7656 Content-Type: text/html; charset=$lang{charset}\n
7660 $debug_info =~ s/\n/<br\/>\n/g;
7662 $html_output .=<<p1;
7665 <title
>$lang{get_remote_calendars
}</title
>
7666 <link rel
="stylesheet" href
="$css_path" type
="text/css" media
="screen"/>
7668 <body onResize
="javascript:do_onresize();">
7669 $popup_javascript_info
7670 <div
class="info_box" style
="padding:5px;"><br
/>
7675 $html_output .=<<p1;
7676 $remote_calendar_info
7687 sub remote_calendar_request() {
7688 my $html_output .=<<p1;
7689 Cache
-control
: no-cache
,no-store
,private
7690 Content
-Type
: text
/xml
; charset
=$lang{charset
}\n
7694 my $current_cal_ids_string = $q->param('cal_id');
7697 <plans_version>$plans_version</plans_version>
7700 #$debug_info .= "remote calendar request!";
7702 # if the client requests a list of all calendars that are publically share-able.
7703 if ($q->param('get_public_calendars') eq "1") {
7704 foreach $cal_id (keys %calendars) {
7705 if ($calendars{$cal_id}{allow_remote_calendar_requests}) {
7706 my $temp=$calendars{$cal_id}{remote_calendar_requests_require_password};
7708 <public_calendar
><id
>$cal_id</id><title>$calendars{$cal_id}{title}</title
><requires_password
>$temp</requires_password></public_calendar
>
7712 } else { # return xml data for the events.
7714 my @current_cal_ids = ();
7715 my @temp = split (",",$current_cal_ids_string);
7719 foreach $cal_id (@temp) {
7720 if ($cal_id !~ /\D/) {
7721 push @current_cal_ids, $cal_id;
7724 $results .= "<error>Invalid calendar ID: $cal_id</error>";
7728 if ($cal_id_valid) {
7729 foreach $current_cal_id (@current_cal_ids) {
7731 <calendar><id>$current_cal_id</id><title>$calendars{$current_cal_id}{title}</title><gmtime_diff>$calendars{$current_cal_id}{gmtime_diff}</gmtime_diff></calendar>
7735 foreach $current_cal_id (@current_cal_ids) {
7736 foreach $event_id (keys %events) {
7738 my $event_in_current_calendar = 0;
7740 foreach $temp_cal_id (@{$events{$event_id}{cal_ids}}) {
7741 if ($temp_cal_id eq $current_cal_id) {
7742 $event_in_current_calendar = 1;
7747 next if ($event_in_current_calendar == 0);
7749 my $xml_data = &event2xml($events{$event_id});
7758 if ($debug_info ne "") {
7759 $results .= "<debug_info>$debug_info</debug_info>";}
7761 $html_output .= "<xml>$results</xml>";
7770 #******************* the following subroutines don't display any HTML **********
7775 sub diagnostic_info
() {
7779 <b>Script Name:</b>$name<br/>
7783 if ($options{email_mode} && !$writable{email_reminders_datafile}) {
7785 <b
>Warning
:</b
> The email reminders data file
: $options{email_reminders_datafile
} is
not writable
. This will
7786 cause some email functions to be disabled
or not work correctly
.<br
/>
7789 if ($options{data_storage_mode
} == 0 && !$writable{calendars_file
}) {
7791 <b>Warning:</b> The calendars data file: $options{calendars_file} is not writable. The add/edit calendars tab won't appear
7792 unless this file is writable.<br/>
7795 if ($options{data_storage_mode} == 0 && !$writable{pending_actions_file}) {
7797 <b
>Warning
:</b> The pending actions data file: $options{pending_actions_file} is not writable. The add/edit calendars tab won
't appear
7798 unless this file is writable.<br/>
7801 if ($options{data_storage_mode} == 0 && !$writable{events_file}) {
7803 <b>Warning:</b> The events data file: $options{events_file} is not writable. The add/edit events tab won't appear
7804 unless this file is writable
.<br
/>
7811 <b>Plans version:</b> $plans_version<br/>
7812 <b>Perl version:</b> $perl_version<br/>
7813 <b>script name:</b> $name<br/>
7814 <b>script file path:</b> <span style="color:#00f;">$cwd</span><br/>
7815 <b>script url path:</b> $script_url<br/>
7817 <b>Theme url:</b> $theme_url<br/>
7818 <b>graphics url:</b> $graphics_url<br/>
7819 <b>icons url:</b> $icons_url<br/>
7821 <b>Options:</b><br/>
7824 # blank out options that we don't want public
7825 delete $options{db_name};
7826 delete $options{db_hostname};
7827 delete $options{db_username};
7828 delete $options{db_password_file};
7829 delete $options{mysql_password};
7830 delete $options{salt};
7832 foreach $option (keys %options) {
7834 <b
>$option:</b> $options{$option}<br/>
7839 } # end diagnostic subroutine
7842 sub assemble_icon_menus
() {
7843 # this function extracts a data structure for the icon menus from the xml definition
7846 # first, get the menuitems
7847 my @new_menuitems=();
7849 my @menuitems = &xml_extract
($data, "menuitem", 0);
7850 if (scalar @menuitems == 0) {
7851 $debug_info .= "Warning. There's a menu with no menuitems. This may be caused by an older version of Perl ( < 5.6).\n";
7852 $debug_info .= "$data";
7854 foreach my $menuitem (@menuitems) {
7855 #$debug_info .= "menuitem: $menuitem->{data} ($menuitem->{position})<br/>";
7856 my $icon_name = $menuitem->{attributes
}{"value"};
7857 my $icon_description = $menuitem->{data
};
7858 $icon_description = &encode
($icon_description);
7859 $new_menuitems[$menuitem->{position
}] = [$icon_name,$icon_description];
7860 #$new_menuitems[$menuitem->{position}] = "name,description";
7864 # then get the submenus
7865 my @submenus = &xml_extract
($data, "menu", 0);
7866 foreach $submenu (@submenus) {
7867 my $temp = $submenu->{data
};
7868 my $temp2 = $submenu->{attributes
}{name
};
7869 my @submenuitems = assemble_icon_menus
($temp);
7870 #$debug_info .= "submenu: $temp2 ($submenu->{position})<br/>";
7871 $new_menuitems[$submenu->{position
}] = [$temp2, \
@submenuitems];
7874 return @new_menuitems;
7875 } #******************** end assemble_icon_menus **********************
7878 sub generate_flat_icon_menus
{
7879 my ($icons_list, $selected_icon) = @_;
7881 #$debug_info .= "selected icon: $selected_icon<br/>";
7884 for ($l1=0;$l1<$index_number;$l1++) {
7888 foreach $icon_ref (@
{$icons_list}) {
7889 my $identifier = @
{$icon_ref}[1];
7891 if ($identifier =~ /ARRAY/) { # if it's a submenu
7892 $icon_menu_index_number++;
7893 my $submenu_name = @
{$icon_ref}[0];
7895 #$debug_info .= "submenu $submenu_name<br/>";
7897 $return_text .= <<p1;
7898 <optgroup label="$submenu_name">
7900 $return_text .= &generate_flat_icon_menus(@{$icon_ref}[1], $selected_icon);
7901 $return_text .= <<p1;
7904 } else { # if it's a menu item
7905 my $icon_filename = @
{$icon_ref}[0];
7906 my $icon_name = @
{$icon_ref}[1];
7908 $icon_name = &decode
($icon_name);
7909 #$debug_info .= "icon name: $icon_name <br/>";
7910 #$debug_info .= "icon filename: $icon_filename <br/>";
7911 #$debug_info .= "<br/>";
7913 if ($icon_filename eq $selected_icon) {
7914 $return_text .= <<p1;
7915 <option value = "$icon_filename" selected>$icon_name</option>
7918 $return_text .= <<p1;
7919 <option value
= "$icon_filename">$icon_name</option
>
7924 return $return_text;
7926 } #******************** end generate_flat_icon_menus **********************
7929 sub get_upcoming_events
() {
7930 my $days_before = $q->param('days_before')+0;
7931 my $days_after = $q->param('days_after')+0;
7932 my $background_calendars_mode = $q->param('background_calendars_mode');
7933 my $upcoming_events_id = $q->param('upcoming_events_id');
7936 my $start = $rightnow - $days_before*86400;
7937 my $end = $rightnow + $days_after*86400;
7938 #$debug_info .= "start: $start\n";
7939 #$debug_info .= "end: $end\n";
7941 #$debug_info .= (scalar keys %events)." events\n";
7944 #$debug_info .= (scalar keys %events)." events\n";
7946 my @cal_ids = split(',',$q->param('cal_ids'));
7947 #$debug_info .= "cal_ids[0]: $cal_ids[0]\n";
7948 #$debug_info .= "cal_ids[1]: $cal_ids[1]\n";
7951 #&load_events("all");
7953 #$debug_info .= (scalar keys %events)." events\n";
7956 #$results .= &common_javascript();
7957 my $date_format = lc $current_calendar{date_format
};
7958 $results .= "date_format = '$date_format';\n";
7960 my %all_calendar_ids;
7962 foreach $calendar_id (@cal_ids) {
7963 next if ($calendars{$calendar_id}{id
} eq "");
7965 foreach $local_background_calendar_id (keys %{$calendars{$calendar_id}{local_background_calendars
}}) {
7966 $all_calendar_ids{$local_background_calendar_id} = 1;
7968 $all_calendar_ids{$calendar_id} = 1;
7971 foreach $calendar_id (keys %all_calendar_ids) {
7972 $results .= "calendars['$calendar_id'] = new Calendar({".&calendar2javascript
($calendars{$calendar_id})."});\n";
7976 if ($background_calendars_mode ne "none") {
7977 @temp = keys %all_calendar_ids;
7982 &load_events
($start, $end, \
@temp);
7983 &normalize_timezone
;
7985 $results .= "all_calendars = new Array('".(join "','", keys %all_calendar_ids)."');\n";
7987 foreach $event_id (keys %events) {
7988 $results .= "upcoming_events['$event_id'] = new Event({".&event2javascript
($events{$event_id})."});\n";
7989 $results .= "upcoming_events_order.push('$event_id'); \n";
7992 if ($debug_info ne "") {
7993 $debug_info = &javascript_cleanup
($debug_info);
7994 #$debug_info = "debug_info = '$debug_info';\n";
7995 $results .= "if ($upcoming_events_id.debug) debug('$debug_info');\n";
7998 $results .= "$upcoming_events_id.plans_theme_url='$theme_url';\n";
7999 $results .= "$upcoming_events_id.show();\n";
8001 my $nice_expires = $rightnow + $options{upcoming_events_cache_seconds
};
8002 $nice_expires = uc &formatted_time
($nice_expires, "mn/md/yy hh:mm:ss AMPM");
8004 my $cache_line = "Cache-control: no-cache,no-store,private";
8005 $cache_line = "Cache-Control: max-age=$options{upcoming_events_cache_seconds};\nExpires: $nice_expires;" if ($options{upcoming_events_cache_seconds
} > 0);
8008 my $html_output .=<<p1;
8010 Content-Type: text/html; charset=$lang{charset}\n
8023 sub export_calendar_link() {
8027 <a href
="javascript:document.export_cal_form.submit();">$lang{export
}</a
> $lang{these_events_to
}
8028 <form name
="export_cal_form" target
="_blank" action
="$script_url/$name" method
="POST">
8029 <input type
="hidden" name
="export_calendar" value
=1>
8031 <select name
="export_type">
8032 <option value
="ascii_text">$lang{text_option
}
8033 <option value
="csv_file">$lang{csv_file
}
8034 <option value
="csv_file_palm">$lang{csv_file_palm
}
8035 <option value
="icalendar">$lang{icalendar_option
}
8036 <option value
="vcalendar">$lang{vcalendar_option
}
8046 sub add_edit_user
() {
8050 my $id = $q->param('user_id');
8051 my $name = $q->param('name');
8052 my $notes = $q->param('notes');
8053 my $password = $q->param('password');
8054 my $new_password = $q->param('new_password');
8055 my $repeat_password = $q->param('repeat_password');
8056 my $delete_flag = $q->param('delete');
8059 #$results .= "add/edit user!";
8060 #$debug_info .= "cal_password: ".$q->param('cal_password')."\n";
8061 #$debug_info .= "logged_in_as_root: $logged_in_as_root\n";
8062 #$debug_info .= "logged_in_as_current_cal_admin: $logged_in_as_current_cal_admin\n";
8064 $results .= "success = false;";
8066 my $login_valid = 0;
8068 if ($logged_in_as_root) { # plans 'root' password
8069 $login_valid = 1;} elsif ($logged_in_as_current_cal_admin) { # current calendar admin
8072 #$debug_info .= "login_valid: $login_valid\n";
8074 if (!$login_valid) {
8075 if ($delete_flag eq "1") {
8076 $results .= "messages = '$lang{user_not_deleted}';";} else {
8077 $results .= "messages = '$lang{user_not_added}';";}
8080 if ($delete_flag eq "1") {
8081 my $temp = $lang{user_deleted
};
8082 $temp =~ s/\$1/$users{$id}{name}/;
8083 $results .= "messages = '$temps';";
8085 delete $user{calendars
}{$calendar_id};
8087 #$debug_info .= "user $user_id, ".(scalar keys %{$user{calendars}})." calendars\n";
8089 if (scalar keys %{$user{calendars
}} == 0) {
8090 delete $users{$user_id};
8092 &update_user
($user_id);
8095 $results .= "success = true;";
8096 $results .= "users = new Array();";
8097 $results .= &generate_users_javascript
();
8100 if ($id eq "") { # add
8102 $password = crypt($password, $options{salt
});
8104 my $new_id = $max_user_id+1;
8106 $cal_refs{$current_cal_id}{edit_events
} = 1;
8108 $users{$new_id} = {id
=> $new_id,
8111 password
=> $password,
8112 calendars
=> \
%cal_refs
8116 $results .= "success = true;";
8117 $results .= "users = new Array();";
8118 $results .= &generate_users_javascript
();
8120 $results .= "messages += '$lang{user_added}';";
8122 $password = crypt($password, $options{salt
});
8125 $cal_refs{$current_cal_id}{edit_events
} = 1;
8127 $users{$id} = {id
=> $id,
8130 password
=> $password,
8131 calendars
=> \
%cal_refs
8135 $results .= "success = true;";
8136 $results .= "users = new Array();";
8137 $results .= &generate_users_javascript
();
8139 $results .= "messages += '$lang{user_updated}';";
8143 $results .= "messages += '###debug_info###';";
8146 $debug_info =~ s/\//\\\
//g;
8147 $debug_info =~ s/\n/<br\/>/g
;
8148 $debug_info =~ s/"/\\"/g;
8149 $debug_info =~ s/'/\\'/g;
8150 $results =~ s/###debug_info###/$debug_info/;
8153 Cache-control: no-cache,no-store,private
8154 Content-Type: text/html; charset=iso-8859-1\n
8162 my $ical_url = &decode($q->param('ical_url'));
8165 if (!$logged_in_as_root) {
8166 $results .= "messages = 'You must be logged in to add an iCal!';";
8167 $results .= "var successful = false;";
8169 # try getting the URL
8170 my $url_results = &get_remote_file($ical_url);
8171 $debug_info .= $url_results;
8173 if ($url_results eq "404 not found!" || $url_results =~ /cannot connect/i) {
8174 $results .= "messages = 'iCal calendar <b>not</b> added! (invalid url)';";
8175 $results .= "var successful = false;";
8177 my %new_calendar = &deep_copy(\%default_cal);
8178 my $new_cal_id = $max_cal_id + 1;
8180 $new_calendar{id} = $new_cal_id;
8181 $new_calendar{title} = "($ical_url)";
8182 $new_calendar{type} = "ical";
8183 $new_calendar{url} = $ical_url;
8185 $calendars{$new_cal_id} = &deep_copy(\%new_calendar);
8187 &add_calendars([$new_calendar{id}]);
8189 $results .= "messages = 'iCal calendar ($ical_url) added!';";
8190 $results .= "success = true;";
8194 $debug_info =~ s/\//\\\//g;
8195 $debug_info =~ s/\n/<br\/>/g;
8196 $debug_info =~ s/"/\\"/g;
8197 $debug_info =~ s/'/\\'/g;
8198 #$results .= "\ndebug_info: $debug_info";
8201 Cache
-control
: no-cache
,no-store
,private
8202 Content
-Type
: text
/html
; charset
=iso
-8859-1\n
8215 $results .= "logged_in = true;";
8216 $results .= "messages = get_lang('logged_in1')+'<br/>###debug_info###';";
8217 $results .= "setcookie('plans_sid','".$session->id."', null, '$cookie_path');";
8218 } elsif( $q->param('logout') eq "1") {
8219 $results .= "logged_in = false;";
8220 $results .= "messages = get_lang('logged_in2')+'<br/>###debug_info###';";
8222 $results .= "logged_in = false;";
8223 $results .= "messages = get_lang('logged_in3')+'<br/>###debug_info###';";
8226 $debug_info =~ s/\//\\\
//g;
8227 $debug_info =~ s/\n/<br\/>/g
;
8228 $debug_info =~ s/"/\\"/g;
8229 $debug_info =~ s/'/\\'/g;
8230 $results =~ s/###debug_info###/$debug_info/;
8233 Cache-control: no-cache,no-store,private
8234 Content-Type: text/html; charset=iso-8859-1\n
8243 sub manage_pending_events() {
8244 &normalize_timezone();
8246 my $approve = $q->param('approve');
8247 my $delete = $q->param('delete');
8251 if ($logged_in_as_root || $logged_in_as_current_cal_admin) {
8252 $add_edit_event = "add";
8254 $approve =~ s/[^(\d|,)]//g;
8255 $approve =~ s/[^(\d|,)]//g;
8257 my @events_to_approve = split(',', $q->param('approve'));
8258 my @events_to_delete = split(',', $q->param('delete'));
8260 foreach $event_to_approve (@events_to_approve) {
8261 &commit_event($new_events{$event_to_approve});
8263 my $temp = $lang{pending_event_approved};
8264 $temp =~ s/\$1/$event_to_approve/;
8265 $messages .= "$temp\n";
8267 foreach $event_to_delete (@events_to_delete) {
8268 my $temp = $lang{pending_event_deleted};
8269 $temp =~ s/\$1/$event_to_delete/;
8270 $messages .= "$temp\n";
8273 push @events_to_delete, @events_to_approve;
8274 &delete_pending_actions(\@events_to_delete);
8276 $debug_info =~ s/\//\\\//g;
8277 $debug_info =~ s/\n/<br\/>/g;
8278 $debug_info =~ s/"/\\"/g;
8279 $debug_info =~ s/'/\\'/g;
8281 if ($debug_info != "") {$messages = "Debug info: $debug_info";}
8283 $messages =~ s/\//\\\//g;
8284 $messages =~ s/\n/<br\/>/g;
8285 $messages =~ s/"/\\"/g;
8286 $messages =~ s/'/\\'/g;
8287 #$results .= "messages = '$messages';\n";
8289 $results .= "window.location='$script_url/$name?messages=".&encode($messages)."';";
8290 #$results .= "alert(\"window.location=$script_url/$name&messages=".&encode($messages)."\");";
8292 $results .= "messages = '$lang{invalid_password}';update_messages();";
8293 $results .= "cal_password = '';";
8297 Cache
-control
: no-cache
,no-store
,private
8298 Content
-Type
: text
/html
; charset
=iso
-8859-1\n
8308 sub generate_calendars_javascript
() {
8311 foreach $calendar_id (sort {$a <=> $b} keys %calendars) {
8312 my %calendar = %{$calendars{$calendar_id}};
8313 $results .= "calendars[$calendar_id] = new Object;";
8314 $results .= "calendars[$calendar_id].users = new Array();";
8316 foreach $user_ref (@
{$calendar{users
}}) {
8317 my %user = %{$user_ref};
8318 $results .= "calendars[$calendar_id].users[$user{id}] = new Object;";
8325 sub api_add_delete_events
() {
8328 #$debug_info .= "(api_add_delete_events) before add_edit_events $events{159}{start} - $events{159}{end}\n";
8329 my %add_edit_events_results = %{&add_edit_events
()};
8330 #$debug_info .= "(api_add_delete_events) after add_edit_events $events{159}{start} - $events{159}{end}\n";
8333 if ($api_output_format eq "javascript") {
8334 if ($add_edit_events_results{success
} eq "1") {
8335 $results .= "success=true;\n";
8337 $results .= "success=false;\n";
8341 foreach $results_message (@
{$add_edit_events_results{messages
}}) {
8342 $messages .= &javascript_cleanup
($results_message);
8345 $debug_info = &javascript_cleanup
($debug_info);
8346 $debug_info =~ s/\\n/<br\/>/g
;
8349 $rightnow_messages = "messages='$debug_info\\n$messages';\n";
8351 $results .= $rightnow_messages;
8352 $results .= "update_messages(messages);";
8353 $results .= "dialog_box.close();";
8355 if ($add_edit_events_results{success
} eq "1") {
8356 $results .= "window.location='$script_url/$name?messages=".&encode
($messages)."';";
8360 Cache-control: no-cache,no-store,private
8361 Content-Type: text/html; charset=iso-8859-1\n
8370 my $diagnostic_results = &diagnostic_info();
8373 $error_info =~ s/\n/<br>/g;
8375 $html_output .=<<p1;
8376 Cache
-control
: no-cache
,no-store
,private
8377 Content
-Type
: text
/html
; charset
=iso
-8859-1\n
8378 <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN">
8381 <title
>Plans error
!</title
>
8385 <b
>Plans error
:</b><br/>
8388 <b
>Diagnostic information
:</b><br/>
8392 if ($debug_info ne "") {
8393 $debug_info =~ s/\n/<br>/g;
8394 $html_output .=<<p1;
8401 $html_output .=<<p1;