#!/usr/bin/perl
use lib '/home/martin/ethereal/mgmt';

################################################################################
# Created       : Martin Foster
# Modified      : 28-Aug-2005 
################################################################################
#
# Mail - Script part of Ethereal Realms designed to compose, retreive, view
#        and manage mail
# Copyright (C) 2000-2006  Martin Foster
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# Author of this script can be contacted at the following:
#       E-Mail  : martin@ethereal-realms.org
#       Address : 29-26503 TWP RD 511
#                 Spruce Grove, Alberta
#                 T7Y 1G4
#
#################################################################################

use CGI;							# Common gateway interface
use CGI::Carp qw(fatalsToBrowser);				# CGI Error logs
use strict;							# Strict variable enforcement

use Ethereal::Database;						# Database handler
use Ethereal::Login;						# Login functionality
use Ethereal::Mail;						# Mail handler
use Ethereal::Param;						# Parameter control
use Ethereal::Template;						# Template handling

#################################################################################
# Gobal override
#################################################################################
$CGI::POST_MAX=1024 * 50;					# Maximum posts
$CGI::DISABLE_UPLOADS = 1;					# Disable uploads

################################################################################
# Data Members
################################################################################
my $cgi;							# Common gateway interface handle
my $database;							# Database handle
my $login;							# Login handle
my $param;							# Parameter handle
my $tmpl;							# Template handler

my %mail;							# Mail hash


################################################################################
# Program Area
################################################################################

	# Initial handles
	$cgi      = new CGI;
	$database = new Ethereal::Database();

	# Connect and fetch
	$database->Connect($cgi);

	# Parameter handling
	$param = new Ethereal::Param($database, $cgi);
	$param->GetParam();

	# Mail hash
	$database->GetHashMail(\%mail);

	# Template instance
	$tmpl = new Ethereal::Template(\%mail);


	# Login handle
	$login = new Ethereal::Login($database, $cgi, $param);

	# Authenticate user
	if ($login->GetVerificationNormal())
	{
		# Document header
		print $database->DocumentGetHeader(), "\n";

		# Decisions
		# Remove mail
		if (defined($param->{$mail{'TxtMailDelete'}}))
		{ MailPurge($database, $cgi, $param, $tmpl, \%mail); }

		# Sender
		elsif (defined($param->{'SEND'}))
		{ MailSender($database, $cgi, $param, $tmpl, \%mail); }
		
		# Viewer
		elsif (defined($param->{'MID'}))
		{ MailViewer($database, $cgi, $param, $tmpl, \%mail); }
		
		# Composer
		elsif (defined($param->{'WRITE'}))
		{ MailComposer($database, $cgi, $param, $tmpl, \%mail); }

		# Mail listing
		else
		{ MailList($database, $cgi, $param, $tmpl, \%mail); }


		# Document footer
		print $database->DocumentGetFooter(), "\n";
	}

#################################################################################
# Sub-Routines
################################################################################

#####################
# MailComposer
#
# Allows for the composition of mail to be sent out to the designated person.
# Since the list of puppets can get long, this will requires a textfield.

