#!/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!

	sub exitGracefully() {
		if (defined $main::Session && ref($main::Session) eq "CGISession") { $main::Session->saveSession(); }
		exit(0);
		}

	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\n<B>ERROR:</B><BR>Your server does not provide the PATH_TRANSLATED or SCRIPT_FILENAME environment variables.<br><br>Please see the installation documentation for how to set the \$BASE_DIR variable manually.";
			&exitGracefully();
			}
		$path =~ s|[^/\\]*$||;
		$path =~ s|\\|/|g;
		$path =~ s|/+|/|g;
		$path =~ s|([^/])$|$1/|;
		$BASE_DIR = $path . "calendarscript/";
		}
	unshift(@INC,$BASE_DIR."lib");
	unshift(@INC,$BASE_DIR."plugins");
	require "DBFile.pm";
	require "DBFileUtil.inc";
	require "asp.inc";
	require "TimeLocal.inc";
	require "Date.inc";
	require "ConfigFile.pm";
	require "Event.inc";
	require "calendars.inc";
	require "CGISession.inc";
	require "HTML.pm";
	require "User.pm";
	}

sub ERROR {
	my($msg,$severity) = @_;
	&addUserMessage($msg);
	&showSameScreen();
	}
sub FATALERROR {
	my ($msg) = @_;
	&addErrorMessage($msg);
	if ($in{template} eq "error.html") { print "Content-type:text/html\n\n$Template::errorMessage \n<br>\n<br>\n FATAL ERROR: COULD NOT LOAD error.html"; &exitGracefully(); }
	$in{template} = "error.html";
	&showScreen();
	}

# Load the required template and execute it
# -----------------------------------------
sub showScreen {
	$template_dir = $BASE_DIR . "templates/admin/$admin_template_dir/";
	$template_file = &getFile($template_dir . $in{template});
	unless (-e $template_file) { &FATALERROR(&getMessage("TEMPLATE_FILE_DOES_NOT_EXIST")); }
	$Template::thisTemplate = $in{template};
	$template = &ASPLoadTemplate($template_file);
	&ASPEval($template,$template_dir);
	&ASPError($tmp_parsed_template) if $@;
	&exitGracefully();
	}
sub showSameScreen() {
	$in{'template'} = $in{'fromTemplate'} || "error.html";
	&showScreen();
	}

# Handle error messages
# ---------------------
sub addUserMessage {
	my($msg) = shift;
	if ($msg ne "") {
		$Template::userMessage .= $msg . "<BR>";
		}
	}
sub addErrorMessage {
	my($msg) = shift;
	if ($msg ne "") {
		$Template::errorMessage .= $msg . "<BR>";
		}
	}

# Get input Data
# --------------
sub getInput {
	unless(&handleCustomFunction("before_getInput")) {
		my ($in,@in,$key,$val);
		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);
		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;
			$in{$key} = $val;
			}
		}
	}

# Check Permissions
# -----------------
sub checkPermissions {
	unless(&handleCustomFunction("before_checkPermissions")) {
		my ($calendar) = shift;
		$calendar ||= $Session->{'calendar'};
		while ($action = shift) {
			if ($User->hasPermission($calendar, $action)) {
				return;
				}
			}
		$in{'template'} = "permissions_error.html";
		&showScreen();
		}
	}

# 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 (<PLUGINFILES>) {
			next if /^\s*(#|$)/;
			chomp;
			($file,$plugin) = split(/\t/);
			unless (exists $pluginfiles->{$file}) {
				$pluginfiles->{$file} = "plugins/$plugin/$file";
				}
			}
		close(PLUGINFILES);
		}
	return $pluginfiles;
	}

# Get filename from plugin if it exists, or the given file
# --------------------------------------------------------
sub getFile {
	my ($file) = @_;
	my ($filename) = $file;
	$filename =~ s|^.*[/\\]||;
	if ($PluginFiles->{$filename}) {
		return $BASE_DIR . $PluginFiles->{$filename};
		}
	return $file;
	}

# Get a list of available permissions
# -----------------------------------
sub getPermissionsList {
	my ($type,$name,$description);
	my ($permissionslist,$permissionsfile);
	foreach $permissionsfile (${BASE_DIR}."permissions_list.txt", $plugins_dir."permissions_list.txt") {
		if (-e $permissionsfile) {
			open(PERMISSIONSLIST,$permissionsfile) || &FATALERROR(&getMessage("ERROR_OPENING_PERMISSIONS_LIST",$!));
			while (<PERMISSIONSLIST>) {
				next if /^\s*(#|$)/;
				chomp;
				($type,$name,$description) = split(/\t/);
				push(@$permissionslist, {'type'=>$type, 'name'=>$name, 'description'=>$description} );
				}
			close(PERMISSIONSLIST);
			}
		}
	return $permissionslist;
	}

# Get a list of available commands
# --------------------------------
sub getCommandList {
	my ($category,$title,$description,$link,$permissions_required);
	my ($commandlist,$command,$commandsfile,$permissions,$permission,$type,$name,$p);
	my ($i,$allowed);
	$i=0;
	# Always put "View Calendar" in the list
	$commandlist->{'Calendar'}->{'order'}=$i++;
	$command->{'title'} = "View Calendar";
	$command->{'description'} = "";
	$command->{'link'} = $AdminConfig->get("calendar_url")."?calendar=".$calendar;
	push(@{$commandlist->{'Calendar'}->{'commands'}}, $command);
	# Get other commands
	foreach $commandsfile (${BASE_DIR}."command_list.txt", $plugins_dir."command_list.txt") {
		if (-e $commandsfile) {
			open(COMMANDLIST,$commandsfile) || &FATALERROR(&getMessage("ERROR_OPENING_COMMANDS_LIST",$!));
			while (<COMMANDLIST>) {
				my ($command);
				next if /^\s*(#|$)/;
				chomp;
				($category,$title,$description,$link,$permissions_required) = split(/\t/);
				# Only add command to list if user has required permission
				if ($permissions_required) {
					foreach $permission (split(/,/,$permissions_required)) {
						($type,$name) = split(':',$permission);
						if ($type eq "GLOBAL") {
							$allowed = $User->hasPermission("_global",$name);
							}
						else {
							$allowed = $User->hasPermission($calendar,$name);
							}
						last if $allowed;
						}
					}
				else {
					$allowed = 1;
					}
				if ($allowed) {
					unless (defined $commandlist->{$category}) {
						$commandlist->{$category}->{'order'} = $i++;
						}
					$command->{'title'} = $title;
					$command->{'description'} = $description;
					if ($link =~ /^template=/) {
						$command->{'link'} = $Template::CGI_URL . "?" . $link;
						}
					else {
						$command->{'link'} = $link;
						}
					push (@{$commandlist->{$category}->{'commands'}}, $command);
					}
				}
			close(COMMANDLIST);
			}
		}
	return $commandlist;
	}

# 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 = &getFile($BASE_DIR . "templates/admin/$admin_template_dir/messages.txt");
		open(MESSAGES,$msgfile) || &FATALERROR("Error opening messages file [$msgfile]: $!");
		while(<MESSAGES>) {
			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;
	}

# Handle custom-defined functionality
# -----------------------------------
sub handleCustomFunction() {
	my ($funcName) = @_;
	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}();");
		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;
	}

#################################
# 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";

# Get input
&getInput();

# Start output
# ------------
$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"; }
	}
