Files
server/usr/share/psa-horde/ingo/lib/Script/Base.php
2026-01-07 20:52:11 +01:00

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)));
}
}