From: Michael M Slusarz Date: Tue, 9 Feb 2010 18:34:20 +0000 (-0700) Subject: Conversions to H4 formats X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=840f1b2390b7936d58b2abcafdcaec1b46fff40d;p=horde.git Conversions to H4 formats --- diff --git a/ingo/blacklist.php b/ingo/blacklist.php index 291e2ebad..367ba43cf 100644 --- a/ingo/blacklist.php +++ b/ingo/blacklist.php @@ -28,22 +28,23 @@ $scriptor = Ingo::loadIngoScript(); $have_mark = $scriptor && in_array(Ingo_Storage::ACTION_FLAGONLY, $scriptor->availableActions()); /* Get the blacklist object. */ -$blacklist = &$ingo_storage->retrieve(Ingo_Storage::ACTION_BLACKLIST); -if (is_a($blacklist, 'PEAR_Error')) { - $notification->push($blacklist); +try { + $blacklist = $ingo_storage->retrieve(Ingo_Storage::ACTION_BLACKLIST); +} catch (Ingo_Exception $e) { + $notification->push($e); $blacklist = new Ingo_Storage_Blacklist(); } $folder = $blacklist_folder = null; /* Perform requested actions. */ -$actionID = Horde_Util::getFormData('actionID'); -switch ($actionID) { +$vars = Horde_Variables::getDefaultVariables(); +switch ($vars->actionID) { case 'create_folder': - $blacklist_folder = Ingo::createFolder(Horde_Util::getFormData('new_folder_name')); + $blacklist_folder = Ingo::createFolder($vars->new_folder_name); break; case 'rule_update': - switch (Horde_Util::getFormData('action')) { + switch ($vars->action) { case 'delete': $folder = ''; break; @@ -53,14 +54,14 @@ case 'rule_update': break; case 'folder': - $folder = Horde_Util::getFormData('actionvalue'); + $folder = $vars->actionvalue; break; } if (($folder == Ingo::BLACKLIST_MARKER) && !$have_mark) { $notification->push("Not supported by this script generator.", 'horde.error'); } else { - $ret = $blacklist->setBlacklist(Horde_Util::getFormData('blacklist')); + $ret = $blacklist->setBlacklist($vars->blacklist); if (is_a($ret, 'PEAR_Error')) { $notification->push($ret, $ret->getCode()); } else { @@ -94,7 +95,7 @@ $folder_list = Ingo::flistSelect($blacklist_folder, 'filters', 'actionvalue', '].checked=true'); /* Get the blacklist rule. */ -$filters = &$ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); +$filters = $ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); $bl_rule = $filters->findRule(Ingo_Storage::ACTION_BLACKLIST); Ingo::prepareMenu(); diff --git a/ingo/config/fields.php.dist b/ingo/config/fields.php.dist index 2c77ff68d..e6cf33d3f 100644 --- a/ingo/config/fields.php.dist +++ b/ingo/config/fields.php.dist @@ -25,84 +25,86 @@ * $Id$ */ $ingo_fields = array( - 'To' => array( - 'label' => _("To"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'Subject' => array( - 'label' => _("Subject"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'Sender' => array( - 'label' => _("Sender"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'From' => array( - 'label' => _("From"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'Cc' => array( - 'label' => _("Cc"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'Bcc' => array( - 'label' => _("Bcc"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'Resent-from' => array( - 'label' => _("Resent-From"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'Resent-to' => array( - 'label' => _("Resent-To"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'List-Id' => array( - 'label' => _("List-ID"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'Received' => array( - 'label' => _("Received"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'X-Spam-Level' => array( - 'label' => _("X-Spam-Level"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'X-Spam-Score' => array( - 'label' => _("X-Spam-Score"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'X-Spam-Status' => array( - 'label' => _("X-Spam-Status"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'X-Priority' => array( - 'label' => _("X-Priority"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'To,Cc,Bcc,Resent-to' => array( - 'label' => _("Destination (To, Cc, Bcc, etc.)"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'From,Sender,Reply-to,Resent-from' => array( - 'label' => _("Source (From, Reply-to, etc.)"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'To,Cc,Bcc,Resent-to,From,Sender,Reply-to,Resent-from' => array( - 'label' => _("Participant (From, To, etc.)"), - 'type' => Ingo_Storage::TYPE_HEADER - ), - 'Size' => array( - 'label' => _("Size"), - 'type' => Ingo_Storage::TYPE_SIZE, - 'tests' => array('greater than', 'less than') - ), - 'Body' => array( - 'label' => _("Body"), - 'type' => Ingo_Storage::TYPE_BODY, - 'tests' => array('contains', 'not contain', 'is', 'not is', 'begins with', - 'not begins with', 'ends with', 'not ends with', 'regex', - 'matches', 'not matches') - ) + 'To' => array( + 'label' => _("To"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'Subject' => array( + 'label' => _("Subject"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'Sender' => array( + 'label' => _("Sender"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'From' => array( + 'label' => _("From"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'Cc' => array( + 'label' => _("Cc"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'Bcc' => array( + 'label' => _("Bcc"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'Resent-from' => array( + 'label' => _("Resent-From"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'Resent-to' => array( + 'label' => _("Resent-To"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'List-Id' => array( + 'label' => _("List-ID"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'Received' => array( + 'label' => _("Received"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'X-Spam-Level' => array( + 'label' => _("X-Spam-Level"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'X-Spam-Score' => array( + 'label' => _("X-Spam-Score"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'X-Spam-Status' => array( + 'label' => _("X-Spam-Status"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'X-Priority' => array( + 'label' => _("X-Priority"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'To,Cc,Bcc,Resent-to' => array( + 'label' => _("Destination (To, Cc, Bcc, etc.)"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'From,Sender,Reply-to,Resent-from' => array( + 'label' => _("Source (From, Reply-to, etc.)"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'To,Cc,Bcc,Resent-to,From,Sender,Reply-to,Resent-from' => array( + 'label' => _("Participant (From, To, etc.)"), + 'type' => Ingo_Storage::TYPE_HEADER + ), + 'Size' => array( + 'label' => _("Size"), + 'type' => Ingo_Storage::TYPE_SIZE, + 'tests' => array('greater than', 'less than') + ), + 'Body' => array( + 'label' => _("Body"), + 'type' => Ingo_Storage::TYPE_BODY, + 'tests' => array( + 'contains', 'not contain', 'is', 'not is', 'begins with', + 'not begins with', 'ends with', 'not ends with', 'regex', + 'matches', 'not matches' + ) + ) ); diff --git a/ingo/config/prefs.php.dist b/ingo/config/prefs.php.dist index d0264bb6c..2b16d00cf 100644 --- a/ingo/config/prefs.php.dist +++ b/ingo/config/prefs.php.dist @@ -66,45 +66,45 @@ $_prefs['rules'] = array( ); // Blacklist. -// Lock this preference to disable blacklists. $_prefs['blacklist'] = array( 'value' => 'a:2:{s:1:"a";a:0:{}s:1:"f";s:0:"";}', + // Lock this preference to disable blacklists. 'locked' => false, 'shared' => false, 'type' => 'implicit' ); // Whitelist. -// Lock this preference to disable whitelists. $_prefs['whitelist'] = array( 'value' => 'a:0:{}', + // Lock this preference to disable whitelists. 'locked' => false, 'shared' => false, 'type' => 'implicit' ); // Vacation notices. -// Lock this preference to disable vacation notices. $_prefs['vacation'] = array( 'value' => 'a:8:{s:9:"addresses";a:0:{}s:4:"days";i:7;s:8:"excludes";a:0:{}s:10:"ignorelist";b:1;s:6:"reason";s:0:"";s:7:"subject";s:0:"";s:5:"start";i:0;s:3:"end";i:0;}', + // Lock this preference to disable vacation notices. 'locked' => false, 'shared' => false, 'type' => 'implicit' ); // Forwarding. -// Lock this preference to disable forwarding. $_prefs['forward'] = array( 'value' => 'a:2:{s:1:"a";a:0:{}s:1:"k";i:0;}', + // Lock this preference to disable forwarding. 'locked' => false, 'shared' => false, 'type' => 'implicit' ); // Spam rule. -// Lock this preference to disable the spam rule. $_prefs['spam'] = array( 'value' => 'a:2:{s:6:"folder";N;s:5:"level";i:5;}', + // Lock this preference to disable the spam rule. 'locked' => false, 'shared' => false, 'type' => 'implicit' diff --git a/ingo/filters.php b/ingo/filters.php index a8f5b9e0b..4b3d7c8c8 100644 --- a/ingo/filters.php +++ b/ingo/filters.php @@ -14,10 +14,7 @@ require_once dirname(__FILE__) . '/lib/Application.php'; Horde_Registry::appInit('ingo'); /* Get the list of filter rules. */ -$filters = &$ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); -if (is_a($filters, 'PEAR_Error')) { - throw new Horde_Exception($filters); -} +$filters = $ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); /* Load the Ingo_Script:: driver. */ $ingo_script = Ingo::loadIngoScript(); @@ -26,15 +23,14 @@ $ingo_script = Ingo::loadIngoScript(); $on_demand = $ingo_script->performAvailable(); /* Get web parameter data. */ -$actionID = Horde_Util::getFormData('actionID'); -$id = Horde_Util::getFormData('rulenumber'); +$vars = Horde_Variables::getDefaultVariables(); /* Get permissions. */ $edit_allowed = Ingo::hasSharePermission(Horde_Perms::EDIT); $delete_allowed = Ingo::hasSharePermission(Horde_Perms::DELETE); /* Perform requested actions. */ -switch ($actionID) { +switch ($vars->actionID) { case 'rule_down': case 'rule_up': case 'rule_copy': @@ -46,7 +42,7 @@ case 'rule_enable': header('Location: ' . Horde::applicationUrl('filters.php', true)); exit; } - switch ($actionID) { + switch ($vars->actionID) { case 'rule_delete': if (!$delete_allowed) { $notification->push(_("You do not have permission to delete filter rules."), 'horde.error'); @@ -54,8 +50,8 @@ case 'rule_enable': exit; } - $tmp = $filters->getFilter($id); - if ($filters->deleteRule($id)) { + $tmp = $filters->getFilter($vars->rulenumber); + if ($filters->deleteRule($vars->rulenumber)) { $notification->push(sprintf(_("Rule \"%s\" deleted."), $tmp['name']), 'horde.success'); } break; @@ -79,32 +75,30 @@ case 'rule_enable': $notification->push($message, 'horde.error', array('content.raw')); break 2; } else { - $tmp = $filters->getFilter($id); - if ($filters->copyRule($id)) { + $tmp = $filters->getFilter($vars->rulenumber); + if ($filters->copyRule($vars->rulenumber)) { $notification->push(sprintf(_("Rule \"%s\" copied."), $tmp['name']), 'horde.success'); } } break; case 'rule_up': - $steps = Horde_Util::getFormData('steps', 1); - $filters->ruleUp($id, $steps); + $filters->ruleUp($vars->rulenumber, $vars->steps || 1); break; case 'rule_down': - $steps = Horde_Util::getFormData('steps', 1); - $filters->ruleDown($id, $steps); + $filters->ruleDown($vars->rulenumber, $vars->steps || 1); break; case 'rule_disable': - $tmp = $filters->getFilter($id); - $filters->ruleDisable($id); + $tmp = $filters->getFilter($vars->rulenumber); + $filters->ruleDisable($vars->rulenumber); $notification->push(sprintf(_("Rule \"%s\" disabled."), $tmp['name']), 'horde.success'); break; case 'rule_enable': - $tmp = $filters->getFilter($id); - $filters->ruleEnable($id); + $tmp = $filters->getFilter($vars->rulenumber); + $filters->ruleEnable($vars->rulenumber); $notification->push(sprintf(_("Rule \"%s\" enabled."), $tmp['name']), 'horde.success'); break; } @@ -122,8 +116,8 @@ case 'settings_save': header('Location: ' . Horde::applicationUrl('filters.php', true)); exit; } - $prefs->setValue('show_filter_msg', Horde_Util::getFormData('show_filter_msg')); - $prefs->setValue('filter_seen', Horde_Util::getFormData('filter_seen')); + $prefs->setValue('show_filter_msg', $vars->show_filter_msg); + $prefs->setValue('filter_seen', $vars->filter_seen); $notification->push(_("Settings successfully updated."), 'horde.success'); break; @@ -172,7 +166,7 @@ if (count($filter_list) == 0) { $entry = array(); $entry['number'] = ++$i; - $url = Horde_Util::addParameter($filters_url, 'rulenumber', $rule_number); + $url = $filters_url->copy()->add('rulenumber', $rule_number); $copyurl = $delurl = $editurl = $name = null; switch ($filter['action']) { @@ -207,9 +201,9 @@ if (count($filter_list) == 0) { break; default: - $editurl = Horde_Util::addParameter($rule_url, array('edit' => $rule_number, 'actionID' => 'rule_edit')); - $delurl = Horde_Util::addParameter($url, 'actionID', 'rule_delete'); - $copyurl = Horde_Util::addParameter($url, 'actionID', 'rule_copy'); + $editurl = $rule_url->copy()->add(array('edit' => $rule_number, 'actionID' => 'rule_edit')); + $delurl = $url->copy()->add('actionID', 'rule_delete'); + $copyurl = $url->copy()->add('actionID', 'rule_copy'); $entry['filterimg'] = false; $name = $filter['name']; break; @@ -274,14 +268,18 @@ if (count($filter_list) == 0) { } /* Create up/down arrow links. */ - $entry['upurl'] = Horde_Util::addParameter($url, 'actionID', 'rule_up'); - $entry['downurl'] = Horde_Util::addParameter($url, 'actionID', 'rule_down'); - $entry['uplink'] = ($i > 1) ? Horde::link($entry['upurl'], _("Move Rule Up")) : false; - $entry['downlink'] = ($i < $rule_count) ? Horde::link($entry['downurl'], _("Move Rule Down")) : false; + $entry['upurl'] = $url->copy()->add('actionID', 'rule_up'); + $entry['downurl'] = $url->copy()->add('actionID', 'rule_down'); + $entry['uplink'] = ($i > 1) + ? Horde::link($entry['upurl'], _("Move Rule Up")) + : false; + $entry['downlink'] = ($i < $rule_count) + ? Horde::link($entry['downurl'], _("Move Rule Down")) + : false; if (empty($filter['disable'])) { if ($edit_allowed) { - $entry['disablelink'] = Horde::link(Horde_Util::addParameter($url, 'actionID', 'rule_disable'), sprintf(_("Disable %s"), $name)); + $entry['disablelink'] = Horde::link($url->copy()->add('actionID', 'rule_disable'), sprintf(_("Disable %s"), $name)); $entry['disableimg'] = Horde::img('enable.png', sprintf(_("Disable %s"), $name)); } else { $entry['disableimg'] = Horde::img('enable.png'); @@ -291,7 +289,7 @@ if (count($filter_list) == 0) { $entry['enableimg'] = false; } else { if ($edit_allowed) { - $entry['enablelink'] = Horde::link(Horde_Util::addParameter($url, 'actionID', 'rule_enable'), sprintf(_("Enable %s"), $name)); + $entry['enablelink'] = Horde::link($url->copy()->add('actionID', 'rule_enable'), sprintf(_("Enable %s"), $name)); $entry['enableimg'] = Horde::img('disable.png', sprintf(_("Enable %s"), $name)); } else { $entry['enableimg'] = Horde::img('disable.png'); diff --git a/ingo/forward.php b/ingo/forward.php index f742b35bc..a1470b983 100644 --- a/ingo/forward.php +++ b/ingo/forward.php @@ -21,56 +21,50 @@ if (!in_array(Ingo_Storage::ACTION_FORWARD, $_SESSION['ingo']['script_categories } /* Get the forward object and rule. */ -$forward = &$ingo_storage->retrieve(Ingo_Storage::ACTION_FORWARD); -$filters = &$ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); +$forward = $ingo_storage->retrieve(Ingo_Storage::ACTION_FORWARD); +$filters = $ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); $fwd_id = $filters->findRuleId(Ingo_Storage::ACTION_FORWARD); $fwd_rule = $filters->getRule($fwd_id); /* Load libraries. */ -$vars = &Horde_Variables::getDefaultVariables(); -if ($vars->get('submitbutton') == _("Return to Rules List")) { +$vars = Horde_Variables::getDefaultVariables(); +if ($vars->submitbutton == _("Return to Rules List")) { header('Location: ' . Horde::applicationUrl('filters.php', true)); exit; } /* Build form. */ $form = new Horde_Form($vars); -$v = &$form->addVariable(_("Keep a copy of messages in this account?"), 'keep_copy', 'boolean', false); +$v = $form->addVariable(_("Keep a copy of messages in this account?"), 'keep_copy', 'boolean', false); $v->setHelp('forward-keepcopy'); -$v = &$form->addVariable(_("Address(es) to forward to:"), 'addresses', 'longtext', false, false, null, array(5, 40)); +$v = $form->addVariable(_("Address(es) to forward to:"), 'addresses', 'longtext', false, false, null, array(5, 40)); $v->setHelp('forward-addresses'); $form->setButtons(_("Save")); /* Perform requested actions. */ if ($form->validate($vars)) { - $forward->setForwardAddresses($vars->get('addresses')); - $forward->setForwardKeep($vars->get('keep_copy') == 'on'); + $forward->setForwardAddresses($vars->addresses); + $forward->setForwardKeep($vars->keep_copy == 'on'); $success = true; - if (is_a($result = $ingo_storage->store($forward), 'PEAR_Error')) { - $notification->push($result); - $success = false; - } else { + try { + $ingo_storage->store($forward); $notification->push(_("Changes saved."), 'horde.success'); - if ($vars->get('submitbutton') == _("Save and Enable")) { + if ($vars->submitbutton == _("Save and Enable")) { $filters->ruleEnable($fwd_id); - if (is_a($result = $ingo_storage->store($filters), 'PEAR_Error')) { - $notification->push($result); - $success = false; - } else { - $notification->push(_("Rule Enabled"), 'horde.success'); - $fwd_rule['disable'] = false; - } - } elseif ($vars->get('submitbutton') == _("Save and Disable")) { + $ingo_storage->store($filters); + $notification->push(_("Rule Enabled"), 'horde.success'); + $fwd_rule['disable'] = false; + } elseif ($vars->submitbutton == _("Save and Disable")) { $filters->ruleDisable($fwd_id); - if (is_a($result = $ingo_storage->store($filters), 'PEAR_Error')) { - $notification->push($result); - $success = false; - } else { - $notification->push(_("Rule Disabled"), 'horde.success'); - $fwd_rule['disable'] = true; - } + $ingo_storage->store($filters); + $notification->push(_("Rule Disabled"), 'horde.success'); + $fwd_rule['disable'] = true; } + } catch (Ingo_Exception $e) { + $notification->push($e); + $success = false; } + if ($success && $prefs->getValue('auto_update')) { Ingo::updateScript(); } @@ -86,8 +80,8 @@ $form->appendButtons(_("Return to Rules List")); /* Set default values. */ if (!$form->isSubmitted()) { - $vars->set('keep_copy', $forward->getForwardKeep()); - $vars->set('addresses', implode("\n", $forward->getForwardAddresses())); + $vars->keep_copy = $forward->getForwardKeep(); + $vars->addresses = implode("\n", $forward->getForwardAddresses()); } /* Set form title. */ diff --git a/ingo/lib/Api.php b/ingo/lib/Api.php index 3cf195d10..0bfaecb08 100644 --- a/ingo/lib/Api.php +++ b/ingo/lib/Api.php @@ -42,16 +42,16 @@ class Ingo_Api extends Horde_Registry_Api } if (!empty($addresses)) { - $blacklist = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_BLACKLIST); - $ret = $blacklist->setBlacklist(array_merge($blacklist->getBlacklist(), $addresses)); - if (is_a($ret, 'PEAR_Error')) { - $GLOBALS['notification']->push($ret, $ret->getCode()); - } else { + try { + $blacklist = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_BLACKLIST); + $blacklist->setBlacklist(array_merge($blacklist->getBlacklist(), $addresses)); $GLOBALS['ingo_storage']->store($blacklist); Ingo::updateScript(); foreach ($addresses as $from) { $GLOBALS['notification']->push(sprintf(_("The address \"%s\" has been added to your blacklist."), $from)); } + } catch (Ingo_Exception $e) { + $GLOBALS['notification']->push($e); } } } @@ -67,16 +67,16 @@ class Ingo_Api extends Horde_Registry_Api $_SESSION['ingo']['current_share'] = $signature; } - $whitelist = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_WHITELIST); - $ret = $whitelist->setWhitelist(array_merge($whitelist->getWhitelist(), $addresses)); - if (is_a($ret, 'PEAR_Error')) { - $GLOBALS['notification']->push($ret, $ret->getCode()); - } else { + try { + $whitelist = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_WHITELIST); + $whitelist->setWhitelist(array_merge($whitelist->getWhitelist(), $addresses)); $GLOBALS['ingo_storage']->store($whitelist); Ingo::updateScript(); foreach ($addresses as $from) { $GLOBALS['notification']->push(sprintf(_("The address \"%s\" has been added to your whitelist."), $from)); } + } catch (Ingo_Exception $e) { + $GLOBALS['notification']->push($e); } } @@ -87,10 +87,11 @@ class Ingo_Api extends Horde_Registry_Api */ public function canApplyFilters() { - $ingo_script = Ingo::loadIngoScript(); - return $ingo_script - ? $ingo_script->performAvailable() - : false; + try { + return Ingo::loadIngoScript()->performAvailable(); + } catch (Ingo_Exception $e) { + return false; + } } /** @@ -105,16 +106,21 @@ class Ingo_Api extends Horde_Registry_Api if (!empty($GLOBALS['ingo_shares'])) { $_SESSION['ingo']['current_share'] = $signature; } - $ingo_script = Ingo::loadIngoScript(); - if (!$ingo_script) { + + try { + $ingo_script = Ingo::loadIngoScript(); + } catch (Ingo_Exception $e) { return false; } + if (!isset($params['filter_seen'])) { $params['filter_seen'] = $GLOBALS['prefs']->getValue('filter_seen'); } + if (!isset($params['show_filter_msg'])) { $params['show_filter_msg'] = $GLOBALS['prefs']->getValue('show_filter_msg'); } + return $ingo_script->perform($params); } @@ -127,20 +133,20 @@ class Ingo_Api extends Horde_Registry_Api */ public function setVacation($info) { - if (!empty($GLOBALS['ingo_shares'])) { - $_SESSION['ingo']['current_share'] = $signature; - } - if (empty($info)) { return true; } + if (!empty($GLOBALS['ingo_shares'])) { + $_SESSION['ingo']['current_share'] = $signature; + } + /* Get vacation filter. */ - $filters = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FILTERS); + $filters = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FILTERS); $vacation_rule_id = $filters->findRuleId(Ingo_Storage::ACTION_VACATION); /* Set vacation object and rules. */ - $vacation = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_VACATION); + $vacation = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_VACATION); /* Make sure we have at least one address. */ if (empty($info['addresses'])) { @@ -178,17 +184,21 @@ class Ingo_Api extends Horde_Registry_Api } $filters->ruleEnable($vacation_rule_id); - $result = $GLOBALS['ingo_storage']->store($filters); - if (!is_a($result, 'PEAR_Error')) { + + try { + $GLOBALS['ingo_storage']->store($filters); + if ($GLOBALS['prefs']->getValue('auto_update')) { Ingo::updateScript(); } /* Update the timestamp for the rules. */ $_SESSION['ingo']['change'] = time(); - } - return $result; + return true; + } catch (Ingo_Exception $e) {} + + return false; } /** @@ -203,21 +213,25 @@ class Ingo_Api extends Horde_Registry_Api } /* Get vacation filter. */ - $filters = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FILTERS); + $filters = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FILTERS); $vacation_rule_id = $filters->findRuleId(Ingo_Storage::ACTION_VACATION); $filters->ruleDisable($vacation_rule_id); - $result = $GLOBALS['ingo_storage']->store($filters); - if (!is_a($result, 'PEAR_Error')) { + + try { + $GLOBALS['ingo_storage']->store($filters); + if ($GLOBALS['prefs']->getValue('auto_update')) { Ingo::updateScript(); } /* Update the timestamp for the rules. */ $_SESSION['ingo']['change'] = time(); - } - return $result; + return true; + } catch (Ingo_Exception $e) {} + + return false; } } diff --git a/ingo/lib/Application.php b/ingo/lib/Application.php index b28c3fb02..89dd9ed16 100644 --- a/ingo/lib/Application.php +++ b/ingo/lib/Application.php @@ -58,10 +58,8 @@ class Ingo_Application extends Horde_Registry_Application // Load the Ingo_Storage driver. $GLOBALS['ingo_storage'] = Ingo_Storage::factory(); - // Create the ingo session (if needed). - if (!isset($_SESSION['ingo']) || !is_array($_SESSION['ingo'])) { - Ingo_Session::createSession(); - } + // Create the ingo session. + Ingo::createSession(); // Create shares if necessary. $driver = Ingo::getDriver(); @@ -159,59 +157,61 @@ class Ingo_Application extends Horde_Registry_Application * * @param string $user Name of user to remove data for. * - * @return mixed true on success | PEAR_Error on failure + * @throws Horde_Auth_Exception. */ public function removeUserData($user) { - if (!Horde_Auth::isAdmin() && $user != Horde_Auth::getAuth()) { - return PEAR::raiseError(_("You are not allowed to remove user data.")); + if (!Horde_Auth::isAdmin() && + ($user != Horde_Auth::getAuth())) { + throw new Horde_Auth_Exception(_("You are not allowed to remove user data.")); } /* Remove all filters/rules owned by the user. */ - $result = $GLOBALS['ingo_storage']->removeUserData($user); - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR); - return $result; + try { + $GLOBALS['ingo_storage']->removeUserData($user); + } catch (Ingo_Exception $e) { + Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR); + throw new Horde_Auth_Exception($e); } /* Now remove all shares owned by the user. */ if (!empty($GLOBALS['ingo_shares'])) { /* Get the user's default share. */ $share = $GLOBALS['ingo_shares']->getShare($user); - if (is_a($share, 'PEAR_Error')) { + if ($share instanceof PEAR_Error) { Horde::logMessage($share, __FILE__, __LINE__, PEAR_LOG_ERR); - return $share; - } else { - $result = $GLOBALS['ingo_shares']->removeShare($share); - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR); - return $result; - } + throw new Horde_Auth_Exception($share); + } + + $result = $GLOBALS['ingo_shares']->removeShare($share); + if ($result instanceof PEAR_Error) { + Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR); + throw new Horde_Auth_Exception($share); } /* Get a list of all shares this user has perms to and remove the * perms. */ $shares = $GLOBALS['ingo_shares']->listShares($user); - if (is_a($shares, 'PEAR_Error')) { + if ($shares instanceof PEAR_Error) { Horde::logMessage($shares, __FILE__, __LINE__, PEAR_LOG_ERR); - } - foreach ($shares as $share) { - $share->removeUser($user); + } else { + foreach ($shares as $share) { + $share->removeUser($user); + } } /* Get a list of all shares this user owns and has perms to delete * and remove them. */ $shares = $GLOBALS['ingo_shares']->listShares($user, Horde_Perms::DELETE, $user); - if (is_a($shares, 'PEAR_Error')) { + if ($shares instanceof PEAR_Error) { Horde::logMessage($shares, __FILE__, __LINE__, PEAR_LOG_ERR); - return $shares; + throw new Horde_Auth_Exception($share); } + foreach ($shares as $share) { $GLOBALS['ingo_shares']->removeShare($share); } } - - return true; } } diff --git a/ingo/lib/Driver.php b/ingo/lib/Driver.php index b85d5e2d5..96482c0f3 100644 --- a/ingo/lib/Driver.php +++ b/ingo/lib/Driver.php @@ -28,24 +28,24 @@ class Ingo_Driver protected $_support_shares = false; /** - * Attempts to return a concrete Ingo_Driver instance based on $driver. + * Attempts to return a concrete instance based on $driver. * - * @param string $driver The type of concrete Ingo_Driver subclass to - * return. - * @param array $params A hash containing any additional configuration or - * connection parameters a subclass might need. + * @param string $driver The type of concrete subclass to return. + * @param array $params A hash containing any additional configuration + * or connection parameters a subclass might need. * - * @return mixed The newly created concrete Ingo_Driver instance, or - * false on error. + * @return Ingo_Driver The newly created concrete instance. + * @throws Ingo_Exception */ static public function factory($driver, $params = array()) { - $driver = basename($driver); - $class = 'Ingo_Driver_' . ucfirst($driver); + $class = __CLASS__ . '_' . ucfirst(basename($driver)); - return class_exists($class) - ? new $class($params) - : false; + if (class_exists($class)) { + return new $class($params); + } + + throw new Ingo_Exception('Could not load driver.'); } /** @@ -61,8 +61,8 @@ class Ingo_Driver * * @param string $script The filter script. * - * @return mixed True on success, false if script can't be activated. - * Returns PEAR_Error on error. + * @return boolean True on success, false if script can't be activated. + * @throws Ingo_Exception */ public function setScriptActive($script) { @@ -76,7 +76,8 @@ class Ingo_Driver */ public function supportShares() { - return $this->_support_shares && !empty($_SESSION['ingo']['backend']['shares']); + return ($this->_support_shares && + !empty($_SESSION['ingo']['backend']['shares'])); } } diff --git a/ingo/lib/Driver/Ldap.php b/ingo/lib/Driver/Ldap.php index 5986d9c74..f4ec454e4 100644 --- a/ingo/lib/Driver/Ldap.php +++ b/ingo/lib/Driver/Ldap.php @@ -14,12 +14,12 @@ class Ingo_Driver_Ldap extends Ingo_Driver /** * Constructor. * - * @throws Horde_Exception + * @throws Ingo_Exception */ public function __construct($params = array()) { if (!Horde_Util::extensionExists('ldap')) { - throw new Horde_Exception(_("LDAP support is required but the LDAP module is not available or not loaded.")); + throw new Ingo_Exception(_("LDAP support is required but the LDAP module is not available or not loaded.")); } $default_params = array( @@ -64,12 +64,14 @@ class Ingo_Driver_Ldap extends Ingo_Driver /** * Connect and bind to ldap server. + * + * @throws Ingo_Exception */ protected function _connect() { if (!($ldapcn = @ldap_connect($this->_params['hostspec'], $this->_params['port']))) { - return PEAR::raiseError(_("Connection failure")); + throw new Ingo_Exception(_("Connection failure")); } /* Set the LDAP protocol version. */ @@ -80,39 +82,34 @@ class Ingo_Driver_Ldap extends Ingo_Driver } /* Start TLS if we're using it. */ - if (!empty($this->_params['tls'])) { - if (!@ldap_start_tls($ldapcn)) { - return PEAR::raiseError(sprintf(_("STARTTLS failed: (%s) %s"), - ldap_errno($ldapcn), - ldap_error($ldapcn))); - } + if (!empty($this->_params['tls']) && + !@ldap_start_tls($ldapcn)) { + throw new Ingo_Exception(sprintf(_("STARTTLS failed: (%s) %s"), + ldap_errno($ldapcn), + ldap_error($ldapcn))); } /* Bind to the server. */ if (isset($this->_params['bind_dn'])) { $bind_dn = $this->_substUser($this->_params['bind_dn']); - if (is_a($bind_dn, 'PEAR_Error')) { - return $bind_dn; - } - if (isset($this->_params['bind_password'])) { - $password = $this->_params['bind_password']; - } else { - $password = $this->_params['password']; - } + $password = isset($this->_params['bind_password']) + ? $this->_params['bind_password'] + : $this->_params['password']; - if (!@ldap_bind($ldapcn, $bind_dn, $password)) { - return PEAR::raiseError(sprintf(_("Bind failed: (%s) %s"), - ldap_errno($ldapcn), - ldap_error($ldapcn))); - } - } elseif (!(@ldap_bind($ldapcn))) { - return PEAR::raiseError(sprintf(_("Bind failed: (%s) %s"), - ldap_errno($ldapcn), - ldap_error($ldapcn))); + $bind_success = @ldap_bind($ldapcn, $bind_dn, $password); + } else { + $bind_success = @ldap_bind($ldapcn); } - return $ldapcn; + if ($bind_success) { + return $ldapcn; + } + + + throw new Ingo_Exception(sprintf(_("Bind failed: (%s) %s"), + ldap_errno($ldapcn), + ldap_error($ldapcn))); } /** @@ -121,7 +118,8 @@ class Ingo_Driver_Ldap extends Ingo_Driver * @param resource $ldapcn The connection to the LDAP server. * @param string $userDN Set to the user object's real DN. * - * @return mixed Array of script sources, or PEAR_Error on failure. + * @return array Script sources list. + * @throws Ingo_Exception */ protected function _getScripts($ldapcn, &$userDN) { @@ -132,28 +130,30 @@ class Ingo_Driver_Ldap extends Ingo_Driver $sr = @ldap_search($ldapcn, $this->_params['script_base'], $filter, $attrs); if ($sr === false) { - return PEAR::raiseError(sprintf(_("Error retrieving current script: (%d) %s"), - ldap_errno($ldapcn), - ldap_error($ldapcn))); + throw new Ingo_Exception(sprintf(_("Error retrieving current script: (%d) %s"), + ldap_errno($ldapcn), + ldap_error($ldapcn))); } + if (@ldap_count_entries($ldapcn, $sr) != 1) { - return PEAR::raiseError(sprintf(_("Expected 1 object, got %d."), - ldap_count_entries($ldapcn, $sr))); + throw new Ingo_Exception(sprintf(_("Expected 1 object, got %d."), + ldap_count_entries($ldapcn, $sr))); } + $ent = @ldap_first_entry($ldapcn, $sr); if ($ent === false) { - return PEAR::raiseError(sprintf(_("Error retrieving current script: (%d) %s"), - ldap_errno($ldapcn), - ldap_error($ldapcn))); + throw new Ingo_Exception(sprintf(_("Error retrieving current script: (%d) %s"), + ldap_errno($ldapcn), + ldap_error($ldapcn))); } /* Retrieve the user's DN. */ $v = @ldap_get_dn($ldapcn, $ent); if ($v === false) { @ldap_free_result($sr); - return PEAR::raiseError(sprintf(_("Error retrieving current script: (%d) %s"), - ldap_errno($ldapcn), - ldap_error($ldapcn))); + throw new Ingo_Exception(sprintf(_("Error retrieving current script: (%d) %s"), + ldap_errno($ldapcn), + ldap_error($ldapcn))); } $userDN = $v; @@ -161,9 +161,9 @@ class Ingo_Driver_Ldap extends Ingo_Driver $attrs = @ldap_get_attributes($ldapcn, $ent); @ldap_free_result($sr); if ($attrs === false) { - return PEAR::raiseError(sprintf(_("Error retrieving current script: (%d) %s"), - ldap_errno($ldapcn), - ldap_error($ldapcn))); + throw new Ingo_Exception(sprintf(_("Error retrieving current script: (%d) %s"), + ldap_errno($ldapcn), + ldap_error($ldapcn))); } /* Attribute can be in any case, and can have a ";binary" @@ -186,19 +186,12 @@ class Ingo_Driver_Ldap extends Ingo_Driver * * @param string $script The sieve script. * - * @return mixed True on success, PEAR_Error on error. + * @throws Ingo_Exception */ protected function setScriptActive($script) { $ldapcn = $this->_connect(); - if (is_a($ldapcn, 'PEAR_Error')) { - return $ldapcn; - } - $values = $this->_getScripts($ldapcn, $userDN); - if (is_a($values, 'PEAR_Error')) { - return $values; - } $found = false; foreach ($values as $i => $value) { @@ -212,24 +205,25 @@ class Ingo_Driver_Ldap extends Ingo_Driver break; } } + if (!$found && !empty($script)) { $values[] = $script; } $replace = array(Horde_String::lower($this->_params['script_attribute']) => $values); - if (empty($values)) { - $r = @ldap_mod_del($ldapcn, $userDN, $replace); - } else { - $r = @ldap_mod_replace($ldapcn, $userDN, $replace); - } + $r = empty($values) + ? @ldap_mod_del($ldapcn, $userDN, $replace) + : @ldap_mod_replace($ldapcn, $userDN, $replace); + if (!$r) { - return PEAR::raiseError(sprintf(_("Activating the script for \"%s\" failed: (%d) %s"), - $userDN, - ldap_errno($ldapcn), - ldap_error($ldapcn))); + throw new Ingo_Exception(sprintf(_("Activating the script for \"%s\" failed: (%d) %s"), + $userDN, + ldap_errno($ldapcn), + ldap_error($ldapcn))); } @ldap_close($ldapcn); + return true; } @@ -237,18 +231,13 @@ class Ingo_Driver_Ldap extends Ingo_Driver * Returns the content of the currently active script. * * @return string The complete ruleset of the specified user. + * + * @throws Ingo_Exception */ public function getScript() { $ldapcn = $this->_connect(); - if (is_a($ldapcn, 'PEAR_Error')) { - return $ldapcn; - } - $values = $this->_getScripts($ldapcn, $userDN); - if (is_a($values, 'PEAR_Error')) { - return $values; - } $script = ''; foreach ($values as $value) { diff --git a/ingo/lib/Driver/Sivtest.php b/ingo/lib/Driver/Sivtest.php index 8cc36cf33..fda72d82b 100644 --- a/ingo/lib/Driver/Sivtest.php +++ b/ingo/lib/Driver/Sivtest.php @@ -45,12 +45,12 @@ class Ingo_Driver_Sivtest extends Ingo_Driver /** * Connect to the sieve server. * - * @return mixed True on success, PEAR_Error on false. + * @throws Ingo_Exception; */ protected function _connect() { if (!empty($this->_sieve)) { - return true; + return; } $this->sivtestSocket($this->_params['username'], @@ -68,11 +68,9 @@ class Ingo_Driver_Sivtest extends Ingo_Driver $this->_params['usetls']); $res = $this->_sieve->getError(); - if (is_a($res, 'PEAR_Error')) { + if ($res instanceof PEAR_Error) { unset($this->_sieve); - return $res; - } else { - return true; + throw new Ingo_Exception($res); } } @@ -81,19 +79,15 @@ class Ingo_Driver_Sivtest extends Ingo_Driver * * @param string $script The sieve script. * - * @return mixed True on success. - * Returns PEAR_Error on error. + * @throws Ingo_Exception */ public function setScriptActive($script) { - $res = $this->_connect(); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_connect(); $res = $this->_sieve->haveSpace($this->_params['scriptname'], strlen($script)); - if (is_a($res, 'PEAR_ERROR')) { - return $res; + if ($res instanceof PEAR_Error) { + throw new Ingo_Exception($res); } return $this->_sieve->installScript($this->_params['scriptname'], $script, true); @@ -103,13 +97,11 @@ class Ingo_Driver_Sivtest extends Ingo_Driver * Returns the content of the currently active script. * * @return string The complete ruleset of the specified user. + * @throws Ingo Exception */ public function getScript() { - $res = $this->_connect(); - if (is_a($res, 'PEAR_Error')) { - return $res; - } + $this->_connect(); return $this->_sieve->getScript($this->_sieve->getActive()); } @@ -122,6 +114,7 @@ class Ingo_Driver_Sivtest extends Ingo_Driver * @param string $hostspec The hostspec. * * @return TODO + * @throws Ingo_Exception */ public function sivtestSocket($username, $password, $hostspec) { @@ -160,7 +153,7 @@ class Ingo_Driver_Sivtest extends Ingo_Driver } $socket = new Net_Socket(); $error = $socket->connect($domain_socket, 0, true, 30); - if (!is_a($error, 'PEAR_Error')) { + if (!($error instanceof PEAR_Error)) { break; } @@ -169,22 +162,22 @@ class Ingo_Driver_Sivtest extends Ingo_Driver } if (!empty($error_return)) { - return PEAR::raiseError(_($error_return)); + throw new Ingo_Exception($error_return); } $status = $socket->getStatus(); - if (is_a($status, 'PEAR_Error') || $status['eof']) { - return PEAR::raiseError(_('Failed to write to socket: (connection lost!)')); + if ($status instanceof PEAR_Error || $status['eof']) { + throw new Ingo_Exception(_("Failed to write to socket: (connection lost!)")); } $error = $socket->writeLine("CAPABILITY"); - if (is_a($error, 'PEAR_Error')) { - return PEAR::raiseError(_('Failed to write to socket: ' . $error->getMessage())); + if ($error instanceof PEAR_Error) { + throw new Ingo_Exception(_("Failed to write to socket: " . $error->getMessage())); } $result = $socket->readLine(); - if (is_a($result, 'PEAR_Error')) { - return PEAR::raiseError(_('Failed to read from socket: ' . $error->getMessage())); + if ($result instanceof PEAR_Error) { + throw new Ingo_Exception(_("Failed to read from socket: " . $error->getMessage())); } if (preg_match('|^bye \(referral "(sieve://)?([^"]+)|i', diff --git a/ingo/lib/Driver/Timsieved.php b/ingo/lib/Driver/Timsieved.php index 92867b839..e7c3af42d 100644 --- a/ingo/lib/Driver/Timsieved.php +++ b/ingo/lib/Driver/Timsieved.php @@ -42,6 +42,8 @@ class Ingo_Driver_Timsieved extends Ingo_Driver /** * Connects to the sieve server. + * + * @throws Ingo_Exception */ protected function _connect() { @@ -49,11 +51,10 @@ class Ingo_Driver_Timsieved extends Ingo_Driver return; } - if (empty($this->_params['admin'])) { - $auth = $this->_params['username']; - } else { - $auth = $this->_params['admin']; - } + $auth = empty($this->_params['admin']) + ? $this->_params['username'] + : $this->_params['admin']; + $this->_sieve = new Net_Sieve($auth, $this->_params['password'], $this->_params['hostspec'], @@ -65,9 +66,9 @@ class Ingo_Driver_Timsieved extends Ingo_Driver $this->_params['usetls']); $res = $this->_sieve->getError(); - if (is_a($res, 'PEAR_Error')) { + if ($res instanceof PEAR_Error) { unset($this->_sieve); - return $res; + throw new Ingo_Exception($res); } if (!empty($this->_params['debug'])) { @@ -91,23 +92,20 @@ class Ingo_Driver_Timsieved extends Ingo_Driver * * @param string $script The sieve script. * - * @return mixed True on success, PEAR_Error on error. + * @return mixed True on success. + * @throws Ingo_Exception */ public function setScriptActive($script) { $res = $this->_connect(); - if (is_a($res, 'PEAR_Error')) { - return $res; - } if (!strlen($script)) { return $this->_sieve->setActive(''); } - $res = $this->_sieve->haveSpace($this->_params['scriptname'], - strlen($script)); - if (is_a($res, 'PEAR_ERROR')) { - return $res; + $res = $this->_sieve->haveSpace($this->_params['scriptname'], strlen($script)); + if ($res instanceof PEAR_Error) { + throw new Ingo_Exception($res); } return $this->_sieve->installScript($this->_params['scriptname'], @@ -118,18 +116,16 @@ class Ingo_Driver_Timsieved extends Ingo_Driver * Returns the content of the currently active script. * * @return string The complete ruleset of the specified user. + * @throws Ingo_Exception */ public function getScript() { $res = $this->_connect(); - if (is_a($res, 'PEAR_Error')) { - return $res; - } $active = $this->_sieve->getActive(); - if (empty($active)) { - return ''; - } - return $this->_sieve->getScript($active); + + return empty($active) + ? '' + : $this->_sieve->getScript($active); } } diff --git a/ingo/lib/Driver/Vfs.php b/ingo/lib/Driver/Vfs.php index 262ef693f..83bc49d70 100644 --- a/ingo/lib/Driver/Vfs.php +++ b/ingo/lib/Driver/Vfs.php @@ -37,50 +37,46 @@ class Ingo_Driver_Vfs extends Ingo_Driver /** * Sets a script running on the backend. * - * @param string $script The filter script + * @param string $script The filter script. * - * @return mixed True on success, or PEAR_Error on failure. + * @return mixed True on success. + * @throws Ingo_Exception */ public function setScriptActive($script) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); - if (empty($script)) { - $result = $this->_vfs->deleteFile($this->_params['vfs_path'], $this->_params['filename']); - } else { - $result = $this->_vfs->writeData($this->_params['vfs_path'], $this->_params['filename'], $script, true); - } - if (is_a($result, 'PEAR_Error')) { - return $result; + $result = empty($script) + ? $this->_vfs->deleteFile($this->_params['vfs_path'], $this->_params['filename']) + : $this->_vfs->writeData($this->_params['vfs_path'], $this->_params['filename'], $script, true); + if ($result instanceof PEAR_Error) { + throw new Ingo_Exception($result); } if (isset($this->_params['file_perms']) && !empty($script)) { $result = $this->_vfs->changePermissions($this->_params['vfs_path'], $this->_params['filename'], $this->_params['file_perms']); - if (is_a($result, 'PEAR_Error')) { - return $result; + if ($result instanceof PEAR_Error) { + throw new Ingo_Exception($result); } } // Get the backend; necessary if a .forward is needed for // procmail. $backend = Ingo::getBackend(); - if ($backend['script'] == 'procmail' && isset($backend['params']['forward_file']) && isset($backend['params']['forward_string'])) { - if (empty($script)) { - $result = $this->_vfs->deleteFile($this->_params['vfs_forward_path'], $backend['params']['forward_file']); - } else { - $result = $this->_vfs->writeData($this->_params['vfs_forward_path'], $backend['params']['forward_file'], $backend['params']['forward_string'], true); - } - if (is_a($result, 'PEAR_Error')) { - return $result; + if (($backend['script'] == 'procmail') && + isset($backend['params']['forward_file']) && + isset($backend['params']['forward_string'])) { + $result = empty($script) + ? $this->_vfs->deleteFile($this->_params['vfs_forward_path'], $backend['params']['forward_file']) + : $this->_vfs->writeData($this->_params['vfs_forward_path'], $backend['params']['forward_file'], $backend['params']['forward_string'], true); + if ($result instanceof PEAR_Error) { + throw new Ingo_Exception($result); } if (isset($this->_params['file_perms']) && !empty($script)) { $result = $this->_vfs->changePermissions($this->_params['vfs_forward_path'], $backend['params']['forward_file'], $this->_params['file_perms']); - if (is_a($result, 'PEAR_Error')) { - return $result; + if ($result instanceof PEAR_Error) { + throw new Ingo_Exception($result); } } } @@ -92,20 +88,18 @@ class Ingo_Driver_Vfs extends Ingo_Driver * Returns the content of the currently active script. * * @return string The complete ruleset of the specified user. + * @throws Ingo_Exception */ public function getScript() { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_connect(); return $this->_vfs->read($this->_params['vfs_path'], $this->_params['filename']); } /** * Connect to the VFS server. * - * @return boolean True on success, PEAR_Error on false. + * @throws Ingo_Exception */ protected function _connect() { @@ -130,13 +124,11 @@ class Ingo_Driver_Vfs extends Ingo_Driver return true; } - $this->_vfs = &VFS::singleton($this->_params['vfstype'], $this->_params); - if (is_a($this->_vfs, 'PEAR_Error')) { - $error = $this->_vfs; - $this->_vfs = null; - return $error; - } else { - return true; + $this->_vfs = VFS::singleton($this->_params['vfstype'], $this->_params); + if ($this->_vfs instanceof PEAR_Error) { + $error = new Ingo_Exception($this->_vfs); + unset($this->_vfs); + throw new Ingo_Exception($error); } } diff --git a/ingo/lib/Exception.php b/ingo/lib/Exception.php new file mode 100644 index 000000000..a8df59f6c --- /dev/null +++ b/ingo/lib/Exception.php @@ -0,0 +1,15 @@ + + * @package Ingo + */ +class Ingo_Exception extends Horde_Exception +{ +} diff --git a/ingo/lib/Ingo.php b/ingo/lib/Ingo.php index cc8c6cdf0..40588f422 100644 --- a/ingo/lib/Ingo.php +++ b/ingo/lib/Ingo.php @@ -22,13 +22,75 @@ class Ingo */ const USER_HEADER = '++USER_HEADER++'; - /* getMenu() cache. */ + /** + * getMenu() cache. + * + * @var string + */ static private $_menuCache = null; - /* hasSharePermission() cache. */ + /** + * hasSharePermission() cache. + * + * @var integer + */ static private $_shareCache = null; /** + * Create an ingo session. + * + * Creates the $ingo session variable with the following entries: + * 'backend' (array) - The backend configuration to use. + * 'change' (integer) - The timestamp of the last time the rules were + * altered. + * 'storage' (array) - Used by Ingo_Storage:: for caching data. + * 'script_categories' (array) - The list of available categories for the + * Ingo_Script driver in use. + * 'script_generate' (boolean) - Is the Ingo_Script::generate() call + * available? + * + * @throws Ingo_Exception + */ + static public function createSession() + { + if (isset($_SESSION['ingo'])) { + return; + } + + global $prefs; + + $_SESSION['ingo'] = array( + 'backend' => Ingo::getBackend(), + 'change' => 0, + 'storage' => array() + ); + + $ingo_script = Ingo::loadIngoScript(); + $_SESSION['ingo']['script_generate'] = $ingo_script->generateAvailable(); + + /* Disable categories as specified in preferences */ + $disabled = array(); + if ($prefs->isLocked('blacklist')) { + $disabled[] = Ingo_Storage::ACTION_BLACKLIST; + } + if ($prefs->isLocked('whitelist')) { + $disabled[] = Ingo_Storage::ACTION_WHITELIST; + } + if ($prefs->isLocked('vacation')) { + $disabled[] = Ingo_Storage::ACTION_VACATION; + } + if ($prefs->isLocked('forward')) { + $disabled[] = Ingo_Storage::ACTION_FORWARD; + } + if ($prefs->isLocked('spam')) { + $disabled[] = Ingo_Storage::ACTION_SPAM; + } + + /* Set the list of categories this driver supports. */ + $_SESSION['ingo']['script_categories'] = array_merge($ingo_script->availableActions(), array_diff($ingo_script->availableCategories(), $disabled)); + } + + /** * Generates a folder widget. * If an application is available that provides a folderlist method * then a <select> input is created else a simple text field @@ -153,25 +215,28 @@ class Ingo */ static public function activateScript($script, $deactivate = false) { - global $notification; - $driver = self::getDriver(); - $res = $driver->setScriptActive($script); - if (is_a($res, 'PEAR_Error')) { + + try { + $res = $driver->setScriptActive($script); + } catch (Ingo_Exception $e) { $msg = ($deactivate) ? _("There was an error deactivating the script.") : _("There was an error activating the script."); - $notification->push($msg . ' ' . _("The driver said: ") . $res->getMessage(), 'horde.error'); + $GLOBALS['notification']->push($msg . ' ' . _("The driver said: ") . $e->getMessage(), 'horde.error'); + return false; + } + + if ($res === false) { return false; - } elseif ($res === true) { - $msg = ($deactivate) - ? _("Script successfully deactivated.") - : _("Script successfully activated."); - $notification->push($msg, 'horde.success'); - return true; } - return false; + $msg = ($deactivate) + ? _("Script successfully deactivated.") + : _("Script successfully activated."); + $GLOBALS['notification']->push($msg, 'horde.success'); + + return true; } /** @@ -181,8 +246,7 @@ class Ingo */ static public function getScript() { - $driver = self::getDriver(); - return $driver->getScript(); + return self::getDriver()->getScript(); } /** @@ -190,16 +254,15 @@ class Ingo */ static public function updateScript() { - global $notification; - if ($_SESSION['ingo']['script_generate']) { - $ingo_script = self::loadIngoScript(); - if (!$ingo_script) { - $notification->push(_("Script not updated."), 'horde.error'); - } else { + try { + $ingo_script = self::loadIngoScript(); + /* Generate and activate the script. */ $script = $ingo_script->generate(); self::activateScript($script); + } catch (Ingo_Exception $e) { + $GLOBALS['notification']->push(_("Script not updated."), 'horde.error'); } } } @@ -213,7 +276,7 @@ class Ingo * single value or an array of multiple values. * * @return array The backend entry. - * @throws Horde_Exception + * @throws Ingo_Exception */ static public function getBackend() { @@ -243,16 +306,16 @@ class Ingo /* Check for valid backend configuration. */ if (!isset($backend)) { - throw new Horde_Exception(_("No backend configured for this host")); + throw new Ingo_Exception(_("No backend configured for this host")); } $backends[$backend]['id'] = $name; $backend = $backends[$backend]; if (empty($backend['script'])) { - throw new Horde_Exception(sprintf(_("No \"%s\" element found in backend configuration."), 'script')); + throw new Ingo_Exception(sprintf(_("No \"%s\" element found in backend configuration."), 'script')); } elseif (empty($backend['driver'])) { - throw new Horde_Exception(sprintf(_("No \"%s\" element found in backend configuration."), 'driver')); + throw new Ingo_Exception(sprintf(_("No \"%s\" element found in backend configuration."), 'driver')); } /* Make sure the 'params' entry exists. */ @@ -267,23 +330,19 @@ class Ingo * Loads a Ingo_Script:: backend and checks for errors. * * @return Ingo_Script Script object on success. - * @throws Horde_Exception + * @throws Ingo_Exception */ static public function loadIngoScript() { - $ingo_script = Ingo_Script::factory($_SESSION['ingo']['backend']['script'], - isset($_SESSION['ingo']['backend']['scriptparams']) ? $_SESSION['ingo']['backend']['scriptparams'] : array()); - if (is_a($ingo_script, 'PEAR_Error')) { - throw new Horde_Exception($ingo_script); - } - - return $ingo_script; + return Ingo_Script::factory($_SESSION['ingo']['backend']['script'], + isset($_SESSION['ingo']['backend']['scriptparams']) ? $_SESSION['ingo']['backend']['scriptparams'] : array()); } /** * Returns an instance of the configured driver. * * @return Ingo_Driver The configured driver. + * @throws Ingo_Exception */ static public function getDriver() { @@ -320,7 +379,7 @@ class Ingo $permission = Horde_Perms::SHOW) { $rulesets = $GLOBALS['ingo_shares']->listShares(Horde_Auth::getAuth(), $permission, $owneronly ? Horde_Auth::getAuth() : null); - if (is_a($rulesets, 'PEAR_Error')) { + if ($rulesets instanceof PEAR_Error) { Horde::logMessage($rulesets, __FILE__, __LINE__, PEAR_LOG_ERR); return array(); } diff --git a/ingo/lib/Script.php b/ingo/lib/Script.php index d0b01ee4d..b64b2c1d6 100644 --- a/ingo/lib/Script.php +++ b/ingo/lib/Script.php @@ -103,19 +103,19 @@ class Ingo_Script protected $_scriptfile = false; /** - * Attempts to return a concrete Ingo_Script instance based on $script. + * Attempts to return a concrete instance based on $script. * - * @param string $script The type of Ingo_Script subclass to return. - * @param array $params Hash containing additional paramters to be passed - * to the subclass' constructor. + * @param string $script The type of subclass to return. + * @param array $params Hash containing additional paramters to be + * passed to the subclass' constructor. * - * @return Ingo_Script The newly created concrete Ingo_Script instance, or - * false on error. + * @return Ingo_Script The newly created concrete instance. + * @throws Ingo_Exception */ static public function factory($script, $params = array()) { $script = Horde_String::ucfirst(basename($script)); - $class = 'Ingo_Script_' . $script; + $class = __CLASS__ . '_' . $script; if (!isset($params['spam_compare'])) { $params['spam_compare'] = $GLOBALS['conf']['spam']['compare']; @@ -140,9 +140,11 @@ class Ingo_Script } } - return class_exists($class) - ? new $class($params) - : PEAR::raiseError(sprintf(_("Unable to load the definition of %s."), $class)); + if (class_exists($class)) { + return new $class($params); + } + + throw new Ingo_Exception(sprintf(_("Unable to load the definition of %s."), $class)); } /** @@ -154,10 +156,6 @@ class Ingo_Script { $this->_params = $params; - if (!isset($GLOBALS['registry'])) { - return; - } - /* Determine if ingo should handle the blacklist. */ $key = array_search(Ingo_Storage::ACTION_BLACKLIST, $this->_categories); if ($key !== false && ($GLOBALS['registry']->hasMethod('mail/blacklistFrom') != 'ingo')) { @@ -268,8 +266,6 @@ class Ingo_Script /** * Returns a script previously generated with generate(). * - * @abstract - * * @return string The script. */ public function toCode() @@ -291,8 +287,6 @@ class Ingo_Script * Generates the script to do the filtering specified in * the rules. * - * @abstract - * * @return string The script. */ public function generate() @@ -313,8 +307,6 @@ class Ingo_Script /** * Perform the filtering specified in the rules. * - * @abstract - * * @param array $params The parameter array. * * @return boolean True if filtering performed, false if not. @@ -340,8 +332,6 @@ class Ingo_Script * function to be called from within Ingo ensuring that all necessary * parameters are set. * - * @abstract - * * @return boolean See perform(). */ public function apply() diff --git a/ingo/lib/Script/Imap.php b/ingo/lib/Script/Imap.php index e0e8e4a55..a8a1425ed 100644 --- a/ingo/lib/Script/Imap.php +++ b/ingo/lib/Script/Imap.php @@ -116,7 +116,7 @@ class Ingo_Script_Imap extends Ingo_Script } /* Grab the rules list. */ - $filters = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FILTERS); + $filters = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FILTERS); /* Parse through the rules, one-by-one. */ foreach ($filters->getFilterList() as $rule) { diff --git a/ingo/lib/Script/Maildrop.php b/ingo/lib/Script/Maildrop.php index 91362f8f0..3f3909cbd 100644 --- a/ingo/lib/Script/Maildrop.php +++ b/ingo/lib/Script/Maildrop.php @@ -10,23 +10,19 @@ * @author Matt Weyland * @package Ingo */ +class Ingo_Script_Maildrop extends Ingo_Script +{ -/** - * Additional storage action since maildrop does not support the - * "c-flag" as in procmail. - */ -define('MAILDROP_STORAGE_ACTION_STOREANDFORWARD', 100); - -/** - */ -class Ingo_Script_Maildrop extends Ingo_Script { + /* Additional storage action since maildrop does not support the + * "c-flag" as in procmail. */ + const MAILDROP_STORAGE_ACTION_STOREANDFORWARD = 100; /** * The list of actions allowed (implemented) for this driver. * * @var array */ - var $_actions = array( + protected $_actions = array( Ingo_Storage::ACTION_KEEP, Ingo_Storage::ACTION_MOVE, Ingo_Storage::ACTION_DISCARD, @@ -40,7 +36,7 @@ class Ingo_Script_Maildrop extends Ingo_Script { * * @var array */ - var $_categories = array( + protected $_categories = array( Ingo_Storage::ACTION_BLACKLIST, Ingo_Storage::ACTION_WHITELIST, Ingo_Storage::ACTION_VACATION, @@ -53,7 +49,7 @@ class Ingo_Script_Maildrop extends Ingo_Script { * * @var array */ - var $_types = array( + protected $_types = array( Ingo_Storage::TYPE_HEADER, ); @@ -62,7 +58,7 @@ class Ingo_Script_Maildrop extends Ingo_Script { * * @var array */ - var $_tests = array( + protected $_tests = array( 'contains', 'not contain', 'is', 'not is', 'begins with','not begins with', @@ -80,35 +76,35 @@ class Ingo_Script_Maildrop extends Ingo_Script { * * @var boolean */ - var $_casesensitive = true; + protected $_casesensitive = true; /** * Does the driver support the stop-script option? * * @var boolean */ - var $_supportStopScript = false; + protected $_supportStopScript = false; /** * Does the driver require a script file to be generated? * * @var boolean */ - var $_scriptfile = true; + protected $_scriptfile = true; /** * The recipes that make up the code. * * @var array */ - var $_recipes = array(); + protected $_recipes = array(); /** * Returns a script previously generated with generate(). * * @return string The maildrop script. */ - function toCode() + public function toCode() { $code = ''; foreach ($this->_recipes as $item) { @@ -123,17 +119,17 @@ class Ingo_Script_Maildrop extends Ingo_Script { * * @return string The maildrop script. */ - function generate() + public function generate() { $filters = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FILTERS); - $this->addItem(new Maildrop_Comment(_("maildrop script generated by Ingo") . ' (' . date('F j, Y, g:i a') . ')')); + $this->addItem(new Ingo_Script_Maildrop_Comment(_("maildrop script generated by Ingo") . ' (' . date('F j, Y, g:i a') . ')')); /* Add variable information, if present. */ if (!empty($this->_params['variables']) && is_array($this->_params['variables'])) { foreach ($this->_params['variables'] as $key => $val) { - $this->addItem(new Maildrop_Variable(array('name' => $key, 'value' => $val))); + $this->addItem(new Ingo_Script_Maildrop_Variable(array('name' => $key, 'value' => $val))); } } @@ -162,11 +158,11 @@ class Ingo_Script_Maildrop extends Ingo_Script { default: if (in_array($filter['action'], $this->_actions)) { /* Create filter if using AND. */ - $recipe = new Maildrop_Recipe($filter, $this->_params); + $recipe = new Ingo_Script_Maildrop_Recipe($filter, $this->_params); foreach ($filter['conditions'] as $condition) { $recipe->addCondition($condition); } - $this->addItem(new Maildrop_Comment($filter['name'], !empty($filter['disable']), true)); + $this->addItem(new Ingo_Script_Maildrop_Comment($filter['name'], !empty($filter['disable']), true)); $this->addItem($recipe); } } @@ -181,23 +177,25 @@ class Ingo_Script_Maildrop extends Ingo_Script { * * @param boolean $disable Disable the blacklist? */ - function generateBlacklist($disable = false) + public function generateBlacklist($disable = false) { - $blacklist = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_BLACKLIST); + $blacklist = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_BLACKLIST); $bl_addr = $blacklist->getBlacklist(); $bl_folder = $blacklist->getBlacklistFolder(); - $bl_type = (empty($bl_folder)) ? Ingo_Storage::ACTION_DISCARD : Ingo_Storage::ACTION_MOVE; + $bl_type = empty($bl_folder) + ? Ingo_Storage::ACTION_DISCARD + : Ingo_Storage::ACTION_MOVE; if (!empty($bl_addr)) { - $this->addItem(new Maildrop_Comment(_("Blacklisted Addresses"), $disable, true)); + $this->addItem(new Ingo_Script_Maildrop_Comment(_("Blacklisted Addresses"), $disable, true)); $params = array('action-value' => $bl_folder, 'action' => $bl_type, 'disable' => $disable); foreach ($bl_addr as $address) { if (!empty($address)) { - $recipe = new Maildrop_Recipe($params, $this->_params); + $recipe = new Ingo_Script_Maildrop_Recipe($params, $this->_params); $recipe->addCondition(array('field' => 'From', 'value' => $address)); $this->addItem($recipe); } @@ -211,16 +209,16 @@ class Ingo_Script_Maildrop extends Ingo_Script { * * @param boolean $disable Disable the whitelist? */ - function generateWhitelist($disable = false) + public function generateWhitelist($disable = false) { - $whitelist = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_WHITELIST); + $whitelist = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_WHITELIST); $wl_addr = $whitelist->getWhitelist(); if (!empty($wl_addr)) { - $this->addItem(new Maildrop_Comment(_("Whitelisted Addresses"), $disable, true)); + $this->addItem(new Ingo_Script_Maildrop_Comment(_("Whitelisted Addresses"), $disable, true)); foreach ($wl_addr as $address) { if (!empty($address)) { - $recipe = new Maildrop_Recipe(array('action' => Ingo_Storage::ACTION_KEEP, 'disable' => $disable), $this->_params); + $recipe = new Ingo_Script_Maildrop_Recipe(array('action' => Ingo_Storage::ACTION_KEEP, 'disable' => $disable), $this->_params); $recipe->addCondition(array('field' => 'From', 'value' => $address)); $this->addItem($recipe); } @@ -233,20 +231,20 @@ class Ingo_Script_Maildrop extends Ingo_Script { * * @param boolean $disable Disable forwarding? */ - function generateForward($disable = false) + public function generateForward($disable = false) { - $forward = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FORWARD); + $forward = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FORWARD); $addresses = $forward->getForwardAddresses(); if (!empty($addresses)) { - $this->addItem(new Maildrop_Comment(_("Forwards"), $disable, true)); + $this->addItem(new Ingo_Script_Maildrop_Comment(_("Forwards"), $disable, true)); $params = array('action' => Ingo_Storage::ACTION_FORWARD, 'action-value' => $addresses, 'disable' => $disable); if ($forward->getForwardKeep()) { - $params['action'] = MAILDROP_STORAGE_ACTION_STOREANDFORWARD; + $params['action'] = self::MAILDROP_STORAGE_ACTION_STOREANDFORWARD; } - $recipe = new Maildrop_Recipe($params, $this->_params); + $recipe = new Ingo_Script_Maildrop_Recipe($params, $this->_params); $recipe->addCondition(array('field' => 'From', 'value' => '')); $this->addItem($recipe); } @@ -257,9 +255,9 @@ class Ingo_Script_Maildrop extends Ingo_Script { * * @param boolean $disable Disable forwarding? */ - function generateVacation($disable = false) + public function generateVacation($disable = false) { - $vacation = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_VACATION); + $vacation = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_VACATION); $addresses = $vacation->getVacationAddresses(); $actionval = array('addresses' => $addresses, 'subject' => $vacation->getVacationSubject(), @@ -271,23 +269,24 @@ class Ingo_Script_Maildrop extends Ingo_Script { 'end' => $vacation->getVacationEnd()); if (!empty($addresses)) { - $this->addItem(new Maildrop_Comment(_("Vacation"), $disable, true)); + $this->addItem(new Ingo_Script_Maildrop_Comment(_("Vacation"), $disable, true)); $params = array('action' => Ingo_Storage::ACTION_VACATION, 'action-value' => $actionval, 'disable' => $disable); - $recipe = new Maildrop_Recipe($params, $this->_params); + $recipe = new Ingo_Script_Maildrop_Recipe($params, $this->_params); $this->addItem($recipe); } } /** - * Generates the maildrop script to handle spam as identified by SpamAssassin + * Generates the maildrop script to handle spam as identified by + * SpamAssassin. * * @param boolean $disable Disable the spam-filter? */ - function generateSpamfilter($disable = false) + public function generateSpamfilter($disable = false) { - $spam = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_SPAM); + $spam = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_SPAM); if ($spam == false) { return; } @@ -295,12 +294,12 @@ class Ingo_Script_Maildrop extends Ingo_Script { $spam_folder = $spam->getSpamFolder(); $spam_action = (empty($spam_folder)) ? Ingo_Storage::ACTION_DISCARD : Ingo_Storage::ACTION_MOVE; - $this->addItem(new Maildrop_Comment(_("Spam Filter"), $disable, true)); + $this->addItem(new Ingo_Script_Maildrop_Comment(_("Spam Filter"), $disable, true)); $params = array('action-value' => $spam_folder, 'action' => $spam_action, 'disable' => $disable); - $recipe = new Maildrop_Recipe($params, $this->_params); + $recipe = new Ingo_Script_Maildrop_Recipe($params, $this->_params); if ($this->_params['spam_compare'] == 'numeric') { $recipe->addCondition(array('match' => 'greater than or equal to', 'field' => $this->_params['spam_header'], @@ -320,440 +319,9 @@ class Ingo_Script_Maildrop extends Ingo_Script { * @param object $item The item to add to the recipe list. * The object should have a generate() function. */ - function addItem($item) + public function addItem($item) { $this->_recipes[] = $item; } } - -/** - * The Maildrop_Comment:: class represents a maildrop comment. This is - * a pretty simple class, but it makes the code in Ingo_Script_Maildrop:: - * cleaner as it provides a generate() function and can be added to the - * recipe list the same way as a recipe can be. - * - * @author Matt Weyland - * @package Ingo - */ -class Maildrop_Comment { - - /** - * The comment text. - * - * @var string - */ - var $_comment = ''; - - /** - * Constructs a new maildrop comment. - * - * @param string $comment Comment to be generated. - * @param boolean $disable Output 'DISABLED' comment? - * @param boolean $header Output a 'header' comment? - */ - function Maildrop_Comment($comment, $disable = false, $header = false) - { - if ($disable) { - $comment = _("DISABLED: ") . $comment; - } - - if ($header) { - $this->_comment .= "##### $comment #####"; - } else { - $this->_comment .= "# $comment"; - } - } - - /** - * Returns the comment stored by this object. - * - * @return string The comment stored by this object. - */ - function generate() - { - return $this->_comment; - } - -} - -/** - * The Maildrop_Recipe:: class represents a maildrop recipe. - * - * @author Matt Weyland - * @package Ingo - */ -class Maildrop_Recipe { - - var $_action = array(); - var $_conditions = array(); - var $_disable = ''; - var $_flags = ''; - var $_params = array(); - var $_combine = ''; - var $_valid = true; - - var $_operators = array( - 'less than' => '<', - 'less than or equal to' => '<=', - 'equal' => '==', - 'not equal' => '!=', - 'greater than' => '>', - 'greater than or equal to' => '>=', - ); - - /** - * Constructs a new maildrop recipe. - * - * @param array $params Array of parameters. - * REQUIRED FIELDS: - * 'action' - * OPTIONAL FIELDS: - * 'action-value' (only used if the - * 'action' requires it) - * @param array $scriptparams Array of parameters passed to - * Ingo_Script_Maildrop::. - */ - function Maildrop_Recipe($params = array(), $scriptparams = array()) - { - $this->_disable = !empty($params['disable']); - $this->_params = $scriptparams; - $this->_action[] = 'exception {'; - - switch ($params['action']) { - case Ingo_Storage::ACTION_KEEP: - $this->_action[] = ' to "${DEFAULT}"'; - break; - - case Ingo_Storage::ACTION_MOVE: - $this->_action[] = ' to ' . $this->maildropPath($params['action-value']); - break; - - case Ingo_Storage::ACTION_DISCARD: - $this->_action[] = ' exit'; - break; - - case Ingo_Storage::ACTION_REDIRECT: - $this->_action[] = ' to "! ' . $params['action-value'] . '"'; - break; - - case Ingo_Storage::ACTION_REDIRECTKEEP: - $this->_action[] = ' cc "! ' . $params['action-value'] . '"'; - $this->_action[] = ' to "${DEFAULT}"'; - break; - - case Ingo_Storage::ACTION_REJECT: - $this->_action[] = ' EXITCODE=77'; # EX_NOPERM (permanent failure) - $this->_action[] = ' echo "5.7.1 ' . $params['action-value'] . '"'; - $this->_action[] = ' exit'; - break; - - case Ingo_Storage::ACTION_VACATION: - $from = ''; - foreach ($params['action-value']['addresses'] as $address) { - $from = $address; - } - - /** - * @TODO - * - * Exclusion and listfilter - */ - $exclude = ''; - foreach ($params['action-value']['excludes'] as $address) { - $exclude .= $address . ' '; - } - - $start = strftime($params['action-value']['start']); - if ($start === false) { - $start = 0; - } - $end = strftime($params['action-value']['end']); - if ($end === false) { - $end = 0; - } - $days = strftime($params['action-value']['days']); - if ($days === false) { - // Set to same value as $_days in ingo/lib/Storage.php - $days = 7; - } - - // Writing vacation.msg file - $reason = Horde_Mime::encode($params['action-value']['reason'], $scriptparams['charset']); - $driver = Ingo::getDriver(); - $driver->_connect(); - $result = $driver->_vfs->writeData($driver->_params['vfs_path'], 'vacation.msg', $reason, true); - - // Rule : Do not send responses to bulk or list messages - if ($params['action-value']['ignorelist'] == 1) { - $params['combine'] = Ingo_Storage::COMBINE_ALL; - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Precedence: (bulk|list|junk)/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Return-Path:.*<#@\[\]>/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Return-Path:.*<>/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^From:.*MAILER-DAEMON/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^X-ClamAV-Notice-Flag: *YES/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Content-Type:.*message\/delivery-status/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Delivery Status Notification/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Undelivered Mail Returned to Sender/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Delivery failure/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Message delay/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Mail Delivery Subsystem/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Mail System Error.*Returned Mail/')); - $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^X-Spam-Flag: YES/ ')); - } else { - $this->addCondition(array('field' => 'From', 'value' => '')); - } - - // Rule : Start/End of vacation - if (($start != 0) && ($end !== 0)) { - $this->_action[] = ' flock "vacationprocess.lock" {'; - $this->_action[] = ' current_time=time'; - $this->_action[] = ' if ( \ '; - $this->_action[] = ' ($current_time >= ' . $start . ') && \ '; - $this->_action[] = ' ($current_time <= ' . $end . ')) '; - $this->_action[] = ' {'; - } - $this->_action[] = " cc \"| mailbot -D " . $params['action-value']['days'] . " -c '" . $scriptparams['charset'] . "' -t \$HOME/vacation.msg -d \$HOME/vacation -A 'From: $from' -s '" . Horde_Mime::encode($params['action-value']['subject'], $scriptparams['charset']) . "' /usr/sbin/sendmail -t \""; - if (($start != 0) && ($end !== 0)) { - $this->_action[] = ' }'; - $this->_action[] = ' }'; - } - - break; - - case Ingo_Storage::ACTION_FORWARD: - case MAILDROP_STORAGE_ACTION_STOREANDFORWARD: - foreach ($params['action-value'] as $address) { - if (!empty($address)) { - $this->_action[] = ' cc "! ' . $address . '"'; - } - } - - /* The 'to' must be the last action, because maildrop - * stops processing after it. */ - if ($params['action'] == MAILDROP_STORAGE_ACTION_STOREANDFORWARD) { - $this->_action[] = ' to "${DEFAULT}"'; - } else { - $this->_action[] = ' exit'; - } - break; - - default: - $this->_valid = false; - break; - } - - $this->_action[] = '}'; - - if (isset($params['combine']) && - ($params['combine'] == Ingo_Storage::COMBINE_ALL)) { - $this->_combine = '&& '; - } else { - $this->_combine = '|| '; - } - } - - /** - * Adds a flag to the recipe. - * - * @param string $flag String of flags to append to the current flags. - */ - function addFlag($flag) - { - $this->_flags .= $flag; - } - - /** - * Adds a condition to the recipe. - * - * @param optonal array $condition Array of parameters. Required keys - * are 'field' and 'value'. 'case' is - * an optional keys. - */ - function addCondition($condition = array()) - { - $flag = (!empty($condition['case'])) ? 'D' : ''; - if (empty($this->_conditions)) { - $this->addFlag($flag); - } - - $string = ''; - $extra = ''; - - $match = (isset($condition['match'])) ? $condition['match'] : null; - // negate tests starting with 'not ', except 'not equals', which simply uses the != operator - if ($match != 'not equal' && substr($match, 0, 4) == 'not ') { - $string .= '! '; - } - - // convert 'field' to PCRE pattern matching - if (strpos($condition['field'], ',') == false) { - $string .= '/^' . $condition['field'] . ':\\s*'; - } else { - $string .= '/^(' . str_replace(',', '|', $condition['field']) . '):\\s*'; - } - - switch ($match) { - case 'not regex': - case 'regex': - $string .= $condition['value'] . '/:h'; - break; - - case 'filter': - $string = $condition['value']; - break; - - case 'exists': - case 'not exist': - // Just run a match for the header name - $string .= '/:h'; - break; - - case 'less than or equal to': - case 'less than': - case 'equal': - case 'not equal': - case 'greater than or equal to': - case 'greater than': - $string .= '(\d+(\.\d+)?)/:h'; - $extra = ' && $MATCH1 ' . $this->_operators[$match] . ' ' . (int)$condition['value']; - break; - - case 'begins with': - case 'not begins with': - $string .= preg_quote($condition['value'], '/') . '/:h'; - break; - - case 'ends with': - case 'not ends with': - $string .= '.*' . preg_quote($condition['value'], '/') . '$/:h'; - break; - - case 'is': - case 'not is': - $string .= preg_quote($condition['value'], '/') . '$/:h'; - break; - - case 'matches': - case 'not matches': - $string .= str_replace(array('\\*', '\\?'), array('.*', '.'), preg_quote($condition['value'], '/') . '$') . '/:h'; - break; - - case 'contains': - case 'not contain': - default: - $string .= '.*' . preg_quote($condition['value'], '/') . '/:h'; - break; - } - - $this->_conditions[] = array('condition' => $string, 'flags' => $flag, 'extra' => $extra); - } - - /** - * Generates maildrop code to represent the recipe. - * - * @return string maildrop code to represent the recipe. - */ - function generate() - { - $text = array(); - - if (!$this->_valid) { - return ''; - } - - if (count($this->_conditions) > 0) { - - $text[] = "if( \\"; - - $nest = false; - foreach ($this->_conditions as $condition) { - $cond = $nest ? $this->_combine : ' '; - $text[] = $cond . $condition['condition'] . $condition['flags'] . $condition['extra'] . " \\"; - $nest = true; - } - - $text[] = ')'; - } - - foreach ($this->_action as $val) { - $text[] = $val; - } - - if ($this->_disable) { - $code = ''; - foreach ($text as $val) { - $comment = new Maildrop_Comment($val); - $code .= $comment->generate() . "\n"; - } - return $code . "\n"; - } else { - return implode("\n", $text) . "\n"; - } - } - - /** - * Returns a maildrop-ready mailbox path, converting IMAP folder pathname - * conventions as necessary. - * - * @param string $folder The IMAP folder name. - * - * @return string The maildrop mailbox path. - */ - function maildropPath($folder) - { - /* NOTE: '$DEFAULT' here is a literal, not a PHP variable. */ - if (isset($this->_params) && - ($this->_params['path_style'] == 'maildir')) { - if (empty($folder) || ($folder == 'INBOX')) { - return '"${DEFAULT}"'; - } - if ($this->_params['strip_inbox'] && - substr($folder, 0, 6) == 'INBOX.') { - $folder = substr($folder, 6); - } - return '"${DEFAULT}/.' . $folder . '/"'; - } else { - if (empty($folder) || ($folder == 'INBOX')) { - return '${DEFAULT}'; - } - return str_replace(' ', '\ ', $folder); - } - } - -} - -/** - * The Maildrop_Variable:: class represents a Maildrop variable. - * - * @author Matt Weyland - * @package Ingo - */ -class Maildrop_Variable { - - var $_name; - var $_value; - - /** - * Constructs a new maildrop variable. - * - * @param array $params Array of parameters. Expected fields are 'name' - * and 'value'. - */ - function Maildrop_Variable($params = array()) - { - $this->_name = $params['name']; - $this->_value = $params['value']; - } - - /** - * Generates maildrop code to represent the variable. - * - * @return string maildrop code to represent the variable. - */ - function generate() - { - return $this->_name . '=' . $this->_value . "\n"; - } - -} diff --git a/ingo/lib/Script/Maildrop/Comment.php b/ingo/lib/Script/Maildrop/Comment.php new file mode 100644 index 000000000..ba43f4766 --- /dev/null +++ b/ingo/lib/Script/Maildrop/Comment.php @@ -0,0 +1,53 @@ + + * + * See the enclosed file LICENSE for license information (ASL). If you + * did not receive this file, see http://www.horde.org/licenses/asl.php. + * + * @author Matt Weyland + * @package Ingo + */ +class Ingo_Script_Maildrop_Comment +{ + /** + * The comment text. + * + * @var string + */ + protected $_comment = ''; + + /** + * Constructs a new maildrop comment. + * + * @param string $comment Comment to be generated. + * @param boolean $disable Output 'DISABLED' comment? + * @param boolean $header Output a 'header' comment? + */ + public function __construct($comment, $disable = false, $header = false) + { + if ($disable) { + $comment = _("DISABLED: ") . $comment; + } + + $this->_comment = $header + ? '##### ' . $comment . ' #####' + : '# ' . $comment; + } + + /** + * Returns the comment stored by this object. + * + * @return string The comment stored by this object. + */ + public function generate() + { + return $this->_comment; + } + +} diff --git a/ingo/lib/Script/Maildrop/Recipe.php b/ingo/lib/Script/Maildrop/Recipe.php new file mode 100644 index 000000000..c88dfb394 --- /dev/null +++ b/ingo/lib/Script/Maildrop/Recipe.php @@ -0,0 +1,373 @@ + + * + * See the enclosed file LICENSE for license information (ASL). If you + * did not receive this file, see http://www.horde.org/licenses/asl.php. + * + * @author Matt Weyland + * @package Ingo + */ +class Maildrop_Recipe +{ + /** + */ + protected $_action = array(); + + /** + */ + protected $_conditions = array(); + + /** + */ + protected $_disable = ''; + + /** + */ + protected $_flags = ''; + + /** + */ + protected $_params = array(); + + /** + */ + protected $_combine = ''; + + /** + */ + protected $_valid = true; + + /** + */ + protected $_operators = array( + 'less than' => '<', + 'less than or equal to' => '<=', + 'equal' => '==', + 'not equal' => '!=', + 'greater than' => '>', + 'greater than or equal to' => '>=', + ); + + /** + * Constructs a new maildrop recipe. + * + * @param array $params Array of parameters. + * REQUIRED FIELDS: + * 'action' + * OPTIONAL FIELDS: + * 'action-value' (only used if the + * 'action' requires it) + * @param array $scriptparams Array of parameters passed to + * Ingo_Script_Maildrop::. + */ + public function __construct($params = array(), $scriptparams = array()) + { + $this->_disable = !empty($params['disable']); + $this->_params = $scriptparams; + $this->_action[] = 'exception {'; + + switch ($params['action']) { + case Ingo_Storage::ACTION_KEEP: + $this->_action[] = ' to "${DEFAULT}"'; + break; + + case Ingo_Storage::ACTION_MOVE: + $this->_action[] = ' to ' . $this->maildropPath($params['action-value']); + break; + + case Ingo_Storage::ACTION_DISCARD: + $this->_action[] = ' exit'; + break; + + case Ingo_Storage::ACTION_REDIRECT: + $this->_action[] = ' to "! ' . $params['action-value'] . '"'; + break; + + case Ingo_Storage::ACTION_REDIRECTKEEP: + $this->_action[] = ' cc "! ' . $params['action-value'] . '"'; + $this->_action[] = ' to "${DEFAULT}"'; + break; + + case Ingo_Storage::ACTION_REJECT: + $this->_action[] = ' EXITCODE=77'; # EX_NOPERM (permanent failure) + $this->_action[] = ' echo "5.7.1 ' . $params['action-value'] . '"'; + $this->_action[] = ' exit'; + break; + + case Ingo_Storage::ACTION_VACATION: + $from = ''; + foreach ($params['action-value']['addresses'] as $address) { + $from = $address; + } + + /** + * @TODO + * + * Exclusion and listfilter + */ + $exclude = ''; + foreach ($params['action-value']['excludes'] as $address) { + $exclude .= $address . ' '; + } + + $start = strftime($params['action-value']['start']); + if ($start === false) { + $start = 0; + } + $end = strftime($params['action-value']['end']); + if ($end === false) { + $end = 0; + } + $days = strftime($params['action-value']['days']); + if ($days === false) { + // Set to same value as $_days in ingo/lib/Storage.php + $days = 7; + } + + // Writing vacation.msg file + $reason = Horde_Mime::encode($params['action-value']['reason'], $scriptparams['charset']); + $driver = Ingo::getDriver(); + $driver->_connect(); + $result = $driver->_vfs->writeData($driver->_params['vfs_path'], 'vacation.msg', $reason, true); + + // Rule : Do not send responses to bulk or list messages + if ($params['action-value']['ignorelist'] == 1) { + $params['combine'] = Ingo_Storage::COMBINE_ALL; + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Precedence: (bulk|list|junk)/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Return-Path:.*<#@\[\]>/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Return-Path:.*<>/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^From:.*MAILER-DAEMON/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^X-ClamAV-Notice-Flag: *YES/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Content-Type:.*message\/delivery-status/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Delivery Status Notification/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Undelivered Mail Returned to Sender/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Delivery failure/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Message delay/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Mail Delivery Subsystem/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^Subject:.*Mail System Error.*Returned Mail/')); + $this->addCondition(array('match' => 'filter', 'field' => '', 'value' => '! /^X-Spam-Flag: YES/ ')); + } else { + $this->addCondition(array('field' => 'From', 'value' => '')); + } + + // Rule : Start/End of vacation + if (($start != 0) && ($end !== 0)) { + $this->_action[] = ' flock "vacationprocess.lock" {'; + $this->_action[] = ' current_time=time'; + $this->_action[] = ' if ( \ '; + $this->_action[] = ' ($current_time >= ' . $start . ') && \ '; + $this->_action[] = ' ($current_time <= ' . $end . ')) '; + $this->_action[] = ' {'; + } + $this->_action[] = " cc \"| mailbot -D " . $params['action-value']['days'] . " -c '" . $scriptparams['charset'] . "' -t \$HOME/vacation.msg -d \$HOME/vacation -A 'From: $from' -s '" . Horde_Mime::encode($params['action-value']['subject'], $scriptparams['charset']) . "' /usr/sbin/sendmail -t \""; + if (($start != 0) && ($end !== 0)) { + $this->_action[] = ' }'; + $this->_action[] = ' }'; + } + + break; + + case Ingo_Storage::ACTION_FORWARD: + case Ingo_Script_Maildrop::MAILDROP_STORAGE_ACTION_STOREANDFORWARD: + foreach ($params['action-value'] as $address) { + if (!empty($address)) { + $this->_action[] = ' cc "! ' . $address . '"'; + } + } + + /* The 'to' must be the last action, because maildrop + * stops processing after it. */ + if ($params['action'] == Ingo_Script_Maildrop::MAILDROP_STORAGE_ACTION_STOREANDFORWARD) { + $this->_action[] = ' to "${DEFAULT}"'; + } else { + $this->_action[] = ' exit'; + } + break; + + default: + $this->_valid = false; + break; + } + + $this->_action[] = '}'; + + if (isset($params['combine']) && + ($params['combine'] == Ingo_Storage::COMBINE_ALL)) { + $this->_combine = '&& '; + } else { + $this->_combine = '|| '; + } + } + + /** + * Adds a flag to the recipe. + * + * @param string $flag String of flags to append to the current flags. + */ + public function addFlag($flag) + { + $this->_flags .= $flag; + } + + /** + * Adds a condition to the recipe. + * + * @param optonal array $condition Array of parameters. Required keys + * are 'field' and 'value'. 'case' is + * an optional keys. + */ + public function addCondition($condition = array()) + { + $flag = (!empty($condition['case'])) ? 'D' : ''; + if (empty($this->_conditions)) { + $this->addFlag($flag); + } + + $string = ''; + $extra = ''; + + $match = (isset($condition['match'])) ? $condition['match'] : null; + // negate tests starting with 'not ', except 'not equals', which simply uses the != operator + if ($match != 'not equal' && substr($match, 0, 4) == 'not ') { + $string .= '! '; + } + + // convert 'field' to PCRE pattern matching + if (strpos($condition['field'], ',') == false) { + $string .= '/^' . $condition['field'] . ':\\s*'; + } else { + $string .= '/^(' . str_replace(',', '|', $condition['field']) . '):\\s*'; + } + + switch ($match) { + case 'not regex': + case 'regex': + $string .= $condition['value'] . '/:h'; + break; + + case 'filter': + $string = $condition['value']; + break; + + case 'exists': + case 'not exist': + // Just run a match for the header name + $string .= '/:h'; + break; + + case 'less than or equal to': + case 'less than': + case 'equal': + case 'not equal': + case 'greater than or equal to': + case 'greater than': + $string .= '(\d+(\.\d+)?)/:h'; + $extra = ' && $MATCH1 ' . $this->_operators[$match] . ' ' . (int)$condition['value']; + break; + + case 'begins with': + case 'not begins with': + $string .= preg_quote($condition['value'], '/') . '/:h'; + break; + + case 'ends with': + case 'not ends with': + $string .= '.*' . preg_quote($condition['value'], '/') . '$/:h'; + break; + + case 'is': + case 'not is': + $string .= preg_quote($condition['value'], '/') . '$/:h'; + break; + + case 'matches': + case 'not matches': + $string .= str_replace(array('\\*', '\\?'), array('.*', '.'), preg_quote($condition['value'], '/') . '$') . '/:h'; + break; + + case 'contains': + case 'not contain': + default: + $string .= '.*' . preg_quote($condition['value'], '/') . '/:h'; + break; + } + + $this->_conditions[] = array('condition' => $string, 'flags' => $flag, 'extra' => $extra); + } + + /** + * Generates maildrop code to represent the recipe. + * + * @return string maildrop code to represent the recipe. + */ + public function generate() + { + $text = array(); + + if (!$this->_valid) { + return ''; + } + + if (count($this->_conditions) > 0) { + + $text[] = "if( \\"; + + $nest = false; + foreach ($this->_conditions as $condition) { + $cond = $nest ? $this->_combine : ' '; + $text[] = $cond . $condition['condition'] . $condition['flags'] . $condition['extra'] . " \\"; + $nest = true; + } + + $text[] = ')'; + } + + foreach ($this->_action as $val) { + $text[] = $val; + } + + if ($this->_disable) { + $code = ''; + foreach ($text as $val) { + $comment = new Ingo_Script_Maildrop_Comment($val); + $code .= $comment->generate() . "\n"; + } + return $code . "\n"; + } else { + return implode("\n", $text) . "\n"; + } + } + + /** + * Returns a maildrop-ready mailbox path, converting IMAP folder pathname + * conventions as necessary. + * + * @param string $folder The IMAP folder name. + * + * @return string The maildrop mailbox path. + */ + public function maildropPath($folder) + { + /* NOTE: '$DEFAULT' here is a literal, not a PHP variable. */ + if (isset($this->_params) && + ($this->_params['path_style'] == 'maildir')) { + if (empty($folder) || ($folder == 'INBOX')) { + return '"${DEFAULT}"'; + } + if ($this->_params['strip_inbox'] && + substr($folder, 0, 6) == 'INBOX.') { + $folder = substr($folder, 6); + } + return '"${DEFAULT}/.' . $folder . '/"'; + } else { + if (empty($folder) || ($folder == 'INBOX')) { + return '${DEFAULT}'; + } + return str_replace(' ', '\ ', $folder); + } + } + +} diff --git a/ingo/lib/Script/Maildrop/Variable.php b/ingo/lib/Script/Maildrop/Variable.php new file mode 100644 index 000000000..054508816 --- /dev/null +++ b/ingo/lib/Script/Maildrop/Variable.php @@ -0,0 +1,45 @@ + + * + * See the enclosed file LICENSE for license information (ASL). If you + * did not receive this file, see http://www.horde.org/licenses/asl.php. + * + * @author Matt Weyland + * @package Ingo + */ +class Maildrop_Variable +{ + /** + */ + protected $_name; + + /** + */ + protected $_value; + + /** + * Constructs a new maildrop variable. + * + * @param array $params Array of parameters. Expected fields are 'name' + * and 'value'. + */ + public function __construct($params = array()) + { + $this->_name = $params['name']; + $this->_value = $params['value']; + } + + /** + * Generates maildrop code to represent the variable. + * + * @return string maildrop code to represent the variable. + */ + public function generate() + { + return $this->_name . '=' . $this->_value . "\n"; + } + +} diff --git a/ingo/lib/Script/Procmail.php b/ingo/lib/Script/Procmail.php index 6507f9725..c5d18a377 100644 --- a/ingo/lib/Script/Procmail.php +++ b/ingo/lib/Script/Procmail.php @@ -11,14 +11,14 @@ * @author Ben Chavet * @package Ingo */ -class Ingo_Script_Procmail extends Ingo_Script { - +class Ingo_Script_Procmail extends Ingo_Script +{ /** * The list of actions allowed (implemented) for this driver. * * @var array */ - var $_actions = array( + protected $_actions = array( Ingo_Storage::ACTION_KEEP, Ingo_Storage::ACTION_MOVE, Ingo_Storage::ACTION_DISCARD, @@ -32,7 +32,7 @@ class Ingo_Script_Procmail extends Ingo_Script { * * @var array */ - var $_categories = array( + protected $_categories = array( Ingo_Storage::ACTION_BLACKLIST, Ingo_Storage::ACTION_WHITELIST, Ingo_Storage::ACTION_VACATION, @@ -44,7 +44,7 @@ class Ingo_Script_Procmail extends Ingo_Script { * * @var array */ - var $_types = array( + protected $_types = array( Ingo_Storage::TYPE_HEADER, Ingo_Storage::TYPE_BODY ); @@ -54,7 +54,7 @@ class Ingo_Script_Procmail extends Ingo_Script { * * @var array */ - var $_special_types = array( + protected $_special_types = array( 'Destination', ); @@ -63,7 +63,7 @@ class Ingo_Script_Procmail extends Ingo_Script { * * @var array */ - var $_tests = array( + protected $_tests = array( 'contains', 'not contain', 'begins with', @@ -78,35 +78,35 @@ class Ingo_Script_Procmail extends Ingo_Script { * * @var boolean */ - var $_casesensitive = true; + protected $_casesensitive = true; /** * Does the driver support the stop-script option? * * @var boolean */ - var $_supportStopScript = true; + protected $_supportStopScript = true; /** * Does the driver require a script file to be generated? * * @var boolean */ - var $_scriptfile = true; + protected $_scriptfile = true; /** * The recipes that make up the code. * * @var array */ - var $_recipes = array(); + protected $_recipes = array(); /** * Returns a script previously generated with generate(). * * @return string The procmail script. */ - function toCode() + public function toCode() { $code = ''; foreach ($this->_recipes as $item) { @@ -131,17 +131,17 @@ class Ingo_Script_Procmail extends Ingo_Script { * * @return string The procmail script. */ - function generate() + public function generate() { $filters = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FILTERS); - $this->addItem(new Procmail_Comment(_("procmail script generated by Ingo") . ' (' . date('F j, Y, g:i a') . ')')); + $this->addItem(new Ingo_Script_Procmail_Comment(_("procmail script generated by Ingo") . ' (' . date('F j, Y, g:i a') . ')')); /* Add variable information, if present. */ if (!empty($this->_params['variables']) && is_array($this->_params['variables'])) { foreach ($this->_params['variables'] as $key => $val) { - $this->addItem(new Procmail_Variable(array('name' => $key, 'value' => $val))); + $this->addItem(new Ingo_Script_Procmail_Variable(array('name' => $key, 'value' => $val))); } } @@ -167,21 +167,21 @@ class Ingo_Script_Procmail extends Ingo_Script { if (in_array($filter['action'], $this->_actions)) { /* Create filter if using AND. */ if ($filter['combine'] == Ingo_Storage::COMBINE_ALL) { - $recipe = new Procmail_Recipe($filter, $this->_params); + $recipe = new Ingo_Script_Procmail_Recipe($filter, $this->_params); if (!$filter['stop']) { $recipe->addFlag('c'); } foreach ($filter['conditions'] as $condition) { $recipe->addCondition($condition); } - $this->addItem(new Procmail_Comment($filter['name'], !empty($filter['disable']), true)); + $this->addItem(new Ingo_Script_Procmail_Comment($filter['name'], !empty($filter['disable']), true)); $this->addItem($recipe); } else { /* Create filter if using OR */ - $this->addItem(new Procmail_Comment($filter['name'], !empty($filter['disable']), true)); + $this->addItem(new Ingo_Script_Procmail_Comment($filter['name'], !empty($filter['disable']), true)); $loop = 0; foreach ($filter['conditions'] as $condition) { - $recipe = new Procmail_Recipe($filter, $this->_params); + $recipe = new Ingo_Script_Procmail_Recipe($filter, $this->_params); if ($loop++) { $recipe->addFlag('E'); } @@ -205,23 +205,25 @@ class Ingo_Script_Procmail extends Ingo_Script { * * @param boolean $disable Disable the blacklist? */ - function generateBlacklist($disable = false) + public function generateBlacklist($disable = false) { - $blacklist = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_BLACKLIST); + $blacklist = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_BLACKLIST); $bl_addr = $blacklist->getBlacklist(); $bl_folder = $blacklist->getBlacklistFolder(); - $bl_type = (empty($bl_folder)) ? Ingo_Storage::ACTION_DISCARD : Ingo_Storage::ACTION_MOVE; + $bl_type = empty($bl_folder) + ? Ingo_Storage::ACTION_DISCARD + : Ingo_Storage::ACTION_MOVE; if (!empty($bl_addr)) { - $this->addItem(new Procmail_Comment(_("Blacklisted Addresses"), $disable, true)); + $this->addItem(new Ingo_Script_Procmail_Comment(_("Blacklisted Addresses"), $disable, true)); $params = array('action-value' => $bl_folder, 'action' => $bl_type, 'disable' => $disable); foreach ($bl_addr as $address) { if (!empty($address)) { - $recipe = new Procmail_Recipe($params, $this->_params); + $recipe = new Ingo_Script_Procmail_Recipe($params, $this->_params); $recipe->addCondition(array('field' => 'From', 'value' => $address, 'match' => 'address')); $this->addItem($recipe); } @@ -235,16 +237,16 @@ class Ingo_Script_Procmail extends Ingo_Script { * * @param boolean $disable Disable the whitelist? */ - function generateWhitelist($disable = false) + public function generateWhitelist($disable = false) { - $whitelist = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_WHITELIST); + $whitelist = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_WHITELIST); $wl_addr = $whitelist->getWhitelist(); if (!empty($wl_addr)) { - $this->addItem(new Procmail_Comment(_("Whitelisted Addresses"), $disable, true)); + $this->addItem(new Ingo_Script_Procmail_Comment(_("Whitelisted Addresses"), $disable, true)); foreach ($wl_addr as $address) { if (!empty($address)) { - $recipe = new Procmail_Recipe(array('action' => Ingo_Storage::ACTION_KEEP, 'disable' => $disable), $this->_params); + $recipe = new Ingo_Script_Procmail_Recipe(array('action' => Ingo_Storage::ACTION_KEEP, 'disable' => $disable), $this->_params); $recipe->addCondition(array('field' => 'From', 'value' => $address, 'match' => 'address')); $this->addItem($recipe); } @@ -257,9 +259,9 @@ class Ingo_Script_Procmail extends Ingo_Script { * * @param boolean $disable Disable vacation? */ - function generateVacation($disable = false) + public function generateVacation($disable = false) { - $vacation = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_VACATION); + $vacation = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_VACATION); $addresses = $vacation->getVacationAddresses(); $actionval = array( 'addresses' => $addresses, @@ -273,11 +275,11 @@ class Ingo_Script_Procmail extends Ingo_Script { ); if (!empty($addresses)) { - $this->addItem(new Procmail_Comment(_("Vacation"), $disable, true)); + $this->addItem(new Ingo_Script_Procmail_Comment(_("Vacation"), $disable, true)); $params = array('action' => Ingo_Storage::ACTION_VACATION, 'action-value' => $actionval, 'disable' => $disable); - $recipe = new Procmail_Recipe($params, $this->_params); + $recipe = new Ingo_Script_Procmail_Recipe($params, $this->_params); $this->addItem($recipe); } } @@ -287,17 +289,17 @@ class Ingo_Script_Procmail extends Ingo_Script { * * @param boolean $disable Disable forwarding? */ - function generateForward($disable = false) + public function generateForward($disable = false) { - $forward = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FORWARD); + $forward = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FORWARD); $addresses = $forward->getForwardAddresses(); if (!empty($addresses)) { - $this->addItem(new Procmail_Comment(_("Forwards"), $disable, true)); + $this->addItem(new Ingo_Script_Procmail_Comment(_("Forwards"), $disable, true)); $params = array('action' => Ingo_Storage::ACTION_FORWARD, 'action-value' => $addresses, 'disable' => $disable); - $recipe = new Procmail_Recipe($params, $this->_params); + $recipe = new Ingo_Script_Procmail_Recipe($params, $this->_params); if ($forward->getForwardKeep()) { $recipe->addFlag('c'); } @@ -311,490 +313,9 @@ class Ingo_Script_Procmail extends Ingo_Script { * @param object $item The item to add to the recipe list. * The object should have a generate() function. */ - function addItem($item) + public function addItem($item) { $this->_recipes[] = $item; } } - -/** - * The Procmail_Comment:: class represents a Procmail comment. This is - * a pretty simple class, but it makes the code in Ingo_Script_Procmail:: - * cleaner as it provides a generate() function and can be added to the - * recipe list the same way as a recipe can be. - * - * @author Ben Chavet - * @package Ingo - */ -class Procmail_Comment { - - /** - * The comment text. - * - * @var string - */ - var $_comment = ''; - - /** - * Constructs a new procmail comment. - * - * @param string $comment Comment to be generated. - * @param boolean $disable Output 'DISABLED' comment? - * @param boolean $header Output a 'header' comment? - */ - function Procmail_Comment($comment, $disable = false, $header = false) - { - if ($disable) { - $comment = _("DISABLED: ") . $comment; - } - - if ($header) { - $this->_comment .= "##### $comment #####"; - } else { - $this->_comment .= "# $comment"; - } - } - - /** - * Returns the comment stored by this object. - * - * @return string The comment stored by this object. - */ - function generate() - { - return $this->_comment; - } - -} - -/** - * The Procmail_Recipe:: class represents a Procmail recipe. - * - * @author Ben Chavet - * @package Ingo - */ -class Procmail_Recipe { - - var $_action = array(); - var $_conditions = array(); - var $_disable = ''; - var $_flags = ''; - var $_params = array( - 'date' => 'date', - 'echo' => 'echo', - 'ls' => 'ls' - ); - var $_valid = true; - - /** - * Constructs a new procmail recipe. - * - * @param array $params Array of parameters. - * REQUIRED FIELDS: - * 'action' - * OPTIONAL FIELDS: - * 'action-value' (only used if the - * 'action' requires it) - * @param array $scriptparams Array of parameters passed to - * Ingo_Script_Procmail::. - */ - function Procmail_Recipe($params = array(), $scriptparams = array()) - { - $this->_disable = !empty($params['disable']); - $this->_params = array_merge($this->_params, $scriptparams); - - switch ($params['action']) { - case Ingo_Storage::ACTION_KEEP: - // Note: you may have to set the DEFAULT variable in your - // backend configuration. - if (isset($this->_params['delivery_agent']) && isset($this->_params['delivery_mailbox_prefix'])) { - $this->_action[] = '| ' . $this->_params['delivery_agent'] . ' ' . $this->_params['delivery_mailbox_prefix'] . '$DEFAULT'; - } elseif (isset($this->_params['delivery_agent'])) { - $this->_action[] = '| ' . $this->_params['delivery_agent'] . ' $DEFAULT'; - } else { - $this->_action[] = '$DEFAULT'; - } - break; - - case Ingo_Storage::ACTION_MOVE: - if (isset($this->_params['delivery_agent']) && isset($this->_params['delivery_mailbox_prefix'])) { - $this->_action[] = '| ' . $this->_params['delivery_agent'] . ' ' . $this->_params['delivery_mailbox_prefix'] . $this->procmailPath($params['action-value']); - } elseif (isset($this->_params['delivery_agent'])) { - $this->_action[] = '| ' . $this->_params['delivery_agent'] . ' ' . $this->procmailPath($params['action-value']); - } else { - $this->_action[] = $this->procmailPath($params['action-value']); - } - break; - - case Ingo_Storage::ACTION_DISCARD: - $this->_action[] = '/dev/null'; - break; - - case Ingo_Storage::ACTION_REDIRECT: - $this->_action[] = '! ' . $params['action-value']; - break; - - case Ingo_Storage::ACTION_REDIRECTKEEP: - $this->_action[] = '{'; - $this->_action[] = ' :0 c'; - $this->_action[] = ' ! ' . $params['action-value']; - $this->_action[] = ''; - $this->_action[] = ' :0' . (isset($this->_params['delivery_agent']) ? ' w' : ''); - if (isset($this->_params['delivery_agent']) && isset($this->_params['delivery_mailbox_prefix'])) { - $this->_action[] = ' | ' . $this->_params['delivery_agent'] . ' ' . $this->_params['delivery_mailbox_prefix'] . '$DEFAULT'; - } elseif (isset($this->_params['delivery_agent'])) { - $this->_action[] = ' | ' . $this->_params['delivery_agent'] . ' $DEFAULT'; - } else { - $this->_action[] = ' $DEFAULT'; - } - $this->_action[] = '}'; - break; - - case Ingo_Storage::ACTION_REJECT: - $this->_action[] = '{'; - $this->_action[] = ' EXITCODE=' . $params['action-value']; - $this->_action[] = ' HOST="no.address.here"'; - $this->_action[] = '}'; - break; - - case Ingo_Storage::ACTION_VACATION: - $days = $params['action-value']['days']; - $timed = !empty($params['action-value']['start']) && - !empty($params['action-value']['end']); - $this->_action[] = '{'; - foreach ($params['action-value']['addresses'] as $address) { - if (!empty($address)) { - $this->_action[] = ' :0'; - $this->_action[] = ' * ^TO_' . $address; - $this->_action[] = ' {'; - $this->_action[] = ' FILEDATE=`test -f ${VACATION_DIR:-.}/\'.vacation.' . $address . '\' && ' - . $this->_params['ls'] . ' -lcn --time-style=+%s ${VACATION_DIR:-.}/\'.vacation.' . $address . '\' | ' - . 'awk \'{ print $6 + (' . $days * 86400 . ') }\'`'; - $this->_action[] = ' DATE=`' . $this->_params['date'] . ' +%s`'; - $this->_action[] = ' DUMMY=`test -f ${VACATION_DIR:-.}/\'.vacation.' . $address . '\' && ' - . 'test $FILEDATE -le $DATE && ' - . 'rm ${VACATION_DIR:-.}/\'.vacation.' . $address . '\'`'; - if ($timed) { - $this->_action[] = ' START=' . $params['action-value']['start']; - $this->_action[] = ' END=' . $params['action-value']['end']; - } - $this->_action[] = ''; - $this->_action[] = ' :0 h'; - $this->_action[] = ' SUBJECT=| formail -xSubject:'; - $this->_action[] = ''; - $this->_action[] = ' :0 Whc: ${VACATION_DIR:-.}/vacation.lock'; - if ($timed) { - $this->_action[] = ' * ? test $DATE -gt $START && test $END -gt $DATE'; - $this->_action[] = ' {'; - $this->_action[] = ' :0 Wh'; - } - $this->_action[] = ' * ^TO_' . $address; - $this->_action[] = ' * !^X-Loop: ' . $address; - $this->_action[] = ' * !^X-Spam-Flag: YES'; - if (count($params['action-value']['excludes']) > 0) { - foreach ($params['action-value']['excludes'] as $exclude) { - if (!empty($exclude)) { - $this->_action[] = ' * !^From.*' . $exclude; - } - } - } - if ($params['action-value']['ignorelist']) { - $this->_action[] = ' * !^FROM_DAEMON'; - } - $this->_action[] = ' | formail -rD 8192 ${VACATION_DIR:-.}/.vacation.' . $address; - $this->_action[] = ' :0 eh'; - $this->_action[] = ' | (formail -rI"Precedence: junk" \\'; - $this->_action[] = ' -a"From: <' . $address . '>" \\'; - $this->_action[] = ' -A"X-Loop: ' . $address . '" \\'; - if (Horde_Mime::is8bit($params['action-value']['reason'])) { - $this->_action[] = ' -i"Subject: ' . Horde_Mime::encode($params['action-value']['subject'] . ' (Re: $SUBJECT)', $scriptparams['charset']) . '" \\'; - $this->_action[] = ' -i"Content-Transfer-Encoding: quoted-printable" \\'; - $this->_action[] = ' -i"Content-Type: text/plain; charset=' . $scriptparams['charset'] . '" ; \\'; - $reason = Horde_Mime::quotedPrintableEncode($params['action-value']['reason'], "\n"); - } else { - $this->_action[] = ' -i"Subject: ' . Horde_Mime::encode($params['action-value']['subject'] . ' (Re: $SUBJECT)', $scriptparams['charset']) . '" ; \\'; - $reason = $params['action-value']['reason']; - } - $reason = addcslashes($reason, "\\\n\r\t\"`"); - $this->_action[] = ' ' . $this->_params['echo'] . ' -e "' . $reason . '" \\'; - $this->_action[] = ' ) | $SENDMAIL -f' . $address . ' -oi -t'; - if ($timed) { - $this->_action[] = ' }'; - } - $this->_action[] = ' }'; - } - } - $this->_action[] = '}'; - break; - - case Ingo_Storage::ACTION_FORWARD: - /* Make sure that we prevent mail loops using 3 methods. - * - * First, we call sendmail -f to set the envelope sender to be the - * same as the original sender, so bounces will go to the original - * sender rather than to us. This unfortunately triggers lots of - * Authentication-Warning: messages in sendmail's logs. - * - * Second, add an X-Loop header, to handle the case where the - * address we forward to forwards back to us. - * - * Third, don't forward mailer daemon messages (i.e., bounces). - * Method 1 above should make this redundant, unless we're sending - * mail from this account and have a bad forward-to account. - * - * Get the from address, saving a call to formail if possible. - * The procmail code for doing this is borrowed from the - * Procmail Library Project, http://pm-lib.sourceforge.net/. - * The Ingo project has the permission to use Procmail Library code - * under Apache licence v 1.x or any later version. - * Permission obtained 2006-04-04 from Author Jari Aalto. */ - $this->_action[] = '{'; - $this->_action[] = ' :0 '; - $this->_action[] = ' *$ ! ^From *\/[^ ]+'; - $this->_action[] = ' *$ ! ^Sender: *\/[^ ]+'; - $this->_action[] = ' *$ ! ^From: *\/[^ ]+'; - $this->_action[] = ' *$ ! ^Reply-to: *\/[^ ]+'; - $this->_action[] = ' {'; - $this->_action[] = ' OUTPUT = `formail -zxFrom:`'; - $this->_action[] = ' }'; - $this->_action[] = ' :0 E'; - $this->_action[] = ' {'; - $this->_action[] = ' OUTPUT = $MATCH'; - $this->_action[] = ' }'; - $this->_action[] = ''; - - /* Forward to each address on our list. */ - foreach ($params['action-value'] as $address) { - if (!empty($address)) { - $this->_action[] = ' :0 c'; - $this->_action[] = ' * !^FROM_MAILER'; - $this->_action[] = ' * !^X-Loop: to-' . $address; - $this->_action[] = ' | formail -A"X-Loop: to-' . $address . '" | $SENDMAIL -oi -f $OUTPUT ' . $address; - } - } - - /* In case of mail loop or bounce, store a copy locally. Note - * that if we forward to more than one address, only a mail loop - * on the last address will cause a local copy to be saved. TODO: - * The next two lines are redundant (and create an extra copy of - * the message) if "Keep a copy of messages in this account" is - * checked. */ - $this->_action[] = ' :0 E' . (isset($this->_params['delivery_agent']) ? 'w' : ''); - if (isset($this->_params['delivery_agent'])) { - $this->_action[] = isset($this->_params['delivery_mailbox_prefix']) ? - ' | ' . $this->_params['delivery_agent'] . ' ' . $this->_params['delivery_mailbox_prefix'] . '$DEFAULT' : - ' | ' . $this->_params['delivery_agent'] . ' $DEFAULT'; - } else { - $this->_action[] = ' $DEFAULT'; - } - $this->_action[] = ' :0 '; - $this->_action[] = ' /dev/null'; - $this->_action[] = '}'; - break; - - default: - $this->_valid = false; - break; - } - } - - /** - * Adds a flag to the recipe. - * - * @param string $flag String of flags to append to the current flags. - */ - function addFlag($flag) - { - $this->_flags .= $flag; - } - - /** - * Adds a condition to the recipe. - * - * @param array $condition Array of parameters. Required keys are 'field' - * and 'value'. 'case' is an optional key. - */ - function addCondition($condition = array()) - { - $flag = !empty($condition['case']) ? 'D' : ''; - $match = isset($condition['match']) ? $condition['match'] : null; - $string = ''; - $prefix = ''; - - switch ($condition['field']) { - case 'Destination': - $string = '^TO_'; - break; - - case 'Body': - $flag .= 'B'; - break; - - default: - // convert 'field' to PCRE pattern matching - if (!strpos($condition['field'], ',')) { - $string = '^' . $condition['field'] . ':'; - } else { - $string .= '^(' . str_replace(',', '|', $condition['field']) . '):'; - } - $prefix = ' '; - } - - $reverseCondition = false; - switch ($match) { - case 'regex': - $string .= $prefix . $condition['value']; - break; - - case 'address': - $string .= '(.*\<)?' . quotemeta($condition['value']); - break; - - case 'not begins with': - $reverseCondition = true; - // fall through - case 'begins with': - $string .= $prefix . quotemeta($condition['value']); - break; - - case 'not ends with': - $reverseCondition = true; - // fall through - case 'ends with': - $string .= '.*' . quotemeta($condition['value']) . '$'; - break; - - case 'not contain': - $reverseCondition = true; - // fall through - case 'contains': - default: - $string .= '.*' . quotemeta($condition['value']); - break; - } - - $this->_conditions[] = array('condition' => ($reverseCondition ? '* !' : '* ') . $string, - 'flags' => $flag); - } - - /** - * Generates procmail code to represent the recipe. - * - * @return string Procmail code to represent the recipe. - */ - function generate() - { - $nest = 0; - $prefix = ''; - $text = array(); - - if (!$this->_valid) { - return ''; - } - - // Set the global flags for the whole rule, each condition - // will add its own (such as Body or Case Sensitive) - $global = $this->_flags; - if (isset($this->_conditions[0])) { - $global .= $this->_conditions[0]['flags']; - } - $text[] = ':0 ' . $global . (isset($this->_params['delivery_agent']) ? 'w' : ''); - foreach ($this->_conditions as $condition) { - if ($nest > 0) { - $text[] = str_repeat(' ', $nest - 1) . '{'; - $text[] = str_repeat(' ', $nest) . ':0 ' . $condition['flags']; - $text[] = str_repeat(' ', $nest) . $condition['condition']; - } else { - $text[] = $condition['condition']; - } - $nest++; - } - - if (--$nest > 0) { - $prefix = str_repeat(' ', $nest); - } - foreach ($this->_action as $val) { - $text[] = $prefix . $val; - } - - for ($i = $nest; $i > 0; $i--) { - $text[] = str_repeat(' ', $i - 1) . '}'; - } - - if ($this->_disable) { - $code = ''; - foreach ($text as $val) { - $comment = new Procmail_Comment($val); - $code .= $comment->generate() . "\n"; - } - return $code . "\n"; - } else { - return implode("\n", $text) . "\n"; - } - } - - /** - * Returns a procmail-ready mailbox path, converting IMAP folder - * pathname conventions as necessary. - * - * @param string $folder The IMAP folder name. - * - * @return string The procmail mailbox path. - */ - function procmailPath($folder) - { - /* NOTE: '$DEFAULT' here is a literal, not a PHP variable. */ - if (isset($this->_params) && - ($this->_params['path_style'] == 'maildir')) { - if (empty($folder) || ($folder == 'INBOX')) { - return '$DEFAULT'; - } - if (substr($folder, 0, 6) == 'INBOX.') { - $folder = substr($folder, 6); - } - return '"$DEFAULT/.' . escapeshellcmd($folder) . '/"'; - } else { - if (empty($folder) || ($folder == 'INBOX')) { - return '$DEFAULT'; - } - return str_replace(' ', '\ ', escapeshellcmd($folder)); - } - } - -} - -/** - * The Procmail_Variable:: class represents a Procmail variable. - * - * @author Michael Slusarz - * @package Ingo - */ -class Procmail_Variable { - - var $_name; - var $_value; - - /** - * Constructs a new procmail variable. - * - * @param array $params Array of parameters. Expected fields are 'name' - * and 'value'. - */ - function Procmail_Variable($params = array()) - { - $this->_name = $params['name']; - $this->_value = $params['value']; - } - - /** - * Generates procmail code to represent the variable. - * - * @return string Procmail code to represent the variable. - */ - function generate() - { - return $this->_name . '=' . $this->_value . "\n"; - } - -} diff --git a/ingo/lib/Script/Procmail/Comment.php b/ingo/lib/Script/Procmail/Comment.php new file mode 100644 index 000000000..d31a4a6ec --- /dev/null +++ b/ingo/lib/Script/Procmail/Comment.php @@ -0,0 +1,53 @@ + + * @package Ingo + */ +class Ingo_Script_Procmail_Comment +{ + /** + * The comment text. + * + * @var string + */ + protected $_comment = ''; + + /** + * Constructs a new procmail comment. + * + * @param string $comment Comment to be generated. + * @param boolean $disable Output 'DISABLED' comment? + * @param boolean $header Output a 'header' comment? + */ + public function __construct($comment, $disable = false, $header = false) + { + if ($disable) { + $comment = _("DISABLED: ") . $comment; + } + + $this->_comment = $header + ? '##### ' . $comment . ' #####' + : '# ' . $comment; + } + + /** + * Returns the comment stored by this object. + * + * @return string The comment stored by this object. + */ + public function generate() + { + return $this->_comment; + } + +} diff --git a/ingo/lib/Script/Procmail/Recipe.php b/ingo/lib/Script/Procmail/Recipe.php new file mode 100644 index 000000000..50fe06a4d --- /dev/null +++ b/ingo/lib/Script/Procmail/Recipe.php @@ -0,0 +1,418 @@ + + * @package Ingo + */ +class Ingo_Script_Procmail_Recipe +{ + /** + */ + protected $_action = array(); + + /** + */ + protected $_conditions = array(); + + /** + */ + protected $_disable = ''; + + /** + */ + protected $_flags = ''; + + /** + */ + protected $_params = array( + 'date' => 'date', + 'echo' => 'echo', + 'ls' => 'ls' + ); + + /** + */ + protected $_valid = true; + + /** + * Constructs a new procmail recipe. + * + * @param array $params Array of parameters. + * REQUIRED FIELDS: + * 'action' + * OPTIONAL FIELDS: + * 'action-value' (only used if the + * 'action' requires it) + * @param array $scriptparams Array of parameters passed to + * Ingo_Script_Procmail::. + */ + public function __construct($params = array(), $scriptparams = array()) + { + $this->_disable = !empty($params['disable']); + $this->_params = array_merge($this->_params, $scriptparams); + + switch ($params['action']) { + case Ingo_Storage::ACTION_KEEP: + // Note: you may have to set the DEFAULT variable in your + // backend configuration. + if (isset($this->_params['delivery_agent']) && isset($this->_params['delivery_mailbox_prefix'])) { + $this->_action[] = '| ' . $this->_params['delivery_agent'] . ' ' . $this->_params['delivery_mailbox_prefix'] . '$DEFAULT'; + } elseif (isset($this->_params['delivery_agent'])) { + $this->_action[] = '| ' . $this->_params['delivery_agent'] . ' $DEFAULT'; + } else { + $this->_action[] = '$DEFAULT'; + } + break; + + case Ingo_Storage::ACTION_MOVE: + if (isset($this->_params['delivery_agent']) && isset($this->_params['delivery_mailbox_prefix'])) { + $this->_action[] = '| ' . $this->_params['delivery_agent'] . ' ' . $this->_params['delivery_mailbox_prefix'] . $this->procmailPath($params['action-value']); + } elseif (isset($this->_params['delivery_agent'])) { + $this->_action[] = '| ' . $this->_params['delivery_agent'] . ' ' . $this->procmailPath($params['action-value']); + } else { + $this->_action[] = $this->procmailPath($params['action-value']); + } + break; + + case Ingo_Storage::ACTION_DISCARD: + $this->_action[] = '/dev/null'; + break; + + case Ingo_Storage::ACTION_REDIRECT: + $this->_action[] = '! ' . $params['action-value']; + break; + + case Ingo_Storage::ACTION_REDIRECTKEEP: + $this->_action[] = '{'; + $this->_action[] = ' :0 c'; + $this->_action[] = ' ! ' . $params['action-value']; + $this->_action[] = ''; + $this->_action[] = ' :0' . (isset($this->_params['delivery_agent']) ? ' w' : ''); + if (isset($this->_params['delivery_agent']) && isset($this->_params['delivery_mailbox_prefix'])) { + $this->_action[] = ' | ' . $this->_params['delivery_agent'] . ' ' . $this->_params['delivery_mailbox_prefix'] . '$DEFAULT'; + } elseif (isset($this->_params['delivery_agent'])) { + $this->_action[] = ' | ' . $this->_params['delivery_agent'] . ' $DEFAULT'; + } else { + $this->_action[] = ' $DEFAULT'; + } + $this->_action[] = '}'; + break; + + case Ingo_Storage::ACTION_REJECT: + $this->_action[] = '{'; + $this->_action[] = ' EXITCODE=' . $params['action-value']; + $this->_action[] = ' HOST="no.address.here"'; + $this->_action[] = '}'; + break; + + case Ingo_Storage::ACTION_VACATION: + $days = $params['action-value']['days']; + $timed = !empty($params['action-value']['start']) && + !empty($params['action-value']['end']); + $this->_action[] = '{'; + foreach ($params['action-value']['addresses'] as $address) { + if (!empty($address)) { + $this->_action[] = ' :0'; + $this->_action[] = ' * ^TO_' . $address; + $this->_action[] = ' {'; + $this->_action[] = ' FILEDATE=`test -f ${VACATION_DIR:-.}/\'.vacation.' . $address . '\' && ' + . $this->_params['ls'] . ' -lcn --time-style=+%s ${VACATION_DIR:-.}/\'.vacation.' . $address . '\' | ' + . 'awk \'{ print $6 + (' . $days * 86400 . ') }\'`'; + $this->_action[] = ' DATE=`' . $this->_params['date'] . ' +%s`'; + $this->_action[] = ' DUMMY=`test -f ${VACATION_DIR:-.}/\'.vacation.' . $address . '\' && ' + . 'test $FILEDATE -le $DATE && ' + . 'rm ${VACATION_DIR:-.}/\'.vacation.' . $address . '\'`'; + if ($timed) { + $this->_action[] = ' START=' . $params['action-value']['start']; + $this->_action[] = ' END=' . $params['action-value']['end']; + } + $this->_action[] = ''; + $this->_action[] = ' :0 h'; + $this->_action[] = ' SUBJECT=| formail -xSubject:'; + $this->_action[] = ''; + $this->_action[] = ' :0 Whc: ${VACATION_DIR:-.}/vacation.lock'; + if ($timed) { + $this->_action[] = ' * ? test $DATE -gt $START && test $END -gt $DATE'; + $this->_action[] = ' {'; + $this->_action[] = ' :0 Wh'; + } + $this->_action[] = ' * ^TO_' . $address; + $this->_action[] = ' * !^X-Loop: ' . $address; + $this->_action[] = ' * !^X-Spam-Flag: YES'; + if (count($params['action-value']['excludes']) > 0) { + foreach ($params['action-value']['excludes'] as $exclude) { + if (!empty($exclude)) { + $this->_action[] = ' * !^From.*' . $exclude; + } + } + } + if ($params['action-value']['ignorelist']) { + $this->_action[] = ' * !^FROM_DAEMON'; + } + $this->_action[] = ' | formail -rD 8192 ${VACATION_DIR:-.}/.vacation.' . $address; + $this->_action[] = ' :0 eh'; + $this->_action[] = ' | (formail -rI"Precedence: junk" \\'; + $this->_action[] = ' -a"From: <' . $address . '>" \\'; + $this->_action[] = ' -A"X-Loop: ' . $address . '" \\'; + if (Horde_Mime::is8bit($params['action-value']['reason'])) { + $this->_action[] = ' -i"Subject: ' . Horde_Mime::encode($params['action-value']['subject'] . ' (Re: $SUBJECT)', $scriptparams['charset']) . '" \\'; + $this->_action[] = ' -i"Content-Transfer-Encoding: quoted-printable" \\'; + $this->_action[] = ' -i"Content-Type: text/plain; charset=' . $scriptparams['charset'] . '" ; \\'; + $reason = Horde_Mime::quotedPrintableEncode($params['action-value']['reason'], "\n"); + } else { + $this->_action[] = ' -i"Subject: ' . Horde_Mime::encode($params['action-value']['subject'] . ' (Re: $SUBJECT)', $scriptparams['charset']) . '" ; \\'; + $reason = $params['action-value']['reason']; + } + $reason = addcslashes($reason, "\\\n\r\t\"`"); + $this->_action[] = ' ' . $this->_params['echo'] . ' -e "' . $reason . '" \\'; + $this->_action[] = ' ) | $SENDMAIL -f' . $address . ' -oi -t'; + if ($timed) { + $this->_action[] = ' }'; + } + $this->_action[] = ' }'; + } + } + $this->_action[] = '}'; + break; + + case Ingo_Storage::ACTION_FORWARD: + /* Make sure that we prevent mail loops using 3 methods. + * + * First, we call sendmail -f to set the envelope sender to be the + * same as the original sender, so bounces will go to the original + * sender rather than to us. This unfortunately triggers lots of + * Authentication-Warning: messages in sendmail's logs. + * + * Second, add an X-Loop header, to handle the case where the + * address we forward to forwards back to us. + * + * Third, don't forward mailer daemon messages (i.e., bounces). + * Method 1 above should make this redundant, unless we're sending + * mail from this account and have a bad forward-to account. + * + * Get the from address, saving a call to formail if possible. + * The procmail code for doing this is borrowed from the + * Procmail Library Project, http://pm-lib.sourceforge.net/. + * The Ingo project has the permission to use Procmail Library code + * under Apache licence v 1.x or any later version. + * Permission obtained 2006-04-04 from Author Jari Aalto. */ + $this->_action[] = '{'; + $this->_action[] = ' :0 '; + $this->_action[] = ' *$ ! ^From *\/[^ ]+'; + $this->_action[] = ' *$ ! ^Sender: *\/[^ ]+'; + $this->_action[] = ' *$ ! ^From: *\/[^ ]+'; + $this->_action[] = ' *$ ! ^Reply-to: *\/[^ ]+'; + $this->_action[] = ' {'; + $this->_action[] = ' OUTPUT = `formail -zxFrom:`'; + $this->_action[] = ' }'; + $this->_action[] = ' :0 E'; + $this->_action[] = ' {'; + $this->_action[] = ' OUTPUT = $MATCH'; + $this->_action[] = ' }'; + $this->_action[] = ''; + + /* Forward to each address on our list. */ + foreach ($params['action-value'] as $address) { + if (!empty($address)) { + $this->_action[] = ' :0 c'; + $this->_action[] = ' * !^FROM_MAILER'; + $this->_action[] = ' * !^X-Loop: to-' . $address; + $this->_action[] = ' | formail -A"X-Loop: to-' . $address . '" | $SENDMAIL -oi -f $OUTPUT ' . $address; + } + } + + /* In case of mail loop or bounce, store a copy locally. Note + * that if we forward to more than one address, only a mail loop + * on the last address will cause a local copy to be saved. TODO: + * The next two lines are redundant (and create an extra copy of + * the message) if "Keep a copy of messages in this account" is + * checked. */ + $this->_action[] = ' :0 E' . (isset($this->_params['delivery_agent']) ? 'w' : ''); + if (isset($this->_params['delivery_agent'])) { + $this->_action[] = isset($this->_params['delivery_mailbox_prefix']) ? + ' | ' . $this->_params['delivery_agent'] . ' ' . $this->_params['delivery_mailbox_prefix'] . '$DEFAULT' : + ' | ' . $this->_params['delivery_agent'] . ' $DEFAULT'; + } else { + $this->_action[] = ' $DEFAULT'; + } + $this->_action[] = ' :0 '; + $this->_action[] = ' /dev/null'; + $this->_action[] = '}'; + break; + + default: + $this->_valid = false; + break; + } + } + + /** + * Adds a flag to the recipe. + * + * @param string $flag String of flags to append to the current flags. + */ + public function addFlag($flag) + { + $this->_flags .= $flag; + } + + /** + * Adds a condition to the recipe. + * + * @param array $condition Array of parameters. Required keys are 'field' + * and 'value'. 'case' is an optional key. + */ + public function addCondition($condition = array()) + { + $flag = !empty($condition['case']) ? 'D' : ''; + $match = isset($condition['match']) ? $condition['match'] : null; + $string = ''; + $prefix = ''; + + switch ($condition['field']) { + case 'Destination': + $string = '^TO_'; + break; + + case 'Body': + $flag .= 'B'; + break; + + default: + // convert 'field' to PCRE pattern matching + if (!strpos($condition['field'], ',')) { + $string = '^' . $condition['field'] . ':'; + } else { + $string .= '^(' . str_replace(',', '|', $condition['field']) . '):'; + } + $prefix = ' '; + } + + $reverseCondition = false; + switch ($match) { + case 'regex': + $string .= $prefix . $condition['value']; + break; + + case 'address': + $string .= '(.*\<)?' . quotemeta($condition['value']); + break; + + case 'not begins with': + $reverseCondition = true; + // fall through + case 'begins with': + $string .= $prefix . quotemeta($condition['value']); + break; + + case 'not ends with': + $reverseCondition = true; + // fall through + case 'ends with': + $string .= '.*' . quotemeta($condition['value']) . '$'; + break; + + case 'not contain': + $reverseCondition = true; + // fall through + case 'contains': + default: + $string .= '.*' . quotemeta($condition['value']); + break; + } + + $this->_conditions[] = array('condition' => ($reverseCondition ? '* !' : '* ') . $string, + 'flags' => $flag); + } + + /** + * Generates procmail code to represent the recipe. + * + * @return string Procmail code to represent the recipe. + */ + public function generate() + { + $nest = 0; + $prefix = ''; + $text = array(); + + if (!$this->_valid) { + return ''; + } + + // Set the global flags for the whole rule, each condition + // will add its own (such as Body or Case Sensitive) + $global = $this->_flags; + if (isset($this->_conditions[0])) { + $global .= $this->_conditions[0]['flags']; + } + $text[] = ':0 ' . $global . (isset($this->_params['delivery_agent']) ? 'w' : ''); + foreach ($this->_conditions as $condition) { + if ($nest > 0) { + $text[] = str_repeat(' ', $nest - 1) . '{'; + $text[] = str_repeat(' ', $nest) . ':0 ' . $condition['flags']; + $text[] = str_repeat(' ', $nest) . $condition['condition']; + } else { + $text[] = $condition['condition']; + } + $nest++; + } + + if (--$nest > 0) { + $prefix = str_repeat(' ', $nest); + } + foreach ($this->_action as $val) { + $text[] = $prefix . $val; + } + + for ($i = $nest; $i > 0; $i--) { + $text[] = str_repeat(' ', $i - 1) . '}'; + } + + if ($this->_disable) { + $code = ''; + foreach ($text as $val) { + $comment = new Ingo_Script_Procmail_Comment($val); + $code .= $comment->generate() . "\n"; + } + return $code . "\n"; + } else { + return implode("\n", $text) . "\n"; + } + } + + /** + * Returns a procmail-ready mailbox path, converting IMAP folder + * pathname conventions as necessary. + * + * @param string $folder The IMAP folder name. + * + * @return string The procmail mailbox path. + */ + public function procmailPath($folder) + { + /* NOTE: '$DEFAULT' here is a literal, not a PHP variable. */ + if (isset($this->_params) && + ($this->_params['path_style'] == 'maildir')) { + if (empty($folder) || ($folder == 'INBOX')) { + return '$DEFAULT'; + } + if (substr($folder, 0, 6) == 'INBOX.') { + $folder = substr($folder, 6); + } + return '"$DEFAULT/.' . escapeshellcmd($folder) . '/"'; + } else { + if (empty($folder) || ($folder == 'INBOX')) { + return '$DEFAULT'; + } + return str_replace(' ', '\ ', escapeshellcmd($folder)); + } + } + +} diff --git a/ingo/lib/Script/Procmail/Variable.php b/ingo/lib/Script/Procmail/Variable.php new file mode 100644 index 000000000..5fd4ad748 --- /dev/null +++ b/ingo/lib/Script/Procmail/Variable.php @@ -0,0 +1,45 @@ + + * @package Ingo + */ +class Ingo_Script_Procmail_Variable +{ + /** + */ + protected $_name; + + /** + */ + protected $_value; + + /** + * Constructs a new procmail variable. + * + * @param array $params Array of parameters. Expected fields are 'name' + * and 'value'. + */ + public function __construct($params = array()) + { + $this->_name = $params['name']; + $this->_value = $params['value']; + } + + /** + * Generates procmail code to represent the variable. + * + * @return string Procmail code to represent the variable. + */ + public function generate() + { + return $this->_name . '=' . $this->_value . "\n"; + } + +} diff --git a/ingo/lib/Script/Sieve.php b/ingo/lib/Script/Sieve.php index 5ea6daffa..4b2bfe47f 100644 --- a/ingo/lib/Script/Sieve.php +++ b/ingo/lib/Script/Sieve.php @@ -8,14 +8,14 @@ * @author Mike Cochrane * @package Ingo */ -class Ingo_Script_Sieve extends Ingo_Script { - +class Ingo_Script_Sieve extends Ingo_Script +{ /** * The list of actions allowed (implemented) for this driver. * * @var array */ - var $_actions = array( + protected $_actions = array( Ingo_Storage::ACTION_KEEP, Ingo_Storage::ACTION_MOVE, Ingo_Storage::ACTION_DISCARD, @@ -32,7 +32,7 @@ class Ingo_Script_Sieve extends Ingo_Script { * * @var array */ - var $_categories = array( + protected $_categories = array( Ingo_Storage::ACTION_BLACKLIST, Ingo_Storage::ACTION_WHITELIST, Ingo_Storage::ACTION_VACATION, @@ -45,11 +45,25 @@ class Ingo_Script_Sieve extends Ingo_Script { * * @var array */ - var $_tests = array( - 'contains', 'not contain', 'is', 'not is', 'begins with', - 'not begins with', 'ends with', 'not ends with', 'exists', 'not exist', - 'less than', 'less than or equal to', 'equal', 'not equal', - 'greater than', 'greater than or equal to', 'regex', 'matches', + protected $_tests = array( + 'contains', + 'not contain', + 'is', + 'not is', + 'begins with', + 'not begins with', + 'ends with', + 'not ends with', + 'exists', + 'not exist', + 'less than', + 'less than or equal to', + 'equal', + 'not equal', + 'greater than', + 'greater than or equal to', + 'regex', + 'matches', 'not matches' ); @@ -58,7 +72,7 @@ class Ingo_Script_Sieve extends Ingo_Script { * * @var array */ - var $_types = array( + protected $_types = array( Ingo_Storage::TYPE_HEADER, Ingo_Storage::TYPE_SIZE, Ingo_Storage::TYPE_BODY @@ -69,49 +83,49 @@ class Ingo_Script_Sieve extends Ingo_Script { * * @var boolean */ - var $_casesensitive = true; + protected $_casesensitive = true; /** * Does the driver support setting IMAP flags? * * @var boolean */ - var $_supportIMAPFlags = true; + protected $_supportIMAPFlags = true; /** * Does the driver support the stop-script option? * * @var boolean */ - var $_supportStopScript = true; + protected $_supportStopScript = true; /** * Does the driver require a script file to be generated? * * @var boolean */ - var $_scriptfile = true; + protected $_scriptfile = true; /** * The blocks that make up the code. * * @var array */ - var $_blocks = array(); + protected $_blocks = array(); /** * The blocks that have to appear at the end of the code. * * @var array */ - var $_endBlocks = array(); + protected $_endBlocks = array(); /** * Returns a script previously generated with generate(). * * @return string The Sieve script. */ - function toCode() + public function toCode() { $code = "# Sieve Filter\n# " . _("Generated by Ingo (http://www.horde.org/ingo/)") . ' (' @@ -147,7 +161,7 @@ class Ingo_Script_Sieve extends Ingo_Script { * * @return string The string, UTF-8 encoded. */ - function encode($string) + public function encode($string) { return Horde_String::convertCharset($string, $this->_params['charset'], 'UTF-8'); } @@ -161,16 +175,14 @@ class Ingo_Script_Sieve extends Ingo_Script { * * @return string The escaped string. */ - function escapeString($string, $regexmode = false) + static public function escapeString($string, $regexmode = false) { /* Remove any backslashes in front of commas. */ $string = str_replace('\,', ',', $string); - if ($regexmode) { - return str_replace('"', addslashes('"'), $string); - } else { - return str_replace(array('\\', '"'), array(addslashes('\\'), addslashes('"')), $string); - } + return $regexmode + ? str_replace('"', addslashes('"'), $string) + : str_replace(array('\\', '"'), array(addslashes('\\'), addslashes('"')), $string); } /** @@ -179,7 +191,7 @@ class Ingo_Script_Sieve extends Ingo_Script { * @return boolean|string True if all rules are valid, an error message * otherwise. */ - function check() + public function check() { foreach ($this->_blocks as $block) { $res = $block->check(); @@ -197,7 +209,7 @@ class Ingo_Script_Sieve extends Ingo_Script { * * @return array A Sieve extension list. */ - function requires() + public function requires() { $requires = array(); foreach ($this->_blocks as $block) { @@ -210,13 +222,13 @@ class Ingo_Script_Sieve extends Ingo_Script { /** * Adds all blocks necessary for the forward rule. */ - function _addForwardBlocks() + protected function _addForwardBlocks() { if (!$this->_validRule(Ingo_Storage::ACTION_FORWARD)) { return; } - $forward = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FORWARD); + $forward = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_FORWARD); $fwd_addr = $forward->getForwardAddresses(); if (empty($fwd_addr)) { return; @@ -226,26 +238,26 @@ class Ingo_Script_Sieve extends Ingo_Script { foreach ($fwd_addr as $addr) { $addr = trim($addr); if (!empty($addr)) { - $action[] = new Sieve_Action_Redirect(array('address' => $addr)); + $action[] = new Ingo_Script_Sieve_Action_Redirect(array('address' => $addr)); } } if (count($action)) { if($forward->getForwardKeep()) { - $this->_endBlocks[] = new Sieve_Comment($this->encode(_("Forward Keep Action"))); - $if = new Sieve_If(new Sieve_Test_True()); - $if->setActions(array(new Sieve_Action_Keep(), - new Sieve_Action_Stop())); + $this->_endBlocks[] = new Ingo_Script_Sieve_Comment($this->encode(_("Forward Keep Action"))); + $if = new Ingo_Script_Sieve_If(new Ingo_Script_Sieve_Test_True()); + $if->setActions(array(new Ingo_Script_Sieve_Action_Keep(), + new Ingo_Script_Sieve_Action_Stop())); $this->_endBlocks[] = $if; } else { - $action[] = new Sieve_Action_Stop(); + $action[] = new Ingo_Script_Sieve_Action_Stop(); } } - $this->_blocks[] = new Sieve_Comment($this->encode(_("Forwards"))); + $this->_blocks[] = new Ingo_Script_Sieve_Comment($this->encode(_("Forwards"))); - $test = new Sieve_Test_True(); - $if = new Sieve_If($test); + $test = new Ingo_Script_Sieve_Test_True(); + $if = new Ingo_Script_Sieve_If($test); $if->setActions($action); $this->_blocks[] = $if; } @@ -253,13 +265,13 @@ class Ingo_Script_Sieve extends Ingo_Script { /** * Adds all blocks necessary for the blacklist rule. */ - function _addBlacklistBlocks() + protected function _addBlacklistBlocks() { if (!$this->_validRule(Ingo_Storage::ACTION_BLACKLIST)) { return; } - $blacklist = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_BLACKLIST); + $blacklist = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_BLACKLIST); $bl_addr = $blacklist->getBlacklist(); $folder = $blacklist->getBlacklistFolder(); if (empty($bl_addr)) { @@ -268,18 +280,18 @@ class Ingo_Script_Sieve extends Ingo_Script { $action = array(); if (empty($folder)) { - $action[] = new Sieve_Action_Discard(); + $action[] = new Ingo_Script_Sieve_Action_Discard(); } elseif ($folder == Ingo::BLACKLIST_MARKER) { - $action[] = new Sieve_Action_Addflag(array('flags' => Ingo_Storage::FLAG_DELETED)); - $action[] = new Sieve_Action_Keep(); - $action[] = new Sieve_Action_Removeflag(array('flags' => Ingo_Storage::FLAG_DELETED)); + $action[] = new Ingo_Script_Sieve_Action_Addflag(array('flags' => Ingo_Storage::FLAG_DELETED)); + $action[] = new Ingo_Script_Sieve_Action_Keep(); + $action[] = new Ingo_Script_Sieve_Action_Removeflag(array('flags' => Ingo_Storage::FLAG_DELETED)); } else { - $action[] = new Sieve_Action_Fileinto(array_merge($this->_params, array('folder' => $folder))); + $action[] = new Ingo_Script_Sieve_Action_Fileinto(array_merge($this->_params, array('folder' => $folder))); } - $action[] = new Sieve_Action_Stop(); + $action[] = new Ingo_Script_Sieve_Action_Stop(); - $this->_blocks[] = new Sieve_Comment($this->encode(_("Blacklisted Addresses"))); + $this->_blocks[] = new Ingo_Script_Sieve_Comment($this->encode(_("Blacklisted Addresses"))); /* Split the test up to only do 5 addresses at a time. */ $temp = array(); @@ -294,15 +306,15 @@ class Ingo_Script_Sieve extends Ingo_Script { } } if (count($temp) == 5) { - $test = new Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'addresses' => implode("\n", $temp))); - $if = new Sieve_If($test); + $test = new Ingo_Script_Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'addresses' => implode("\n", $temp))); + $if = new Ingo_Script_Sieve_If($test); $if->setActions($action); $this->_blocks[] = $if; $temp = array(); } if (count($wildcards) == 5) { - $test = new Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'match-type' => ':matches', 'addresses' => implode("\n", $wildcards))); - $if = new Sieve_If($test); + $test = new Ingo_Script_Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'match-type' => ':matches', 'addresses' => implode("\n", $wildcards))); + $if = new Ingo_Script_Sieve_If($test); $if->setActions($action); $this->_blocks[] = $if; $wildcards = array(); @@ -310,15 +322,15 @@ class Ingo_Script_Sieve extends Ingo_Script { } if ($temp) { - $test = new Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'addresses' => implode("\n", $temp))); - $if = new Sieve_If($test); + $test = new Ingo_Script_Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'addresses' => implode("\n", $temp))); + $if = new Ingo_Script_Sieve_If($test); $if->setActions($action); $this->_blocks[] = $if; } if ($wildcards) { - $test = new Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'match-type' => ':matches', 'addresses' => implode("\n", $wildcards))); - $if = new Sieve_If($test); + $test = new Ingo_Script_Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'match-type' => ':matches', 'addresses' => implode("\n", $wildcards))); + $if = new Ingo_Script_Sieve_If($test); $if->setActions($action); $this->_blocks[] = $if; } @@ -327,7 +339,7 @@ class Ingo_Script_Sieve extends Ingo_Script { /** * Adds all blocks necessary for the whitelist rule. */ - function _addWhitelistBlocks() + protected function _addWhitelistBlocks() { if (!$this->_validRule(Ingo_Storage::ACTION_WHITELIST)) { return; @@ -339,11 +351,11 @@ class Ingo_Script_Sieve extends Ingo_Script { return; } - $this->_blocks[] = new Sieve_Comment($this->encode(_("Whitelisted Addresses"))); + $this->_blocks[] = new Ingo_Script_Sieve_Comment($this->encode(_("Whitelisted Addresses"))); - $action = array(new Sieve_Action_Keep(), new Sieve_Action_Stop()); - $test = new Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'addresses' => implode("\n", $wl_addr))); - $if = new Sieve_If($test); + $action = array(new Ingo_Script_Sieve_Action_Keep(), new Ingo_Script_Sieve_Action_Stop()); + $test = new Ingo_Script_Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'addresses' => implode("\n", $wl_addr))); + $if = new Ingo_Script_Sieve_If($test); $if->setActions($action); $this->_blocks[] = $if; } @@ -351,7 +363,7 @@ class Ingo_Script_Sieve extends Ingo_Script { /** * Adds all blocks necessary for the vacation rule. */ - function _addVacationBlocks() + protected function _addVacationBlocks() { if (!$this->_validRule(Ingo_Storage::ACTION_VACATION)) { return; @@ -379,26 +391,26 @@ class Ingo_Script_Sieve extends Ingo_Script { ); $action = $tests = array(); - $action[] = new Sieve_Action_Vacation($vals); + $action[] = new Ingo_Script_Sieve_Action_Vacation($vals); if ($vacation->getVacationIgnorelist()) { $mime_headers = new Horde_Mime_Headers(); $headers = $mime_headers->listHeaders(); $headers['Mailing-List'] = null; - $tmp = new Sieve_Test_Exists(array('headers' => implode("\n", array_keys($headers)))); - $tests[] = new Sieve_Test_Not($tmp); + $tmp = new Ingo_Script_Sieve_Test_Exists(array('headers' => implode("\n", array_keys($headers)))); + $tests[] = new Ingo_Script_Sieve_Test_Not($tmp); $vals = array('headers' => 'Precedence', 'match-type' => ':is', 'strings' => "list\nbulk\njunk", 'comparator' => 'i;ascii-casemap'); - $tmp = new Sieve_Test_Header($vals); - $tests[] = new Sieve_Test_Not($tmp); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); + $tests[] = new Ingo_Script_Sieve_Test_Not($tmp); $vals = array('headers' => 'To', 'match-type' => ':matches', 'strings' => 'Multiple recipients of*', 'comparator' => 'i;ascii-casemap'); - $tmp = new Sieve_Test_Header($vals); - $tests[] = new Sieve_Test_Not($tmp); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); + $tests[] = new Ingo_Script_Sieve_Test_Not($tmp); } $addrs = array(); @@ -410,15 +422,15 @@ class Ingo_Script_Sieve extends Ingo_Script { } if ($addrs) { - $tmp = new Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'addresses' => implode("\n", $addrs))); - $tests[] = new Sieve_Test_Not($tmp); + $tmp = new Ingo_Script_Sieve_Test_Address(array('headers' => "From\nSender\nResent-From", 'addresses' => implode("\n", $addrs))); + $tests[] = new Ingo_Script_Sieve_Test_Not($tmp); } - $this->_blocks[] = new Sieve_Comment($this->encode(_("Vacation"))); + $this->_blocks[] = new Ingo_Script_Sieve_Comment($this->encode(_("Vacation"))); if ($tests) { - $test = new Sieve_Test_Allof($tests); - $if = new Sieve_If($test); + $test = new Ingo_Script_Sieve_Test_Allof($tests); + $if = new Ingo_Script_Sieve_If($test); $if->setActions($action); $this->_blocks[] = $if; } else { @@ -429,21 +441,21 @@ class Ingo_Script_Sieve extends Ingo_Script { /** * Adds all blocks necessary for the spam rule. */ - function _addSpamBlocks() + protected function _addSpamBlocks() { if (!$this->_validRule(Ingo_Storage::ACTION_SPAM)) { return; } - $spam = &$GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_SPAM); + $spam = $GLOBALS['ingo_storage']->retrieve(Ingo_Storage::ACTION_SPAM); if ($spam === false) { return; } - $this->_blocks[] = new Sieve_Comment($this->encode(_("Spam Filter"))); + $this->_blocks[] = new Ingo_Script_Sieve_Comment($this->encode(_("Spam Filter"))); $actions = array(); - $actions[] = new Sieve_Action_Fileinto(array_merge($this->_params, array('folder' => $spam->getSpamFolder()))); + $actions[] = new Ingo_Script_Sieve_Action_Fileinto(array_merge($this->_params, array('folder' => $spam->getSpamFolder()))); if ($this->_params['spam_compare'] == 'numeric') { $vals = array( @@ -451,7 +463,7 @@ class Ingo_Script_Sieve extends Ingo_Script { 'comparison' => 'ge', 'value' => $spam->getSpamLevel(), ); - $test = new Sieve_Test_Relational($vals); + $test = new Ingo_Script_Sieve_Test_Relational($vals); } elseif ($this->_params['spam_compare'] == 'string') { $vals = array( 'headers' => $this->_params['spam_header'], @@ -460,12 +472,12 @@ class Ingo_Script_Sieve extends Ingo_Script { $spam->getSpamLevel()), 'comparator' => 'i;ascii-casemap', ); - $test = new Sieve_Test_Header($vals); + $test = new Ingo_Script_Sieve_Test_Header($vals); } - $actions[] = new Sieve_Action_Stop(); + $actions[] = new Ingo_Script_Sieve_Action_Stop(); - $if = new Sieve_If($test); + $if = new Ingo_Script_Sieve_If($test); $if->setActions($actions); $this->_blocks[] = $if; } @@ -476,7 +488,7 @@ class Ingo_Script_Sieve extends Ingo_Script { * * @return string The Sieve script. */ - function generate() + public function generate() { global $ingo_storage; @@ -493,74 +505,74 @@ class Ingo_Script_Sieve extends Ingo_Script { switch ($filter['action']) { case Ingo_Storage::ACTION_KEEP: if (!empty($filter['flags'])) { - $action[] = new Sieve_Action_Addflag(array('flags' => $filter['flags'])); + $action[] = new Ingo_Script_Sieve_Action_Addflag(array('flags' => $filter['flags'])); } - $action[] = new Sieve_Action_Keep(); + $action[] = new Ingo_Script_Sieve_Action_Keep(); if (!empty($filter['flags'])) { - $action[] = new Sieve_Action_RemoveFlag(array('flags' => $filter['flags'])); + $action[] = new Ingo_Script_Sieve_Action_RemoveFlag(array('flags' => $filter['flags'])); } break; case Ingo_Storage::ACTION_DISCARD: - $action[] = new Sieve_Action_Discard(); + $action[] = new Ingo_Script_Sieve_Action_Discard(); break; case Ingo_Storage::ACTION_MOVE: if (!empty($filter['flags'])) { - $action[] = new Sieve_Action_Addflag(array('flags' => $filter['flags'])); + $action[] = new Ingo_Script_Sieve_Action_Addflag(array('flags' => $filter['flags'])); } - $action[] = new Sieve_Action_Fileinto(array_merge($this->_params, array('folder' => $filter['action-value']))); + $action[] = new Ingo_Script_Sieve_Action_Fileinto(array_merge($this->_params, array('folder' => $filter['action-value']))); if (!empty($filter['flags'])) { - $action[] = new Sieve_Action_RemoveFlag(array('flags' => $filter['flags'])); + $action[] = new Ingo_Script_Sieve_Action_RemoveFlag(array('flags' => $filter['flags'])); } break; case Ingo_Storage::ACTION_REJECT: - $action[] = new Sieve_Action_Reject(array('reason' => $filter['action-value'])); + $action[] = new Ingo_Script_Sieve_Action_Reject(array('reason' => $filter['action-value'])); break; case Ingo_Storage::ACTION_REDIRECT: - $action[] = new Sieve_Action_Redirect(array('address' => $filter['action-value'])); + $action[] = new Ingo_Script_Sieve_Action_Redirect(array('address' => $filter['action-value'])); break; case Ingo_Storage::ACTION_REDIRECTKEEP: if (!empty($filter['flags'])) { - $action[] = new Sieve_Action_Addflag(array('flags' => $filter['flags'])); + $action[] = new Ingo_Script_Sieve_Action_Addflag(array('flags' => $filter['flags'])); } - $action[] = new Sieve_Action_Redirect(array('address' => $filter['action-value'])); - $action[] = new Sieve_Action_Keep(); + $action[] = new Ingo_Script_Sieve_Action_Redirect(array('address' => $filter['action-value'])); + $action[] = new Ingo_Script_Sieve_Action_Keep(); if (!empty($filter['flags'])) { - $action[] = new Sieve_Action_RemoveFlag(array('flags' => $filter['flags'])); + $action[] = new Ingo_Script_Sieve_Action_RemoveFlag(array('flags' => $filter['flags'])); } break; case Ingo_Storage::ACTION_MOVEKEEP: if (!empty($filter['flags'])) { - $action[] = new Sieve_Action_Addflag(array('flags' => $filter['flags'])); + $action[] = new Ingo_Script_Sieve_Action_Addflag(array('flags' => $filter['flags'])); } - $action[] = new Sieve_Action_Keep(); - $action[] = new Sieve_Action_Fileinto(array_merge($this->_params, array('folder' => $filter['action-value']))); + $action[] = new Ingo_Script_Sieve_Action_Keep(); + $action[] = new Ingo_Script_Sieve_Action_Fileinto(array_merge($this->_params, array('folder' => $filter['action-value']))); if (!empty($filter['flags'])) { - $action[] = new Sieve_Action_RemoveFlag(array('flags' => $filter['flags'])); + $action[] = new Ingo_Script_Sieve_Action_RemoveFlag(array('flags' => $filter['flags'])); } break; case Ingo_Storage::ACTION_FLAGONLY: if (!empty($filter['flags'])) { - $action[] = new Sieve_Action_Addflag(array('flags' => $filter['flags'])); + $action[] = new Ingo_Script_Sieve_Action_Addflag(array('flags' => $filter['flags'])); } break; case Ingo_Storage::ACTION_NOTIFY: - $action[] = new Sieve_Action_Notify(array('address' => $filter['action-value'], 'name' => $filter['name'])); + $action[] = new Ingo_Script_Sieve_Action_Notify(array('address' => $filter['action-value'], 'name' => $filter['name'])); break; case Ingo_Storage::ACTION_WHITELIST: @@ -584,72 +596,72 @@ class Ingo_Script_Sieve extends Ingo_Script { continue 2; } - $this->_blocks[] = new Sieve_Comment($this->encode($filter['name'])); + $this->_blocks[] = new Ingo_Script_Sieve_Comment($this->encode($filter['name'])); if ($filter['stop']) { - $action[] = new Sieve_Action_Stop(); + $action[] = new Ingo_Script_Sieve_Action_Stop(); } - $test = new Sieve_Test(); + $test = new Ingo_Script_Sieve_Test(); if ($filter['combine'] == Ingo_Storage::COMBINE_ANY) { - $test = new Sieve_Test_Anyof(); + $test = new Ingo_Script_Sieve_Test_Anyof(); } else { - $test = new Sieve_Test_Allof(); + $test = new Ingo_Script_Sieve_Test_Allof(); } foreach ($filter['conditions'] as $condition) { $tmp = ''; switch ($condition['match']) { case 'equal': - $tmp = new Sieve_Test_Relational(array('comparison' => 'eq', 'headers' => $condition['field'], 'value' => $condition['value'])); + $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'eq', 'headers' => $condition['field'], 'value' => $condition['value'])); $test->addTest($tmp); break; case 'not equal': - $tmp = new Sieve_Test_Relational(array('comparison' => 'ne', 'headers' => $condition['field'], 'value' => $condition['value'])); + $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'ne', 'headers' => $condition['field'], 'value' => $condition['value'])); $test->addTest($tmp); break; case 'less than': if ($condition['field'] == 'Size') { /* Message Size Test. */ - $tmp = new Sieve_Test_Size(array('comparison' => ':under', 'size' => $condition['value'])); + $tmp = new Ingo_Script_Sieve_Test_Size(array('comparison' => ':under', 'size' => $condition['value'])); } else { /* Relational Test. */ - $tmp = new Sieve_Test_Relational(array('comparison' => 'lt', 'headers' => $condition['field'], 'value' => $condition['value'])); + $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'lt', 'headers' => $condition['field'], 'value' => $condition['value'])); } $test->addTest($tmp); break; case 'less than or equal to': - $tmp = new Sieve_Test_Relational(array('comparison' => 'le', 'headers' => $condition['field'], 'value' => $condition['value'])); + $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'le', 'headers' => $condition['field'], 'value' => $condition['value'])); $test->addTest($tmp); break; case 'greater than': if ($condition['field'] == 'Size') { /* Message Size Test. */ - $tmp = new Sieve_Test_Size(array('comparison' => ':over', 'size' => $condition['value'])); + $tmp = new Ingo_Script_Sieve_Test_Size(array('comparison' => ':over', 'size' => $condition['value'])); } else { /* Relational Test. */ - $tmp = new Sieve_Test_Relational(array('comparison' => 'gt', 'headers' => $condition['field'], 'value' => $condition['value'])); + $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'gt', 'headers' => $condition['field'], 'value' => $condition['value'])); } $test->addTest($tmp); break; case 'greater than or equal to': - $tmp = new Sieve_Test_Relational(array('comparison' => 'ge', 'headers' => $condition['field'], 'value' => $condition['value'])); + $tmp = new Ingo_Script_Sieve_Test_Relational(array('comparison' => 'ge', 'headers' => $condition['field'], 'value' => $condition['value'])); $test->addTest($tmp); break; case 'exists': - $tmp = new Sieve_Test_Exists(array('headers' => $condition['field'])); + $tmp = new Ingo_Script_Sieve_Test_Exists(array('headers' => $condition['field'])); $test->addTest($tmp); break; case 'not exist': - $tmp = new Sieve_Test_Exists(array('headers' => $condition['field'])); - $test->addTest(new Sieve_Test_Not($tmp)); + $tmp = new Ingo_Script_Sieve_Test_Exists(array('headers' => $condition['field'])); + $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; case 'contains': @@ -692,11 +704,11 @@ class Ingo_Script_Sieve extends Ingo_Script { case 'contains': $vals['match-type'] = ':contains'; if ($use_address_test) { - $tmp = new Sieve_Test_Address($vals); + $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { - $tmp = new Sieve_Test_Body($vals); + $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { - $tmp = new Sieve_Test_Header($vals); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); } $test->addTest($tmp); break; @@ -704,23 +716,23 @@ class Ingo_Script_Sieve extends Ingo_Script { case 'not contain': $vals['match-type'] = ':contains'; if ($use_address_test) { - $tmp = new Sieve_Test_Address($vals); + $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { - $tmp = new Sieve_Test_Body($vals); + $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { - $tmp = new Sieve_Test_Header($vals); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); } - $test->addTest(new Sieve_Test_Not($tmp)); + $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; case 'is': $vals['match-type'] = ':is'; if ($use_address_test) { - $tmp = new Sieve_Test_Address($vals); + $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { - $tmp = new Sieve_Test_Body($vals); + $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { - $tmp = new Sieve_Test_Header($vals); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); } $test->addTest($tmp); break; @@ -728,13 +740,13 @@ class Ingo_Script_Sieve extends Ingo_Script { case 'not is': $vals['match-type'] = ':is'; if ($use_address_test) { - $tmp = new Sieve_Test_Address($vals); + $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { - $tmp = new Sieve_Test_Body($vals); + $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { - $tmp = new Sieve_Test_Header($vals); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); } - $test->addTest(new Sieve_Test_Not($tmp)); + $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; case 'begins with': @@ -749,7 +761,7 @@ class Ingo_Script_Sieve extends Ingo_Script { } else { $vals['addresses'] .= '*'; } - $tmp = new Sieve_Test_Address($vals); + $tmp = new Ingo_Script_Sieve_Test_Address($vals); } else { $add_arr = preg_split('(\r\n|\n|\r)', $vals['strings']); if (count($add_arr) > 1) { @@ -761,9 +773,9 @@ class Ingo_Script_Sieve extends Ingo_Script { $vals['strings'] .= '*'; } if ($condition['field'] == 'Body') { - $tmp = new Sieve_Test_Body($vals); + $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { - $tmp = new Sieve_Test_Header($vals); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); } } $test->addTest($tmp); @@ -781,7 +793,7 @@ class Ingo_Script_Sieve extends Ingo_Script { } else { $vals['addresses'] .= '*'; } - $tmp = new Sieve_Test_Address($vals); + $tmp = new Ingo_Script_Sieve_Test_Address($vals); } else { $add_arr = preg_split('(\r\n|\n|\r)', $vals['strings']); if (count($add_arr) > 1) { @@ -793,12 +805,12 @@ class Ingo_Script_Sieve extends Ingo_Script { $vals['strings'] .= '*'; } if ($condition['field'] == 'Body') { - $tmp = new Sieve_Test_Body($vals); + $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { - $tmp = new Sieve_Test_Header($vals); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); } } - $test->addTest(new Sieve_Test_Not($tmp)); + $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; case 'ends with': @@ -813,7 +825,7 @@ class Ingo_Script_Sieve extends Ingo_Script { } else { $vals['addresses'] = '*' . $vals['addresses']; } - $tmp = new Sieve_Test_Address($vals); + $tmp = new Ingo_Script_Sieve_Test_Address($vals); } else { $add_arr = preg_split('(\r\n|\n|\r)', $vals['strings']); if (count($add_arr) > 1) { @@ -825,9 +837,9 @@ class Ingo_Script_Sieve extends Ingo_Script { $vals['strings'] = '*' . $vals['strings']; } if ($condition['field'] == 'Body') { - $tmp = new Sieve_Test_Body($vals); + $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { - $tmp = new Sieve_Test_Header($vals); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); } } $test->addTest($tmp); @@ -845,7 +857,7 @@ class Ingo_Script_Sieve extends Ingo_Script { } else { $vals['addresses'] = '*' . $vals['addresses']; } - $tmp = new Sieve_Test_Address($vals); + $tmp = new Ingo_Script_Sieve_Test_Address($vals); } else { $add_arr = preg_split('(\r\n|\n|\r)', $vals['strings']); if (count($add_arr) > 1) { @@ -857,22 +869,22 @@ class Ingo_Script_Sieve extends Ingo_Script { $vals['strings'] = '*' . $vals['strings']; } if ($condition['field'] == 'Body') { - $tmp = new Sieve_Test_Body($vals); + $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { - $tmp = new Sieve_Test_Header($vals); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); } } - $test->addTest(new Sieve_Test_Not($tmp)); + $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; case 'regex': $vals['match-type'] = ':regex'; if ($use_address_test) { - $tmp = new Sieve_Test_Address($vals); + $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { - $tmp = new Sieve_Test_Body($vals); + $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { - $tmp = new Sieve_Test_Header($vals); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); } $test->addTest($tmp); break; @@ -880,11 +892,11 @@ class Ingo_Script_Sieve extends Ingo_Script { case 'matches': $vals['match-type'] = ':matches'; if ($use_address_test) { - $tmp = new Sieve_Test_Address($vals); + $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { - $tmp = new Sieve_Test_Body($vals); + $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { - $tmp = new Sieve_Test_Header($vals); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); } $test->addTest($tmp); break; @@ -892,19 +904,19 @@ class Ingo_Script_Sieve extends Ingo_Script { case 'not matches': $vals['match-type'] = ':matches'; if ($use_address_test) { - $tmp = new Sieve_Test_Address($vals); + $tmp = new Ingo_Script_Sieve_Test_Address($vals); } elseif ($condition['field'] == 'Body') { - $tmp = new Sieve_Test_Body($vals); + $tmp = new Ingo_Script_Sieve_Test_Body($vals); } else { - $tmp = new Sieve_Test_Header($vals); + $tmp = new Ingo_Script_Sieve_Test_Header($vals); } - $test->addTest(new Sieve_Test_Not($tmp)); + $test->addTest(new Ingo_Script_Sieve_Test_Not($tmp)); break; } } } - $if = new Sieve_If($test); + $if = new Ingo_Script_Sieve_If($test); $if->setActions($action); $this->_blocks[] = $if; } @@ -918,2062 +930,3 @@ class Ingo_Script_Sieve extends Ingo_Script { } } - -/** - * The Sieve_If class represents a Sieve If Statement - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_If { - - /** - * The Sieve_Test object for the if test. - * - * @var Sieve_Test - */ - var $_test; - - /** - * A list of Sieve_Action objects that go into the if clause. - * - * @var array - */ - var $_actions = array(); - - /** - * A list of Sieve_Elseif objects that create optional elsif clauses. - * - * @var array - */ - var $_elsifs = array(); - - /** - * A Sieve_Else object that creates an optional else clause. - * - * @var Sieve_Else - */ - var $_else; - - /** - * Constructor. - * - * @param Sieve_Test $test A Sieve_Test object. - */ - function Sieve_If($test = null) - { - if (is_null($test)) { - $this->_test = new Sieve_Test_False(); - } else { - $this->_test = $test; - } - - $this->_actions[] = new Sieve_Action_Keep(); - $this->_else = new Sieve_Else(); - } - - function getTest() - { - return $this->_test; - } - - function setTest($test) - { - $this->_test = $test; - } - - function getActions() - { - return $this->_actions; - } - - function setActions($actions) - { - $this->_actions = $actions; - } - - function getElsifs() - { - return $this->_elsifs; - } - - function setElsifs($elsifs) - { - $this->_elsifs = $elsifs; - } - - function addElsif($elsif) - { - $this->_elsifs[] = $elsif; - } - - function getElse() - { - return $this->_else; - } - - function setElse($else) - { - $this->_else = $else; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - $code = 'if ' . $this->_test->toCode() . " { \n"; - foreach ($this->_actions as $action) { - $code .= ' ' . $action->toCode() . "\n"; - } - $code .= "} "; - - foreach ($this->_elsifs as $elsif) { - $code .= $elsif->toCode(); - } - - $code .= $this->_else->toCode(); - - return $code . "\n"; - } - - /** - * Checks if all sub-rules are valid. - * - * @return boolean|string True if all rules are valid, an error message - * otherwise. - */ - function check() - { - $res = $this->_test->check(); - if ($res !== true) { - return $res; - } - - foreach ($this->_elsifs as $elsif) { - $res = $elsif->check(); - if ($res !== true) { - return $res; - } - } - - $res = $this->_else->check(); - if ($res !== true) { - return $res; - } - - foreach ($this->_actions as $action) { - $res = $action->check(); - if ($res !== true) { - return $res; - } - } - - return true; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - $requires = array(); - - foreach ($this->_actions as $action) { - $requires = array_merge($requires, $action->requires()); - } - - foreach ($this->_elsifs as $elsif) { - $requires = array_merge($requires, $elsif->requires()); - } - - $requires = array_merge($requires, $this->_test->requires(), $this->_else->requires()); - - return $requires; - } - -} - -/** - * The Sieve_Else class represents a Sieve Else Statement - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Else { - - /** - * A list of Sieve_Action objects that go into the else clause. - * - * @var array - */ - var $_actions = array(); - - /** - * Constructor. - * - * @param Sieve_Action|array $actions A Sieve_Action object or a list of - * Sieve_Action objects. - */ - function Sieve_Else($actions = null) - { - if (is_array($actions)) { - $this->_actions = $actions; - } elseif (!is_null($actions)) { - $this->_actions[] = $actions; - } - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - if (count($this->_actions) == 0) { - return ''; - } - - $code = 'else' . " { \n"; - foreach ($this->_actions as $action) { - $code .= ' ' . $action->toCode() . "\n"; - } - $code .= "} "; - - return $code; - } - - function setActions($actions) - { - $this->_actions = $actions; - } - - function getActions() - { - return $this->_actions; - } - - /** - * Checks if all sub-rules are valid. - * - * @return boolean|string True if all rules are valid, an error message - * otherwise. - */ - function check() - { - foreach ($this->_actions as $action) { - $res = $action->check(); - if ($res !== true) { - return $res; - } - } - - return true; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - $requires = array(); - - foreach ($this->_actions as $action) { - $requires = array_merge($requires, $action->requires()); - } - - return $requires; - } - -} - -/** - * The Sieve_Elsif class represents a Sieve Elsif Statement - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Elsif { - - /** - * The Sieve_Test object for the if test. - * - * @var Sieve_Test - */ - var $_test; - - /** - * A list of Sieve_Action objects that go into the if clause. - * - * @var array - */ - var $_actions = array(); - - /** - * Constructor. - * - * @param Sieve_Test $test A Sieve_Test object. - */ - function Sieve_Elsif($test = null) - { - if (is_null($test)) { - $this->_test = new Sieve_Test_False(); - } else { - $this->_test = $test; - } - $this->_actions[] = new Sieve_Action_Keep(); - } - - function getTest() - { - return $this->_test; - } - - function setTest($test) - { - $this->_test = $test; - } - - function getActions() - { - return $this->_actions; - } - - function setActions($actions) - { - $this->_actions = $actions; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - $code = 'elsif ' . $this->_test->toCode() . " { \n"; - foreach ($this->_actions as $action) { - $code .= ' ' . $action->toCode() . "\n"; - } - $code .= "} "; - - return $code; - } - - /** - * Checks if all sub-rules are valid. - * - * @return boolean|string True if all rules are valid, an error message - * otherwise. - */ - function check() - { - $res = $this->_test->check(); - if ($res !== true) { - return $res; - } - - foreach ($this->_actions as $action) { - $res = $action->check(); - if ($res !== true) { - return $res; - } - } - - return true; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - $requires = array(); - - foreach ($this->_actions as $action) { - $requires = array_merge($requires, $action->requires()); - } - - $requires = array_merge($requires, $this->_test->requires()); - - return $requires; - } - -} - -/** - * The Sieve_Test class represents a Sieve Test. - * - * A test is a piece of code that evaluates to true or false. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Test { - - /** - * Any necessary test parameters. - * - * @var array - */ - var $_vars = array(); - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'toCode() Function Not Implemented in class ' . get_class($this); - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - return 'check() Function Not Implemented in class ' . get_class($this); - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - return array(); - } - -} - -/** - * The Sieve_Test_True class represents a test that always evaluates to true. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Test_True extends Sieve_Test { - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'true'; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - return true; - } - -} - -/** - * The Sieve_Test_False class represents a test that always evaluates to - * false. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Test_False extends Sieve_Test { - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'false'; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - return true; - } - -} - -/** - * The Sieve_Test_Allof class represents a Allof test structure. - * - * Equivalent to a logical AND of all the tests it contains. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Test_Allof extends Sieve_Test { - - var $_tests = array(); - - /** - * Constructor. - * - * @param Sieve_Test|array $test A Sieve_Test object or a list of - * Sieve_Test objects. - */ - function Sieve_Test_Allof($test = null) - { - if (is_array($test)) { - $this->_tests = $test; - } elseif (!is_null($test)) { - $this->_tests[] = $test; - } - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - $code = ''; - if (count($this->_tests) > 1) { - $testlist = ''; - foreach ($this->_tests as $test) { - $testlist .= (empty($testlist)) ? '' : ', '; - $testlist .= trim($test->toCode()); - } - - $code = "allof ( $testlist )"; - } elseif (count($this->_tests) == 1) { - $code = $this->_tests[0]->toCode(); - } else { - return 'true'; - } - return $code; - } - - /** - * Checks if all sub-rules are valid. - * - * @return boolean|string True if all rules are valid, an error message - * otherwise. - */ - function check() - { - foreach ($this->_tests as $test) { - $res = $test->check(); - if ($res !== true) { - return $res; - } - } - - return true; - } - - function addTest($test) - { - $this->_tests[] = $test; - } - - function getTests() - { - return $this->_tests; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - $requires = array(); - - foreach ($this->_tests as $test) { - $requires = array_merge($requires, $test->requires()); - } - - return $requires; - } - -} - -/** - * The Sieve_Test_Anyof class represents a Anyof test structure. - * - * Equivalent to a logical OR of all the tests it contains. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Test_Anyof extends Sieve_Test { - - var $_tests = array(); - - /** - * Constructor. - * - * @param Sieve_Test|array $test A Sieve_Test object or a list of - * Sieve_Test objects. - */ - function Sieve_Test_Anyof($test = null) - { - if (is_array($test)) { - $this->_tests = $test; - } elseif (!is_null($test)) { - $this->_tests[] = $test; - } - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - $testlist = ''; - if (count($this->_tests) > 1) { - $testlist = ''; - foreach ($this->_tests as $test) { - $testlist .= (empty($testlist)) ? '' : ', '; - $testlist .= trim($test->toCode()); - } - - $code = "anyof ( $testlist )"; - } elseif (count($this->_tests) == 1) { - $code = $this->_tests[0]->toCode(); - } else { - return 'true'; - } - return $code; - } - - function addTest($test) - { - $this->_tests[] = $test; - } - - function getTests() - { - return $this->_tests; - } - - /** - * Checks if all sub-rules are valid. - * - * @return boolean|string True if all rules are valid, an error message - * otherwise. - */ - function check() - { - foreach ($this->_tests as $test) { - $res = $test->check(); - if ($res !== true) { - return $res; - } - } - - return true; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - $requires = array(); - - foreach ($this->_tests as $test) { - $requires = array_merge($requires, $test->requires()); - } - - return $requires; - } - -} - -/** - * The Sieve_Test_Relational class represents a relational test. - * - * @author Todd Merritt - * @package Ingo - */ -class Sieve_Test_Relational extends Sieve_Test { - - /** - * Constructor. - * - * @param array $vars Any required parameters. - */ - function Sieve_Test_Relational($vars = array()) - { - $this->_vars['comparison'] = (isset($vars['comparison'])) ? $vars['comparison'] : ''; - $this->_vars['headers'] = (isset($vars['headers'])) ? $vars['headers'] : ''; - $this->_vars['value'] = (isset($vars['value'])) ? $vars['value'] : 0; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - $code = 'header :value "' . - $this->_vars['comparison'] . '" ' . - ':comparator "i;ascii-numeric" '; - - $headers = preg_split('(\r\n|\n|\r)', $this->_vars['headers']); - $header_count = count($headers); - - if ($header_count > 1) { - $code .= "["; - $headerstr = ''; - - foreach ($headers as $val) { - $headerstr .= (empty($headerstr) ? '"' : ', "') . - Ingo_Script_Sieve::escapeString($val) . '"'; - } - - $code .= $headerstr . '] '; - $headerstr = '[' . $headerstr . ']'; - } elseif ($header_count == 1) { - $code .= '"' . Ingo_Script_Sieve::escapeString($headers[0]) . '" '; - $headerstr = Ingo_Script_Sieve::escapeString($headers[0]); - } - - $code .= '["' . $this->_vars['value'] . '"]'; - - // Add workarounds for negative numbers - works only if the comparison - // value is positive. Sieve doesn't support comparisons of negative - // numbers at all so this is the best we can do. - switch ($this->_vars['comparison']) { - case 'gt': - case 'ge': - case 'eq': - // Greater than, greater or equal, equal: number must be - // non-negative. - return 'allof ( not header :comparator "i;ascii-casemap" :contains "' - . $headerstr . '" "-", ' . $code . ' )'; - break; - case 'lt': - case 'le': - case 'ne': - // Less than, less or equal, nonequal: also match negative numbers - return 'anyof ( header :comparator "i;ascii-casemap" :contains "' - . $headerstr . '" "-", ' . $code . ' )'; - break; - } - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - $headers = preg_split('(\r\n|\n|\r)', $this->_vars['headers']); - return $headers ? true : _("No headers specified"); - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - return array('relational', 'comparator-i;ascii-numeric'); - } - -} - -/** - * The Sieve_Test_Size class represents a message size test. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Test_Size extends Sieve_Test { - - /** - * Constructor. - * - * @param array $vars Any required parameters. - */ - function Sieve_Test_Size($vars = array()) - { - $this->_vars['comparison'] = (isset($vars['comparison'])) ? $vars['comparison'] : ''; - $this->_vars['size'] = (isset($vars['size'])) ? $vars['size'] : ''; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'size ' . $this->_vars['comparison'] . ' ' . $this->_vars['size']; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - if (!(isset($this->_vars['comparison']) && - isset($this->_vars['size']))) { - return false; - } - - return true; - } - -} - -/** - * The Sieve_Test_Not class represents the inverse of a given test. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Test_Not extends Sieve_Test { - - var $_test = array(); - - /** - * Constructor. - * - * @param Sieve_Test $test A Sieve_Test object. - */ - function Sieve_Test_Not($test) - { - $this->_test = $test; - } - - /** - * Checks if the sub-rule is valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - return $this->_test->check(); - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'not ' . $this->_test->toCode(); - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - return $this->_test->requires(); - } - -} - -/** - * The Sieve_Test_Exists class represents a test for the existsance of one or - * more headers in a message. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Test_Exists extends Sieve_Test { - - /** - * Constructor. - * - * @param array $vars Any required parameters. - */ - function Sieve_Test_Exists($vars = array()) - { - $this->_vars['headers'] = (isset($vars['headers'])) ? $vars['headers'] : ''; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - $headers = preg_split('(\r\n|\n|\r)', $this->_vars['headers']); - if (!$headers) { - return _("No headers specified"); - } - - return true; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - $code = 'exists '; - $headers = preg_split('(\r\n|\n|\r)', $this->_vars['headers']); - if (count($headers) > 1) { - $code .= "["; - $headerstr = ''; - foreach ($headers as $header) { - $headerstr .= (empty($headerstr) ? '"' : ', "') . - Ingo_Script_Sieve::escapeString($header) . '"'; - } - $code .= $headerstr . "] "; - } elseif (count($headers) == 1) { - $code .= '"' . Ingo_Script_Sieve::escapeString($headers[0]) . '" '; - } else { - return "**error** No Headers Specified"; - } - - return $code; - } - -} - -/** - * The Sieve_Test_Address class represents a test on parts or all of the - * addresses in the given fields. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Test_Address extends Sieve_Test { - - /** - * Constructor. - * - * @param array $vars Any required parameters. - */ - function Sieve_Test_Address($vars) - { - $this->_vars['headers'] = (isset($vars['headers'])) ? $vars['headers'] : ''; - $this->_vars['comparator'] = (isset($vars['comparator'])) ? $vars['comparator'] : 'i;ascii-casemap'; - $this->_vars['match-type'] = (isset($vars['match-type'])) ? $vars['match-type'] : ':is'; - $this->_vars['address-part'] = (isset($vars['address-part'])) ? $vars['address-part'] : ':all'; - $this->_vars['addresses'] = (isset($vars['addresses'])) ? $vars['addresses'] : ''; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - $headers = preg_split('(\r\n|\n|\r)', $this->_vars['headers']); - if (!$headers) { - return false; - } - - $addresses = preg_split('(\r\n|\n|\r)', $this->_vars['addresses']); - if (!$addresses) { - return false; - } - - return true; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - $code = 'address ' . - $this->_vars['address-part'] . ' ' . - ':comparator "' . $this->_vars['comparator'] . '" ' . - $this->_vars['match-type'] . ' '; - - $headers = preg_split('(\r\n|\n|\r|,)', $this->_vars['headers']); - $headers = array_filter($headers); - if (count($headers) > 1) { - $code .= "["; - $headerstr = ''; - foreach ($headers as $header) { - $header = trim($header); - if (!empty($header)) { - $headerstr .= empty($headerstr) ? '"' : ', "'; - $headerstr .= Ingo_Script_Sieve::escapeString($header, $this->_vars['match-type'] == ':regex') . '"'; - } - } - $code .= $headerstr . "] "; - } elseif (count($headers) == 1) { - $code .= '"' . Ingo_Script_Sieve::escapeString($headers[0], $this->_vars['match-type'] == ':regex') . '" '; - } else { - return "No Headers Specified"; - } - - $addresses = preg_split('(\r\n|\n|\r)', $this->_vars['addresses']); - $addresses = array_filter($addresses); - if (count($addresses) > 1) { - $code .= "["; - $addressstr = ''; - foreach ($addresses as $addr) { - $addr = trim($addr); - if (!empty($addr)) { - $addressstr .= empty($addressstr) ? '"' : ', "'; - $addressstr .= Ingo_Script_Sieve::escapeString($addr, $this->_vars['match-type'] == ':regex') . '"'; - } - } - $code .= $addressstr . "] "; - } elseif (count($addresses) == 1) { - $code .= '"' . Ingo_Script_Sieve::escapeString($addresses[0], $this->_vars['match-type'] == ':regex') . '" '; - } else { - return "No Addresses Specified"; - } - - return $code; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - if ($this->_vars['match-type'] == ':regex') { - return array('regex'); - } - return array(); - } - -} - -/** - * The Sieve_Test_Header class represents a test on the contents of one or - * more headers in a message. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Test_Header extends Sieve_Test { - - /** - * Constructor. - * - * @param array $vars Any required parameters. - */ - function Sieve_Test_Header($vars = array()) - { - $this->_vars['headers'] = isset($vars['headers']) - ? $vars['headers'] - : 'Subject'; - $this->_vars['comparator'] = isset($vars['comparator']) - ? $vars['comparator'] - : 'i;ascii-casemap'; - $this->_vars['match-type'] = isset($vars['match-type']) - ? $vars['match-type'] - : ':is'; - $this->_vars['strings'] = isset($vars['strings']) - ? $vars['strings'] - : ''; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - $headers = preg_split('((?_vars['headers']); - if (!$headers) { - return false; - } - - $strings = preg_split('((?_vars['strings']); - if (!$strings) { - return false; - } - - return true; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - $code = 'header ' . - ':comparator "' . $this->_vars['comparator'] . '" ' . - $this->_vars['match-type'] . ' '; - - $headers = preg_split('(\r\n|\n|\r)', $this->_vars['headers']); - $headers = array_filter($headers); - if (count($headers) > 1) { - $code .= "["; - $headerstr = ''; - foreach ($headers as $header) { - $headerstr .= empty($headerstr) ? '"' : ', "'; - $headerstr .= Ingo_Script_Sieve::escapeString($header, $this->_vars['match-type'] == ':regex') . '"'; - } - $code .= $headerstr . "] "; - } elseif (count($headers) == 1) { - $code .= '"' . $headers[0] . '" '; - } else { - return _("No headers specified"); - } - - $strings = preg_split('(\r\n|\n|\r)', $this->_vars['strings']); - $strings = array_filter($strings); - if (count($strings) > 1) { - $code .= "["; - $stringlist = ''; - foreach ($strings as $str) { - $stringlist .= empty($stringlist) ? '"' : ', "'; - $stringlist .= Ingo_Script_Sieve::escapeString($str, $this->_vars['match-type'] == ':regex') . '"'; - } - $code .= $stringlist . "] "; - } elseif (count($strings) == 1) { - $code .= '"' . Ingo_Script_Sieve::escapeString(reset($strings), $this->_vars['match-type'] == ':regex') . '" '; - } else { - return _("No strings specified"); - } - - return $code; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - if ($this->_vars['match-type'] == ':regex') { - return array('regex'); - } - return array(); - } - -} - -/** - * The Sieve_Test_Body class represents a test on the contents of the body in - * a message. - * - * @author Michael Menge - * @package Ingo - */ -class Sieve_Test_Body extends Sieve_Test { - - /** - * Constructor. - * - * @param array $vars Any required parameters. - */ - function Sieve_Test_Body($vars = array()) - { - $this->_vars['comparator'] = (isset($vars['comparator'])) ? $vars['comparator'] : 'i;ascii-casemap'; - $this->_vars['match-type'] = (isset($vars['match-type'])) ? $vars['match-type'] : ':is'; - $this->_vars['strings'] = (isset($vars['strings'])) ? $vars['strings'] : ''; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - $strings = preg_split('((?_vars['strings']); - if (!$strings) { - return false; - } - - return true; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - $code = 'body ' . - ':comparator "' . $this->_vars['comparator'] . '" ' . - $this->_vars['match-type'] . ' '; - - $strings = preg_split('(\r\n|\n|\r)', $this->_vars['strings']); - $strings = array_filter($strings); - if (count($strings) > 1) { - $code .= "["; - $stringlist = ''; - foreach ($strings as $str) { - $stringlist .= empty($stringlist) ? '"' : ', "'; - $stringlist .= Ingo_Script_Sieve::escapeString($str, $this->_vars['match-type'] == ':regex') . '"'; - } - $code .= $stringlist . "] "; - } elseif (count($strings) == 1) { - $code .= '"' . Ingo_Script_Sieve::escapeString($strings[0], $this->_vars['match-type'] == ':regex') . '" '; - } else { - return _("No strings specified"); - } - - return $code; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - if ($this->_vars['match-type'] == ':regex') { - return array('regex', 'body'); - } - - return array('body'); - } - -} - -/** - * A Comment. - * - * @author Mike Cochrane - * @package Ingo - * @todo This and Sieve_If should really extends a Sieve_Block eventually. - */ -class Sieve_Comment { - - var $_comment; - - /** - * Constructor. - * - * @param string $comment The comment text. - */ - function Sieve_Comment($comment) - { - $this->_comment = $comment; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - $code = ''; - $lines = preg_split('(\r\n|\n|\r)', $this->_comment); - foreach ($lines as $line) { - $line = trim($line); - if (strlen($line)) { - $code .= (empty($code) ? '' : "\n") . '# ' . $line; - } - } - return $code; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - return true; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - return array(); - } - -} - -/** - * The Sieve_Action class represents an action in a Sieve script. - * - * An action is anything that has a side effect eg: discard, redirect. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Action { - - /** - * Any necessary action parameters. - * - * @var array - */ - var $_vars = array(); - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'toCode() Function Not Implemented in class ' . get_class($this) ; - } - - function toString() - { - return $this->toCode(); - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - return 'check() Function Not Implemented in class ' . get_class($this) ; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - return array(); - } - -} - -/** - * The Sieve_Action_Redirect class represents a redirect action. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Action_Redirect extends Sieve_Action { - - /** - * Constructor. - * - * @param array $vars Any required parameters. - */ - function Sieve_Action_Redirect($vars = array()) - { - $this->_vars['address'] = (isset($vars['address'])) ? $vars['address'] : ''; - } - - function toCode($depth = 0) - { - return str_repeat(' ', $depth * 4) . 'redirect ' . - '"' . Ingo_Script_Sieve::escapeString($this->_vars['address']) . '";'; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - if (empty($this->_vars['address'])) { - return _("Missing address to redirect message to"); - } - - return true; - } - -} - -/** - * The Sieve_Action_Reject class represents a reject action. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Action_Reject extends Sieve_Action { - - /** - * Constructor. - * - * @param array $vars Any required parameters. - */ - function Sieve_Action_Reject($vars = array()) - { - $this->_vars['reason'] = (isset($vars['reason'])) ? $vars['reason'] : ''; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'reject "' . Ingo_Script_Sieve::escapeString($this->_vars['reason']) . '";'; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - if (empty($this->_vars['reason'])) { - return _("Missing reason for reject"); - } - - return true; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - return array('reject'); - } - -} - -/** - * The Sieve_Action_Keep class represents a keep action. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Action_Keep extends Sieve_Action { - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'keep;'; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - return true; - } - -} - -/** - * The Sieve_Action_Discard class represents a discard action. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Action_Discard extends Sieve_Action { - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'discard;'; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - return true; - } - -} - -/** - * The Sieve_Action_Stop class represents a stop action. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Action_Stop extends Sieve_Action { - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'stop;'; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - return true; - } - -} - -/** - * The Sieve_Action_Fileinto class represents a fileinto action. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Action_Fileinto extends Sieve_Action { - - /** - * Constructor. - * - * @param array $vars Any required parameters. - */ - function Sieve_Action_Fileinto($vars = array()) - { - $this->_vars['folder'] = (isset($vars['folder'])) ? $vars['folder'] : ''; - if (!empty($vars['utf8'])) { - $this->_vars['folder'] = String::convertCharset($this->_vars['folder'], 'UTF7-IMAP', 'UTF-8'); - } - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'fileinto "' . Ingo_Script_Sieve::escapeString($this->_vars['folder']) . '";'; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - if (empty($this->_vars['folder'])) { - return _("Inexistant mailbox specified for message delivery."); - } - - return true; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - return array('fileinto'); - } - -} - -/** - * The Sieve_Action_Vacation class represents a vacation action. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Action_Vacation extends Sieve_Action { - - /** - * Constructor. - * - * @param array $vars Any required parameters. - */ - function Sieve_Action_Vacation($vars = array()) - { - $this->_vars['days'] = isset($vars['days']) ? intval($vars['days']) : ''; - $this->_vars['addresses'] = isset($vars['addresses']) ? $vars['addresses'] : ''; - $this->_vars['subject'] = isset($vars['subject']) ? $vars['subject'] : ''; - $this->_vars['reason'] = isset($vars['reason']) ? $vars['reason'] : ''; - $this->_vars['start'] = isset($vars['start']) ? $vars['start'] : ''; - $this->_vars['start_year'] = isset($vars['start_year']) ? $vars['start_year'] : ''; - $this->_vars['start_month'] = isset($vars['start_month']) ? $vars['start_month'] : ''; - $this->_vars['start_day'] = isset($vars['start_day']) ? $vars['start_day'] : ''; - $this->_vars['end'] = isset($vars['end']) ? $vars['end'] : ''; - $this->_vars['end_year'] = isset($vars['end_year']) ? $vars['end_year'] : ''; - $this->_vars['end_month'] = isset($vars['end_month']) ? $vars['end_month'] : ''; - $this->_vars['end_day'] = isset($vars['end_day']) ? $vars['end_day'] : ''; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - $start_year = $this->_vars['start_year']; - $start_month = $this->_vars['start_month']; - $start_day = $this->_vars['start_day']; - - $end_year = $this->_vars['end_year']; - $end_month = $this->_vars['end_month']; - $end_day = $this->_vars['end_day']; - - $code = ''; - - if (empty($this->_vars['start']) || empty($this->_vars['end'])) { - return $this->_vacationCode(); - } elseif ($end_year > $start_year + 1) { - $code .= $this->_yearCheck($start_year + 1, $end_year - 1) - . $this->_vacationCode() - . "\n}\n" - . $this->_yearCheck($start_year, $start_year); - if ($start_month < 12) { - $code .= $this->_monthCheck($start_month + 1, 12) - . $this->_vacationCode() - . "\n}\n"; - } - $code .= $this->_monthCheck($start_month, $start_month) - . $this->_dayCheck($start_day, 31) - . $this->_vacationCode() - . "\n}\n}\n}\n" - . $this->_yearCheck($end_year, $end_year); - if ($end_month > 1) { - $code .= $this->_monthCheck(1, $end_month - 1) - . $this->_vacationCode() - . "\n}\n"; - } - $code .= $this->_monthCheck($end_month, $end_month) - . $this->_dayCheck(1, $end_day) - . $this->_vacationCode() - . "\n}\n}\n}\n"; - } elseif ($end_year == $start_year + 1) { - $code .= $this->_yearCheck($start_year, $start_year); - if ($start_month < 12) { - $code .= $this->_monthCheck($start_month + 1, 12) - . $this->_vacationCode() - . "\n}\n"; - } - $code .= $this->_monthCheck($start_month, $start_month) - . $this->_dayCheck($start_day, 31) - . $this->_vacationCode() - . "\n}\n}\n}\n" - . $this->_yearCheck($end_year, $end_year); - if ($end_month > 1) { - $code .= $this->_monthCheck(1, $end_month - 1) - . $this->_vacationCode() - . "\n}\n"; - } - $code .= $this->_monthCheck($end_month, $end_month) - . $this->_dayCheck(1, $end_day) - . $this->_vacationCode() - . "\n}\n}\n}\n"; - } elseif ($end_year == $start_year) { - $code .= $this->_yearCheck($start_year, $start_year); - if ($end_month > $start_month) { - if ($end_month > $start_month + 1) { - $code .= $this->_monthCheck($start_month + 1, $end_month - 1) - . $this->_vacationCode() - . "\n}\n"; - } - $code .= $this->_monthCheck($start_month, $start_month) - . $this->_dayCheck($start_day, 31) - . $this->_vacationCode() - . "\n}\n}\n" - . $this->_monthCheck($end_month, $end_month) - . $this->_dayCheck(1, $end_day) - . $this->_vacationCode() - . "\n}\n}\n"; - } elseif ($end_month == $start_month) { - $code .= $this->_monthCheck($start_month, $start_month) - . $this->_dayCheck($start_day, $end_day) - . $this->_vacationCode() - . "\n}\n}\n"; - } - $code .= "}\n"; - } - - return $code; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - if (empty($this->_vars['reason'])) { - return _("Missing reason in vacation."); - } - - return true; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - return array('vacation', 'regex'); - } - - /** - */ - function _vacationCode() - { - $code = 'vacation :days ' . $this->_vars['days'] . ' '; - $addresses = $this->_vars['addresses']; - $stringlist = ''; - if (count($addresses) > 1) { - foreach ($addresses as $address) { - $address = trim($address); - if (!empty($address)) { - $stringlist .= empty($stringlist) ? '"' : ', "'; - $stringlist .= Ingo_Script_Sieve::escapeString($address) . '"'; - } - } - $stringlist = "[" . $stringlist . "] "; - } elseif (count($addresses) == 1) { - $stringlist = '"' . Ingo_Script_Sieve::escapeString($addresses[0]) . '" '; - } - - if (!empty($stringlist)) { - $code .= ':addresses ' . $stringlist; - } - - if (!empty($this->_vars['subject'])) { - $code .= ':subject "' . Horde_Mime::encode(Ingo_Script_Sieve::escapeString($this->_vars['subject']), 'UTF-8') . '" '; - } - return $code - . '"' . Ingo_Script_Sieve::escapeString($this->_vars['reason']) - . '";'; - } - - /** - */ - function _yearCheck($begin, $end) - { - $code = 'if header :regex "Received" "^.*(' . $begin; - for ($i = $begin + 1; $i <= $end; $i++) { - $code .= '|' . $i; - } - return $code - . ') (\\\\(.*\\\\) )?..:..:.. (\\\\(.*\\\\) )?((\\\\+|\\\\-)[[:digit:]]{4}|.{1,5})( \\\\(.*\\\\))?$" {' - . "\n "; - } - - /** - */ - function _monthCheck($begin, $end) - { - $months = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'); - $code = 'if header :regex "Received" "^.*(' . $months[$begin - 1]; - for ($i = $begin + 1; $i <= $end; $i++) { - $code .= '|' . $months[$i - 1]; - } - return $code - . ') (\\\\(.*\\\\) )?.... (\\\\(.*\\\\) )?..:..:.. (\\\\(.*\\\\) )?((\\\\+|\\\\-)[[:digit:]]{4}|.{1,5})( \\\\(.*\\\\))?$" {' - . "\n "; - } - - /** - */ - function _dayCheck($begin, $end) - { - $code = 'if header :regex "Received" "^.*(' . str_repeat('[0 ]', 2 - strlen($begin)) . $begin; - for ($i = $begin + 1; $i <= $end; $i++) { - $code .= '|' . str_repeat('[0 ]', 2 - strlen($i)) . $i; - } - return $code - . ') (\\\\(.*\\\\) )?... (\\\\(.*\\\\) )?.... (\\\\(.*\\\\) )?..:..:.. (\\\\(.*\\\\) )?((\\\\+|\\\\-)[[:digit:]]{4}|.{1,5})( \\\\(.*\\\\))?$" {' - . "\n "; - } - -} - -/** - * The Sieve_Action_Flag class is the base class for flag actions. - * - * @author Michael Slusarz - * @package Ingo - */ -class Sieve_Action_Flag extends Sieve_Action { - - /** - * Constructor. - * - * @params array $vars Any required parameters. - */ - function Sieve_Action_Flag($vars = array()) - { - if (isset($vars['flags'])) { - if ($vars['flags'] & Ingo_Storage::FLAG_ANSWERED) { - $this->_vars['flags'][] = '\Answered'; - } - if ($vars['flags'] & Ingo_Storage::FLAG_DELETED) { - $this->_vars['flags'][] = '\Deleted'; - } - if ($vars['flags'] & Ingo_Storage::FLAG_FLAGGED) { - $this->_vars['flags'][] = '\Flagged'; - } - if ($vars['flags'] & Ingo_Storage::FLAG_SEEN) { - $this->_vars['flags'][] = '\Seen'; - } - } else { - $this->_vars['flags'] = ''; - } - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @param string $mode The sieve flag command to use. Either 'removeflag' - * or 'addflag'. - * - * @return string A Sieve script snippet. - */ - function _toCode($mode) - { - $code = ''; - - if (is_array($this->_vars['flags']) && !empty($this->_vars['flags'])) { - $code .= $mode . ' '; - if (count($this->_vars['flags']) > 1) { - $stringlist = ''; - foreach ($this->_vars['flags'] as $flag) { - $flag = trim($flag); - if (!empty($flag)) { - $stringlist .= empty($stringlist) ? '"' : ', "'; - $stringlist .= Ingo_Script_Sieve::escapeString($flag) . '"'; - } - } - $stringlist = '[' . $stringlist . ']'; - $code .= $stringlist . ';'; - } else { - $code .= '"' . Ingo_Script_Sieve::escapeString($this->_vars['flags'][0]) . '";'; - } - } - return $code; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - return true; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - return array('imapflags'); - } - -} - -/** - * The Sieve_Action_Addflag class represents an add flag action. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Action_Addflag extends Sieve_Action_Flag { - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return $this->_toCode('addflag'); - } - -} - -/** - * The Sieve_Action_Removeflag class represents a remove flag action. - * - * @author Mike Cochrane - * @package Ingo - */ -class Sieve_Action_Removeflag extends Sieve_Action_Flag { - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return $this->_toCode('removeflag'); - } - -} - -/** - * The Sieve_Action_Notify class represents a notify action. - * - * @author Paul Wolstenholme - * @package Ingo - */ -class Sieve_Action_Notify extends Sieve_Action { - - /** - * Constructor. - * - * @param array $vars Any required parameters. - */ - function Sieve_Action_Notify($vars = array()) - { - $this->_vars['address'] = isset($vars['address']) ? $vars['address'] : ''; - $this->_vars['name'] = isset($vars['name']) ? $vars['name'] : ''; - } - - /** - * Returns a script snippet representing this rule and any sub-rules. - * - * @return string A Sieve script snippet. - */ - function toCode() - { - return 'notify :method "mailto" :options "' . - Ingo_Script_Sieve::escapeString($this->_vars['address']) . - '" :message "' . - _("You have received a new message") . "\n" . - _("From:") . " \$from\$ \n" . - _("Subject:") . " \$subject\$ \n" . - _("Rule:") . ' ' . $this->_vars['name'] . '";'; - } - - /** - * Checks if the rule parameters are valid. - * - * @return boolean|string True if this rule is valid, an error message - * otherwise. - */ - function check() - { - if (empty($this->_vars['address'])) { - return _("Missing address to notify"); - } - - return true; - } - - /** - * Returns a list of sieve extensions required for this rule and any - * sub-rules. - * - * @return array A Sieve extension list. - */ - function requires() - { - return array('notify'); - } - -} diff --git a/ingo/lib/Script/Sieve/Action.php b/ingo/lib/Script/Sieve/Action.php new file mode 100644 index 000000000..13bbe2b10 --- /dev/null +++ b/ingo/lib/Script/Sieve/Action.php @@ -0,0 +1,59 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action +{ + /** + * Any necessary action parameters. + * + * @var array + */ + protected $_vars = array(); + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'toCode() Function Not Implemented in class ' . get_class($this) ; + } + + public function toString() + { + return $this->toCode(); + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return 'check() Function Not Implemented in class ' . get_class($this) ; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return array(); + } + +} diff --git a/ingo/lib/Script/Sieve/Action/Addflag.php b/ingo/lib/Script/Sieve/Action/Addflag.php new file mode 100644 index 000000000..11fd1460c --- /dev/null +++ b/ingo/lib/Script/Sieve/Action/Addflag.php @@ -0,0 +1,23 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action_Addflag extends Ingo_Script_Sieve_Action_Flag +{ + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return $this->_toCode('addflag'); + } + +} diff --git a/ingo/lib/Script/Sieve/Action/Discard.php b/ingo/lib/Script/Sieve/Action/Discard.php new file mode 100644 index 000000000..8cec42e98 --- /dev/null +++ b/ingo/lib/Script/Sieve/Action/Discard.php @@ -0,0 +1,34 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action_Discard extends Ingo_Script_Sieve_Action +{ + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'discard;'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return true; + } + +} diff --git a/ingo/lib/Script/Sieve/Action/Fileinto.php b/ingo/lib/Script/Sieve/Action/Fileinto.php new file mode 100644 index 000000000..d3d7532e0 --- /dev/null +++ b/ingo/lib/Script/Sieve/Action/Fileinto.php @@ -0,0 +1,63 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action_Fileinto extends Ingo_Script_Sieve_Action +{ + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + public function __construct($vars = array()) + { + $this->_vars['folder'] = isset($vars['folder']) + ? $vars['folder'] + : ''; + + if (!empty($vars['utf8'])) { + $this->_vars['folder'] = Horde_String::convertCharset($this->_vars['folder'], 'UTF7-IMAP', 'UTF-8'); + } + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'fileinto "' . Ingo_Script_Sieve::escapeString($this->_vars['folder']) . '";'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return empty($this->_vars['folder']) + ? _("Inexistant mailbox specified for message delivery.") + : true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return array('fileinto'); + } + +} diff --git a/ingo/lib/Script/Sieve/Action/Flag.php b/ingo/lib/Script/Sieve/Action/Flag.php new file mode 100644 index 000000000..b21ab891e --- /dev/null +++ b/ingo/lib/Script/Sieve/Action/Flag.php @@ -0,0 +1,92 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action_Flag extends Ingo_Script_Sieve_Action +{ + /** + * Constructor. + * + * @params array $vars Any required parameters. + */ + public function __construct($vars = array()) + { + if (isset($vars['flags'])) { + if ($vars['flags'] & Ingo_Storage::FLAG_ANSWERED) { + $this->_vars['flags'][] = '\Answered'; + } + if ($vars['flags'] & Ingo_Storage::FLAG_DELETED) { + $this->_vars['flags'][] = '\Deleted'; + } + if ($vars['flags'] & Ingo_Storage::FLAG_FLAGGED) { + $this->_vars['flags'][] = '\Flagged'; + } + if ($vars['flags'] & Ingo_Storage::FLAG_SEEN) { + $this->_vars['flags'][] = '\Seen'; + } + } else { + $this->_vars['flags'] = ''; + } + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @param string $mode The sieve flag command to use. Either 'removeflag' + * or 'addflag'. + * + * @return string A Sieve script snippet. + */ + public function _toCode($mode) + { + $code = ''; + + if (is_array($this->_vars['flags']) && !empty($this->_vars['flags'])) { + $code .= $mode . ' '; + if (count($this->_vars['flags']) > 1) { + $stringlist = ''; + foreach ($this->_vars['flags'] as $flag) { + $flag = trim($flag); + if (!empty($flag)) { + $stringlist .= empty($stringlist) ? '"' : ', "'; + $stringlist .= Ingo_Script_Sieve::escapeString($flag) . '"'; + } + } + $stringlist = '[' . $stringlist . ']'; + $code .= $stringlist . ';'; + } else { + $code .= '"' . Ingo_Script_Sieve::escapeString($this->_vars['flags'][0]) . '";'; + } + } + return $code; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return array('imapflags'); + } + +} diff --git a/ingo/lib/Script/Sieve/Action/Keep.php b/ingo/lib/Script/Sieve/Action/Keep.php new file mode 100644 index 000000000..0096ed59a --- /dev/null +++ b/ingo/lib/Script/Sieve/Action/Keep.php @@ -0,0 +1,34 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action_Keep extends Ingo_Script_Sieve_Action +{ + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'keep;'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return true; + } + +} diff --git a/ingo/lib/Script/Sieve/Action/Notify.php b/ingo/lib/Script/Sieve/Action/Notify.php new file mode 100644 index 000000000..b0dc5fed6 --- /dev/null +++ b/ingo/lib/Script/Sieve/Action/Notify.php @@ -0,0 +1,68 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action_Notify extends Ingo_Script_Sieve_Action +{ + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + public function __construct($vars = array()) + { + $this->_vars['address'] = isset($vars['address']) + ? $vars['address'] + : ''; + $this->_vars['name'] = isset($vars['name']) + ? $vars['name'] + : ''; + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'notify :method "mailto" :options "' . + Ingo_Script_Sieve::escapeString($this->_vars['address']) . + '" :message "' . + _("You have received a new message") . "\n" . + _("From:") . " \$from\$ \n" . + _("Subject:") . " \$subject\$ \n" . + _("Rule:") . ' ' . $this->_vars['name'] . '";'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return empty($this->_vars['address']) + ? _("Missing address to notify") + : true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return array('notify'); + } + +} diff --git a/ingo/lib/Script/Sieve/Action/Redirect.php b/ingo/lib/Script/Sieve/Action/Redirect.php new file mode 100644 index 000000000..dd869447b --- /dev/null +++ b/ingo/lib/Script/Sieve/Action/Redirect.php @@ -0,0 +1,46 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action_Redirect extends Ingo_Script_Sieve_Action +{ + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + public function __construct($vars = array()) + { + $this->_vars['address'] = isset($vars['address']) + ? $vars['address'] + : ''; + } + + /** + */ + public function toCode($depth = 0) + { + return str_repeat(' ', $depth * 4) . 'redirect ' . + '"' . Ingo_Script_Sieve::escapeString($this->_vars['address']) . '";'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return empty($this->_vars['address']) + ? _("Missing address to redirect message to") + : true; + } + +} diff --git a/ingo/lib/Script/Sieve/Action/Reject.php b/ingo/lib/Script/Sieve/Action/Reject.php new file mode 100644 index 000000000..b387f3516 --- /dev/null +++ b/ingo/lib/Script/Sieve/Action/Reject.php @@ -0,0 +1,59 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action_Reject extends Ingo_Script_Sieve_Action +{ + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + public function __construct($vars = array()) + { + $this->_vars['reason'] = isset($vars['reason']) + ? $vars['reason'] + : ''; + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'reject "' . Ingo_Script_Sieve::escapeString($this->_vars['reason']) . '";'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return empty($this->_vars['reason']) + ? _("Missing reason for reject") + : true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return array('reject'); + } + +} diff --git a/ingo/lib/Script/Sieve/Action/Removeflag.php b/ingo/lib/Script/Sieve/Action/Removeflag.php new file mode 100644 index 000000000..6944fdf18 --- /dev/null +++ b/ingo/lib/Script/Sieve/Action/Removeflag.php @@ -0,0 +1,24 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action_Removeflag extends Ingo_Script_Sieve_Action_Flag +{ + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return $this->_toCode('removeflag'); + } + +} diff --git a/ingo/lib/Script/Sieve/Action/Stop.php b/ingo/lib/Script/Sieve/Action/Stop.php new file mode 100644 index 000000000..19c547032 --- /dev/null +++ b/ingo/lib/Script/Sieve/Action/Stop.php @@ -0,0 +1,34 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action_Stop extends Ingo_Script_Sieve_Action +{ + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'stop;'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return true; + } + +} diff --git a/ingo/lib/Script/Sieve/Action/Vacation.php b/ingo/lib/Script/Sieve/Action/Vacation.php new file mode 100644 index 000000000..1787b04a9 --- /dev/null +++ b/ingo/lib/Script/Sieve/Action/Vacation.php @@ -0,0 +1,225 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Action_Vacation extends Ingo_Script_Sieve_Action +{ + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + public function __construct($vars = array()) + { + $this->_vars = array_merge(array( + 'days' => '', + 'addresses' => '', + 'subject' => '', + 'reason' => '', + 'start' => '', + 'start_year' => '', + 'start_month' => '', + 'start_day' => '', + 'end' => '', + 'end_year' => '', + 'end_month' => '', + 'end_day' => '' + ), $vars); + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + $start_year = $this->_vars['start_year']; + $start_month = $this->_vars['start_month']; + $start_day = $this->_vars['start_day']; + + $end_year = $this->_vars['end_year']; + $end_month = $this->_vars['end_month']; + $end_day = $this->_vars['end_day']; + + $code = ''; + + if (empty($this->_vars['start']) || empty($this->_vars['end'])) { + return $this->_vacationCode(); + } elseif ($end_year > $start_year + 1) { + $code .= $this->_yearCheck($start_year + 1, $end_year - 1) + . $this->_vacationCode() + . "\n}\n" + . $this->_yearCheck($start_year, $start_year); + if ($start_month < 12) { + $code .= $this->_monthCheck($start_month + 1, 12) + . $this->_vacationCode() + . "\n}\n"; + } + $code .= $this->_monthCheck($start_month, $start_month) + . $this->_dayCheck($start_day, 31) + . $this->_vacationCode() + . "\n}\n}\n}\n" + . $this->_yearCheck($end_year, $end_year); + if ($end_month > 1) { + $code .= $this->_monthCheck(1, $end_month - 1) + . $this->_vacationCode() + . "\n}\n"; + } + $code .= $this->_monthCheck($end_month, $end_month) + . $this->_dayCheck(1, $end_day) + . $this->_vacationCode() + . "\n}\n}\n}\n"; + } elseif ($end_year == $start_year + 1) { + $code .= $this->_yearCheck($start_year, $start_year); + if ($start_month < 12) { + $code .= $this->_monthCheck($start_month + 1, 12) + . $this->_vacationCode() + . "\n}\n"; + } + $code .= $this->_monthCheck($start_month, $start_month) + . $this->_dayCheck($start_day, 31) + . $this->_vacationCode() + . "\n}\n}\n}\n" + . $this->_yearCheck($end_year, $end_year); + if ($end_month > 1) { + $code .= $this->_monthCheck(1, $end_month - 1) + . $this->_vacationCode() + . "\n}\n"; + } + $code .= $this->_monthCheck($end_month, $end_month) + . $this->_dayCheck(1, $end_day) + . $this->_vacationCode() + . "\n}\n}\n}\n"; + } elseif ($end_year == $start_year) { + $code .= $this->_yearCheck($start_year, $start_year); + if ($end_month > $start_month) { + if ($end_month > $start_month + 1) { + $code .= $this->_monthCheck($start_month + 1, $end_month - 1) + . $this->_vacationCode() + . "\n}\n"; + } + $code .= $this->_monthCheck($start_month, $start_month) + . $this->_dayCheck($start_day, 31) + . $this->_vacationCode() + . "\n}\n}\n" + . $this->_monthCheck($end_month, $end_month) + . $this->_dayCheck(1, $end_day) + . $this->_vacationCode() + . "\n}\n}\n"; + } elseif ($end_month == $start_month) { + $code .= $this->_monthCheck($start_month, $start_month) + . $this->_dayCheck($start_day, $end_day) + . $this->_vacationCode() + . "\n}\n}\n"; + } + $code .= "}\n"; + } + + return $code; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return empty($this->_vars['reason']) + ? _("Missing reason in vacation.") + : true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return array('vacation', 'regex'); + } + + /** + */ + protected function _vacationCode() + { + $code = 'vacation :days ' . $this->_vars['days'] . ' '; + $addresses = $this->_vars['addresses']; + $stringlist = ''; + if (count($addresses) > 1) { + foreach ($addresses as $address) { + $address = trim($address); + if (!empty($address)) { + $stringlist .= empty($stringlist) ? '"' : ', "'; + $stringlist .= Ingo_Script_Sieve::escapeString($address) . '"'; + } + } + $stringlist = "[" . $stringlist . "] "; + } elseif (count($addresses) == 1) { + $stringlist = '"' . Ingo_Script_Sieve::escapeString($addresses[0]) . '" '; + } + + if (!empty($stringlist)) { + $code .= ':addresses ' . $stringlist; + } + + if (!empty($this->_vars['subject'])) { + $code .= ':subject "' . Horde_Mime::encode(Ingo_Script_Sieve::escapeString($this->_vars['subject']), 'UTF-8') . '" '; + } + return $code + . '"' . Ingo_Script_Sieve::escapeString($this->_vars['reason']) + . '";'; + } + + /** + */ + protected function _yearCheck($begin, $end) + { + $code = 'if header :regex "Received" "^.*(' . $begin; + for ($i = $begin + 1; $i <= $end; $i++) { + $code .= '|' . $i; + } + return $code + . ') (\\\\(.*\\\\) )?..:..:.. (\\\\(.*\\\\) )?((\\\\+|\\\\-)[[:digit:]]{4}|.{1,5})( \\\\(.*\\\\))?$" {' + . "\n "; + } + + /** + */ + protected function _monthCheck($begin, $end) + { + $months = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'); + $code = 'if header :regex "Received" "^.*(' . $months[$begin - 1]; + for ($i = $begin + 1; $i <= $end; $i++) { + $code .= '|' . $months[$i - 1]; + } + return $code + . ') (\\\\(.*\\\\) )?.... (\\\\(.*\\\\) )?..:..:.. (\\\\(.*\\\\) )?((\\\\+|\\\\-)[[:digit:]]{4}|.{1,5})( \\\\(.*\\\\))?$" {' + . "\n "; + } + + /** + */ + protected function _dayCheck($begin, $end) + { + $code = 'if header :regex "Received" "^.*(' . str_repeat('[0 ]', 2 - strlen($begin)) . $begin; + for ($i = $begin + 1; $i <= $end; $i++) { + $code .= '|' . str_repeat('[0 ]', 2 - strlen($i)) . $i; + } + return $code + . ') (\\\\(.*\\\\) )?... (\\\\(.*\\\\) )?.... (\\\\(.*\\\\) )?..:..:.. (\\\\(.*\\\\) )?((\\\\+|\\\\-)[[:digit:]]{4}|.{1,5})( \\\\(.*\\\\))?$" {' + . "\n "; + } + +} diff --git a/ingo/lib/Script/Sieve/Comment.php b/ingo/lib/Script/Sieve/Comment.php new file mode 100644 index 000000000..7d96616f6 --- /dev/null +++ b/ingo/lib/Script/Sieve/Comment.php @@ -0,0 +1,68 @@ + + * @package Ingo + * @todo This and Sieve_If should really extends a Sieve_Block eventually. + */ +class Ingo_Script_Sieve_Comment +{ + /** + */ + protected $_comment; + + /** + * Constructor. + * + * @param string $comment The comment text. + */ + public function __construct($comment) + { + $this->_comment = $comment; + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + $code = ''; + $lines = preg_split('(\r\n|\n|\r)', $this->_comment); + foreach ($lines as $line) { + $line = trim($line); + if (strlen($line)) { + $code .= (empty($code) ? '' : "\n") . '# ' . $line; + } + } + return $code; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return array(); + } + +} diff --git a/ingo/lib/Script/Sieve/Else.php b/ingo/lib/Script/Sieve/Else.php new file mode 100644 index 000000000..577c26179 --- /dev/null +++ b/ingo/lib/Script/Sieve/Else.php @@ -0,0 +1,104 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Else +{ + /** + * A list of Ingo_Script_Sieve_Action objects that go into the else clause. + * + * @var array + */ + protected $_actions = array(); + + /** + * Constructor. + * + * @param mixed $actions An Ingo_Script_Sieve_Action object or a list of + * Ingo_Script_Sieve_Action objects. + */ + public function __construct($actions = null) + { + if (is_array($actions)) { + $this->_actions = $actions; + } elseif (!is_null($actions)) { + $this->_actions[] = $actions; + } + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + if (count($this->_actions) == 0) { + return ''; + } + + $code = 'else' . " { \n"; + foreach ($this->_actions as $action) { + $code .= ' ' . $action->toCode() . "\n"; + } + $code .= "} "; + + return $code; + } + + /** + */ + public function setActions($actions) + { + $this->_actions = $actions; + } + + /** + */ + public function getActions() + { + return $this->_actions; + } + + /** + * Checks if all sub-rules are valid. + * + * @return boolean|string True if all rules are valid, an error message + * otherwise. + */ + public function check() + { + foreach ($this->_actions as $action) { + $res = $action->check(); + if ($res !== true) { + return $res; + } + } + + return true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + $requires = array(); + + foreach ($this->_actions as $action) { + $requires = array_merge($requires, $action->requires()); + } + + return $requires; + } + +} diff --git a/ingo/lib/Script/Sieve/Elsif.php b/ingo/lib/Script/Sieve/Elsif.php new file mode 100644 index 000000000..f1871a49a --- /dev/null +++ b/ingo/lib/Script/Sieve/Elsif.php @@ -0,0 +1,124 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Elsif +{ + /** + * The Ingo_Script_Sieve_Test object for the if test. + * + * @var Ingo_Script_Sieve_Test + */ + protected $_test; + + /** + * A list of Ingo_Script_Sieve_Action objects that go into the if clause. + * + * @var array + */ + protected $_actions = array(); + + /** + * Constructor. + * + * @param Ingo_Script_Sieve_Test $test A Ingo_Script_Sieve_Test object. + */ + public function __construct($test = null) + { + $this->_test = is_null($test) + ? new Ingo_Script_Sieve_Test_False() + : $test; + $this->_actions[] = new Ingo_Script_Sieve_Action_Keep(); + } + + /** + */ + public function getTest() + { + return $this->_test; + } + + /** + */ + public function setTest($test) + { + $this->_test = $test; + } + + /** + */ + public function getActions() + { + return $this->_actions; + } + + /** + */ + public function setActions($actions) + { + $this->_actions = $actions; + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + $code = 'elsif ' . $this->_test->toCode() . " { \n"; + foreach ($this->_actions as $action) { + $code .= ' ' . $action->toCode() . "\n"; + } + $code .= "} "; + + return $code; + } + + /** + * Checks if all sub-rules are valid. + * + * @return boolean|string True if all rules are valid, an error message + * otherwise. + */ + public function check() + { + $res = $this->_test->check(); + if ($res !== true) { + return $res; + } + + foreach ($this->_actions as $action) { + $res = $action->check(); + if ($res !== true) { + return $res; + } + } + + return true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + $requires = array(); + + foreach ($this->_actions as $action) { + $requires = array_merge($requires, $action->requires()); + } + + return array_merge($requires, $this->_test->requires()); + } + +} diff --git a/ingo/lib/Script/Sieve/If.php b/ingo/lib/Script/Sieve/If.php new file mode 100644 index 000000000..3bdcd19e9 --- /dev/null +++ b/ingo/lib/Script/Sieve/If.php @@ -0,0 +1,198 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_If +{ + /** + * The Ingo_Script_Sieve_Test object for the if test. + * + * @var Ingo_Script_Sieve_Test + */ + protected $_test; + + /** + * A list of Ingo_Script_Sieve_Action objects that go into the if clause. + * + * @var array + */ + protected $_actions = array(); + + /** + * A list of Ingo_Script_Sieve_Elseif objects that create optional elsif + * clauses. + * + * @var array + */ + protected $_elsifs = array(); + + /** + * A Ingo_Script_Sieve_Else object that creates an optional else clause. + * + * @var Ingo_Script_Sieve_Else + */ + protected $_else; + + /** + * Constructor. + * + * @param Ingo_Script_Sieve_Test $test A Ingo_Script_Sieve_Test object. + */ + public function __construct($test = null) + { + $this->_test = is_null($test) + ? new Ingo_Script_Sieve_Test_False() + : $test; + + $this->_actions[] = new Ingo_Script_Sieve_Action_Keep(); + $this->_else = new Ingo_Script_Sieve_Else(); + } + + /** + */ + public function getTest() + { + return $this->_test; + } + + /** + */ + public function setTest($test) + { + $this->_test = $test; + } + + /** + */ + public function getActions() + { + return $this->_actions; + } + + /** + */ + public function setActions($actions) + { + $this->_actions = $actions; + } + + /** + */ + public function getElsifs() + { + return $this->_elsifs; + } + + /** + */ + public function setElsifs($elsifs) + { + $this->_elsifs = $elsifs; + } + + /** + */ + public function addElsif($elsif) + { + $this->_elsifs[] = $elsif; + } + + /** + */ + public function getElse() + { + return $this->_else; + } + + /** + */ + public function setElse($else) + { + $this->_else = $else; + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + $code = 'if ' . $this->_test->toCode() . " { \n"; + foreach ($this->_actions as $action) { + $code .= ' ' . $action->toCode() . "\n"; + } + $code .= "} "; + + foreach ($this->_elsifs as $elsif) { + $code .= $elsif->toCode(); + } + + $code .= $this->_else->toCode(); + + return $code . "\n"; + } + + /** + * Checks if all sub-rules are valid. + * + * @return boolean|string True if all rules are valid, an error message + * otherwise. + */ + public function check() + { + $res = $this->_test->check(); + if ($res !== true) { + return $res; + } + + foreach ($this->_elsifs as $elsif) { + $res = $elsif->check(); + if ($res !== true) { + return $res; + } + } + + $res = $this->_else->check(); + if ($res !== true) { + return $res; + } + + foreach ($this->_actions as $action) { + $res = $action->check(); + if ($res !== true) { + return $res; + } + } + + return true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + $requires = array(); + + foreach ($this->_actions as $action) { + $requires = array_merge($requires, $action->requires()); + } + + foreach ($this->_elsifs as $elsif) { + $requires = array_merge($requires, $elsif->requires()); + } + + return array_merge($requires, $this->_test->requires(), $this->_else->requires()); + } + +} diff --git a/ingo/lib/Script/Sieve/Sieve.php b/ingo/lib/Script/Sieve/Sieve.php new file mode 100644 index 000000000..8287fb517 --- /dev/null +++ b/ingo/lib/Script/Sieve/Sieve.php @@ -0,0 +1,674 @@ + + * @package Ingo + */ +/** + * The Sieve_Action_Redirect class represents a redirect action. + * + * @author Mike Cochrane + * @package Ingo + */ +class Sieve_Action_Redirect extends Sieve_Action { + + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + function Sieve_Action_Redirect($vars = array()) + { + $this->_vars['address'] = (isset($vars['address'])) ? $vars['address'] : ''; + } + + function toCode($depth = 0) + { + return str_repeat(' ', $depth * 4) . 'redirect ' . + '"' . Ingo_Script_Sieve::escapeString($this->_vars['address']) . '";'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + function check() + { + if (empty($this->_vars['address'])) { + return _("Missing address to redirect message to"); + } + + return true; + } + +} + +/** + * The Sieve_Action_Reject class represents a reject action. + * + * @author Mike Cochrane + * @package Ingo + */ +class Sieve_Action_Reject extends Sieve_Action { + + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + function Sieve_Action_Reject($vars = array()) + { + $this->_vars['reason'] = (isset($vars['reason'])) ? $vars['reason'] : ''; + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + function toCode() + { + return 'reject "' . Ingo_Script_Sieve::escapeString($this->_vars['reason']) . '";'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + function check() + { + if (empty($this->_vars['reason'])) { + return _("Missing reason for reject"); + } + + return true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + function requires() + { + return array('reject'); + } + +} + +/** + * The Sieve_Action_Keep class represents a keep action. + * + * @author Mike Cochrane + * @package Ingo + */ +class Sieve_Action_Keep extends Sieve_Action { + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + function toCode() + { + return 'keep;'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + function check() + { + return true; + } + +} + +/** + * The Sieve_Action_Discard class represents a discard action. + * + * @author Mike Cochrane + * @package Ingo + */ +class Sieve_Action_Discard extends Sieve_Action { + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + function toCode() + { + return 'discard;'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + function check() + { + return true; + } + +} + +/** + * The Sieve_Action_Stop class represents a stop action. + * + * @author Mike Cochrane + * @package Ingo + */ +class Sieve_Action_Stop extends Sieve_Action { + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + function toCode() + { + return 'stop;'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + function check() + { + return true; + } + +} + +/** + * The Sieve_Action_Fileinto class represents a fileinto action. + * + * @author Mike Cochrane + * @package Ingo + */ +class Sieve_Action_Fileinto extends Sieve_Action { + + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + function Sieve_Action_Fileinto($vars = array()) + { + $this->_vars['folder'] = (isset($vars['folder'])) ? $vars['folder'] : ''; + if (!empty($vars['utf8'])) { + $this->_vars['folder'] = String::convertCharset($this->_vars['folder'], 'UTF7-IMAP', 'UTF-8'); + } + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + function toCode() + { + return 'fileinto "' . Ingo_Script_Sieve::escapeString($this->_vars['folder']) . '";'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + function check() + { + if (empty($this->_vars['folder'])) { + return _("Inexistant mailbox specified for message delivery."); + } + + return true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + function requires() + { + return array('fileinto'); + } + +} + +/** + * The Sieve_Action_Vacation class represents a vacation action. + * + * @author Mike Cochrane + * @package Ingo + */ +class Sieve_Action_Vacation extends Sieve_Action { + + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + function Sieve_Action_Vacation($vars = array()) + { + $this->_vars['days'] = isset($vars['days']) ? intval($vars['days']) : ''; + $this->_vars['addresses'] = isset($vars['addresses']) ? $vars['addresses'] : ''; + $this->_vars['subject'] = isset($vars['subject']) ? $vars['subject'] : ''; + $this->_vars['reason'] = isset($vars['reason']) ? $vars['reason'] : ''; + $this->_vars['start'] = isset($vars['start']) ? $vars['start'] : ''; + $this->_vars['start_year'] = isset($vars['start_year']) ? $vars['start_year'] : ''; + $this->_vars['start_month'] = isset($vars['start_month']) ? $vars['start_month'] : ''; + $this->_vars['start_day'] = isset($vars['start_day']) ? $vars['start_day'] : ''; + $this->_vars['end'] = isset($vars['end']) ? $vars['end'] : ''; + $this->_vars['end_year'] = isset($vars['end_year']) ? $vars['end_year'] : ''; + $this->_vars['end_month'] = isset($vars['end_month']) ? $vars['end_month'] : ''; + $this->_vars['end_day'] = isset($vars['end_day']) ? $vars['end_day'] : ''; + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + function toCode() + { + $start_year = $this->_vars['start_year']; + $start_month = $this->_vars['start_month']; + $start_day = $this->_vars['start_day']; + + $end_year = $this->_vars['end_year']; + $end_month = $this->_vars['end_month']; + $end_day = $this->_vars['end_day']; + + $code = ''; + + if (empty($this->_vars['start']) || empty($this->_vars['end'])) { + return $this->_vacationCode(); + } elseif ($end_year > $start_year + 1) { + $code .= $this->_yearCheck($start_year + 1, $end_year - 1) + . $this->_vacationCode() + . "\n}\n" + . $this->_yearCheck($start_year, $start_year); + if ($start_month < 12) { + $code .= $this->_monthCheck($start_month + 1, 12) + . $this->_vacationCode() + . "\n}\n"; + } + $code .= $this->_monthCheck($start_month, $start_month) + . $this->_dayCheck($start_day, 31) + . $this->_vacationCode() + . "\n}\n}\n}\n" + . $this->_yearCheck($end_year, $end_year); + if ($end_month > 1) { + $code .= $this->_monthCheck(1, $end_month - 1) + . $this->_vacationCode() + . "\n}\n"; + } + $code .= $this->_monthCheck($end_month, $end_month) + . $this->_dayCheck(1, $end_day) + . $this->_vacationCode() + . "\n}\n}\n}\n"; + } elseif ($end_year == $start_year + 1) { + $code .= $this->_yearCheck($start_year, $start_year); + if ($start_month < 12) { + $code .= $this->_monthCheck($start_month + 1, 12) + . $this->_vacationCode() + . "\n}\n"; + } + $code .= $this->_monthCheck($start_month, $start_month) + . $this->_dayCheck($start_day, 31) + . $this->_vacationCode() + . "\n}\n}\n}\n" + . $this->_yearCheck($end_year, $end_year); + if ($end_month > 1) { + $code .= $this->_monthCheck(1, $end_month - 1) + . $this->_vacationCode() + . "\n}\n"; + } + $code .= $this->_monthCheck($end_month, $end_month) + . $this->_dayCheck(1, $end_day) + . $this->_vacationCode() + . "\n}\n}\n}\n"; + } elseif ($end_year == $start_year) { + $code .= $this->_yearCheck($start_year, $start_year); + if ($end_month > $start_month) { + if ($end_month > $start_month + 1) { + $code .= $this->_monthCheck($start_month + 1, $end_month - 1) + . $this->_vacationCode() + . "\n}\n"; + } + $code .= $this->_monthCheck($start_month, $start_month) + . $this->_dayCheck($start_day, 31) + . $this->_vacationCode() + . "\n}\n}\n" + . $this->_monthCheck($end_month, $end_month) + . $this->_dayCheck(1, $end_day) + . $this->_vacationCode() + . "\n}\n}\n"; + } elseif ($end_month == $start_month) { + $code .= $this->_monthCheck($start_month, $start_month) + . $this->_dayCheck($start_day, $end_day) + . $this->_vacationCode() + . "\n}\n}\n"; + } + $code .= "}\n"; + } + + return $code; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + function check() + { + if (empty($this->_vars['reason'])) { + return _("Missing reason in vacation."); + } + + return true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + function requires() + { + return array('vacation', 'regex'); + } + + /** + */ + function _vacationCode() + { + $code = 'vacation :days ' . $this->_vars['days'] . ' '; + $addresses = $this->_vars['addresses']; + $stringlist = ''; + if (count($addresses) > 1) { + foreach ($addresses as $address) { + $address = trim($address); + if (!empty($address)) { + $stringlist .= empty($stringlist) ? '"' : ', "'; + $stringlist .= Ingo_Script_Sieve::escapeString($address) . '"'; + } + } + $stringlist = "[" . $stringlist . "] "; + } elseif (count($addresses) == 1) { + $stringlist = '"' . Ingo_Script_Sieve::escapeString($addresses[0]) . '" '; + } + + if (!empty($stringlist)) { + $code .= ':addresses ' . $stringlist; + } + + if (!empty($this->_vars['subject'])) { + $code .= ':subject "' . Horde_Mime::encode(Ingo_Script_Sieve::escapeString($this->_vars['subject']), 'UTF-8') . '" '; + } + return $code + . '"' . Ingo_Script_Sieve::escapeString($this->_vars['reason']) + . '";'; + } + + /** + */ + function _yearCheck($begin, $end) + { + $code = 'if header :regex "Received" "^.*(' . $begin; + for ($i = $begin + 1; $i <= $end; $i++) { + $code .= '|' . $i; + } + return $code + . ') (\\\\(.*\\\\) )?..:..:.. (\\\\(.*\\\\) )?((\\\\+|\\\\-)[[:digit:]]{4}|.{1,5})( \\\\(.*\\\\))?$" {' + . "\n "; + } + + /** + */ + function _monthCheck($begin, $end) + { + $months = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'); + $code = 'if header :regex "Received" "^.*(' . $months[$begin - 1]; + for ($i = $begin + 1; $i <= $end; $i++) { + $code .= '|' . $months[$i - 1]; + } + return $code + . ') (\\\\(.*\\\\) )?.... (\\\\(.*\\\\) )?..:..:.. (\\\\(.*\\\\) )?((\\\\+|\\\\-)[[:digit:]]{4}|.{1,5})( \\\\(.*\\\\))?$" {' + . "\n "; + } + + /** + */ + function _dayCheck($begin, $end) + { + $code = 'if header :regex "Received" "^.*(' . str_repeat('[0 ]', 2 - strlen($begin)) . $begin; + for ($i = $begin + 1; $i <= $end; $i++) { + $code .= '|' . str_repeat('[0 ]', 2 - strlen($i)) . $i; + } + return $code + . ') (\\\\(.*\\\\) )?... (\\\\(.*\\\\) )?.... (\\\\(.*\\\\) )?..:..:.. (\\\\(.*\\\\) )?((\\\\+|\\\\-)[[:digit:]]{4}|.{1,5})( \\\\(.*\\\\))?$" {' + . "\n "; + } + +} + +/** + * The Sieve_Action_Flag class is the base class for flag actions. + * + * @author Michael Slusarz + * @package Ingo + */ +class Sieve_Action_Flag extends Sieve_Action { + + /** + * Constructor. + * + * @params array $vars Any required parameters. + */ + function Sieve_Action_Flag($vars = array()) + { + if (isset($vars['flags'])) { + if ($vars['flags'] & Ingo_Storage::FLAG_ANSWERED) { + $this->_vars['flags'][] = '\Answered'; + } + if ($vars['flags'] & Ingo_Storage::FLAG_DELETED) { + $this->_vars['flags'][] = '\Deleted'; + } + if ($vars['flags'] & Ingo_Storage::FLAG_FLAGGED) { + $this->_vars['flags'][] = '\Flagged'; + } + if ($vars['flags'] & Ingo_Storage::FLAG_SEEN) { + $this->_vars['flags'][] = '\Seen'; + } + } else { + $this->_vars['flags'] = ''; + } + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @param string $mode The sieve flag command to use. Either 'removeflag' + * or 'addflag'. + * + * @return string A Sieve script snippet. + */ + function _toCode($mode) + { + $code = ''; + + if (is_array($this->_vars['flags']) && !empty($this->_vars['flags'])) { + $code .= $mode . ' '; + if (count($this->_vars['flags']) > 1) { + $stringlist = ''; + foreach ($this->_vars['flags'] as $flag) { + $flag = trim($flag); + if (!empty($flag)) { + $stringlist .= empty($stringlist) ? '"' : ', "'; + $stringlist .= Ingo_Script_Sieve::escapeString($flag) . '"'; + } + } + $stringlist = '[' . $stringlist . ']'; + $code .= $stringlist . ';'; + } else { + $code .= '"' . Ingo_Script_Sieve::escapeString($this->_vars['flags'][0]) . '";'; + } + } + return $code; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + function check() + { + return true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + function requires() + { + return array('imapflags'); + } + +} + +/** + * The Sieve_Action_Addflag class represents an add flag action. + * + * @author Mike Cochrane + * @package Ingo + */ +class Sieve_Action_Addflag extends Sieve_Action_Flag { + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + function toCode() + { + return $this->_toCode('addflag'); + } + +} + +/** + * The Sieve_Action_Removeflag class represents a remove flag action. + * + * @author Mike Cochrane + * @package Ingo + */ +class Sieve_Action_Removeflag extends Sieve_Action_Flag { + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + function toCode() + { + return $this->_toCode('removeflag'); + } + +} + +/** + * The Sieve_Action_Notify class represents a notify action. + * + * @author Paul Wolstenholme + * @package Ingo + */ +class Sieve_Action_Notify extends Sieve_Action { + + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + function Sieve_Action_Notify($vars = array()) + { + $this->_vars['address'] = isset($vars['address']) ? $vars['address'] : ''; + $this->_vars['name'] = isset($vars['name']) ? $vars['name'] : ''; + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + function toCode() + { + return 'notify :method "mailto" :options "' . + Ingo_Script_Sieve::escapeString($this->_vars['address']) . + '" :message "' . + _("You have received a new message") . "\n" . + _("From:") . " \$from\$ \n" . + _("Subject:") . " \$subject\$ \n" . + _("Rule:") . ' ' . $this->_vars['name'] . '";'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + function check() + { + if (empty($this->_vars['address'])) { + return _("Missing address to notify"); + } + + return true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + function requires() + { + return array('notify'); + } + +} diff --git a/ingo/lib/Script/Sieve/Test.php b/ingo/lib/Script/Sieve/Test.php new file mode 100644 index 000000000..7e4ed6e2e --- /dev/null +++ b/ingo/lib/Script/Sieve/Test.php @@ -0,0 +1,54 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test +{ + /** + * Any necessary test parameters. + * + * @var array + */ + protected $_vars = array(); + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'toCode() Function Not Implemented in class ' . get_class($this); + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return 'check() Function Not Implemented in class ' . get_class($this); + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return array(); + } + +} diff --git a/ingo/lib/Script/Sieve/Test/Address.php b/ingo/lib/Script/Sieve/Test/Address.php new file mode 100644 index 000000000..e116e803d --- /dev/null +++ b/ingo/lib/Script/Sieve/Test/Address.php @@ -0,0 +1,116 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test_Address extends Ingo_Script_Sieve_Test +{ + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + public function __construct($vars) + { + $this->_vars['headers'] = isset($vars['headers']) + ? $vars['headers'] + : ''; + $this->_vars['comparator'] = isset($vars['comparator']) + ? $vars['comparator'] + : 'i;ascii-casemap'; + $this->_vars['match-type'] = isset($vars['match-type']) + ? $vars['match-type'] + : ':is'; + $this->_vars['address-part'] = isset($vars['address-part']) + ? $vars['address-part'] + : ':all'; + $this->_vars['addresses'] = isset($vars['addresses']) + ? $vars['addresses'] + : ''; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return preg_split('(\r\n|\n|\r)', $this->_vars['headers']) && + preg_split('(\r\n|\n|\r)', $this->_vars['addresses']); + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + $code = 'address ' . + $this->_vars['address-part'] . ' ' . + ':comparator "' . $this->_vars['comparator'] . '" ' . + $this->_vars['match-type'] . ' '; + + $headers = preg_split('(\r\n|\n|\r|,)', $this->_vars['headers']); + $headers = array_filter($headers); + if (count($headers) > 1) { + $code .= "["; + $headerstr = ''; + foreach ($headers as $header) { + $header = trim($header); + if (!empty($header)) { + $headerstr .= empty($headerstr) ? '"' : ', "'; + $headerstr .= Ingo_Script_Sieve::escapeString($header, $this->_vars['match-type'] == ':regex') . '"'; + } + } + $code .= $headerstr . "] "; + } elseif (count($headers) == 1) { + $code .= '"' . Ingo_Script_Sieve::escapeString($headers[0], $this->_vars['match-type'] == ':regex') . '" '; + } else { + return "No Headers Specified"; + } + + $addresses = preg_split('(\r\n|\n|\r)', $this->_vars['addresses']); + $addresses = array_filter($addresses); + if (count($addresses) > 1) { + $code .= "["; + $addressstr = ''; + foreach ($addresses as $addr) { + $addr = trim($addr); + if (!empty($addr)) { + $addressstr .= empty($addressstr) ? '"' : ', "'; + $addressstr .= Ingo_Script_Sieve::escapeString($addr, $this->_vars['match-type'] == ':regex') . '"'; + } + } + $code .= $addressstr . "] "; + } elseif (count($addresses) == 1) { + $code .= '"' . Ingo_Script_Sieve::escapeString($addresses[0], $this->_vars['match-type'] == ':regex') . '" '; + } else { + return "No Addresses Specified"; + } + + return $code; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return ($this->_vars['match-type'] == ':regex') + ? array('regex') + : array(); + } + +} diff --git a/ingo/lib/Script/Sieve/Test/Allof.php b/ingo/lib/Script/Sieve/Test/Allof.php new file mode 100644 index 000000000..f35506da3 --- /dev/null +++ b/ingo/lib/Script/Sieve/Test/Allof.php @@ -0,0 +1,107 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test_Allof extends Ingo_Script_Sieve_Test +{ + /** + */ + protected $_tests = array(); + + /** + * Constructor. + * + * @param mixed $test A Ingo_Script_Sieve_Test object or a list of + * Ingo_Script_Sieve_Test objects. + */ + public function __construct($test = null) + { + if (is_array($test)) { + $this->_tests = $test; + } elseif (!is_null($test)) { + $this->_tests[] = $test; + } + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + $code = ''; + if (count($this->_tests) > 1) { + $testlist = ''; + foreach ($this->_tests as $test) { + $testlist .= (empty($testlist)) ? '' : ', '; + $testlist .= trim($test->toCode()); + } + + $code = "allof ( $testlist )"; + } elseif (count($this->_tests) == 1) { + $code = $this->_tests[0]->toCode(); + } else { + return 'true'; + } + return $code; + } + + /** + * Checks if all sub-rules are valid. + * + * @return boolean|string True if all rules are valid, an error message + * otherwise. + */ + public function check() + { + foreach ($this->_tests as $test) { + $res = $test->check(); + if ($res !== true) { + return $res; + } + } + + return true; + } + + /** + */ + public function addTest($test) + { + $this->_tests[] = $test; + } + + /** + */ + public function getTests() + { + return $this->_tests; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + $requires = array(); + + foreach ($this->_tests as $test) { + $requires = array_merge($requires, $test->requires()); + } + + return $requires; + } + +} diff --git a/ingo/lib/Script/Sieve/Test/Anyof.php b/ingo/lib/Script/Sieve/Test/Anyof.php new file mode 100644 index 000000000..913517279 --- /dev/null +++ b/ingo/lib/Script/Sieve/Test/Anyof.php @@ -0,0 +1,105 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test_Anyof extends Ingo_Script_Sieve_Test +{ + protected $_tests = array(); + + /** + * Constructor. + * + * @param mixed $test An Ingo_Script_Sieve_Test object or a list of + * Ingo_Script_Sieve_Test objects. + */ + public function __construct($test = null) + { + if (is_array($test)) { + $this->_tests = $test; + } elseif (!is_null($test)) { + $this->_tests[] = $test; + } + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + $testlist = ''; + if (count($this->_tests) > 1) { + $testlist = ''; + foreach ($this->_tests as $test) { + $testlist .= (empty($testlist)) ? '' : ', '; + $testlist .= trim($test->toCode()); + } + + $code = "anyof ( $testlist )"; + } elseif (count($this->_tests) == 1) { + $code = $this->_tests[0]->toCode(); + } else { + return 'true'; + } + return $code; + } + + /** + */ + public function addTest($test) + { + $this->_tests[] = $test; + } + + /** + */ + public function getTests() + { + return $this->_tests; + } + + /** + * Checks if all sub-rules are valid. + * + * @return boolean|string True if all rules are valid, an error message + * otherwise. + */ + public function check() + { + foreach ($this->_tests as $test) { + $res = $test->check(); + if ($res !== true) { + return $res; + } + } + + return true; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + $requires = array(); + + foreach ($this->_tests as $test) { + $requires = array_merge($requires, $test->requires()); + } + + return $requires; + } + +} diff --git a/ingo/lib/Script/Sieve/Test/Body.php b/ingo/lib/Script/Sieve/Test/Body.php new file mode 100644 index 000000000..c2d4549ca --- /dev/null +++ b/ingo/lib/Script/Sieve/Test/Body.php @@ -0,0 +1,86 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test_Body extends Ingo_Script_Sieve_Test +{ + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + public function __construct($vars = array()) + { + $this->_vars['comparator'] = isset($vars['comparator']) + ? $vars['comparator'] + : 'i;ascii-casemap'; + $this->_vars['match-type'] = isset($vars['match-type']) + ? $vars['match-type'] + : ':is'; + $this->_vars['strings'] = isset($vars['strings']) + ? $vars['strings'] + : ''; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return preg_split('((?_vars['strings']); + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + $code = 'body ' . + ':comparator "' . $this->_vars['comparator'] . '" ' . + $this->_vars['match-type'] . ' '; + + $strings = preg_split('(\r\n|\n|\r)', $this->_vars['strings']); + $strings = array_filter($strings); + if (count($strings) > 1) { + $code .= "["; + $stringlist = ''; + foreach ($strings as $str) { + $stringlist .= empty($stringlist) ? '"' : ', "'; + $stringlist .= Ingo_Script_Sieve::escapeString($str, $this->_vars['match-type'] == ':regex') . '"'; + } + $code .= $stringlist . "] "; + } elseif (count($strings) == 1) { + $code .= '"' . Ingo_Script_Sieve::escapeString($strings[0], $this->_vars['match-type'] == ':regex') . '" '; + } else { + return _("No strings specified"); + } + + return $code; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return ($this->_vars['match-type'] == ':regex') + ? array('regex', 'body') + : array('body'); + } + +} diff --git a/ingo/lib/Script/Sieve/Test/Exists.php b/ingo/lib/Script/Sieve/Test/Exists.php new file mode 100644 index 000000000..a8c34a50a --- /dev/null +++ b/ingo/lib/Script/Sieve/Test/Exists.php @@ -0,0 +1,65 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test_Exists extends Ingo_Script_Sieve_Test +{ + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + public function __construct($vars = array()) + { + $this->_vars['headers'] = isset($vars['headers']) + ? $vars['headers'] + : ''; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return preg_split('(\r\n|\n|\r)', $this->_vars['headers']) + ? true + : _("No headers specified"); + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + $code = 'exists '; + $headers = preg_split('(\r\n|\n|\r)', $this->_vars['headers']); + if (count($headers) > 1) { + $code .= "["; + $headerstr = ''; + foreach ($headers as $header) { + $headerstr .= (empty($headerstr) ? '"' : ', "') . + Ingo_Script_Sieve::escapeString($header) . '"'; + } + $code .= $headerstr . "] "; + } elseif (count($headers) == 1) { + $code .= '"' . Ingo_Script_Sieve::escapeString($headers[0]) . '" '; + } else { + return "**error** No Headers Specified"; + } + + return $code; + } + +} diff --git a/ingo/lib/Script/Sieve/Test/False.php b/ingo/lib/Script/Sieve/Test/False.php new file mode 100644 index 000000000..c997cea31 --- /dev/null +++ b/ingo/lib/Script/Sieve/Test/False.php @@ -0,0 +1,35 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test_False extends Ingo_Script_Sieve_Test +{ + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'false'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return true; + } + +} diff --git a/ingo/lib/Script/Sieve/Test/Header.php b/ingo/lib/Script/Sieve/Test/Header.php new file mode 100644 index 000000000..c317218e8 --- /dev/null +++ b/ingo/lib/Script/Sieve/Test/Header.php @@ -0,0 +1,106 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test_Header extends Ingo_Script_Sieve_Test +{ + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + public function __construct($vars = array()) + { + $this->_vars['headers'] = isset($vars['headers']) + ? $vars['headers'] + : 'Subject'; + $this->_vars['comparator'] = isset($vars['comparator']) + ? $vars['comparator'] + : 'i;ascii-casemap'; + $this->_vars['match-type'] = isset($vars['match-type']) + ? $vars['match-type'] + : ':is'; + $this->_vars['strings'] = isset($vars['strings']) + ? $vars['strings'] + : ''; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return preg_split('((?_vars['headers']) && + preg_split('((?_vars['strings']); + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + $code = 'header ' . + ':comparator "' . $this->_vars['comparator'] . '" ' . + $this->_vars['match-type'] . ' '; + + $headers = preg_split('(\r\n|\n|\r)', $this->_vars['headers']); + $headers = array_filter($headers); + if (count($headers) > 1) { + $code .= "["; + $headerstr = ''; + foreach ($headers as $header) { + $headerstr .= empty($headerstr) ? '"' : ', "'; + $headerstr .= Ingo_Script_Sieve::escapeString($header, $this->_vars['match-type'] == ':regex') . '"'; + } + $code .= $headerstr . "] "; + } elseif (count($headers) == 1) { + $code .= '"' . $headers[0] . '" '; + } else { + return _("No headers specified"); + } + + $strings = preg_split('(\r\n|\n|\r)', $this->_vars['strings']); + $strings = array_filter($strings); + if (count($strings) > 1) { + $code .= "["; + $stringlist = ''; + foreach ($strings as $str) { + $stringlist .= empty($stringlist) ? '"' : ', "'; + $stringlist .= Ingo_Script_Sieve::escapeString($str, $this->_vars['match-type'] == ':regex') . '"'; + } + $code .= $stringlist . "] "; + } elseif (count($strings) == 1) { + $code .= '"' . Ingo_Script_Sieve::escapeString(reset($strings), $this->_vars['match-type'] == ':regex') . '" '; + } else { + return _("No strings specified"); + } + + return $code; + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return ($this->_vars['match-type'] == ':regex') + ? array('regex') + : array(); + } + +} diff --git a/ingo/lib/Script/Sieve/Test/Not.php b/ingo/lib/Script/Sieve/Test/Not.php new file mode 100644 index 000000000..f9825cc5e --- /dev/null +++ b/ingo/lib/Script/Sieve/Test/Not.php @@ -0,0 +1,60 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test_Not extends Ingo_Script_Sieve_Test +{ + /** + */ + protected $_test = array(); + + /** + * Constructor. + * + * @param Ingo_Script_Sieve_Test $test An Ingo_Script_Sieve_Test object. + */ + public function __construct($test) + { + $this->_test = $test; + } + + /** + * Checks if the sub-rule is valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return $this->_test->check(); + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'not ' . $this->_test->toCode(); + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return $this->_test->requires(); + } + +} diff --git a/ingo/lib/Script/Sieve/Test/Relational.php b/ingo/lib/Script/Sieve/Test/Relational.php new file mode 100644 index 000000000..b9b704d64 --- /dev/null +++ b/ingo/lib/Script/Sieve/Test/Relational.php @@ -0,0 +1,107 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test_Relational extends Ingo_Script_Sieve_Test +{ + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + public function __construct($vars = array()) + { + $this->_vars['comparison'] = isset($vars['comparison']) + ? $vars['comparison'] + : ''; + $this->_vars['headers'] = isset($vars['headers']) + ? $vars['headers'] + : ''; + $this->_vars['value'] = isset($vars['value']) + ? $vars['value'] + : 0; + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + $code = 'header :value "' . + $this->_vars['comparison'] . '" ' . + ':comparator "i;ascii-numeric" '; + + $headers = preg_split('(\r\n|\n|\r)', $this->_vars['headers']); + $header_count = count($headers); + + if ($header_count > 1) { + $code .= "["; + $headerstr = ''; + + foreach ($headers as $val) { + $headerstr .= (empty($headerstr) ? '"' : ', "') . + Ingo_Script_Sieve::escapeString($val) . '"'; + } + + $code .= $headerstr . '] '; + $headerstr = '[' . $headerstr . ']'; + } elseif ($header_count == 1) { + $code .= '"' . Ingo_Script_Sieve::escapeString($headers[0]) . '" '; + $headerstr = Ingo_Script_Sieve::escapeString($headers[0]); + } + + $code .= '["' . $this->_vars['value'] . '"]'; + + // Add workarounds for negative numbers - works only if the comparison + // value is positive. Sieve doesn't support comparisons of negative + // numbers at all so this is the best we can do. + switch ($this->_vars['comparison']) { + case 'gt': + case 'ge': + case 'eq': + // Greater than, greater or equal, equal: number must be + // non-negative. + return 'allof ( not header :comparator "i;ascii-casemap" :contains "' + . $headerstr . '" "-", ' . $code . ' )'; + + case 'lt': + case 'le': + case 'ne': + // Less than, less or equal, nonequal: also match negative numbers + return 'anyof ( header :comparator "i;ascii-casemap" :contains "' + . $headerstr . '" "-", ' . $code . ' )'; + } + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + $headers = preg_split('(\r\n|\n|\r)', $this->_vars['headers']); + return $headers ? true : _("No headers specified"); + } + + /** + * Returns a list of sieve extensions required for this rule and any + * sub-rules. + * + * @return array A Sieve extension list. + */ + public function requires() + { + return array('relational', 'comparator-i;ascii-numeric'); + } + +} diff --git a/ingo/lib/Script/Sieve/Test/Size.php b/ingo/lib/Script/Sieve/Test/Size.php new file mode 100644 index 000000000..5e1ca732f --- /dev/null +++ b/ingo/lib/Script/Sieve/Test/Size.php @@ -0,0 +1,54 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test_Size extends Ingo_Script_Sieve_Test +{ + /** + * Constructor. + * + * @param array $vars Any required parameters. + */ + public function __construct($vars = array()) + { + $this->_vars['comparison'] = isset($vars['comparison']) + ? $vars['comparison'] + : ''; + $this->_vars['size'] = isset($vars['size']) + ? $vars['size'] + : ''; + } + + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'size ' . $this->_vars['comparison'] . ' ' . $this->_vars['size']; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + if (!(isset($this->_vars['comparison']) && + isset($this->_vars['size']))) { + return false; + } + + return true; + } + +} diff --git a/ingo/lib/Script/Sieve/Test/True.php b/ingo/lib/Script/Sieve/Test/True.php new file mode 100644 index 000000000..414e60851 --- /dev/null +++ b/ingo/lib/Script/Sieve/Test/True.php @@ -0,0 +1,35 @@ + + * @package Ingo + */ +class Ingo_Script_Sieve_Test_True extends Ingo_Script_Sieve_Test +{ + /** + * Returns a script snippet representing this rule and any sub-rules. + * + * @return string A Sieve script snippet. + */ + public function toCode() + { + return 'true'; + } + + /** + * Checks if the rule parameters are valid. + * + * @return boolean|string True if this rule is valid, an error message + * otherwise. + */ + public function check() + { + return true; + } + +} diff --git a/ingo/lib/Session.php b/ingo/lib/Session.php deleted file mode 100644 index da03b760b..000000000 --- a/ingo/lib/Session.php +++ /dev/null @@ -1,71 +0,0 @@ - - * @package Ingo - */ -class Ingo_Session -{ - /** - * Create an ingo session. - * This function should only be called once, when the user first uses - * Ingo in a session. - * - * Creates the $ingo session variable with the following entries: - * 'backend' (array) - The backend configuration to use. - * 'change' (integer) - The timestamp of the last time the rules were - * altered. - * 'storage' (array) - Used by Ingo_Storage:: for caching data. - * 'script_categories' (array) - The list of available categories for the - * Ingo_Script driver in use. - * 'script_generate' (boolean) - Is the Ingo_Script::generate() call - * available? - * - * @return boolean True on success, false on failure. - */ - static public function createSession() - { - global $prefs; - - $_SESSION['ingo'] = array( - 'change' => 0, - 'storage' => array(), - /* Get the backend. */ - 'backend' => Ingo::getBackend()); - - /* Determine if the Ingo_Script:: generate() method is available. */ - $ingo_script = Ingo::loadIngoScript(); - $_SESSION['ingo']['script_generate'] = $ingo_script->generateAvailable(); - - /* Disable categories as specified in preferences */ - $disabled = array(); - if ($prefs->isLocked('blacklist')) { - $disabled[] = Ingo_Storage::ACTION_BLACKLIST; - } - if ($prefs->isLocked('whitelist')) { - $disabled[] = Ingo_Storage::ACTION_WHITELIST; - } - if ($prefs->isLocked('vacation')) { - $disabled[] = Ingo_Storage::ACTION_VACATION; - } - if ($prefs->isLocked('forward')) { - $disabled[] = Ingo_Storage::ACTION_FORWARD; - } - if ($prefs->isLocked('spam')) { - $disabled[] = Ingo_Storage::ACTION_SPAM; - } - - /* Set the list of categories this driver supports. */ - $_SESSION['ingo']['script_categories'] = - array_merge($ingo_script->availableActions(), - array_diff($ingo_script->availableCategories(), - $disabled)); - } - -} diff --git a/ingo/lib/Storage.php b/ingo/lib/Storage.php index b8716ca16..599085a23 100644 --- a/ingo/lib/Storage.php +++ b/ingo/lib/Storage.php @@ -131,6 +131,7 @@ class Ingo_Storage * @param boolean $readonly Whether to disable any write operations. * * @return Ingo_Storage_Rule|Ingo_Storage_Filters The specified object. + * @throws Ingo_Exception */ public function retrieve($field, $cache = true, $readonly = false) { @@ -156,8 +157,6 @@ class Ingo_Storage /** * Retrieves the specified data from the storage backend. * - * @abstract - * * @param integer $field The field name of the desired data. * See lib/Storage.php for the available fields. * @param boolean $readonly Whether to disable any write operations. @@ -176,6 +175,7 @@ class Ingo_Storage * @param boolean $cache Cache the object? * * @return boolean True on success. + * @throws Ingo_Exception */ public function store(&$ob, $cache = true) { @@ -209,10 +209,7 @@ class Ingo_Storage break; } $filters->addRule(array('action' => $type, 'name' => $name)); - $result = $this->store($filters, $cache); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->store($filters, $cache); } } @@ -227,8 +224,6 @@ class Ingo_Storage /** * Stores the specified data in the storage backend. * - * @abstract - * * @param Ingo_Storage_Rule|Ingo_Storage_Filters $ob The object to store. * * @return boolean True on success. @@ -376,13 +371,13 @@ class Ingo_Storage * Removes the user data from the storage backend. * Stub for child class to override if it can implement. * - * @param string $user The user name to delete filters for. + * @param string $user The user name to delete filters for. * - * @return mixed True | PEAR_Error + * @throws Ingo_Exception */ - function removeUserData($user) + public function removeUserData($user) { - return PEAR::raiseError(_("Removing user data is not supported with the current filter storage backend.")); + throw new Ingo_Exception(_("Removing user data is not supported with the current filter storage backend.")); } } diff --git a/ingo/lib/Storage/Blacklist.php b/ingo/lib/Storage/Blacklist.php index 74f2cbe91..e1aeca00c 100644 --- a/ingo/lib/Storage/Blacklist.php +++ b/ingo/lib/Storage/Blacklist.php @@ -21,7 +21,8 @@ class Ingo_Storage_Blacklist extends Ingo_Storage_Rule * @param mixed $data The list of addresses (array or string). * @param boolean $sort Sort the list? * - * @return mixed PEAR_Error on error, true on success. + * @return boolean True on success. + * @throws Ingo_Exception */ public function setBlacklist($data, $sort = true) { @@ -29,7 +30,7 @@ class Ingo_Storage_Blacklist extends Ingo_Storage_Rule if (!empty($GLOBALS['conf']['storage']['maxblacklist'])) { $addr_count = count($addr); if ($addr_count > $GLOBALS['conf']['storage']['maxblacklist']) { - return PEAR::raiseError(sprintf(_("Maximum number of blacklisted addresses exceeded (Total addresses: %s, Maximum addresses: %s). Could not add new addresses to blacklist."), $addr_count, $GLOBALS['conf']['storage']['maxblacklist']), 'horde.error'); + throw new Ingo_Exception(sprintf(_("Maximum number of blacklisted addresses exceeded (Total addresses: %s, Maximum addresses: %s). Could not add new addresses to blacklist."), $addr_count, $GLOBALS['conf']['storage']['maxblacklist']), 'horde.error'); } } @@ -37,11 +38,15 @@ class Ingo_Storage_Blacklist extends Ingo_Storage_Rule return true; } + /** + */ public function setBlacklistFolder($data) { $this->_folder = $data; } + /** + */ public function getBlacklist() { return empty($this->_addr) @@ -49,6 +54,8 @@ class Ingo_Storage_Blacklist extends Ingo_Storage_Rule : array_filter($this->_addr, array('Ingo', 'filterEmptyAddress')); } + /** + */ public function getBlacklistFolder() { return $this->_folder; diff --git a/ingo/lib/Storage/Forward.php b/ingo/lib/Storage/Forward.php index 8a23f485e..51b2b79dc 100644 --- a/ingo/lib/Storage/Forward.php +++ b/ingo/lib/Storage/Forward.php @@ -11,20 +11,34 @@ */ class Ingo_Storage_Forward extends Ingo_Storage_Rule { + /** + */ protected $_addr = array(); + + /** + */ protected $_keep = true; + + /** + */ protected $_obtype = Ingo_Storage::ACTION_FORWARD; + /** + */ public function setForwardAddresses($data, $sort = true) { $this->_addr = $this->_addressList($data, $sort); } + /** + */ public function setForwardKeep($data) { $this->_keep = $data; } + /** + */ public function getForwardAddresses() { if (is_array($this->_addr)) { @@ -37,6 +51,8 @@ class Ingo_Storage_Forward extends Ingo_Storage_Rule return $this->_addr; } + /** + */ public function getForwardKeep() { return $this->_keep; diff --git a/ingo/lib/Storage/Mock.php b/ingo/lib/Storage/Mock.php index 373fb0789..b046c899a 100644 --- a/ingo/lib/Storage/Mock.php +++ b/ingo/lib/Storage/Mock.php @@ -12,8 +12,12 @@ class Ingo_Storage_Mock extends Ingo_Storage { + /** + */ protected $_data = array(); + /** + */ protected function _retrieve($field) { if (empty($this->_data[$field])) { @@ -47,6 +51,8 @@ class Ingo_Storage_Mock extends Ingo_Storage return $this->_data[$field]; } + /** + */ protected function _store(&$ob) { $this->_data[$ob->obType()] = $ob; diff --git a/ingo/lib/Storage/Rule.php b/ingo/lib/Storage/Rule.php index 9dfb0e7f2..bbf345321 100644 --- a/ingo/lib/Storage/Rule.php +++ b/ingo/lib/Storage/Rule.php @@ -74,11 +74,9 @@ class Ingo_Storage_Rule $output = (empty($data)) ? array() : preg_split("/\s+/", $data); } - if ($sort) { - $output = Horde_Array::prepareAddressList($output); - } - - return $output; + return $sort + ? Horde_Array::prepareAddressList($output) + : $output; } } diff --git a/ingo/lib/Storage/Spam.php b/ingo/lib/Storage/Spam.php index 9f3f2da2b..dfc61e58d 100644 --- a/ingo/lib/Storage/Spam.php +++ b/ingo/lib/Storage/Spam.php @@ -18,24 +18,37 @@ class Ingo_Storage_Spam extends Ingo_Storage_Rule */ protected $_obtype = Ingo_Storage::ACTION_SPAM; + /** + */ protected $_folder = null; + + /** + */ protected $_level = 5; + /** + */ public function setSpamFolder($folder) { $this->_folder = $folder; } + /** + */ public function setSpamLevel($level) { $this->_level = $level; } + /** + */ public function getSpamFolder() { return $this->_folder; } + /** + */ public function getSpamLevel() { return $this->_level; diff --git a/ingo/lib/Storage/Sql.php b/ingo/lib/Storage/Sql.php index 07d68bf45..584b7c9f6 100644 --- a/ingo/lib/Storage/Sql.php +++ b/ingo/lib/Storage/Sql.php @@ -139,10 +139,7 @@ class Ingo_Storage_Sql extends Ingo_Storage case self::ACTION_WHITELIST: if ($field == self::ACTION_BLACKLIST) { $ob = new Ingo_Storage_Blacklist(); - $filters = &$this->retrieve(self::ACTION_FILTERS); - if (is_a($filters, 'PEAR_Error')) { - return $filters; - } + $filters = $this->retrieve(self::ACTION_FILTERS); $rule = $filters->findRule($field); if (isset($rule['action-value'])) { $ob->setBlacklistFolder($rule['action-value']); @@ -271,10 +268,7 @@ class Ingo_Storage_Sql extends Ingo_Storage case self::ACTION_WHITELIST: $is_blacklist = (int)($ob->obType() == self::ACTION_BLACKLIST); if ($is_blacklist) { - $filters = &$this->retrieve(self::ACTION_FILTERS); - if (is_a($filters, 'PEAR_Error')) { - return $filters; - } + $filters = $this->retrieve(self::ACTION_FILTERS); $id = $filters->findRuleId(self::ACTION_BLACKLIST); if ($id !== null) { $rule = $filters->getRule($id); @@ -402,12 +396,12 @@ class Ingo_Storage_Sql extends Ingo_Storage * * @param string $user The user name to delete filters for. * - * @return mixed True | PEAR_Error + * @throws Ingo_Exception */ - function removeUserData($user) + public function removeUserData($user) { if (!Horde_Auth::isAdmin() && $user != Horde_Auth::getAuth()) { - return PEAR::raiseError(_("Permission Denied")); + throw new Ingo_Exception(_("Permission Denied")); } $queries = array(sprintf('DELETE FROM %s WHERE rule_owner = ?', @@ -425,8 +419,8 @@ class Ingo_Storage_Sql extends Ingo_Storage foreach ($queries as $query) { Horde::logMessage('Ingo_Storage_sql::removeUserData(): ' . $query, __FILE__, __LINE__, PEAR_LOG_DEBUG); $result = $this->_write_db->query($query, $values); - if (is_a($result, 'PEAR_Error')) { - return $result; + if ($result instanceof PEAR_Error) { + throw new Ingo_Exception($result); } } diff --git a/ingo/lib/Storage/Vacation.php b/ingo/lib/Storage/Vacation.php index 08bc6e998..43e767201 100644 --- a/ingo/lib/Storage/Vacation.php +++ b/ingo/lib/Storage/Vacation.php @@ -11,56 +11,101 @@ */ class Ingo_Storage_Vacation extends Ingo_Storage_Rule { + + /** + */ protected $_addr = array(); + + /** + */ protected $_days = 7; + + /** + */ protected $_excludes = array(); + + /** + */ protected $_ignorelist = true; + + /** + */ protected $_reason = ''; + + /** + */ protected $_subject = ''; + + /** + */ protected $_start; + + /** + */ protected $_end; + + /** + */ protected $_obtype = Ingo_Storage::ACTION_VACATION; + /** + */ public function setVacationAddresses($data, $sort = true) { $this->_addr = $this->_addressList($data, $sort); } + /** + */ public function setVacationDays($data) { $this->_days = $data; } + /** + */ public function setVacationExcludes($data, $sort = true) { $this->_excludes = $this->_addressList($data, $sort); } + /** + */ public function setVacationIgnorelist($data) { $this->_ignorelist = $data; } + /** + */ public function setVacationReason($data) { $this->_reason = $data; } + /** + */ public function setVacationSubject($data) { $this->_subject = $data; } + /** + */ public function setVacationStart($data) { $this->_start = $data; } + /** + */ public function setVacationEnd($data) { $this->_end = $data; } + /** + */ public function getVacationAddresses() { try { @@ -70,66 +115,92 @@ class Ingo_Storage_Vacation extends Ingo_Storage_Rule } } + /** + */ public function getVacationDays() { return $this->_days; } + /** + */ public function getVacationExcludes() { return $this->_excludes; } + /** + */ public function getVacationIgnorelist() { return $this->_ignorelist; } + /** + */ public function getVacationReason() { return $this->_reason; } + /** + */ public function getVacationSubject() { return $this->_subject; } + /** + */ public function getVacationStart() { return $this->_start; } + /** + */ public function getVacationStartYear() { return date('Y', $this->_start); } + /** + */ public function getVacationStartMonth() { return date('n', $this->_start); } + /** + */ public function getVacationStartDay() { return date('j', $this->_start); } + /** + */ public function getVacationEnd() { return $this->_end; } + /** + */ public function getVacationEndYear() { return date('Y', $this->_end); } + /** + */ public function getVacationEndMonth() { return date('n', $this->_end); } + /** + */ public function getVacationEndDay() { return date('j', $this->_end); diff --git a/ingo/lib/Storage/VacationTest.php b/ingo/lib/Storage/VacationTest.php index 682b5d40b..f0fa926f7 100644 --- a/ingo/lib/Storage/VacationTest.php +++ b/ingo/lib/Storage/VacationTest.php @@ -11,8 +11,11 @@ */ class Ingo_Storage_VacationTest extends Ingo_Storage_Vacation { + /** + */ public function getVacationAddresses() { return $this->_addr; } + } diff --git a/ingo/lib/Storage/Whitelist.php b/ingo/lib/Storage/Whitelist.php index 38c56839a..919b92f52 100644 --- a/ingo/lib/Storage/Whitelist.php +++ b/ingo/lib/Storage/Whitelist.php @@ -11,7 +11,12 @@ */ class Ingo_Storage_Whitelist extends Ingo_Storage_Rule { + /** + */ protected $_addr = array(); + + /** + */ protected $_obtype = Ingo_Storage::ACTION_WHITELIST; /** @@ -20,7 +25,8 @@ class Ingo_Storage_Whitelist extends Ingo_Storage_Rule * @param mixed $data The list of addresses (array or string). * @param boolean $sort Sort the list? * - * @return mixed PEAR_Error on error, true on success. + * @return boolean True on success. + * @throws Ingo_Exception */ public function setWhitelist($data, $sort = true) { @@ -29,7 +35,7 @@ class Ingo_Storage_Whitelist extends Ingo_Storage_Rule if (!empty($GLOBALS['conf']['storage']['maxwhitelist'])) { $addr_count = count($addr); if ($addr_count > $GLOBALS['conf']['storage']['maxwhitelist']) { - return PEAR::raiseError(sprintf(_("Maximum number of whitelisted addresses exceeded (Total addresses: %s, Maximum addresses: %s). Could not add new addresses to whitelist."), $addr_count, $GLOBALS['conf']['storage']['maxwhitelist']), 'horde.error'); + throw new Ingo_Exception(sprintf(_("Maximum number of whitelisted addresses exceeded (Total addresses: %s, Maximum addresses: %s). Could not add new addresses to whitelist."), $addr_count, $GLOBALS['conf']['storage']['maxwhitelist']), 'horde.error'); } } @@ -37,6 +43,8 @@ class Ingo_Storage_Whitelist extends Ingo_Storage_Rule return true; } + /** + */ public function getWhitelist() { return empty($this->_addr) diff --git a/ingo/rule.php b/ingo/rule.php index 2c5e472d4..03b61c82a 100644 --- a/ingo/rule.php +++ b/ingo/rule.php @@ -41,12 +41,11 @@ if (empty($availActions)) { require INGO_BASE . '/config/fields.php'; /* Get the current rules. */ -$filters = &$ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); +$filters = $ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); /* Run through action handlers. */ -$actionID = Horde_Util::getFormData('actionID'); -$edit_number = Horde_Util::getFormData('edit'); -switch ($actionID) { +$vars = Horde_Variables::getDefaultVariables(); +switch ($vars->actionID) { case 'create_folder': case 'rule_save': case 'rule_update': @@ -58,26 +57,24 @@ case 'rule_delete': } $rule = array( - 'id' => Horde_Util::getFormData('id'), - 'name' => Horde_Util::getFormData('name'), - 'combine' => Horde_Util::getFormData('combine'), + 'id' => $vars->id, + 'name' => $vars->name, + 'combine' => $vars->combine, 'conditions' => array() ); - $field = Horde_Util::getFormData('field'); - $match = Horde_Util::getFormData('match'); - $userheader = Horde_Util::getFormData('userheader'); - $value = Horde_Util::getFormData('value'); if ($ingo_script->caseSensitive()) { - $casesensitive = Horde_Util::getFormData('case'); + $casesensitive = $vars->case; } $valid = true; - foreach ($field as $key => $val) { + foreach ($vars->field as $key => $val) { if (!empty($val)) { $condition = array(); if ($val == Ingo::USER_HEADER) { - $condition['field'] = (empty($userheader[$key])) ? '' : $userheader[$key]; + $condition['field'] = empty($vars->userheader[$key]) + ? '' + : $vars->userheader[$key]; $condition['type'] = Ingo_Storage::TYPE_HEADER; } elseif (!isset($ingo_fields[$val])) { $condition['field'] = $val; @@ -86,35 +83,38 @@ case 'rule_delete': $condition['field'] = $val; $condition['type'] = $ingo_fields[$val]['type']; } - $condition['match'] = isset($match[$key]) ? $match[$key] : ''; + $condition['match'] = isset($vars->match[$key]) + ? $vars->match[$key] + : ''; - if ($actionID == 'rule_save' - && empty($value[$key]) - && $condition['match'] != 'exists' - && $condition['match'] != 'not exist') { + if (($vars->actionID == 'rule_save') && + empty($vars->value[$key]) && + !in_array($condition['match'], array('exists', 'not exist'))) { $notification->push(sprintf(_("You cannot create empty conditions. Please fill in a value for \"%s\"."), $condition['field']), 'horde.error'); $valid = false; } - $condition['value'] = isset($value[$key]) ? $value[$key] : ''; + $condition['value'] = isset($vars->value[$key]) + ? $vars->value[$key] + : ''; if (isset($casesensitive)) { - $condition['case'] = isset($casesensitive[$key]) ? $casesensitive[$key] : ''; + $condition['case'] = isset($casesensitive[$key]) + ? $casesensitive[$key] + : ''; } $rule['conditions'][] = $condition; } } - if ($actionID == 'create_folder') { - $rule['action-value'] = Ingo::createFolder(Horde_Util::getFormData('new_folder_name')); - } else { - $rule['action-value'] = Horde_Util::getFormData('actionvalue'); - } + $rule['action-value'] = ($vars->actionID == 'create_folder') + ? Ingo::createFolder($vars->new_folder_name) + : $vars->actionvalue; - $rule['action'] = Horde_Util::getFormData('action'); - $rule['stop'] = Horde_Util::getFormData('stop'); + $rule['action'] = $vars->action; + $rule['stop'] = $vars->stop; $rule['flags'] = 0; - $flags = Horde_Util::getFormData('flags', array()); + $flags = $vars->flags || array(); if (!empty($flags)) { foreach ($flags as $val) { $rule['flags'] |= $val; @@ -125,8 +125,8 @@ case 'rule_delete': $_SESSION['ingo']['change'] = time(); /* Save the rule. */ - if ($actionID == 'rule_save' && $valid) { - if (is_null($edit_number)) { + if ($vars->actionID == 'rule_save' && $valid) { + if (!isset($vars->edit)) { if ($GLOBALS['perms']->hasAppPermission('max_rules') !== true && $GLOBALS['perms']->hasAppPermission('max_rules') <= count($filters->getFilterList())) { header('Location: ' . Horde::applicationUrl('filters.php', true)); @@ -134,7 +134,7 @@ case 'rule_delete': } $filters->addRule($rule); } else { - $filters->updateRule($rule, $edit_number); + $filters->updateRule($rule, $vars->edit); } $ingo_storage->store($filters); $notification->push(_("Changes saved."), 'horde.success'); @@ -145,15 +145,16 @@ case 'rule_delete': header('Location: ' . Horde::applicationUrl('filters.php')); exit; - } elseif ($actionID == 'rule_delete') { + } + + if ($vars->actionID == 'rule_delete') { if (!Ingo::hasSharePermission(Horde_Perms::DELETE)) { $notification->push(_("You do not have permission to delete filter rules."), 'horde.error'); header('Location: ' . Horde::applicationUrl('filters.php', true)); exit; } - $cond_num = Horde_Util::getFormData('conditionnumber'); - if (!is_null($cond_num)) { - unset($rule['conditions'][$cond_num]); + if (isset($vars->conditionnumber)) { + unset($rule['conditions'][$vars->conditionnumner]); $rule['conditions'] = array_values($rule['conditions']); } } @@ -165,7 +166,7 @@ default: header('Location: ' . Horde::applicationUrl('filters.php', true)); exit; } - if (is_null($edit_number)) { + if (!isset($vars->edit)) { if ($GLOBALS['perms']->hasAppPermission('max_rules') !== true && $GLOBALS['perms']->hasAppPermission('max_rules') <= count($filters->getFilterList())) { try { @@ -179,7 +180,7 @@ default: } $rule = $filters->getDefaultRule(); } else { - $rule = $filters->getRule($edit_number); + $rule = $filters->getRule($vars->edit); } break; } @@ -254,11 +255,10 @@ foreach ($rule['conditions'] as $cond_num => $condition) { '\n"; if (!$option_selected) { $header_entry = true; - $userheader = Horde_Util::getFormData('userheader'); - if (empty($userheader)) { - $userheader = isset($condition['field']) ? $condition['field'] : ''; + if (empty($vars->userheader)) { + $vars->userheader = isset($condition['field']) ? $condition['field'] : ''; } else { - $userheader = $userheader[$cond_num]; + $vars->userheader = $vars->userheader[$cond_num]; } } } diff --git a/ingo/script.php b/ingo/script.php index 70199b4ba..e865eeb3f 100644 --- a/ingo/script.php +++ b/ingo/script.php @@ -21,10 +21,9 @@ $script = ''; /* Get the Ingo_Script:: backend. */ $scriptor = Ingo::loadIngoScript(); -if ($scriptor) { - /* Generate the script. */ - $script = $scriptor->generate(); -} + +/* Generate the script. */ +$script = $scriptor->generate(); /* Activate/deactivate script if requested. activateScript() does its own $notification->push() on error. */ @@ -41,9 +40,10 @@ case 'action_deactivate': break; case 'show_active': - $script = Ingo::getScript(); - if (is_a($script, 'PEAR_Error')) { - $notification->push($script, 'horde.error'); + try { + $script = Ingo::getScript(); + } catch (Ingo_Exception $e) { + $notification->push($e); $script = ''; } break; diff --git a/ingo/scripts/ingo-postfix-policyd b/ingo/scripts/ingo-postfix-policyd index 595314766..14c3df236 100755 --- a/ingo/scripts/ingo-postfix-policyd +++ b/ingo/scripts/ingo-postfix-policyd @@ -134,19 +134,20 @@ function smtpd_access_policy($query) // Retrieve the data. $GLOBALS['auth']->setAuth($user, array()); $_SESSION['ingo']['current_share'] = ':' . $user; - $wl = $GLOBALS['rules_storage']->retrieve(Ingo_Storage::ACTION_WHITELIST, false); - $bl = $GLOBALS['rules_storage']->retrieve(Ingo_Storage::ACTION_BLACKLIST, false); - // Fill in data from saved rules. - if (!is_a($wl, 'PEAR_Error')) { - $whitelists[$user] = $wl->getWhitelist(); - } - if (!is_a($bl, 'PEAR_Error') && !$bl->getBlacklistFolder()) { - // We will only reject email at delivery time if the user - // wants blacklisted mail deleted completely, not filed - // into a separate folder. - $blacklists[$user] = $bl->getBlacklist(); - } + try { + $whitelists[$user] = $GLOBALS['rules_storage']->retrieve(Ingo_Storage::ACTION_WHITELIST, false)->getWhitelist(); + } catch (Ingo_Exception $e) {} + + try { + $bl = $GLOBALS['rules_storage']->retrieve(Ingo_Storage::ACTION_BLACKLIST, false); + if (!$bl->getBlacklistFolder()) { + // We will only reject email at delivery time if the user + // wants blacklisted mail deleted completely, not filed + // into a separate folder. + $blacklists[$user] = $bl->getBlacklist(); + } + } catch (Ingo_Exception $e) {} } // Check whitelist rules first so that mistaken overlap doesn't diff --git a/ingo/scripts/upgrades/convert_prefs_to_sql.php b/ingo/scripts/upgrades/convert_prefs_to_sql.php index 01f28a839..84f7d33be 100755 --- a/ingo/scripts/upgrades/convert_prefs_to_sql.php +++ b/ingo/scripts/upgrades/convert_prefs_to_sql.php @@ -57,7 +57,7 @@ while (!feof(STDIN)) { foreach ($rules as $rule) { $filter = $prefs_storage->retrieve($rule, false); if ($rule == Ingo_Storage::ACTION_FILTERS) { - $new_filter = &$sql_storage->retrieve(Ingo_Storage::ACTION_FILTERS, true, true); + $new_filter = $sql_storage->retrieve(Ingo_Storage::ACTION_FILTERS, true, true); foreach ($filter->getFilterList() as $rule) { $new_filter->addRule($rule); echo '.'; diff --git a/ingo/spam.php b/ingo/spam.php index 2cb9ffa95..f06099eb5 100644 --- a/ingo/spam.php +++ b/ingo/spam.php @@ -48,13 +48,13 @@ if (!in_array(Ingo_Storage::ACTION_SPAM, $_SESSION['ingo']['script_categories']) } /* Get the spam object and rule. */ -$spam = &$ingo_storage->retrieve(Ingo_Storage::ACTION_SPAM); -$filters = &$ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); +$spam = $ingo_storage->retrieve(Ingo_Storage::ACTION_SPAM); +$filters = $ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); $spam_id = $filters->findRuleId(Ingo_Storage::ACTION_SPAM); $spam_rule = $filters->getRule($spam_id); -$vars = &Horde_Variables::getDefaultVariables(); -if ($vars->get('submitbutton') == _("Return to Rules List")) { +$vars = Horde_Variables::getDefaultVariables(); +if ($vars->submitbutton == _("Return to Rules List")) { header('Location: ' . Horde::applicationUrl('filters.php', true)); exit; } @@ -63,10 +63,10 @@ if ($vars->get('submitbutton') == _("Return to Rules List")) { $form = new Horde_Form($vars); $renderer = new Horde_Form_Renderer(array('varrenderer_driver' => array('ingo', 'ingo'), 'encode_title' => false)); -$v = &$form->addVariable(_("Spam Level:"), 'level', 'int', false, false, _("Messages with a likely spam score greater than or equal to this number will be treated as spam.")); +$v = $form->addVariable(_("Spam Level:"), 'level', 'int', false, false, _("Messages with a likely spam score greater than or equal to this number will be treated as spam.")); $v->setHelp('spam-level'); -$folder_var = &$form->addVariable(_("Folder to receive spam:"), 'folder', 'ingo_folders', false); +$folder_var = $form->addVariable(_("Folder to receive spam:"), 'folder', 'ingo_folders', false); $folder_var->setHelp('spam-folder'); $form->addHidden('', 'actionID', 'text', false); $form->addHidden('', 'new_folder_name', 'text', false); @@ -78,9 +78,9 @@ if ($form->validate($vars)) { $success = true; // Create a new folder if requested. - if ($vars->get('actionID') == 'create_folder') { + if ($vars->actionID == 'create_folder') { try { - $result = Ingo::createFolder($vars->get('new_folder_name')); + $result = Ingo::createFolder($vars->new_folder_name); if ($result) { $spam->setSpamFolder($result); } else { @@ -88,39 +88,33 @@ if ($form->validate($vars)) { } } catch (Horde_Exception $e) { $success = false; - $notification->push($e->getMessage()); + $notification->push($e); } } else { - $spam->setSpamFolder($vars->get('folder')); + $spam->setSpamFolder($vars->folder); } - $spam->setSpamLevel($vars->get('level')); + $spam->setSpamLevel($vars->level); - if (is_a($result = $ingo_storage->store($spam), 'PEAR_Error')) { - $notification->push($result); - $success = false; - } else { + try { + $ingo_storage->store($spam): $notification->push(_("Changes saved."), 'horde.success'); - if ($vars->get('submitbutton') == _("Save and Enable")) { + if ($vars->submitbutton == _("Save and Enable")) { $filters->ruleEnable($spam_id); - if (is_a($result = $ingo_storage->store($filters), 'PEAR_Error')) { - $notification->push($result); - $success = false; - } else { - $notification->push(_("Rule Enabled"), 'horde.success'); - $spam_rule['disable'] = false; - } - } elseif ($vars->get('submitbutton') == _("Save and Disable")) { + $ingo_storage->store($filters); + $notification->push(_("Rule Enabled"), 'horde.success'); + $spam_rule['disable'] = false; + } elseif ($vars->submitbutton == _("Save and Disable")) { $filters->ruleDisable($spam_id); - if (is_a($result = $ingo_storage->store($filters), 'PEAR_Error')) { - $notification->push($result); - $success = false; - } else { - $notification->push(_("Rule Disabled"), 'horde.success'); - $spam_rule['disable'] = true; - } + $ingo_storage->store($filters); + $notification->push(_("Rule Disabled"), 'horde.success'); + $spam_rule['disable'] = true; } + } catch (Ingo_Exception $e) { + $notification->push($result); + $success = false; } + if ($success && $prefs->getValue('auto_update')) { Ingo::updateScript(); } @@ -140,10 +134,10 @@ $form->appendButtons(_("Return to Rules List")); /* Set default values. */ $folder_var->type->setFolder($spam->getSpamFolder()); if (!$form->isSubmitted()) { - $vars->set('level', $spam->getSpamLevel()); - $vars->set('folder', $spam->getSpamFolder()); - $vars->set('actionID', ''); - $vars->set('new_folder_name', ''); + $vars->level = $spam->getSpamLevel(); + $vars->folder = $spam->getSpamFolder(); + $vars->actionID = ''; + $vars->new_folder_name = ''; } /* Set form title. */ diff --git a/ingo/templates/rule/filter.inc b/ingo/templates/rule/filter.inc index d4ef8bd42..77238b19b 100644 --- a/ingo/templates/rule/filter.inc +++ b/ingo/templates/rule/filter.inc @@ -13,7 +13,7 @@ - + diff --git a/ingo/templates/rule/header.inc b/ingo/templates/rule/header.inc index 24ce582b8..88f11e398 100644 --- a/ingo/templates/rule/header.inc +++ b/ingo/templates/rule/header.inc @@ -3,8 +3,8 @@ - - +edit)): ?> + diff --git a/ingo/vacation.php b/ingo/vacation.php index ed248edc8..6ffafda7c 100644 --- a/ingo/vacation.php +++ b/ingo/vacation.php @@ -21,14 +21,14 @@ if (!in_array(Ingo_Storage::ACTION_VACATION, $_SESSION['ingo']['script_categorie } /* Get vacation object and rules. */ -$vacation = &$ingo_storage->retrieve(Ingo_Storage::ACTION_VACATION); -$filters = &$ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); +$vacation = $ingo_storage->retrieve(Ingo_Storage::ACTION_VACATION); +$filters = $ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); $vac_id = $filters->findRuleId(Ingo_Storage::ACTION_VACATION); $vac_rule = $filters->getRule($vac_id); /* Load libraries. */ $vars = Horde_Variables::getDefaultVariables(); -if ($vars->get('submitbutton') == _("Return to Rules List")) { +if ($vars->submitbutton == _("Return to Rules List")) { header('Location: ' . Horde::applicationUrl('filters.php', true)); exit; } @@ -37,21 +37,21 @@ if ($vars->get('submitbutton') == _("Return to Rules List")) { $form = new Horde_Form($vars); $form->setSection('basic', _("Basic Settings")); -$v = &$form->addVariable(_("Start of vacation:"), 'start', 'monthdayyear', ''); +$v = $form->addVariable(_("Start of vacation:"), 'start', 'monthdayyear', ''); $v->setHelp('vacation-period'); $form->addVariable(_("End of vacation:"), 'end', 'monthdayyear', ''); -$v = &$form->addVariable(_("Subject of vacation message:"), 'subject', 'text', false); +$v = $form->addVariable(_("Subject of vacation message:"), 'subject', 'text', false); $v->setHelp('vacation-subject'); -$v = &$form->addVariable(_("Reason:"), 'reason', 'longtext', false, false, null, array(10, 40)); +$v = $form->addVariable(_("Reason:"), 'reason', 'longtext', false, false, null, array(10, 40)); $v->setHelp('vacation-reason'); $form->setSection('advanced', _("Advanced Settings")); -$v = &$form->addVariable(_("My email addresses:"), 'addresses', 'longtext', true, false, null, array(5, 40)); +$v = $form->addVariable(_("My email addresses:"), 'addresses', 'longtext', true, false, null, array(5, 40)); $v->setHelp('vacation-myemail'); -$v = &$form->addVariable(_("Addresses to not send responses to:"), 'excludes', 'longtext', false, false, null, array(10, 40)); +$v = $form->addVariable(_("Addresses to not send responses to:"), 'excludes', 'longtext', false, false, null, array(10, 40)); $v->setHelp('vacation-noresponse'); -$v = &$form->addVariable(_("Do not send responses to bulk or list messages?"), 'ignorelist', 'boolean', false); +$v = $form->addVariable(_("Do not send responses to bulk or list messages?"), 'ignorelist', 'boolean', false); $v->setHelp('vacation-bulk'); -$v = &$form->addVariable(_("Number of days between vacation replies:"), 'days', 'int', false); +$v = $form->addVariable(_("Number of days between vacation replies:"), 'days', 'int', false); $v->setHelp('vacation-days'); $form->setButtons(_("Save")); @@ -68,30 +68,23 @@ if ($form->validate($vars)) { $vacation->setVacationEnd($info['end']); $success = true; - if (is_a($result = $ingo_storage->store($vacation), 'PEAR_Error')) { - $notification->push($result); - $success = false; - } else { + try { + $ingo_storage->store($vacation); $notification->push(_("Changes saved."), 'horde.success'); - if ($vars->get('submitbutton') == _("Save and Enable")) { + if ($vars->submitbutton == _("Save and Enable")) { $filters->ruleEnable($vac_id); - if (is_a($result = $ingo_storage->store($filters), 'PEAR_Error')) { - $notification->push($result); - $success = false; - } else { - $notification->push(_("Rule Enabled"), 'horde.success'); - $vac_rule['disable'] = false; - } + $ingo_storage->store($filters); + $notification->push(_("Rule Enabled"), 'horde.success'); + $vac_rule['disable'] = false; } elseif ($vars->get('submitbutton') == _("Save and Disable")) { $filters->ruleDisable($vac_id); - if (is_a($result = $ingo_storage->store($filters), 'PEAR_Error')) { - $notification->push($result); - $success = false; - } else { - $notification->push(_("Rule Disabled"), 'horde.success'); - $vac_rule['disable'] = true; - } + $ingo_storage->store($filters); + $notification->push(_("Rule Disabled"), 'horde.success'); + $vac_rule['disable'] = true; } + } catch (Ingo_Exception $e) { + $notification->push($result); + $success = false; } if ($success && $prefs->getValue('auto_update')) { diff --git a/ingo/whitelist.php b/ingo/whitelist.php index 17d094035..8169f3e4b 100644 --- a/ingo/whitelist.php +++ b/ingo/whitelist.php @@ -22,16 +22,13 @@ if (!in_array(Ingo_Storage::ACTION_WHITELIST, $_SESSION['ingo']['script_categori exit; } -$whitelist = &$ingo_storage->retrieve(Ingo_Storage::ACTION_WHITELIST); +$whitelist = $ingo_storage->retrieve(Ingo_Storage::ACTION_WHITELIST); /* Perform requested actions. */ -$actionID = Horde_Util::getFormData('actionID'); -switch ($actionID) { +switch (Horde_Util::getFormData('actionID')) { case 'rule_update': - $ret = $whitelist->setWhitelist(Horde_Util::getFormData('whitelist')); - if (is_a($ret, 'PEAR_Error')) { - $notification->push($ret, $ret->getCode()); - } else { + try { + $whitelist->setWhitelist(Horde_Util::getFormData('whitelist')); if (!$ingo_storage->store($whitelist)) { $notification->push("Error saving changes.", 'horde.error'); } else { @@ -45,13 +42,14 @@ case 'rule_update': /* Update the timestamp for the rules. */ $_SESSION['ingo']['change'] = time(); + } catch (Ingo_Exception $e) { + $notification->push($e); } - break; } /* Get the whitelist rule. */ -$filters = &$ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); +$filters = $ingo_storage->retrieve(Ingo_Storage::ACTION_FILTERS); $wl_rule = $filters->findRule(Ingo_Storage::ACTION_WHITELIST); $title = _("Whitelist Edit");