#!/usr/bin/perl -w
# cPanel cPsupport email filter 
# (C) 2004 cPanel Inc.
#
# $Id: support 115 2005-01-03 22:23:31Z nirosys $

BEGIN { require("../config.cgi"); }

use strict;
use warnings;
use cpSupport;
use cpSupport::User;
use cpSupport::Config;
use cpSupport::Ticket;
use cpSupport::TicketType;
use cpSupport::Transaction;

use HTML::Template;

# {{{ Variables
my $inHeader = 1;
my $curHeader = "";
my $content = "";
my %HEADERS = ();
my $origHeaders = "";
my @BODY = ();
my $numLines = 0;
my $specClients = ();
# }}}

# {{{ Gather e-mail header into %HEADERS #############
while (<STDIN>) {
	$numLines++;
	if ($numLines > 35000) { last; }
	if ($inHeader && /^([-\w]+):\s+(.*)$/) {
		my $head = $1; my $val  = $2;
		if (lc($head) eq "to" && (defined($HEADERS{'to'}) || lc($curHeader) eq "to") ) { next; }
		if ($content ne "" && $curHeader ne "") {
			$HEADERS{$curHeader} = $content;
			$content = "";
		}
		$content = $val;
		$curHeader = lc($head);
	}
	elsif (/^$/ && $inHeader) {
		if ($content ne "" && $curHeader ne "") {
			$HEADERS{$curHeader} = $content;
			$content = "";
		}
		$inHeader = 0;
	}
	else {
		$content .= $_;
	}
	if ($inHeader) { $origHeaders .= $_; }
}
# }}}
if (!$inHeader) { @BODY = split(/\n/,$content); }

my $toAddr = cpSupport::addressFromHeader($HEADERS{'to'});
my $fromAddr = cpSupport::addressFromHeader($HEADERS{'from'});
my $domain = cpSupport::domainFromEmail($toAddr);

if (!cpSupport::loadConfig($domain)) {
   cpSupport::writeError(__FILE__.": Unable to load domain information: bailing.");
   exit;
}

my $dbh = cpSupport::connectToDb();

if (!defined($dbh)) {
   cpSupport::logExit(__FILE__.": invalid dbh.");
}

cpSupport::writeLog(__FILE__.": '${fromAddr}' => '${toAddr}'");

my $user = cpSupport::User->new();

my $conf = cpSupport::Config->new($dbh);
my %types = cpSupport::getTypes;
my ($fromUser) = $fromAddr =~ m/(.*)\@.*/;

# Check to see if we're recieving mail from 'ourself'
if ($domain eq $conf->get("domain")) {
   if (grep(/^\Q${fromUser}\E$/,keys %types)) {
      cpSupport::logExit(__FILE__.": from address is one of our support addresses: rejecting.");
   }
}

if (lc($fromUser) eq "mailer-daemon") {
   cpSupport::logExit(__FILE__.": recieved mail from mailer-daemon\@: rejecting.");
}

if ($conf->get("emailsupport") eq 'n') {
   cpSupport::logExit(__FILE__.": e-mail support not configured for this domain.");
}

if (cpSupport::isBanned($fromAddr,$dbh)) {
   my $select = $dbh->prepare("SELECT * FROM ${cpSupport::DB_PREFIX}_emails WHERE name='bannedUser'");
   $select->execute;

   if ($select->rows == 1) { 
      my $rowRef = $select->fetchrow_hashref();
      my $content = $$rowRef{content};
      my $template = HTML::Template->new( scalarref => \$content,
                                          die_on_bad_params => 0 );
      open(SENDMAIL,"|/usr/sbin/sendmail -t");
      print SENDMAIL "To: ${fromAddr}\n";
      print SENDMAIL "From: ${toAddr}\n";
      print SENDMAIL "Subject: re: ".$HEADERS{subject}."\n";
      print SENDMAIL $template->output;
      close(SENDMAIL);
      cpSupport::logExit(__FILE__.": banned user <${fromAddr}>: rejected e-mail.");
   }
   else {
      cpSupport::logExit(__FILE__.": unable to find 'bannedUser' email template.");
   }
}

if ($user->load_email_from_dbh($fromAddr,$dbh) != 1) {
   my $select = $dbh->prepare("SELECT * FROM ${cpSupport::DB_PREFIX}_emails WHERE name='notRegistered'");
   $select->execute;

   if ($select->rows != 1) {
      cpSupport::logExit(__FILE__.": unable to find 'notRegistered' email template.");
   }
   
   my $rowRef = $select->fetchrow_hashref();

   my $content = $$rowRef{content};

   my $template = HTML::Template->new( scalarref => \$content,
                                       die_on_bad_params => 0 );

   $template->param( url => $conf->get('baseurl') );

   open(SENDMAIL,"|/usr/sbin/sendmail -t");
   print SENDMAIL "To: ${fromAddr}\n";
   print SENDMAIL "From: ${toAddr}\n";
   print SENDMAIL "Subject: re: ".$HEADERS{subject}."\n";
   print SENDMAIL $template->output;
   close(SENDMAIL);
   cpSupport::logExit(__FILE__.": ticket from ${fromAddr} rejected due to unregistered user.");
}
$toAddr =~ m/(.*)\@.*/;
my $type = $1;

