#!/usr/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);
}