unless ($no_header) {
	print "Content-type: text/html\n\n";
	}

# The CGI URL for call-back
$Template::CGI_URL = $ENV{'SCRIPT_NAME'} || $ENV{'REQUEST_URI'};

# Handle display of the Setup Wizard
$setupScreen = $in{'setupScreen'} || $AdminConfig->get("setup_wizard_completed_steps");
if ($in{'command'} eq "setup") {
	$AdminConfig->set("setup_wizard_completed_steps",$setupScreen);
	foreach $key (keys %in) {
		if ($key =~ /^CONFIG_(.*)/) {
			$AdminConfig->set($1,$in{$key});
			}
		}
	if (!$AdminConfig->save()) {
		&addUserMessage(&getMessage("ERROR_WHILE_TRYING_TO_CONTINUE"));
		&addUserMessage($AdminConfig->getErrorMessage());
		&showSameScreen();
		}
	# If wizard steps are now complete, go to setup complete screen
	if ($AdminConfig->get("setup_wizard_completed_steps") == $AdminConfig->get("setup_wizard_total_steps")) {
		$in{template} = "setup_complete.html";
		&showScreen();
		}
	}
if ($AdminConfig->get("setup_wizard_completed_steps") < $AdminConfig->get("setup_wizard_total_steps")) {
	$setupScreen++;
	$Template::setupScreen = $setupScreen;
	$in{template} = "setup".$setupScreen.".html";
	&showScreen();
	}

$in{template} ||= "login.html";
$in{template} =~ s|[^\w\d\._]||g;
$in{command} =~ s|[^\w\d\._]||g;

$calendar = $Session->getValue("calendar") || $in{'calendar'};
if (($calendar eq "") && ($in{'command'} ne "select_calendar")) {
	$in{'template'} = "select_calendar.html";
	}
elsif ($in{'command'} eq "select_calendar") {
	$calendar = $in{'calendar'};
	$Session->{'calendar'} = $calendar;
	}
$Template::calendar_key = $calendar;

$db_dir          = $BASE_DIR . "calendars/" . $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";
$templates_dir   = $BASE_DIR . "templates/";
$plugins_dir     = $BASE_DIR . "plugins/";

# Make sure calendar directory exists
if ($calendar) {
	unless (-d $db_dir) { &FATALERROR(&getMessage("DATA_DIRECTORY_NOT_FOUND",$calendar,$db_dir)); }
	$Template::Calendar = &getCalendarInfo($calendar);
	}

# Read the config file for the selected calendar, if it exists
if ($calendar) { 
	$Config = new ConfigFile($config_file); 
	$localtime_offset = 3600*$Config->get("time_zone_offset");
	}
$Template::Config = $Config;

# Make session available in template files
$Template::Session = $Session;

# Create a global "User" object
# -----------------------------
if ($Session->{'username'} ne "") {
	$User = new User($Session->{'username'}, $users_db, $permissions_db);
	}
elsif ($in{'username'} ne "") {
	$User = new User($in{'username'}, $users_db, $permissions_db);
	}
$Template::User = $User;

# Get the list of files controlled by plugins
$PluginFiles = &getPluginFileList();

# Force login?
# ------------
unless(&handleCustomFunction("before_forceLogin")) {
	$force_login=0;
	if (($Session->{'username'} eq "") && ($in{'username'} eq "anonymous")) {
		$Session->{'username'} = $User->{'username'};
		$Session->{'name'} = $User->{'name'};
		if ($in{'calendar'} ne "") {
			$Session->{'calendar'} = $in{'calendar'};
			$in{'template'} ||= "main.html";
			}
		else {
			$in{'template'} = "select_calendar.html";
			}
		}
	elsif (!$Session->isValid()) {
		&addUserMessage(&getMessage("SESSION_EXPIRED"));
		$Session->ExpireNow();
		$Session->cleanupExpiredSessions();
		$force_login = 1;
		}
	elsif ( ($Session->isNew() || ($Session->{'username'} eq "")) && ($in{'command'} ne "login")) {
		$force_login = 1;
		}
	elsif ($in{template} eq "login.html") {
		$in{template} = "main.html";
		}
	if ($force_login) {
		$in{template} = "login.html";
		undef $Template::Session;
		&showScreen();
		}
	&handleCustomFunction("after_forceLogin");
	}

# Get the list of available commands for main menu and drop-down
$CommandList = &getCommandList();

&handleCustomFunction("before_commands");

