#!/usr/local/bin/perl # # CalendarScript # Version: 3.21 # # Copyright 2003 Matt Kruse # http://www.CalendarScript.com/ # BEGIN { # CHANGE THE LINE BELOW IF NECESSARY # Be sure to remove the # before $BASE_DIR, and change the path between the quotes #$BASE_DIR = "/...change.to.full.file.path.of.dir.../calendarscript/"; # DO NOT CHANGE ANYTHING BELOW HERE! if ($BASE_DIR ne "") { $BASE_DIR =~ s|([^/])$|$1/|; } else { my ($path) = $ENV{'PATH_TRANSLATED'} || $ENV{'SCRIPT_FILENAME'}; unless ($path) { print "Content-type:text/html\n\nERROR:
Your server does not provide the PATH_TRANSLATED or SCRIPT_FILENAME environment variables.

Please see the installation documentation for how to set the \$BASE_DIR variable manually."; exit(0); } $path =~ s|[^/\\]*$||; $path =~ s|([^/])$|$1/|; $BASE_DIR = $path . "calendarscript/"; } unshift(@INC,$BASE_DIR."lib"); require "asp.inc"; require "DBFile.pm"; require "DBFileUtil.inc"; require "TimeLocal.inc"; require "Date.inc"; require "ConfigFile.pm"; require "Event.inc"; require "HTML.pm"; require "CGISession.inc"; require "User.pm"; require "SimpleDateFormat.pm"; require "calendars.inc"; } sub ERROR { my($msg,$severity) = @_; &addUserMessage($msg); &showScreen(); } sub FATALERROR { my ($msg) = @_; &addErrorMessage($msg); if ($in{template} eq "error.html") { print "FATAL ERROR: COULD NOT LOAD error.html"; exit(0); } $in{template} = "error.html"; &showScreen(); } # Load the required template and execute it # ----------------------------------------- sub showScreen { &populateTemplateVariables(); $template_dir = $BASE_DIR . "templates/calendars/" . $Config->get("template_dir") . "/"; $template_file = $template_dir . $in{'template'}; unless (-e $template_file) { &FATALERROR(&getMessage("TEMPLATE_FILE_DOES_NOT_EXIST")); } $template = &ASPLoadTemplate($template_file); &ASPEval($template,$template_dir); &ASPError($tmp_parsed_template) if $@; exit(0); } sub showSameScreen() { &populateTemplateVariables(); $in{'template'} = $in{'fromTemplate'} || "error.html"; &showScreen(); } # Handle error messages # --------------------- sub addUserMessage { my($msg) = shift; if ($msg ne "") { $Template::userMessage .= $msg . "
"; } } sub addErrorMessage { my($msg) = shift; if ($msg ne "") { $Template::errorMessage .= $msg . "
"; } } # Get message text to support language translation # ------------------------------------------------ sub getMessage() { my ($name,$p1,$p2,$p3,$p4) = @_; # Only read in the file if there is a message to be retrieved unless ($MESSAGES) { $msgfile = $BASE_DIR . "templates/admin/$admin_template_dir/messages.txt"; open(MESSAGES,$msgfile) || &FATALERROR("Error opening messages file [$msgfile]: $!"); while() { next if /^#/; next unless /\S/; chomp; my($name,$value) = split(/=/,$_,2); $MESSAGES->{$name} = $value; } close(MESSAGES); } my ($message) = $MESSAGES->{$name}; if ($message eq "") { return "MESSAGE TEXT MISSING FOR: $name"; } if ($p1) { $message =~ s/\%s/$p1/; } if ($p2) { $message =~ s/\%s/$p2/; } if ($p3) { $message =~ s/\%s/$p3/; } if ($p4) { $message =~ s/\%s/$p4/; } return $message; } # Get a list of plugin files # -------------------------- sub getPluginFileList { my ($file,$plugin); my ($pluginfiles,$pluginsfilesfile); $pluginsfilesfile = $plugins_dir."plugin_files.txt"; if (-e $pluginsfilesfile) { open(PLUGINFILES,$pluginsfilesfile) || &FATALERROR(&getMessage("ERROR_OPENING_PLUGIN_FILES_LIST",$!)); while () { next if /^\s*(#|$)/; chomp; ($file,$plugin) = split(/\t/); unless (exists $pluginfiles->{$file}) { $pluginfiles->{$file} = "plugins/$plugin/$file"; } } close(PLUGINFILES); } return $pluginfiles; } # Handle custom-defined functionality # ----------------------------------- sub handleCustomFunction() { my ($funcName,@args) = @_; my ($result) = 0; my ($filename) = $funcName . ".pl"; if ($PluginFiles->{$filename}) { $filename = $BASE_DIR . $PluginFiles->{$filename}; eval("require \"$filename\";"); if ($@) { # Error including file - return error msg and continue running normal functions &addUserMessage(&getMessage("ERROR_REQUIRING_CUSTOM_FUNCTION",$filename,$@)); return 0; } # Try to call custom function eval("\$result = \&${funcName}(\@args);"); if ($@) { # Error calling function - return error msg and continue running normal functions &addUserMessage(&getMessage("ERROR_RUNNING_CUSTOM_FUNCTION",$funcName,$@)); return 0; } # Custom function was executed. Return whatever it returned. return $result; } return 0; } # Get a Template Preference value, either from the config file or the default # --------------------------------------------------------------------------- sub getTemplatePreference { my ($name) = @_; my ($key) = "template_preference_".$Config->get("template_dir")."_".$name; if ($Config->contains($key)) { return $Config->get($key); } return $main::TemplateDefaults->{$name}; } sub LZ { my($x)=shift;if(length($x)==1){return "0$x";}return $x; } sub URLEncode { my($url)=@_; my(@characters)=split(/(\%[0-9a-fA-F]{2})/,$url); foreach(@characters) { if ( /\%[0-9a-fA-F]{2}/ ) { unless ( /(20|7f|[0189a-fA-F][0-9a-fA-F])/i || /2[2356fF]|3[a-fA-F]|40/i ) { s/\%([2-7][0-9a-fA-F])/sprintf "%c",hex($1)/e; } } else { s/([\000-\040\177-\377\074\076\042])/sprintf "%%%02x",unpack("C",$1)/egx; } } return join("",@characters); } # Get input Data # -------------- sub getInput { my ($in,@in,$key,$val); my (@keys,%formvars); if ($ENV{'REQUEST_METHOD'}) { if ($ENV{'REQUEST_METHOD'} eq "GET") { $in = $ENV{'QUERY_STRING'}; } elsif ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN,$in,$ENV{'CONTENT_LENGTH'}); } @in = split(/&/,$in); # First get all the raw form vars foreach $i (0 .. $#in) { $in[$i] =~ s/\+/ /g; ($key, $val) = split(/=/,$in[$i],2); $key =~ s/%(..)/pack("c",hex($1))/ge; $val =~ s/%(..)/pack("c",hex($1))/ge; # Keep a record of their order, because later values take precendent push(@keys,$key); $formvars{$key} = $val; } # Process the special QUERY_STRING field, if it exists # These values come first and then might be over-written if ($formvars{'QUERY_STRING'}) { @in = split(/&/,$formvars{'QUERY_STRING'}); foreach $i (0 .. $#in) { $in[$i] =~ s/\+/ /g; ($key, $val) = split(/=/,$in[$i],2); if ($val ne "") { $in{$key} = $val; if ($in{'datestring'} && (($key eq 'year') || ($key eq 'month') || ($key eq 'date'))) { delete $in{'datestring'}; } if ($key eq "datestring") { delete $in{'year'}; delete $in{'month'}; delete $in{'date'}; } } } delete $formvars{'QUERY_STRING'}; } # Process all the new field values, over-writing the old ones foreach $key (@keys) { next if ($key eq "QUERY_STRING"); $in{$key} = $formvars{$key}; if ($in{'datestring'} && (($key eq 'year') || ($key eq 'month') || ($key eq 'date'))) { delete $in{'datestring'}; } if ($key eq "datestring") { delete $in{'year'}; delete $in{'month'}; delete $in{'date'}; } } # Form the query string from form input foreach $key (keys %in) { if (($key eq "command") || ($key eq "username") || ($key eq "password") || ($key =~/^FIELD_/)) { delete $formvars{$key}; next; } if ($QUERY_STRING ne "") { $QUERY_STRING .= "&"; } $QUERY_STRING .= &URLEncode($key) . "=" . &URLEncode($in{$key}); } $FORM_QUERY = join('&', map {"$_=$formvars{$_}"} keys %formvars); } elsif ($ENV{'DOCUMENT_URI'}) { open(SSI,$BASE_DIR."ssi.txt"); while() { chomp; ($key,$val) = ( /^\s*([^=]+)\s*=\s*"?(.*?)"?$/o ); $key =~ s|\s*$||; $val =~ s|\s*$||; next unless ($key); $in{$key} = $val; } close(SSI); $no_session = 1; } elsif ($#ARGV >= 0) { while ($in = shift(@ARGV)) { ($key,$val) = split(/=/,$in); $in{$key} = $val; } $no_session = 1; $no_header=1; } } ################################# # Here is all the dirty work... # ################################# $|=1; # Read the main admin config file $admin_config = $BASE_DIR . "config.txt"; $AdminConfig = new ConfigFile($admin_config); $Template::AdminConfig = $AdminConfig; $admin_template_dir = $AdminConfig->get("admin_template_dir") || "English"; $plugins_dir = $BASE_DIR . "plugins/"; $PluginFiles = &getPluginFileList(); # Get input unless(&handleCustomFunction("display_before_getInput")) { &getInput(); } &handleCustomFunction("display_after_getInput"); # Start output # ------------ if (($ENV{'HTTP_COOKIE'} =~ /CGISessionID/) || ($in{'command'} eq "login")) { $Session = new CGISession($BASE_DIR . "session/"); unless ($no_session) { my ($id) = ($ENV{'HTTP_COOKIE'} =~ /CGISessionID\s*=\s*([^;]*)/); $Session->getSession($id); if (($Session->isValid()) && ($in{'command'} ne "logout")) { print "Set-cookie: CGISessionID=",$Session->getValue("_id"),";path=/\n"; } else { print "Set-cookie: CGISessionID=;path=/;expires=Thu, 01-Jan-1970 00:00:00 GMT\n"; } } # Make session available in template files $Template::Session = $Session; } unless ($no_header) { print "Content-type: text/html\n\n"; } $in{'calendar'} ||= $AdminConfig->get("default_calendar"); $in{'calendar'} =~ s|[^\w\d\._]||g; $calendar = $in{'calendar'}; $in{'template'} ||= "default.html"; $in{'template'} =~ s|[^\w\d\._]||g; $db_dir = $BASE_DIR . "calendars/" . $in{'calendar'} . "/"; $config_file = $db_dir . "config.txt"; $schedule_db = $db_dir . "schedule"; $events_db = $db_dir . "events"; $calendars_db = $BASE_DIR . "calendars"; $users_db = $BASE_DIR . "users"; $permissions_db = $BASE_DIR . "permissions"; # Read the config file for the calendar $Config = new ConfigFile($config_file); $Template::Config = $Config; # Get calendar name, description $Calendar = &getCalendarInfo($calendar); # Get display options for the template set to be used $TemplateFields = &GetFieldProperties($BASE_DIR."templates/calendars/".$Config->get("template_dir")."/preferences.txt"); foreach $field (@$TemplateFields) { $TemplateDefaults->{$field->{'field_name'}} = $field->{'defaultvalue'}; } # The CGI URL for call-back $Template::CGI_URL = $AdminConfig->get("calendar_url") || $ENV{'SCRIPT_NAME'} || $ENV{'REQUEST_URI'}; $Template::CGI_URL_QUERYSTRING = $Template::CGI_URL . "?".$QUERY_STRING; if ($QUERY_STRING ne "") { $Template::CGI_URL_QUERYSTRING .= "&"; } $Template::QUERY_STRING = $QUERY_STRING; $Template::CGI_HIDDEN_FIELDS .= ""; $Template::ADMIN_CGI_URL = $AdminConfig->get("calendar_admin_url"); # Attempt to Login? # ----------------- if ($in{'command'} eq "login") { unless(&handleCustomFunction("display_before_login")) { $User = new User($in{username}, $users_db, $permissions_db); my ($result) = $User->login($in{password}); if ($result == 1) { # User logged in $Session->{'username'} = $User->{'username'}; $Session->{'name'} = $User->{'name'}; $Session->{'calendar'} = $calendar; &addUserMessage(($User->{'name'} || $User->{'username'}) . $User::MSG_LOGGED_IN_SUCCESSFULLY); } elsif ($result == 2) { undef $Session; &addUserMessage(&getMessage("CALENDAR_PASSWORD_MUST_BE_CHANGED")); &showSameScreen(); } else { &addUserMessage($User->getErrorMessage()); &showSameScreen(); } } &handleCustomFunction("display_after_login"); } # Handle Logout # ------------- if ($in{'command'} eq "logout") { unless(&handleCustomFunction("display_before_logout")) { $Session->ExpireNow(); $Session->cleanupExpiredSessions(); undef $Session; undef $Template::Session; undef $User; } &handleCustomFunction("display_after_logout"); } # Create a global "User" object if it doesn't already exist # --------------------------------------------------------- unless(&handleCustomFunction("display_before_create_user")) { unless ($User) { if ($Session && ($Session->{'username'} ne "")) { $User = new User($Session->{'username'}, $users_db, $permissions_db); $User->{'logged_in'} = 1; $Session->{'calendar'} = $calendar; } else { $User = new User('anonymous', $users_db, $permissions_db); $User->{'logged_in'} = 0; } } $Template::User = $User; } &handleCustomFunction("display_after_create_user"); # Require Login? # -------------- if ($Config->get("require_login")) { unless(&handleCustomFunction("display_before_require_login")) { if ($Session->{'username'}) { unless ($User->hasPermission($calendar,"VIEW")) { $Template::userMessage = &getMessage("CALENDAR_NO_VIEW_PERMISSION"); &FATALERROR(""); } } else { $in{'template'} = "login.html"; &showScreen(); } } } &handleCustomFunction("display_after_require_login"); # Create the event and schedule database objects $DBEvents = new DBFile($events_db); $DBSchedule = new DBFile($schedule_db); # Handle any commands here # ------------------------ # SEARCH # ------ if ($in{'command'} eq "search") { unless(&handleCustomFunction("display_before_search")) { my ($properties,$name,$field); foreach $name (keys %in) { $field = $name; if (($in{$name} ne "") && ($field =~ s/^FIELD_//)) { $properties->{$field} = $in{$name}; } } if (scalar keys %$properties <= 0) { &addUserMessage("Search query must not be blank!"); } else { $start = Time::Local::timegm(0,0,0,$in{start_date},$in{start_month}-1,$in{start_year}); $end = Time::Local::timegm(0,0,0,$in{end_date},$in{end_month}-1,$in{end_year}); $Template::SEARCH_RESULTS = &Event::search($DBEvents, $DBSchedule, "", $properties, $start, $end); } } &handleCustomFunction("display_after_search"); } # Load the required template and execute it # ----------------------------------------- &showScreen(); END { if (defined $main::Session && ref($main::Session) eq "CGISession") { $main::Session->saveSession(); } } ################################################## # Populate variables and references for templates ################################################## sub populateTemplateVariables { $localtime_offset = 3600*$Config->get("time_zone_offset"); ($now_ss,$now_mi,$now_hh,$now_dd,$now_mm,$now_yy,$now_wd,$now_yd,$now_dst) = localtime(time+$localtime_offset); $now_mm++; $now_yy += 1900; # Get the displayed dates, etc $year = substr($in{'datestring'},0,4) || $in{'year'} || substr($in{'selected_datestring'},0,4) || $now_yy; $month = substr($in{'datestring'},4,2) || $in{'month'} || substr($in{'selected_datestring'},4,2) || $now_mm; $date = substr($in{'datestring'},6,2) || $in{'date'} || substr($in{'selected_datestring'},6,2) || $now_dd; # Get selected date $selected_datestring = $in{'selected_datestring'} || $year.&LZ($now_mm).&LZ($now_dd); # Date-related fields and HTML elements $Template::YEAR_SELECT = ""; $Template::MONTH_SELECT = ""; $Template::MONTH_ABBREVIATION_SELECT = ""; $Template::DAY_NAMES = $Config->get("day_names"); $Template::DAY_ABBREVIATIONS = $Config->get("day_abbreviations"); $Template::MONTH_NAMES = $Config->get("month_names"); $Template::MONTH_ABBREVIATIONS = $Config->get("month_abbreviations"); for ($i=0; $i<7; $i++) { ${"Template::DAY_NAME_".$i} = $Template::DAY_NAMES->[$i]; } for ($i=0; $i<12; $i++) { ${"Template::MONTH_NAME_".$i} = $Template::MONTH_NAMES->[$i]; } for ($i=0; $i<7; $i++) { ${"Template::DAY_ABBREVIATION_".$i} = $Template::DAY_ABBREVIATIONS->[$i]; } for ($i=0; $i<12; $i++) { ${"Template::MONTH_ABBREVIATION_".$i} = $Template::MONTH_ABBREVIATIONS->[$i]; } $Template::MONTH_NAME = $Template::MONTH_NAMES->[$month-1]; $Template::YEAR = $year; $Template::MONTH = $month; $Template::DATE = $date; $Template::DATESTRING = $year . &LZ($month) . &LZ($date); $Template::NEXT_YEAR = $year+1; $Template::LAST_YEAR = $year-1; ($Template::NEXT_MONTH_YEAR,$Template::NEXT_MONTH) = &Date::getNextMonthYear($year,$month); $Template::NEXT_MONTH_NAME = $Template::MONTH_NAMES->[$Template::NEXT_MONTH-1]; ($Template::LAST_MONTH_YEAR,$Template::LAST_MONTH) = &Date::getLastMonthYear($year,$month); $Template::LAST_MONTH_NAME = $Template::MONTH_NAMES->[$Template::LAST_MONTH-1]; ($Template::LAST_WEEK_YEAR,$Template::LAST_WEEK_MONTH,$Template::LAST_WEEK_DATE) = &Date::getLastWeek($year,$month,$date); ($Template::NEXT_WEEK_YEAR,$Template::NEXT_WEEK_MONTH,$Template::NEXT_WEEK_DATE) = &Date::getNextWeek($year,$month,$date); ($Template::NEXT_DAY_YEAR,$Template::NEXT_DAY_MONTH,$Template::NEXT_DAY_DATE) = &Date::getTomorrow($year,$month,$date); $Template::NEXT_DAY_DATESTRING = $Template::NEXT_DAY_YEAR . &LZ($Template::NEXT_DAY_MONTH) . &LZ($Template::NEXT_DAY_DATE); ($Template::PREVIOUS_DAY_YEAR,$Template::PREVIOUS_DAY_MONTH,$Template::PREVIOUS_DAY_DATE) = &Date::getYesterday($year,$month,$date); $Template::PREVIOUS_DAY_DATESTRING = $Template::PREVIOUS_DAY_YEAR . &LZ($Template::PREVIOUS_DAY_MONTH) . &LZ($Template::PREVIOUS_DAY_DATE); ($Template::TODAY_YEAR,$Template::TODAY_MONTH,$Template::TODAY_DATE) = ($now_yy,$now_mm,$now_dd); $Template::TODAY_DATESTRING = $Template::TODAY_YEAR . &LZ($Template::TODAY_MONTH) . &LZ($Template::TODAY_DATE); # Other $Template::CALENDAR = $Calendar; $Template::CALENDAR_KEY = $Calendar->{'key'}; # Call-back method to get events *Template::getEvents = \&getEvents; *Template::getEvent = \&getEvent; # Method to get template preferences *Template::getPreference = \&getTemplatePreference; # Form input %Template::in = %in; # Looping and conditional special tags &ASPCustomTag('\s*FOREACH\s*GRID\s*ROW\s*','foreach $ROW (0 .. $Grid->{rowcount}-1) {'); &ASPCustomTag('\s*FOREACH\s*GRID\s*COLUMN\s*','foreach $COL (0 .. $Grid->{colcount}-1) { $DAY = $Grid->{grid}->[$ROW]->[$COL]; my ($EVENTS) = $Grid->{grid}->[$ROW]->[$COL]->{events};'); &ASPCustomTag('\s*FOREACH\s*DAY\s*OF\s*WEEK\s*','foreach $COL (0 .. $Grid->{colcount}-1) { $DAY = $Grid->{grid}->[0]->[$COL]; my ($EVENTS) = $Grid->{grid}->[0]->[$COL]->{events};'); &ASPCustomTag('\s*FOREACH\s*HOUR\s*OF\s*DAY\s*','foreach $HOUR ( 99, $Config->{days_hours_display_start} .. $Config->{days_hours_display_end} ) { my ($EVENTS) = $DAY->{hours}->[$HOUR]->{events};'); &ASPCustomTag('\s*FOREACH\s*EVENTLIST','foreach $datestring (sort keys %$EventList) { $DAY = $EventList->{$datestring}; my ($EVENTS) = $DAY->{events};'); &ASPCustomTag('\s*FOREACH\s*EVENT\s*','foreach $EVENT (@$EVENTS) { '); &ASPCustomTag('\s*FOREACH\s*SEARCH\s*RESULT\s*','foreach $i (0 .. $#$SEARCH_RESULTS) { $EVENT = $SEARCH_RESULTS->[$i]; '); &ASPCustomTag('\s*IF\s*SEARCH\s*RESULT\s*','if ($in{command} eq "search") {'); &ASPCustomTag('\s*IF\s*SEARCH\s*RESULTS\s*EXIST\s*','if ($#$SEARCH_RESULTS < 0) {'); &ASPCustomTag('\s*IF\s*EVENTS\s*EXIST\s*','if ($#{$EVENTS} >= 0) {'); &ASPCustomTag('\s*IF\s*NEXT\s*OCCURRENCE\s*EXISTS\s*','if ($EVENT->{schedule}->{nextoccurrence}) {'); &ASPCustomTag('\s*IF\s*NO\s*EVENTS\s*EXIST\s*','if (!($#{$EVENTS} >= 0)) {'); &ASPCustomTag('\s*IF\s*DISPLAY\s*','if ($DAY->{\'display\'}) {'); &ASPCustomTag('\s*IF\s*SELECTED\s*','if ($DAY->{\'selected\'}) {'); &ASPCustomTag('\s*IF\s*USER\s*LOGGED\s*IN\s*','if ($User->{username} ne "anonymous") {'); &ASPCustomTag('\s*/FOREACH\s*','}'); &ASPCustomTag('\s*ELSE\s*','}else{'); &ASPCustomTag('\s*/IF\s*','}'); # Other special tags &ASPCustomTag('=?\s*EVENT\s*FIELD\s*\((\w+)\)\s*','= $EVENT->{details}->{$1} '); &ASPCustomTag('=?\s*SCHEDULE\s*FIELD\s*\((\w+)\)\s*','= $EVENT->{schedule}->{$1} '); &ASPCustomTag('=?\s*PREFERENCE\s*\((\w+)\)\s*','= &getPreference(\'$1\') '); &ASPCustomTag('\s*LAST\s*YEAR\s*LINK\s*','= $CGI_URL_QUERYSTRING."year=".$LAST_YEAR'); &ASPCustomTag('\s*NEXT\s*YEAR\s*LINK\s*','= $CGI_URL_QUERYSTRING."year=".$NEXT_YEAR'); &ASPCustomTag('\s*LAST\s*MONTH\s*LINK\s*','= $CGI_URL_QUERYSTRING."year=".$LAST_MONTH_YEAR."&month=".$LAST_MONTH'); &ASPCustomTag('\s*NEXT\s*MONTH\s*LINK\s*','= $CGI_URL_QUERYSTRING."year=".$NEXT_MONTH_YEAR."&month=".$NEXT_MONTH'); &ASPCustomTag('\s*LAST\s*WEEK\s*LINK\s*','= $CGI_URL_QUERYSTRING."year=".$LAST_WEEK_YEAR."&month=".$LAST_WEEK_MONTH."&date=".$LAST_WEEK_DATE'); &ASPCustomTag('\s*NEXT\s*WEEK\s*LINK\s*','= $CGI_URL_QUERYSTRING."year=".$NEXT_WEEK_YEAR."&month=".$NEXT_WEEK_MONTH."&date=".$NEXT_WEEK_DATE'); &ASPCustomTag('\s*PREVIOUS\s*DAY\s*LINK\s*','= $CGI_URL_QUERYSTRING."datestring=".$PREVIOUS_DAY_DATESTRING."&selected_datestring=".$PREVIOUS_DAY_DATESTRING'); &ASPCustomTag('\s*NEXT\s*DAY\s*LINK\s*','= $CGI_URL_QUERYSTRING."datestring=".$NEXT_DAY_DATESTRING."&selected_datestring=".$NEXT_DAY_DATESTRING'); &ASPCustomTag('\s*CALENDAR\s*NAME\s*','= ($CALENDAR->{name})'); &ASPCustomTag('\s*CALENDAR\s*DESCRIPTION\s*','= ($CALENDAR->{description})'); &ASPCustomTag('\s*CALENDAR\s*KEY\s*','= ($CALENDAR->{key})'); } ################################################## # Subroutine called by Template to get an event ################################################## sub getEvent { my ($id) = @_; unless(&handleCustomFunction("display_before_getEvent",$id)) { my ($db) = new DBFile($events_db); my ($event) = $db->getRecord( {'id'=>$id } ); if ($event == 0) { return {}; } # Add the auto-links if necessary if ($Config->get("auto_link")) { foreach $key (keys %$event) { $event->{$key} = &HTML::autoLink($event->{$key},$Config->get("auto_link_target")); } } &handleCustomFunction("display_after_getEvent"); return $event; } } ################################################## # Subroutine called by Template to populate events ################################################## sub getEvents { my ($properties) = @_; unless(&handleCustomFunction("display_before_getEvents",$properties)) { my ($event_ids,$events,$event_details,$s); my ($month,$year,$date,$datestring,$start,$end); $month = &LZ($properties->{'month'}) || &LZ($Template::MONTH); $year = $properties->{'year'} || ($Template::YEAR); $date = &LZ($properties->{'date'}) || &LZ($Template::DATE); if ($properties->{'range'} eq "month") { $datestring = $year . $month . "01"; $properties->{'startdate'} = $datestring; } else { $datestring = $year . $month . $date; $properties->{'startdate'} ||= $datestring; } ($start,$end) = &Date::getTimeSpan( $properties ); $Template::RANGE_START = &SimpleDateFormat::formatDate($start,$Config->get("date_format")); ($Template::RANGE_START_DATE,$Template::RANGE_START_MONTH,$Template::RANGE_START_YEAR) = (gmtime($start))[3,4,5]; $Template::RANGE_START_MONTH++; $Template::RANGE_START_YEAR+=1900; $Template::RANGE_END = &SimpleDateFormat::formatDate($end,$Config->get("date_format")); ($Template::RANGE_END_DATE,$Template::RANGE_END_MONTH,$Template::RANGE_END_YEAR) = (gmtime($end))[3,4,5]; $Template::RANGE_END_MONTH++; $Template::RANGE_END_YEAR+=1900; $schedule = &Event::getEventsInRange($DBSchedule,$start,$end); foreach $s (@$schedule) { $event_ids->{$s->{'event_id'}}=1; } $event_details = &Event::getEventDetails($DBEvents,$event_ids); foreach $s (@$schedule) { # Skip the event unless it's approved next unless ($event_details->{$s->{'event_id'}}->{'approved'}); # Skip if it's private next if ($event_details->{$s->{'event_id'}}->{'private'}); push(@$events, { 'schedule'=>$s, 'details'=>$event_details->{$s->{'event_id'}} } ); } # Put the raw events into the template # ------------------------------------ $Template::EVENTS = $events; my ($Grid); my ($start_ss,$start_mi,$start_hh,$start_dd,$start_mm,$start_yy,$start_wd,$start_yd,$start_dst) = gmtime($start); $week_start_day = $Config->get("week_start_day"); if ($start_wd >= $week_start_day) { $offset_days = $start_wd - $week_start_day; } elsif ($start_wd < $week_start_day) { $offset_days = 7-$week_start_day+$start_wd; } $i = $start; my $x = 0; my $y = 0; # Place pre-empty grid cells if more than one row if ((($end - $start)/86400) > 7) { foreach (0 .. ($offset_days-1)) { $Grid->{'grid'}->[$y]->[$x]->{'display'} = 0; $x++; } } while ($i < $end) { my ($ss,$mi,$hh,$dd,$mm,$yy,$wd,$yd,$dst) = gmtime($i); my ($datestring) = (1900+$yy) . &LZ($mm+1) . &LZ($dd); $gridMappings->{$datestring} = [$y,$x]; $Grid->{'grid'}->[$y]->[$x]->{'dd'} = $dd; $Grid->{'grid'}->[$y]->[$x]->{'mm'} = $mm+1; $Grid->{'grid'}->[$y]->[$x]->{'yyyy'} = 1900+$yy; $Grid->{'grid'}->[$y]->[$x]->{'wd'} = $wd; $Grid->{'grid'}->[$y]->[$x]->{'yd'} = $yd; $Grid->{'daynames'}->[$x] = $Template::DAY_NAMES->[$wd]; $Grid->{'grid'}->[$y]->[$x]->{'dayname'} = $Template::DAY_NAMES->[$wd]; $Grid->{'grid'}->[$y]->[$x]->{'dayabbreviation'} = $Template::DAY_ABBREVIATIONS->[$wd]; $Grid->{'grid'}->[$y]->[$x]->{'monthname'} = $Template::MONTH_NAMES->[$mm]; $Grid->{'grid'}->[$y]->[$x]->{'monthabbreviation'} = $Template::MONTH_ABBREVIATIONS->[$mm]; $Grid->{'grid'}->[$y]->[$x]->{'datestring'} = $datestring; $Grid->{'grid'}->[$y]->[$x]->{'display'} = 1; if ($datestring eq $selected_datestring) { $Grid->{'grid'}->[$y]->[$x]->{'selected'} = 1; } $x++; $Grid->{'rowcount'} = $y+1; if ($x > $Grid->{'colcount'}) { $Grid->{'colcount'} = $x; } if ($x > 6) { $x=0; $y++; } $i+=86400; } # Place post-empty grid cells if more than one row if ((($end - $start)/86400) > 7) { while($wd < 6) { $Grid->{'grid'}->[$y]->[$x]->{'display'} = 0; $x++; $wd++; } } $Template::Grid = $Grid; $Template::GRID_ROW_COUNT = $Grid->{'rowcount'}; $Template::GRID_COLUMN_COUNT = $Grid->{'colcount'}; # Map events on to Grid and dates/hours/etc # ----------------------------------------- foreach $event (sort {$a->{'schedule'}->{'start'} <=> $b->{'schedule'}->{'start'} } @$events) { # Time of event if ($event->{'schedule'}->{'start_time'} == $event->{'schedule'}->{'end_time'}) { $event->{'schedule'}->{'end_time'} = ""; } if ($event->{'schedule'}->{'all_day'}) { $event->{'schedule'}->{'start_time'} = ""; $event->{'schedule'}->{'end_time'} = ""; $event->{'schedule'}->{'start_hh'}=99; $event->{'schedule'}->{'start_mm'}=0; $event->{'schedule'}->{'end_hh'}=99; $event->{'schedule'}->{'end_mm'}=0; } else { ($hh,$mm) = ($event->{'schedule'}->{'start_time'} =~ /^(\d\d)(\d\d)/); $event->{'schedule'}->{'start_hh'} = $hh; $event->{'schedule'}->{'start_mm'} = $mm; ($hh,$mm) = ($event->{'schedule'}->{'end_time'} =~ /^(\d\d)(\d\d)/); $event->{'schedule'}->{'end_hh'} = $hh; $event->{'schedule'}->{'end_mm'} = $mm; $event->{'schedule'}->{'start_time'} = &Date::formatTime($event->{'schedule'}->{'start_time'}, $Config->get("time_format")); $event->{'schedule'}->{'end_time'} = &Date::formatTime($event->{'schedule'}->{'end_time'} , $Config->get("time_format")); } # Date, month, day name, month name, etc my ($event_start) = $event->{'schedule'}->{'start'}; my ($event_end) = $event->{'schedule'}->{'end'}; my ($continued) = 0; # If event spans multiple days, keep track of it $event->{'schedule'}->{'span'} = (($event_end - $event_start) > 86400)?1:0; while ($event_start <= $event_end) { if (($event_start >= $start) && ($event_start <= $end)) { my ($ss,$mi,$hh,$dd,$mm,$yy,$wd,$yd,$dst) = gmtime($event_start); $event->{'schedule'}->{'year'} = (1900+$yy); $event->{'schedule'}->{'month'} = $mm+1; $event->{'schedule'}->{'date'} = $dd; $event->{'schedule'}->{'day'} = $wd; my ($datestring) = (1900+$yy) . &LZ($mm+1) . &LZ($dd); $event->{'schedule'}->{'datestring'} = $datestring; if ($event->{'schedule'}->{'all_day'}) { $hh = 99; } else { $hh = &LZ($hh); } push(@{$Grid->{'grid'}->[$gridMappings->{$datestring}->[0]]->[$gridMappings->{$datestring}->[1]]->{'events'}} , $event); push(@{$Grid->{'grid'}->[$gridMappings->{$datestring}->[0]]->[$gridMappings->{$datestring}->[1]]->{'hours'}->[$hh]->{'events'}} , $event); $continued=1; } $event_start = $event_start+86400; } } # Sort the events on each day into chronological order for ($y=0; $y<$Grid->{'rowcount'}; $y++) { for ($x=0; $x<$Grid->{'colcount'}; $x++) { if ($Grid->{'grid'}->[$y]->[$x]->{'display'}) { @{$Grid->{'grid'}->[$y]->[$x]->{'events'}} = sort { ($a->{'schedule'}->{'start'} <=> $b->{'schedule'}->{'start'}) || ($a->{'details'}->{'id'} <=> $b->{'details'}->{'id'}) } @{$Grid->{'grid'}->[$y]->[$x]->{'events'}}; $EventList->{$Grid->{'grid'}->[$y]->[$x]->{'datestring'}} = $Grid->{'grid'}->[$y]->[$x]; } } } $Template::EventList = $EventList; if ($properties->{'range'} eq "day") { $Template::DAY = $Grid->{'grid'}->[0]->[0]; $Template::EVENTS = $Grid->{'grid'}->[0]->[0]->{'events'}; } } &handleCustomFunction("display_after_getEvents",$properties); }