CalendarScript Help

apps

#1

I keep getting this message:

Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator, webmaster@equineempire.com and inform them of the time the error occurred, and anything you might have done that may have caused the error.

More information about this error may be available in the server error log.

Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.

What am I doing wrong? Do the files have to have the extension .cgi, because they are currently .pl?

Here’s my script

#!/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 = “/cig-bin/calendar/”;

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 “%%x”,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 .= “<INPUT TYPE=“hidden” NAME=“QUERY_STRING” VALUE=”$FORM_QUERY">";
$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 = “<SELECT NAME=“year”>” . &HTML::yearOptions($year) ."";
$Template::MONTH_SELECT = “<SELECT NAME=“month”>” . &HTML::monthNameOptions($month) . “”;
$Template::MONTH_ABBREVIATION_SELECT = “<SELECT NAME=“month”>” . &HTML::monthAbbreviationOptions($month) . “”;
$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(’\sFOREACH\sGRID\sROW\s’,‘foreach $ROW (0 … $Grid->{rowcount}-1) {’);
&ASPCustomTag(’\sFOREACH\sGRID\sCOLUMN\s’,‘foreach $COL (0 … $Grid->{colcount}-1) { $DAY = $Grid->{grid}->[$ROW]->[$COL]; my ($EVENTS) = $Grid->{grid}->[$ROW]->[$COL]->{events};’);
&ASPCustomTag(’\sFOREACH\sDAY\sOF\sWEEK\s*’,‘foreach $COL (0 … $Grid->{colcount}-1) { $DAY = $Grid->{grid}->[0]->[$COL]; my ($EVENTS) = $Grid->{grid}->[0]->[$COL]->{events};’);
&ASPCustomTag(’\sFOREACH\sHOUR\sOF\sDAY\s*’,‘foreach $HOUR ( 99, $Config->{days_hours_display_start} … $Config->{days_hours_display_end} ) { my ($EVENTS) = $DAY->{hours}->[$HOUR]->{events};’);
&ASPCustomTag(’\sFOREACH\sEVENTLIST’,‘foreach $datestring (sort keys %$EventList) { $DAY = $EventList->{$datestring}; my ($EVENTS) = $DAY->{events};’);
&ASPCustomTag(’\sFOREACH\sEVENT\s*’,‘foreach $EVENT (@$EVENTS) { ‘);
&ASPCustomTag(’\sFOREACH\sSEARCH\sRESULT\s’,‘foreach $i (0 … $#$SEARCH_RESULTS) { $EVENT = $SEARCH_RESULTS->[$i]; ‘);
&ASPCustomTag(’\sIF\sSEARCH\sRESULT\s’,‘if ($in{command} eq “search”) {’);
&ASPCustomTag(’\sIF\sSEARCH\sRESULTS\sEXIST\s*’,‘if ($#$SEARCH_RESULTS < 0) {’);
&ASPCustomTag(’\sIF\sEVENTS\sEXIST\s’,‘if ($#{$EVENTS} >= 0) {’);
&ASPCustomTag(’\sIF\sNEXT\sOCCURRENCE\sEXISTS\s*’,‘if ($EVENT->{schedule}->{nextoccurrence}) {’);
&ASPCustomTag(’\sIF\sNO\sEVENTS\sEXIST\s*’,‘if (!($#{$EVENTS} >= 0)) {’);
&ASPCustomTag(’\sIF\sDISPLAY\s*’,‘if ($DAY->{‘display’}) {’);
&ASPCustomTag(’\sIF\sSELECTED\s*’,‘if ($DAY->{‘selected’}) {’);
&ASPCustomTag(’\sIF\sUSER\sLOGGED\sIN\s*’,‘if ($User->{username} ne “anonymous”) {’);
&ASPCustomTag(’\s*/FOREACH\s*’,’}’);
&ASPCustomTag(’\sELSE\s’,’}else{’);
&ASPCustomTag(’\s*/IF\s*’,’}’);

Other special tags

&ASPCustomTag(’=?\sEVENT\sFIELD\s*((\w+))\s*’,’= $EVENT->{details}->{$1} ‘);
&ASPCustomTag(’=?\sSCHEDULE\sFIELD\s*((\w+))\s*’,’= $EVENT->{schedule}->{$1} ‘);
&ASPCustomTag(’=?\sPREFERENCE\s((\w+))\s*’,’= &getPreference(’$1’) ‘);
&ASPCustomTag(’\sLAST\sYEAR\sLINK\s’,’= $CGI_URL_QUERYSTRING.“year=”.$LAST_YEAR’);
&ASPCustomTag(’\sNEXT\sYEAR\sLINK\s’,’= $CGI_URL_QUERYSTRING.“year=”.$NEXT_YEAR’);
&ASPCustomTag(’\sLAST\sMONTH\sLINK\s’,’= $CGI_URL_QUERYSTRING.“year=”.$LAST_MONTH_YEAR."&month=".$LAST_MONTH’);
&ASPCustomTag(’\sNEXT\sMONTH\sLINK\s’,’= $CGI_URL_QUERYSTRING.“year=”.$NEXT_MONTH_YEAR."&month=".$NEXT_MONTH’);
&ASPCustomTag(’\sLAST\sWEEK\sLINK\s’,’= $CGI_URL_QUERYSTRING.“year=”.$LAST_WEEK_YEAR."&month=".$LAST_WEEK_MONTH."&date=".$LAST_WEEK_DATE’);
&ASPCustomTag(’\sNEXT\sWEEK\sLINK\s’,’= $CGI_URL_QUERYSTRING.“year=”.$NEXT_WEEK_YEAR."&month=".$NEXT_WEEK_MONTH."&date=".$NEXT_WEEK_DATE’);

&ASPCustomTag(’\sPREVIOUS\sDAY\sLINK\s’,’= $CGI_URL_QUERYSTRING.“datestring=”.$PREVIOUS_DAY_DATESTRING."&selected_datestring=".$PREVIOUS_DAY_DATESTRING’);
&ASPCustomTag(’\sNEXT\sDAY\sLINK\s’,’= $CGI_URL_QUERYSTRING.“datestring=”.$NEXT_DAY_DATESTRING."&selected_datestring=".$NEXT_DAY_DATESTRING’);

&ASPCustomTag(’\sCALENDAR\sNAME\s*’,’= ($CALENDAR->{name})’);
&ASPCustomTag(’\sCALENDAR\sDESCRIPTION\s*’,’= ($CALENDAR->{description})’);
&ASPCustomTag(’\sCALENDAR\sKEY\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);
}