if (!$user->is_whitelisted($dbh)) {
   if ( !checkBadWords($HEADERS{subject},$dbh) || !checkBadWords($content,$dbh) ) {
      my $select = $dbh->prepare("SELECT * FROM ${cpSupport::DB_PREFIX}_emails WHERE name='badwordReply'");
      $select->execute;

      if ($select->rows != 1) {
         exit;
      }
      my $rowRef = $select->fetchrow_hashref();

      my $content = $$rowRef{content};
      
      my $template = HTML::Template->new( scalarref => \$content,
                                          die_on_bad_params => 0 );
      
      open(SENDMAIL,"|/usr/sbin/sendmail -t");
      print SENDMAIL "To: ${fromAddr}\n";
      print SENDMAIL "From: ${toAddr}\n";
      print SENDMAIL "Subject: re: ".$HEADERS{subject}."\n";
      print SENDMAIL $template->output;
      close(SENDMAIL);
      cpSupport::logExit(__FILE__.":: ticket from ${fromAddr} rejected due to badwords.");
   }
}
my $ttype = cpSupport::TicketType->new;
$ttype->load_name_from_dbh($type,$dbh);
if (grep(/^\Q$type\E$/,keys %types) ) {
   if ($content =~ /^[\<\>\s\t]*Ticket Id: (\d+)[\s\t]*$/m) {
      my $id = $1;
      continueTicket($id,$user,$content,$dbh);
      cpSupport::writeLog(__FILE__.": ticket #${id} continued by ".$user->name);
   }
   else { # New Ticket
      my $id = newTicket($user,\%HEADERS,$content,$ttype,$dbh);
      cpSupport::writeLog(__FILE__.": new ticket: #${id} opened by ".$user->name);
   }
}
else { # Error or something.
   cpSupport::writeLog(__FILE__.": unable to process mail from ${fromAddr}");
}


# newTicket ################################################# {{{
sub newTicket {
   my ($user,$headers,$body,$ttype,$dbh) = @_;

   my $id = cpSupport::Ticket::insert_new($user->id,$$headers{subject},$body,$ttype->id,$dbh);

   my $conf = cpSupport::Config->new($dbh);

   # Send e-mail confirming new ticket.
   my $select = $dbh->prepare("SELECT * FROM ${cpSupport::DB_PREFIX}_emails WHERE name='newTicketReply'");
   $select->execute;

   if ($select->rows != 1) {
      exit;
   }
   my $rowRef = $select->fetchrow_hashref();

   my $content = $$rowRef{content};
      
   my $template = HTML::Template->new( scalarref => \$content,
                                       die_on_bad_params => 0 );
   $template->param( ticketid => $id );

   open(SENDMAIL,"|/usr/sbin/sendmail -t");
   print SENDMAIL "To: ${fromAddr}\n";
   print SENDMAIL "From: ${toAddr}\n"; 
   print SENDMAIL "Subject: re: ".$$headers{subject}."\n";
   print SENDMAIL $template->output;
   close(SENDMAIL);

   return $id;
}
# }}}

# Continue Ticket ########################################### {{{
sub continueTicket {
   my ($id,$user,$body,$dbh) = @_;

   my $ticket = cpSupport::Ticket->new( ticketid => $id, load_id => 1, dbh => $dbh );
   my $tran = new cpSupport::Transaction(
                  ticketId => $id,
                  type     => "recieve",
                  user     => $user->id,
                  body     => $body,
              );
   $tran->insert($dbh);
   my $update = $dbh->prepare("UPDATE ${cpSupport::DB_PREFIX}_tickets SET lastresponse=NOW(), status='open', needres='y' WHERE ticketid=?");
   $update->execute($id);
}
# }}}

# checkBadWords ############################################# {{{
sub checkBadWords {
	my ($body,$dbh) = @_;
	
	my $select = $dbh->prepare("SELECT * FROM ${cpSupport::DB_PREFIX}_badwords");
	$select->execute;
	while (my $rowRef = $select->fetchrow_hashref()) {
		foreach my $line (split('\n',$body)) {
			my $word = $$rowRef{word};
			return 0 if $line =~ m/\b\Q${word}\E\b/i;
		}
	}
	return 1;
}
# }}}