sub MailComposer
{
	#####################
	# Data members

	my $database = shift;					# Database Handle
	my $cgi      = shift;					# Common gateway interface
	my $param    = shift;					# Parameter list
	my $tmpl     = shift;					# Template management
	my $mail     = shift;					# Mail hash

	my $body;						# Body of message
	my $from;						# Origin of message
	my $rcpt;						# Intended audience
	my $subj;						# Subject of message
	my $time;						# Time of posting

	my $inline;						# Inline parameter
	my $url;						# Self reference

	my $wchars;						# Character widget
	my $wmrcpt;						# Recipient textbox
	my $wmsubj;						# Subject box
	my $wmbody;						# Message body
	my $wmsbmt;						# Submit button
	my $wmrset;						# Reset button
	my $lback;						# Back button

	my @puppets;						# List of puppets


	#####################
	# Program area

	# Retreive puppet list
	$database->GetListPuppetYours(\@puppets, $param->{'USER'});

	# Determine values
	# Reply
	if (defined($param->{'REPLY'}))
	{
		# Retreive information
		($_,
		 $from, 
		 $rcpt, 
		 $subj, 
		 $time, 
		 $body) = $database->DataGetPuppeteerMail($param->{'REPLY'});

		# Inverse values
		$_ = $rcpt;
		$rcpt = $from;
		$from = $_;

		# Message message row
		$body =~ s/^(.+)/$rcpt Wrote on $time:\n\n$1\n---\n\n/s;

		# Subject line
		unless ($subj =~ /\(RE\)/)
		{
			# Replace subject line
			$subj =~ s/^(.+)/(RE) $subj/s;
		}
	}

	# Normal message
	else
	{
		# Determine values
		$from = (defined($param->{'MFROM'})) ? $param->{'MFROM'} : $puppets[0];
		$rcpt = (defined($param->{'MRCPT'})) ? $mail->{'TxtMailInvalid'} : '';
		$subj = (defined($param->{'MSUBJ'})) ? $param->{'MSUBJ'} : '';
		$body = (defined($param->{'MBODY'})) ? $param->{'MBODY'} : '';
	}


	# Generate back link
	$url    = $cgi->url(-absolute=>1);
	$inline = $param->EmbedInline(USER=>$param->{'USER'}, CRYPT=>$param->{'CRYPT'});


	# Widgets
	# Popup menu
	$wchars = $cgi->popup_menu('MFROM', \@puppets, $from);

	# Text fields
	$wmrcpt = $cgi->textfield('MRCPT', $rcpt, 25, 30);
	$wmsubj = $cgi->textfield('MSUBJ', $subj, 25, 250);

	# Text area
	$wmbody = $cgi->textarea(
		-name    => 'MBODY',
		-rows    => 10,
		-columns => 60,
		-wrap    => 'SOFT',
		-default => $body);

	# Buttons
	$wmsbmt = $cgi->submit($mail->{'TxtMailSend'});
	$wmrset = $cgi->reset($mail->{'TxtMailReset'});

	# Links
	$lback    = $url . $inline;



	# Display area
	# Start of form, table
	print $cgi->start_form();
	print $param->EmbedNormal($param->Flat(), SEND=>'True'), "\n";

	# Show template
	$tmpl->Show('TmplCompose',
		WCHARS => $wchars,
		WMRCPT => $wmrcpt,
		WMSUBJ => $wmsubj,
		WMBODY => $wmbody,
		WMSBMT => $wmsbmt,
		WMRSET => $wmrset,
		LBACK  => $lback
	 );

	# End of form
	print $cgi->end_form(), "\n";
}


#####################
# MailList
#
# Shows a listing of all currently received emails, giving an option to delete, view, reply 
# to them in some matter or the other.

