379 lines
11 KiB
PHP
379 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* See the enclosed file LICENSE for license information (ASL). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/apache.
|
|
*
|
|
* @author Brent J. Nordquist <bjn@horde.org>
|
|
* @author Jan Schneider <jan@horde.org>
|
|
* @category Horde
|
|
* @license http://www.horde.org/licenses/apache ASL
|
|
* @package Ingo
|
|
*/
|
|
|
|
/**
|
|
* The Ingo_Script_Base class provides a common abstracted interface to the
|
|
* script-generation subclasses.
|
|
*
|
|
* @author Brent J. Nordquist <bjn@horde.org>
|
|
* @author Jan Schneider <jan@horde.org>
|
|
* @category Horde
|
|
* @license http://www.horde.org/licenses/apache ASL
|
|
* @package Ingo
|
|
*/
|
|
abstract class Ingo_Script_Base
|
|
{
|
|
/**
|
|
* The script class' additional parameters.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_params = array();
|
|
|
|
/**
|
|
* A list of driver features.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_features = array(
|
|
/* Can tests be case sensitive? */
|
|
'case_sensitive' => false,
|
|
/* Does the driver support setting IMAP flags? */
|
|
'imap_flags' => false,
|
|
/* Does the driver support the stop-script option? */
|
|
'stop_script' => false,
|
|
/* Can this driver perform on demand filtering? */
|
|
'on_demand' => false,
|
|
/* Does the driver require a script file to be generated? */
|
|
'script_file' => false,
|
|
);
|
|
|
|
/**
|
|
* The list of actions allowed (implemented) for this driver.
|
|
* This SHOULD be defined in each subclass.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_actions = array();
|
|
|
|
/**
|
|
* The categories of filtering allowed.
|
|
* This SHOULD be defined in each subclass.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_categories = array();
|
|
|
|
/**
|
|
* Which form fields are supported in each category by this driver?
|
|
*
|
|
* This is an associative array with the keys taken from $_actions, each
|
|
* value is a list of strings with the supported feature names. An absent
|
|
* key is interpreted as "all features supported".
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_categoryFeatures = array();
|
|
|
|
/**
|
|
* The list of tests allowed (implemented) for this driver.
|
|
* This SHOULD be defined in each subclass.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_tests = array();
|
|
|
|
/**
|
|
* The types of tests allowed (implemented) for this driver.
|
|
* This SHOULD be defined in each subclass.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_types = array();
|
|
|
|
/**
|
|
* A list of any special types that this driver supports.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_special_types = array();
|
|
|
|
/**
|
|
* The recipes that make up the code.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_recipes = array();
|
|
|
|
/**
|
|
* Have the recipes been generated yet?
|
|
*
|
|
* @var boolean
|
|
*/
|
|
protected $_generated = false;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param array $params A hash containing parameters needed.
|
|
*/
|
|
public function __construct(array $params = array())
|
|
{
|
|
global $registry;
|
|
|
|
$this->setParams($params);
|
|
|
|
/* Determine if ingo should handle the blacklist. */
|
|
if ((($key = array_search(Ingo_Storage::ACTION_BLACKLIST, $this->_categories)) !== false) &&
|
|
($registry->hasMethod('mail/blacklistFrom') != 'ingo')) {
|
|
unset($this->_categories[$key]);
|
|
}
|
|
|
|
/* Determine if ingo should handle the whitelist. */
|
|
if ((($key = array_search(Ingo_Storage::ACTION_WHITELIST, $this->_categories)) !== false) &&
|
|
($registry->hasMethod('mail/whitelistFrom') != 'ingo')) {
|
|
unset($this->_categories[$key]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the parameters.
|
|
*
|
|
* @param array $params A hash containing parameters.
|
|
*
|
|
* @return Ingo_Script This object, for chaining.
|
|
*/
|
|
public function setParams(array $params = array())
|
|
{
|
|
$this->_params = array_merge($this->_params, $params);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the script driver supports a certain feature.
|
|
*
|
|
* @see $_features
|
|
*
|
|
* @param string $feature A feature name.
|
|
*
|
|
* @return boolean True if this feature is supported.
|
|
*/
|
|
public function hasFeature($feature)
|
|
{
|
|
return !empty($this->_features[$feature]);
|
|
}
|
|
|
|
/**
|
|
* Returns a regular expression that should catch mails coming from most
|
|
* daemons, mailing list, newsletters, and other bulk.
|
|
*
|
|
* This is the expression used for procmail's FROM_DAEMON, including all
|
|
* mailinglist headers.
|
|
*
|
|
* @return string A regular expression.
|
|
*/
|
|
public function excludeRegexp()
|
|
{
|
|
return '(^(Mailing-List:|List-(Id|Help|Unsubscribe|Subscribe|Owner|Post|Archive):|Precedence:.*(junk|bulk|list)|To: Multiple recipients of|(((Resent-)?(From|Sender)|X-Envelope-From):|>?From)([^>]*[^(.%@a-z0-9])?(Post(ma?(st(e?r)?|n)|office)|(send)?Mail(er)?|daemon|m(mdf|ajordomo)|n?uucp|LIST(SERV|proc)|NETSERV|o(wner|ps)|r(e(quest|sponse)|oot)|b(ounce|bs\.smtp)|echo|mirror|s(erv(ices?|er)|mtp(error)?|ystem)|A(dmin(istrator)?|MMGR|utoanswer))(([^).!:a-z0-9][-_a-z0-9]*)?[%@>\t ][^<)]*(\(.*\).*)?)?$([^>]|$)))';
|
|
}
|
|
|
|
/**
|
|
* Returns the available actions for this driver.
|
|
*
|
|
* @return array The list of available actions.
|
|
*/
|
|
public function availableActions()
|
|
{
|
|
return $this->_actions;
|
|
}
|
|
|
|
/**
|
|
* Returns the available categories for this driver.
|
|
*
|
|
* @return array The list of categories.
|
|
*/
|
|
public function availableCategories()
|
|
{
|
|
return $this->_categories;
|
|
}
|
|
|
|
/**
|
|
* Returns the supported form fields for this driver.
|
|
*
|
|
* @return array An array with the supported field names of the requested category.
|
|
*/
|
|
public function availableCategoryFeatures($category)
|
|
{
|
|
return isset($this->_categoryFeatures[$category]) ? $this->_categoryFeatures[$category] : array();
|
|
}
|
|
|
|
/**
|
|
* Returns the available tests for this driver.
|
|
*
|
|
* @return array The list of tests actions.
|
|
*/
|
|
public function availableTests()
|
|
{
|
|
return $this->_tests;
|
|
}
|
|
|
|
/**
|
|
* Returns the available test types for this driver.
|
|
*
|
|
* @return array The list of test types.
|
|
*/
|
|
public function availableTypes()
|
|
{
|
|
return $this->_types;
|
|
}
|
|
|
|
/**
|
|
* Returns any test types that are special for this driver.
|
|
*
|
|
* @return array The list of special types
|
|
*/
|
|
public function specialTypes()
|
|
{
|
|
return $this->_special_types;
|
|
}
|
|
|
|
/**
|
|
* Generates the scripts to do the filtering specified in the rules.
|
|
*
|
|
* @return array The scripts.
|
|
*/
|
|
public function generate()
|
|
{
|
|
if (!$this->_generated) {
|
|
$this->_generate();
|
|
$this->_generated = true;
|
|
}
|
|
|
|
$scripts = array();
|
|
foreach ($this->_recipes as $item) {
|
|
$rule = isset($this->_params['transport'][$item['rule']])
|
|
? $item['rule']
|
|
: Ingo::RULE_ALL;
|
|
$name = '';
|
|
if (strlen($item['name'])) {
|
|
$name = $item['name'];
|
|
} elseif (isset($this->_params['transport'][$rule]['params']['filename'])) {
|
|
$name = $this->_params['transport'][$rule]['params']['filename'];
|
|
} elseif (isset($this->_params['transport'][$rule]['params']['scriptname'])) {
|
|
$name = $this->_params['transport'][$rule]['params']['scriptname'];
|
|
}
|
|
|
|
if (!isset($scripts[$rule . $name])) {
|
|
$scripts[$rule . $name] = array(
|
|
'transport' => $this->_params['transport'][$rule],
|
|
'name' => $name,
|
|
'script' => '',
|
|
'recipes' => array(),
|
|
);
|
|
}
|
|
$scripts[$rule . $name]['script'] .= $item['object']->generate() . "\n";
|
|
$scripts[$rule . $name]['recipes'][] = $item;
|
|
}
|
|
return array_values($scripts);
|
|
}
|
|
|
|
/**
|
|
* Generates the scripts to do the filtering specified in the rules.
|
|
*/
|
|
protected function _generate()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Adds an item to the recipe list.
|
|
*
|
|
* @param integer $rule One of the Ingo::RULE_* constants.
|
|
* @param Ingo_Script_Item $item An item to add to the recipe list.
|
|
* @param string $name A script name.
|
|
*/
|
|
protected function _addItem($rule, Ingo_Script_Item $item, $name = null)
|
|
{
|
|
$this->_recipes[] = array(
|
|
'rule' => $rule,
|
|
'object' => $item,
|
|
'name' => $name
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Inserts an item into the recipe list.
|
|
*
|
|
* @param integer $rule One of the Ingo::RULE_* constants.
|
|
* @param Ingo_Script_Item $item An item to add to the recipe list.
|
|
* @param string $name A script name.
|
|
* @þaram integer $position Where to add the item.
|
|
*/
|
|
protected function _insertItem($rule, Ingo_Script_Item $item, $name = null,
|
|
$position = 0)
|
|
{
|
|
array_splice(
|
|
$this->_recipes,
|
|
$position,
|
|
0,
|
|
array(array(
|
|
'rule' => $rule,
|
|
'object' => $item,
|
|
'name' => $name
|
|
))
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Performs the filtering specified in the rules.
|
|
*
|
|
* @param integer $change The timestamp of the latest rule change during
|
|
* the current session (uses session value if
|
|
* null).
|
|
*/
|
|
public function perform($change = null)
|
|
{
|
|
global $session;
|
|
|
|
if (is_null($change)) {
|
|
$change = $session->get('ingo', 'change');
|
|
}
|
|
|
|
$this->_perform($change);
|
|
}
|
|
|
|
/**
|
|
* @see perform()
|
|
*/
|
|
protected function _perform($change)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Is the perform() function available right now?
|
|
*
|
|
* This is not a duplication of hasFeature() because drivers might override
|
|
* this to do real-time checks if on-demand filtering is not only available
|
|
* theoretically but practically in this very moment.
|
|
*
|
|
* @return boolean True if perform() is available, false if not.
|
|
*/
|
|
public function canPerform()
|
|
{
|
|
return $this->hasFeature('on_demand');
|
|
}
|
|
|
|
/**
|
|
* Is this a valid rule?
|
|
*
|
|
* @param integer $type The rule type.
|
|
*
|
|
* @return boolean Whether the rule is valid or not for this driver.
|
|
*/
|
|
protected function _validRule($type)
|
|
{
|
|
return (!empty($type) && in_array($type, array_merge($this->_categories, $this->_actions)));
|
|
}
|
|
|
|
}
|