diff --git a/include/class.banlist.php b/include/class.banlist.php
index 27729b44a42f45cb0d187f1e8f2a8b731991784e..c620b105033fbc1275b6f0cb82ee69bb2c5306d3 100644
--- a/include/class.banlist.php
+++ b/include/class.banlist.php
@@ -27,7 +27,7 @@ class Banlist {
     }
     
     function isbanned($email) {
-        return EmailFilter::isBanned($email);
+        return TicketFilter::isBanned($email);
     }
 
     function includes($email) {
@@ -50,7 +50,7 @@ class Banlist {
             'name'          => 'SYSTEM BAN LIST',
             'isactive'      => 1,
             'match_all_rules' => false,
-            'reject_email'  => true,
+            'reject_ticket'  => true,
             'rules'         => array(),
             'notes'         => 'Internal list for email banning. Do not remove'
         ), $errors);
diff --git a/include/class.canned.php b/include/class.canned.php
index b9ff6de802da17026ce4bc8206af1607e2f1593e..c84950e7d6d19b062dbb3a53c0ccfe95eab96c48 100644
--- a/include/class.canned.php
+++ b/include/class.canned.php
@@ -35,7 +35,7 @@ class Canned {
             .' count(filter.id) as filters '
             .' FROM '.CANNED_TABLE.' canned '
             .' LEFT JOIN '.CANNED_ATTACHMENT_TABLE.' attach ON (attach.canned_id=canned.canned_id) ' 
-            .' LEFT JOIN '.EMAIL_FILTER_TABLE.' filter ON (canned.canned_id = filter.canned_response_id) '
+            .' LEFT JOIN '.FILTER_TABLE.' filter ON (canned.canned_id = filter.canned_response_id) '
             .' WHERE canned.canned_id='.db_input($id)
             .' GROUP BY canned.canned_id';
 
@@ -102,7 +102,7 @@ class Canned {
         if (!$this->_filters) {
             $this->_filters = array();
             $res = db_query(
-                  'SELECT name FROM '.EMAIL_FILTER_TABLE
+                  'SELECT name FROM '.FILTER_TABLE
                 .' WHERE canned_response_id = '.db_input($this->getId())
                 .' ORDER BY name');
             while ($row = db_fetch_row($res))
diff --git a/include/class.filter.php b/include/class.filter.php
index b6c81b42b60d0d4b8c67d3f7b33b1138695fa1e7..ce7d7d92cb273705bc458e32e6c7dd93cf8668e7 100644
--- a/include/class.filter.php
+++ b/include/class.filter.php
@@ -2,7 +2,7 @@
 /*********************************************************************
     class.filter.php
 
-    Email Filter Class
+    Ticket Filter
 
     Peter Rotich <peter@osticket.com>
     Copyright (c)  2006-2012 osTicket
@@ -18,7 +18,7 @@ class Filter {
     var $id;
     var $ht;
 
-    function Filter($id){
+    function Filter($id) {
         $this->id=0;
         $this->load($id);
     }
@@ -29,8 +29,8 @@ class Filter {
             return false;
 
         $sql='SELECT filter.*,count(rule.id) as rule_count '
-            .' FROM '.EMAIL_FILTER_TABLE.' filter '
-            .' LEFT JOIN '.EMAIL_FILTER_RULE_TABLE.' rule ON(rule.filter_id=filter.id) '
+            .' FROM '.FILTER_TABLE.' filter '
+            .' LEFT JOIN '.FILTER_RULE_TABLE.' rule ON(rule.filter_id=filter.id) '
             .' WHERE filter.id='.db_input($id)
             .' GROUP BY filter.id';
 
@@ -47,27 +47,31 @@ class Filter {
         return $this->load($this->getId());
     }
 
-    function getId(){
+    function getId() {
         return $this->id;
     }
 
-    function getName(){
+    function getTarget() {
+        return $this->ht['target'];
+    }
+
+    function getName() {
         return $this->ht['name'];
     }
 
-    function getNotes(){
+    function getNotes() {
         return $this->ht['notes'];
     }
 
-    function getInfo(){
+    function getInfo() {
         return  $this->ht;
     }
 
-    function getNumRules(){
+    function getNumRules() {
         return $this->ht['rule_count'];
     }
 
-    function getExecOrder(){
+    function getExecOrder() {
         return $this->ht['execorder'];
     }
 
@@ -75,7 +79,7 @@ class Filter {
         return $this->ht['email_id'];
     }
 
-    function isActive(){
+    function isActive() {
         return ($this->ht['isactive']);
     }
 
@@ -83,23 +87,23 @@ class Filter {
         return !strcasecmp($this->getName(),'SYSTEM BAN LIST');
     }
 
-    function getDeptId(){
+    function getDeptId() {
         return $this->ht['dept_id'];
     }
 
-    function getPriorityId(){
+    function getPriorityId() {
         return $this->ht['priority_id'];
     }
 
-    function getSLAId(){
+    function getSLAId() {
         return $this->ht['sla_id'];
     }
 
-    function getStaffId(){
+    function getStaffId() {
         return $this->ht['staff_id'];
     }
 
-    function getTeamId(){
+    function getTeamId() {
         return $this->ht['team_id'];
     }
 
@@ -107,36 +111,36 @@ class Filter {
         return $this->ht['canned_response_id'];
     }
 
-    function stopOnMatch(){
+    function stopOnMatch() {
         return ($this->ht['stop_on_match']);
     }
 
-    function matchAllRules(){
+    function matchAllRules() {
         return ($this->ht['match_all_rules']);
     }
 
-    function rejectEmail(){
-        return ($this->ht['reject_email']);
+    function rejectOnMatch() {
+        return ($this->ht['reject_ticket']);
     }
 
-    function useReplyToEmail(){
+    function useReplyToEmail() {
         return ($this->ht['use_replyto_email']);
     }
 
-    function disableAlerts(){
+    function disableAlerts() {
         return ($this->ht['disable_autoresponder']);
     }
      
-    function sendAlerts(){
+    function sendAlerts() {
         return (!$this->disableAlerts());
     }
 
-    function getRules(){
+    function getRules() {
         if (!$this->ht['rules']) {
             $rules=array();
             //We're getting the rules...live because it gets cleared on update.
-            $sql='SELECT * FROM '.EMAIL_FILTER_RULE_TABLE.' WHERE filter_id='.db_input($this->getId());
-            if(($res=db_query($sql)) && db_num_rows($res)){
+            $sql='SELECT * FROM '.FILTER_RULE_TABLE.' WHERE filter_id='.db_input($this->getId());
+            if(($res=db_query($sql)) && db_num_rows($res)) {
                 while($row=db_fetch_array($res))
                     $rules[]=array('w'=>$row['what'],'h'=>$row['how'],'v'=>$row['val']);
             }
@@ -145,11 +149,11 @@ class Filter {
         return $this->ht['rules'];
     }
 
-    function getFlatRules(){ //Format used on html... I'm ashamed 
+    function getFlatRules() { //Format used on html... I'm ashamed 
 
         $info=array();
-        if(($rules=$this->getRules())){
-            foreach($rules as $k=>$rule){
+        if(($rules=$this->getRules())) {
+            foreach($rules as $k=>$rule) {
                 $i=$k+1;
                 $info["rule_w$i"]=$rule['w'];
                 $info["rule_h$i"]=$rule['h'];
@@ -169,7 +173,7 @@ class Filter {
 
     function removeRule($what, $how, $val) {
 
-        $sql='DELETE FROM '.EMAIL_FILTER_RULE_TABLE
+        $sql='DELETE FROM '.FILTER_RULE_TABLE
             .' WHERE filter_id='.db_input($this->getId())
             .' AND what='.db_input($what)
             .' AND how='.db_input($how)
@@ -187,17 +191,19 @@ class Filter {
     }
 
     function containsRule($what, $how, $val) {
+        $val = trim($val);
         if (isset($this->ht['rules'])) {
+            $match = array("w"=>$what, "h"=>$how, "v"=>$val);
             foreach ($this->ht['rules'] as $rule) {
-                if (array("w"=>$what, "h"=>$how, "v"=>$val) == $rule) {
-                    return True;
-                }
+                if ($match == $rule)
+                    return true;
             }
-            return False;
+            return false;
+
         } else {
             # Fetch from database
             return 0 != db_count(
-                "SELECT COUNT(*) FROM ".EMAIL_FILTER_RULE_TABLE
+                "SELECT COUNT(*) FROM ".FILTER_RULE_TABLE
                ." WHERE filter_id=".db_input($this->id)
                ." AND what=".db_input($what)." AND how=".db_input($how)
                ." AND val=".db_input($val)
@@ -208,35 +214,41 @@ class Filter {
      * Simple true/false if the rules defined for this filter match the
      * incoming email
      *
-     * $email is an ARRAY, which has valid keys
-     *  *from - email address of sender
-     *   name - name of sender
-     *   subject - subject line of the email
-     *   body - body content of the email (no attachments, please)
+     * $info is an ARRAY, which has valid keys
+     *   email - FROM email address of the ticket owner
+     *   name - name of ticket owner
+     *   subject - subject line of the ticket
+     *   body - body content of the message (no attachments, please)
      *   reply-to - reply-to email address
      *   reply-to-name - name of sender to reply-to
      *   headers - array of email headers
-     *   emailid - osTicket email id of recipient
+     *   emailId - osTicket system email id 
      */
-    function matches($email) {
+    function matches($info) {
+
+        if(!$info || !is_array($info)) return false;
+
         $what = array(
-            "email"     => $email['email'],
-            "subject"   => $email['subject'],
+            'email'     => $info['email'],
+            'subject'   => $info['subject'],
             # XXX: Support reply-to too ?
-            "name"      => $email['name'],
-            "body"      => $email['message']
+            'name'      => $info['name'],
+            'body'      => $info['message']
             # XXX: Support headers
         );
         $how = array(
             # how => array(function, null or === this, null or !== this)
-            "equal"     => array("strcmp", 0),
-            "not_equal" => array("strcmp", null, 0),
-            "contains"  => array("strpos", null, false),
-            "dn_contain"=> array("strpos", false)
+            'equal'     => array('strcmp', 0),
+            'not_equal' => array('strcmp', null, 0),
+            'contains'  => array('strpos', null, false),
+            'dn_contain'=> array('strpos', false)
         );
+
         $match = false;
         # Respect configured filter email-id
-        if ($this->getEmailId() && $this->getEmailId() != $email['emailId'])
+        if ($this->getEmailId() 
+                && !strcasecmp($this->getTarget(), 'Email')
+                && $this->getEmailId() != $info['emailId'])
             return false;
 
         foreach ($this->getRules() as $rule) {
@@ -265,7 +277,7 @@ class Filter {
      * If the matches() method returns TRUE, send the initial ticket to this
      * method to apply the filter actions defined
      */
-    function apply(&$ticket, $email=null) {
+    function apply(&$ticket, $info=null) {
         # TODO: Disable alerting
         # XXX: Does this imply turning it on as well? (via ->sendAlerts())
         if ($this->disableAlerts()) $ticket['autorespond']=false;
@@ -279,22 +291,24 @@ class Filter {
         #       XXX: Unset the other (of staffId or teamId) (?)
         if ($this->getStaffId())    $ticket['staffId']=$this->getStaffId();
         elseif ($this->getTeamId()) $ticket['teamId']=$this->getTeamId();
-        #       Override name with reply-to information from the EmailFilter
+        #       Override name with reply-to information from the TicketFilter
         #       match
-        if ($this->useReplyToEmail() && $email['reply-to']) {
-            $ticket['email'] = $email['reply-to'];
-            if ($email['reply-to-name']) 
-                $ticket['name'] = $email['reply-to-name'];
+        if ($this->useReplyToEmail() && $info['reply-to']) {
+            $ticket['email'] = $info['reply-to'];
+            if ($info['reply-to-name']) 
+                $ticket['name'] = $info['reply-to-name'];
         }
+
+        # Use canned response.
         if ($this->getCannedResponse())
             $ticket['cannedResponseId'] = $this->getCannedResponse();
     }
     /* static */ function getSupportedMatches() {
         return array(
-            'name'=>    "Sender's Name",
-            'email'=>   "Sender's Email",
-            'subject'=> 'Email Subject',
-            'body'=>    'Email Body/Text'
+            'name'=>    'Name',
+            'email'=>   'Email',
+            'subject'=> 'Subject',
+            'body'=>    'Body/Text'
         );
     }
     /* static */ function getSupportedMatchTypes() {
@@ -306,7 +320,7 @@ class Filter {
         );
     }
 
-    function update($vars,&$errors){
+    function update($vars,&$errors) {
 
         if(!Filter::save($this->getId(),$vars,$errors))
             return false;
@@ -316,47 +330,55 @@ class Filter {
         return true;
     }
 
-    function delete(){
+    function delete() {
         
         $id=$this->getId();
-        $sql='DELETE FROM '.EMAIL_FILTER_TABLE.' WHERE id='.db_input($id).' LIMIT 1';
-        if(db_query($sql) && ($num=db_affected_rows())){
-            db_query('DELETE FROM '.EMAIL_FILTER_RULE_TABLE.' WHERE filter_id='.db_input($id));
+        $sql='DELETE FROM '.FILTER_TABLE.' WHERE id='.db_input($id).' LIMIT 1';
+        if(db_query($sql) && ($num=db_affected_rows())) {
+            db_query('DELETE FROM '.FILTER_RULE_TABLE.' WHERE filter_id='.db_input($id));
         }
 
         return $num;
     }
 
     /** static functions **/
-    function create($vars,&$errors){
+    function getTargets() {
+        return array(
+                'Any' => 'Any',
+                'Web' => 'Web Forms',
+                'API' => 'API Calls',
+                'Email' => 'Emails');
+    }
+
+    function create($vars,&$errors) {
         return Filter::save(0,$vars,$errors);
     }
 
-    function getIdByName($name){
+    function getIdByName($name) {
 
-        $sql='SELECT id FROM '.EMAIL_FILTER_TABLE.' WHERE name='.db_input($name);
+        $sql='SELECT id FROM '.FILTER_TABLE.' WHERE name='.db_input($name);
         if(($res=db_query($sql)) && db_num_rows($res))
             list($id)=db_fetch_row($res);
 
         return $id;
     }
 
-    function lookup($id){
+    function lookup($id) {
         return ($id && is_numeric($id) && ($f= new Filter($id)) && $f->getId()==$id)?$f:null;
     }
 
-    function validate_rules($vars,&$errors){
+    function validate_rules($vars,&$errors) {
         return self::save_rules(0,$vars,$errors);
     }
 
-    function save_rules($id,$vars,&$errors){
+    function save_rules($id,$vars,&$errors) {
 
         $matches=array('name','email','subject','body','header');
         $types=array('equal','not_equal','contains','dn_contain');
 
         $rules=array();
         for($i=1; $i<=25; $i++) { //Expecting no more than 25 rules...
-            if($vars["rule_w$i"] || $vars["rule_h$i"]){
+            if($vars["rule_w$i"] || $vars["rule_h$i"]) {
                 if(!$vars["rule_w$i"] || !in_array($vars["rule_w$i"],$matches))
                     $errors["rule_$i"]='Invalid match selection';
                 elseif(!$vars["rule_h$i"] || !in_array($vars["rule_h$i"],$types))
@@ -367,7 +389,7 @@ class Filter {
                     $errors["rule_$i"]='Valid email required for the match type';
                 else //for everything-else...we assume it's valid.
                     $rules[]=array('w'=>$vars["rule_w$i"],'h'=>$vars["rule_h$i"],'v'=>$vars["rule_v$i"]);
-            }elseif($vars["rule_v$i"]){
+            }elseif($vars["rule_v$i"]) {
                 $errors["rule_$i"]='Incomplete selection';
             }
         }
@@ -383,7 +405,7 @@ class Filter {
         if(!$id) return true; //When ID is 0 then assume it was just validation...
 
         //Clear existing rules...we're doing mass replace on each save!! 
-        db_query('DELETE FROM '.EMAIL_FILTER_RULE_TABLE.' WHERE filter_id='.db_input($id));
+        db_query('DELETE FROM '.FILTER_RULE_TABLE.' WHERE filter_id='.db_input($id));
         $num=0;
         foreach($rules as $rule) {
             $rule['filter_id']=$id;
@@ -394,39 +416,52 @@ class Filter {
         return $num; 
     }
 
-    function save($id,$vars,&$errors){
+    function save($id,$vars,&$errors) {
 
 
         if(!$vars['execorder'])
-            $errors['execorder']='Order required';
+            $errors['execorder'] = 'Order required';
         elseif(!is_numeric($vars['execorder']))
-            $errors['execorder']='Must be numeric value';
+            $errors['execorder'] = 'Must be numeric value';
             
         if(!$vars['name'])
-            $errors['name']='Name required';
+            $errors['name'] = 'Name required';
         elseif(($sid=self::getIdByName($vars['name'])) && $sid!=$id)
-            $errors['name']='Name already in-use';
+            $errors['name'] = 'Name already in-use';
 
         if(!$errors && !self::validate_rules($vars,$errors) && !$errors['rules'])
-            $errors['rules']='Unable to validate rules as entered';
+            $errors['rules'] = 'Unable to validate rules as entered';
+
+        $targets = self::getTargets();
+        if(!$vars['target'])
+            $errors['target'] = 'Target required';
+        else if(!is_numeric($vars['target']) && !$targets[$vars['target']])
+            $errors['target'] = 'Unknown or invalid target';
 
         if($errors) return false;
 
-        $sql=' updated=NOW() '.
-             ',isactive='.db_input($vars['isactive']).
-             ',name='.db_input($vars['name']).
-             ',execorder='.db_input($vars['execorder']).
-             ',email_id='.db_input($vars['email_id']).
-             ',dept_id='.db_input($vars['dept_id']).
-             ',priority_id='.db_input($vars['priority_id']).
-             ',sla_id='.db_input($vars['sla_id']).
-             ',match_all_rules='.db_input($vars['match_all_rules']).
-             ',stop_onmatch='.db_input(isset($vars['stop_onmatch'])?1:0).
-             ',reject_email='.db_input(isset($vars['reject_email'])?1:0).
-             ',use_replyto_email='.db_input(isset($vars['use_replyto_email'])?1:0).
-             ',disable_autoresponder='.db_input(isset($vars['disable_autoresponder'])?1:0).
-             ',canned_response_id='.db_input($vars['canned_response_id']).
-             ',notes='.db_input($vars['notes']);
+        $emailId = 0;
+        if(is_numeric($vars['target'])) {
+            $emailId = $vars['target'];
+            $vars['target'] = 'Email';
+        }
+
+        $sql=' updated=NOW() '
+            .',isactive='.db_input($vars['isactive'])
+            .',target='.db_input($vars['target'])
+            .',name='.db_input($vars['name'])
+            .',execorder='.db_input($vars['execorder'])
+            .',email_id='.db_input($emailId)
+            .',dept_id='.db_input($vars['dept_id'])
+            .',priority_id='.db_input($vars['priority_id'])
+            .',sla_id='.db_input($vars['sla_id'])
+            .',match_all_rules='.db_input($vars['match_all_rules'])
+            .',stop_onmatch='.db_input(isset($vars['stop_onmatch'])?1:0)
+            .',reject_ticket='.db_input(isset($vars['reject_ticket'])?1:0)
+            .',use_replyto_email='.db_input(isset($vars['use_replyto_email'])?1:0)
+            .',disable_autoresponder='.db_input(isset($vars['disable_autoresponder'])?1:0)
+            .',canned_response_id='.db_input($vars['canned_response_id'])
+            .',notes='.db_input($vars['notes']);
        
 
         //Auto assign ID is overloaded...
@@ -438,11 +473,11 @@ class Filter {
             $sql.=',staff_id=0,team_id=0 '; //no auto-assignment!
 
         if($id) {
-            $sql='UPDATE '.EMAIL_FILTER_TABLE.' SET '.$sql.' WHERE id='.db_input($id);
+            $sql='UPDATE '.FILTER_TABLE.' SET '.$sql.' WHERE id='.db_input($id);
             if(!db_query($sql))
                 $errors['err']='Unable to update the filter. Internal error occurred';
         }else{
-            $sql='INSERT INTO '.EMAIL_FILTER_TABLE.' SET '.$sql.',created=NOW() ';
+            $sql='INSERT INTO '.FILTER_TABLE.' SET '.$sql.',created=NOW() ';
             if(!db_query($sql) || !($id=db_insert_id()))
                 $errors['err']='Unable to add filter. Internal error';
         }
@@ -464,14 +499,14 @@ class FilterRule {
 
     var $filter;
 
-    function FilterRule($id,$filterId=0){
+    function FilterRule($id,$filterId=0) {
         $this->id=0;
         $this->load($id,$filterId);
     }
 
     function load($id,$filterId=0) {
 
-        $sql='SELECT rule.* FROM '.EMAIL_FILTER_RULE_TABLE.' rule '
+        $sql='SELECT rule.* FROM '.FILTER_RULE_TABLE.' rule '
             .' WHERE rule.id='.db_input($id);
         if($filterId)
             $sql.=' AND rule.filter_id='.db_input($filterId);
@@ -529,9 +564,9 @@ class FilterRule {
         return true;
     }
 
-    function delete(){
+    function delete() {
         
-        $sql='DELETE FROM '.EMAIL_FILTER_RULE_TABLE.' WHERE id='.db_input($this->getId()).' AND filter_id='.db_input($this->getFilterId());
+        $sql='DELETE FROM '.FILTER_RULE_TABLE.' WHERE id='.db_input($this->getId()).' AND filter_id='.db_input($this->getFilterId());
 
         return (db_query($sql) && db_affected_rows());
     }
@@ -559,12 +594,12 @@ class FilterRule {
             $sql.=',notes='.db_input($vars['notes']);
 
         if($id) {
-            $sql='UPDATE '.EMAIL_FILTER_RULE_TABLE.' SET '.$sql.' WHERE id='.db_input($id).' AND filter_id='.db_input($vars['filter_id']);
+            $sql='UPDATE '.FILTER_RULE_TABLE.' SET '.$sql.' WHERE id='.db_input($id).' AND filter_id='.db_input($vars['filter_id']);
             if(db_query($sql))
                 return true;
 
         } else {
-            $sql='INSERT INTO '.EMAIL_FILTER_RULE_TABLE.' SET created=NOW(), filter_id='.db_input($vars['filter_id']).', '.$sql;
+            $sql='INSERT INTO '.FILTER_RULE_TABLE.' SET created=NOW(), filter_id='.db_input($vars['filter_id']).', '.$sql;
             if(db_query($sql) && ($id=db_insert_id()))
                 return $id;
         }
@@ -579,50 +614,65 @@ class FilterRule {
 }
 
 /**
- * Applies rules defined in the staff control panel "Email Filters". Each
+ * Applies rules defined in the admin control panel > Settings tab > "Ticket Filters". Each
  * filter can have up to 25 rules (*currently). This will attempt to match
- * the incoming email against the defined rules, and, if the email matches,
- * the ticket will be modified as described in the filter
+ * the incoming tickets against the defined rules, and, if the email matches,
+ * the ticket will be modified as described in the filter actions.
  */
-class EmailFilter {
+class TicketFilter {
+
+    var $target;
+    var $vars;
+
     /**
-     * Construct a list of filters to handle a new ticket generated from an
-     * email or something with information common to email (such as API
-     * calls, etc).
+     * Construct a list of filters to handle a new ticket
+     * taking into account the source/origin of the ticket.
      *
-     * $email is an ARRAY, which has valid keys
-     *  *email - email address of sender
-     *   name - name of sender
-     *   subject - subject line of the email
-     *   email-id - id of osTicket email recipient address
+     * $vars is an ARRAY, which has valid keys
+     *  *email - email address of user
+     *   name - name of user
+     *   subject - subject of the ticket
+     *   emailId - id of osTicket's system email (for emailed tickets)
      *  ---------------
      *  @see Filter::matches() for a complete list of supported keys
      *
-     * $slow - if TRUE, every (active) filter will be fetched from the
-     *         database and matched against the email. Otherwise, a subset
-     *         of filters from the database that appear to have rules that
-     *         deal with the data in the email will be considered. @see
-     *         ::quickList() for more information.
+     *  IF $vars is not provided, every (active) filter will be fetched from the
+     *  database and matched against the incoming ticket. Otherwise, a subset
+     *  of filters from the database that appear to have rules that
+     *  deal with the data in the incoming ticket (based on $vars) will be considered.
+     *  @see ::quickList() for more information.
      */
-    function EmailFilter($email, $slow=false) {
-        $this->email = $email;
-        if ($slow) {
-            $this->build($this->getAllActive());
-        } else {
-            $this->build(
-                $this->quickList($email['email'], $email['name'],
-                    $email['subject'], $email['emailId']));
-        }
+    function TicketFilter($origin, $vars=null) {
+        
+        $this->target = self::origin2target($origin);
+        $this->vars = ($vars && is_array($vars))?array_filter(array_map('trim', $vars)):null;
+       
+        //Init filters.
+        $this->build();
     }
-    
-    function build($res) {
+
+    function build() {
+        
+        //Clear any memoized filters
         $this->filters = array();
-        while (list($id) = db_fetch_row($res))
-            array_push($this->filters, new Filter($id));
+        $this->short_list = array();
+
+        //Query DB for "possibly" matching filters.
+        $res = $this->vars?$this->quickList():$this->getAllActive();
+        if($res) {
+            while (list($id) = db_fetch_row($res))
+                array_push($this->filters, new Filter($id));
+        }
+
         return $this->filters;
     }
+
+    function getTarget() {
+        return $this->target;
+    }
+
     /**
-     * Fetches the short list of filters that match the email received in the
+     * Fetches the short list of filters that match the ticket vars received in the
      * constructor. This function is memoized so subsequent calls will
      * return immediately.
      */
@@ -630,17 +680,18 @@ class EmailFilter {
         if (!isset($this->short_list)) {
             $this->short_list = array();
             foreach ($this->filters as $filter)
-                if ($filter->matches($this->email))
+                if ($filter->matches($this->vars))
                     $this->short_list[] = $filter;
         }
+
         return $this->short_list;
     }
     /**
-     * Determine if the filters that match the received email indicate that
+     * Determine if the filters that match the received vars 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
+     * be rejected, the first filter that matches and has reject ticket set is
      * returned.
      */
     function shouldReject() {
@@ -649,7 +700,7 @@ class EmailFilter {
             # 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;
+            if ($filter->rejectOnMatch()) return $filter;
         }
         return false;
     }
@@ -659,17 +710,21 @@ class EmailFilter {
      */
     function apply(&$ticket) {
         foreach ($this->getMatchingFilterList() as $filter) {
-            $filter->apply($ticket, $this->email);
+            $filter->apply($ticket, $this->vars);
             if ($filter->stopOnMatch()) break;
         }
     }
     
     /* static */ function getAllActive() {
-        $sql="SELECT id FROM ".EMAIL_FILTER_TABLE." WHERE isactive"
-           ." ORDER BY execorder";
+
+        $sql='SELECT id FROM '.FILTER_TABLE
+            .' WHERE isactive=1 '
+            .'  AND target IN ("Any", '.db_input($this->getTarget()).') '
+            .' ORDER BY execorder';
 
         return db_query($sql);
     }
+
     /**
      * Fast lookup function to all filters that have at least one rule that
      * matches the received address or name or is not defined to match based
@@ -693,45 +748,55 @@ class EmailFilter {
      * information from the database. Whether the filter will completely
      * match or not is determined in the Filter::matches() method.
      */
-    /* static */ function quickList($addr, $name=false, $subj=false, 
-            $emailid=0) {
-        $sql="SELECT DISTINCT filter_id FROM ".EMAIL_FILTER_RULE_TABLE." rule"
-           ." INNER JOIN ".EMAIL_FILTER_TABLE." filter"
-           ." ON (filter.id=rule.filter_id)"
-           ." WHERE filter.isactive";
-        # Filter by recipient email-id if specified
-        if ($emailid) #TODO: Fix the logic here...
-            $sql.=" AND filter.email_id=".db_input($emailid);
+     function quickList() {
+
+        if(!$this->vars || !$this->vars['email'])
+            return $this->getAllActive();
+
+        $sql='SELECT DISTINCT filter_id FROM '.FILTER_RULE_TABLE.' rule '
+            .' INNER JOIN '.FILTER_TABLE.' filter '
+            .' ON (filter.id=rule.filter_id) '
+            .' WHERE filter.isactive '
+            ."  AND filter.target IN ('Any', ".db_input($this->getTarget()).') ';
+
+        # Filter by system's email-id if specified
+        if($this->vars['emailId'])
+            $sql.=' AND (filter.email_id=0 OR filter.email_id='.db_input($this->vars['emailId']).')';
+        
         # Include rules for sender-email, sender-name and subject as
         # requested
-        $sql.=" AND ((what='email' AND LOCATE(val,".db_input($addr)."))";
-        if ($name) 
-            $sql.=" OR (what='name' AND LOCATE(val,".db_input($name)."))";
-        if ($subj) 
-            $sql.=" OR (what='subject' AND LOCATE(val,".db_input($subj)."))";
+        $sql.=" AND ((what='email' AND LOCATE(val, ".db_input($this->vars['email']).'))';
+        if($this->vars['name']) 
+            $sql.=" OR (what='name' AND LOCATE(val, ".db_input($this->vars['name']).'))';
+        if($this->vars['subject']) 
+            $sql.=" OR (what='subject' AND LOCATE(val, ".db_input($this->vars['subject']).'))';
         # Also include filters that do not have any rules concerning either
         # sender-email-addresses or sender-names or subjects
         $sql.=") OR filter.id IN ("
                ." SELECT filter_id "
-               ." FROM ".EMAIL_FILTER_RULE_TABLE." rule"
-               ." INNER JOIN ".EMAIL_FILTER_TABLE." filter"
+               ." FROM ".FILTER_RULE_TABLE." rule"
+               ." INNER JOIN ".FILTER_TABLE." filter"
                ." ON (rule.filter_id=filter.id)"
+               ." WHERE filter.isactive"
+               ." AND filter.target IN('Any', ".db_input($this->getTarget()).")"
                ." GROUP BY filter_id"
                ." HAVING COUNT(*)-COUNT(NULLIF(what,'email'))=0";
-        if ($name!==false) $sql.=" AND COUNT(*)-COUNT(NULLIF(what,'name'))=0";
-        if ($subj!==false) $sql.=" AND COUNT(*)-COUNT(NULLIF(what,'subject'))=0";
+        if (!$this->vars['name']) $sql.=" AND COUNT(*)-COUNT(NULLIF(what,'name'))=0";
+        if (!$this->vars['subject']) $sql.=" AND COUNT(*)-COUNT(NULLIF(what,'subject'))=0";
         # Also include filters that do not have match_all_rules set to and
         # have at least one rule 'what' type that wasn't considered
         $sql.=") OR filter.id IN ("
                ." SELECT filter_id"
-               ." FROM ".EMAIL_FILTER_RULE_TABLE." rule"
-               ." INNER JOIN ".EMAIL_FILTER_TABLE." filter"
+               ." FROM ".FILTER_RULE_TABLE." rule"
+               ." INNER JOIN ".FILTER_TABLE." filter"
                ." ON (rule.filter_id=filter.id)"
-               ." WHERE what NOT IN ('email'"
+               ." WHERE filter.isactive"
+               ." AND filter.target IN ('Any', ".db_input($this->getTarget()).")"
+               ." AND what NOT IN ('email'"
         # Handle sender-name and subject if specified
-               .(($name!==false)?",'name'":"")
-               .(($subj!==false)?",'subject'":"")
-               .") AND filter.match_all_rules = false"
+               .((!$this->vars['name'])?",'name'":"")
+               .((!$this->vars['subject'])?",'subject'":"")
+               .") AND filter.match_all_rules = 0 "
         # Return filters in declared execution order
             .") ORDER BY filter.execorder";
         
@@ -751,10 +816,10 @@ class EmailFilter {
     /* static */ function isBanned($addr) {
 
         $sql='SELECT filter.id, what, how, UPPER(val) '
-            .' FROM '.EMAIL_FILTER_TABLE.' filter'
-            .' INNER JOIN '.EMAIL_FILTER_RULE_TABLE.' rule'
+            .' FROM '.FILTER_TABLE.' filter'
+            .' INNER JOIN '.FILTER_RULE_TABLE.' rule'
             .' ON (filter.id=rule.filter_id)'
-            .' WHERE filter.reject_email'
+            .' WHERE filter.reject_ticket'
             .'   AND filter.match_all_rules=0'
             .'   AND filter.email_id=0'
             .'   AND filter.isactive'
@@ -762,20 +827,22 @@ class EmailFilter {
             .'   AND rule.what="email"'
             .'   AND LOCATE(rule.val,'.db_input($addr).')';
 
+        if(!($res=db_query($sql)) || !db_num_rows($res))
+            return false;
+
         # XXX: Use MB_xxx function for proper unicode support
         $addr = strtoupper($addr);
         $how=array('equal'      => array('strcmp', 0),
                    'contains'   => array('strpos', null, false));
-
-        if ($res=db_query($sql)) {
-            while ($row=db_fetch_array($res)) {
-                list($func, $pos, $neg) = $how[$row['how']];
-                if (!$func) continue;
-                $res = call_user_func($func, $addr, $row['val']);
-                if (($neg === null && $res === $pos) || $res !== $neg)
-                    return $row['id'];
-            }
+            
+        while ($row=db_fetch_array($res)) {
+            list($func, $pos, $neg) = $how[$row['how']];
+            if (!$func) continue;
+            $result = call_user_func($func, $addr, $row['val']);
+            if (($neg === null && $result === $pos) || $result !== $neg)
+                return $row['id'];
         }
+
         return false;
     }
 
@@ -814,5 +881,15 @@ class EmailFilter {
         }
         return false;
     }
+
+    /** 
+     * Normalize ticket source to supported filter target 
+     *
+     */
+    function origin2target($origin) {
+        $sources=array('web' => 'Web', 'email' => 'Email', 'phone' => 'Web', 'staff' => 'Web', 'api' => 'API');
+    
+        return $sources[strtolower($origin)];
+    }
 }
 ?>
diff --git a/include/class.mailfetch.php b/include/class.mailfetch.php
index fb8402169e83b39c258118329215d2459d7547a2..5a4e7e0f73e2edbe006f485f9dbe50b6d69809ce 100644
--- a/include/class.mailfetch.php
+++ b/include/class.mailfetch.php
@@ -376,7 +376,7 @@ class MailFetcher {
             return true; //Reporting success so the email can be moved or deleted.
 
 	    //Is the email address banned?
-        if($mailinfo['email'] && EmailFilter::isBanned($mailinfo['email'])) {
+        if($mailinfo['email'] && TicketFilter::isBanned($mailinfo['email'])) {
 	        //We need to let admin know...
             $ost->logWarning('Ticket denied', 'Banned email - '.$mailinfo['email']);
 	        return true; //Report success (moved or delete)
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 8b9581d532a1e94c8076d3eca0b82bcfe88d7d0e..fc7eb1c520d45dfaab47ee3d7cd61db4f78f2eba 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -1331,7 +1331,7 @@ class Ticket{
         if($newticket) return $msgid; //Our work is done...
 
         $autorespond = true;
-        if ($autorespond && $headers && EmailFilter::isAutoResponse(Mail_Parse::splitHeaders($headers)))
+        if ($autorespond && $headers && TicketFilter::isAutoResponse(Mail_Parse::splitHeaders($headers)))
             $autorespond=false;
 
         $this->onMessage($autorespond); //must be called b4 sending alerts to staff.
@@ -1845,7 +1845,7 @@ class Ticket{
         if ($vars['email']  && Validator::is_email($vars['email'])) {
 
             //Make sure the email address is not banned
-            if(EmailFilter::isBanned($vars['email'])) {
+            if(TicketFilter::isBanned($vars['email'])) {
                 $errors['err']='Ticket denied. Error #403';
                 $ost->logWarning('Ticket denied', 'Banned email - '.$vars['email']);
                 return 0;
@@ -1865,12 +1865,15 @@ class Ticket{
                 return 0;
             }
         }
+
+        //Init ticket filters...
+        $ticket_filter = new TicketFilter($origin, $vars);
         // Make sure email contents should not be rejected
-        if (($email_filter=new EmailFilter($vars))
-                && ($filter=$email_filter->shouldReject())) {
+        if($ticket_filter 
+                && ($filter=$ticket_filter->shouldReject())) {
             $errors['err']='Ticket denied. Error #403';
             $ost->logWarning('Ticket denied', 
-                    sprintf('Banned email - %s by filter "%s"', 
+                    sprintf('Ticket rejected ( %s) by filter "%s"', 
                         $vars['email'], $filter->getName()));
 
             return 0;
@@ -1915,7 +1918,7 @@ class Ticket{
         }
 
         //Make sure the due date is valid
-        if($vars['duedate']){
+        if($vars['duedate']) {
             if(!$vars['time'] || strpos($vars['time'],':')===false)
                 $errors['time']='Select time';
             elseif(strtotime($vars['duedate'].' '.$vars['time'])===false)
@@ -1924,16 +1927,16 @@ class Ticket{
                 $errors['duedate']='Due date must be in the future';
         }
 
-        # Perform email filter actions on the new ticket arguments XXX: Move filter to the top and check for reject...
-        if (!$errors && $email_filter) $email_filter->apply($vars);
+        //Any error above is fatal.
+        if($errors)  return 0;
+
+        # Perform ticket filter actions on the new ticket arguments
+        if ($ticket_filter) $ticket_filter->apply($vars);
 
         # Some things will need to be unpacked back into the scope of this
         # function
         if (isset($vars['autorespond'])) $autorespond=$vars['autorespond'];
 
-        //Any error above is fatal.
-        if($errors)  return 0;
-        
         // OK...just do it.
         $deptId=$vars['deptId']; //pre-selected Dept if any.
         $priorityId=$vars['priorityId'];
@@ -1951,11 +1954,7 @@ class Ticket{
             if($autorespond) $autorespond=$email->autoRespond();
             $email=null;
             $source='Email';
-        }elseif($vars['deptId']){ //Opened by staff.
-            $deptId=$vars['deptId'];
-            $source=ucfirst($vars['source']);
         }
-
         //Last minute checks
         $priorityId=$priorityId?$priorityId:$cfg->getDefaultPriorityId();
         $deptId=$deptId?$deptId:$cfg->getDefaultDeptId();
@@ -2019,7 +2018,7 @@ class Ticket{
         # Messages that are clearly auto-responses from email systems should
         # not have a return 'ping' message
         if ($autorespond && $vars['header'] &&
-                EmailFilter::isAutoResponse(Mail_Parse::splitHeaders($vars['header']))) {
+                TicketFilter::isAutoResponse(Mail_Parse::splitHeaders($vars['header']))) {
             $autorespond=false;
         }
 
diff --git a/include/staff/banlist.inc.php b/include/staff/banlist.inc.php
index 0b61d1e8b779edaf48c448c82eb38c3d1ce3deed..b2b37b284b0ae4de0750650b2feb9fae2135cf5d 100644
--- a/include/staff/banlist.inc.php
+++ b/include/staff/banlist.inc.php
@@ -3,7 +3,7 @@ if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin() || !$filter)
 
 $qstr='';
 $select='SELECT rule.* ';
-$from='FROM '.EMAIL_FILTER_RULE_TABLE.' rule ';
+$from='FROM '.FILTER_RULE_TABLE.' rule ';
 $where='WHERE rule.filter_id='.db_input($filter->getId());
 $search=false;
 if($_REQUEST['q'] && strlen($_REQUEST['q'])>3) {
diff --git a/include/staff/filter.inc.php b/include/staff/filter.inc.php
index c2aad0bcf4456d5bade4fa323a4ba3c991c39929..36186838bd93cdba6977add500645becba4d673e 100644
--- a/include/staff/filter.inc.php
+++ b/include/staff/filter.inc.php
@@ -33,7 +33,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
         <tr>
             <th colspan="2">
                 <h4><?php echo $title; ?></h4>
-                <em>Filters are executed based on execution order.</em>
+                <em>Filters are executed based on execution order. Filter can target specific ticket source.</em>
             </th>
         </tr>
     </thead>
@@ -71,31 +71,37 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
             </td>
         </tr>
         <tr>
-            <td width="180">
-                To Email Address:
+            <td width="180" class="required">
+                Target:
             </td>
             <td>
-                <select name="email_id">
-                    <option value="0">&mdash; Filter applies to ALL incoming emails &dash;</option>
-                    <?php
+                <select name="target">
+                   <option value="">&mdash; Select a Target &dash;</option>
+                   <?php
+                   foreach(Filter::getTargets() as $k => $v) {
+                       echo sprintf('<option value="%s" %s>%s</option>',
+                               $k, (($k==$info['target'])?'selected="selected"':''), $v);
+                    }
                     $sql='SELECT email_id,email,name FROM '.EMAIL_TABLE.' email ORDER by name';
-                    if(($res=db_query($sql)) && db_num_rows($res)){
-                        while(list($id,$email,$name)=db_fetch_row($res)){
+                    if(($res=db_query($sql)) && db_num_rows($res)) {
+                        echo '<OPTGROUP label="Specific System Email">';
+                        while(list($id,$email,$name)=db_fetch_row($res)) {
                             $selected=($info['email_id'] && $id==$info['email_id'])?'selected="selected"':'';
                             if($name)
                                 $email=Format::htmlchars("$name <$email>");
                             echo sprintf('<option value="%d" %s>%s</option>',$id,$selected,$email);
                         }
+                        echo '</OPTGROUP>';
                     }
                     ?>
                 </select>
-                <br><em>(Highly recommended if the filter is specific to one incoming email address)</em>
+                &nbsp;
+                <span class="error">*&nbsp;<?php echo $errors['target']; ?></span>
             </td>
         </tr>
         <tr>
             <th colspan="2">
-                <em><strong>Filter Rules</strong>: Rules are applied based on the criteria.&nbsp;
-                    <span class="error">*&nbsp;<?php echo $errors['rules']; ?></span></em>
+                <em><strong>Filter Rules</strong>: Rules are applied based on the criteria.&nbsp;<span class="error">*&nbsp;<?php echo $errors['rules']; ?></span></em>
             </th>
         </tr>
         <tr>
@@ -156,11 +162,11 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
         </tr>
         <tr>
             <td width="180">
-                Ban Email:
+                Reject Ticket:
             </td>
             <td>
-                <input type="checkbox" name="reject_email" value="1" <?php echo $info['reject_email']?'checked="checked"':''; ?> >
-                    <strong><font class="error">Reject email</font></strong> <em>(All other actions, rules and filters are ignored)</em>
+                <input type="checkbox" name="reject_ticket" value="1" <?php echo $info['reject_ticket']?'checked="checked"':''; ?> >
+                    <strong><font class="error">Reject Ticket</font></strong> <em>(All other actions and filters are ignored)</em>
             </td>
         </tr>
         <tr>
diff --git a/include/staff/filters.inc.php b/include/staff/filters.inc.php
index 7f3aab393f56cb3b1eb3f8dc3da0113204d35e41..7573eceec7d3a82950a52e9e04ce2fce213754e8 100644
--- a/include/staff/filters.inc.php
+++ b/include/staff/filters.inc.php
@@ -1,13 +1,13 @@
 <?php
 if(!defined('OSTADMININC') || !$thisstaff->isAdmin()) die('Access Denied');
-
+$targets = Filter::getTargets();
 $qstr='';
 $sql='SELECT filter.*,count(rule.id) as rules '.
-     'FROM '.EMAIL_FILTER_TABLE.' filter '.
-     'LEFT JOIN '.EMAIL_FILTER_RULE_TABLE.' rule ON(rule.filter_id=filter.id) '.
+     'FROM '.FILTER_TABLE.' filter '.
+     'LEFT JOIN '.FILTER_RULE_TABLE.' rule ON(rule.filter_id=filter.id) '.
      'GROUP BY filter.id';
 $sortOptions=array('name'=>'filter.name','status'=>'filter.isactive','order'=>'filter.execorder','rules'=>'rules',
-                   'created'=>'filter.created','updated'=>'filter.updated');
+                   'target'=>'filter.target', 'created'=>'filter.created','updated'=>'filter.updated');
 $orderWays=array('DESC'=>'DESC','ASC'=>'ASC');
 $sort=($_REQUEST['sort'] && $sortOptions[strtolower($_REQUEST['sort'])])?strtolower($_REQUEST['sort']):'name';
 //Sorting options...
@@ -28,7 +28,7 @@ $x=$sort.'_sort';
 $$x=' class="'.strtolower($order).'" ';
 $order_by="$order_column $order ";
 
-$total=db_count('SELECT count(*) FROM '.EMAIL_FILTER_TABLE.' filter ');
+$total=db_count('SELECT count(*) FROM '.FILTER_TABLE.' filter ');
 $page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
 $pageNav=new Pagenate($total, $page, PAGE_LIMIT);
 $pageNav->setURL('filters.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
@@ -44,7 +44,7 @@ else
 ?>
 
 <div style="width:700;padding-top:5px; float:left;">
- <h2>Email Filters</h2>
+ <h2>Ticket Filters</h2>
 </div>
 <div style="float:right;text-align:right;padding-top:5px;padding-right:5px;">
  <b><a href="filters.php?a=add" class="Icon newEmailFilter">Add New Filter</a></b></div>
@@ -58,9 +58,10 @@ else
         <tr>
             <th width="7">&nbsp;</th>        
             <th width="320"><a <?php echo $name_sort; ?> href="filters.php?<?php echo $qstr; ?>&sort=name">Name</a></th>
-            <th width="100"><a  <?php echo $status_sort; ?> href="filters.php?<?php echo $qstr; ?>&sort=status">Status</a></th>
+            <th width="80"><a  <?php echo $status_sort; ?> href="filters.php?<?php echo $qstr; ?>&sort=status">Status</a></th>
             <th width="80" style="text-align:center;"><a  <?php echo $order_sort; ?> href="filters.php?<?php echo $qstr; ?>&sort=order">Order</a></th>
             <th width="80" style="text-align:center;"><a  <?php echo $rules_sort; ?> href="filters.php?<?php echo $qstr; ?>&sort=rules">Rules</a></th>
+            <th width="100"><a  <?php echo $target_sort; ?> href="filters.php?<?php echo $qstr; ?>&sort=target">Target</a></th>
             <th width="120" nowrap><a  <?php echo $created_sort; ?>href="filters.php?<?php echo $qstr; ?>&sort=created">Date Added</a></th>
             <th width="150" nowrap><a  <?php echo $updated_sort; ?>href="filters.php?<?php echo $qstr; ?>&sort=updated">Last Updated</a></th>
         </tr>
@@ -85,6 +86,7 @@ else
                 <td><?php echo $row['isactive']?'Active':'<b>Disabled</b>'; ?></td>
                 <td style="text-align:right;padding-right:25px;"><?php echo $row['execorder']; ?>&nbsp;</td>
                 <td style="text-align:right;padding-right:25px;"><?php echo $row['rules']; ?>&nbsp;</td>
+                <td>&nbsp;<?php echo Format::htmlchars($targets[$row['target']]); ?></td>
                 <td>&nbsp;<?php echo Format::db_date($row['created']); ?></td>
                 <td>&nbsp;<?php echo Format::db_datetime($row['updated']); ?></td>
             </tr>
@@ -93,7 +95,7 @@ else
         endif; ?>
     <tfoot>
      <tr>
-        <td colspan="7">
+        <td colspan="8">
             <?php if($res && $num){ ?>
             Select:&nbsp;
             <a href="#" onclick="return select_all(document.forms['filters'],true)">All</a>&nbsp;&nbsp;
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index a58206963acf4deb36fd48bf17d80c2ea63020aa..ddd2839b24a720341841edd2c9b81e4efd218164 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -27,7 +27,7 @@ if($ticket->isAssigned() && (
     $warn.='&nbsp;&nbsp;<span class="Icon assignedTicket">Ticket is assigned to '.implode('/', $ticket->getAssignees()).'</span>';
 if(!$errors['err'] && ($lock && $lock->getStaffId()!=$thisstaff->getId()))
     $errors['err']='This ticket is currently locked by '.$lock->getStaffName();
-if(!$errors['err'] && ($emailBanned=EmailFilter::isBanned($ticket->getEmail())))
+if(!$errors['err'] && ($emailBanned=TicketFilter::isBanned($ticket->getEmail())))
     $errors['err']='Email is in banlist! Must be removed before any reply/response';
 
 $unbannable=($emailBanned) ? BanList::includes($ticket->getEmail()) : false;
diff --git a/include/upgrader/sql/c00511c7-7be60a84.patch.sql b/include/upgrader/sql/c00511c7-7be60a84.patch.sql
index 638248b976019a670c773578b564d99a3daacc6a..fdefd09bea960de619fc5a1feac8bd69d3c77b8e 100644
--- a/include/upgrader/sql/c00511c7-7be60a84.patch.sql
+++ b/include/upgrader/sql/c00511c7-7be60a84.patch.sql
@@ -63,7 +63,7 @@ ALTER TABLE `%TABLE_PREFIX%config`
     ADD `transfer_alert_dept_manager` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '1' AFTER `transfer_alert_assigned` ,
     ADD `transfer_alert_dept_members` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `transfer_alert_dept_manager`,
     ADD `send_sys_errors` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1' AFTER `enable_email_piping`,
-    ADD `enable_kb` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1' AFTER `use_email_priority`,
+    ADD `enable_kb` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `use_email_priority`,
     ADD `enable_premade` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1' AFTER `enable_kb`,
     ADD `show_related_tickets` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1' AFTER `auto_assign_reopened_tickets`,
     ADD `schema_signature` CHAR( 32 ) NOT NULL AFTER `ostversion`;
diff --git a/include/upgrader/sql/d0e37dca-1da1bcba.patch.sql b/include/upgrader/sql/d0e37dca-1da1bcba.patch.sql
new file mode 100644
index 0000000000000000000000000000000000000000..3d3bda68e2fd49293e1a73545506416c7a1cc126
--- /dev/null
+++ b/include/upgrader/sql/d0e37dca-1da1bcba.patch.sql
@@ -0,0 +1,23 @@
+/**
+ * @version v1.7 RC3
+ * @signature 1da1bcbafcedc65efef58f142a48ac91
+ *
+ *  Upgrade from 1.6 RC3 + filters
+ *  
+ */
+
+RENAME TABLE  `%TABLE_PREFIX%email_filter` TO  `%TABLE_PREFIX%filter`;
+
+RENAME TABLE  `%TABLE_PREFIX%email_filter_rule` TO  `%TABLE_PREFIX%filter_rule`;
+
+ALTER TABLE  `%TABLE_PREFIX%filter` CHANGE  `reject_email`  `reject_ticket` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT  '0';
+
+ALTER TABLE  `%TABLE_PREFIX%filter` 
+    ADD  `target` ENUM(  'Any',  'Web',  'Email',  'API' ) NOT NULL DEFAULT  'Any' AFTER  `sla_id` ,
+    ADD INDEX (  `target` );
+
+UPDATE `%TABLE_PREFIX%filter` SET `target` = 'Email' WHERE `email_id` != 0;
+
+-- Finished with patch
+UPDATE `%TABLE_PREFIX%config`
+    SET `schema_signature`='1da1bcbafcedc65efef58f142a48ac91';
diff --git a/main.inc.php b/main.inc.php
index abcbfeabdaee005bdd83abb7719ac163e0e531af..c3986f80922687722184fc90df9bfeb150f5fb71 100644
--- a/main.inc.php
+++ b/main.inc.php
@@ -63,8 +63,7 @@
 
     #Current version && schema signature (Changes from version to version)
     define('THIS_VERSION','1.7-RC2'); //Shown on admin panel
-    define('SCHEMA_SIGNATURE','d0e37dca324648f1ce2d10528a6026d4'); //MD5 signature of the db schema. (used to trigger upgrades)
-
+    define('SCHEMA_SIGNATURE','1da1bcbafcedc65efef58f142a48ac91'); //MD5 signature of the db schema. (used to trigger upgrades)
     #load config info
     $configfile='';
     if(file_exists(ROOT_DIR.'ostconfig.php')) //Old installs prior to v 1.6 RC5
@@ -159,8 +158,10 @@
   
     define('EMAIL_TABLE',TABLE_PREFIX.'email');
     define('EMAIL_TEMPLATE_TABLE',TABLE_PREFIX.'email_template');
-    define('EMAIL_FILTER_TABLE',TABLE_PREFIX.'email_filter');
-    define('EMAIL_FILTER_RULE_TABLE',TABLE_PREFIX.'email_filter_rule');
+
+    define('FILTER_TABLE',TABLE_PREFIX.'filter');
+    define('FILTER_RULE_TABLE',TABLE_PREFIX.'filter_rule');
+    
     define('BANLIST_TABLE',TABLE_PREFIX.'email_banlist'); //Not in use anymore....as of v 1.7
 
     define('SLA_TABLE',TABLE_PREFIX.'sla');
diff --git a/scp/banlist.php b/scp/banlist.php
index 081fde9b4ed0cd18713cab78e795c2e0eaf1df1b..a31d91d7e8d2392c2d7e23dba570a07257532ec8 100644
--- a/scp/banlist.php
+++ b/scp/banlist.php
@@ -68,7 +68,7 @@ if($_POST && !$errors && $filter){
             }else{
                 $count=count($_POST['ids']);
                 if($_POST['enable']){
-                    $sql='UPDATE '.EMAIL_FILTER_RULE_TABLE.' SET isactive=1 WHERE filter_id='.
+                    $sql='UPDATE '.FILTER_RULE_TABLE.' SET isactive=1 WHERE filter_id='.
                             db_input($filter->getId()).
                          ' AND id IN ('.
                             implode(',', db_input($_POST['ids'])).')';
@@ -81,7 +81,7 @@ if($_POST && !$errors && $filter){
                         $errors['err']='Unable to enable selected emails';
                     }
                 }elseif($_POST['disable']){
-                    $sql='UPDATE '.EMAIL_FILTER_RULE_TABLE.' SET isactive=0 WHERE filter_id='.
+                    $sql='UPDATE '.FILTER_RULE_TABLE.' SET isactive=0 WHERE filter_id='.
                             db_input($filter->getId()).
                          ' AND id IN ('.
                             implode(',', db_input($_POST['ids'])).')';
diff --git a/scp/filters.php b/scp/filters.php
index 2fe1f9fb7c06f9848f958d1e2e8b6ebe62b17390..29045410fe685f10a86a362942f34259a6401edd 100644
--- a/scp/filters.php
+++ b/scp/filters.php
@@ -49,7 +49,7 @@ if($_POST){
             }else{
                 $count=count($_POST['ids']);
                 if($_POST['enable']){
-                    $sql='UPDATE '.EMAIL_FILTER_TABLE.' SET isactive=1 WHERE id IN ('.
+                    $sql='UPDATE '.FILTER_TABLE.' SET isactive=1 WHERE id IN ('.
                         implode(',', db_input($_POST['ids'])).')';
                     if(db_query($sql) && ($num=db_affected_rows())){
                         if($num==$count)
@@ -60,7 +60,7 @@ if($_POST){
                         $errors['err']='Unable to enable selected filters';
                     }
                 }elseif($_POST['disable']){
-                    $sql='UPDATE '.EMAIL_FILTER_TABLE.' SET isactive=0  WHERE id IN ('.
+                    $sql='UPDATE '.FILTER_TABLE.' SET isactive=0  WHERE id IN ('.
                         implode(',', db_input($_POST['ids'])).')';
                     if(db_query($sql) && ($num=db_affected_rows())) {
                         if($num==$count)
diff --git a/scp/tickets.php b/scp/tickets.php
index 8c799a2a6a02a26c4185afece329ffc5e57cdcf4..77eec14eab39caed7e1c235ffa079bdeaa658ace 100644
--- a/scp/tickets.php
+++ b/scp/tickets.php
@@ -52,7 +52,7 @@ if($_POST && !$errors):
                 $errors['err']='Action Denied. Ticket is locked by someone else!';
             
             //Make sure the email is not banned
-            if(!$errors['err'] && EmailFilter::isBanned($ticket->getEmail()))
+            if(!$errors['err'] && TicketFilter::isBanned($ticket->getEmail()))
                 $errors['err']='Email is in banlist. Must be removed to reply.';
 
             $wasOpen =($ticket->isOpen());
diff --git a/setup/inc/sql/osTicket-mysql.sql b/setup/inc/sql/osTicket-mysql.sql
index 5cfba00d6538506e29e136f188610df4508551cb..6be37af6d3ebdc802140748fc4c4b8b03b333796 100644
--- a/setup/inc/sql/osTicket-mysql.sql
+++ b/setup/inc/sql/osTicket-mysql.sql
@@ -91,7 +91,7 @@ CREATE TABLE `%TABLE_PREFIX%config` (
   `clickable_urls` tinyint(1) unsigned NOT NULL default '1',
   `allow_priority_change` tinyint(1) unsigned NOT NULL default '0',
   `use_email_priority` tinyint(1) unsigned NOT NULL default '0',
-  `enable_kb` tinyint(1) unsigned NOT NULL default '1',
+  `enable_kb` tinyint(1) unsigned NOT NULL default '0',
   `enable_premade` tinyint(1) unsigned NOT NULL default '1',
   `enable_captcha` tinyint(1) unsigned NOT NULL default '0',
   `enable_auto_cron` tinyint(1) unsigned NOT NULL default '0',
@@ -228,14 +228,14 @@ CREATE TABLE `%TABLE_PREFIX%email` (
   KEY `dept_id` (`dept_id`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 
-DROP TABLE IF EXISTS `%TABLE_PREFIX%email_filter`;
-CREATE TABLE `%TABLE_PREFIX%email_filter` (
+DROP TABLE IF EXISTS `%TABLE_PREFIX%filter`;
+CREATE TABLE `%TABLE_PREFIX%filter` (
   `id` int(11) unsigned NOT NULL auto_increment,
   `execorder` int(10) unsigned NOT NULL default '99',
   `isactive` tinyint(1) unsigned NOT NULL default '1',
   `match_all_rules` tinyint(1) unsigned NOT NULL default '0',
   `stop_onmatch` tinyint(1) unsigned NOT NULL default '0',
-  `reject_email` tinyint(1) unsigned NOT NULL default '0',
+  `reject_ticket` tinyint(1) unsigned NOT NULL default '0',
   `use_replyto_email` tinyint(1) unsigned NOT NULL default '0',
   `disable_autoresponder` tinyint(1) unsigned NOT NULL default '0',
   `canned_response_id` int(11) unsigned NOT NULL default '0',
@@ -245,20 +245,22 @@ CREATE TABLE `%TABLE_PREFIX%email_filter` (
   `staff_id` int(10) unsigned NOT NULL default '0',
   `team_id` int(10) unsigned NOT NULL default '0',
   `sla_id` int(10) unsigned NOT NULL default '0',
+  `target` ENUM(  'Any',  'Web',  'Email',  'API' ) NOT NULL DEFAULT  'Any',
   `name` varchar(32) NOT NULL default '',
   `notes` text,
   `created` datetime NOT NULL,
   `updated` datetime NOT NULL,
   PRIMARY KEY  (`id`),
+  KEY `target` (`target`),
   KEY `email_id` (`email_id`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 
 
-INSERT INTO `%TABLE_PREFIX%email_filter` (
-  `id`,`isactive`,`execorder`,`reject_email`,`name`,`notes`,`created`)
+INSERT INTO `%TABLE_PREFIX%filter` (
+  `id`,`isactive`,`execorder`,`reject_ticket`,`name`,`notes`,`created`)
     VALUES (1, 1, 99, 1, 'SYSTEM BAN LIST', 'Internal list for email banning. Do not remove', NOW());
 
-DROP TABLE IF EXISTS `%TABLE_PREFIX%email_filter_rule`;
+DROP TABLE IF EXISTS `%TABLE_PREFIX%filter_rule`;
 CREATE TABLE `%TABLE_PREFIX%email_filter_rule` (
   `id` int(11) unsigned NOT NULL auto_increment,
   `filter_id` int(10) unsigned NOT NULL default '0',
@@ -274,7 +276,7 @@ CREATE TABLE `%TABLE_PREFIX%email_filter_rule` (
   UNIQUE `filter` (`filter_id`, `what`, `how`, `val`) 
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%email_filter_rule` (
+INSERT INTO `%TABLE_PREFIX%filter_rule` (
   `id`, `filter_id`, `isactive`, `what`,`how`,`val`,`created`)
     VALUES (1, 1, 1, 'email', 'equal', 'test@example.com',NOW());
 
diff --git a/setup/inc/sql/osTicket-mysql.sql.md5 b/setup/inc/sql/osTicket-mysql.sql.md5
index 63d2ce443b0448ca776ebc37b298a3c4ff93c387..29a60022fd9f87dda3a08126c338d76ae84bbef8 100644
--- a/setup/inc/sql/osTicket-mysql.sql.md5
+++ b/setup/inc/sql/osTicket-mysql.sql.md5
@@ -1 +1 @@
-d0e37dca324648f1ce2d10528a6026d4
+1da1bcbafcedc65efef58f142a48ac91