sub MailList
{
	#####################
	# Data members

	my $database = shift;					# Database Handle
	my $cgi      = shift;					# Common gateway interface
	my $param    = shift;					# Parameter list
	my $tmpl     = shift;					# Template viewer
	my $mail     = shift;					# Mail hash
	my $action   = shift;					# Action tag

	my $res;						# Results list
	my $statement;						# Query statement

	my $listing;						# Listing of specific messages
	my $internal;						# Listing of internal mail
	my $purge;						# Removing of email
	
	my $color;						# Selected color
	my $unread;						# Unread tag
	my $subject;						# Subject line

	my $icount   = 0;					# Arbitrary counter
	my $mcount   = 0;					# Arbitrary counter

	my $url      = $cgi->url(-absolute=>1);			# Current location

	my $ibio;						# Biographical link
	my $inline;						# Inline parameter list
	my $icomp;						# Composition value
	my $irefresh;						# Refresh value


	#####################
	# Program area

	# Data gathering
	# Prepare and execute
	$database->Pull(\$statement, "SELECT
		 MailIDNumber AS \"MailIDNumber\",
		 MailFrom     AS \"MailFrom\",
		 MailSubject  AS \"MailSubject\",
		 MailRead     AS \"MailRead\",
		 getDate(MailTimestamp) AS \"MailTimestamp\"
		FROM Mail
		WHERE PuppeteerLogin=?
		ORDER BY MailFrom, MailTimestamp",

	 $param->{'USER'}
	);


	# Retreive and display
	if ($res = $statement->fetchrow_hashref())
	{
		# Initialize
		$listing  = '';
		$internal = '';
	
		do
		{
			# Determine values
			$unread  = (defined($res->{'MailRead'}))       ? $mail->{'TagMailRead'} : $mail->{'TagMailUnread'};
			$subject = (length($res->{'MailSubject'}) > 1) ? $res->{'MailSubject'}  : $mail->{'TxtSubject'};

			# Generate inline
			$inline = $param->EmbedInline(
				USER  => $param->{'USER'},
				CRYPT => $param->{'CRYPT'},
				MID   => $res->{'MailIDNumber'}
			 );


			# Purging widget
			$purge = $cgi->checkbox(-name=>"PURGE_$res->{MailIDNumber}", -label=>'');

			# Keep or show		 
			# Display information
			unless (defined($param->{"PURGE_$res->{MailIDNumber}"}))
			{
				# Normal mail
				if (defined($res->{'MailFrom'}))
				{
					# Increment
					$mcount++;

					# Determine values
					$color   = (($mcount % 2) != 0) ? $mail->{'SetSecColor'} : $mail->{'SetPriColor'};

					# Biographical link
					$ibio = $param->Crypt(
						BCHAR => $res->{'MailFrom'},
						BPOOL => 'system'
					 );


					# Append
					# Use template
					$listing = $listing . $tmpl->Pass('TmplListing',
						MCOLOR => $color,
						MMREAD => $unread,
						MMFROM => $res->{'MailFrom'},
						MMSUBJ => $subject,
						MMTIME => $res->{'MailTimestamp'},
						LCHBIO => $mail->{'LnkBio'} . $ibio,
						LMLINK => $url . $inline,
						WDELE  => $purge
					 );
				}

				# Internal messaging
				else
				{
					# Increment
					$icount++;

					# Determine values
					$color   = (($icount % 2) != 0) ? $mail->{'SetSecColor'} : $mail->{'SetPriColor'};

					# Append
					# Use template
					$internal = $internal . $tmpl->Pass('TmplInternal',
						MCOLOR => $color,
						MMREAD => $unread,
						MMSUBJ => $subject,
						MMTIME => $res->{'MailTimestamp'},
						LMLINK => $url . $inline,
						WDELE  => $purge
					 );
				}
			}

			# Delete
			else
			{
				# Delete and ask questions delete
				$database->Quick("DELETE FROM Mail
					WHERE MailIDNumber=?
					  AND PuppeteerLogin=?",

				 $res->{'MailIDNumber'},
				 $param->{'USER'}
				);
			}

		# All good things must come to an end
		} while ($res = $statement->fetchrow_hashref());

		# End execution
		$statement->finish();
	}

	# Be nice to user
	$listing  = $mail->{'TagMessEmpty'} if ($mcount == 0);
	$internal = $mail->{'TagIntEmpty'}  if ($icount == 0);
	

	# Determine composer values
	$icomp = $param->EmbedInline(
		USER  => $param->{'USER'},
		CRYPT => $param->{'CRYPT'},
		WRITE => 'True'
	 );

	# Refresh value
	$irefresh = $param->EmbedInline(
		USER  => $param->{'USER'},
		CRYPT => $param->{'CRYPT'}
	 );

	# Action check
	$action = (defined($action)) ? $mail->{'TagMailSent'} : '';


	# Form handling
	print $cgi->start_form();
	print $param->EmbedNormal(USER=>$param->{'USER'}, CRYPT=>$param->{'CRYPT'});

	# Display master template
	$tmpl->Show('TmplSummary',
		LSTMAIL => $listing,
		LSTINT  => $internal,
		MMSENT  => $action,
		MMTOTAL => $mcount,
		MITOTAL => $icount,
		LMCOMP  => $url . $icomp,
		LRLOAD  => $url . $irefresh,
		WDELE   => $cgi->submit($mail->{'TxtMailDelete'})
	 );

	# End form
	print $cgi->end_form(), "\n";
}


