From 28911eec06afefeb39d0a15d0ae8c1e56260812e Mon Sep 17 00:00:00 2001
From: Jared Hancock <gravydish@gmail.com>
Date: Tue, 20 Mar 2012 21:20:00 -0500
Subject: [PATCH] Reject tickets from banned emails

This will include other information described in email filters that mark the
email as rejected. For instance, sender-name, message body content, etc. It
also allows for other matching methods (contains, !=, !contains), rather
than the quick banlist method from EmailFilter::isBanned().

Also fix bug in Filter::__construct that prevented any filter from ever
matching
---
 include/class.filter.php | 42 ++++++++++++++++++++++++++++++++++------
 include/class.ticket.php | 15 +++++++++++---
 2 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/include/class.filter.php b/include/class.filter.php
index 9a1caf2b1..9b9d72790 100644
--- a/include/class.filter.php
+++ b/include/class.filter.php
@@ -38,7 +38,7 @@ class Filter {
             return false;
         
         $this->ht=db_fetch_array($res);
-        $this->id=$info['id'];
+        $this->id=$this->ht['id'];
         
         return true;
     }
@@ -589,16 +589,46 @@ class EmailFilter {
             array_push($this->filters, new Filter($id));
         return $this->filters;
     }
+    /**
+     * Fetches the short list of filters that match the email received in the
+     * constructor. This function is memoized so subsequent calls will
+     * return immediately.
+     */
+    function getMatchingFilterList() {
+        if (!isset($this->short_list)) {
+            $this->short_list = array();
+            foreach ($this->filters as $filter)
+                if ($filter->matches($this->email))
+                    $this->short_list[] = $filter;
+        }
+        return $this->short_list;
+    }
+    /**
+     * Determine if the filters that match the received email indicate that
+     * the email should be rejected
+     *
+     * Returns FALSE if the email should be acceptable. If the email should
+     * be rejected, the first filter that matches and has rejectEmail set is
+     * returned.
+     */
+    function shouldReject() {
+        foreach ($this->getMatchingFilterList() as $filter) {
+            # Set reject if this filter indicates that the email should
+            # be blocked; however, don't unset $reject, because if it
+            # was set by another rule that did not set stopOnMatch(), we
+            # should still honor its configuration
+            if ($filter->rejectEmail()) return $filter;
+        }
+        return false;
+    }
     /**
      * Determine if any filters match the received email, and if so, apply
      * actions defined in those filters to the ticket-to-be-created.
      */
     function apply(&$ticket) {
-        foreach ($this->filters as $filter) {
-            if ($filter->matches($this->email)) {
-                $filter->apply($ticket, $this->email);
-                if ($filter->stopOnMatch()) break;
-            }
+        foreach ($this->getMatchingFilterList() as $filter) {
+            $filter->apply($ticket, $this->email);
+            if ($filter->stopOnMatch()) break;
         }
     }
     
diff --git a/include/class.ticket.php b/include/class.ticket.php
index edb9ac460..538492da0 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -1627,12 +1627,21 @@ class Ticket{
     function create($vars,&$errors, $origin, $autorespond=true, $alertstaff=true) {
         global $cfg,$thisclient,$_FILES;
 
-        //Make sure the email is not banned
+        //Make sure the email address is not banned
         if ($vars['email'] && EmailFilter::isBanned($vars['email'])) {
             $errors['err']='Ticket denied. Error #403';
             Sys::log(LOG_WARNING,'Ticket denied','Banned email - '.$vars['email']);
             return 0;
-         }
+        }
+        // Make sure email contents should not be rejected
+        if (($email_filter=new EmailFilter($vars))
+                && ($filter=$email_filter->shouldReject())) {
+            $errors['err']='Ticket denied. Error #403';
+            Sys::log(LOG_WARNING,'Ticket denied',
+                sprintf('Banned email - %s by filter "%s"', $vars['email'],
+                    $filter->getName()));
+            return 0;
+        }
 
         $id=0;
         $fields=array();
@@ -1692,7 +1701,7 @@ class Ticket{
         }
 
         # Perform email filter actions on the new ticket arguments XXX: Move filter to the top and check for reject...
-        if (!$errors && $ef = new EmailFilter($vars)) $ef->apply($vars);
+        if (!$errors && $email_filter) $email_filter->apply($vars);
 
         # Some things will need to be unpacked back into the scope of this
         # function
-- 
GitLab