diff --git a/config/hooks.php.dist b/config/hooks.php.dist index aae13e4e..8a179179 100644 --- a/config/hooks.php.dist +++ b/config/hooks.php.dist @@ -51,6 +51,29 @@ class Ingo_Hooks // return true; // } + /** + * A hook to override the transport params based on the driver and the current params + * @param string $driver The driver name (array key from backends.php). + * @param array $currentParams The currently used params + * + * @return array|null The params that should be overriden for this transport driver. + * If the return value is not an array nothing will be overriden. + */ +// public function transport_params($driver, $currentParams) +// { +// // in this example we use a different sieve server for certain users based on the domin in their username +// // we also increase the port by one. This might not be a very realistic example, but it shows that you are very flexible with this hook +// $params = []; +// switch ($driver) { +// case 'timsieved': +// $userDomain = $GLOBALS['registry']->getAuth('domain'); +// if ($userDomain === 'new-server.localhost') { +// $params['hostspec'] = 'mail.new-server.localhost'; +// $params['port'] = $currentParams['port'] + 1; +// } +// } +// return $params; +// } /** * Set the default addresses used for the vacation module. diff --git a/lib/Application.php b/lib/Application.php index 1648c129..cfe1fb61 100644 --- a/lib/Application.php +++ b/lib/Application.php @@ -49,7 +49,7 @@ class Ingo_Application extends Horde_Registry_Application /** */ - public $version = 'H5 (4.0.0alpha7)'; + public $version = 'H6 (4.0.0alpha7)'; /** * Cached list of all rulesets. diff --git a/lib/Factory/Transport.php b/lib/Factory/Transport.php index 024097ec..12550ece 100644 --- a/lib/Factory/Transport.php +++ b/lib/Factory/Transport.php @@ -35,16 +35,19 @@ public function create(array $transport) { global $registry; + $coreHooks = $GLOBALS['injector']->getInstance('Horde_Core_Hooks'); + $transportDriver = $transport['driver']; + $transportParams = $transport['params']; + /* Get authentication parameters. */ try { - $auth = $GLOBALS['injector']->getInstance('Horde_Core_Hooks') - ->callHook('transport_auth', 'ingo', array($transport['driver'])); + $auth = $coreHooks->callHook('transport_auth', 'ingo', [$transportDriver]); } catch (Horde_Exception_HookNotSet $e) { $auth = null; } if (!is_array($auth)) { - $auth = array(); + $auth = []; } if (!isset($auth['password'])) { @@ -57,9 +60,19 @@ public function create(array $transport) $auth['euser'] = Ingo::getUser(false); } - $class = 'Ingo_Transport_' . ucfirst($transport['driver']); + // Get transport parameters. + try { + $customParams = $coreHooks->callHook('transport_params', 'ingo', [$transportDriver, $transportParams]); + } catch (Horde_Exception_HookNotSet $e) { + $customParams = null; + } + if (is_array($customParams)){ + $transportParams = array_merge($transportParams, $customParams); + } + + $class = 'Ingo_Transport_' . ucfirst($transportDriver); if (class_exists($class)) { - return new $class(array_merge($auth, $transport['params'])); + return new $class(array_merge($auth, $transportParams)); } throw new Ingo_Exception(sprintf(_("Unable to load the transport driver \"%s\"."), $class)); diff --git a/lib/Transport/Sieveconnect.php b/lib/Transport/Sieveconnect.php new file mode 100644 index 00000000..acc54268 --- /dev/null +++ b/lib/Transport/Sieveconnect.php @@ -0,0 +1,115 @@ + + * @category Horde + * @license http://www.horde.org/licenses/apache ASL + * @package Ingo + */ + +/** + * Ingo_Transport_Sieveconnect implements an Ingo transport driver to + * delegate ManageSieve connections to an external sieve-connect script + * + * @author Mike Cochrane + * @author Jan Schneider + * @category Horde + * @license http://www.horde.org/licenses/apache ASL + * @package Ingo + */ +class Ingo_Transport_Sieveconnect extends Ingo_Transport_Base +{ + /** + */ + protected $_supportShares = true; + + /** + * Constructor. + */ + public function __construct(array $params = array()) + { + parent::__construct(array_merge(array( + 'admin' => '', + 'debug' => false, + 'euser' => '', + 'hostspec' => 'localhost', + 'logintype' => 'PLAIN', + 'port' => 4190, + 'scriptname' => 'ingo', + 'usetls' => true, + 'script' => '/usr/bin/sieve-connect', + 'tmpdir' => $GLOBALS['conf']['tmpdir'] + ), $params)); + } + + /** + * Sets a script running on the backend. + * + * @param array $script The filter script information. Passed elements: + * - 'name': (string) the script name. + * - 'recipes': (array) the filter recipe objects. + * - 'script': (string) the filter script. + * + * @throws Ingo_Exception + */ + public function setScriptActive($script) + { + $scriptFile = $this->_params['tmpdir'] . '/transport' . md5($this->_params['username'] . $script['name']); + file_put_contents($scriptFile, $script['script']); + $cmd = sprintf("echo '%s' | %s -s %s -p %s -u %s --upload --localsieve %s --remotesieve %s ; echo '%s' | %s -s %s -p %s -u %s --activate --remotesieve %s", + $this->_params['password'], + $this->_params['script'], + $this->_params['hostspec'], + $this->_params['port'], + $this->_params['username'], + $scriptFile, + $script['name'], + $this->_params['password'], + $this->_params['script'], + $this->_params['hostspec'], + $this->_params['port'], + $this->_params['username'], + $script['name'] + ); + if (!empty($this->_params['debug'])) { + file_put_contents($scriptFile . 'debug', $cmd); + } + shell_exec($cmd); + unlink($scriptFile); + } + + /** + * Returns the content of the currently active script. + * + * @return array Keys 'name' (string) the active script, 'script' (string) The complete ruleset of the specified user. + * @throws Ingo_Exception + * @throws Horde_Exception_NotFound + */ + public function getScript() + { + $cmdList = sprintf("echo '%s' | %s -s %s -p %s -u %s --list | grep ACTIVE", + $this->_params['password'], + $this->_params['script'], + $this->_params['hostspec'], + $this->_params['port'], + $this->_params['username'] + ); + $files = shell_exec($cmdList); + list(, $name,) = explode('"', $files, 3); + $cmdDownload = sprintf("echo '%s' | %s -s %s -p %s -u %s --download --localsieve - --remotesieve %s", + $this->_params['password'], + $this->_params['script'], + $this->_params['hostspec'], + $this->_params['port'], + $this->_params['username'], + $name + ); + $rules = shell_exec($cmdDownload); + + return array('name' => $name, 'script' => $rules); + } +} diff --git a/lib/Transport/Timsieved.php b/lib/Transport/Timsieved.php index e8186817..124a6727 100644 --- a/lib/Transport/Timsieved.php +++ b/lib/Transport/Timsieved.php @@ -125,7 +125,7 @@ public function setScriptActive($script) /** * Returns the content of the currently active script. * - * @return string The complete ruleset of the specified user. + * @return array Keys 'name' (string) the active script, 'script' (string) The complete ruleset of the specified user. * @throws Ingo_Exception * @throws Horde_Exception_NotFound */ diff --git a/lib/Transport/Vfs.php b/lib/Transport/Vfs.php index 1ff15ef8..12d8308d 100644 --- a/lib/Transport/Vfs.php +++ b/lib/Transport/Vfs.php @@ -112,8 +112,8 @@ protected function _connect() /* Do variable substitution. */ if (!empty($this->_params['vfs_path'])) { $this->_params['vfs_path'] = str_replace( - array('%u', '%d', '%U', '%u_full'), - array(Ingo::getUser(), Ingo::getDomain(), $this->_params['username'], Ingo::getUser(true)), + array('%u_full', '%u', '%d', '%U'), + array(Ingo::getUser(true), Ingo::getUser(), Ingo::getDomain(), $this->_params['username']), $this->_params['vfs_path']); }