#####################
# Mail Purge
#
# Allows for the purging of vile messages from the list of known messages.   Simple and easy
# to use.

sub MailPurge
{
	#####################
	# Data members

	my $database = shift;					# Database Handle
	my $cgi      = shift;					# Common gateway interface
	my $param    = shift;					# Parameter list
	my $tmpl     = shift;					# Template listing
	my $mail     = shift;					# Mail hash

	my $id;							# Identification number;


	#####################
	# Program area

	# Retreive id
	$id = $param->{'OID'};

	# Parameter handling
	$param->Cleanup('OID');

	
	# Remove entry
	$database->Quick("DELETE FROM Mail 
		WHERE MailIDNumber=?
		  AND PuppeteerLogin=?",

	 $id,
	 $param->{'USER'});

	
	# Call listing
	MailList($database, $cgi, $param, $tmpl, $mail);
}



#####################
# MailSender
#
# Allows for composed message to be sent out to the designated person.

sub MailSender
{
	#####################
	# Data members

	my $database = shift;					# Database Handle
	my $cgi      = shift;					# Common gateway interface
	my $param    = shift;					# Parameter list
	my $tmpl     = shift;					# Template
	my $mail     = shift;					# Mail hash

	my $send;						# Mail handler

	my $from;						# Origin of message
	my $rcpt;						# Intended audience
	my $subj;						# Subject of message
	my $body;						# Body of message

	my $id;							# ID Number of message
	my $notice;						# Notice message

	my $email;						# Email address
	my $ignored;						# Ignored user
	my $mailer;						# Mailer settings
	my $name;						# Name of target
	my $target;						# Display of drop down

	my %system;						# Systems hash


	#####################
	# Program area

	# Data retreival
	$from = $param->{'MFROM'};	
	$rcpt = $param->{'MRCPT'};
	$subj = $param->{'MSUBJ'};
	$body = $param->{'MBODY'};

	# Determine puppeteer
	($target)  = $database->DataGetPuppeteerLogin($rcpt);
	($ignored) = $database->DataGetIgnored($target, $rcpt, $param->{'USER'});


	# Determine action
	# Processing
	if ((defined($target))
	 && (!defined($ignored)))
	{
		# Retreive full name
		($name)           = $database->DataGetPuppeteerName($target);
		($email, $mailer) = $database->DataGetPuppeteerEmail($target);

		# Pull ID
		($id)     = $database->DataGetInsert('seqMail');

		# Insert into database
		$database->Write("INSERT INTO Mail
			(MailIDNumber,
			 PuppeteerLogin,
			 MailFrom,
			 MailRcpt,
			 MailSubject,
			 MailContents)
			VALUES(?,?,?,?,?,?)", 

		 $id,
		 $target,
		 $from,
		 $rcpt,
		 $subj,
		 $body);


	 	# Notification email
	 	if ($mailer eq 'ext')
		{
			# Final preperations
			# Retreive values
			($notice) = $database->DocumentGetMailNotice();
					
			# Build link
			my $url    = $cgi->url();
			my $inline = $param->Crypt(
				MID   => $id,
				MRCPT => $rcpt,
				MFROM => $from,
				MSUBJ => $subj
			 );


			# Compose and send email
			# Link to hash
			$database->GetHashSystem(\%system);

			# Message information
			if (defined($notice))
			{
				# Send mail
				# Initiate instance
				$send = tie(*MAIL, 'Ethereal::Mail', $database);

				# Initial setup
				$send->SetSubject("You have mail from: $from");
				$send->SetSearch(
					AUTHSTRING  => "$url$inline",
					FULLNAME    => $name,
					ORIGIN      => $from,
					RETURNEMAIL => $system{'SetInfoContactAddress'},
					SERVERNAME  => $system{'SetInfoServer'},
					SUBJECT     => $subj
				 );

				# Recipients
				$send->AddTo("$name <$email>");

				# Message
				print MAIL $notice;

				# Close and Send
				close(MAIL);
			}
		}

		# Show listing
		MailList($database, $cgi, $param, $tmpl, $mail, 'SENT');
	}

	# Imporper puppet name
	else
	{
		# Recall composer
		MailComposer($database, $cgi, $param, $tmpl, $mail);
	}
}


