From: Gunnar Wrobel Date: Thu, 15 Jul 2010 20:26:41 +0000 (+0200) Subject: Rewrote the basic filter definition. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=2b3e6238214798f8aacaddfeced9459631e1b80a;p=horde.git Rewrote the basic filter definition. --- diff --git a/framework/Kolab_Filter/lib/Horde/Kolab/Filter.php b/framework/Kolab_Filter/lib/Horde/Kolab/Filter.php new file mode 100644 index 000000000..674ce72ee --- /dev/null +++ b/framework/Kolab_Filter/lib/Horde/Kolab/Filter.php @@ -0,0 +1,66 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ + +/** Setup default autoloading */ +require_once 'Horde/Autoloader/Default.php'; + +/** + * The main entry point for the Kolab_Filter application. + * + * Copyright 2010 Klarälvdalens Datakonsult AB + * + * See the enclosed file COPYING for license information (LGPL). If you did not + * receive this file, see + * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + * + * @category Kolab + * @package Kolab_Filter + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ +class Horde_Kolab_Filter +{ + public function __construct(Horde_Injector $injector = null) + { + if ($injector === null) { + $this->injector = new Horde_Injector(new Horde_Injector_TopLevel()); + + $this->injector->bindFactory( + 'Horde_Log_Logger', 'Horde_Kolab_Filter_Factory', 'getLogger' + ); + $this->injector->bindImplementation( + 'Horde_Kolab_Filter_Temporary', 'Horde_Kolab_Filter_Temporary_File' + ); + } else { + $this->injector = $injector; + } + } + + /** + * Run the mail filter. + * + * @param string $type The type of filtering to run (Incoming|Content). + */ + public function main($type, $inh = STDIN, $transport = null) + { + /** Setup all configuration information */ + /* $configuration = $this->injector->getInstance('Horde_Kolab_Filter_Configuration'); */ + /* $configuration->init(); */ + + /** Now run the filter */ + $filter = $this->injector->getInstance('Horde_Kolab_Filter_' . $type); + $filter->init(); + $filter->parse($inh, $transport); + } +} \ No newline at end of file diff --git a/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Base.php b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Base.php index d7240f2fa..2f8930306 100644 --- a/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Base.php +++ b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Base.php @@ -25,92 +25,42 @@ class Horde_Kolab_Filter_Base var $_id = ''; /** - * A temporary buffer file for storing the message. + * Configuration. * - * @var string - */ - var $_tmpfile; - - /** - * The file handle for the temporary file. - * - * @var int - */ - var $_tmpfh; - - /** - * The message sender. - * - * @var string - */ - var $_sender; - - /** - * The message recipients. - * - * @var array + * @param Horde_Kolab_Filter_Configuration */ - var $_recipients = array(); - - /** - * The client host trying to send the message. - * - * @var string - */ - var $_client_address; - - /** - * The client host trying to send the message. - * - * @var string - */ - var $_fqhostname; - - /** - * The authenticated username of the sender. - * - * @var string - */ - var $_sasl_username; - - /** - * Comman line parser. - * - * @param Horde_Kolab_Filter_Cli - */ - private $_cli; + private $_config; /** * The log backend that needs to implement the debug(), info() and err() * methods. * - * @param mixed + * @param Horde_Kolab_Filter_Logger */ - private $_logger; + protected $_logger; /** * Constructor. * - * @param mixed $logger The logger. + * @param Horde_Kolab_Filter_Configuration $config The configuration. + * @param Horde_Kolab_Filter_Logger $logger The logging backend. */ public function __construct( - Horde_Kolab_Filter_Cli $cli, - $logger + Horde_Kolab_Filter_Configuration $config, + Horde_Log_Logger $logger ) { - $this->_cli = $cli; - $this->_logger = $logger; + $this->_config = $config; + $this->_logger = $logger; } /** - * Initialize the class. + * Initialize the filter. + * + * @return NULL */ - function init() + public function init() { - /* Parse our arguments */ - $result = $this->_parseArgs(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_config->init(); } /** @@ -118,147 +68,40 @@ class Horde_Kolab_Filter_Base * * @param int $inh The file handle pointing to the message. * @param string $transport The name of the transport driver. + * + * @return NULL */ - function parse($inh = STDIN, $transport = null) + public function parse($inh = STDIN, $transport = null) { - /* Setup the temporary storage */ - $result = $this->_initTmp(); - if ($result instanceOf PEAR_Error) { - return $result; - } + /* $this->_logger->debug( */ + /* sprintf( */ + /* "Arguments: %s", */ + /* print_r($this->_config->getArguments(), true) */ + /* ) */ + /* ); */ $this->_logger->debug( sprintf( "%s starting up (sender=%s, recipients=%s, client_address=%s)", get_class($this), - $this->_sender, - join(', ',$this->_recipients), - $this->_client_address + $this->_config->getSender(), + join(', ',$this->_config->getRecipients()), + $this->_config->getClientAddress() ) ); - $result = $this->_parse($inh, $transport); - if (is_a($result, 'PEAR_Error')) { - return $result; - } + $this->_parse($inh, $transport); - Horde::logMessage(sprintf("%s successfully completed (sender=%s, recipients=%s, client_address=%s, id=%s)", - get_class($this), $this->_sender, - join(', ',$this->_recipients), - $this->_client_address, $this->_id), - 'INFO'); - } - - /** - * Creates a buffer for temporary storage of the message. - * - * @return mixed A PEAR_Error in case of an error, nothing otherwise. - */ - function _initTmp() - { - global $conf; - - if (isset($conf['kolab']['filter']['tempdir'])) { - $tmpdir = $conf['kolab']['filter']['tempdir']; - } else { - $tmpdir = Horde::getTempDir(); - } - - /* Temp file for storing the message */ - $this->_tmpfile = @tempnam($tmpdir, 'IN.' . get_class($this) . '.'); - $this->_tmpfh = @fopen($this->_tmpfile, "w"); - if( !$this->_tmpfh ) { - $msg = $php_errormsg; - return PEAR::raiseError(sprintf("Error: Could not open %s for writing: %s", - $this->_tmpfile, $msg), - OUT_LOG | EX_IOERR); - } - - register_shutdown_function(array($this, '_cleanupTmp')); - } - - /** - * A shutdown function for removing the temporary file. - */ - function _cleanupTmp() { - if (@file_exists($this->_tmpfile)) { - @unlink($this->_tmpfile); - } - } - - /** - * Parse the command line arguments provided to the filter and - * setup the class. - * - * @return mixed A PEAR_Error in case of an error, nothing otherwise. - */ - function _parseArgs() - { - global $conf; - - $values = $this->_cli->getOptions(); - - if (!empty($values['config']) && file_exists($values['config'])) { - require_once $values['config']; - } - - $this->_sender = strtolower($values['sender']); - $this->_recipients = array_map('strtolower', $values['recipient']); - $this->_client_address = $values['client']; - $this->_fqhostname = strtolower($values['host']); - $this->_sasl_username = strtolower($values['user']); - - Horde::logMessage(sprintf("Arguments: %s", print_r($values, true)), 'DEBUG'); - - $GLOBALS['registry']->setCharset('utf-8'); - - if (!empty($conf['kolab']['filter']['locale_path']) - && !empty($conf['kolab']['filter']['locale'])) { - $GLOBALS['registry']->setTextdomain('Kolab_Filter', $conf['kolab']['filter']['locale_path']); - setlocale(LC_ALL, $conf['kolab']['filter']['locale']); - } - - /* This is used as the default domain for unqualified adresses */ - global $_SERVER; - if (!array_key_exists('SERVER_NAME', $_SERVER)) { - $_SERVER['SERVER_NAME'] = $conf['kolab']['imap']['server']; - } - - if (!array_key_exists('REMOTE_ADDR', $_SERVER)) { - $_SERVER['REMOTE_ADDR'] = $conf['kolab']['imap']['server']; - } - - if (!array_key_exists('REMOTE_HOST', $_SERVER)) { - $_SERVER['REMOTE_HOST'] = $conf['kolab']['imap']['server']; - } - - /* Always display all possible problems */ - ini_set('error_reporting', E_ALL); - ini_set('track_errors', '1'); - - /* Setup error logging */ - if (isset($conf['kolab']['filter']['error_log'])) { - ini_set('log_errors', '1'); - ini_set('error_log', $conf['kolab']['filter']['error_log']); - } - - /* Print PHP messages to StdOut if we are debugging */ - if (isset($conf['kolab']['filter']['debug']) - && $conf['kolab']['filter']['debug']) { - ini_set('display_errors', '1'); - } - - /* Provide basic syslog debugging if nothing has been - * specified - */ - if (!isset($conf['log'])) { - $conf['log']['enabled'] = true; - $conf['log']['priority'] = 'DEBUG'; - $conf['log']['type'] = 'syslog'; - $conf['log']['name'] = LOG_MAIL; - $conf['log']['ident'] = 'kolabfilter'; - $conf['log']['params'] = array(); - } + $this->_logger->info( + sprintf( + "%s successfully completed (sender=%s, recipients=%s, client_address=%s, id=%s)", + get_class($this), + $this->_config->getSender(), + join(', ',$this->_config->getRecipients()), + $this->_config->getClientAddress(), + $this->_id + ) + ); } } diff --git a/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Configuration.php b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Configuration.php new file mode 100644 index 000000000..1b812e88e --- /dev/null +++ b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Configuration.php @@ -0,0 +1,193 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ + +/** + * The configuration of the Kolab_Filter package. + * + * Copyright 2008 Klarälvdalens Datakonsult AB + * + * See the enclosed file COPYING for license information (LGPL). If you did not + * receive this file, see + * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + * + * @category Kolab + * @package Kolab_Filter + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ +class Horde_Kolab_Filter_Configuration +{ + /** + * The message sender. + * + * @var string + */ + private $_sender; + + /** + * The message recipients. + * + * @var array + */ + private $_recipients = array(); + + /** + * The client host trying to send the message. + * + * @var string + */ + private $_client_address; + + /** + * The client host trying to send the message. + * + * @var string + */ + private $_fqhostname; + + /** + * The authenticated username of the sender. + * + * @var string + */ + private $_sasl_username; + + /** + * The parameters from the configuration file. + * + * @var array + */ + private $_conf; + + /** + * Command line parser. + * + * @param Horde_Kolab_Filter_Cli + */ + private $_cli; + + /** + * Constructor. + * + * @param Horde_Kolab_Filter_Cli $cli The CLI parser. + */ + public function __construct( + Horde_Kolab_Filter_Cli $cli + ) { + $this->_cli = $cli; + } + + /** + * Initialize the configuration. + * + * @return NULL + */ + public function init() + { + $values = $this->_cli->getOptions(); + + $this->_sender = strtolower($values['sender']); + $this->_recipients = array_map('strtolower', $values['recipient']); + $this->_client_address = $values['client']; + $this->_fqhostname = strtolower($values['host']); + $this->_sasl_username = strtolower($values['user']); + + global $conf; + + if (!empty($values['config']) && file_exists($values['config'])) { + require_once $values['config']; + } + + Horde_Nls::setCharset('utf-8'); + + if (!empty($conf['kolab']['filter']['locale_path']) + && !empty($conf['kolab']['filter']['locale'])) { + Horde_Nls::setTextdomain('Kolab_Filter', $conf['kolab']['filter']['locale_path'], Horde_Nls::getCharset()); + setlocale(LC_ALL, $conf['kolab']['filter']['locale']); + } + + /* This is used as the default domain for unqualified adresses */ + if (!array_key_exists('SERVER_NAME', $_SERVER)) { + $_SERVER['SERVER_NAME'] = $conf['kolab']['imap']['server']; + } + + if (!array_key_exists('REMOTE_ADDR', $_SERVER)) { + $_SERVER['REMOTE_ADDR'] = $conf['kolab']['imap']['server']; + } + + if (!array_key_exists('REMOTE_HOST', $_SERVER)) { + $_SERVER['REMOTE_HOST'] = $conf['kolab']['imap']['server']; + } + + /* Always display all possible problems */ + ini_set('error_reporting', E_ALL); + ini_set('track_errors', '1'); + + /* Setup error logging */ + if (isset($conf['kolab']['filter']['error_log'])) { + ini_set('log_errors', '1'); + ini_set('error_log', $conf['kolab']['filter']['error_log']); + } + + /* Print PHP messages to StdOut if we are debugging */ + if (isset($conf['kolab']['filter']['debug']) + && $conf['kolab']['filter']['debug']) { + ini_set('display_errors', '1'); + } + + /* Provide basic syslog debugging if nothing has been + * specified + */ + if (!isset($conf['log'])) { + $conf['log']['enabled'] = true; + $conf['log']['priority'] = 'DEBUG'; + $conf['log']['type'] = 'syslog'; + $conf['log']['name'] = LOG_MAIL; + $conf['log']['ident'] = 'kolabfilter'; + $conf['log']['params'] = array(); + } + + $this->_conf = $conf; + } + + public function getSender() + { + return $this->_sender; + } + + public function getRecipients() + { + return $this->_recipients; + } + + public function getClientAddress() + { + return $this->_client_address; + } + + public function getFqHostname() + { + return $this->_fqhostname; + } + + public function getSaslUsername() + { + return $this->_sasl_username; + } + + public function getConf() + { + return $this->_conf; + } +} \ No newline at end of file diff --git a/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Exception/IoError.php b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Exception/IoError.php new file mode 100644 index 000000000..156e5dc8d --- /dev/null +++ b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Exception/IoError.php @@ -0,0 +1,46 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ + +/** + * This class provides an error thrown when an I/O error occured. + * + * Copyright 2010 Klarälvdalens Datakonsult AB + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Kolab + * @package Kolab_Filter + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ +class Horde_Kolab_Filter_Exception_IoError +extends Horde_Kolab_Filter_Exception +{ + /** + * Construct the exception + * + * @param string $msg + * @param Exception $previous + */ + public function __construct($msg = '', Exception $previous = null) + { + parent::__construct( + $msg, + Horde_Kolab_Filter_Exception::OUT_LOG | + Horde_Kolab_Filter_Exception::EX_IOERR, + $previous + ); + } +} diff --git a/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Factory.php b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Factory.php new file mode 100644 index 000000000..01cd29b85 --- /dev/null +++ b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Factory.php @@ -0,0 +1,98 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ + +/** + * A factory for Kolab_Filter objects. + * + * Copyright 2010 Klarälvdalens Datakonsult AB + * + * See the enclosed file COPYING for license information (LGPL). If you did not + * receive this file, see + * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + * + * @category Kolab + * @package Kolab_Filter + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ +class Horde_Kolab_Filter_Factory +{ + /** + * Creates the logger. + * + * @param Horde_Injector $injector The injector provides the required + * configuration. + * + * @return Horde_Log_Logger The logger. + */ + public function getLogger(Horde_Injector $injector) + { + $configuration = $injector->getInstance('Horde_Kolab_Filter_Configuration'); + + $conf = $configuration->getConf(); + switch ($conf['log']['type']) { + case 'file': + case 'stream': + $append = ($conf['log']['type'] == 'file') + ? ($conf['log']['params']['append'] ? 'a+' : 'w+') + : null; + $format = isset($conf['log']['params']['format']) + ? $conf['log']['params']['format'] + : 'default'; + + switch ($format) { + case 'custom': + $formatter = new Horde_Log_Formatter_Xml(array('format' => $conf['log']['params']['template'])); + break; + + case 'default': + default: + // Use Horde_Log defaults. + $formatter = null; + break; + + case 'xml': + $formatter = new Horde_Log_Formatter_Xml(); + break; + } + + try { + $handler = new Horde_Log_Handler_Stream($conf['log']['name'], $append, $formatter); + } catch (Horde_Log_Exception $e) { + return new Horde_Log_Logger(new Horde_Log_Handler_Null()); + } + break; + case 'syslog': + try { + $handler = new Horde_Log_Handler_Syslog(); + } catch (Horde_Log_Exception $e) { + return new Horde_Log_Logger(new Horde_Log_Handler_Null()); + } + break; + case 'mock': + $handler = new Horde_Log_Handler_Mock(); + break; + case 'null': + default: + // Use default null handler. + return new Horde_Log_Logger(new Horde_Log_Handler_Null()); + break; + } + if (!defined('Horde_Log::' . $conf['log']['priority'])) { + $conf['log']['priority'] = 'NOTICE'; + } + $handler->addFilter(constant('Horde_Log::' . $conf['log']['priority'])); + return new Horde_Log_Logger($handler); + } +} \ No newline at end of file diff --git a/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Incoming.php b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Incoming.php index 544133e05..279e3069b 100644 --- a/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Incoming.php +++ b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Incoming.php @@ -24,6 +24,12 @@ require_once dirname(__FILE__) . '/Transport.php'; */ class Horde_Kolab_Filter_Incoming extends Horde_Kolab_Filter_Base { + /** + * A temporary storage place for incoming messages. + * + * @param Horde_Kolab_Filter_Temporary + */ + private $_temporary; /** * An array of headers to be added to the message @@ -33,6 +39,34 @@ class Horde_Kolab_Filter_Incoming extends Horde_Kolab_Filter_Base var $_add_headers; /** + * Constructor. + * + * @param Horde_Kolab_Filter_Configuration $config The configuration. + * @param Horde_Kolab_Filter_Temporary $temporaray Temporary storage + * location. + * @param Horde_Kolab_Filter_Logger $logger The logging backend. + */ + public function __construct( + Horde_Kolab_Filter_Configuration $config, + Horde_Kolab_Filter_Temporary $temporary, + Horde_Log_Logger $logger + ) { + parent::__construct($config, $logger); + $this->_temporary = $temporary; + } + + /** + * Initialize the filter. + * + * @return NULL + */ + public function init() + { + parent::init(); + $this->_temporary->init(); + } + + /** * Handle the message. * * @param int $inh The file handle pointing to the message. @@ -44,11 +78,6 @@ class Horde_Kolab_Filter_Incoming extends Horde_Kolab_Filter_Base { global $conf; - $result = $this->init(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - if (empty($transport)) { if (isset($conf['kolab']['filter']['delivery_backend'])) { $transport = $conf['kolab']['filter']['delivery_backend']; @@ -57,6 +86,8 @@ class Horde_Kolab_Filter_Incoming extends Horde_Kolab_Filter_Base } } + $this->_tmpfh = $this->_temporary->getHandle(); + $ical = false; $add_headers = array(); $headers_done = false; @@ -161,7 +192,7 @@ class Horde_Kolab_Filter_Incoming extends Horde_Kolab_Filter_Base /* Check if we still have recipients */ if (empty($this->_recipients)) { - Horde::logMessage("No recipients left.", 'DEBUG'); + $this->_logger->debug("No recipients left.", 'DEBUG'); return; } else { $result = $this->_deliver($transport); @@ -170,7 +201,7 @@ class Horde_Kolab_Filter_Incoming extends Horde_Kolab_Filter_Base } } - Horde::logMessage("Filter_Incoming successfully completed.", 'DEBUG'); + $this->_logger->debug("Filter_Incoming successfully completed.", 'DEBUG'); } private function _transportItipReply(Horde_Kolab_Resource_Reply $reply) @@ -287,7 +318,7 @@ class Horde_Kolab_Filter_Incoming extends Horde_Kolab_Filter_Base } $transport = &Horde_Kolab_Filter_Transport::factory($transport, $params); - $tmpf = @fopen($this->_tmpfile, 'r'); + $tmpf = $this->_temporary->getReadHandle(); if (!$tmpf) { $msg = $php_errormsg; return PEAR::raiseError(sprintf("Error: Could not open %s for writing: %s", diff --git a/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Temporary.php b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Temporary.php new file mode 100644 index 000000000..87c9ab86a --- /dev/null +++ b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Temporary.php @@ -0,0 +1,31 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ + +/** + * Definition of a temporary storage place for incoming messages. + * + * Copyright 2010 Klarälvdalens Datakonsult AB + * + * See the enclosed file COPYING for license information (LGPL). If you did not + * receive this file, see + * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + * + * @category Kolab + * @package Kolab_Filter + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ +interface Horde_Kolab_Filter_Temporary +{ +} \ No newline at end of file diff --git a/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Temporary/File.php b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Temporary/File.php new file mode 100644 index 000000000..fc203e45e --- /dev/null +++ b/framework/Kolab_Filter/lib/Horde/Kolab/Filter/Temporary/File.php @@ -0,0 +1,126 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ + +/** + * File based temporary storage place for incoming messages. + * + * Copyright 2004-2010 Klarälvdalens Datakonsult AB + * + * See the enclosed file COPYING for license information (LGPL). If you did not + * receive this file, see + * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + * + * @category Kolab + * @package Kolab_Filter + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ +class Horde_Kolab_Filter_Temporary_File +implements Horde_Kolab_Filter_Temporary +{ + /** + * A temporary buffer file for storing the message. + * + * @var string + */ + var $_tmpfile; + + /** + * The file handle for the temporary file. + * + * @var int + */ + var $_tmpfh; + + /** + * Configuration. + * + * @param Horde_Kolab_Filter_Configuration + */ + private $_config; + + /** + * Constructor. + * + * @param Horde_Kolab_Filter_Configuration $config The configuration. + */ + public function __construct( + Horde_Kolab_Filter_Configuration $config + ) { + $this->_config = $config; + } + + + /** + * Creates a buffer for temporary storage of the message. + * + * @return NULL + */ + public function init() + { + $conf = $this->_config->getConf(); + + if (isset($conf['kolab']['filter']['tempdir'])) { + $tmpdir = $conf['kolab']['filter']['tempdir']; + } else { + $tmpdir = Horde_Util::getTempDir(); + } + + $this->_tmpfile = @tempnam($tmpdir, 'IN.' . get_class($this) . '.'); + $this->_tmpfh = @fopen($this->_tmpfile, 'w'); + if (!$this->_tmpfh) { + throw new Horde_Kolab_Filter_Exception_IoError( + sprintf( + "Error: Could not open %s for writing: %s", + $this->_tmpfile, + $php_errormsg + ) + ); + } + + register_shutdown_function(array($this, 'cleanup')); + } + + /** + * Return the file handle for writing data. + * + * @return resource The file handle. + */ + public function getHandle() + { + return $this->_tmpfh; + } + + /** + * Return the file handle for reading data. + * + * @return resource The file handle. + */ + public function getReadHandle() + { + return @fopen($this->_tmpfile, 'r');; + } + + /** + * A shutdown function for removing the temporary file. + * + * @return NULL + */ + public function cleanup() + { + if (@file_exists($this->_tmpfile)) { + @unlink($this->_tmpfile); + } + } +} \ No newline at end of file diff --git a/framework/Kolab_Filter/package.xml b/framework/Kolab_Filter/package.xml index 1d192a01e..00fe5aa54 100644 --- a/framework/Kolab_Filter/package.xml +++ b/framework/Kolab_Filter/package.xml @@ -65,6 +65,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + @@ -78,15 +79,22 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + + + + + @@ -253,15 +261,20 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + + + diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/AllTests.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/AllTests.php index 66b842c36..0b4246d4e 100644 --- a/framework/Kolab_Filter/test/Horde/Kolab/Filter/AllTests.php +++ b/framework/Kolab_Filter/test/Horde/Kolab/Filter/AllTests.php @@ -1,22 +1,22 @@ * @license http://www.fsf.org/copyleft/lgpl.html LGPL - * @link http://pear.horde.org/index.php?package=Kolab_Storage + * @link http://pear.horde.org/index.php?package=Kolab_Filter */ /** * Define the main method */ if (!defined('PHPUnit_MAIN_METHOD')) { - define('PHPUnit_MAIN_METHOD', 'Horde_Kolab_Storage_AllTests::main'); + define('PHPUnit_MAIN_METHOD', 'Horde_Kolab_Filter_AllTests::main'); } /** @@ -25,10 +25,10 @@ if (!defined('PHPUnit_MAIN_METHOD')) { require_once 'Horde/Test/AllTests.php'; /** - * @package Horde_Kolab_Storage + * @package Horde_Kolab_Filter * @subpackage UnitTests */ -class Horde_Kolab_Storage_AllTests extends Horde_Test_AllTests +class Horde_Kolab_Filter_AllTests extends Horde_Test_AllTests { /** * Main entry point for running the suite. @@ -63,15 +63,15 @@ class Horde_Kolab_Storage_AllTests extends Horde_Test_AllTests */ public static function detectTestFixture(PHPUnit_Framework_TestSuite $suite) { - $config = getenv('KOLAB_STORAGE_TEST_CONFIG'); + $config = getenv('KOLAB_FILTER_TEST_CONFIG'); if ($config === false) { $config = dirname(__FILE__) . '/conf.php'; } if (file_exists($config)) { require $config; - if (isset($conf['kolab']['storage']['test'])) { + if (isset($conf['kolab']['filter']['test'])) { $fixture = new stdClass; - $fixture->conf = $conf['kolab']['storage']['test']; + $fixture->conf = $conf['kolab']['filter']['test']; $fixture->drivers = array(); $suite->setSharedFixture($fixture); } @@ -80,8 +80,8 @@ class Horde_Kolab_Storage_AllTests extends Horde_Test_AllTests } } -Horde_Kolab_Storage_AllTests::init('Horde_Kolab_Storage', __FILE__); +Horde_Kolab_Filter_AllTests::init('Horde_Kolab_Filter', __FILE__); -if (PHPUnit_MAIN_METHOD == 'Horde_Kolab_Storage_AllTests::main') { - Horde_Kolab_Storage_AllTests::main(); +if (PHPUnit_MAIN_METHOD == 'Horde_Kolab_Filter_AllTests::main') { + Horde_Kolab_Filter_AllTests::main(); } diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/Autoload.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/Autoload.php index d92650cea..fe49a4fb5 100644 --- a/framework/Kolab_Filter/test/Horde/Kolab/Filter/Autoload.php +++ b/framework/Kolab_Filter/test/Horde/Kolab/Filter/Autoload.php @@ -36,3 +36,6 @@ error_reporting(E_ALL | E_STRICT); /** Load the basic test definition */ require_once dirname(__FILE__) . '/StoryTestCase.php'; + +/** Load the test helpers */ +require_once dirname(__FILE__) . '/Helper/AddressFilter.php'; diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/ContentTest.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/ContentTest.php deleted file mode 100644 index 1b1b07682..000000000 --- a/framework/Kolab_Filter/test/Horde/Kolab/Filter/ContentTest.php +++ /dev/null @@ -1,199 +0,0 @@ - - * @package Horde_Kolab_Filter - */ -class Horde_Kolab_Filter_ContentTest extends Horde_Kolab_Test_Filter -{ - - /** - * Set up testing. - */ - protected function setUp() - { - $result = $this->prepareBasicSetup(); - - $this->server = &$result['server']; - $this->storage = &$result['storage']; - $this->auth = &$result['auth']; - - global $conf; - - $conf['kolab']['imap']['server'] = 'localhost'; - $conf['kolab']['imap']['port'] = 0; - $conf['kolab']['imap']['allow_special_users'] = true; - $conf['kolab']['filter']['reject_forged_from_header'] = false; - $conf['kolab']['filter']['email_domain'] = 'example.org'; - $conf['kolab']['filter']['privileged_networks'] = '127.0.0.1,192.168.0.0/16'; - $conf['kolab']['filter']['verify_from_header'] = true; - $conf['kolab']['filter']['calendar_id'] = 'calendar'; - $conf['kolab']['filter']['calendar_pass'] = 'calendar'; - $conf['kolab']['filter']['lmtp_host'] = 'imap.example.org'; - $conf['kolab']['filter']['simple_locks'] = true; - $conf['kolab']['filter']['simple_locks_timeout'] = 3; - - $result = $this->auth->authenticate('wrobel', array('password' => 'none')); - $this->assertNoError($result); - - $folder = $this->storage->getNewFolder(); - $folder->setName('Kalender'); - $result = $folder->save(array('type' => 'event', - 'default' => true)); - $this->assertNoError($result); - } - - /** - * Test sending messages through the content filter. - * - * @dataProvider addressCombinations - */ - public function testContentHandler($infile, $outfile, $user, $client, $from, - $to, $host, $params = array()) - { - $this->sendFixture($infile, $outfile, $user, $client, $from, $to, - $host, $params); - } - - /** - * Provides various test situations for the Kolab content filter. - */ - public function addressCombinations() - { - return array( - /** - * Test a simple message - */ - array(dirname(__FILE__) . '/fixtures/vacation.eml', - dirname(__FILE__) . '/fixtures/vacation.ret', - '', '', 'me@example.org', 'you@example.net', 'example.org', - array('unmodified_content' => true)), - /** - * Test a simple message - */ - array(dirname(__FILE__) . '/fixtures/tiny.eml', - dirname(__FILE__) . '/fixtures/tiny.ret', - '', '', 'me@example.org', 'you@example.org', 'example.org', - array('unmodified_content' => true)), - /** - * Test a simple message - */ - array(dirname(__FILE__) . '/fixtures/simple.eml', - dirname(__FILE__) . '/fixtures/simple_out.ret', - '', '', 'me@example.org', 'you@example.org', 'example.org', - array('unmodified_content' => true)), - /** - * Test sending from a remote server without authenticating. This - * will be considered forging the sender. - */ - /* array(dirname(__FILE__) . '/fixtures/forged.eml', - dirname(__FILE__) . '/fixtures/forged.ret', - '', '10.0.0.1', 'me@example.org', 'you@example.org', 'example.org', - array('unmodified_content' => true)),*/ - /** - * Test sending from a remote server without authenticating but - * within the priviledged network. This will not be considered - * forging the sender. - */ - array(dirname(__FILE__) . '/fixtures/forged.eml', - dirname(__FILE__) . '/fixtures/privileged.ret', - '', '192.168.178.1', 'me@example.org', 'you@example.org', 'example.org', - array('unmodified_content' => true)), - /** - * Test authenticated sending of a message from a remote client. - */ - array(dirname(__FILE__) . '/fixtures/validation.eml', - dirname(__FILE__) . '/fixtures/validation.ret', - 'me@example.org', 'remote.example.org', 'me@example.org', 'you@example.org', 'example.org'), - /** - * Test authenticated sending of a message from a remote client - * using an alias. - */ - array(dirname(__FILE__) . '/fixtures/validation.eml', - dirname(__FILE__) . '/fixtures/validation.ret', - 'me@example.org', 'remote.example.org', 'me.me@example.org', 'you@example.org', 'example.org'), - /** - * Test authenticated sending of a message from a remote client - * using an alias with capitals (MEME@example.org). - */ - array(dirname(__FILE__) . '/fixtures/validation.eml', - dirname(__FILE__) . '/fixtures/validation.ret', - 'me@example.org', 'remote.example.org', 'meme@example.org', 'you@example.org', 'example.org'), - /** - * Test authenticated sending of a message from a remote client - * as delegate - */ - array(dirname(__FILE__) . '/fixtures/validation.eml', - dirname(__FILE__) . '/fixtures/validation.ret', - 'me@example.org', 'remote.example.org', 'else@example.org', 'you@example.org', 'example.org'), - /** - * Test authenticated sending of a message from a remote client - * with an address that is not allowed. - */ - array(dirname(__FILE__) . '/fixtures/validation.eml', - dirname(__FILE__) . '/fixtures/validation.ret', - 'me@example.org', 'remote.example.org', 'else3@example.org', 'you@example.org', 'example.org', - array('error' =>'Invalid From: header. else3@example.org looks like a forged sender')), - /** - * Test forwarding an invitation - */ - array(dirname(__FILE__) . '/fixtures/invitation_forward.eml', - dirname(__FILE__) . '/fixtures/invitation_forward.ret', - 'me@example.org', '10.0.2.1', 'me@example.org', 'you@example.org', 'example.org'), - ); - } - - /** - * Test rejecting a forged from header. - */ - public function testRejectingForgedFromHeader() - { - global $conf; - - $conf['kolab']['filter']['reject_forged_from_header'] = true; - - $this->sendFixture(dirname(__FILE__) . '/fixtures/forged.eml', - dirname(__FILE__) . '/fixtures/forged.ret', - '', '10.0.0.1', 'me@example.org', 'you@example.org', 'example.org', - array('error' =>'Invalid From: header. me@example.org looks like a forged sender', - 'unmodified_content' => true)); - } - - /** - * Test translated forged from headers. - */ - public function testTranslatedForgedFromHeader() - { - $this->markTestIncomplete('Some the translation does not kick in.'); - global $conf; - - $conf['kolab']['filter']['locale_path'] = dirname(__FILE__) . '/../../../../../data/Kolab_Filter/locale'; - $conf['kolab']['filter']['locale'] = 'de_DE'; - - $this->sendFixture(dirname(__FILE__) . '/fixtures/forged.eml', - dirname(__FILE__) . '/fixtures/forged_trans.ret', - '', '10.0.0.1', 'me@example.org', 'you@example.org', 'example.org', - array('unmodified_content' => true)); - } - -} diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/ContentTestOld.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/ContentTestOld.php new file mode 100644 index 000000000..1b1b07682 --- /dev/null +++ b/framework/Kolab_Filter/test/Horde/Kolab/Filter/ContentTestOld.php @@ -0,0 +1,199 @@ + + * @package Horde_Kolab_Filter + */ +class Horde_Kolab_Filter_ContentTest extends Horde_Kolab_Test_Filter +{ + + /** + * Set up testing. + */ + protected function setUp() + { + $result = $this->prepareBasicSetup(); + + $this->server = &$result['server']; + $this->storage = &$result['storage']; + $this->auth = &$result['auth']; + + global $conf; + + $conf['kolab']['imap']['server'] = 'localhost'; + $conf['kolab']['imap']['port'] = 0; + $conf['kolab']['imap']['allow_special_users'] = true; + $conf['kolab']['filter']['reject_forged_from_header'] = false; + $conf['kolab']['filter']['email_domain'] = 'example.org'; + $conf['kolab']['filter']['privileged_networks'] = '127.0.0.1,192.168.0.0/16'; + $conf['kolab']['filter']['verify_from_header'] = true; + $conf['kolab']['filter']['calendar_id'] = 'calendar'; + $conf['kolab']['filter']['calendar_pass'] = 'calendar'; + $conf['kolab']['filter']['lmtp_host'] = 'imap.example.org'; + $conf['kolab']['filter']['simple_locks'] = true; + $conf['kolab']['filter']['simple_locks_timeout'] = 3; + + $result = $this->auth->authenticate('wrobel', array('password' => 'none')); + $this->assertNoError($result); + + $folder = $this->storage->getNewFolder(); + $folder->setName('Kalender'); + $result = $folder->save(array('type' => 'event', + 'default' => true)); + $this->assertNoError($result); + } + + /** + * Test sending messages through the content filter. + * + * @dataProvider addressCombinations + */ + public function testContentHandler($infile, $outfile, $user, $client, $from, + $to, $host, $params = array()) + { + $this->sendFixture($infile, $outfile, $user, $client, $from, $to, + $host, $params); + } + + /** + * Provides various test situations for the Kolab content filter. + */ + public function addressCombinations() + { + return array( + /** + * Test a simple message + */ + array(dirname(__FILE__) . '/fixtures/vacation.eml', + dirname(__FILE__) . '/fixtures/vacation.ret', + '', '', 'me@example.org', 'you@example.net', 'example.org', + array('unmodified_content' => true)), + /** + * Test a simple message + */ + array(dirname(__FILE__) . '/fixtures/tiny.eml', + dirname(__FILE__) . '/fixtures/tiny.ret', + '', '', 'me@example.org', 'you@example.org', 'example.org', + array('unmodified_content' => true)), + /** + * Test a simple message + */ + array(dirname(__FILE__) . '/fixtures/simple.eml', + dirname(__FILE__) . '/fixtures/simple_out.ret', + '', '', 'me@example.org', 'you@example.org', 'example.org', + array('unmodified_content' => true)), + /** + * Test sending from a remote server without authenticating. This + * will be considered forging the sender. + */ + /* array(dirname(__FILE__) . '/fixtures/forged.eml', + dirname(__FILE__) . '/fixtures/forged.ret', + '', '10.0.0.1', 'me@example.org', 'you@example.org', 'example.org', + array('unmodified_content' => true)),*/ + /** + * Test sending from a remote server without authenticating but + * within the priviledged network. This will not be considered + * forging the sender. + */ + array(dirname(__FILE__) . '/fixtures/forged.eml', + dirname(__FILE__) . '/fixtures/privileged.ret', + '', '192.168.178.1', 'me@example.org', 'you@example.org', 'example.org', + array('unmodified_content' => true)), + /** + * Test authenticated sending of a message from a remote client. + */ + array(dirname(__FILE__) . '/fixtures/validation.eml', + dirname(__FILE__) . '/fixtures/validation.ret', + 'me@example.org', 'remote.example.org', 'me@example.org', 'you@example.org', 'example.org'), + /** + * Test authenticated sending of a message from a remote client + * using an alias. + */ + array(dirname(__FILE__) . '/fixtures/validation.eml', + dirname(__FILE__) . '/fixtures/validation.ret', + 'me@example.org', 'remote.example.org', 'me.me@example.org', 'you@example.org', 'example.org'), + /** + * Test authenticated sending of a message from a remote client + * using an alias with capitals (MEME@example.org). + */ + array(dirname(__FILE__) . '/fixtures/validation.eml', + dirname(__FILE__) . '/fixtures/validation.ret', + 'me@example.org', 'remote.example.org', 'meme@example.org', 'you@example.org', 'example.org'), + /** + * Test authenticated sending of a message from a remote client + * as delegate + */ + array(dirname(__FILE__) . '/fixtures/validation.eml', + dirname(__FILE__) . '/fixtures/validation.ret', + 'me@example.org', 'remote.example.org', 'else@example.org', 'you@example.org', 'example.org'), + /** + * Test authenticated sending of a message from a remote client + * with an address that is not allowed. + */ + array(dirname(__FILE__) . '/fixtures/validation.eml', + dirname(__FILE__) . '/fixtures/validation.ret', + 'me@example.org', 'remote.example.org', 'else3@example.org', 'you@example.org', 'example.org', + array('error' =>'Invalid From: header. else3@example.org looks like a forged sender')), + /** + * Test forwarding an invitation + */ + array(dirname(__FILE__) . '/fixtures/invitation_forward.eml', + dirname(__FILE__) . '/fixtures/invitation_forward.ret', + 'me@example.org', '10.0.2.1', 'me@example.org', 'you@example.org', 'example.org'), + ); + } + + /** + * Test rejecting a forged from header. + */ + public function testRejectingForgedFromHeader() + { + global $conf; + + $conf['kolab']['filter']['reject_forged_from_header'] = true; + + $this->sendFixture(dirname(__FILE__) . '/fixtures/forged.eml', + dirname(__FILE__) . '/fixtures/forged.ret', + '', '10.0.0.1', 'me@example.org', 'you@example.org', 'example.org', + array('error' =>'Invalid From: header. me@example.org looks like a forged sender', + 'unmodified_content' => true)); + } + + /** + * Test translated forged from headers. + */ + public function testTranslatedForgedFromHeader() + { + $this->markTestIncomplete('Some the translation does not kick in.'); + global $conf; + + $conf['kolab']['filter']['locale_path'] = dirname(__FILE__) . '/../../../../../data/Kolab_Filter/locale'; + $conf['kolab']['filter']['locale'] = 'de_DE'; + + $this->sendFixture(dirname(__FILE__) . '/fixtures/forged.eml', + dirname(__FILE__) . '/fixtures/forged_trans.ret', + '', '10.0.0.1', 'me@example.org', 'you@example.org', 'example.org', + array('unmodified_content' => true)); + } + +} diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/Helper/AddressFilter.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/Helper/AddressFilter.php new file mode 100644 index 000000000..1a94330ce --- /dev/null +++ b/framework/Kolab_Filter/test/Horde/Kolab/Filter/Helper/AddressFilter.php @@ -0,0 +1,79 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ + +/** + * Rewrites address information in a mail template. + * + * Copyright 2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + * + * @category Kolab + * @package Kolab_Filter + * @subpackage UnitTests + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ +class Horde_Kolab_Filter_Helper_AddressFilter +extends php_user_filter +{ + public $_previous = ''; + + public $_sender; + + public $_recipient; + + public function onCreate() + { + $this->_sender = isset($this->params['sender']) ? $this->params['sender'] : ''; + $this->_recipient = isset($this->params['recipient']) ? $this->params['recipient'] : ''; + $this->_previous = ''; + } + + public function filter($in, $out, &$consumed, $closing) + { + while ($bucket = stream_bucket_make_writeable($in)) { + if (!empty($this->_previous)) { + $bucket->data = $this->_previous . $bucket->data; + $this->_previous = ''; + } + if (!feof($this->stream) && preg_match('/(%[12]\$|%[12]|%)$/', $bucket->data)) { + $this->_previous .= $bucket->data; + return PSFS_FEED_ME; + } + $consumed += $bucket->datalen; + if (preg_match('/%([12])\$s/', $bucket->data, $matches)) { + if ($matches[1] == '1') { + $bucket->data = preg_replace('/%1\$s/', $this->_sender, $bucket->data); + } else { + $bucket->data = preg_replace('/%2\$s/', $this->_recipient, $bucket->data); + } + } + $bucket->datalen = strlen($bucket->data); + stream_bucket_append($out, $bucket); + } + if (!empty($this->_previous)) { + if ($closing) { + $bucket = stream_bucket_new($this->stream, $this->_previous); + $bucket->data = $this->_previous; + $consumed += strlen($this->_previous); + $this->_previous = ''; + stream_bucket_append($out, $bucket); + } + } + return PSFS_PASS_ON; + } +} diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/IncomingTest.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/IncomingTest.php deleted file mode 100644 index 15c503442..000000000 --- a/framework/Kolab_Filter/test/Horde/Kolab/Filter/IncomingTest.php +++ /dev/null @@ -1,85 +0,0 @@ - - * @package Horde_Kolab_Filter - */ -class Horde_Kolab_Filter_IncomingTest extends Horde_Kolab_Test_Filter -{ - - /** - * Set up testing. - */ - protected function setUp() - { - global $conf; - - $conf = array(); - - $test = new Horde_Kolab_Test_Filter(); - $test->prepareBasicSetup(); - - $conf['log']['enabled'] = false; - - $conf['kolab']['filter']['debug'] = true; - - $conf['kolab']['imap']['server'] = 'localhost'; - $conf['kolab']['imap']['port'] = 0; - - $_SERVER['SERVER_NAME'] = 'localhost'; - } - - - /** - * Test receiving the simple.eml message. - */ - public function testSimpleIn() - { - $params = array('unmodified_content' => true, - 'incoming' => true); - - $this->sendFixture(dirname(__FILE__) . '/fixtures/simple.eml', - dirname(__FILE__) . '/fixtures/simple2.ret', - '', '', 'wrobel@example.org', 'me@example.org', - 'home.example.org', $params); - } - - /** - * Test handling the line end with incoming messages. - */ - public function testIncomingLineEnd() - { - $params = array('unmodified_content' => true, - 'incoming' => true); - - $this->sendFixture(dirname(__FILE__) . '/fixtures/empty.eml', - dirname(__FILE__) . '/fixtures/empty2.ret', - '', '127.0.0.1', 'wrobel@example.org', 'me@example.org', - 'home.example.org', $params); - } -} diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/Integration/CliTest.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/Integration/CliTest.php index 72abeb608..7b246924f 100644 --- a/framework/Kolab_Filter/test/Horde/Kolab/Filter/Integration/CliTest.php +++ b/framework/Kolab_Filter/test/Horde/Kolab/Filter/Integration/CliTest.php @@ -32,37 +32,19 @@ require_once dirname(__FILE__) . '/../Autoload.php'; * @license http://www.fsf.org/copyleft/lgpl.html LGPL * @link http://pear.horde.org/index.php?package=Kolab_Filter */ -class Horde_Kolab_Filter_Integration_CliTest extends PHPUnit_Framework_TestCase +class Horde_Kolab_Filter_Integration_CliTest +extends PHPUnit_Framework_TestCase { - - /** - * Set up testing. - */ - protected function setUp() - { - $GLOBALS['conf']['log']['enabled'] = false; - - $_SERVER['SERVER_NAME'] = 'localhost'; - $_SERVER['REMOTE_ADDR'] = 'ADDR'; - $_SERVER['REMOTE_HOST'] = 'HOST'; - } - - /** * Test incorrect usage of the Filter. */ public function testIncorrectUsage() { $_SERVER['argv'] = array($_SERVER['argv'][0]); - $parser = new Horde_Kolab_Filter_Incoming( - new Horde_Kolab_Filter_Cli(), - new Horde_Log_Logger( - new Horde_Log_Handler_Mock() - ) - ); + $filter = new Horde_Kolab_Filter(); $inh = fopen(dirname(__FILE__) . '/../fixtures/tiny.eml', 'r'); try { - $result = $parser->parse($inh, 'echo'); + $result = $filter->main('Incoming', $inh, 'echo'); } catch (Horde_Kolab_Filter_Exception $e) { $this->assertContains( 'Please provide one or more recipients.', @@ -82,15 +64,10 @@ class Horde_Kolab_Filter_Integration_CliTest extends PHPUnit_Framework_TestCase $_SERVER['argv'][0], '--recipient' ); - $parser = new Horde_Kolab_Filter_Incoming( - new Horde_Kolab_Filter_Cli(), - new Horde_Log_Logger( - new Horde_Log_Handler_Mock() - ) - ); + $filter = new Horde_Kolab_Filter(); $inh = fopen(dirname(__FILE__) . '/../fixtures/tiny.eml', 'r'); try { - $result = $parser->parse($inh, 'echo'); + $result = $filter->main('Incoming', $inh, 'echo'); } catch (Horde_Kolab_Filter_Exception $e) { $this->assertContains( 'error: --recipient option requires an argument', diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/Integration/IncomingTest.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/Integration/IncomingTest.php new file mode 100644 index 000000000..4a92e7f0c --- /dev/null +++ b/framework/Kolab_Filter/test/Horde/Kolab/Filter/Integration/IncomingTest.php @@ -0,0 +1,65 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ + +/** + * Prepare the test setup. + */ +require_once dirname(__FILE__) . '/../Autoload.php'; + +/** + * Test the incoming filter. + * + * Copyright 2008-2010 Klarälvdalens Datakonsult AB + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + * + * @category Kolab + * @package Kolab_Filter + * @subpackage UnitTests + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ +class Horde_Kolab_Filter_Integration_IncomingTest +extends Horde_Kolab_Filter_StoryTestCase +{ + /** + * Test receiving the simple.eml message. + */ + public function testSimpleIn() + { + $this->given('an incoming message on host', 'home.example.org') + ->and('the SMTP sender address is', 'wrobel@example.org') + ->and('the SMTP recipient address is', 'me@example.org') + ->and('the unmodified message content is', dirname(__FILE__) . '/../fixtures/simple.eml') + ->when('handling the message') + ->then('the result will be the same as the content in', dirname(__FILE__) . '/../fixtures/simple2.ret'); + } + + /** + * Test handling the line end with incoming messages. + */ + public function testIncomingLineEnd() + { + $this->given('an incoming message on host', 'home.example.org') + ->and('the SMTP sender address is', 'wrobel@example.org') + ->and('the SMTP recipient address is', 'me@example.org') + ->and('the client address is', '127.0.0.1') + ->and('the hostname is', 'home.example.com') + ->and('the unmodified message content is', dirname(__FILE__) . '/../fixtures/empty.eml') + ->when('handling the message') + ->then('the result will be the same as the content in', dirname(__FILE__) . '/../fixtures/empty2.ret'); + } +} diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/LoadTest.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/LoadTest.php deleted file mode 100644 index d4faa304d..000000000 --- a/framework/Kolab_Filter/test/Horde/Kolab/Filter/LoadTest.php +++ /dev/null @@ -1,117 +0,0 @@ - - * @package Horde_Kolab_Filter - */ -class Horde_Kolab_Filter_LoadTest extends PHPUnit_Extensions_PerformanceTestCase -{ - - /** - * Set up testing. - */ - protected function setUp() - { - global $conf; - - $conf = array(); - $conf['log']['enabled'] = false; - - $conf['kolab']['filter']['debug'] = true; - - $conf['kolab']['server'] = array( - 'driver' => 'test', - 'params' => array( - 'data' => array( - 'cn=me' => array( - 'dn' => 'cn=me', - 'data' => array( - 'objectClass' => array('kolabInetOrgPerson'), - 'mail' => array('me@example.com'), - 'kolabImapHost' => array('localhost'), - 'uid' => array('me'), - ) - ), - 'cn=you' => array( - 'dn' => 'cn=you', - 'data' => array( - 'objectClass' => array('kolabInetOrgPerson'), - 'mail' => array('you@example.com'), - 'kolabImapHost' => array('localhost'), - 'uid' => array('you'), - ) - ), - ), - ) - ); - $conf['kolab']['imap']['server'] = 'localhost'; - $conf['kolab']['imap']['port'] = 0; - $conf['kolab']['imap']['allow_special_users'] = true; - - $_SERVER['SERVER_NAME'] = 'localhost'; - } - - - /** - * Test the time the script takes in handling some messages. - */ - public function testLoad() - { - $this->setMaxRunningTime(3); - - $tmpdir = Horde::getTempDir(); - $tmpfile = @tempnam($tmpdir, 'BIG.eml.'); - $tmpfh = @fopen($tmpfile, "w"); - $head = file_get_contents(dirname(__FILE__) . '/fixtures/tiny.eml'); - $body = ''; - for ($i = 0; $i < 50000;$i++) { - $body .= md5(microtime()); - if (($i % 2) == 0) { - $body .= "\n"; - } - } - @fwrite($tmpfh, $head); - @fwrite($tmpfh, $body); - @fclose($tmpfh); - - $_SERVER['argv'] = array($_SERVER['argv'][0], '--sender=me@example.com', '--recipient=you@example.com', '--user=', '--host=example.com'); - - for ($i = 0; $i < 10; $i++) { - - $parser = &new Horde_Kolab_Filter_Incoming(); - $inh = fopen(dirname(__FILE__) . '/fixtures/tiny.eml', 'r'); - $parser->parse($inh, 'drop'); - - $parser = &new Horde_Kolab_Filter_Incoming(); - $inh = fopen(dirname(__FILE__) . '/fixtures/simple.eml', 'r'); - $parser->parse($inh, 'drop'); - - $parser = &new Horde_Kolab_Filter_Incoming(); - $inh = fopen($tmpfile, 'r'); - $parser->parse($inh, 'drop'); - - } - unlink($tmpfile); - } -} diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/ResourceTest.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/ResourceTest.php deleted file mode 100644 index 69d1274ea..000000000 --- a/framework/Kolab_Filter/test/Horde/Kolab/Filter/ResourceTest.php +++ /dev/null @@ -1,371 +0,0 @@ - - * @package Horde_Kolab_Filter - */ -class Horde_Kolab_Filter_ResourceTest extends Horde_Kolab_Test_Filter -{ - - /** - * Set up testing. - */ - protected function setUp() - { - $result = $this->prepareBasicSetup(); - - $this->server = &$result['server']; - $this->storage = &$result['storage']; - $this->auth = &$result['auth']; - - global $conf; - - $conf['kolab']['imap']['server'] = 'localhost'; - $conf['kolab']['imap']['port'] = 0; - $conf['kolab']['imap']['allow_special_users'] = true; - $conf['kolab']['filter']['reject_forged_from_header'] = false; - $conf['kolab']['filter']['email_domain'] = 'example.org'; - $conf['kolab']['filter']['privileged_networks'] = '127.0.0.1,192.168.0.0/16'; - $conf['kolab']['filter']['verify_from_header'] = true; - $conf['kolab']['filter']['calendar_id'] = 'calendar'; - $conf['kolab']['filter']['calendar_pass'] = 'calendar'; - $conf['kolab']['filter']['lmtp_host'] = 'imap.example.org'; - $conf['kolab']['filter']['simple_locks'] = true; - $conf['kolab']['filter']['simple_locks_timeout'] = 3; - - $conf['kolab']['filter']['itipreply']['driver'] = 'echo'; - $conf['kolab']['filter']['itipreply']['params']['host'] = 'localhsot'; - $conf['kolab']['filter']['itipreply']['params']['port'] = 25; - - $result = $this->auth->authenticate('wrobel', array('password' => 'none')); - $this->assertNoError($result); - - $folder = $this->storage->getNewFolder(); - $folder->setName('Kalender'); - $result = $folder->save(array('type' => 'event', - 'default' => true)); - $this->assertNoError($result); - } - - /** - * Test retrieval of the resource information - */ - public function testGetResourceData() - { - $r = &new Kolab_Resource(); - $d = $r->_getResourceData('test@example.org', 'wrobel@example.org'); - $this->assertNoError($d); - $this->assertEquals('wrobel@example.org', $d['id']); - $this->assertEquals('home.example.org', $d['homeserver']); - $this->assertEquals('ACT_REJECT_IF_CONFLICTS', $d['action']); - $this->assertEquals('cn=Gunnar Wrobel', $d['cn']); - } - - /** - * Test manual actions - */ - public function testManual() - { - $r = &new Kolab_Resource(); - $this->assertTrue($r->handleMessage('otherhost', 'test@example.org', 'wrobel@example.org', null)); - $r = &new Kolab_Resource(); - $this->assertTrue($r->handleMessage('localhost', 'test@example.org', 'wrobel@example.org', null)); - } - - - /** - * Test invitation. - */ - public function testRecurrenceInvitation() - { - $this->markTestIncomplete('Fails for unknown reason.'); - - $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20080926T000000Z')); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20081126T000000Z')); - - $params = array('unmodified_content' => true, - 'incoming' => true); - - $this->sendFixture(dirname(__FILE__) . '/fixtures/recur_invitation.eml', - dirname(__FILE__) . '/fixtures/recur_invitation.ret2', - '', '', 'test@example.org', 'wrobel@example.org', - 'home.example.org', $params); - - $result = $this->auth->authenticate('wrobel', array('password' => 'none')); - $this->assertNoError($result); - - $folder = $this->storage->getFolder('INBOX/Kalender'); - $data = $folder->getData(); - $events = $data->getObjects(); - $this->assertEquals(1222419600, $events[0]['start-date']); - - $result = $data->deleteAll(); - $this->assertNoError($result); - } - - /** - * Test an that contains a long string. - */ - public function testLongStringInvitation() - { - $this->markTestIncomplete('Fails for unknown reason.'); - - require_once 'Horde/Icalendar/Vfreebusy.php'; - $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20080926T000000Z')); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20081126T000000Z')); - - $params = array('unmodified_content' => true, - 'incoming' => true); - - $this->sendFixture(dirname(__FILE__) . '/fixtures/longstring_invitation.eml', - dirname(__FILE__) . '/fixtures/longstring_invitation.ret', - '', '', 'test@example.org', 'wrobel@example.org', - 'home.example.org', $params); - - $result = $this->auth->authenticate('wrobel', array('password' => 'none')); - $this->assertNoError($result); - - $folder = $this->storage->getFolder('INBOX/Kalender'); - $data = $folder->getData(); - $events = $data->getObjects(); - $summaries = array(); - foreach ($events as $event) { - $summaries[] = $event['summary']; - } - $this->assertContains('invitationtest2', $summaries); - - $result = $data->deleteAll(); - $this->assertNoError($result); - } - - /** - * Test an invitation that books a whole day. - */ - public function testWholeDayInvitation() - { - require_once 'Horde/Icalendar/Vfreebusy.php'; - $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20090401T000000Z')); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20090601T000000Z')); - - $params = array('unmodified_content' => true, - 'incoming' => true); - - $this->sendFixture(dirname(__FILE__) . '/fixtures/invitation_whole_day.eml', - dirname(__FILE__) . '/fixtures/invitation_whole_day.ret', - '', '', 'test@example.org', 'wrobel@example.org', - 'home.example.org', $params); - - $result = $this->auth->authenticate('wrobel', array('password' => 'none')); - $this->assertNoError($result); - - $folder = $this->storage->getFolder('INBOX/Kalender'); - $data = $folder->getData(); - $events = $data->getObjects(); - $summaries = array(); - foreach ($events as $event) { - $summaries[] = $event['summary']; - } - $this->assertContains('issue3558', $summaries); - - $result = $data->deleteAll(); - $this->assertNoError($result); - } - - /** - * Test an invitation with plus addressing. - */ - public function testInvitationWithPlusAddressing() - { - require_once 'Horde/Icalendar/Vfreebusy.php'; - $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20090401T000000Z')); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20090601T000000Z')); - - $params = array('unmodified_content' => true, - 'incoming' => true); - - $this->sendFixture(dirname(__FILE__) . '/fixtures/invitation_plus_addressing.eml', - dirname(__FILE__) . '/fixtures/invitation_plus_addressing.ret', - '', '', 'test@example.org', 'wrobel+laptop@example.org', - 'home.example.org', $params); - - $result = $this->auth->authenticate('wrobel', array('password' => 'none')); - $this->assertNoError($result); - - $folder = $this->storage->getFolder('INBOX/Kalender'); - $data = $folder->getData(); - $events = $data->getObjects(); - $summaries = array(); - foreach ($events as $event) { - $summaries[] = $event['summary']; - } - $this->assertContains('issue3521', $summaries); - - $result = $data->deleteAll(); - $this->assertNoError($result); - } - - /** - * Test invitation when no default has been given. - */ - public function testRecurrenceNodefault() - { - $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20080926T000000Z')); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20081126T000000Z')); - - $params = array('unmodified_content' => true, - 'incoming' => true); - - $this->sendFixture(dirname(__FILE__) . '/fixtures/recur_invitation.eml', - dirname(__FILE__) . '/fixtures/recur_invitation.ret', - '', '', 'wrobel@example.org', 'else@example.org', - 'home.example.org', $params); - } - - /** - * Test an issue with recurring invitations. - * - * https://issues.kolab.org/issue3868 - */ - public function testIssue3868() - { - $this->markTestIncomplete('Fails for unknown reason.'); - - $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20090901T000000Z')); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20091101T000000Z')); - - $params = array('unmodified_content' => true, - 'incoming' => true); - - $this->sendFixture(dirname(__FILE__) . '/fixtures/recur_invitation2.eml', - dirname(__FILE__) . '/fixtures/null.ret', - '', '', 'test@example.org', 'wrobel@example.org', - 'home.example.org', $params); - - $result = $this->auth->authenticate('wrobel', array('password' => 'none')); - $this->assertNoError($result); - - $folder = $this->storage->getFolder('INBOX/Kalender'); - $data = $folder->getData(); - $events = $data->getObjects(); - $this->assertEquals(1251950400, $events[0]['start-date']); - - $result = $data->deleteAll(); - $this->assertNoError($result); - } - - /** - * Test all day events - */ - public function testAllDay() - { - $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20090901T000000Z')); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20091101T000000Z')); - - $params = array('unmodified_content' => true, - 'incoming' => true); - - $this->sendFixture(dirname(__FILE__) . '/fixtures/allday_invitation.eml', - dirname(__FILE__) . '/fixtures/null.ret', - '', '', 'test@example.org', 'wrobel@example.org', - 'home.example.org', $params); - - $result = $this->auth->authenticate('wrobel', array('password' => 'none')); - $this->assertNoError($result); - - $folder = $this->storage->getFolder('INBOX/Kalender'); - $data = $folder->getData(); - $events = $data->getObjects(); - - $this->assertEquals(1251928800, $events[0]['start-date']); - $this->assertEquals(1252015200, $events[0]['end-date']); - - $result = $data->deleteAll(); - $this->assertNoError($result); - } - - /** - * Test that the attendee status gets transferred. - */ - public function testAttendeeStatusInvitation() - { - $this->markTestIncomplete('Sends mail'); - - require_once 'Horde/Icalendar/Vfreebusy.php'; - $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20080926T000000Z')); - $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20081126T000000Z')); - - $params = array('unmodified_content' => true, - 'incoming' => true); - - $this->sendFixture(dirname(__FILE__) . '/fixtures/attendee_status_invitation.eml', - dirname(__FILE__) . '/fixtures/null.ret', - '', '', 'test@example.org', 'wrobel@example.org', - 'home.example.org', $params); - - $result = $this->auth->authenticate('wrobel', array('password' => 'none')); - $this->assertNoError($result); - - $folder = $this->storage->getFolder('INBOX/Kalender'); - $data = $folder->getData(); - $events = $data->getObjects(); - $summaries = array(); - foreach ($events as $event) { - foreach ($event['attendee'] as $attendee) { - switch ($attendee['smtp-address']) { - case 'needs@example.org': - $this->assertEquals('none', $attendee['status']); - break; - case 'accepted@example.org': - $this->assertEquals('accepted', $attendee['status']); - break; - case 'declined@example.org': - $this->assertEquals('declined', $attendee['status']); - break; - case 'tentative@example.org': - $this->assertEquals('tentative', $attendee['status']); - break; - case 'delegated@example.org': - $this->assertEquals('none', $attendee['status']); - break; - default: - $this->fail('Unexpected attendee!'); - break; - } - } - } - $result = $data->deleteAll(); - $this->assertNoError($result); - } - -} diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/ResourceTestOld.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/ResourceTestOld.php new file mode 100644 index 000000000..69d1274ea --- /dev/null +++ b/framework/Kolab_Filter/test/Horde/Kolab/Filter/ResourceTestOld.php @@ -0,0 +1,371 @@ + + * @package Horde_Kolab_Filter + */ +class Horde_Kolab_Filter_ResourceTest extends Horde_Kolab_Test_Filter +{ + + /** + * Set up testing. + */ + protected function setUp() + { + $result = $this->prepareBasicSetup(); + + $this->server = &$result['server']; + $this->storage = &$result['storage']; + $this->auth = &$result['auth']; + + global $conf; + + $conf['kolab']['imap']['server'] = 'localhost'; + $conf['kolab']['imap']['port'] = 0; + $conf['kolab']['imap']['allow_special_users'] = true; + $conf['kolab']['filter']['reject_forged_from_header'] = false; + $conf['kolab']['filter']['email_domain'] = 'example.org'; + $conf['kolab']['filter']['privileged_networks'] = '127.0.0.1,192.168.0.0/16'; + $conf['kolab']['filter']['verify_from_header'] = true; + $conf['kolab']['filter']['calendar_id'] = 'calendar'; + $conf['kolab']['filter']['calendar_pass'] = 'calendar'; + $conf['kolab']['filter']['lmtp_host'] = 'imap.example.org'; + $conf['kolab']['filter']['simple_locks'] = true; + $conf['kolab']['filter']['simple_locks_timeout'] = 3; + + $conf['kolab']['filter']['itipreply']['driver'] = 'echo'; + $conf['kolab']['filter']['itipreply']['params']['host'] = 'localhsot'; + $conf['kolab']['filter']['itipreply']['params']['port'] = 25; + + $result = $this->auth->authenticate('wrobel', array('password' => 'none')); + $this->assertNoError($result); + + $folder = $this->storage->getNewFolder(); + $folder->setName('Kalender'); + $result = $folder->save(array('type' => 'event', + 'default' => true)); + $this->assertNoError($result); + } + + /** + * Test retrieval of the resource information + */ + public function testGetResourceData() + { + $r = &new Kolab_Resource(); + $d = $r->_getResourceData('test@example.org', 'wrobel@example.org'); + $this->assertNoError($d); + $this->assertEquals('wrobel@example.org', $d['id']); + $this->assertEquals('home.example.org', $d['homeserver']); + $this->assertEquals('ACT_REJECT_IF_CONFLICTS', $d['action']); + $this->assertEquals('cn=Gunnar Wrobel', $d['cn']); + } + + /** + * Test manual actions + */ + public function testManual() + { + $r = &new Kolab_Resource(); + $this->assertTrue($r->handleMessage('otherhost', 'test@example.org', 'wrobel@example.org', null)); + $r = &new Kolab_Resource(); + $this->assertTrue($r->handleMessage('localhost', 'test@example.org', 'wrobel@example.org', null)); + } + + + /** + * Test invitation. + */ + public function testRecurrenceInvitation() + { + $this->markTestIncomplete('Fails for unknown reason.'); + + $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20080926T000000Z')); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20081126T000000Z')); + + $params = array('unmodified_content' => true, + 'incoming' => true); + + $this->sendFixture(dirname(__FILE__) . '/fixtures/recur_invitation.eml', + dirname(__FILE__) . '/fixtures/recur_invitation.ret2', + '', '', 'test@example.org', 'wrobel@example.org', + 'home.example.org', $params); + + $result = $this->auth->authenticate('wrobel', array('password' => 'none')); + $this->assertNoError($result); + + $folder = $this->storage->getFolder('INBOX/Kalender'); + $data = $folder->getData(); + $events = $data->getObjects(); + $this->assertEquals(1222419600, $events[0]['start-date']); + + $result = $data->deleteAll(); + $this->assertNoError($result); + } + + /** + * Test an that contains a long string. + */ + public function testLongStringInvitation() + { + $this->markTestIncomplete('Fails for unknown reason.'); + + require_once 'Horde/Icalendar/Vfreebusy.php'; + $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20080926T000000Z')); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20081126T000000Z')); + + $params = array('unmodified_content' => true, + 'incoming' => true); + + $this->sendFixture(dirname(__FILE__) . '/fixtures/longstring_invitation.eml', + dirname(__FILE__) . '/fixtures/longstring_invitation.ret', + '', '', 'test@example.org', 'wrobel@example.org', + 'home.example.org', $params); + + $result = $this->auth->authenticate('wrobel', array('password' => 'none')); + $this->assertNoError($result); + + $folder = $this->storage->getFolder('INBOX/Kalender'); + $data = $folder->getData(); + $events = $data->getObjects(); + $summaries = array(); + foreach ($events as $event) { + $summaries[] = $event['summary']; + } + $this->assertContains('invitationtest2', $summaries); + + $result = $data->deleteAll(); + $this->assertNoError($result); + } + + /** + * Test an invitation that books a whole day. + */ + public function testWholeDayInvitation() + { + require_once 'Horde/Icalendar/Vfreebusy.php'; + $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20090401T000000Z')); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20090601T000000Z')); + + $params = array('unmodified_content' => true, + 'incoming' => true); + + $this->sendFixture(dirname(__FILE__) . '/fixtures/invitation_whole_day.eml', + dirname(__FILE__) . '/fixtures/invitation_whole_day.ret', + '', '', 'test@example.org', 'wrobel@example.org', + 'home.example.org', $params); + + $result = $this->auth->authenticate('wrobel', array('password' => 'none')); + $this->assertNoError($result); + + $folder = $this->storage->getFolder('INBOX/Kalender'); + $data = $folder->getData(); + $events = $data->getObjects(); + $summaries = array(); + foreach ($events as $event) { + $summaries[] = $event['summary']; + } + $this->assertContains('issue3558', $summaries); + + $result = $data->deleteAll(); + $this->assertNoError($result); + } + + /** + * Test an invitation with plus addressing. + */ + public function testInvitationWithPlusAddressing() + { + require_once 'Horde/Icalendar/Vfreebusy.php'; + $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20090401T000000Z')); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20090601T000000Z')); + + $params = array('unmodified_content' => true, + 'incoming' => true); + + $this->sendFixture(dirname(__FILE__) . '/fixtures/invitation_plus_addressing.eml', + dirname(__FILE__) . '/fixtures/invitation_plus_addressing.ret', + '', '', 'test@example.org', 'wrobel+laptop@example.org', + 'home.example.org', $params); + + $result = $this->auth->authenticate('wrobel', array('password' => 'none')); + $this->assertNoError($result); + + $folder = $this->storage->getFolder('INBOX/Kalender'); + $data = $folder->getData(); + $events = $data->getObjects(); + $summaries = array(); + foreach ($events as $event) { + $summaries[] = $event['summary']; + } + $this->assertContains('issue3521', $summaries); + + $result = $data->deleteAll(); + $this->assertNoError($result); + } + + /** + * Test invitation when no default has been given. + */ + public function testRecurrenceNodefault() + { + $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20080926T000000Z')); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20081126T000000Z')); + + $params = array('unmodified_content' => true, + 'incoming' => true); + + $this->sendFixture(dirname(__FILE__) . '/fixtures/recur_invitation.eml', + dirname(__FILE__) . '/fixtures/recur_invitation.ret', + '', '', 'wrobel@example.org', 'else@example.org', + 'home.example.org', $params); + } + + /** + * Test an issue with recurring invitations. + * + * https://issues.kolab.org/issue3868 + */ + public function testIssue3868() + { + $this->markTestIncomplete('Fails for unknown reason.'); + + $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20090901T000000Z')); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20091101T000000Z')); + + $params = array('unmodified_content' => true, + 'incoming' => true); + + $this->sendFixture(dirname(__FILE__) . '/fixtures/recur_invitation2.eml', + dirname(__FILE__) . '/fixtures/null.ret', + '', '', 'test@example.org', 'wrobel@example.org', + 'home.example.org', $params); + + $result = $this->auth->authenticate('wrobel', array('password' => 'none')); + $this->assertNoError($result); + + $folder = $this->storage->getFolder('INBOX/Kalender'); + $data = $folder->getData(); + $events = $data->getObjects(); + $this->assertEquals(1251950400, $events[0]['start-date']); + + $result = $data->deleteAll(); + $this->assertNoError($result); + } + + /** + * Test all day events + */ + public function testAllDay() + { + $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20090901T000000Z')); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20091101T000000Z')); + + $params = array('unmodified_content' => true, + 'incoming' => true); + + $this->sendFixture(dirname(__FILE__) . '/fixtures/allday_invitation.eml', + dirname(__FILE__) . '/fixtures/null.ret', + '', '', 'test@example.org', 'wrobel@example.org', + 'home.example.org', $params); + + $result = $this->auth->authenticate('wrobel', array('password' => 'none')); + $this->assertNoError($result); + + $folder = $this->storage->getFolder('INBOX/Kalender'); + $data = $folder->getData(); + $events = $data->getObjects(); + + $this->assertEquals(1251928800, $events[0]['start-date']); + $this->assertEquals(1252015200, $events[0]['end-date']); + + $result = $data->deleteAll(); + $this->assertNoError($result); + } + + /** + * Test that the attendee status gets transferred. + */ + public function testAttendeeStatusInvitation() + { + $this->markTestIncomplete('Sends mail'); + + require_once 'Horde/Icalendar/Vfreebusy.php'; + $GLOBALS['KOLAB_FILTER_TESTING'] = new Horde_Icalendar_Vfreebusy(); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTSTART', Horde_Icalendar::_parseDateTime('20080926T000000Z')); + $GLOBALS['KOLAB_FILTER_TESTING']->setAttribute('DTEND', Horde_Icalendar::_parseDateTime('20081126T000000Z')); + + $params = array('unmodified_content' => true, + 'incoming' => true); + + $this->sendFixture(dirname(__FILE__) . '/fixtures/attendee_status_invitation.eml', + dirname(__FILE__) . '/fixtures/null.ret', + '', '', 'test@example.org', 'wrobel@example.org', + 'home.example.org', $params); + + $result = $this->auth->authenticate('wrobel', array('password' => 'none')); + $this->assertNoError($result); + + $folder = $this->storage->getFolder('INBOX/Kalender'); + $data = $folder->getData(); + $events = $data->getObjects(); + $summaries = array(); + foreach ($events as $event) { + foreach ($event['attendee'] as $attendee) { + switch ($attendee['smtp-address']) { + case 'needs@example.org': + $this->assertEquals('none', $attendee['status']); + break; + case 'accepted@example.org': + $this->assertEquals('accepted', $attendee['status']); + break; + case 'declined@example.org': + $this->assertEquals('declined', $attendee['status']); + break; + case 'tentative@example.org': + $this->assertEquals('tentative', $attendee['status']); + break; + case 'delegated@example.org': + $this->assertEquals('none', $attendee['status']); + break; + default: + $this->fail('Unexpected attendee!'); + break; + } + } + } + $result = $data->deleteAll(); + $this->assertNoError($result); + } + +} diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/StoryTestCase.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/StoryTestCase.php index 6b6c285e3..d6fa53caf 100644 --- a/framework/Kolab_Filter/test/Horde/Kolab/Filter/StoryTestCase.php +++ b/framework/Kolab_Filter/test/Horde/Kolab/Filter/StoryTestCase.php @@ -42,7 +42,41 @@ extends PHPUnit_Extensions_Story_TestCase public function runGiven(&$world, $action, $arguments) { switch($action) { - case 'that no Kolab server configuration file can be found': + case 'an incoming message on host': + $world['hostname'] = $arguments[0]; + $world['type'] = 'Incoming'; + break; + case 'the SMTP sender address is': + $world['sender'] = $arguments[0]; + break; + case 'the SMTP recipient address is': + $world['recipient'] = $arguments[0]; + break; + case 'the client address is': + $world['client'] = $arguments[0]; + break; + case 'the hostname is': + $world['hostname'] = $arguments[0]; + break; + case 'the unmodified message content is': + $world['infile'] = $arguments[0]; + $world['fp'] = fopen($world['infile'], 'r'); + break; + case 'the modified message template is': + $world['infile'] = $arguments[0]; + $world['fp'] = fopen($world['infile'], 'r'); + stream_filter_register( + 'addresses', 'Horde_Kolab_Filter_Helper_AddressFilter' + ); + stream_filter_append( + $world['fp'], + 'addresses', + STREAM_FILTER_READ, + array( + 'recipient' => $world['recipient'], + 'sender' => $world['sender'] + ) + ); break; default: return $this->notImplemented($action); @@ -61,7 +95,13 @@ extends PHPUnit_Extensions_Story_TestCase public function runWhen(&$world, $action, $arguments) { switch($action) { - case 'reading the configuration': + case 'handling the message': + $_SERVER['argv'] = $this->_prepareArguments($world); + $filter = new Horde_Kolab_Filter(); + ob_start(); + $result = $filter->main($world['type'], $world['fp'], 'echo'); + $world['output'] = ob_get_contents(); + ob_end_clean(); break; default: return $this->notImplemented($action); @@ -80,11 +120,49 @@ extends PHPUnit_Extensions_Story_TestCase public function runThen(&$world, $action, $arguments) { switch($action) { - case 'the Config Object will throw an exception of type': + case 'the result will be the same as the content in': + $out = file_get_contents($arguments[0]); + $this->_cleanAndCompareOutput($out, $world['output']); break; default: return $this->notImplemented($action); } } + private function _prepareArguments(&$world) + { + $recipient = isset($world['recipient']) ? $world['recipient'] : ''; + $sender = isset($world['sender']) ? $world['sender'] : ''; + $user = isset($world['user']) ? $world['user'] : ''; + $hostname = isset($world['hostname']) ? $world['hostname'] : ''; + $client = isset($world['client']) ? $world['client'] : ''; + return array( + $_SERVER['argv'][0], + '--sender=' . $sender, + '--recipient=' . $recipient, + '--user=' . $user, + '--host=' . $hostname, + '--client=' . $client + ); + + } + + private function _cleanAndCompareOutput($received, $expected) + { + $replace = array( + '/^Received:.*$/m' => '', + '/^Date:.*$/m' => '', + '/DTSTAMP:.*$/m' => '', + '/^--+=.*$/m' => '----', + '/^Message-ID.*$/m' => '----', + '/boundary=.*$/m' => '----', + '/\s/' => '', + ); + foreach ($replace as $pattern => $replacement) { + $received = preg_replace($pattern, $replacement, $received); + $expected = preg_replace($pattern, $replacement, $expected); + } + + $this->assertEquals($received, $expected); + } } \ No newline at end of file diff --git a/framework/Kolab_Filter/test/Horde/Kolab/Filter/Unit/Helper/AddressFilter.php b/framework/Kolab_Filter/test/Horde/Kolab/Filter/Unit/Helper/AddressFilter.php new file mode 100644 index 000000000..6be864596 --- /dev/null +++ b/framework/Kolab_Filter/test/Horde/Kolab/Filter/Unit/Helper/AddressFilter.php @@ -0,0 +1,113 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ + +/** + * Prepare the test setup. + */ +require_once dirname(__FILE__) . '/../../Autoload.php'; + +/** + * Test the address rewriting filter. + * + * Copyright 2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + * + * @category Kolab + * @package Kolab_Filter + * @subpackage UnitTests + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Filter + */ +class Horde_Kolab_Filter_Unit_Helper_AddressFilterTest +extends PHPUnit_Framework_TestCase +{ + public function testFilter() + { + $fp = fopen('php://memory', 'w+'); + fputs($fp, "hello\n"); + rewind($fp); + stream_filter_register('addresses', 'Horde_Kolab_Filter_Helper_AddressFilter'); + stream_filter_append($fp, 'addresses'); + $this->assertEquals("hello\n", stream_get_contents($fp)); + } + + public function testFilterEmptiesUnsetParameterOne() + { + $fp = fopen('php://memory', 'w+'); + fputs($fp, "hello%1\$s\n"); + rewind($fp); + stream_filter_register('addresses', 'Horde_Kolab_Filter_Helper_AddressFilter'); + stream_filter_append($fp, 'addresses'); + $this->assertEquals("hello\n", stream_get_contents($fp)); + } + + public function testFilterEmptiesUnsetParameterTwo() + { + $fp = fopen('php://memory', 'w+'); + fputs($fp, "hello%2\$s\n"); + rewind($fp); + stream_filter_register('addresses', 'Horde_Kolab_Filter_Helper_AddressFilter'); + stream_filter_append($fp, 'addresses'); + $this->assertEquals("hello\n", stream_get_contents($fp)); + } + + public function testFilterSetsParameterSender() + { + $fp = fopen('php://memory', 'w+'); + fputs($fp, "hello %1\$s\n"); + rewind($fp); + stream_filter_register('addresses', 'Horde_Kolab_Filter_Helper_AddressFilter'); + stream_filter_append($fp, 'addresses', STREAM_FILTER_READ, array('sender' => 'sender')); + $this->assertEquals("hello sender\n", stream_get_contents($fp)); + } + + public function testFilterSetsParameterRecipient() + { + $fp = fopen('php://memory', 'w+'); + fputs($fp, "hello %2\$s\n"); + rewind($fp); + stream_filter_register('addresses', 'Horde_Kolab_Filter_Helper_AddressFilter'); + stream_filter_append($fp, 'addresses', STREAM_FILTER_READ, array('recipient' => 'recipient')); + $this->assertEquals("hello recipient\n", stream_get_contents($fp)); + } + + /** + * @dataProvider provideBrokenParameters + */ + public function testFilterHandlesBrokenParameter($param) + { + $fp = fopen('php://memory', 'w+'); + $append = "hello $param\n"; + fputs($fp, str_repeat('a', 16384 - strlen($append)) . $append . str_repeat('test', 300)); + rewind($fp); + stream_filter_register('addresses', 'Horde_Kolab_Filter_Helper_AddressFilter'); + stream_filter_append($fp, 'addresses'); + fread($fp, 16384 - strlen($append)); + $this->assertEquals("hello $param\n", fread($fp, strlen($append))); + } + + public function provideBrokenParameters() + { + return array( + array("%"), + array("%1"), + array("%2"), + array("%2\$"), + array("%2\$\ns"), + ); + } +} \ No newline at end of file