#!/usr/bin/perl
# before anything else, the script needs to find out its own name
#
# some servers (notably IIS on windows) don't set the cwd to the script's
# directory before executing it. So we get that information
# from $0 (the full name & path of the script).
BEGIN{($_=$0)=~s![\\/][^\\/]+$!!;push@INC,$_}
$name = $0;
$name =~ s/.+\/?.+\///; # for unix
$name =~ s/.+\\.+\\//; # for windows
$path = $0;
$path =~ s/(.+\/).+/$1/g; # for unix
$path =~ s/(.+\\).+/$1/g; # for windows
# The "use Cwd" method would be nice, but it doesn't work with
# some versions of IIS/ActivePerl
#use Cwd;
#$path = cwd;
if ($path ne "") {
chdir $path;
push @INC,$path;
}
# finished discovering name
#use Data::Dumper;
# some global variables (more further down)
local $plans_version = "7.10"; # version
local $debug_info;
local %options;
local $perl_version = (sprintf ("%vd",$^V));
#local $options{data_storage_mode};
local $fatal_error = 0; # fatal errors cause plans to abort and print an error message to the browser
local $error_info = "";
local $html_output;
local $script_url = "";
local $messages = ""; # formatted in plain text with newlines. Converted to html at display time.
local $template_html;
local $local_template_file = 0; # tells whether the template was loaded via a filesystem open or through a http request.
local $event_details_template;
local $list_item_template;
local $calendar_item_template;
local $upcoming_item_template;
local %calendars;
local %current_calendar;
local %latest_calendar;
local %new_calendars;
local $normalized_timezone = 0;
local $normalized_timezone_pending_events = 0;
# used when adding new entries
local $max_cal_id = 0;
local $max_event_id = 0;
local $max_series_id = 0;
local $max_user_id = 0;
local $max_action_id = 0;
# used to protect against refreshes
local $latest_cal_id = 0;
local $latest_event_id = 0;
local $latest_new_cal_id = 0;
local $latest_new_event_id = 0;
local $session;
local %users;
my $profile;
local $logged_in = 0;
local $logged_in_as_root = 0;
local $logged_in_as_current_cal_user = 0;
local $logged_in_as_current_cal_admin = 0;
local $lg_name = "";
local $lg_password = "";
local %events;
local %new_events;
local @pending_events_to_display;
local %text;
local %cookie_parms;
local $cookie_text = "";
local $cookie_header_text = "";
local $max_remote_event_id = 0;
local $options{default_template_path} = "";
local $theme_url = "";
local $options{choose_themes} = "";
local $graphics_url = "";
local $ical_export_url = "";
local $icons_url = "";
local $input_cal_id_valid = 0;
local $options{right_click_menus_enabled} = 0;
local %cal_options;
local $rightnow;
local @months;
local @months_abv;
local @day_names;
local $loaded_all_events; # flag used to avoid calling load_events("all") twice
# not needed for calendars (we always load all calendars)
local @disabled_tabs;
# check for required modules.
my $module_found=0;
foreach $temp_path (@INC) {
if (-e "$temp_path/plans_config.pl") {
$module_found=1;}
}
if ($module_found == 0) {
$fatal_error=1;
$error_info .= "Unable to locate plans_config.pl! It should be in the same directory as plans.cgi!\n";
} else {require "plans_config.pl";}
$module_found=0;
foreach $temp_path (@INC) {
if (-e "$temp_path/CGI") {
$module_found=1;}
}
if ($module_found == 0) {
$fatal_error=1;
$error_info .= "unable to locate required module CGI!\n";
} else {
use CGI;}
$module_found=0;
foreach $temp_path (@INC) {
if (-e "$temp_path/CGI/Session") {
$module_found=1;}
}
if ($options{sessions} eq "1") {
if ($module_found == 0) {
$fatal_error = 1;
$error_info .= "unable to locate required module CGI::Session!\n";
} else {
require CGI::Session;}
}
$module_found=0;
foreach $temp_path (@INC) {
if (-e "$temp_path/CGI/Carp.pm") {
$module_found=1;}
}
if ($module_found == 0) {
$fatal_error=1;
$error_info .= "unable to locate required module CGI::Carp!\n";
} else {
use CGI::Carp qw/fatalsToBrowser/;}
$module_found=0;
foreach $temp_path (@INC) {
if (-e "$temp_path/Time") {
$module_found=1;}
}
if ($module_found == 0) {
$fatal_error=1;
$error_info .= "unable to locate required module Time.pm!\n";
} else {
use Time::Local;}
$module_found=0;
foreach $temp_path (@INC) {
if (-e "$temp_path/IO.pm") {
$module_found=1;}
}
if ($module_found == 0) {
$fatal_error=1;
$error_info .= "unable to locate required module IO.pm!\n";
} else {
use IO::Socket;}
if ($fatal_error == 1) { # print error and bail out
&fatal_error();
}
$module_found=0;
foreach $temp_path (@INC) {
if (-r "$temp_path/plans_lib.pl") {
$module_found=1;}
}
if ($module_found == 0) {
$fatal_error=1;
$error_info .= "Unable to locate plans_lib.pl! It should be in the same directory as plans.cgi!\n";
} else {require "plans_lib.pl";}
# multi-language stuff
if (defined $options{language_files}) {
my @language_files = split(',', $options{language_files});
# pull in language files
foreach $language_file (@language_files) {
$module_found=0;
foreach $temp_path (@INC) {
if (-r "$temp_path/$language_file") {
$module_found=1;}
}
if ($module_found == 0) {
$fatal_error=1;
$error_info .= "Unable to locate language file $language_file! It should be in the same directory as plans.cgi!\n";
} else {require $language_file;}
}
# create a javascript file with language strings
open (FH, "$options{default_theme_path}/$options{js_language_file}") || {$debug_info.= "unable to open file $options{default_theme_path}/$options{js_language_file}\n"};
flock FH,2;
my $first_lang_line=;
close FH;
if ($options{generate_js_lang} eq "1" || $first_lang_line !~ /$plans_version/) {
my $lang_string = "";
$lang_string .= "//$plans_version\n";
$lang_string .= "var plans_lang = new Array();\n";
# generate %lang keys
foreach $lang_key (keys %lang) {
if (ref $lang{$lang_key} eq "ARRAY") {
$lang_string .= "plans_lang['$lang_key']=new Array(";
my $first = 1;
foreach $key (@{$lang{$lang_key}}) {
if (!$first) {$lang_string .= ',';}
if ($first) {$first = 0;}
my $lang_val = &js_string($key);
$lang_string .= "'$lang_val'";
}
$lang_string .= ");\n";
} else {
my $lang_val = &js_string($lang{$lang_key});
$lang_string .= "plans_lang['$lang_key']='$lang_val';\n"
}
}
open (FH, ">$options{default_theme_path}/$options{js_language_file}") || {$debug_info .= "unable to open file $options{default_theme_path}/$options{js_language_file} for writing!\n"};
flock FH,2;
print FH $lang_string;
close FH;
}
} else {
$fatal_error=1;
$error_info .= "No language files defined in plans.config!\n";
}
# check for perl version
if ( ! check_perl_version( $perl_version, '5.6' ) ) {
$fatal_error=1;
$error_info .= "Your version of perl ($perl_version) is too old! Plans requires perl version 5.6 or better.\n";
}
if ($fatal_error == 1) { # print error and bail out
&fatal_error();
}
# init cgi stuff
$q = new CGI;
if ($options{calendar_url} ne "") {
$script_url = $options{calendar_url};
} else {
$script_url = $q->url(-path_info>=1);
}
$script_url =~ /(.*)\//; # remove trailing / and all text after
$script_url = $1; # remove trailing / and all text after
%cookie_parms = %{&extract_cookie_parms()};
my $cookie_path = $q->url( -absolute => 1 );
$cookie_path =~ s/$name$//;
$cookie_path =~ s/admin\/?$//; # This is better than using just '/'
# check if data files or tables are present
&check_data();
# fatal error? Print error and bail out
if ($fatal_error == 1) {
&fatal_error();}
if ($theme_url eq "") { # not defined in config file
$theme_url = "$script_url/theme";
}
if ($options{choose_themes}) {
$chosen_url = $q->param('theme_url');
$chosen_url = $cookie_parms{'theme_url'} if ($chosen_url eq "");
$theme_url = $chosen_url if ($chosen_url ne "");
}
$graphics_url ="$theme_url/graphics"; # where misc. graphics are
$ical_export_url ="$theme_url/ical"; # where icalendar .ics files are placed
$ical_export_url =~ s/http:\/\//$options{ical_prefix}/; # replace with custom prefix
$icons_url = "$theme_url/icons"; # where icons are
$css_path = "$theme_url/plans.css"; # css file
# globals from http parameters
my $active_tab = $q->param('active_tab') + 0; # +0 ensures numericity
$active_tab = 0 if ($active_tab > scalar @{$lang{tab_text}} - 1);
my $api_output_format = $q->param('output_format');
my $api_command = $q->param('api_command');
my $add_edit_cal_action = $q->param('add_edit_cal_action');
$add_edit_cal_action = "" if (!&contains(["add", "edit", "view_pending"],$add_edit_cal_action)); # validate
my $add_edit_event = $q->param('add_edit_event');
$add_edit_event = "" if (!&contains(["add", "edit"],$add_edit_event)); # validate
local $current_event_id = $q->param('evt_id');
$current_event_id = "" if ($current_event_id !~ /^R?\d+$/); # validate
local $pending_event_id = $q->param('pending_event_id');
$pending_event_id = "" if ($pending_event_id !~ /^R?\d+$/); # validate
local $cal_start_month = $q->param('cal_start_month') + 0; # +0 ensures numericity
local $cal_start_year = $q->param('cal_start_year') + 0; # +0 ensures numericity
local $cal_num_months = $q->param('cal_num_months') + 0; # +0 ensures numericity
# if view parameters not supplied in http request, check cookie
$cal_start_month = $cookie_parms{'cal_start_month'} if ($q->param('cal_start_month') eq "");
$cal_start_year = $cookie_parms{'cal_start_year'} if ($cal_start_year == 0);
$cal_num_months = $cookie_parms{'cal_num_months'} if ($cal_num_months == 0);
my $special_action = $q->param('special_action'); # needs no validation - never used in output
local $display_type = $q->param('display_type') + 0; # +0 ensures numericity
$display_type = $cookie_parms{'display_type'} if ($q->param('display_type') eq "");
$messages = $q->param('messages') if ($q->param('messages') ne "");
# other globals
my $event_start_date;
my $event_start_timestamp;
my $event_days;
my $start_mday;
my $start_mon;
my $start_year;
my @timestamp_array;
my $prev_month_link = "";
my $next_month_link = "";
# load calendar data
&load_calendars();
&load_users();
&load_actions();
local $current_cal_id = 0;
if ($q->param('cal_id') eq "") {
$current_cal_id = $cookie_parms{'cal_id'} if ($current_cal_id == 0);
} else {
$current_cal_id = $q->param('cal_id');
}
$current_cal_id += 0; # +0 ensures numericity
# if calendar id not supplied, but evt_id is supplied (like when viewing an event) use that event's calendar as the current calendar
#if ($current_event_id ne "")
#{
# &load_event($current_event_id);
#
# my %temp_current_event = %{$events{$current_event_id}};
# if ($current_cal_id eq "")
# {
# $current_cal_id = $temp_current_event{cal_ids}[0];
# }
#}
foreach $cal_id (keys %calendars) {
if ($cal_id eq $current_cal_id) {
$input_cal_id_valid = 1;}
}
if ($current_cal_id eq "") {
$input_cal_id_valid = 0;}
if ($current_cal_id =~ /\D/) {
$input_cal_id_valid = 0;}
$current_cal_id = 0 if ($current_event_id eq "" && !$input_cal_id_valid);
# make all calendars selectable by default
foreach $cal_id (keys %calendars) {
$default_cal{selectable_calendars}{$cal_id} = 1;}
%current_calendar = %{$calendars{$current_cal_id}};
# time-related globals
$rightnow = time() + 3600 * $current_calendar{gmtime_diff};
@rightnow_array = gmtime $rightnow;
$rightnow_year = $rightnow_array[5]+1900;
$rightnow_month = $rightnow_array[4];
$rightnow_mday = $rightnow_array[3];
$next_year = $rightnow_year+1;
$rightnow_description = formatted_time($rightnow, "hh:mm:ss mn md yy");
@weekday_sequence = @day_names;
# session stuff
if ($options{sessions} eq "1") {
#$lg_name = $q->param('lg_name');
$lg_name = $current_cal_id;
$lg_password = $q->param('cal_password');
&delete_old_sessions(1); # in days
#$debug_info .= "plans_sid (cookie): ".$q->cookie("plans_sid")."\n";
my $current_session_id = $q->cookie("plans_sid") || undef;
$session = new CGI::Session(undef, $current_session_id, {Directory=>$options{sessions_directory}});
$session->expire("+1d");
#$debug_info .= "current_session_id: $current_session_id\n";
# log out?
if ($q->param('logout') eq "1") {
$session->delete();
$cookie_text .= "Set-Cookie; plans_sid=deleted; path=$cookie_path;\n";
}
# try to match session with user id. (If this fails, it's not really a session.)
my $results = &init_session($q, $session);
$profile = $session->param("~profile");
if (defined $profile->{calendar_permissions}) {
$logged_in = 1;
$cookie_text .= "Set-Cookie: plans_sid=".$session->id."; path=$cookie_path;\n";
}
}
if ($options{sessions} eq "1") {
$logged_in_as_root = ($profile->{calendar_permissions}->{0}->{admin} eq "1") ? 1:0;
$logged_in_as_current_cal_user = ($profile->{calendar_permissions}->{$current_cal_id}->{user} ne "") ? 1:0;
$logged_in_as_current_cal_admin = ($profile->{calendar_permissions}->{$current_cal_id}->{admin} ne "") ? 1:0;
} elsif ($q->param('cal_password') ne "") {
$logged_in_as_root = ($calendars{0}{password} eq crypt($q->param('cal_password'), $options{salt})) ? 1:0;
$logged_in_as_current_cal_admin = ($current_calendar{password} eq crypt($q->param('cal_password'), $options{salt})) ? 1:0;
foreach $user_id (keys %users) {
my %user = %{$users{$user_id}};
my %user_calendars = %{$user{calendars}};
foreach $user_cal_id (keys %user_calendars) {
if ($user_cal_id eq $current_cal_id && $user{calendars}{$user_cal_id}{edit_events} eq "1" &&
$user{password} eq crypt($q->param('cal_password'), $options{salt})) {
$logged_in_as_current_cal_user = 1;
last;
}
last if ($logged_in_as_current_cal_user == 1);
}
last if ($logged_in_as_current_cal_user == 1);
}
}
$logged_in_as_current_cal_user = 0 if (!$options{users}) ;
#$debug_info .= "init_session results: $results\n";
#$debug_info .= "logged-in: ".$session->param("~logged-in")."\n";
#$debug_info .= "session id: ".$session->id."\n";
#$debug_info .= "profile user_id: ".$profile->{calendar_permissions}->{$current_cal_id}."\n";
#$debug_info .= "options{sessions}: $options{sessions}\n";
#$debug_info .= "logged_in_as_root: $logged_in_as_root\n";
#$debug_info .= "logged_in_as_current_cal_user: $logged_in_as_current_cal_user\n";
#$debug_info .= "logged_in_as_current_cal_admin: $logged_in_as_current_cal_admin\n";
#$debug_info .= "current_calendar{password}: $current_calendar{password}\n";
#$debug_info .= ($profile->{calendar_permissions}->{$current_cal_id}->{admin})."\n";
# custom stylesheet?
if ($current_calendar{custom_stylesheet} ne "") {
$css_path = "http://$current_calendar{custom_stylesheet}";
}
# if this is a custom calendar request, shoehorn the request parameters in
if ($q->param('custom_calendar') eq "1") {
$current_cal_id = $q->param('custom_calendar_calendar') + 0;
@custom_calendar_backgound_calendars = $q->param('custom_calendar_background_calendars');
foreach $local_background_calendar (keys %{$calendars{$current_cal_id}{local_background_calendars}}) {
delete $calendars{$current_cal_id}{local_background_calendars}{$local_background_calendar};}
foreach $local_background_calendar (@custom_calendar_backgound_calendars) {
$calendars{$current_cal_id}{local_background_calendars}{$local_background_calendar} = 1;}
%current_calendar = %{$calendars{$current_cal_id}};
}
# make sure we can select the current calendar
#$current_calendar{selectable_calendars}{$current_cal_id} = 1;
# set info window height & width
$current_calendar{info_window_size} ="400x400" if ($current_calendar{info_window_size} eq ""); # default
my ($info_window_width, $info_window_height) = split("x", $current_calendar{info_window_size});
# rotate weekday_sequence by the offset defined in the week start day.
for ($l1=0;$l1 < $current_calendar{week_start_day};$l1++) {
push @weekday_sequence, (shift @weekday_sequence);}
# load background_colors
my @temp_lines = split ("\n", $event_background_colors);
foreach $temp_line (@temp_lines) {
next if ($temp_line !~ /\w/); # skip any blank lines
$temp_line =~ s/^\s+//;
my ($hex_color, $hex_color_title) = split (/,*\s+/, $temp_line, 2);
$hex_color_title = " " if ($hex_color_title eq "");
push @event_bgcolors, {color => $hex_color, title => $hex_color_title};
}
#evaluate browser type and version
$_ = $ENV{HTTP_USER_AGENT};
if (/Mozilla/) {
if (/Opera.([0-9\.]+)/) { $browser_type = 'Opera'; $browser_version=$1;} elsif (/MSIE.([0-9.]+)/) { $browser_type = 'IE'; $browser_version = $1;} elsif (/Mozilla\/([0-9\.]+)/) {$browser_type = 'Mozilla'; $browser_version=$1;
if (($browser_version<5) || (/Netscape/)) {$browser_type = "Netscape";} }
if (/\)[^0-9.]+[0-9]*[\/\ ]([0-9.]+)/) {$browser_version=$1;}
} elsif (/(\w+)\/([0-9\.]+)/) {$browser_type = $1; $browser_version = $2}
#evaluate, transform, tweak, adjust, modify input values
#$debug_info .= "browser type: $browser_type ";
#if no month is selected, use the current month
if ($cal_start_month eq "" && $q->param('cal_start_month') eq "") {
$cal_start_month = $rightnow_month;
#$cal_start_month = 2;
}
#if the input year is out of range use the current year
if (($cal_start_year+0) < 1902 || ($cal_start_year+0)> 2037) {
$cal_start_year = $rightnow_year;
}
$cal_num_months = $current_calendar{default_number_of_months} if ($cal_num_months < 1);
$cal_num_months = $current_calendar{default_number_of_months} if ($cal_num_months > $current_calendar{max_number_of_months});
$cal_num_months = 1 if ($cal_num_months > $current_calendar{max_number_of_months});
$cal_num_months = 1 if ($cal_num_months == 0);
#calculate calendar end month and year
$cal_end_month = $cal_start_month;
$cal_end_year = $cal_start_year;
for ($l1=1;$l1<$cal_num_months;$l1++) {
$cal_end_month++;
if ($cal_end_month == 12) {
$cal_end_month=0;
$cal_end_year++;
}
}
#check to make sure num_months+cal_start_date doesn't go out of bounds
if ($cal_end_year < 1902 || $cal_end_year> 2037) {
$cal_end_year = $cal_start_year;
$cal_end_month = $cal_start_month;
$cal_num_months = 1;
}
# time window for loading events
my $cal_start_timestamp = timegm(0,0,0,1,$cal_start_month,$cal_start_year) - 2592000;
my $cal_end_timestamp = timegm(0,0,0,1,$cal_end_month,$cal_end_year) + 5184000;
if ($q->param('cal_start_timestamp') ne "" && $q->param('cal_start_timestamp') !~ /\D/) {
$cal_start_timestamp = $q->param('cal_start_timestamp');}
if ($q->param('cal_end_timestamp') ne "" && $q->param('cal_end_timestamp') !~ /\D/) {
$cal_end_timestamp = $q->param('cal_end_timestamp');}
#$debug_info .="start: $cal_start_timestamp\nend: $cal_end_timestamp\nrightnow: $rightnow\n";
# load event data, for main calendar and its background calendars
my @temp_calendars = ($current_cal_id);
foreach $local_background_calendar (keys %{$current_calendar{local_background_calendars}}) {
push @temp_calendars, $local_background_calendar;
}
my $initial_load_events = 1;
$initial_load_events = 0 if ($q->param('get_upcoming_events') eq "1");
&load_events($cal_start_timestamp, $cal_end_timestamp, \@temp_calendars) if ($initial_load_events == 1);
if ($current_event_id ne "") {
&load_event($current_event_id);
}
# load events from remote background calendars
if (scalar keys %{$current_calendar{remote_background_calendars}} > 0) {
$remote_calendars_status="";
my $temp = scalar keys %{$current_calendar{remote_background_calendars}};
foreach $remote_calendar_id (keys %{$current_calendar{remote_background_calendars}}) {
# pull in remote calendar name
my $remote_calendar_url = $current_calendar{remote_background_calendars}{$remote_calendar_id}{url};
$remote_calendar_complete_url = $remote_calendar_url;
#$debug_info .= "remote calendar: $remote_calendar_complete_url\n";
$remote_calendar_complete_url .= "?remote_calendar_request=1&cal_id=$current_calendar{remote_background_calendars}{$remote_calendar_id}{remote_id}&cal_start_year=$cal_start_year&cal_start_month=$cal_start_month&num_months=$cal_num_months";
#$debug_info .= "remote calendar url: $remote_calendar_complete_url\n";
my $xml_results = &get_remote_file($remote_calendar_complete_url);
if ($xml_results =~ //) {
$xml_results =~ s/</g;
$xml_results =~ s/>/>/g;
#$debug_info .= "Error fetching remote calendar: $xml_results\n";
} else {
my %remote_calendar = %{&xml2hash($xml_results)};
my $remote_cal_title = $remote_calendar{'xml'}{calendar}{title};
my $remote_cal_gmtime_diff = $remote_calendar{'xml'}{calendar}{gmtime_diff};
#$debug_info .= "remote_cal_gmtime_diff: $remote_cal_gmtime_diff\n";
#my $temp = $xml_results;
#$temp=~ s/>/>/g;
#$temp=~ s/</g;
#$debug_info .= "xml results: $temp\n";
&load_remote_events($xml_results, $remote_calendar_id, $remote_cal_gmtime_diff);
}
}
}
# this should be done after all $current_cal_id is calculated and events are loaded.
&normalize_timezone();
&normalize_timezone_pending_events();
# calculate previous X months range.
my $previous_cal_start_month = $cal_start_month - $cal_num_months;
my $previous_cal_start_year = $cal_start_year;
if ($previous_cal_start_month < 0) {
$previous_cal_start_year = $cal_start_year - 1 - int(abs($cal_num_months - $cal_start_month) / 12);
$previous_cal_start_month = 12 - abs($previous_cal_start_month) % 12;
}
# for the case when num_months = 12 and start_month=0
if ($previous_cal_start_month == 12) {
$previous_cal_start_month=0;
$previous_cal_start_year++;
}
# singular or plural?
if ($cal_num_months > 1) {
$prev_string = $lang{previous_months};
$prev_string =~ s/###num###/$cal_num_months/;
} else {
$prev_string = $lang{previous_month};
}
# calculate next X months range.
my $next_cal_start_month = $cal_start_month + $cal_num_months;
my $next_cal_start_year = $cal_start_year;
if ($next_cal_start_month > 11) {
$next_cal_start_year = $cal_start_year + int(abs($cal_num_months + $cal_start_month) / 12);
$next_cal_start_month = abs($cal_start_month + $cal_num_months) % 12;
}
# singular or plural?
if ($cal_num_months > 1) {
$next_string = $lang{next_months};
$next_string =~ s/###num###/$cal_num_months/;
} else {
$next_string = $lang{next_month};
}
if ($q->param('diagnostic_mode') eq "1") {
my $diagnostic_results = &diagnostic_info;
$html_output = <Diagnostic mode
Plans Diagnostic information
$diagnostic_results
Debug info:
$debug_info
p1
print $html_output;
exit(0);
}
if ($q->param('detect_remote_calendars') eq "1") {
&detect_remote_calendars();
exit(0);
}
if ($q->param('remote_calendar_request') eq "1") {
&remote_calendar_request();
exit(0);
}
if ($q->param('add_edit_user') eq "1") {
&add_edit_user();
exit(0);
}
if ($q->param('add_new_ical') eq "1") {
&add_new_ical();
exit(0);
}
if ($q->param('js_login') eq "1") {
&js_login();
exit(0);
}
if ($q->param('manage_pending_events') eq "1") {
&manage_pending_events();
exit(0);
}
if ($q->param('export_calendar') eq "1") {
if ($q->param('export_type') eq "ascii_text") {
&ascii_text_cal($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year);
exit(0);
} elsif ($q->param('export_type') eq "csv_file") {
&csv_file($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year);
exit(0);
} elsif ($q->param('export_type') eq "csv_file_palm") {
&csv_file_palm($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year);
exit(0);
} elsif ($q->param('export_type') eq "vcalendar") {
&vcalendar_export_cal($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year);
exit(0);
} elsif ($q->param('export_type') eq "icalendar") {
my $html_output =<param('export_event') eq "1") {
if ($q->param('export_type') eq "ascii_text") {
&ascii_text_event();
exit(0);
} elsif ($q->param('export_type') eq "icalendar") {
&icalendar_export_event();
exit(0);
} elsif ($q->param('export_type') eq "vcalendar") {
&vcalendar_export_event();
exit(0);
}
} elsif ($q->param('get_upcoming_events') eq "1") {
&get_upcoming_events();
exit(0);
} elsif ($api_command ne "") {
if ($api_command eq "delete_event") {
&api_add_delete_events();
exit(0);
}
} elsif ($q->param('view_event') eq "1") {
&load_templates();
&view_event();
exit(0);
} elsif ($q->param('view_pending_event') eq "1") {
&load_templates();
my %pending_event = %{$new_events{$pending_event_id}};
&view_pending_event(\%pending_event);
exit(0);
} elsif ($q->param('email_reminder') eq "1") {
&load_templates();
&email_reminder_prompt();
exit(0);
} elsif ($q->param('email_reminder_confirm') eq "1") {
&load_templates();
&email_reminder_confirm();
exit(0);
} elsif ($special_action eq "preview_event") {
&load_templates();
&preview_event();
exit(0);
} elsif ($special_action eq "preview_date") {
&load_templates();
&preview_date();
exit(0);
} elsif ($q->param('validate_event') eq "1") {
&validate_event();
exit(0);
}
#load templates
&load_templates();
# ssi-style includes in the template
if ($local_template_file) {
my $new_html = $template_html;
$template_html =~ s/###include\s+(.+)###/&load_file($1)/ge;
#while ($new_html =~ s/###include\s+(.+)###//g)
if(0) {
my $include_file=$1;
if (-e $include_file) {
open (FH, "$include_file") || ($debug_info .=" unable to open include file $include_file for reading ");
flock FH,2;
my @include_lines=;
close FH;
$include_html = join "", @include_lines;
}
$template_html =~ s/###include\s+(.+)###/$include_html/;
}
}
if($options{choose_themes}) {
my $theme_file="choose_theme.html";
my $theme_html="";
if (-e $theme_file) {
open (FH, "$theme_file") || ($debug_info .=" unable to open theme file $theme_file for reading ");
flock FH,2;
my @theme_lines=;
close FH;
$theme_html = join "", @theme_lines;
}
$template_html =~ s/###choose theme###/$theme_html/;
} else {
$template_html =~ s/###choose theme###//;
}
my $view_cookie = &xml_store($cal_start_month, "cal_start_month");
$view_cookie .= &xml_store($cal_start_year, "cal_start_year");
$view_cookie .= &xml_store($cal_num_months, "cal_num_months");
$view_cookie .= &xml_store($current_cal_id, "cal_id");
$view_cookie .= &xml_store($display_type, "display_type");
$cookie_text .= "Set-Cookie: plans_view=$view_cookie; path=$cookie_path;\n";
$cookie_header_text = $cookie_text;
#$debug_info .= "cookie: $cookie_header_text\n";
$html_output .=<
p1
chomp $insert_text;
$html_output =~ s/###javascript stuff###/$insert_text/;
# sneak in the color select javascript before all other javascript.
my $temp =<
p1
$html_output =~ s/(
p1
} else {
$popup_javascript_info .=<
p1
}
$popup_javascript_info =~ s/\n/\\n/g;
$popup_javascript_info =~ s/"/\\"/g;
$popup_javascript_info =~ s/\//\\\//g;
my $get_remote_calendars_html =<
p1
$get_remote_calendars_html =~ s/\n/\\n/g;
$get_remote_calendars_html =~ s/"/\\"/g;
$get_remote_calendars_html =~ s/\//\\\//g;
$return_string.=<');
doc.write('$lang{get_remote_calendars}<\\/title>');
doc.write('');
doc.write('$popup_javascript_info');
doc.write('');
doc.write("
");
doc.write('$get_remote_calendars_html');
doc.write("<\\/div>");
doc.write('<\\/body><\\/html>');
doc.close();
info_window.focus();
}
// color select stuff
var cs0 = new color_select();
cs0.setrgb("$current_calendar{background_events_color}");
var cs1 = new color_select();
cs1.setrgb("$current_calendar{calendar_events_color}");
function color_menu0_update(new_color) {
if (document.update_cal_form.background_events_display_style2.checked) {
document.update_cal_form.background_events_color.value = new_color;
document.getElementById("bg_preview_e1").style.background = new_color;
document.getElementById("bg_preview_e2").style.background = new_color;
}
}
function color_menu1_update(new_color) {
//if (new_color == "#000000") return;
if (document.getElementById("color_select_icon1").style.visibility != "visible") return;
document.update_cal_form.calendar_events_color[document.update_cal_form.calendar_events_color.options.length-1].value = new_color;
document.update_cal_form.calendar_events_color.style.background = new_color;
document.getElementById("custom_evt_color").style.background = new_color;
document.getElementById("preview_e1").style.background = new_color;
document.getElementById("preview_e2").style.background = new_color;
}
function update_cal_color_select_box() {
if (!document.update_cal_form) return;
if (!document.update_cal_form.calendar_events_color) return;
var current_color = document.update_cal_form.calendar_events_color[document.update_cal_form.calendar_events_color.selectedIndex].value;
if (current_color == "") {
document.getElementById('preview_e1').style.background = '#ffffcc';
document.getElementById('preview_e2').style.background = '#ccffcc';
document.getElementById("color_select_icon1").style.visibility = "hidden";
document.update_cal_form.calendar_events_color.style.background = "#ffffff";
return;
}
if (document.update_cal_form.calendar_events_color.selectedIndex == document.update_cal_form.calendar_events_color.options.length-1) {
document.getElementById("color_select_icon1").style.visibility = "visible";
var current_custom_color = document.getElementById("custom_evt_color").value;
document.getElementById("preview_e1").style.background = current_custom_color;
document.getElementById("preview_e2").style.background = current_custom_color;
document.update_cal_form.calendar_events_color.style.background = current_custom_color;
return;
} else {
cs1.setrgb(current_color);
document.getElementById("color_select_icon1").style.visibility = "hidden";
document.getElementById("preview_e1").style.background = current_color;
document.getElementById("preview_e2").style.background = current_color;
document.update_cal_form.calendar_events_color.style.background = current_color;
// take focus off the select (in IE, making a selection highlights it in blue, so you cannot see the actual color you picked. Removing focus makes this go away)
document.update_cal_form.dummy.style.display='inline';
document.update_cal_form.dummy.select();
document.update_cal_form.dummy.style.display='none';
}
//document.add_event_form.evt_bgcolor.style.background = document.add_event_form.evt_bgcolor[document.add_event_form.evt_bgcolor.selectedIndex].value
//document.update_cal_form.evt_title.select();
}
// end color_select stuff
p1
$return_string.=<');
doc.write('$lang{help_box_title}<\\/title>');
doc.write('');
doc.write('$popup_javascript_info');
doc.write('');
doc.write(help_text);
doc.write('<\\/body><\\/html>');
doc.close();
info_window.focus();
}
function preview_cal() {
var cal_title = document.update_cal_form.cal_title.value
var cal_link = document.update_cal_form.cal_link.value
var cal_details = document.update_cal_form.cal_details.value;
if (cal_title == "") {
evt_label = "$lang{preview_calendar_temp_title}<\\/span>";
add_disable = true;
}
//
if (document.getElementById("preview_warning")) {
document.getElementById("preview_warning").innerHTML="";
}
info_window = this.open("", "info_window", "resizable=yes,status=yes,scrollbars=yes,top="+info_window_y+",left="+info_window_x+",width="+info_window_width+",height="+info_window_height);
doc = info_window.document;
doc.open('text/html');
doc.write('');
doc.write('$lang{preview_calendar_title}<\\/title>');
doc.write('');
doc.write('$popup_javascript_info');
doc.write('');
doc.write("
p1
$return_text .= <
$lang{calendar_direct_link} $script_url/$name?cal_id=$calendar{id}
p1
return $results;
}
sub render_calendar {
my $return_text = "";
my $week_events = {};
my $week_slots = {};
my $debug = 0;
my @debug_events = ("105");
my $show_month_breaks = ($cal_num_months > 1 && $options{continuous_multimonth} ne '1' ? 1 : 0);
my $cal_month_idx = 0;
my $last_cal_month;
my $is_first_cal_date = 1;
my @use_other_month = (0, 1);
my ($cal_start_month, $cal_start_year, $cal_end_month, $cal_end_year, $selected_events) = @_;
#initialize loop variables
my $cal_start_timestamp = timegm(0,0,0,1,$cal_start_month,$cal_start_year);
my $cal_end_timestamp = find_end_of_month($cal_end_month, $cal_end_year);
my $current_month = $cal_start_month;
my $current_year = $cal_start_year;
while ($current_year < $cal_end_year || ($current_year == $cal_end_year && $current_month <= $cal_end_month)) {
$last_cal_month = ($current_year * 100 + $current_month) == ($cal_end_year * 100 + $cal_end_month);
foreach $key (keys %week_events) {delete $week_events{$key};}
foreach $key (keys %week_slots) {delete $week_slots{$key};}
#for calendars with multiple months, display the name of each month above the calendar
if ($show_month_breaks) {
$return_text .=<
$months[$current_month] $current_year
p1
}
#calculate where to start the calendar (first sunday)
#first, calculate what day of the week this month begins on
#format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year);
my $cal_month_start_date = timegm(0,0,0,1, $current_month, $current_year);
my @cal_month_start_date_array = gmtime $cal_month_start_date;
my $cal_start_day_offset = $cal_month_start_date_array[6] - $current_calendar{week_start_day};
$cal_start_day_offset += 7 if ($cal_start_day_offset < 0);
my $cal_start_date = $cal_month_start_date - (86400 * $cal_start_day_offset);
# in continuous_multimonth mode, skip first week if we already drew it in the previous iteration
$cal_start_date = $cal_start_date + 604800 if (!$show_month_breaks && $cal_month_idx > 0 && $cal_start_day_offset != 0);
# start with other_month if the first month does not start on the first day of the week (i.e there is an offset)
@use_other_month = (1, 0) if (!$show_month_breaks && $cal_month_idx == 0 && $cal_start_day_offset != 0 && $current_month % 2);
my @cal_start_date_array = gmtime $cal_start_date;
my $cal_end_date = $cal_start_date + 86400*37;
my $next_month = $current_month+1;
if ($next_month == 12) {$next_month=0;}
#cal_date keeps track of the date (in timestamp format)
#as the calendar loop iterates through each day on the calendar page
my $cal_date = $cal_start_date;
my @cal_date_array = gmtime $cal_date;
my %max_day_events;
my %week_max_slots;
#make a first pass through the month, assemble event week events structure:
#week_events{week_index}{id} ={}
#this hash has 4 keys--start_weekday, start_day, length and slot_order (slot_order will be calculated in the second pass)
for ($l1=0;$cal_date_array[4] != $next_month;$l1++) { #each calendar has 5 or 6 weeks
$week_start_timestamp = $cal_date;
$week_end_timestamp = $week_start_timestamp + 604800;
$max_day_events{$l1} = 0;
@cal_date_array = gmtime $cal_date;
foreach $event_id (keys %events) {
$debug = 1 if ($debug == 1 && (&contains(\@debug_events, $event_id) || $debug_events[0] eq "all"));
my %event = %{$events{$event_id}};
#$debug_info .= "checking event $event_id ($event{start}, $event{end})\n";
#$debug_info .= "checking event $event_id ($event{start} - $event{end}) against week $l1 ($week_start_timestamp - $week_end_timestamp)\n";
$debug_info .= "week $l1 checking event $event_id ($event{start}-$event{end}}) for overlap ($week_start_timestamp-$week_end_timestamp)\n" if ($debug && &contains(\@debug_events, $event_id));
if (&time_overlap($event{start}, $event{end}, $week_start_timestamp, $week_end_timestamp)) {
$debug_info .= "week $l1 event $event_id overlaps\n" if ($debug);
#$debug_info .= "event $event_id ($event{days} days) in week $l1\n";
#$debug_info .= "check passed!\n";
my @event_date_array = gmtime $event{start};
my @event_end_date_array = gmtime $event{end};
my $event_start_weekday = $event_date_array[6] - $current_calendar{week_start_day};
my $event_end_weekday = $event_end_date_array[6] - $current_calendar{week_start_day};
$event_start_weekday +=7 if ($event_start_weekday < 0);
$event_end_weekday +=7 if ($event_end_weekday < 0);
#$event_start_weekday = 0 if ($event_start_weekday < 0);
#$event_end_weekday = 0 if ($event_end_weekday < 0);
#$event_start_weekday = 6 if ($event_start_weekday > 6);
#$event_end_weekday = 6 if ($event_end_weekday > 6);
my $days_before_week_start = 0;
my $days_after_week_end = 0;
$debug_info .= "week $l1 event $event_id event_date_array[6]: $event_date_array[6]\n" if ($debug);
$debug_info .= "week $l1 event $event_id event_end_date_array[6]: $event_end_date_array[6]\n" if ($debug);
$debug_info .= "week $l1 event $event_id current_calendar{week_start_day}: $current_calendar{week_start_day}\n" if ($debug);
$debug_info .= "week $l1 event $event_id event_start_weekday: $event_start_weekday event_end_weekday: $event_end_weekday\n" if ($debug);
# the event might fall completely within the week boundary, or it
# might overlap event begins or ends outside the week boundaries
# (there are four possible cases):
if ($event{start} < $week_start_timestamp && $event{end} > $week_end_timestamp) { # the event both starts and ends outside this week
$debug_info .= "case 0\n" if ($debug);
$week_events{$l1}{$event{id}}{start_weekday} = 0;
$week_events{$l1}{$event{id}}{length} = 7;
} elsif ($event{start} < $week_start_timestamp) { # the event starts before this week and ends within it
$debug_info .= "case 1\n" if ($debug);
#$days_before_week_start = int(($week_start_timestamp - $event{start})/86400);
$week_events{$l1}{$event{id}}{start_weekday} = 0;
#$week_events{$l1}{$event{id}}{length} = $event{days} - $days_before_week_start;
$week_events{$l1}{$event{id}}{length} = $event_end_weekday+1;
$debug_info .= "week $l1 event $event_id week_start_timestamp: $week_start_timestamp start: $event{start} start_wkday: $week_events{$l1}{$event{id}}{start_weekday} length: $week_events{$l1}{$event{id}}{length}\n" if ($debug);
} elsif ($event{end} > $week_end_timestamp) { # the event starts within this week and ends after it
$debug_info .= "case 2\n" if ($debug);
$week_events{$l1}{$event{id}}{start_weekday} = $event_start_weekday;
$week_events{$l1}{$event{id}}{length} = 7-$event_start_weekday;
if ($debug == 1) {
foreach $debug_event_id (@debug_events) {
next if ($debug_event_id ne $event{id});
$debug_info .= "event $debug_event_id days: $events{$debug_event_id}{days} event_start_weekday: $event_start_weekday event_end_weekday: $event_end_weekday length: $week_events{$l1}{$debug_event_id}{length}\n";
}
}
} else { #the event begins and ends within the week
$debug_info .= "case 3\n" if ($debug);
$week_events{$l1}{$event{id}}{length} = $event{days};
$week_events{$l1}{$event{id}}{start_weekday} = $event_start_weekday;
}
if ($week_events{$l1}{$event{id}}{start_weekday} < 0) {
$week_events{$l1}{$event{id}}{start_weekday} += 7;
} elsif ($week_events{$l1}{$event{id}}{start_weekday} > 6) {
$week_events{$l1}{$event{id}}{start_weekday} -= 7;
}
$week_events{$l1}{$event{id}}{length} = 7 if ($week_events{$l1}{$event{id}}{length} > 7);
$debug_info .= "week $l1 event $event_id event_start_weekday: $week_events{$l1}{$event{id}}{start_weekday} length: $week_events{$l1}{$event{id}}{length}\n\n" if ($debug);
}
}
$temp_debug_info = "";
$cal_date += 604800;
# each day has at least two slots (the date, and a blank box beneath it)
for ($l2=0;$l2<7;$l2++) {
$week_slots{$l1}{$l2}{0}{width}=1;
$week_slots{$l1}{$l2}{0}{depth}=1;
$week_slots{$l1}{$l2}{1}{width}=1;
$week_slots{$l1}{$l2}{1}{depth}=1;
}
if ($debug == 1) {
foreach $debug_event_id (@debug_events) {
$debug_info .= "event $debug_event_id length: $week_events{$l1}{$debug_event_id}{length} start: $events{$debug_event_id}{start}\n";
}
}
#order the week_events
#fill in the %slots data structure:
# $week_slots{week_index}{day_index}{slot_index}
# $width = colspan
# $depth = rowspan
# $spacer = 1 if spacer slot.
# @ids = event ids
my $max_week_needed_slots = 0;
my %max_day_needed_slots;
# hey man, that's a sharp-lookin' sort you got there
foreach $week_event_id (sort {
return $week_events{$l1}{$b}{length} <=> $week_events{$l1}{$a}{length}
if ($week_events{$l1}{$b}{length} != $week_events{$l1}{$a}{length});
return $events{$a}{title} cmp $events{$b}{title}
if ($events{$b}{all_day_event} ne "" && $events{$a}{all_day_event} ne "");
return $events{$b}{all_day_event} cmp $events{$a}{all_day_event}
if ($events{$b}{all_day_event} ne "" || $events{$a}{all_day_event} ne "");
return $events{$a}{start} <=> $events{$b}{start};
}
keys %{$week_events{$l1}})
{
#$debug = 0;
#$debug = 1 if (&contains(\@debug_events, $week_event_id));
#$debug_info .= "week $l1 week_event $week_event_id length: $week_events{$l1}{$week_event_id}{length} start: $events{$week_event_id}{start}\n" if ($debug);
$empty_slot = 0;
#starting at 1 leaves a row of empty slots (row 0), where the calendar dates will go.
for ($l4=1; $empty_slot != 1; $l4++) {
$empty_slot = 1;
#check each day of the week_event, to make sure the slot is empty
for ($l2=0; $l2<$week_events{$l1}{$week_event_id}{length}; $l2++) {
$day_index=$l2+$week_events{$l1}{$week_event_id}{start_weekday};
if (scalar @{$week_slots{$l1}{$day_index}{$l4}{ids}} > 0) {
$empty_slot = 0;
}
}
$slot_index=$l4;
}
#$debug_info .= "event $week_event_id start_wkday $week_events{$l1}{$week_event_id}{start_weekday} slot $slot_index length $week_events{$l1}{$week_event_id}{length}\n" if ($debug);
#fill up $week_slots with the new event (extend horizontally)
for ($l2=0; $l2<$week_events{$l1}{$week_event_id}{length}; $l2++) {
#$slots_in_row{$l1}{$slot_index}++;
$day_index = $l2+$week_events{$l1}{$week_event_id}{start_weekday};
push @{$week_slots{$l1}{$day_index}{$slot_index}{ids}}, $week_event_id;
if ($l2==0) { # first slot gets the width
$week_slots{$l1}{$day_index}{$slot_index}{width} = $week_events{$l1}{$week_event_id}{length};} else { # other slots get 0 for length (they get absorbed later)
$week_slots{$l1}{$day_index}{$slot_index}{width} = 0;}
$week_slots{$l1}{$day_index}{$slot_index}{depth} = 1;
}
#keep track of the maximum number of slots each week has
if ($slot_index > $week_max_slots{$l1}) {
$week_max_slots{$l1} = $slot_index;
$max_day_events{$l1} = $slot_index;
}
}
# give all blank slots width and depth of 1
for ($l2=0;$l2<7;$l2++) {
for ($l3=1;$l3<$week_max_slots{$l1}+1;$l3++) { # for each slot
if ($week_slots{$l1}{$l2}{$l3}{depth} eq "" || $week_slots{$l1}{$l2}{$l3}{width} eq "") {
$week_slots{$l1}{$l2}{$l3}{width}=1;
$week_slots{$l1}{$l2}{$l3}{depth}=1;
}
}
}
my $total_spacers=0;
# insert spacer slots below multi-day events.
for ($l3=1;$l3<$week_max_slots{$l1}+1;$l3++) { # for each slot
my $inserted_spacers=0;
for ($l2=0;$l2<7;$l2++) {
if ($week_slots{$l1}{$l2}{$l3}{width} > 1) { #multi-day event, add spacers beneath
# create spacer row
if ($inserted_spacers == 0) {
# move everything else down and increment the number of rows
$week_max_slots{$l1}++;
for ($l4=0;$l4<7;$l4++) { # insert blank slots
for ($l5=$week_max_slots{$l1};$l5>$l3+1;$l5--) { # count backwards
$week_slots{$l1}{$l4}{$l5} = &deep_copy($week_slots{$l1}{$l4}{$l5-1});
}
$week_slots{$l1}{$l4}{$l3+1}{width} = 1;
$week_slots{$l1}{$l4}{$l3+1}{depth} = 1;
$week_slots{$l1}{$l4}{$l3+1}{spacer} = 0;
$week_slots{$l1}{$l4}{$l3+1}{ids} = "";
}
$inserted_spacers=1
}
# insert spacers into previously created row.
for ($l4=$l2;$l4<$l2+$week_slots{$l1}{$l2}{$l3}{width};$l4++) {
$week_slots{$l1}{$l4}{$l3+1}{spacer}=1;
#$debug_info .= "inserted spacer into row: ".($l3+1).", column $l4, event ".($week_slots{$l1}{$l4}{$l3}{ids}[0])."\n";
$total_spacers++;
}
#$debug_info .= "week $l1 day 0, slot 3: ".$week_slots{$l1}{0}{3}{ids}[0]."\n";
}
}
}
#if ($l1 == 3) {
#$debug_info .= "$total_spacers spacers inserted for week $l1.\n";
#$debug_info .= "week $l1 day 0, slot 3: ".$week_slots{$l1}{0}{3}{ids}[0]."\n";
#}
#$debug_info .= "week $l1, event slots in row 1: $slots_in_row{$l1}{1}\n";
# calculate slots in each row:
for ($l3=1;$l3<$week_max_slots{$l1};$l3++) { # for each slot
if ((scalar @{$week_slots{$l1}{$l2}{$l3}{ids}}) > 0 ) {
$slots_in_row{$l1}{$l3} += $week_slots{$l1}{$l2}{$l3}{width};
#$debug_info .= "event in row $l1. Incrementing slots_in_row {$l1} {$l3} to $slots_in_row{$l1}{$l3}\n";
}
if ($week_slots{$l1}{$l2}{$l3}{spacer} == 1) {
$slots_in_row{$l1}{$l3}++;
#$debug_info .= "spacer in row $l1. Incrementing slots_in_row {$l1} {$l3} to $slots_in_row{$l1}{$l3}\n";
}
}
%max_day_needed_slots = (0=>$week_max_slots{$l1},1=>$week_max_slots{$l1},2=>$week_max_slots{$l1},3=>$week_max_slots{$l1},4=>$week_max_slots{$l1},5=>$week_max_slots{$l1},6=>$week_max_slots{$l1});
#$slots_in_row{$l1}{$slot_index}++;
# extend event slots vertically.
for ($l2=0;$l2<7;$l2++) { # for each day of the week
for ($l3=1;$l3<$week_max_slots{$l1};$l3++) { # for each slot
if (scalar @{$week_slots{$l1}{$l2}{$l3}{ids}} > 0 && $week_slots{$l1}{$l2}{$l3}{width} > 0) { # if this slot begins an event
my $start_slot = $l3+1;
for ($l4=$start_slot; $l4<$week_max_slots{$l1}+1; $l4++) {
#$debug_info .= "checking slot $l4 below event slot ($l2, $l3)\n";
#if ($week_slots{$l1}{$l2}{$l4}{width} == 0)
# {next;}
if (scalar @{$week_slots{$l1}{$l2}{$l4}{ids}} > 0 && $week_slots{$l1}{$l2}{$l4}{width} eq $week_slots{$l1}{$l2}{$l3}{width}) { # another event below this one, with the same width.
if ($l1 eq "3" && $debug) {
$debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of another event below with the same width.\n";}
#$debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of another event below with the same width.\n";
#$debug_info .= "same-width event slot below week $l1, slot ($l2, $l3)\n";
$week_slots{$l1}{$l2}{$l4}{width}=0;
$week_slots{$l1}{$l2}{$l4}{depth}=0;
$week_slots{$l1}{$l2}{$l3}{depth}++;
push @{$week_slots{$l1}{$l2}{$l3}{ids}}, @{$week_slots{$l1}{$l2}{$l4}{ids}};
$max_day_needed_slots{$l2}--;
#$slots_in_row{$l1}{$l4}--;
} elsif ($week_slots{$l1}{$l2}{$l3}{width} == 1 && (scalar @{$week_slots{$l1}{$l2}{$l4}{ids}}) == 0 && $week_slots{$l1}{$l2}{$l4}{spacer} == 0) { # blank slot below 1-slot wide event slot
if ($l1 eq "3" && $debug) {
$debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of a blank slot below.\n";}
#$debug_info .= "week $l1 slot ($l2, $l3) extended vertically because of a blank slot below.\n";
#$debug_info .= "week $l1 slot ($l2, $l4) # ids:".scalar @{$week_slots{$l1}{$l2}{$l4}{ids}}."\n";
#$debug_info .= "blank slot below week $l1, slot ($l2, $l3)\n";
$week_slots{$l1}{$l2}{$l4}{width}=0;
$week_slots{$l1}{$l2}{$l4}{depth}=0;
$week_slots{$l1}{$l2}{$l3}{depth}++;
$max_day_needed_slots{$l2}--;
#$debug_info .= "week $l1, slot ($l2, $l3) depth: $week_slots{$l1}{$l2}{$l3}{depth} \n";
} else {
$debug_info .= "week $l1 slot ($l2, $l4) occupied. Finished attempting to extend slot $l3\n" if ($debug);
last;
}
}
}
}
}
#$debug_info .= "week $l1, event slots in row 1: $slots_in_row{$l1}{1}\n";
# extend blank slots vertically into other blank slots.
for ($l2=0;$l2<7;$l2++) { # for each day of the week
for ($l3=1;$l3<$week_max_slots{$l1};$l3++) { # for each slot
next if (scalar @{$week_slots{$l1}{$l2}{$l3}{ids}} > 0);
if ($week_slots{$l1}{$l2}{$l3}{width} > 0 && $week_slots{$l1}{$l2}{$l3}{spacer} == 0) { # if it's blank (but not a spacer)
my $start_slot = $l3+1;
for ($l4=$start_slot; $l4<$week_max_slots{$l1}+1; $l4++) {
if ($week_slots{$l1}{$l2}{$l4}{width} == 1 && $week_slots{$l1}{$l2}{$l4}{spacer} == 0) {
#$debug_info .= "blank slot below week $l1, slot ($l2, $l3)\n" if ($debug);
$week_slots{$l1}{$l2}{$l4}{width}=0;
$week_slots{$l1}{$l2}{$l4}{depth}=0;
$week_slots{$l1}{$l2}{$l3}{depth}++;
$max_day_needed_slots{$l2}--;
} else {
last;
}
}
}
}
}
#$debug_info .= "week $l1, event slots in row 1: $slots_in_row{$l1}{1}\n";
#$debug_info .= "week $l1 slot (4, 1) depth: $week_slots{$l1}{4}{1}{depth}\n";
# yet another pass. trim vertical depth and re-calculate max_slots
# calculate trim
my $trim = 0;
#$debug_info .= "\n week $l1 max slots: $week_max_slots{$l1}\n";
#$debug_info .= "\nweek $l1, max_day_needed_slots: $max_day_needed_slots{0} $max_day_needed_slots{1} $max_day_needed_slots{2} $max_day_needed_slots{3} $max_day_needed_slots{4} $max_day_needed_slots{5} $max_day_needed_slots{6} $max_day_needed_slots{7}\n" if ($debug);
$max_week_needed_slots = max(values %max_day_needed_slots);
#$debug_info .= "week $l1 max_week_needed_slots: $max_week_needed_slots\n";
#if ($max_day_needed_slots >$max_week_needed_slots)
# {$max_week_needed_slots = $max_day_needed_slots;}
#$debug_info .= "max needed slots for week $l1, $max_week_needed_slots\n";
my $trim = $week_max_slots{$l1} - $max_week_needed_slots;
# apply trim
#$debug_info .= "trim for week $l1, $trim\n";
for ($l2=0;$l2<7;$l2++) { # for each day of the week
for ($l3=$week_max_slots{$l1};$l3>0;$l3--) { # for each slot, counting backwards (upwards)
if ($week_slots{$l1}{$l2}{$l3}{depth} > 0) { # blank or non-blank, with depth > 0
#$debug_info .= "trimming week $l1, slot ($l2, $l3) by $trim\n";
$week_slots{$l1}{$l2}{$l3}{depth} = $week_slots{$l1}{$l2}{$l3}{depth} - $trim;
last;
}
}
}
$week_max_slots{$l1} = $week_max_slots{$l1} - $trim;
} # repeat for next week
# print day names
if ($cal_month_idx == 0 || $show_month_breaks) {
my @lowercase_day_names;
foreach $day_name (@day_names) {
push @lowercase_day_names, lc $day_name;
}
$return_text .=<
$weekday_sequence[0]
$weekday_sequence[1]
$weekday_sequence[2]
$weekday_sequence[3]
$weekday_sequence[4]
$weekday_sequence[5]
$weekday_sequence[6]
p1
}
#cal_date keeps track of the date (in timestamp format)
#as the calendar loop iterates through each day on the calendar page
$cal_date = $cal_start_date;
@cal_date_array = gmtime $cal_date;
#locked and loaded, data structures assembled--now it's time to kick it, calendar-style.
for ($l1=0;$cal_date_array[4] != $next_month; $l1++) { #each calendar has 5 or 6 weeks
my $last_week=0;
my $timestamp_next_week = $cal_date+604800;
my @timestamp_next_week_array = gmtime $timestamp_next_week;
my $week_date_index = $cal_date;
# draw the table!
for ($l3=0;$l3<$week_max_slots{$l1}+1;$l3++) {
$return_text .="
";
$week_date_index = $cal_date;
for ($l2=0;$l2<7;$l2++) { # 7 days / week
@cal_date_array = gmtime $week_date_index;
my $td_class = "day ".lc($day_names[$l2]);
$td_class .= " today" if ($cal_date_array[4] == $rightnow_month &&
$cal_date_array[3] == $rightnow_mday &&
$cal_date_array[5]+1900 == $rightnow_year);
# display date numbers differently, depending on whether they are in the current month or not
my $cal_month_name = "";
if ($show_month_breaks || $cal_num_months == 1) {
$td_class .= " other_month" if ($cal_date_array[4] != $current_month);
} else {
$td_class .= " other_month_multi" if ($use_other_month[$cal_date_array[4] % 2]);
$cal_month_name = $months[$cal_date_array[4]] if ($cal_date_array[3] == 1);
}
#if ($l2 == $week_events{$l1}{$week_slots{$l1}{$l2}{$l3}{id}}{start_weekday} && $week_events{$l1}{$week_slots{$l1}{$l2}{$l3}{id}}{start_weekday} ne "")
if ($l3 == 0) { #if it's the top blank slot, put the date in there.
$td_style="border-bottom-width:0px;";
#display the cell differently if it is today.
if ($cal_date_array[4] == $rightnow_month &&
$cal_date_array[3] == $rightnow_mday &&
$cal_date_array[5]+1900 == $rightnow_year) {
# offset the date number a few pixels
# (so it will be in the center of the red circle)
# offset a bit more for a double-digit day number.
# small touches are the difference between good and great :)
my $date_div_style = "";
$date_div_style = "text-indent: 11px;" if ($rightnow_mday > 10);
$return_text .=<
$cal_date_array[3] $cal_month_name
p1
} else {
$return_text .=<
$cal_date_array[3] $cal_month_name
p1
}
} elsif ($week_slots{$l1}{$l2}{$l3}{spacer} != 0) { # spacer slot
my $spacer_class = "spacer";
if ($l3 == $week_max_slots{$l1}-1) {
$spacer_class .= " bottom";
}
$return_text .=<
p1
} elsif ($week_slots{$l1}{$l2}{$l3}{width} != 0) { # slot containing events
$num_cols = $week_slots{$l1}{$l2}{$l3}{width};
$num_rows = $week_slots{$l1}{$l2}{$l3}{depth};
if (scalar @{$week_slots{$l1}{$l2}{$l3}{ids}} > 0) {
$td_style="border-top-width:0px;border-bottom-width:0px;";
#($l2,$l3) $num_cols\lx$num_rows
$return_text .=<
p1
foreach $event_id (@{$week_slots{$l1}{$l2}{$l3}{ids}}) {
my $multi_day_event = ($week_slots{$l1}{$l2}{$l3}{width} > 1) ? 1:0;
my $background_event = (&contains($events{$event_id}{cal_ids}, $current_calendar{id})) ? 0:1;
$return_text .= &display_calendar_event($event_id, $multi_day_event, $background_event)
}
$return_text .=<
p1
} elsif ($week_slots{$l1}{$l2}{$l3}{ids} eq "" && $week_slots{$l1}{$l2}{$l3}{width} > 0) { # blank slot
$td_style="border-top-width:0px;border-bottom-width:0px;";
#($l2,$l3) blank $num_cols\lx$num_rows
$return_text .=<
p1
}
}
$week_date_index += 86400;
} # next day (first row)
#right border
$return_text .=<
p1
} # event slot index
# this little trick is the cat's pajamas. It's another row of
# table cells that cause each calendar day to come down a little
# bit below the lowest esvent. It makes the calendar look sharp.
# Also, if the week has a small number of events, we expand the height of the bottom cell.
# This makes all the calendar cells look square, which is the bee's knees.
my $bottom_height_style = "";
if ($max_day_events{$l1} < 2) {
my $height = (4-$max_day_events{$l1}) . "em"; # this algorithm was developed by guess & check
#my $height = "100px"; # this algorithm was developed by guess & check
$bottom_height_style = "line-height:$height;";
}
$return_text .=<
p1
$week_date_index = $cal_date;
for ($l2=0;$l2<7;$l2++) { #each week has 7 days(!)
my $td_class = "";
@cal_date_array = gmtime $week_date_index;
$td_class .= "day ".lc($day_names[$l2])." cell_bottom";
$td_class .= " today" if ($cal_date_array[4] == $rightnow_month &&
$cal_date_array[3] == $rightnow_mday &&
$cal_date_array[5]+1900 == $rightnow_year);
if ($show_month_breaks || $cal_num_months == 1) {
$td_class .= " other_month" if ($cal_date_array[4] != $current_month);
} else {
$td_class .= " other_month_multi" if ($use_other_month[$cal_date_array[4] % 2]);
}
$return_text .=<
p1
$week_date_index+=86400;
}
$return_text .=<
p1
$cal_date+=604800;
@cal_date_array = gmtime $cal_date;
}
#close table tag for each month or only for last month on continuous_multimonth mode
if ($show_month_breaks || $last_cal_month) {
$return_text .=<
p1
}
#increment to the next month--the method used
#here is the most painless way of making
#this work the right way in all cases.
$current_month++;
$cal_month_idx++;
if ($current_month == 12) {
$current_month=0;
$current_year++;
}
}
return $return_text;
} #********************end render_calendar subroutine**********************
sub background_event_colorize {
my ($event_id, $calendar_id) = @_;
my %event = %{$events{$event_id}};
my %calendar = %{$calendars{$calendar_id}};
my $event_bgcolor = $event{bgcolor};
if ($calendars{$event{cal_ids}[0]}{calendar_events_color} ne "") {
$event_bgcolor = $calendars{$event{cal_ids}[0]}{calendar_events_color};}
if ($calendar{background_events_display_style} eq "single_color") {
$event_bgcolor = $calendar{background_events_color};} elsif ($calendar{background_events_display_style} eq "faded") {
# create "faded" look for background event
my $faded_color = $event_bgcolor;
#convert rgb values from hex (00-FF) to decimal integer (0-255)
my $r = hex substr $faded_color,1,2;
my $g = hex substr $faded_color,3,2;
my $b = hex substr $faded_color,5,2;
#convert integer rgb values to hsv
my @hsv_array = &rgb2hsv($r,$g,$b);
#convert s and v from percentages to decimal
$hsv_array[1] = $hsv_array[1]/100;
$hsv_array[2] = $hsv_array[2]/100;
#"fade" the color (decrease saturation)
$hsv_array[1] = $hsv_array[1]/$calendar{background_events_fade_factor};
my @new_rgb_array = &hsv2rgb($hsv_array[0],$hsv_array[1],$hsv_array[2]);
#convert back to hex
$r = (sprintf ("%1.1X",$new_rgb_array[0]));
$g = (sprintf ("%1.1X",$new_rgb_array[1]));
$b = (sprintf ("%1.1X",$new_rgb_array[2]));
$event_bgcolor = "#$r$g$b";
}
return $event_bgcolor;
}
sub display_calendar_event {
my ($event_id, $multi_day, $background_event) = @_;
my %event = %{$events{$event_id}};
my $results = "";
my $event_bgcolor = $event{bgcolor};
# force white color if the background is dark
my $textcolor_style = "";
my $r = hex substr $event_bgcolor,1,2;
my $g = hex substr $event_bgcolor,3,2;
my $b = hex substr $event_bgcolor,5,2;
my $bright = ($r*299+$g*587+$b*114)/1000;
$textcolor_style = "color:#fff" if ($bright < 128);
$event_bgcolor = $current_calendar{calendar_events_color} if ($current_calendar{calendar_events_color} ne "");
my $event_box_class = "event_box";
# handle link
my $event_link = "javascript:display_event('$event_id');";
$event_link = "$event{details}" if ($event{details_url} eq "1");
if ($background_event) {
$event_box_class .= " background";
$event_bgcolor = &background_event_colorize($event_id, $current_calendar{id});
}
# handle icon
my $icon_text = "";
my $unit_icon_text = "";
if ($event{unit_number} ne "") {
$unit_icon_text = $event{unit_number}." ";
$unit_icon_text =~ s/(\d)//g;
}
my $link_style="";
if ($event{icon} ne "blank" && $event{icon} ne "") {
$icon_text = <
p1
chomp $icon_text;
$link_style="padding-left:29px";
}
# context menu stuff
my $event_context_menu_text="onmousedown=\"if (event.shiftKey) return show_event_contextmenu(event, $event_id, '$event_bgcolor', '$event{series_id}'); else return false; \" oncontextmenu=\"return show_event_contextmenu(event, $event_id, '$event_bgcolor', '$event{series_id}');\"";
$event_context_menu_text = "" if ($event_id =~ /\D/);
if ($multi_day == 0) {
my $event_time = "";
if ($event{all_day_event} ne "1") {
$event_time = &nice_time_range_format($event{start}, $event{end});
$event_time = " $event_time ";
}
my $temp_item_text = $calendar_item_template;
$temp_item_text =~ s/###icon###/$icon_text$unit_icon_text/g;
$temp_item_text =~ s/###title###/$event{title}/g;
$temp_item_text =~ s/###time###/$event_time/g;
my $calendar_title = $calendars{$event{cal_ids}[0]}{title};
$temp_item_text =~ s/###calendar title###/$calendar_title/g;
$results .=<
$temp_item_text
p1
} else { # multi-day-event
# handle the case where an event is < 24 hours and crosses midnight.
my $nudge_edge="";
my $event_time = "";
if ($event{all_day_event} ne "1") {
if ($event{end} - $event{start} < 86400) {
my $offset = 25;
my $width = 50;
$nudge_edge = "width:$width%;position:relative;left:$offset%;";
}
$event_time = &nice_time_range_format($event{start}, $event{end});
$event_time = " $event_time ";
}
if ($event{icon} ne "blank" && $event{icon} ne "") {
$icon_text = <
p1
chomp $icon_text;
}
my $temp_item_text = $calendar_item_template;
$temp_item_text =~ s/###icon###/$icon_text$unit_icon_text/g;
$temp_item_text =~ s/###title###/$event{title}/g;
$temp_item_text =~ s/###time###/$event_time/g;
my $calendar_title = $calendars{$event{cal_ids}[0]}{title};
$temp_item_text =~ s/###calendar title###/$calendar_title/g;
$results .=<
$temp_item_text
p1
}
}
sub display_list_event {
my ($event_id, $background_event, $sameday) = @_;
my %event = %{$events{$event_id}};
my $results="";
@event_start_timestamp_array = gmtime $event{start};
my $date_string;
my $weekday_string;
if ($event{days} == 1) {
#single-day event
$date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3]";
$weekday_string = $day_names_abv[$event_start_timestamp_array[6]]
} else { #multi-day event
@event_end_timestamp_array = gmtime $event{end};
if ($event_start_timestamp_array[4] eq $event_end_timestamp_array[4]) {
$date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3]-$event_end_timestamp_array[3]";
} else {
$date_string="$months_abv[$event_start_timestamp_array[4]] $event_start_timestamp_array[3] - $months_abv[$event_end_timestamp_array[4]] $event_end_timestamp_array[3]";
}
$weekday_string = "$day_names_abv[$event_start_timestamp_array[6]]-$day_names_abv[$event_end_timestamp_array[6]]";
}
# weekday abbreviations
my $weekday_abv_string = $weekday_string;
for ($l1=0;$l1/g;
}
if ($event{icon} eq "blank" || $event{icon} eq "") {
$icon_text .= "$unit_icon_text";
} else {
$icon_text .= "$unit_icon_text";
}
my $event_bgcolor = $event{bgcolor};
if ($calendars{$event{cal_ids}[0]}{calendar_events_color} ne "") {
$event_bgcolor = $calendars{$event{cal_ids}[0]}{calendar_events_color};}
if ($background_event eq "1") {
$event_bgcolor = &background_event_colorize($event_id, $current_calendar{id});
}
my $event_context_menu_text="onmousedown=\"if (event.shiftKey) return show_event_contextmenu(event, $event{id}, '$event{bgcolor}', '$event{series_id}'); else return false;\" oncontextmenu=\"return show_event_contextmenu(event, $event{id}, '$event{bgcolor}', '$event{series_id}');\"";
if ($event_id =~ /\D/) {
$event_context_menu_text=""}
my $day_context_menu_text = "onmousedown=\"if (event.shiftKey) return show_day_contextmenu(event, $event{start}); else return false;\" oncontextmenu=\"return show_day_contextmenu(event, $event{start});\"";
# event time
my $event_time = "";
if ($event{all_day_event} ne "1") {
$event_time = &nice_time_range_format($event{start}, $event{end});
$event_time = "$event_time";
}
my $event_link = "javascript:display_event('$event{id}');";
if ($event{details_url} eq "1") {
$event_link = "$event{details}";}
my $margin_top="7px";
$margin_top = "0" if ($sameday);
my $temp_item_text = $list_item_template;
$temp_item_text =~ s/###variable_margin###/$margin_top/g;
$temp_item_text =~ s/###event_contextmenu###/$event_context_menu_text/g;
$temp_item_text =~ s/###day_contextmenu###/$day_context_menu_text/g;
$temp_item_text =~ s/###id###/$event_id/g;
$temp_item_text =~ s/###bgcolor###/$event_bgcolor/g;
$temp_item_text =~ s/###link###/$event_link/g;
$temp_item_text =~ s/###details###/$event{details}/g;
$temp_item_text =~ s/###icon###/$icon_text/g;
$temp_item_text =~ s/###title###/$event{title}/g;
$temp_item_text =~ s/###date###/$date_string/g;
$temp_item_text =~ s/###weekday###/$weekday_string/g;
$temp_item_text =~ s/###weekday_abv###/$weekday_abv_string/g;
$temp_item_text =~ s/###time###/$event_time/g;
$results .= $temp_item_text;
$no_results .=< $date_string $icon_text $event_time $event{title}
p1
return $results;
}
sub render_list {
my $return_text = "";
($start_month, $start_year, $end_month, $end_year) = @_;
#calculate where to start and end the list
#format for timegm: timegm($sec,$min,$hour,$mday,$mon,$year);
my $list_start_timestamp = timegm(0,0,0,1,$start_month,$start_year);
my $list_end_timestamp = &find_end_of_month($end_month, $end_year);
# loop through all the events.
#Create an array of events which fall
# within the current list view dates
my @selected_cal_events;
#and a funky data structure for the background calendars
# each element of this hash will be an array.
my $shared_cal_events={}; #empty hash
foreach $event_id (keys %events) {
if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$list_start_timestamp,$list_end_timestamp)) {
my $event_in_current_calendar = 0;
foreach $temp_cal_id (@{$events{$event_id}{cal_ids}}) {
if ($temp_cal_id eq $current_cal_id) {
push @selected_cal_events, $event_id;}
foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) {
if ($temp_cal_id eq $background_cal_id) {
if ($current_calendar{list_background_calendars_together} eq "yes") {
push @selected_cal_events, $event_id;
} else {
push @{$shared_cal_events{$background_cal_id}}, $event_id if (!&contains(\@selected_cal_events, $event_id));
}
}
}
}
}
}
# initialize loop variables
$current_month = $start_month;
$current_year = $start_year;
$return_text .=<
p1
if ($cal_num_months> 1) {
$return_text .=<
$calendars{$current_cal_id}{title}
p1
#display events for selected calendar
my $previous_event_id;
foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @selected_cal_events) {
my %event = %{$events{$event_id}};
if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) {
my $background_event = "";
$background_event = "1" if ($event{cal_ids}[0] ne $current_cal_id);
my @temp1 = gmtime($event{start});
my @temp2 = gmtime($events{$previous_event_id}{start});
my $sameday = "";
$sameday = "1" if ($temp1[3] == $temp2[3]);
$return_text .= &display_list_event($event_id, $background_event, $sameday);
$previous_event_id = $event_id;
}
}
$return_text .=<
p1
} else {
$return_text .=<
$calendars{$current_cal_id}{title}
p1
#display events for selected calendar
my $previous_event_id;
foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @selected_cal_events) {
my %event = %{$events{$event_id}};
if (&time_overlap($event{start},$event{end},$current_month_start_timestamp, $current_month_end_timestamp)) {
my @temp1 = gmtime($event{start});
my @temp2 = gmtime($events{$previous_event_id}{start});
my $sameday = "";
$sameday = "1" if ($temp1[3] == $temp2[3]);
$return_text .= &display_list_event($event_id,0,$sameday);
$previous_event_id = $event_id;
}
}
$return_text .=<
p1
foreach $background_cal_id (keys %{$current_calendar{local_background_calendars}}) {
$return_text .=<
$calendars{$background_cal_id}{title}
p1
#list events for that calendar
my $previous_event_id;
foreach $event_id (sort {$events{$a}{start} <=> $events{$b}{start}} @{$shared_cal_events{$background_cal_id}}) {
%event = %{$events{$event_id}};
if (&time_overlap($events{$event_id}{start},$events{$event_id}{end},$current_month_start_timestamp, $current_month_end_timestamp)) {
my @temp1 = gmtime($event{start});
my @temp2 = gmtime($events{$previous_event_id}{start});
my $sameday = "";
$sameday = "1" if ($temp1[3] == $temp2[3]);
$return_text .= &display_list_event($event_id,1,$sameday);
$previous_event_id = $event_id;
}
}
$return_text .=<
p1
}
}
$return_text .=<
p1
#increment to the next month--the method used
#here is the most painless way of making
#this work the right way in all cases.
$current_month +=1;
if ($current_month == 12) {
$current_month=0;
$current_year++;
}
}
$return_text .=<
";
}
$html_output .=<
p1
#$html_output .="$debug_info";
$debug_info =~ s/\n/ /g;
$html_output .=<
p1
print $html_output;
} # end preview date subroutine
sub validate_event {
my $results = "";
my $event_title = $q->param('evt_title');
my $all_day_event = $q->param('all_day_event');
my $event_start_date = $q->param('evt_start_date');
my $event_start_time = $q->param('evt_start_time');
my $event_end_time = $q->param('evt_end_time');
my $event_days = $q->param('evt_days');
my $date_valid = &verify_date($event_start_date);
if ($date_valid eq "") {
if ($all_day_event ne "1") {
my $verify_time_results = &verify_time($event_start_time);
if ($verify_time_results ne "") {
my @sub_results = split("\n", $verify_time_results);
foreach $sub_result (@sub_results) {
$date_valid .= "[error]$lang{update_event_err14} $sub_result ";
}
}
my $verify_time_results = &verify_time($event_end_time);
if ($verify_time_results ne "") {
my @sub_results = split("\n", $verify_time_results);
foreach $sub_result (@sub_results) {
$date_valid .= "[error]$lang{update_event_err15} $sub_result ";
}
}
}
}
if ($event_title eq "") {
$date_valid = $lang{update_event_err4};
}
if ($event_days eq "") {
$date_valid = $lang{date_verify_err2};
}
if ($event_days =~ m/\D/ || $event_days <= 0) {
my $temp = $lang{date_verify_err3};
$temp =~ s/\$1/$event_days/;
$date_valid = $temp;
}
if ($date_valid eq "") {
$results .= </g;
$date_valid =~ s/"/\\"/g;
$date_valid =~ s/'/\\'/g;
$results .= </g;
$debug_info =~ s/"/\\"/g;
$debug_info =~ s/'/\\'/g;
$results =~ s/###debug_info###/$debug_info/;
print < $q->param('evt_title'),
details => $q->param('evt_details'),
cal_id => $current_cal_id,
icon => $q->param('evt_icon'),
bgcolor => $q->param('evt_bgcolor'),
start => "",
end => "",
unit_number => $q->param('unit_number')}, 1);
my $html_output .=<$lang{event_preview_title}
$lang{event_preview_title}
$event_info
$debug_info
p1
print $html_output;
} # preview_event
sub view_event {
#$debug_info .= "(view_event) event $current_event{id} start: $current_event{start} \n" if ($current_event{id} eq "1815");
my %current_event = %{$events{$current_event_id}};
my $event_info = &generate_event_details(\%current_event);
$debug_info =~ s/\n/ \n/g;
my $html_output .=<$current_event{title}
$event_info
$debug_info
p1
print $html_output;
} # view_event
sub view_pending_event {
my ($pending_event_ref) = @_;
my %pending_event = %{$pending_event_ref};
$event_details_template =~ s/###export event link###/$lang{event_details_export_disable}/g;
$event_details_template =~ s/###edit event link###/$lang{event_details_edit_disable}/g;
$event_details_template =~ s/###email reminder link###/$lang{event_email_reminder_disable}/g;
my $event_info = &generate_event_details(\%pending_event);
$debug_info =~ s/\n/ \n/g;
my $html_output .=<$current_event{title}
$event_info
$debug_info
p1
print $html_output;
} # view_pending_event
sub email_reminder_prompt {
my %current_event = %{$events{$current_event_id}};
my %previous_current_calendar = %current_calendar;
%current_calendar = %{$calendars{$current_event{cal_ids}[0]}};
$date_string = &nice_date_range_format($current_event{start}, $current_event{end}, " - ");
%current_calendar = %previous_current_calendar;
my $title = "$current_event{title}$lang{email_reminder_title}";
my $results .=<
p1
my $html_output .=<\n/g;
$html_output .=<$lang{get_remote_calendars}
$popup_javascript_info
p1
#
$html_output .=<
$debug_info
p1
print $html_output;
}
sub remote_calendar_request() {
my $html_output .=<param('cal_id');
$results .=<$plans_version
p1
#$debug_info .= "remote calendar request!";
# if the client requests a list of all calendars that are publically share-able.
if ($q->param('get_public_calendars') eq "1") {
foreach $cal_id (keys %calendars) {
if ($calendars{$cal_id}{allow_remote_calendar_requests}) {
my $temp=$calendars{$cal_id}{remote_calendar_requests_require_password};
$results .=<$cal_id$calendars{$cal_id}{title}$temp
p1
}
}
} else { # return xml data for the events.
my @current_cal_ids = ();
my @temp = split (",",$current_cal_ids_string);
my $cal_id_valid=1;
foreach $cal_id (@temp) {
if ($cal_id !~ /\D/) {
push @current_cal_ids, $cal_id;
} else {
$cal_id_valid=0;
$results .= "Invalid calendar ID: $cal_id";
last;
}
}
if ($cal_id_valid) {
foreach $current_cal_id (@current_cal_ids) {
$results .=<$current_cal_id$calendars{$current_cal_id}{title}$calendars{$current_cal_id}{gmtime_diff}
p1
}
foreach $current_cal_id (@current_cal_ids) {
foreach $event_id (keys %events) {
my $event_in_current_calendar = 0;
foreach $temp_cal_id (@{$events{$event_id}{cal_ids}}) {
if ($temp_cal_id eq $current_cal_id) {
$event_in_current_calendar = 1;
last;
}
}
next if ($event_in_current_calendar == 0);
my $xml_data = &event2xml($events{$event_id});
$results .=<Script Name:$name
p1
if ($options{email_mode} && !$writable{email_reminders_datafile}) {
$results .=<Warning: The email reminders data file: $options{email_reminders_datafile} is not writable. This will
cause some email functions to be disabled or not work correctly.
p1
}
if ($options{data_storage_mode} == 0 && !$writable{calendars_file}) {
$results .=<Warning: The calendars data file: $options{calendars_file} is not writable. The add/edit calendars tab won't appear
unless this file is writable.
p1
}
if ($options{data_storage_mode} == 0 && !$writable{pending_actions_file}) {
$results .=<Warning: The pending actions data file: $options{pending_actions_file} is not writable. The add/edit calendars tab won't appear
unless this file is writable.
p1
}
if ($options{data_storage_mode} == 0 && !$writable{events_file}) {
$results .=<Warning: The events data file: $options{events_file} is not writable. The add/edit events tab won't appear
unless this file is writable.
p1
}
my $cwd = `pwd`;
$results .=<Plans version: $plans_version Perl version: $perl_version script name: $name script file path:$cwd script url path: $script_url