#####################
# MailViewer
#
# Allows for the viewing of mail to be sent out to the designated person. This
# will allow the puppeteer to reply if necessary as to make life simpler.

sub MailViewer
{
	#####################
	# Data members

	my $database = shift;					# Database Handle
	my $cgi      = shift;					# Common gateway interface
	my $param    = shift;					# Parameter list
	my $tmpl     = shift;					# Template instance
	my $mail     = shift;					# Mail hash

	my $body;						# Body of message
	my $from;						# Origin of message
	my $rcpt;						# Intended audience
	my $subj;						# Subject of message
	my $time;						# Time of posting
	my $user;						# Intended target

	my $inline;						# Inline parameter
	my $url;						# Self reference

	my $id;							# Identification number;


	#####################
	# Program area

	# Identification number
	$id = $param->{'MID'};
	$param->Cleanup('MID');

	# Assign OID
	$param->{'OID'} = $id;

	# Retreive information
	($user,
	 $from, 
	 $rcpt, 
	 $subj, 
	 $time, 
	 $body) = $database->DataGetPuppeteerMail($id);

	# Message message row
	$body =~ s/\n/<BR>\n/gm;


	# Only complete if intended target
	if ($user =~ /^$param->{'USER'}/i)
	{
		# Generate back
		$url    = $cgi->url(-absolute=>1);
		$inline = $param->EmbedInline(
			USER  => $param->{'USER'},
			CRYPT => $param->{'CRYPT'}
		 );

		# Display area
		# Start of form
		print $cgi->start_form();
		print $param->EmbedNormal($param->Flat(),
			REPLY => $id,
			WRITE => 'True'), "\n";

		# Template select
		# Normal message
		if (defined($from))
		{		
			# Message display template
			$tmpl->Show('TmplViewer',
				MMFROM => $from,
				MMRCPT => $rcpt,
				MMSUBJ => $subj,
				MMBODY => $body,
				MMTIME => $time,
				WMREPL => $cgi->submit($mail->{'TxtMailReply'}),
				WMDELE => $cgi->submit($mail->{'TxtMailDelete'}),
				LBACK  => $url . $inline
			 );
		}

		# Internal messaging lack certain fields
		else
		{
			# Internal display template
			$tmpl->Show('TmplViewerInt',
				MMSUBJ => $subj,
				MMBODY => $body,
				MMTIME => $time,
				WMDELE => $cgi->submit($mail->{'TxtMailDelete'}),
				LBACK  => $url . $inline
			 );
		}

		# Form bottom
		print $cgi->end_form(), "\n";


		# Update information to mark read
		$database->Quick("UPDATE Mail
			SET MailRead=LOCALTIMESTAMP
			WHERE MailIDNumber=?",

		 $id
		);
	}

	# Invalid component
	else
	{
		# Call listing
		MailList($database, $cgi, $param, $tmpl, $mail);
	}
}