# COMMANDS
# -----------------------------------------------
if ($in{'command'} eq "login") {
	unless(&handleCustomFunction("before_login")) {
		#$Session->cleanupExpiredSessions();
		my ($result) = $User->login($in{password});
		if ($result == 1) {
			# User logged in
			$Session->{'username'} = $User->{'username'};
			$Session->{'name'} = $User->{'name'};
			&addUserMessage(&getMessage("USER_LOGGED_IN_SUCCESSFULLY",($User->{'name'} || $User->{'username'})));
			}
		elsif ($result == 2) {
			# Must change password
			$Session->{'username'} = $User->{'username'};
			$Session->{'name'} = $User->{'name'};
			&addUserMessage(&getMessage("USER_LOGGED_IN_SUCCESSFULLY",($User->{"name"} || $User->{"username"})));
			&addUserMessage(&getMessage("USER_MUST_CHANGE_PASSWORD"));
			$in{template} = "change_password.html";
			$Template::force_change = 1;
			}
		else {
			&addUserMessage($User->getErrorMessage());
			&showSameScreen();
			}
		&handleCustomFunction("after_login");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "change_password") {
	unless(&handleCustomFunction("before_change_password")) {
		if ($User->changePassword($in{'oldPassword'},$in{'newPassword'})) {
			&addUserMessage(&getMessage("USER_PASSWORD_CHANGE_SUCCESSFUL"));
			}
		else {
			&addUserMessage($User->getErrorMessage());
			&showSameScreen();
			}
		&handleCustomFunction("after_change_password");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "logout") {
	unless(&handleCustomFunction("before_logout")) {
		$Session->ExpireNow();
		$Session->cleanupExpiredSessions();
		undef $Session;
		undef $Template::Session;
		$in{template} = "login.html";
		$Template::CALENDAR_LINK = $AdminConfig->get("calendar_url")."?calendar=$calendar";
		&handleCustomFunction("after_logout");
		}
	}	
# -----------------------------------------------
elsif ($in{'command'} eq "add_event") {
	unless(&handleCustomFunction("before_add_event")) {
		&checkPermissions("","ADD_EVENT");
		my ($properties,$name,$error);
		my ($db) = new DBFile($events_db);
		my ($id);
		foreach (keys %in) {
			if ((/^FIELD_(.*)/) && ($in{$_} ne "")) {
				$properties->{$1} = $in{$_};
				}
			}
		$error=0;
		foreach (keys %{$db->{'properties'}}) {
			if ($db->{'properties'}->{$_}->{'required'} && ($properties->{$_} eq "")) {
				$name = $db->{'properties'}->{$_}->{'name'} || $_;
				&addUserMessage(&getMessage("FIELD_IS_REQUIRED",$name));
				$error=1;
				}
			}
		if ($error) {
			$Template::record = $properties;
			&ERROR(&getMessage("EVENT_NOT_ADDED_FIELDS_MISSING"));
			}
		unless ($Config->get("allow_html")) {
			foreach (keys %{$properties}) {
				$properties->{$_} = &HTML::filter($properties->{$_});
				}
			}
		$properties->{'author_id'} = $User->{'username'};
		$properties->{'author_name'} = $User->{'name'};
		$properties->{'time_added'} = time;
		if ($User->hasPermission("","APPROVE") || $User->hasPermission($calendar,"APPROVE_OWN_EVENTS")) {
			$properties->{'approved'} = 1;
			}
		else {
			&addUserMessage(&getMessage("EVENT_SAVED_PENDING_APPROVAL"));
			}
		if ($id = $db->addRecord($properties)) {
			&addUserMessage(&getMessage("EVENT_ADDED"));
			$properties->{'id'} = $id;
			$Template::event = $properties;
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		&handleCustomFunction("after_add_event");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "edit_event_form") {
	unless(&handleCustomFunction("before_edit_event_form")) {
		&checkPermissions("","EDIT_EVENTS","EDIT_OWN_EVENTS");
		$Template::template_value = "edit_delete_events.html";
		$Template::command_value = "edit_event";
		$Template::event_id = $in{'EVENT_id'};
		my ($db) = new DBFile($events_db);
		$Template::record = $db->getRecord( {'id'=>$in{'EVENT_id'}} );
		my ($sdb) = new DBFile($schedule_db);
		my ($schedule) = $sdb->getRecord( {'event_id'=>$in{'EVENT_id'}} );
		if ($schedule->{'recurrence_id'} || $schedule->{'recurrence_type'}) {
			$Template::_recurring = 1;
			}
		else {
			$Template::_recurring = 0;
			}
		&handleCustomFunction("after_edit_event_form");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "edit_event") {
	unless(&handleCustomFunction("before_edit_event")) {
		&checkPermissions("","EDIT_EVENTS","EDIT_OWN_EVENTS");
		my ($db) = new DBFile($events_db);
		my ($newproperties);
		$properties = $db->getRecord( {'id'=>$in{EVENT_id}} );
		foreach (keys %in) {
			if (/^FIELD_(.*)/) {
				$newproperties->{$1} = $in{$_};
				}
			}
		$error=0;
		foreach (keys %{$db->{'properties'}}) {
			if ($db->{'properties'}->{$_}->{'required'} && ($newproperties->{$_} eq "")) {
				$name = $db->{'properties'}->{$_}->{'name'} || $_;
				&addUserMessage(&getMessage("FIELD_IS_REQUIRED",$name));
				$error=1;
				}
			}
		if ($error) {
			$Template::record = $newproperties;
			$Template::template_value = "edit_delete_events.html";
			$Template::command_value = "edit_event";
			$Template::event_id = $in{'EVENT_id'};
			&ERROR(&getMessage("EVENT_NOT_UPDATED_FIELDS_MISSING"));
			}
		unless ($Config->get("allow_html")) {
			foreach (keys %{$newproperties}) {
				$newproperties->{$_} = &HTML::filter($newproperties->{$_});
				}
			}
		if ($db->updateRecords( { 'id'=>$in{EVENT_id} } , $newproperties )) {
			&addUserMessage(&getMessage("EVENT_MODIFIED"));
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		$Template::event = $db->getRecord( {'id'=>$in{EVENT_id}} );
		&handleCustomFunction("after_edit_event");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "delete_event") {
	unless(&handleCustomFunction("before_delete_event")) {
		&checkPermissions("","EDIT_EVENTS","EDIT_OWN_EVENTS");
		my ($db) = new DBFile($schedule_db);
		if ($db->deleteRecords( { 'event_id'=>$in{EVENT_id} } )) {
			&addUserMessage(&getMessage("EVENT_DELETED_FROM_SCHEDULE"));
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		$db = new DBFile($events_db);
		if ($db->deleteRecords( { 'id'=>$in{EVENT_id} } )) {
			&addUserMessage(&getMessage("EVENT_DELETED_FROM_DATABASE"));
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		&handleCustomFunction("after_delete_event");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "add_event_field_form") {
	unless(&handleCustomFunction("before_add_event_field_form")) {
		&checkPermissions("","CUSTOMIZE_EVENT_FIELDS");
		$Template::saveCommand = "add_event_field";
		$Template::saveTemplate = "customize_event_fields.html";
		$Template::cancelTemplate = "customize_event_fields.html";
		&handleCustomFunction("after_add_event_field_form");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "edit_event_field_form") {
	unless(&handleCustomFunction("before_edit_event_field_form")) {
		&checkPermissions("","CUSTOMIZE_EVENT_FIELDS");
		$Template::saveCommand = "edit_event_field";
		$Template::saveTemplate = "customize_event_fields.html";
		$Template::cancelTemplate = "customize_event_fields.html";
		my ($db) = new DBFile($events_db);
		$Template::record = $db->{'properties'}->{$in{'fieldname'}};
		$Template::record->{'id'} = $in{'fieldname'};
		&handleCustomFunction("after_edit_event_field_form");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "add_event_field") {
	unless(&handleCustomFunction("before_add_event_field")) {
		&checkPermissions("","CUSTOMIZE_EVENT_FIELDS");
		my ($properties);
		my ($id) = $in{'FIELDPROPERTY_id'};
		delete $in{'FIELDPROPERTY_id'};
		foreach (keys %in) {
			if ((/^FIELDPROPERTY_(.*)/) && ($in{$_} ne "")) {
				$properties->{$1} = $in{$_};
				}
			}
		my ($db) = new DBFile($events_db);
		if ($db->addField($id, $properties, "")) {
			&addUserMessage(&getMessage("FIELD_ADDED_TO_EVENTS_DATABASE",$properties->{'name'}));
			}
		else {
			$properties->{'id'} = $id;
			$Template::record = $properties;
			&ERROR($db->getErrorMessage());
			}
		&handleCustomFunction("after_add_event_field");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "edit_event_field") {
	unless(&handleCustomFunction("before_edit_event_field")) {
		&checkPermissions("","CUSTOMIZE_EVENT_FIELDS");
		my ($properties);
		my ($oldID) = $in{'oldFieldID'};
		my ($id) = $in{'FIELDPROPERTY_id'};
		delete $in{'FIELDPROPERTY_id'};
		foreach (keys %in) {
			if ((/^FIELDPROPERTY_(.*)/) && ($in{$_} ne "")) {
				$properties->{$1} = $in{$_};
				}
			}
		my ($db) = new DBFile($events_db);
		if ($oldID ne $id) {
			unless ($db->renameField($oldID,$id)) {
				$properties->{'id'} = $oldID;
				$Template::record = $properties;
				&ERROR($db->getErrorMessage());
				}
			}
		if ($db->editFieldProperties($id, $properties, "")) {
			&addUserMessage(&getMessage("FIELD_EDITED",$properties->{'name'}));
			}
		else {
			$properties->{'id'} = $id;
			$Template::record = $properties;
			&ERROR($db->getErrorMessage());
			}
		&handleCustomFunction("after_edit_event_field");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "delete_event_field") {
	unless(&handleCustomFunction("before_delete_event_field")) {
		&checkPermissions("","CUSTOMIZE_EVENT_FIELDS");
		my ($id) = $in{'fieldname'};
		my ($db) = new DBFile($events_db);
		if ($db->deleteField($id)) {
			&addUserMessage(&getMessage("FIELD_DELETED_FROM_EVENTS_DATABASE",$id));
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		&handleCustomFunction("after_delete_event_field");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "save_event_field_display_order") {
	unless(&handleCustomFunction("before_delete_event_field")) {
		&checkPermissions("","CUSTOMIZE_EVENT_FIELDS");
		$db = new DBFile($events_db);
		my ($i) = 1;
		foreach (split(",",$in{'fieldOrder'})) {
			$db->{'properties'}->{$_}->{'displayorder'} = $i;
			$i++;
			}
		$db->writeFieldProperties();
		&addUserMessage("FIELD_ORDER_SAVED");
		&handleCustomFunction("after_delete_event_field");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "add_user") {
	unless(&handleCustomFunction("before_add_user")) {
		&checkPermissions("_global","ADD_USER");
		my ($properties,$name,$error);
		my ($db) = new DBFile($users_db);
		foreach (keys %in) {
			if ((/^FIELD_(.*)/) && ($in{$_} ne "")) {
				$properties->{$1} = $in{$_};
				}
			}
		$error=0;
		foreach (keys %{$db->{'properties'}}) {
			if ($db->{'properties'}->{$_}->{'required'} && ($properties->{$_} eq "")) {
				$name = $db->{'properties'}->{$_}->{'name'} || $_;
				&addUserMessage(&getMessage("FIELD_IS_REQUIRED",$name));
				$error=1;
				}
			}
		if ($error) {
			$Template::record = $properties;
			&ERROR(&getMessage("USER_NOT_ADDED_FIELDS_MISSING"));
			}
		if ($properties->{'password'} ne "") {
			$properties->{'password'} = crypt($properties->{'password'}, "crypt");
			}
		if ($db->getRecord( { 'username'=>$properties->{'username'} })) {
			&ERROR("Error: Username [$properties->{username}] already exists!");
			}
		if ($db->addRecord($properties)) {
			&addUserMessage(&getMessage("USER_ADDED"));
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		&handleCustomFunction("after_add_user");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "add_user_field_form") {
	unless(&handleCustomFunction("before_add_user_field_form")) {
		&checkPermissions("_global","CUSTOMIZE_USER_DB");
		$Template::saveCommand = "add_user_field";
		$Template::saveTemplate = "customize_user_fields.html";
		$Template::cancelTemplate = "customize_user_fields.html";
		&handleCustomFunction("after_add_user_field_form");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "edit_user_field_form") {
	unless(&handleCustomFunction("before_edit_user_field_form")) {
		&checkPermissions("_global","CUSTOMIZE_USER_DB");
		$Template::saveCommand = "edit_user_field";
		$Template::saveTemplate = "customize_user_fields.html";
		$Template::cancelTemplate = "customize_user_fields.html";
		my ($db) = new DBFile($users_db);
		$Template::record = $db->{'properties'}->{$in{'fieldname'}};
		$Template::record->{'id'} = $in{'fieldname'};
		&handleCustomFunction("after_edit_user_field_form");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "add_user_field") {
	unless(&handleCustomFunction("before_add_user_field")) {
		&checkPermissions("_global","CUSTOMIZE_USER_DB");
		my ($properties);
		my ($id) = $in{'FIELDPROPERTY_id'};
		delete $in{'FIELDPROPERTY_id'};
		foreach (keys %in) {
			if ((/^FIELDPROPERTY_(.*)/) && ($in{$_} ne "")) {
				$properties->{$1} = $in{$_};
				}
			}
		my ($db) = new DBFile($users_db);
		if ($db->addField($id, $properties, "")) {
			&addUserMessage(&getMessage("FIELD_ADDED_TO_USER_DATABASE",$properties->{'name'}));
			}
		else {
			$properties->{'id'} = $id;
			$Template::record = $properties;
			&ERROR($db->getErrorMessage());
			}
		&handleCustomFunction("after_add_user_field");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "edit_user_field") {
	unless(&handleCustomFunction("before_edit_user_field")) {
		&checkPermissions("_global","CUSTOMIZE_USER_DB");
		my ($properties);
		my ($id) = $in{'FIELDPROPERTY_id'};
		delete $in{'FIELDPROPERTY_id'};
		foreach (keys %in) {
			if ((/^FIELDPROPERTY_(.*)/) && ($in{$_} ne "")) {
				$properties->{$1} = $in{$_};
				}
			}
		my ($db) = new DBFile($users_db);
		if ($db->editFieldProperties($id, $properties, "")) {
			&addUserMessage(&getMessage("FIELD_EDITED",$properties->{'name'}));
			}
		else {
			$properties->{'id'} = $id;
			$Template::record = $properties;
			&ERROR($db->getErrorMessage());
			}
		&handleCustomFunction("after_edit_user_field");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "delete_user_field") {
	unless(&handleCustomFunction("before_delete_user_field")) {
		&checkPermissions("_global","CUSTOMIZE_USER_DB");
		my ($id) = $in{'fieldname'};
		my ($db) = new DBFile($users_db);
		if ($db->deleteField($id)) {
			&addUserMessage(&getMessage("FIELD_DELETED_FROM_USER_DATABASE",$id));
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		&handleCustomFunction("after_delete_user_field");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "save_user_field_display_order") {
	unless(&handleCustomFunction("before_save_user_field_display_order")) {
		&checkPermissions("_global","CUSTOMIZE_USER_DB");
		$db = new DBFile($users_db);
		my ($i) = 1;
		foreach (split(",",$in{'fieldOrder'})) {
			$db->{'properties'}->{$_}->{'displayorder'} = $i;
			$i++;
			}
		$db->writeFieldProperties();
		&addUserMessage(&getMessage("FIELD_ORDER_SAVED"));
		&handleCustomFunction("after_save_user_field_display_order");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "delete_user") {
	unless(&handleCustomFunction("before_delete_user")) {
		&checkPermissions("_global","CUSTOMIZE_USER_DB");
		my ($username) = $in{'username'};
		my ($db) = new DBFile($users_db);
		if ($db->deleteRecords( {'username'=>$username} )) {
			&addUserMessage(&getMessage("USER_DELETED_FROM_DATABASE",$username));
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		&handleCustomFunction("after_delete_user");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "edit_user_form") {
	unless(&handleCustomFunction("before_edit_user_form")) {
		&checkPermissions("_global","EDIT_USERS");
		$Template::template_value = "edit_delete_users.html";
		$Template::command_value = "edit_user";
		my ($db) = new DBFile($users_db);
		$Template::record = $db->getRecord( {'username'=>$in{username}} );
		&handleCustomFunction("after_edit_user_form");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "edit_user") {
	unless(&handleCustomFunction("before_edit_user")) {
		&checkPermissions("_global","EDIT_USERS");
		my ($db) = new DBFile($users_db);
		my ($newproperties);
		$properties = $db->getRecord( {'username'=>$in{username}} );
		foreach (keys %in) {
			if (/^FIELD_(.*)/) {
				$newproperties->{$1} = $in{$_};
				}
			}
		if ($newproperties->{'password'} ne $properties->{'password'}) {
			if ($newproperties->{'password'} ne "") {
				$newproperties->{'password'} = crypt($newproperties->{'password'}, "crypt");
				}
			}
		if ($db->updateRecords( { 'username'=>$in{username} } , $newproperties )) {
			&addUserMessage(&getMessage("USER_MODIFIED"));
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		&handleCustomFunction("after_edit_user");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "schedule_event") {
	unless(&handleCustomFunction("before_schedule_event")) {
		my ($db) = new DBFile($schedule_db);
		my ($event_id) = $in{'EVENT_id'};
		my ($schedule);

		foreach (sort keys %in) {
			if (/^SCHEDULE_(.*)/) {
				$schedule->{$1} = $in{$_};
				}
			}
		$db->deleteRecords( {'event_id'=>$event_id} );
		if (&Event::scheduleEvent($db, $schedule, $event_id)) {
			&addUserMessage(&getMessage("SCHEDULE_SAVED"));
			}
		else {
			&addUserMessage(&getMessage("ERROR_WHILE_SAVING_SCHEDULE"));
			&addUserMessage(&Event::getErrorMessage());
			$Template::schedule = $schedule;
			&showSameScreen();
			}
		&handleCustomFunction("after_schedule_event");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "reschedule_event") {
	unless(&handleCustomFunction("before_reschedule_event")) {
		&checkPermissions("","EDIT_EVENTS","EDIT_OWN_EVENTS");
		$Template::event_id = $in{'EVENT_id'};
		&handleCustomFunction("after_reschedule_event");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "save_settings") {
	unless(&handleCustomFunction("before_save_settings")) {
		&checkPermissions("","CALENDAR_SETTINGS");
		my ($key);
		my (@daynames) = ($in{'day_name_0'},$in{'day_name_1'},$in{'day_name_2'},$in{'day_name_3'},$in{'day_name_4'},$in{'day_name_5'},$in{'day_name_6'});
		my (@dayabbreviations) = ($in{'day_abbreviation_0'},$in{'day_abbreviation_1'},$in{'day_abbreviation_2'},$in{'day_abbreviation_3'},$in{'day_abbreviation_4'},$in{'day_abbreviation_5'},$in{'day_abbreviation_6'});
		my (@monthnames) = ($in{'month_name_0'},$in{'month_name_1'},$in{'month_name_2'},$in{'month_name_3'},$in{'month_name_4'},$in{'month_name_5'},
								  $in{'month_name_6'},$in{'month_name_7'},$in{'month_name_8'},$in{'month_name_9'},$in{'month_name_10'},$in{'month_name_11'});
		my (@monthabbreviations) = ($in{'month_abbreviation_0'},$in{'month_abbreviation_1'},$in{'month_abbreviation_2'},$in{'month_abbreviation_3'},$in{'month_abbreviation_4'},$in{'month_abbreviation_5'},
											 $in{'month_abbreviation_6'},$in{'month_abbreviation_7'},$in{'month_abbreviation_8'},$in{'month_abbreviation_9'},$in{'month_abbreviation_10'},$in{'month_abbreviation_11'});
		$Config->set("day_names",\@daynames);
		$Config->set("day_abbreviations",\@dayabbreviations);
		$Config->set("month_names",\@monthnames);
		$Config->set("month_abbreviations",\@monthabbreviations);
		foreach $key (keys %in) {
			if ($key =~ /^CONFIG_(.*)/) {
				$Config->set($1,$in{$key});
				}
			}
		if ($Config->save()) {
			&addUserMessage(&getMessage("CONFIGURATION_SAVED"));
			}
		else {
			&addUserMessage(&getMessage("ERROR_WHILE_SAVING_CONFIGURATION"));
			&addUserMessage($Config->getErrorMessage());
			&showSameScreen();
			}
		&handleCustomFunction("after_save_settings");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "save_permissions") {
	unless(&handleCustomFunction("before_save_permissions")) {
		&checkPermissions("","PERMISSIONS");
		my ($key,$action,$type,$u,$c,);
		my ($username) = $in{'selected_user'};
		my ($calendar) = $in{'selected_calendar'};
		my ($db) = new DBFile($permissions_db);
		unless ($db->deleteRecords( {'username'=>$username, 'calendar'=>$calendar} )) { &ERROR(&getMessage("ERROR_UPDATING_PERMISSIONS")); }
		#unless ($db->deleteRecords( {'username'=>$username} )) { &ERROR(&getMessage("ERROR_UPDATING_PERMISSIONS")); }
		unless ($db->deleteRecords( {'username'=>'_all', 'calendar'=>$calendar} )) { &ERROR(&getMessage("ERROR_UPDATING_PERMISSIONS")); }
		unless ($db->deleteRecords( {'username'=>$username, 'calendar'=>'_all'} )) { &ERROR(&getMessage("ERROR_UPDATING_PERMISSIONS")); }
		unless ($db->deleteRecords( {'username'=>$username, 'calendar'=>'_global'} )) { &ERROR(&getMessage("ERROR_UPDATING_PERMISSIONS")); }
		foreach $key (keys %in) {
			next unless ($key =~ /^PERMISSIONS_([^_]*)_(.*)/);
			$type = $1;
			$action = $2;
			if ($type eq "GLOBAL") { $u=$username; $c="_global"; }
			elsif ($type eq "CALUSER") { $u=$username; $c=$calendar; }
			elsif ($type eq "CALALL") { $u="_all"; $c=$calendar; }
			elsif ($type eq "ALLUSER") { $u=$username; $c="_all"; }
			unless($db->addRecord( {'username'=>$u, 'calendar'=>$c, 'action'=>$action} )) { &ERROR(&getMessage("ERROR_UPDATING_PERMISSIONS")); }
			}
		$User->readPermissions();
		&addUserMessage(&getMessage("PERMISSIONS_SAVED"));
		&handleCustomFunction("after_save_permissions");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "edit_pending_event") {
	unless(&handleCustomFunction("before_edit_pending_event")) {
		&checkPermissions("","EDIT_EVENTS");
		$Template::template_value = "approve.html";
		$Template::command_value = "edit_event";
		$Template::event_id = $in{'EVENT_id'};
		my ($db) = new DBFile($events_db);
		$Template::record = $db->getRecord( {'id'=>$in{'EVENT_id'}} );
		&handleCustomFunction("after_edit_pending_event");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "approve_events") {
	unless(&handleCustomFunction("before_approve_events")) {
		&checkPermissions("","APPROVE");
		my ($db) = new DBFile($events_db);
		my ($id);
		foreach $key (keys %in) {
			next unless ($key =~ /^APPROVE_(\d+)/);
			$id = $1;
			if ($in{$key} eq "APPROVE") {
				$db->updateRecords( {'id'=>$id} , {'approved'=>1} );
				&addUserMessage($db->getErrorMessage());
				}
			elsif ($in{$key} eq "REJECT") {
				$db->deleteRecords( {'id'=>$id} );
				&addUserMessage($db->getErrorMessage());
				my ($schedule) = new DBFile($schedule_db);
				$schedule->deleteRecords( {'event_id'=>$id} );
				&addUserMessage($schedule->getErrorMessage());
				}
			}
		&addUserMessage(&getMessage("EVENT_APPROVALS_SAVED"));
		&handleCustomFunction("after_approve_events");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "save_admin_styles") {
	unless(&handleCustomFunction("before_save_admin_styles")) {
		&checkPermissions("_global","ADMIN_SETTINGS");
		foreach $key (keys %in) {
			if ($key =~ /^CONFIG_(.*)/) {
				$AdminConfig->set($1,$in{$key});
				}
			}
		if ($AdminConfig->save()) {
			&addUserMessage(&getMessage("CONFIGURATION_SAVED"));
			}
		else {
			&addUserMessage(&getMessage("ERROR_WHILE_SAVING_CONFIGURATION"));
			&addUserMessage($Config->getErrorMessage());
			&showSameScreen();
			}
		&handleCustomFunction("after_save_admin_styles");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "add_calendar") {
	unless(&handleCustomFunction("before_add_calendar")) {
		&checkPermissions("_global","MANAGE_CALENDARS");
		my ($properties,$name,$error);
		my ($db) = new DBFile($calendars_db);
		foreach (keys %in) {
			if ((/^FIELD_(.*)/) && ($in{$_} ne "")) {
				$properties->{$1} = $in{$_};
				}
			}
		$error=0;
		foreach (keys %{$db->{'properties'}}) {
			if ($db->{'properties'}->{$_}->{'required'} && ($properties->{$_} eq "")) {
				$name = $db->{'properties'}->{$_}->{'name'} || $_;
				&addUserMessage(&getMessage("FIELD_IS_REQUIRED",$name));
				$error=1;
				}
			}
		if ($error) {
			$Template::record = $properties;
			&ERROR(&getMessage("CALENDAR_NOT_ADDED_FIELDS_MISSING"));
			}
		if ($db->getRecord( { 'key'=>$properties->{'key'} })) {
			&ERROR(&getMessage("CALENDAR_ALREADY_EXISTS",$properties->{key}));
			}
		my ($dir) = $in{'copydir'};
		my ($give_privileges) = $in{'give_privileges'};
		$dir =~ s|[^\w_-]||g;
		my ($calendars_dir) = $BASE_DIR . "calendars/";
		my ($source_dir) = $calendars_dir . $dir . "/";
		$in{'FIELD_key'} =~ s|[^\w_-]||g;
		my ($dest_dir) = $calendars_dir . $in{'FIELD_key'} . "/";
		unless (-d $source_dir) {
			&ERROR(&getMessage("CALENDAR_COPY_DIR_DOESNT_EXIST",$source_dir));
			}
		if (-d $dest_dir) { 
			&ERROR(&getMessage("CALENDAR_DIRECTORY_ALREADY_EXISTS",$dest_dir));
			}
		unless (-w $calendars_dir) {
			&ERROR(&getMessage("CALENDAR_DIRECTORY_NOT_WRITABLE",$calendars_dir));
			}
		else {
			my ($mkdir) = $calendars_dir . $in{'FIELD_key'};
			unless (mkdir($mkdir,0777)) {
				&ERROR(&getMessage("CALENDAR_COULDNT_CREATE_DIRECTORY",$mkdir,$!));
				}
			}
		# Copy files from source to destination
		require File::Copy;
		opendir(SOURCE,$source_dir) || &ERROR(&getMessage("CALENDAR_COULDNT_OPEN_SOURCE_DIR",$source_dir,$!));
		while($f = readdir(SOURCE)) {
			next if ($f =~ /^\./);
			next if (-d $f);
			File::Copy::copy($source_dir.$f , $dest_dir.$f) || &ERROR(&getMessage("CALENDAR_COULDNT_COPY_FILE",$source_dir.$f,$!));
			chmod(0777,$dest_dir.$f) || &ERROR(&getMessage("CALENDAR_COULDNT_SET_FILE_PERMISSIONS",$source_dir.$f,$!));
			}
		closedir(SOURCE);
		&addUserMessage(&getMessage("CALENDAR_FILES_COPIED"));
		# Add it to the database
		if ($db->addRecord($properties)) {
			&addUserMessage(&getMessage("CALENDAR_ADDED_TO_DATABASE"));
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		# Set permissions, if applicable
		if ($give_privileges && ($give_privileges ne "Administrator")) {
			my ($db2) = new DBFile($permissions_db);
			if ($db2->addRecord( {'username'=>$give_privileges , 'calendar'=>$in{'FIELD_key'} , 'action'=>'_all' })) {
				&addUserMessage(&getMessage("CALENDAR_PERMISSIONS_GRANTED"));
				}
			else {
				&ERROR($db->getErrorMessage());
				}
			}
		&handleCustomFunction("after_add_calendar");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "delete_calendar") {
	unless(&handleCustomFunction("before_delete_calendar")) {
		&checkPermissions("_global","MANAGE_CALENDARS");
		my ($key) = $in{'calendar_id'};
		my ($db) = new DBFile($calendars_db);
		if ($db->deleteRecords( {'key'=>$key} )) {
			&addUserMessage(&getMessage("CALENDAR_DELETED_FROM_DATABASE",$key));
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		my ($dir) = $in{'calendar_id'};
		$dir =~ s|[^\w_-]||g;
		# Remove all permissions
		my ($permissionsdb) = new DBFile($permissions_db);
		if ($permissionsdb->deleteRecords( {'calendar'=>$dir } )) {
			&addUserMessage(&getMessage("CALENDAR_PERMISSIONS_REMOVED"));
			}
		else {
			&ERROR($db->getErrorMessage());
			}
		# Delete files
		my ($source_dir) = $BASE_DIR . "calendars/" . $dir . "/";
		opendir(SOURCE,$source_dir) || &ERROR(&getMessage("CALENDAR_COULDNT_OPEN_DIR",$source_dir,$!));
		while($f = readdir(SOURCE)) {
			next if ($f =~ /^\./);
			unlink($source_dir.$f) || &ERROR(&getMessage("CALENDAR_COULDNT_UNLINK_FILE",$source_dir.$f,$!));
			}
		closedir(SOURCE);
		rmdir($source_dir) || &ERROR(&getMessage("CALENDAR_COULDNT_REMOVE_DIR",$source_dir,$!));
		&addUserMessage(&getMessage("CALENDAR_FILES_DELETED"));
		&handleCustomFunction("after_delete_calendar");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "edit_calendar_form") {
	unless(&handleCustomFunction("before_edit_calendar_form")) {
		&checkPermissions("_global","MANAGE_CALENDARS");
		$Template::template_value = "edit_delete_calendars.html";
		$Template::command_value = "edit_calendar";
		my ($db) = new DBFile($calendars_db);
		$Template::record = $db->getRecord( {'id'=>$in{'calendar_id'}} );
		&handleCustomFunction("after_edit_calendar_form");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "edit_calendar") {
	unless(&handleCustomFunction("before_edit_calendar")) {
		&checkPermissions("_global","MANAGE_CALENDARS");
		my ($db) = new DBFile($calendars_db);
		my ($newproperties);
		# Change calendar DB
		$properties = $db->getRecord( {'id'=>$in{calendar_id}} );
		foreach (keys %in) {
			if (/^FIELD_(.*)/) {
				$newproperties->{$1} = $in{$_};
				}
			}
		$error=0;
		if ($newproperties->{'key'}) {
			$newproperties->{'key'} =~ s|[^\w_-]||g;
			}
		foreach (keys %{$db->{'properties'}}) {
			if ($db->{'properties'}->{$_}->{'required'} && ($newproperties->{$_} eq "")) {
				$name = $db->{'properties'}->{$_}->{'name'} || $_;
				&addUserMessage(&getMessage("FIELD_IS_REQUIRED",$name));
				$error=1;
				}
			}
		if ($error) {
			$newproperties->{'id'} = $in{'calendar_id'};
			$newproperties->{'key'} = $in{'calendar_key'};
			$Template::record = $newproperties;
			&ERROR(&getMessage("CALENDAR_NOT_ADDED_FIELDS_MISSING"));
			}
		unless ($db->updateRecords( { 'id'=>$in{'calendar_id'} } , $newproperties )) {
			$newproperties->{'id'} = $in{'calendar_id'};
			$newproperties->{'key'} = $in{'calendar_key'};
			$Template::record = $newproperties;
			&ERROR($db->getErrorMessage());
			}
		# Modify permissions with new key
		if ($in{'calendar_key'} ne $in{'FIELD_key'}) {
			my ($permissionsdb) = new DBFile($permissions_db);
			unless ($permissionsdb->updateRecords( { 'key'=>$in{'calendar_key'} } , { 'key'=>$in{'FIELD_key'} } )) {
				$newproperties->{'id'} = $in{'calendar_id'};
				$newproperties->{'key'} = $in{'calendar_key'};
				$Template::record = $newproperties;
				&ERROR($db->getErrorMessage());
				}
			}
		# Modify directory name
		if (($in{'calendar_key'} ne $in{'FIELD_key'}) && ($newproperties->{'key'} ne "")) {
			my ($dir) = $in{'calendar_key'};
			$dir =~ s|[^\w_-]||g;
			unless (rename($BASE_DIR."calendars/".$dir , $BASE_DIR."calendars/".$newproperties->{'key'}) ) {
				$newproperties->{'id'} = $in{'calendar_id'};
				$newproperties->{'key'} = $in{'calendar_key'};
				$Template::record = $newproperties;
				&ERROR(&getMessage("CALENDAR_COULDNT_RENAME_DIR",$source_dir,$!));
				}
			}

		&addUserMessage(&getMessage("CALENDAR_MODIFIED"));
		&handleCustomFunction("after_edit_calendar");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "import_events") {
	unless(&handleCustomFunction("before_import_events")) {
		&checkPermissions("","IMPORT_EVENTS");
		my ($header,@fields,$field,$events,@events,$event,$delimiter,$mapping);
		my ($db) = new DBFile($events_db);
		my ($scheduledb) = new DBFile($schedule_db);

		$header = $in{'header'};
		$events = $in{'events'};
		$delimiter = "\\".$in{'delimiter'};

		# Process the header row
		$header =~ s|^#||;
		chomp($header);
		@fields = split($delimiter,$header);

		# Get the field mappings
		foreach (keys %in) {
			if ((/^FIELD_(.*)/) && ($in{$_} ne "")) {
				$mapping->{$in{$_}} = $1;
				}
			}

		# Get the individual events
		@events = split(/[\r]\n/,$events);

		foreach $event (@events) {
			chomp($event);
			next unless ($event =~ /$delimiter/);
			my ($properties);
			# Split this event string and map fields
			my (@eventfields) = split($delimiter,$event);
			foreach $i (0 .. $#eventfields) {
				my ($newname) = $mapping->{$fields[$i]};
				if ($newname) {
					$properties->{$newname} = $eventfields[$i];
					}
				}
			unless ($Config->get("allow_html")) {
				foreach (keys %{$properties}) {
					$properties->{$_} = &HTML::filter($properties->{$_});
					}
				}
			$properties->{'author_id'} = $User->{'username'};
			$properties->{'author_name'} = $User->{'name'};
			$properties->{'time_added'} = time;
			$properties->{'approved'} = 1;
			# Add the event
			if ($id = $db->addRecord($properties)) {
				my ($schedule);
				$schedule->{'static_start_date'} = $properties->{'schedule_datestamp'};
				if ($properties->{'schedule_starttime'}) { 
					($schedule->{'start_time_hh'},$schedule->{'start_time_mm'}) = ($properties->{'schedule_starttime'}=~/(\d\d?):(\d\d?)/);
					}
				else {
					$schedule->{'all_day'} = 1;
					}
				if ($properties->{'schedule_endtime'}) { 
					($schedule->{'end_time_hh'},$schedule->{'end_time_mm'}) = ($properties->{'schedule_endtime'}=~/(\d\d?):(\d\d?)/);
					}
				elsif ($properties->{'schedule_starttime'}) {
					($schedule->{'end_time_hh'},$schedule->{'end_time_mm'}) = ($properties->{'schedule_starttime'}=~/(\d\d?):(\d\d?)/);
					}
				if ($schedule->{'static_start_date'} =~ /^0000/) {
					# Yearly event
					$schedule->{'type'} = "recurring";
					$schedule->{'recurring_type'} = "yearly";
					$schedule->{'recurring_yearly_type'} = "absolute";
					($schedule->{'recurring_yearly_every_month'},$schedule->{'recurring_yearly_date'}) = ($properties->{'schedule_datestamp'} =~ /(\d\d)(\d\d)$/);
					}
				else {
					# One-time event
					$schedule->{'type'} = "static";
					}
				unless (&Event::scheduleEvent($scheduledb, $schedule, $id)) {
					&addUserMessage(&getMessage("ERROR_WHILE_SAVING_SCHEDULE"));
					&addUserMessage(&Event::getErrorMessage());
					}
				}
			else {
				&ERROR($db->getErrorMessage());
				}
			}
		&addUserMessage(&getMessage("IMPORT_SUCCESSFULL"));
		&handleCustomFunction("after_import_events");
		}
	}
# -----------------------------------------------
elsif ($in{'command'} eq "save_template_preferences") {
	unless(&handleCustomFunction("before_save_template_preferences")) {
		&checkPermissions("","TEMPLATE_PREFERENCES");
		my ($key,$key2);
		foreach $key (keys %in) {
			if ($key =~ /^FIELD_(.*)/) {
				$key2 = "template_preference_".$Config->get("template_dir")."_".$1;
				$Config->set($key2,$in{$key});
				}
			}
		if ($Config->save()) {
			&addUserMessage(&getMessage("CONFIGURATION_SAVED"));
			}
		else {
			&addUserMessage(&getMessage("ERROR_WHILE_SAVING_CONFIGURATION"));
			&addUserMessage($Config->getErrorMessage());
			&showSameScreen();
			}
		&handleCustomFunction("after_save_template_preferences");
		}
	}

# As a last resort, check for a custom-defined plugin function to handle this
# ---------------------------------------------------------------------------
else {
	&handleCustomFunction("command_".$in{'command'});
	}


# Show the screen already!
# ------------------------
&showScreen();

