171 lines
5.1 KiB
PHP
171 lines
5.1 KiB
PHP
<?php
|
|
/**
|
|
* Copyright 2003-2017 Horde LLC (http://www.horde.org/)
|
|
* Copyright 2004-2007 Liam Hoekenga <liamr@umich.edu>
|
|
*
|
|
* See the enclosed file LICENSE for license information (ASL). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/apache.
|
|
*
|
|
* @author Jan Schneider <jan@horde.org>
|
|
* @author Liam Hoekenga <liamr@umich.edu>
|
|
* @category Horde
|
|
* @license http://www.horde.org/licenses/apache ASL
|
|
* @package Ingo
|
|
*/
|
|
|
|
/**
|
|
* Ingo_Transport_Sivtest implements an Ingo transport driver to allow scripts
|
|
* to be installed and set active via the Cyrus sivtest command line utility.
|
|
*
|
|
* @author Jan Schneider <jan@horde.org>
|
|
* @author Liam Hoekenga <liamr@umich.edu>
|
|
* @category Horde
|
|
* @license http://www.horde.org/licenses/apache ASL
|
|
* @package Ingo
|
|
*/
|
|
class Ingo_Transport_Sivtest extends Ingo_Transport_Timsieved
|
|
{
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
public function __construct(array $params = array())
|
|
{
|
|
$default_params = array(
|
|
'hostspec' => 'localhost',
|
|
'logintype' => '',
|
|
'port' => 4190,
|
|
'scriptname' => 'ingo',
|
|
'admin' => '',
|
|
'usetls' => true,
|
|
'command' => '',
|
|
'socket' => '',
|
|
);
|
|
|
|
$this->_supportShares = false;
|
|
|
|
parent::__construct(array_merge($default_params, $params));
|
|
}
|
|
|
|
/**
|
|
* Connect to the sieve server.
|
|
*
|
|
* @throws Ingo_Exception;
|
|
*/
|
|
protected function _connect()
|
|
{
|
|
if (!empty($this->_sieve)) {
|
|
return;
|
|
}
|
|
|
|
$this->sivtestSocket(
|
|
$this->_params['username'],
|
|
$this->_params['password'],
|
|
$this->_params['hostspec']);
|
|
|
|
$this->_sieve = new Net_Sieve(
|
|
$this->_params['username'],
|
|
$this->_params['password'],
|
|
'unix://' . $this->_params['socket'],
|
|
0,
|
|
null,
|
|
null,
|
|
false,
|
|
true,
|
|
$this->_params['usetls']);
|
|
|
|
$res = $this->_sieve->getError();
|
|
if ($res instanceof PEAR_Error) {
|
|
unset($this->_sieve);
|
|
throw new Ingo_Exception($res);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Used to figure out which Sieve server the script will be run
|
|
* on, and then open a GSSAPI authenticated socket to said server.
|
|
*
|
|
* @param string $username The username.
|
|
* @param string $password The password.
|
|
* @param string $hostspec The hostspec.
|
|
*
|
|
* @return TODO
|
|
* @throws Ingo_Exception
|
|
*/
|
|
public function sivtestSocket($username, $password, $hostspec)
|
|
{
|
|
$command = '';
|
|
$error_return = '';
|
|
|
|
if (strtolower($this->_params['logintype']) == 'gssapi' &&
|
|
isset($_SERVER['KRB5CCNAME'])) {
|
|
$command .= 'KRB5CCNAME=' . $_SERVER['KRB5CCNAME'];
|
|
}
|
|
|
|
$domain_socket = 'unix://' . $this->_params['socket'];
|
|
|
|
$command .= ' ' . $this->_params['command']
|
|
. ' -m ' . $this->_params['logintype']
|
|
. ' -u ' . $username
|
|
. ' -a ' . $username
|
|
. ' -w ' . $password
|
|
. ' -p ' . $this->_params['port']
|
|
. ' -X ' . $this->_params['socket']
|
|
. ' ' . $hostspec;
|
|
|
|
$conn_attempts = 0;
|
|
while ($conn_attempts++ < 4) {
|
|
$attempts = 0;
|
|
if (!file_exists($this->_params['socket'])) {
|
|
exec($command . ' > /dev/null 2>&1');
|
|
sleep(1);
|
|
while (!file_exists($this->_params['socket'])) {
|
|
usleep(200000);
|
|
if ($attempts++ > 5) {
|
|
$error_return = ': No socket after 10 seconds of trying!';
|
|
continue 2;
|
|
}
|
|
}
|
|
}
|
|
$socket = new Net_Socket();
|
|
$error = $socket->connect($domain_socket, 0, true, 30);
|
|
if (!($error instanceof PEAR_Error)) {
|
|
break;
|
|
}
|
|
|
|
// We failed, break this connection.
|
|
unlink($this->_params['socket']);
|
|
}
|
|
|
|
if (!empty($error_return)) {
|
|
throw new Ingo_Exception($error_return);
|
|
}
|
|
|
|
$status = $socket->getStatus();
|
|
if ($status instanceof PEAR_Error || $status['eof']) {
|
|
throw new Ingo_Exception(_("Failed to write to socket: (connection lost!)"));
|
|
}
|
|
|
|
$error = $socket->writeLine("CAPABILITY");
|
|
if ($error instanceof PEAR_Error) {
|
|
throw new Ingo_Exception(_("Failed to write to socket: " . $error->getMessage()));
|
|
}
|
|
|
|
$result = $socket->readLine();
|
|
if ($result instanceof PEAR_Error) {
|
|
throw new Ingo_Exception(_("Failed to read from socket: " . $error->getMessage()));
|
|
}
|
|
|
|
if (preg_match('|^bye \(referral "(sieve://)?([^"]+)|i',
|
|
$result, $matches)) {
|
|
$socket->disconnect();
|
|
|
|
$this->sivtestSocket($username, $password, $matches[2]);
|
|
} else {
|
|
$socket->disconnect();
|
|
exec($command . ' > /dev/null 2>&1');
|
|
sleep(1);
|
|
}
|
|
}
|
|
|
|
}
|