--- /dev/null
+<?php
+/**
+ * The main entry point for the Kolab_Filter application.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_Filter
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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
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();
}
/**
*
* @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
+ )
+ );
}
}
--- /dev/null
+<?php
+/**
+ * The configuration of the Kolab_Filter package.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_Filter
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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
--- /dev/null
+<?php
+/**
+ * This class provides an error thrown when an I/O error occured.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_Filter
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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
+ );
+ }
+}
--- /dev/null
+<?php
+/**
+ * A factory for Kolab_Filter objects.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_Filter
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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
*/
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
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.
{
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'];
}
}
+ $this->_tmpfh = $this->_temporary->getHandle();
+
$ical = false;
$add_headers = array();
$headers_done = false;
/* 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);
}
}
- Horde::logMessage("Filter_Incoming successfully completed.", 'DEBUG');
+ $this->_logger->debug("Filter_Incoming successfully completed.", 'DEBUG');
}
private function _transportItipReply(Horde_Kolab_Resource_Reply $reply)
}
$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",
--- /dev/null
+<?php
+/**
+ * Definition of a temporary storage place for incoming messages.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_Filter
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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
--- /dev/null
+<?php
+/**
+ * File based temporary storage place for incoming messages.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_Filter
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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
<dir name="lib">
<dir name="Horde">
<dir name="Kolab">
+ <file name="Filter.php" role="php" />
<dir name="Test">
<file name="Filter.php" role="php" />
</dir> <!-- /lib/Horde/Kolab/Test -->
<dir name="Cli">
<file name="Parser.php" role="php" />
</dir> <!-- /lib/Horde/Kolab/Filter/Cli -->
+ <file name="Configuration.php" role="php" />
<file name="Content.php" role="php" />
<file name="Base.php" role="php" />
<file name="Exception.php" role="php" />
<dir name="Exception">
+ <file name="IoError.php" role="php" />
<file name="Usage.php" role="php" />
</dir> <!-- /lib/Horde/Kolab/Filter/Exception -->
+ <file name="Factory.php" role="php" />
<file name="Incoming.php" role="php" />
<file name="Outlook.php" role="php" />
<file name="Response.php" role="php" />
+ <file name="Temporary.php" role="php" />
+ <dir name="Temporary">
+ <file name="File.php" role="php" />
+ </dir> <!-- /lib/Horde/Kolab/Filter/Temporary -->
<file name="Transport.php" role="php" />
<dir name="Transport">
<file name="drop.php" role="php" />
<install name="lib/Horde/Kolab/Resource/Freebusy/Kolab.php" as="Horde/Kolab/Resource/Freebusy/Kolab.php" />
<install name="lib/Horde/Kolab/Resource/Freebusy/Mock.php" as="Horde/Kolab/Resource/Freebusy/Mock.php" />
<install name="lib/Horde/Kolab/Test/Filter.php" as="Horde/Kolab/Test/Filter.php" />
+ <install name="lib/Horde/Kolab/Filter.php" as="Horde/Kolab/Filter.php" />
<install name="lib/Horde/Kolab/Filter/Cli.php" as="Horde/Kolab/Filter/Cli.php" />
<install name="lib/Horde/Kolab/Filter/Cli/Parser.php" as="Horde/Kolab/Filter/Cli/Parser.php" />
+ <install name="lib/Horde/Kolab/Filter/Configuration.php" as="Horde/Kolab/Filter/Configuration.php" />
<install name="lib/Horde/Kolab/Filter/Content.php" as="Horde/Kolab/Filter/Content.php" />
<install name="lib/Horde/Kolab/Filter/Base.php" as="Horde/Kolab/Filter/Base.php" />
<install name="lib/Horde/Kolab/Filter/Exception.php" as="Horde/Kolab/Filter/Exception.php" />
<install name="lib/Horde/Kolab/Filter/Exception/Usage.php" as="Horde/Kolab/Filter/Exception/Usage.php" />
+ <install name="lib/Horde/Kolab/Filter/Factory.php" as="Horde/Kolab/Filter/Factory.php" />
<install name="lib/Horde/Kolab/Filter/Incoming.php" as="Horde/Kolab/Filter/Incoming.php" />
<install name="lib/Horde/Kolab/Filter/Outlook.php" as="Horde/Kolab/Filter/Outlook.php" />
<install name="lib/Horde/Kolab/Filter/Response.php" as="Horde/Kolab/Filter/Response.php" />
+ <install name="lib/Horde/Kolab/Filter/Temporary.php" as="Horde/Kolab/Filter/Temporary.php" />
+ <install name="lib/Horde/Kolab/Filter/Temporary/File.php" as="Horde/Kolab/Filter/Temporary/File.php" />
<install name="lib/Horde/Kolab/Filter/Transport.php" as="Horde/Kolab/Filter/Transport.php" />
<install name="lib/Horde/Kolab/Filter/Transport/DovecotLDA.php" as="Horde/Kolab/Filter/Transport/DovecotLDA.php" />
<install name="lib/Horde/Kolab/Filter/Transport/drop.php" as="Horde/Kolab/Filter/Transport/drop.php" />
<?php
/**
- * All tests for the Kolab_Storage:: package.
+ * All tests for the Kolab_Filter:: package.
*
* PHP version 5
*
* @category Kolab
- * @package Kolab_Storage
+ * @package Kolab_Filter
* @subpackage UnitTests
* @author Gunnar Wrobel <wrobel@pardus.de>
* @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');
}
/**
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.
*/
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);
}
}
}
-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();
}
/** Load the basic test definition */
require_once dirname(__FILE__) . '/StoryTestCase.php';
+
+/** Load the test helpers */
+require_once dirname(__FILE__) . '/Helper/AddressFilter.php';
+++ /dev/null
-<?php
-/**
- * Test the content filter class within the Kolab filter implementation.
- *
- * @package Horde_Kolab_Filter
- */
-
-/**
- * We need the unit test framework
- */
-require_once 'Horde/Kolab/Test/Filter.php';
-
-require_once 'Horde.php';
-require_once 'Horde/Kolab/Filter/Content.php';
-
-/**
- * Test the content filter.
- *
- * 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.
- *
- * @author Gunnar Wrobel <wrobel@pardus.de>
- * @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));
- }
-
-}
--- /dev/null
+<?php
+/**
+ * Test the content filter class within the Kolab filter implementation.
+ *
+ * @package Horde_Kolab_Filter
+ */
+
+/**
+ * We need the unit test framework
+ */
+require_once 'Horde/Kolab/Test/Filter.php';
+
+require_once 'Horde.php';
+require_once 'Horde/Kolab/Filter/Content.php';
+
+/**
+ * Test the content filter.
+ *
+ * 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.
+ *
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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));
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Rewrites address information in a mail template.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_Filter
+ * @subpackage UnitTests
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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;
+ }
+}
+++ /dev/null
-<?php
-/**
- * Test the incoming filter class within the Kolab filter implementation.
- *
- * @package Horde_Kolab_Filter
- */
-
-/**
- * We need the base class
- */
-require_once 'Horde/Kolab/Test/Filter.php';
-
-/**
- * We need the unit test framework
- */
-require_once 'PHPUnit/Extensions/OutputTestCase.php';
-
-require_once 'Horde.php';
-require_once 'Horde/Kolab/Filter/Incoming.php';
-
-/**
- * Test the incoming filter.
- *
- * 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.
- *
- * @author Gunnar Wrobel <wrobel@pardus.de>
- * @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);
- }
-}
* @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.',
$_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',
--- /dev/null
+<?php
+/**
+ * Test the incoming filter.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_Filter
+ * @subpackage UnitTests
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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');
+ }
+}
+++ /dev/null
-<?php
-/**
- * Test the incoming filter class for its load behaviour..
- *
- * @package Horde_Kolab_Filter
- */
-
-/**
- * We need the unit test framework
- */
-require_once 'PHPUnit/Framework.php';
-require_once 'PHPUnit/Extensions/PerformanceTestCase.php';
-
-require_once 'Horde.php';
-require_once 'Horde/Kolab/Filter/Incoming.php';
-
-/**
- * Test the incoming filter load.
- *
- * 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.
- *
- * @author Gunnar Wrobel <wrobel@pardus.de>
- * @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);
- }
-}
+++ /dev/null
-<?php
-/**
- * Test resource handling within the Kolab filter implementation.
- *
- * @package Horde_Kolab_Filter
- */
-
-/**
- * We need the base class
- */
-require_once 'Horde/Kolab/Test/Filter.php';
-
-require_once 'Horde.php';
-require_once 'Horde/Kolab/Resource.php';
-require_once 'Horde/Kolab/Filter/Incoming.php';
-require_once 'Horde/Icalendar.php';
-require_once 'Horde/Icalendar/Vfreebusy.php';
-
-/**
- * Test resource handling
- *
- * 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.
- *
- * @author Gunnar Wrobel <wrobel@pardus.de>
- * @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);
- }
-
-}
--- /dev/null
+<?php
+/**
+ * Test resource handling within the Kolab filter implementation.
+ *
+ * @package Horde_Kolab_Filter
+ */
+
+/**
+ * We need the base class
+ */
+require_once 'Horde/Kolab/Test/Filter.php';
+
+require_once 'Horde.php';
+require_once 'Horde/Kolab/Resource.php';
+require_once 'Horde/Kolab/Filter/Incoming.php';
+require_once 'Horde/Icalendar.php';
+require_once 'Horde/Icalendar/Vfreebusy.php';
+
+/**
+ * Test resource handling
+ *
+ * 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.
+ *
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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);
+ }
+
+}
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);
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);
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
--- /dev/null
+<?php
+/**
+ * Test the address rewriting filter.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package Kolab_Filter
+ * @subpackage UnitTests
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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