From: Gunnar Wrobel Date: Mon, 2 Mar 2009 07:06:50 +0000 (+0000) Subject: Split of Kolab_Session from Kolab_Server. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=c226cce87289e30492c895906eb3d127c66adb8c;p=horde.git Split of Kolab_Session from Kolab_Server. --- diff --git a/framework/Kolab_Server/lib/Horde/Kolab/IMAP.php b/framework/Kolab_Server/lib/Horde/Kolab/IMAP.php deleted file mode 100644 index 23e47f12c..000000000 --- a/framework/Kolab_Server/lib/Horde/Kolab/IMAP.php +++ /dev/null @@ -1,138 +0,0 @@ - - * @author Thomas Jarosch - * @package Kolab_Storage - */ -class Horde_Kolab_IMAP -{ - - /** - * IMAP server to connect to. - * - * @var string - */ - var $_server; - - /** - * IMAP server port to connect to. - * - * @var int - */ - var $_port; - - /** - * IMAP connection. - * - * @var mixed - */ - var $_imap; - - /** - * Connection reuse detection signature. - * - * @var string - */ - var $_reuse_detection; - - /** - * Constructor. - * - * @param string $server Server to connect to - * @param int $port Port to connect to - */ - function Horde_Kolab_IMAP($server, $port) - { - $this->_server = $server; - $this->_port = $port; - } - - /** - * Attempts to return a reference to a concrete Horde_Kolab_IMAP instance. - * It will only create a new instance if no Horde_Kolab_IMAP instance - * exists. - * - * @static - * - * @param string $server Server name - * @param int $port Port - * @param boolean $annotation_required Do we actually need - * the annotation calls? - * - * @return Horde_Kolab_IMAP|PEAR_Error The concrete reference. - */ - function &singleton($server, $port, $annotation_required = true) - { - static $instances = array(); - - /** - * There are Kolab specific PHP functions available that make the IMAP - * access more efficient. If these are detected, or if they are not - * required for the current operation, the PHP IMAP implementation - * should be used. - * - * The c-client Kolab driver provides quicker IMAP routines so is - * preferable whenever possible. - */ - if ($annotation_required) { - if (function_exists('imap_status_current') - && function_exists('imap_getannotation')) { - $driver = 'cclient'; - } else { - $driver = 'pear'; - } - } else { - $driver = 'cclient'; - } - - if (isset($GLOBALS['KOLAB_TESTING'])) { - $driver = 'test'; - } - - $signature = "$server|$port|$driver"; - if (!isset($instances[$signature])) { - $instances[$signature] = &Horde_Kolab_IMAP::factory($server, $port, $driver); - } - - return $instances[$signature]; - } - - /** - * Attempts to return a concrete Horde_Kolab_IMAP instance based on the - * available PHP functionality. - * - * @param string $server Server name. - * @param int $port Server port. - * @param string $driver Which driver should we use? - * - * @return Horde_Kolab_IMAP|PEAR_Error The newly created concrete - * Horde_Kolab_IMAP instance. - */ - function &factory($server, $port, $driver = 'cclient') - { - @include_once dirname(__FILE__) . '/IMAP/' . $driver . '.php'; - - $class = 'Horde_Kolab_IMAP_' . $driver; - if (class_exists($class)) { - $driver = &new $class($server, $port); - } else { - return PEAR::raiseError(sprintf(_("Failed to load Kolab IMAP driver %s"), $driver)); - } - - return $driver; - } -} diff --git a/framework/Kolab_Server/lib/Horde/Kolab/IMAP/cclient.php b/framework/Kolab_Server/lib/Horde/Kolab/IMAP/cclient.php deleted file mode 100644 index cab23898a..000000000 --- a/framework/Kolab_Server/lib/Horde/Kolab/IMAP/cclient.php +++ /dev/null @@ -1,777 +0,0 @@ - - * @author Thomas Jarosch - * @package Kolab_Storage - */ -class Horde_Kolab_IMAP_cclient extends Horde_Kolab_IMAP -{ - - /** - * Basic IMAP connection string. - * - * @var string - */ - var $_base_mbox; - - /** - * IMAP connection string that includes the folder. - * - * @var string - */ - var $_mbox; - - /** - * The signature of the current connection. - * - * @var string - */ - var $_signature; - - /** - * IMAP user name. - * - * @var string - */ - var $_login; - - /** - * IMAP password. - * - * @var string - */ - var $_password; - - /** - * Connects to the IMAP server. - * - * @param string $login The user account name. - * @param string $password The user password. - * @param boolean $tls Should TLS be used for the connection? - * - * @return boolean|PEAR_Error True in case the connection was opened - * successfully. - */ - function connect($login, $password, $tls = false) - { - $options = ''; - if (!$tls) { - $options = '/notls'; - } - - $mbox = '{' . $this->_server . ':' . $this->_port - . $options . '}'; - - $this->_signature = "$mbox|$login|$password"; - if ($this->_signature == $this->_reuse_detection) { - return true; - } - - $this->_mbox = $this->_base_mbox = $mbox; - $this->_login = $login; - $this->_password = $password; - $this->_imap = null; - - $this->_reuse_detection = $this->_signature; - - return true; - } - - /** - * Lazy connect to the IMAP server. - * - * @return mixed True in case the connection was opened successfully, a - * PEAR error otherwise. - */ - function _connect() - { - $result = @imap_open($this->_base_mbox, $this->_login, $this->_password, OP_HALFOPEN); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Server: %s. Error: %s"), $this->_server, @imap_last_error())); - } - $this->_imap = $result; - return true; - } - - /** - * Disconnects from the IMAP server. If not really necessary this - * should not be called. Once the page got served the connections - * should be closed anyhow and if there is a chance to reuse the - * connection it should be used. - * - * @return mixed True in case the connection was closed successfully, a - * PEAR error otherwise. - */ - function disconnect() - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $this->_reuse_detection = null; - - $result = @imap_close($this->_imap); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Server: %s. Error: %s"), $this->_server, @imap_last_error())); - } - return $result; - } - - /** - * Opens the given folder. - * - * @param string $folder The folder to open. - * - * @return mixed True in case the folder was opened successfully, a PEAR - * error otherwise. - */ - function select($folder) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $this->_mbox = $this->_base_mbox . $folder; - - $result = @imap_reopen($this->_imap, $this->_mbox); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); - } - return $result; - } - - /** - * Does the given folder exist? - * - * @param string $folder The folder to check. - * - * @return mixed True in case the folder exists, false otherwise - */ - function exists($folder) - { - $folders = $this->getMailboxes(); - if (is_a($folders, 'PEAR_Error')) { - return $folders; - } - return in_array($folder, $folders); - } - - /** - * Create the specified folder. - * - * @param string $folder The folder to create. - * - * @return mixed True in case the operation was successfull, a - * PEAR error otherwise. - */ - function create($folder) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $mbox = $this->_base_mbox . $folder; - $result = @imap_createmailbox($this->_imap, $mbox); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); - } - return $result; - } - - /** - * Delete the specified folder. - * - * @param string $folder The folder to delete. - * - * @return mixed True in case the operation was successfull, a - * PEAR error otherwise. - */ - function delete($folder) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $mbox = $this->_base_mbox . $folder; - $result = @imap_deletemailbox($this->_imap, $mbox); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); - } - return $result; - } - - /** - * Rename the specified folder. - * - * @param string $old The folder to rename. - * @param string $new The new name of the folder. - * - * @return mixed True in case the operation was successfull, a - * PEAR error otherwise. - */ - function rename($old, $new) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $result = @imap_renamemailbox($this->_imap, - $this->_base_mbox . $old, - $this->_base_mbox . $new); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $old, @imap_last_error())); - } - return $result; - } - - /** - * Returns the status of the current folder. - * - * @return array An array that contains 'uidvalidity' and 'uidnext'. - */ - function status() - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $status = @imap_status_current($this->_imap, SA_MESSAGES | SA_UIDVALIDITY | SA_UIDNEXT); - if (!$status) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $this->_mbox, @imap_last_error())); - } - - return array('uidvalidity' => $status->uidvalidity, - 'uidnext' => $status->uidnext); - } - - /** - * Returns the uids of the messages in this folder. - * - * @return mixed The message ids or a PEAR error in case of an error. - */ - function getUids() - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $uids = @imap_search($this->_imap, 'UNDELETED', SE_UID); - if (!is_array($uids)) { - $uids = array(); - } - - return $uids; - } - - /** - * Searches the current folder using the given list of search criteria. - * - * @param string $search_list A list of search criteria. - * - * @return mixed The list of matching message ids or a PEAR error in case - * of an error. - */ - function search($search_list) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $result = @imap_search($this->_imap, $search_list, SE_UID); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $this->_mbox, @imap_last_error())); - } - return $result; - } - - /** - * Searches the headers of the messages. c-client does not allow using - * "HEADER" as it is possible with Net/IMAP, so we need a workaround. - * - * @param string $field The name of the header field. - * @param string $value The value that field should match. - * - * @return mixed The list of matching message ids or a PEAR error in case - * of an error. - */ - function searchHeaders($field, $value) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $uids = $this->getUids(); - if (is_a($uids, 'PEAR_Error')) { - return $uids; - } - - $result = array(); - foreach ($uids as $uid) { - $header = $this->getMessageHeader($uid, false); - if (is_a($header, 'PEAR_Error')) { - return $header; - } - $header_array = MIME_Headers::parseHeaders($header); - if (isset($header_array[$field]) && $header_array[$field] == $value) { - $result[] = $uid; - } - } - - return $result; - } - - /** - * Retrieves the message headers for a given message id. - * - * @param integer $uid The message id. - * @param boolean $peek_for_body Prefetch the body. - * - * @return mixed The message header or a PEAR error in case of an error. - */ - function getMessageHeader($uid, $peek_for_body = true) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $flags = FT_UID; - if ($peek_for_body) { - $flags |= FT_PREFETCHTEXT; - } - - $result = @imap_fetchheader($this->_imap, $uid, $flags); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), $uid, @imap_last_error())); - } - - return $result; - } - - /** - * Retrieves the message body for a given message id. - * - * @param integer $uid The message id. - * - * @return mixed The message body or a PEAR error in case of an error. - */ - function getMessageBody($uid) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $result = @imap_body($this->_imap, $uid, FT_UID); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), $uid, @imap_last_error())); - } - - return $result; - } - - /** - * Retrieves the full message text for a given message id. - * - * @param integer $uid The message id. - * - * @return mixed The message text or a PEAR error in case of an error. - */ - function getMessage($uid) - { - $header = $this->getMessageHeader($uid); - if (is_a($header, 'PEAR_Error')) { - return $header; - } - - $body = $this->getMessageBody($uid); - if (is_a($body, 'PEAR_Error')) { - return $body; - } - - return $header . $body; - } - - /** - * Retrieves a list of mailboxes on the server. - * - * @return mixed The list of mailboxes or a PEAR error in case of an - * error. - */ - function getMailboxes() - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $folders = array(); - - $result = @imap_list($this->_imap, $this->_base_mbox, '*'); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $this->_base_mbox, @imap_last_error())); - } - - $server_len = strlen($this->_base_mbox); - foreach ($result as $folder) { - if (substr($folder, 0, $server_len) == $this->_base_mbox) { - $folders[] = substr($folder, $server_len); - } - } - - return $folders; - } - - /** - * Fetches the annotation on a folder. - * - * @param string $entries The entry to fetch. - * @param string $value The specific value to fetch. - * @param string $mailbox_name The name of the folder. - * - * @return mixed The annotation value or a PEAR error in case of an error. - */ - function getAnnotation($entries, $value, $mailbox_name) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - static $annotations = array(); - - $signature = "$this->_signature|$entries|$value|$mailbox_name"; - - if (!isset($annotations[$signature])) { - $result = @imap_getannotation($this->_imap, $mailbox_name, $entries, $value); - if (isset($result[$value])) { - $annotations[$signature] = $result[$value]; - } else { - $annotations[$signature] = ''; - } - } - - return $annotations[$signature]; - } - - /** - * Sets the annotation on a folder. - * - * @param string $entries The entry to set. - * @param array $values The values to set - * @param string $mailbox_name The name of the folder. - * - * @return mixed True if successfull, a PEAR error otherwise. - */ - function setAnnotation($entries, $values, $mailbox_name) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - foreach ($values as $key => $value) { - $result = @imap_setannotation($this->_imap, $mailbox_name, $entries, $key, $value); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $mailbox_name, @imap_last_error())); - } - } - return true; - } - - /** - * Retrieve the access rights from a folder - * - * @param string $folder The folder to retrieve the ACLs from. - * - * @return mixed An array of rights if successfull, a PEAR error - * otherwise. - */ - function getACL($folder) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $result = @imap_getacl($this->_imap, $folder); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); - } - return $result; - } - - /** - * Retrieve the access rights from a folder not owned by the current user - * - * @param string $folder The folder to retrieve the ACLs from. - * - * @return mixed An array of rights if successfull, a PEAR error - * otherwise. - */ - function getMyRights($folder) - { - if (!function_exists('imap_myrights')) { - return PEAR::raiseError(sprintf(_("PHP does not support imap_myrights."), $folder, @imap_last_error())); - } - - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $result = @imap_myrights($this->_imap, $folder); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); - } - return $result; - - } - - /** - * Set the access rights for a folder - * - * @param string $folder The folder to retrieve the ACLs from. - * @param string $user The user to set the ACLs for - * @param string $acl The ACLs - * - * @return mixed True if successfull, a PEAR error otherwise. - */ - function setACL($folder, $user, $acl) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $result = @imap_setacl($this->_imap, $folder, $user, $acl); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); - } - return $result; - } - - /** - * Delete the access rights for a user. - * - * @param string $folder The folder that should be modified. - * @param string $user The user that should get the ACLs removed - * - * @return mixed True if successfull, a PEAR error otherwise. - */ - function deleteACL($folder, $user) - { - return $this->setACL($folder, $user, ''); - } - - /** - * Appends a message to the current folder. - * - * @param string $msg The message to append. - * - * @return mixed True or a PEAR error in case of an error. - */ - function appendMessage($msg) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $result = @imap_append($this->_imap, $this->_mbox, $msg); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $this->_mbox, @imap_last_error())); - } - return $result; - } - - /** - * Copies a message to a new folder. - * - * @param integer $uid IMAP message id. - * @param string $new_folder Target folder. - * - * @return mixed True or a PEAR error in case of an error. - */ - function copyMessage($uid, $new_folder) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $result = @imap_mail_copy($this->_imap, $uid, $new_folder, CP_UID); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $new_folder, @imap_last_error())); - } - return $result; - } - - /** - * Moves a message to a new folder. - * - * @param integer $uid IMAP message id. - * @param string $new_folder Target folder. - * - * @return mixed True or a PEAR error in case of an error. - */ - function moveMessage($uid, $new_folder) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $result = @imap_mail_move($this->_imap, $uid, $new_folder, CP_UID); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $new_folder, @imap_last_error())); - } - return $result; - } - - /** - * Deletes messages from the current folder. - * - * @param integer $uids IMAP message ids. - * - * @return mixed True or a PEAR error in case of an error. - */ - function deleteMessages($uids) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - if (!is_array($uids)) { - $uids = array($uids); - } - - foreach($uids as $uid) { - $result = @imap_delete($this->_imap, $uid, FT_UID); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), $uid, @imap_last_error())); - } - } - return true; - } - - /** - * Undeletes a message in the current folder. - * - * @param integer $uid IMAP message id. - * - * @return mixed True or a PEAR error in case of an error. - */ - function undeleteMessages($uid) - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $result = @imap_undelete($this->_imap, $uid, FT_UID); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), $uid, @imap_last_error())); - } - return $result; - } - - /** - * Expunges messages in the current folder. - * - * @return mixed True or a PEAR error in case of an error. - */ - function expunge() - { - if (!isset($this->_imap)) { - $result = $this->_connect(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - - $result = @imap_expunge($this->_imap); - if (!$result) { - return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), $this->_mbox, @imap_last_error())); - } - return $result; - } - - /** - * Return the currently selected mailbox - * - * @return string The mailbox currently selected - */ - function current() - { - return $this->_mbox; - } -} diff --git a/framework/Kolab_Server/lib/Horde/Kolab/IMAP/pear.php b/framework/Kolab_Server/lib/Horde/Kolab/IMAP/pear.php deleted file mode 100644 index dbb71811a..000000000 --- a/framework/Kolab_Server/lib/Horde/Kolab/IMAP/pear.php +++ /dev/null @@ -1,519 +0,0 @@ -= 1.0.3 of Net_IMAP (i.e. a - * version that includes support for the ANNOTATEMORE IMAP extension). The - * latest version of Net_IMAP can be obtained from - * http://pear.php.net/get/Net_IMAP - */ -require_once 'Net/IMAP.php'; - -/** - * The Horde_Kolab_IMAP_Connection_pear class connects to an IMAP server using the - * Net_IMAP PEAR package. - * - * - * Copyright 2007-2009 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.fsf.org/copyleft/lgpl.html. - * - * @author Gunnar Wrobel - * @author Thomas Jarosch - * @package Kolab_Storage - */ -class Horde_Kolab_IMAP_pear extends Horde_Kolab_IMAP -{ - - /** - * The signature of the current connection - * - * @var string - */ - var $_signature; - - /** - * Connects to the IMAP server. - * - * @param string $login The user account name. - * @param string $password The user password. - * @param boolean $tls Should TLS be used for the connection? - * - * @return mixed True in case the connection was opened successfully, a - * PEAR error otherwise. - */ - function connect($login, $password, $tls = false) - { - $this->_signature = $this->_server . '|' . $this->_port . "|$login|$password|$tls"; - - // Reuse existing connection? - if ($this->_signature == $this->_reuse_detection) { - return true; - } - - $this->_imap = &new Net_IMAP($this->_server, $this->_port); - $result = $this->_imap->login($login, $password, true, false); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - $this->_reuse_detection = $this->_signature; - - return true; - } - - /** - * Disconnects from the IMAP server. - * - * @return mixed True in case the connection was closed successfully, a - * PEAR error otherwise. - */ - function disconnect() - { - $this->_reuse_detection = null; - return $this->_imap->disconnect(); - } - - /** - * Opens the given folder. - * - * @param string $folder The folder to open - * - * @return mixed True in case the folder was opened successfully, a PEAR - * error otherwise. - */ - function select($folder) - { - return $this->_imap->selectMailbox($folder); - } - - /** - * Does the given folder exist? - * - * @param string $folder The folder to check. - * - * @return mixed True in case the folder exists, false otherwise - */ - function exists($folder) - { - return $this->_imap->mailboxExist($folder); - } - - /** - * Create the specified folder. - * - * @param string $folder The folder to create. - * - * @return mixed True in case the operation was successfull, a - * PEAR error otherwise. - */ - function create($folder) - { - return $this->_imap->createMailbox($folder); - } - - /** - * Delete the specified folder. - * - * @param string $folder The folder to delete. - * - * @return mixed True in case the operation was successfull, a - * PEAR error otherwise. - */ - function delete($folder) - { - return $this->_imap->deleteMailbox($folder); - } - - /** - * Rename the specified folder. - * - * @param string $old The folder to rename. - * @param string $new The new name of the folder. - * - * @return mixed True in case the operation was successfull, a - * PEAR error otherwise. - */ - function rename($old, $new) - { - return $this->_imap->renameMailbox($old, $new); - } - - /** - * Returns the status of the current folder. - * - * @return array An array that contains 'uidvalidity' and 'uidnext'. - */ - function status() - { - $result = array(); - - $mailbox = $this->_imap->getCurrentMailbox(); - - // Net_IMAP is not very efficent here - $ret = $this->_imap->cmdStatus($mailbox, 'UIDVALIDITY'); - $result['uidvalidity'] = $ret['PARSED']['STATUS']['ATTRIBUTES']['UIDVALIDITY']; - - $ret = $this->_imap->cmdStatus($mailbox, 'UIDNEXT'); - $result['uidnext'] = $ret['PARSED']['STATUS']['ATTRIBUTES']['UIDNEXT']; - - return $result; - } - - /** - * Returns the message ids of the messages in this folder. - * - * @return array The message ids. - */ - function getUids() - { - $uids = $this->_imap->search('UNDELETED', true); - if (!is_array($uids)) { - $uids = array(); - } - return $uids; - } - - /** - * Searches the current folder using the given list of search criteria. - * - * @param string $search_list A list of search criteria. - * - * @return mixed The list of matching message ids or a PEAR error in case - * of an error. - */ - function search($search_list, $uidSearch = true) - { - return $this->_imap->search($search_list, $uidSearch); - } - - /** - * Searches the headers of the messages. - * - * @param string $field The name of the header field. - * @param string $value The value that field should match. - * - * @return mixed The list of matching message ids or a PEAR error in case - * of an error. - */ - function searchHeaders($field, $value) - { - return $this->_imap->search('HEADER "' . $field . '" "' . $value . '"', true); - } - - /** - * Retrieves the message headers for a given message id. - * - * @param int $uid The message id. - * @param boolean $peek_for_body Prefetch the body. - * - * @return mixed The message header or a PEAR error in case of an error. - */ - function getMessageHeader($uid, $peek_for_body = true) - { - $ret = $this->_imap->cmdUidFetch($uid, 'BODY[HEADER]'); - if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { - return PEAR::raiseError(sprintf(_("Failed fetching headers of IMAP message %s. Error was %s"), - $uid, - $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); - } - - if (isset($ret['PARSED'])) { - foreach ($ret['PARSED'] as $msg) { - if (isset($msg['EXT']['BODY[HEADER]']['CONTENT'])) { - return $msg['EXT']['BODY[HEADER]']['CONTENT']; - } - } - } - - return ''; - } - - /** - * Retrieves the message body for a given message id. - * - * @param integet $uid The message id. - * - * @return mixed The message body or a PEAR error in case of an error. - */ - function getMessageBody($uid) - { - $ret = $this->_imap->cmdUidFetch($uid, 'BODY[TEXT]'); - if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { - return PEAR::raiseError(sprintf(_("Failed fetching body of IMAP message %s. Error was %s"), - $uid, - $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); - } - - if (isset($ret['PARSED'])) { - foreach ($ret['PARSED'] as $msg) { - if (isset($msg['EXT']['BODY[TEXT]']['CONTENT'])) { - return $msg['EXT']['BODY[TEXT]']['CONTENT']; - } - } - } - - return ''; - } - - /** - * Retrieves the full message text for a given message id. - * - * @param integer $uid The message id. - * - * @return mixed The message text or a PEAR error in case of an error. - */ - function getMessage($uid) - { - $ret = $this->_imap->cmdUidFetch($uid, 'RFC822'); - if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { - return PEAR::raiseError(sprintf(_("Failed fetching IMAP message %s. Error was %s"), - $uid, - $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); - } - - if (isset($ret['PARSED'])) { - foreach ($ret['PARSED'] as $msg) { - if (isset($msg['EXT']['RFC822']['CONTENT'])) { - return $msg['EXT']['RFC822']['CONTENT']; - } - } - } - - return ''; - } - - /** - * Retrieves a list of mailboxes on the server. - * - * @return mixed The list of mailboxes or a PEAR error in case of an - * error. - */ - function getMailboxes() - { - return $this->_imap->getMailboxes(); - } - - /** - * Fetches the annotation on a folder. - * - * @param string $entries The entry to fetch. - * @param string $value The specific value to fetch. - * @param string $mailbox_name The name of the folder. - * - * @return mixed The annotation value or a PEAR error in case of an error. - */ - function getAnnotation($entries, $value, $mailbox_name) - { - static $annotations = array(); - - $signature = "$this->_signature|$entries|$value|$mailbox_name"; - - if (!isset($annotations[$signature])) { - $annotations[$signature] = $this->_imap->getAnnotation($entries, $value, $mailbox_name); - } - - return $annotations[$signature]; - } - - /** - * Sets the annotation on a folder. - * - * @param string $entries The entry to set. - * @param array $values The values to set - * @param string $mailbox_name The name of the folder. - * - * @return mixed True if successfull, a PEAR error otherwise. - */ - function setAnnotation($entries, $values, $mailbox_name) - { - return $this->_imap->setAnnotation($entries, $values, $mailbox_name); - } - - /** - * Retrieve the access rights from a folder - * - * @param string $folder The folder to retrieve the ACLs from. - * - * @return mixed An array of rights if successfull, a PEAR error - * otherwise. - */ - function getACL($folder) - { - $result = $this->_imap->getACL($folder); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - $acl = array(); - foreach ($result as $user) { - $acl[$user['USER']] = $user['RIGHTS']; - } - return $acl; - } - - /** - * Retrieve the access rights on a folder not owned by the current user - * - * @param string $folder The folder to retrieve the ACLs from. - * - * @return mixed An array of rights if successfull, a PEAR error - * otherwise. - */ - function getMyRights($folder) - { - $result = $this->_imap->getMyRights($folder); - return $result; - } - - /** - * Set the access rights for a folder - * - * @param string $folder The folder to retrieve the ACLs from. - * @param string $user The user to set the ACLs for - * @param string $acl The ACLs - * - * @return mixed True if successfull, a PEAR error otherwise. - */ - function setACL($folder, $user, $acl) - { - return $this->_imap->setACL($folder, $user, $acl); - } - - /** - * Delete the access rights for a user. - * - * @param string $folder The folder that should be modified. - * @param string $user The user that should get the ACLs removed - * - * @return mixed True if successfull, a PEAR error otherwise. - */ - function deleteACL($folder, $user) - { - return $this->_imap->deleteACL($folder, $user); - } - - /** - * Appends a message to the current folder. - * - * @param string $msg The message to append. - * - * @return mixed True or a PEAR error in case of an error. - */ - function appendMessage($msg) - { - return $this->_imap->appendMessage($msg); - } - - /** - * Copies a message to a new folder. - * - * @param integer $uid IMAP message id. - * @param string $new_folder Target folder. - * - * @return mixed True or a PEAR error in case of an error. - */ - function copyMessage($uid, $new_folder) - { - $ret = $this->_imap->cmdUidCopy($uid, $new_folder); - if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { - return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), - $uid, - $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); - } - return true; - } - - /** - * Moves a message to a new folder. - * - * @param integer $uid IMAP message id. - * @param string $new_folder Target folder. - * - * @return mixed True or a PEAR error in case of an error. - */ - function moveMessage($uid, $new_folder) - { - $result = $this->copyMessage($uid, $new_folder); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - $result = $this->deleteMessages($uid); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - $result = $this->expunge(); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - return true; - } - - /** - * Deletes messages from the current folder. - * - * @param integer $uids IMAP message ids. - * - * @return mixed True or a PEAR error in case of an error. - */ - function deleteMessages($uids) - { - if (!is_array($uids)) { - $uids = array($uids); - } - - foreach ($uids as $uid) { - $ret = $this->_imap->cmdUidStore($uid, '+FLAGS.SILENT', '\Deleted'); - if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { - return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), - $uid, - $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); - } - } - - return true; - } - - /** - * Undeletes a message in the current folder. - * - * @param integer $uid IMAP message id. - * - * @return mixed True or a PEAR error in case of an error. - */ - function undeleteMessages($uid) - { - $ret = $this->_imap->cmdUidStore($uid, '-FLAGS.SILENT', '\Deleted'); - if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { - return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), - $uid, - $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); - } - return true; - } - - /** - * Expunges messages in the current folder. - * - * @return mixed True or a PEAR error in case of an error. - */ - function expunge() - { - return $this->_imap->expunge(); - } - - /** - * Return the currently selected mailbox - * - * @return string The mailbox currently selected - */ - function current() - { - return $this->_imap->getCurrentMailbox(); - } -} diff --git a/framework/Kolab_Server/lib/Horde/Kolab/IMAP/test.php b/framework/Kolab_Server/lib/Horde/Kolab/IMAP/test.php deleted file mode 100644 index b95fe3968..000000000 --- a/framework/Kolab_Server/lib/Horde/Kolab/IMAP/test.php +++ /dev/null @@ -1,727 +0,0 @@ - - * @package Kolab_Storage - */ -class Horde_Kolab_IMAP_test extends Horde_Kolab_IMAP -{ - - /** - * If we are supposed to be connected this holds the user - * credentials and some connection details. - * - * @var string - */ - var $_connected; - - /** - * Login of the current user - * - * @var string - */ - var $_user; - - /** - * The data of the mailbox currently opened - * - * @var array - */ - var $_mbox = null; - - /** - * The name of the mailbox currently opened - * - * @var array - */ - var $_mboxname = null; - - /** - * Prepare the dummy server. - * - * @param string $login The user account name. - * @param string $password The user password. - * @param boolean $tls Should TLS be used for the connection? - * - * @return mixed True in case the connection was opened successfully, a - * PEAR error otherwise. - */ - function connect($login, $password, $tls = false) - { - if (!is_array($GLOBALS['KOLAB_TESTING'])) { - /* Simulate an empty IMAP server */ - $GLOBALS['KOLAB_TESTING'] = array(); - } - - $tls = ($tls) ? 'tls' : 'notls'; - $this->_connected = $login . ':' . $password . ':' . $tls; - $this->_user = $login; - $this->_mbox = null; - $this->_mboxname = null; - } - - /** - * Disconnects from the IMAP server. - * - * @return mixed True in case the connection was closed successfully, a - * PEAR error otherwise. - */ - function disconnect() - { - $this->_connected = null; - } - - function _parseFolder($folder) - { - if (substr($folder, 0, 5) == 'INBOX') { - $user = split('@', $this->_user); - return 'user/' . $user[0] . substr($folder, 5); - } - return $folder; - } - - /** - * Opens the given folder. - * - * @param string $folder The folder to open - * - * @return mixed True in case the folder was opened successfully, a PEAR - * error otherwise. - */ - function select($folder) - { - $folder = $this->_parseFolder($folder); - if (!isset($GLOBALS['KOLAB_TESTING'][$folder])) { - return PEAR::raiseError(sprintf("IMAP folder %s does not exist!", $folder)); - } - $this->_mbox = &$GLOBALS['KOLAB_TESTING'][$folder]; - $this->_mboxname = $folder; - return true; - } - - /** - * Does the given folder exist? - * - * @param string $folder The folder to check. - * - * @return mixed True in case the folder exists, false otherwise - */ - function exists($folder) - { - $folder = $this->_parseFolder($folder); - if (!isset($GLOBALS['KOLAB_TESTING'][$folder])) { - return false; - } - return true; - } - - /** - * Create the specified folder. - * - * @param string $folder The folder to create. - * - * @return mixed True in case the operation was successfull, a - * PEAR error otherwise. - */ - function create($folder) - { - $folder = $this->_parseFolder($folder); - if (isset($GLOBALS['KOLAB_TESTING'][$folder])) { - return PEAR::raiseError(sprintf("IMAP folder %s does already exist!", $folder)); - } - $GLOBALS['KOLAB_TESTING'][$folder] = array( - 'status' => array( - 'uidvalidity' => time(), - 'uidnext' => 1), - 'mails' => array(), - 'permissions' => array(), - 'annotations' => array(), - ); - return true; - } - - /** - * Delete the specified folder. - * - * @param string $folder The folder to delete. - * - * @return mixed True in case the operation was successfull, a - * PEAR error otherwise. - */ - function delete($folder) - { - $folder = $this->_parseFolder($folder); - if (!isset($GLOBALS['KOLAB_TESTING'][$folder])) { - return PEAR::raiseError(sprintf("IMAP folder %s does not exist!", $folder)); - } - unset($GLOBALS['KOLAB_TESTING'][$folder]); - return true; - } - - /** - * Rename the specified folder. - * - * @param string $old The folder to rename. - * @param string $new The new name of the folder. - * - * @return mixed True in case the operation was successfull, a - * PEAR error otherwise. - */ - function rename($old, $new) - { - $old = $this->_parseFolder($old); - $new = $this->_parseFolder($new); - - if (!isset($GLOBALS['KOLAB_TESTING'][$old])) { - return PEAR::raiseError(sprintf("IMAP folder %s does not exist!", $old)); - } - if (isset($GLOBALS['KOLAB_TESTING'][$new])) { - return PEAR::raiseError(sprintf("IMAP folder %s does already exist!", $new)); - } - $GLOBALS['KOLAB_TESTING'][$new] = $GLOBALS['KOLAB_TESTING'][$old]; - unset($GLOBALS['KOLAB_TESTING'][$old]); - return true; - } - - /** - * Returns the status of the current folder. - * - * @return array An array that contains 'uidvalidity' and 'uidnext'. - */ - function status() - { - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - return $this->_mbox['status']; - } - - /** - * Returns the message ids of the messages in this folder. - * - * @return array The message ids. - */ - function getUids() - { - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - $uids = array(); - foreach ($this->_mbox['mails'] as $uid => $mail) { - if (!($mail['flags'] & KOLAB_IMAP_FLAG_DELETED)) { - $uids[] = $uid; - } - } - return $uids; - } - - /** - * Searches the current folder using the given list of search criteria. - * - * @param string $search_list A list of search criteria. - * - * @return mixed The list of matching message ids or a PEAR error in case - * of an error. - */ - function search($search_list, $uidSearch = true) - { - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - $uids = array(); - if (substr($search_list, 0, 7) == 'SUBJECT') { - $needle = '^Subject: ' . substr($search_list, 8); - foreach ($this->_mbox['mails'] as $uid => $mail) { - if (preg_match($needle, $mail['header'])) { - $uids[] = $uid; - } - } - } else if (substr($search_list, 0, 6) == 'HEADER') { - preg_match('([^ ]*) ([^ ]*)', substr($search_list, 7), $matches); - $needle = '^' . $matches[0] . ': ' . $matches[1]; - foreach ($this->_mbox['mails'] as $uid => $mail) { - if (preg_match($needle, $mail['header'])) { - $uids[] = $uid; - } - } - - } - return $uids; - } - - /** - * Searches the headers of the messages. - * - * @param string $field The name of the header field. - * @param string $value The value that field should match. - * - * @return mixed The list of matching message ids or a PEAR error in case - * of an error. - */ - function searchHeaders($field, $value) - { - return $this->search('HEADER "' . $field . '" "' . $value . '"', true); - } - - /** - * Retrieves the message headers for a given message id. - * - * @param int $uid The message id. - * @param boolean $peek_for_body Prefetch the body. - * - * @return mixed The message header or a PEAR error in case of an error. - */ - function getMessageHeader($uid, $peek_for_body = true) - { - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - if (!isset($this->_mbox['mails'][$uid])) { - return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); - } - return $this->_mbox['mails'][$uid]['header']; - } - - /** - * Retrieves the message body for a given message id. - * - * @param integet $uid The message id. - * - * @return mixed The message body or a PEAR error in case of an error. - */ - function getMessageBody($uid) - { - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - if (!isset($this->_mbox['mails'][$uid])) { - return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); - } - return $this->_mbox['mails'][$uid]['body']; - } - - /** - * Retrieves the full message text for a given message id. - * - * @param integer $uid The message id. - * - * @return mixed The message text or a PEAR error in case of an error. - */ - function getMessage($uid) - { - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - if (!isset($this->_mbox['mails'][$uid])) { - return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); - } - return $this->_mbox['mails'][$uid]['header'] . $this->_mbox['mails'][$uid]['body']; - } - - /** - * Retrieves a list of mailboxes on the server. - * - * @return mixed The list of mailboxes or a PEAR error in case of an - * error. - */ - function getMailboxes() - { - $mboxes = array_keys($GLOBALS['KOLAB_TESTING']); - $user = split('@', $this->_user); - $pattern = '#^user/' . $user[0] . '#'; - $result = array(); - foreach ($mboxes as $mbox) { - $result[] = preg_replace($pattern, 'INBOX', $mbox); - } - return $result; - } - - /** - * Fetches the annotation on a folder. - * - * @param string $entries The entry to fetch. - * @param string $value The specific value to fetch. - * @param string $mailbox_name The name of the folder. - * - * @return mixed The annotation value or a PEAR error in case of an error. - */ - function getAnnotation($entries, $value, $mailbox_name) - { - $mailbox_name = $this->_parseFolder($mailbox_name); - $old_mbox = null; - if ($mailbox_name != $this->_mboxname) { - $old_mbox = $this->_mboxname; - $result = $this->select($mailbox_name); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - if (!isset($this->_mbox['annotations'][$entries]) - || !isset($this->_mbox['annotations'][$entries][$value])) { - return false; - } - $annotation = $this->_mbox['annotations'][$entries][$value]; - if ($old_mbox) { - $this->select($old_mbox); - } - return $annotation; - } - - /** - * Sets the annotation on a folder. - * - * @param string $entries The entry to set. - * @param array $values The values to set - * @param string $mailbox_name The name of the folder. - * - * @return mixed True if successfull, a PEAR error otherwise. - */ - function setAnnotation($entries, $values, $mailbox_name) - { - $mailbox_name = $this->_parseFolder($mailbox_name); - $old_mbox = null; - if ($mailbox_name != $this->_mboxname) { - $old_mbox = $this->_mboxname; - $result = $this->select($mailbox_name); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - if (!isset($this->_mbox['annotations'][$entries])) { - $this->_mbox['annotations'][$entries] = array(); - } - foreach ($values as $key => $value) { - $this->_mbox['annotations'][$entries][$key] = $value; - } - if ($old_mbox) { - $result = $this->select($old_mbox); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - return true; - } - - /** - * Retrieve the access rights from a folder - * - * @param string $folder The folder to retrieve the ACLs from. - * - * @return mixed An array of rights if successfull, a PEAR error - * otherwise. - */ - function getACL($folder) - { - $folder = $this->_parseFolder($folder); - $old_mbox = null; - if ($folder != $this->_mboxname) { - $old_mbox = $this->_mboxname; - $result = $this->select($folder); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - $acl = $this->_mbox['permissions']; - if ($old_mbox) { - $result = $this->select($old_mbox); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - return $acl; - } - - /** - * Retrieve the access rights on a folder not owned by the current user - * - * @param string $folder The folder to retrieve the ACLs from. - * - * @return mixed An array of rights if successfull, a PEAR error - * otherwise. - */ - function getMyRights($folder) - { - $folder = $this->_parseFolder($folder); - $old_mbox = null; - if ($folder != $this->_mboxname) { - $old_mbox = $this->_mboxname; - $result = $this->select($folder); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - $acl = ''; - if (isset($this->_mbox['permissions'][$this->_user])) { - $acl = $this->_mbox['permissions'][$this->_user]; - } - if ($old_mbox) { - $result = $this->select($old_mbox); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - return $acl; - } - - /** - * Set the access rights for a folder - * - * @param string $folder The folder to retrieve the ACLs from. - * @param string $user The user to set the ACLs for - * @param string $acl The ACLs - * - * @return mixed True if successfull, a PEAR error otherwise. - */ - function setACL($folder, $user, $acl) - { - $folder = $this->_parseFolder($folder); - $old_mbox = null; - if ($folder != $this->_mboxname) { - $old_mbox = $this->_mboxname; - $result = $this->select($folder); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - $this->_mbox['permissions'][$user] = $acl; - if ($old_mbox) { - $result = $this->select($old_mbox); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - return true; - } - - /** - * Delete the access rights for a user. - * - * @param string $folder The folder that should be modified. - * @param string $user The user that should get the ACLs removed - * - * @return mixed True if successfull, a PEAR error otherwise. - */ - function deleteACL($folder, $user) - { - $folder = $this->_parseFolder($folder); - $old_mbox = null; - if ($folder != $this->_mboxname) { - $old_mbox = $this->_mboxname; - $result = $this->select($folder); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - unset($this->_mbox['permissions'][$user]); - if ($old_mbox) { - $result = $this->select($old_mbox); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - return true; - } - - /** - * Appends a message to the current folder. - * - * @param string $msg The message to append. - * - * @return mixed True or a PEAR error in case of an error. - */ - function appendMessage($msg) - { - $split = strpos($msg, "\r\n\r\n"); - $mail = array('header' => substr($msg, 0, $split + 2), - 'body' => substr($msg, $split + 3)); - return $this->_appendMessage($mail); - } - - /** - * Appends a message to the current folder. - * - * @param array $msg The message to append. - * - * @return mixed True or a PEAR error in case of an error. - */ - function _appendMessage($msg) - { - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - $mail = array(); - $mail['flags'] = 0; - $mail['header'] = $msg['header']; - $mail['body'] = $msg['body']; - - - $this->_mbox['mails'][$this->_mbox['status']['uidnext']] = $mail; - $this->_mbox['status']['uidnext']++; - return true; - } - - /** - * Copies a message to a new folder. - * - * @param integer $uid IMAP message id. - * @param string $new_folder Target folder. - * - * @return mixed True or a PEAR error in case of an error. - */ - function copyMessage($uid, $new_folder) - { - $new_folder = $this->_parseFolder($new_folder); - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - if (!isset($this->_mbox['mails'][$uid])) { - return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); - } - $mail = $this->_mbox['mails'][$uid]; - - $old_mbox = null; - $result = $this->select($new_folder); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - $this->_appendMessage($mail); - if ($old_mbox) { - $result = $this->select($old_mbox); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - return true; - } - - /** - * Moves a message to a new folder. - * - * @param integer $uid IMAP message id. - * @param string $new_folder Target folder. - * - * @return mixed True or a PEAR error in case of an error. - */ - function moveMessage($uid, $new_folder) - { - $new_folder = $this->_parseFolder($new_folder); - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - if (!isset($this->_mbox['mails'][$uid])) { - return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); - } - $mail = $this->_mbox['mails'][$uid]; - unset($this->_mbox['mails'][$uid]); - - $old_mbox = null; - $result = $this->select($new_folder); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - $this->_appendMessage($mail); - if ($old_mbox) { - $result = $this->select($old_mbox); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - } - return true; - } - - /** - * Deletes messages from the current folder. - * - * @param integer $uids IMAP message ids. - * - * @return mixed True or a PEAR error in case of an error. - */ - function deleteMessages($uids) - { - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - - if (!is_array($uids)) { - $uids = array($uids); - } - - foreach ($uids as $uid) { - - if (!isset($this->_mbox['mails'][$uid])) { - return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); - } - $this->_mbox['mails'][$uid]['flags'] |= KOLAB_IMAP_FLAG_DELETED; - } - return true; - } - - /** - * Undeletes a message in the current folder. - * - * @param integer $uid IMAP message id. - * - * @return mixed True or a PEAR error in case of an error. - */ - function undeleteMessages($uid) - { - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - - if (!isset($this->_mbox['mails'][$uid])) { - return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); - } - $this->_mbox['mails'][$uid]['flags'] &= ~KOLAB_IMAP_FLAG_DELETED; - return true; - } - - /** - * Expunges messages in the current folder. - * - * @return mixed True or a PEAR error in case of an error. - */ - function expunge() - { - if (!$this->_mbox) { - return PEAR::raiseError("No IMAP folder selected!"); - } - - $remaining = array(); - foreach ($this->_mbox['mails'] as $uid => $mail) { - if (!($mail['flags'] & KOLAB_IMAP_FLAG_DELETED)) { - $remaining[$uid] = $mail; - } - } - $this->_mbox['mails'] = $remaining; - return true; - } - - /** - * Return the currently selected mailbox - * - * @return string The mailbox currently selected - */ - function current() - { - return $this->_mboxname; - } -} diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Session.php b/framework/Kolab_Server/lib/Horde/Kolab/Session.php deleted file mode 100644 index 7f2c1318f..000000000 --- a/framework/Kolab_Server/lib/Horde/Kolab/Session.php +++ /dev/null @@ -1,357 +0,0 @@ - - * @license http://www.fsf.org/copyleft/lgpl.html LGPL - * @link http://pear.horde.org/index.php?package=Kolab_Server - */ - -/** We need the Auth library */ -require_once 'Horde/Auth.php'; - -/** - * The Horde_Kolab_Session class holds additional user details for the current - * session. - * - * The core user credentials (login, pass) are kept within the Auth module and - * can be retrieved using Auth::getAuth() respectively - * Auth::getCredential('password'). Any additional Kolab user data - * relevant for the user session should be accessed via the Horde_Kolab_Session - * class. - * - * - * Copyright 2008-2009 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.fsf.org/copyleft/lgpl.html. - * - * @category Kolab - * @package Kolab_Server - * @author Gunnar Wrobel - * @license http://www.fsf.org/copyleft/lgpl.html LGPL - * @link http://pear.horde.org/index.php?package=Kolab_Server - */ -class Horde_Kolab_Session -{ - - /** - * User ID. - * - * @var string - */ - var $user_id; - - /** - * User UID. - * - * @var string - */ - var $user_uid; - - /** - * Primary user mail address. - * - * @var string - */ - var $user_mail; - - /** - * Full name. - * - * @var string - */ - var $user_name = ''; - - /** - * True if the Kolab_Server login was successfull. - * - * @var boolean|PEAR_Error - */ - var $auth; - - /** - * The connection parameters for the IMAP server. - * - * @var array|PEAR_Error - */ - var $_imap_params; - - /** - * Our IMAP connection. - * - * @var Horde_Kolab_IMAP - */ - var $_imap; - - /** - * The free/busy server for the current user. - * - * @var array|PEAR_Error - */ - var $freebusy_server; - - /** - * Constructor. - * - * @param string $user The session will be setup for the user with - * this ID. - * @param array $credentials An array of login credentials. For Kolab, - * this must contain a "password" entry. - */ - function Horde_Kolab_Session($user = null, $credentials = null) - { - global $conf; - - if (empty($user)) { - $user = Auth::getAuth(); - if (empty($user)) { - $user = 'anonymous'; - } else if (!strpos($user, '@')) { - $user = $user . '@' . (!empty($_SERVER['SERVER_NAME']) ? - $_SERVER['SERVER_NAME'] : 'localhost'); - } - } - - $this->user_id = $user; - $this->_imap_params = array(); - - $user_object = null; - - if ($user != 'anonymous') { - $server = $this->getServer($user, $credentials); - $this->user_uid = $server->uid; - $user_object = $server->fetch(); - - if (empty($conf['kolab']['imap']['allow_special_users']) - && !is_a($user_object, 'Horde_Kolab_Server_Object_user')) { - throw new Horde_Kolab_Server_Exception(_('Access to special Kolab users is denied.')); - } - if (isset($conf['kolab']['server']['deny_group'])) { - $dn = $server->gidForMail($conf['kolab']['server']['deny_group']); - if (empty($dn)) { - Horde::logMessage('The Kolab configuratin setting $conf[\'kolab\'][\'server\'][\'deny_group\'] holds a non-existing group!', - __FILE__, __LINE__, PEAR_LOG_WARNING); - } else if (in_array($dn, $user_object->getGroups())) { - throw new Horde_Kolab_Server_Exception(_('You are member of a group that may not login on this server.')); - } - } - if (isset($conf['kolab']['server']['allow_group'])) { - $dn = $server->gidForMail($conf['kolab']['server']['allow_group']); - if (empty($dn)) { - Horde::logMessage('The Kolab configuratin setting $conf[\'kolab\'][\'server\'][\'allow_group\'] holds a non-existing group!', - __FILE__, __LINE__, PEAR_LOG_WARNING); - } else if (!in_array($dn, $user_object->getGroups())) { - throw new Horde_Kolab_Server_Exception(_('You are no member of a group that may login on this server.')); - } - } - - $result = $user_object->get(KOLAB_ATTR_MAIL); - if (!empty($result) && !is_a($result, 'PEAR_Error')) { - $this->user_mail = $result; - } - - $result = $user_object->get(KOLAB_ATTR_SID); - if (!empty($result) && !is_a($result, 'PEAR_Error')) { - $this->user_id = $result; - } - - $result = $user_object->get(KOLAB_ATTR_FNLN); - if (!empty($result) && !is_a($result, 'PEAR_Error')) { - $this->user_name = $result; - } - - $result = $user_object->getServer('imap'); - if (!empty($result) && !is_a($result, 'PEAR_Error')) { - $server = explode(':', $result, 2); - if (!empty($server[0])) { - $this->_imap_params['hostspec'] = $server[0]; - } - if (!empty($server[1])) { - $this->_imap_params['port'] = $server[1]; - } - } - - $result = $user_object->getServer('freebusy'); - if (!empty($result) && !is_a($result, 'PEAR_Error')) { - $this->freebusy_server = $result; - } - } - - if (empty($this->user_mail)) { - $this->user_mail = $user; - } - - if (!isset($this->_imap_params['hostspec'])) { - if (isset($conf['kolab']['imap']['server'])) { - $this->_imap_params['hostspec'] = $conf['kolab']['imap']['server']; - } else { - $this->_imap_params['hostspec'] = 'localhost'; - } - } - - if (!isset($this->_imap_params['port'])) { - if (isset($conf['kolab']['imap']['port'])) { - $this->_imap_params['port'] = $conf['kolab']['imap']['port']; - } else { - $this->_imap_params['port'] = 143; - } - } - - $this->_imap_params['protocol'] = 'imap/notls/novalidate-cert'; - } - - /** - * Returns the properties that need to be serialized. - * - * @return array List of serializable properties. - */ - function __sleep() - { - $properties = get_object_vars($this); - unset($properties['_imap']); - $properties = array_keys($properties); - return $properties; - } - - /** - * Get the Kolab Server connection. - * - * @param string $user The session will be setup for the user with - * this ID. - * @param array $credentials An array of login credentials. For Kolab, - * this must contain a "password" entry. - * - * @return Horde_Kolab_Server|PEAR_Error The Kolab Server connection. - */ - function &getServer($user = null, $credentials = null) - { - /** We need the Kolab Server access. */ - require_once 'Horde/Kolab/Server.php'; - - $params = array(); - if ($this->user_uid) { - $params['uid'] = $this->user_uid; - $params['pass'] = Auth::getCredential('password'); - } else if (isset($user)) { - $params['user'] = $user; - if (isset($credentials['password'])) { - $params['pass'] = $credentials['password']; - } else { - $params['pass'] = Auth::getCredential('password'); - } - } - return Horde_Kolab_Server::singleton($params); - } - - /** - * Get the IMAP connection parameters. - * - * @return array|PEAR_Error The IMAP connection parameters. - */ - function &getImapParams() - { - return $this->_imap_params; - } - - /** - * Create an IMAP connection. - * - * @return Horde_Kolab_IMAP|PEAR_Error The IMAP connection. - */ - function &getImap() - { - if (!isset($this->_imap)) { - - $params = $this->getImapParams(); - if (is_a($params, 'PEAR_Error')) { - return $params; - } - - /** We need the Kolab IMAP library now. */ - require_once 'Horde/Kolab/IMAP.php'; - - $imap = &Horde_Kolab_IMAP::singleton($params['hostspec'], - $params['port'], true, false); - if (is_a($imap, 'PEAR_Error')) { - return $imap; - } - - $result = $imap->connect(Auth::getAuth(), - Auth::getCredential('password')); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - $this->_imap = &$imap; - } - return $this->_imap; - } - - /** - * Attempts to return a reference to a concrete Horde_Kolab_Session instance. - * - * It will only create a new instance if no Horde_Kolab_Session instance - * currently exists or if a user ID has been specified that does not match the - * user ID/user mail of the current session. - * - * This method must be invoked as: - * $var = &Horde_Kolab_Session::singleton(); - * - * @param string $user The session will be setup for the user with - * this ID. - * @param array $credentials An array of login credentials. For Kolab, - * this must contain a "password" entry. - * - * @static - * - * @return Horde_Kolab_Session The concrete Session reference. - */ - function &singleton($user = null, $credentials = null, $destruct = false) - { - static $session; - - if (!isset($session)) { - /** - * Horde_Kolab_Server currently has no caching so we mainly - * cache some user information here as reading this data - * may be expensive when running in a multi-host - * environment. - */ - require_once 'Horde/SessionObjects.php'; - $hs = &Horde_SessionObjects::singleton(); - $session = $hs->query('kolab_session'); - } - - if (empty($user)) { - $user = Auth::getAuth(); - } - - if ($destruct || empty($session) - || ($user != $session->user_mail && $user != $session->user_id)) { - $session = new Horde_Kolab_Session($user, $credentials); - } - - register_shutdown_function(array(&$session, 'shutdown')); - - return $session; - } - - /** - * Stores the object in the session cache. - * - * @return NULL - */ - function shutdown() - { - require_once 'Horde/SessionObjects.php'; - $session = &Horde_SessionObjects::singleton(); - $session->overwrite('kolab_session', $this, false); - } - -} diff --git a/framework/Kolab_Server/package.xml b/framework/Kolab_Server/package.xml index c341544a9..81df488c5 100644 --- a/framework/Kolab_Server/package.xml +++ b/framework/Kolab_Server/package.xml @@ -39,20 +39,14 @@ http://pear.php.net/dtd/package-2.0.xsd"> LGPL * Converted the package to Horde 4 / PHP 5. + * Split the session driver into a separate package (Kolab_Session). - - - - - - - @@ -90,7 +84,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - @@ -133,12 +126,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - - - - - @@ -163,7 +151,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/SessionTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/SessionTest.php deleted file mode 100644 index 8312c1423..000000000 --- a/framework/Kolab_Server/test/Horde/Kolab/Server/SessionTest.php +++ /dev/null @@ -1,208 +0,0 @@ - - * @license http://www.fsf.org/copyleft/lgpl.html LGPL - * @link http://pear.horde.org/index.php?package=Kolab_Server - */ - -/** - * The Autoloader allows us to omit "require/include" statements. - */ -require_once 'Horde/Autoloader.php'; - -/** - * Test the Kolab session handler. - * - * Copyright 2008-2009 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.fsf.org/copyleft/lgpl.html. - * - * @category Kolab - * @package Kolab_Server - * @author Gunnar Wrobel - * @license http://www.fsf.org/copyleft/lgpl.html LGPL - * @link http://pear.horde.org/index.php?package=Kolab_Server - */ -class Horde_Kolab_Server_SessionTest extends Horde_Kolab_Test_Server -{ - /** - * Test class construction. - * - * @return NULL - */ - public function testConstructEmpty() - { - global $conf; - $conf['kolab']['imap']['allow_special_users'] = true; - - $session = &Horde_Kolab_Session::singleton(); - - $this->assertEquals('anonymous', $session->user_mail); - - $params = $session->getImapParams(); - $this->assertNoError($params); - $this->assertEquals('localhost', $params['hostspec']); - $this->assertEquals(143, $params['port']); - } - - /** - * Test old style class construction. - * - * @return NULL - */ - public function testConstructSimple() - { - global $conf; - $conf['kolab']['imap']['server'] = 'example.com'; - $conf['kolab']['imap']['port'] = 200; - $conf['kolab']['freebusy']['server'] = 'fb.example.com'; - - $session = &new Horde_Kolab_Session(); - $params = $session->getImapParams(); - if (is_a($params, 'PEAR_Error')) { - $this->assertEquals('', $params->getMessage()); - } - $this->assertEquals('example.com', $params['hostspec']); - $this->assertEquals(200, $params['port']); - } - - /** - * Test IMAP server retrieval. - * - * @return NULL - */ - public function testGetServer() - { - $server = &$this->prepareEmptyKolabServer(); - $result = $server->add($this->provideBasicUserTwo()); - $this->assertNoError($result); - $this->assertEquals(1, count($GLOBALS['KOLAB_SERVER_TEST_DATA'])); - - $session = &Horde_Kolab_Session::singleton('test', - array('password' => 'test')); - - $this->assertNoError($session->auth); - $this->assertEquals('test@example.org', $session->user_mail); - - $params = $session->getImapParams(); - $this->assertNoError($params); - $this->assertEquals('home.example.org', $params['hostspec']); - $this->assertEquals(143, $params['port']); - $this->assertEquals('test@example.org', $session->user_mail); - - $session->shutdown(); - - $hs = &Horde_SessionObjects::singleton(); - - $recovered_session = &$hs->query('kolab_session'); - $params = $recovered_session->getImapParams(); - $this->assertNoError($params); - $this->assertEquals('home.example.org', $params['hostspec']); - $this->assertEquals(143, $params['port']); - $this->assertEquals('test@example.org', $session->user_mail); - - $this->assertEquals('https://fb.example.org/freebusy', $session->freebusy_server); - } - - /** - * Test retrieving the FreeBusy server for the unauthenticated state. - * - * @return NULL - */ - public function testGetFreeBusyServer() - { - $server = &$this->prepareEmptyKolabServer(); - $result = $server->add($this->provideBasicUserTwo()); - $this->assertNoError($result); - $session = &Horde_Kolab_Session::singleton(); - $this->assertEquals('', $session->freebusy_server); - } - - /** - * Test group based login allow implemention. - * - * @return NULL - */ - public function testLoginAllow() - { - global $conf; - $conf['kolab']['server']['allow_group'] = 'group2@example.org'; - $conf['kolab']['server']['deny_group'] = null; - - $server = &$this->prepareEmptyKolabServer(); - $result = $server->add($this->provideBasicUserOne()); - $this->assertNoError($result); - $result = $server->add($this->provideBasicUserTwo()); - $this->assertNoError($result); - $groups = $this->validGroups(); - foreach ($groups as $group) { - $result = $server->add($group[0]); - $this->assertNoError($result); - } - - $session = &Horde_Kolab_Session::singleton('wrobel', - array('password' => 'none'), - true); - - $this->assertNoError($session->auth); - $this->assertEquals('wrobel@example.org', $session->user_mail); - - try { - $session = &Horde_Kolab_Session::singleton('test', - array('password' => 'test'), - true); - } catch (Horde_Kolab_Server_Exception $e) { - $this->assertError($e, 'You are no member of a group that may login on this server.'); - } - // FIXME: Ensure that the session gets overwritten - //$this->assertTrue(empty($session->user_mail)); - } - - /** - * Test group based login deny implemention. - * - * @return NULL - */ - public function testLoginDeny() - { - global $conf; - $conf['kolab']['server']['deny_group'] = 'group2@example.org'; - unset($conf['kolab']['server']['allow_group']); - - $server = &$this->prepareEmptyKolabServer(); - $result = $server->add($this->provideBasicUserOne()); - $this->assertNoError($result); - $result = $server->add($this->provideBasicUserTwo()); - $this->assertNoError($result); - $groups = $this->validGroups(); - foreach ($groups as $group) { - $result = $server->add($group[0]); - $this->assertNoError($result); - } - - $session = &Horde_Kolab_Session::singleton('test', - array('password' => 'test'), - true); - - $this->assertNoError($session->auth); - $this->assertEquals('test@example.org', $session->user_mail); - - try { - $session = &Horde_Kolab_Session::singleton('wrobel', - array('password' => 'none'), - true); - } catch (Horde_Kolab_Server_Exception $e) { - $this->assertError($e, 'You are member of a group that may not login on this server.'); - } - // FIXME: Ensure that the session gets overwritten - //$this->assertTrue(empty($session->user_mail)); - } - -} diff --git a/framework/Kolab_Session/lib/Horde/Kolab/IMAP.php b/framework/Kolab_Session/lib/Horde/Kolab/IMAP.php new file mode 100644 index 000000000..23e47f12c --- /dev/null +++ b/framework/Kolab_Session/lib/Horde/Kolab/IMAP.php @@ -0,0 +1,138 @@ + + * @author Thomas Jarosch + * @package Kolab_Storage + */ +class Horde_Kolab_IMAP +{ + + /** + * IMAP server to connect to. + * + * @var string + */ + var $_server; + + /** + * IMAP server port to connect to. + * + * @var int + */ + var $_port; + + /** + * IMAP connection. + * + * @var mixed + */ + var $_imap; + + /** + * Connection reuse detection signature. + * + * @var string + */ + var $_reuse_detection; + + /** + * Constructor. + * + * @param string $server Server to connect to + * @param int $port Port to connect to + */ + function Horde_Kolab_IMAP($server, $port) + { + $this->_server = $server; + $this->_port = $port; + } + + /** + * Attempts to return a reference to a concrete Horde_Kolab_IMAP instance. + * It will only create a new instance if no Horde_Kolab_IMAP instance + * exists. + * + * @static + * + * @param string $server Server name + * @param int $port Port + * @param boolean $annotation_required Do we actually need + * the annotation calls? + * + * @return Horde_Kolab_IMAP|PEAR_Error The concrete reference. + */ + function &singleton($server, $port, $annotation_required = true) + { + static $instances = array(); + + /** + * There are Kolab specific PHP functions available that make the IMAP + * access more efficient. If these are detected, or if they are not + * required for the current operation, the PHP IMAP implementation + * should be used. + * + * The c-client Kolab driver provides quicker IMAP routines so is + * preferable whenever possible. + */ + if ($annotation_required) { + if (function_exists('imap_status_current') + && function_exists('imap_getannotation')) { + $driver = 'cclient'; + } else { + $driver = 'pear'; + } + } else { + $driver = 'cclient'; + } + + if (isset($GLOBALS['KOLAB_TESTING'])) { + $driver = 'test'; + } + + $signature = "$server|$port|$driver"; + if (!isset($instances[$signature])) { + $instances[$signature] = &Horde_Kolab_IMAP::factory($server, $port, $driver); + } + + return $instances[$signature]; + } + + /** + * Attempts to return a concrete Horde_Kolab_IMAP instance based on the + * available PHP functionality. + * + * @param string $server Server name. + * @param int $port Server port. + * @param string $driver Which driver should we use? + * + * @return Horde_Kolab_IMAP|PEAR_Error The newly created concrete + * Horde_Kolab_IMAP instance. + */ + function &factory($server, $port, $driver = 'cclient') + { + @include_once dirname(__FILE__) . '/IMAP/' . $driver . '.php'; + + $class = 'Horde_Kolab_IMAP_' . $driver; + if (class_exists($class)) { + $driver = &new $class($server, $port); + } else { + return PEAR::raiseError(sprintf(_("Failed to load Kolab IMAP driver %s"), $driver)); + } + + return $driver; + } +} diff --git a/framework/Kolab_Session/lib/Horde/Kolab/IMAP/cclient.php b/framework/Kolab_Session/lib/Horde/Kolab/IMAP/cclient.php new file mode 100644 index 000000000..cab23898a --- /dev/null +++ b/framework/Kolab_Session/lib/Horde/Kolab/IMAP/cclient.php @@ -0,0 +1,777 @@ + + * @author Thomas Jarosch + * @package Kolab_Storage + */ +class Horde_Kolab_IMAP_cclient extends Horde_Kolab_IMAP +{ + + /** + * Basic IMAP connection string. + * + * @var string + */ + var $_base_mbox; + + /** + * IMAP connection string that includes the folder. + * + * @var string + */ + var $_mbox; + + /** + * The signature of the current connection. + * + * @var string + */ + var $_signature; + + /** + * IMAP user name. + * + * @var string + */ + var $_login; + + /** + * IMAP password. + * + * @var string + */ + var $_password; + + /** + * Connects to the IMAP server. + * + * @param string $login The user account name. + * @param string $password The user password. + * @param boolean $tls Should TLS be used for the connection? + * + * @return boolean|PEAR_Error True in case the connection was opened + * successfully. + */ + function connect($login, $password, $tls = false) + { + $options = ''; + if (!$tls) { + $options = '/notls'; + } + + $mbox = '{' . $this->_server . ':' . $this->_port + . $options . '}'; + + $this->_signature = "$mbox|$login|$password"; + if ($this->_signature == $this->_reuse_detection) { + return true; + } + + $this->_mbox = $this->_base_mbox = $mbox; + $this->_login = $login; + $this->_password = $password; + $this->_imap = null; + + $this->_reuse_detection = $this->_signature; + + return true; + } + + /** + * Lazy connect to the IMAP server. + * + * @return mixed True in case the connection was opened successfully, a + * PEAR error otherwise. + */ + function _connect() + { + $result = @imap_open($this->_base_mbox, $this->_login, $this->_password, OP_HALFOPEN); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Server: %s. Error: %s"), $this->_server, @imap_last_error())); + } + $this->_imap = $result; + return true; + } + + /** + * Disconnects from the IMAP server. If not really necessary this + * should not be called. Once the page got served the connections + * should be closed anyhow and if there is a chance to reuse the + * connection it should be used. + * + * @return mixed True in case the connection was closed successfully, a + * PEAR error otherwise. + */ + function disconnect() + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $this->_reuse_detection = null; + + $result = @imap_close($this->_imap); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Server: %s. Error: %s"), $this->_server, @imap_last_error())); + } + return $result; + } + + /** + * Opens the given folder. + * + * @param string $folder The folder to open. + * + * @return mixed True in case the folder was opened successfully, a PEAR + * error otherwise. + */ + function select($folder) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $this->_mbox = $this->_base_mbox . $folder; + + $result = @imap_reopen($this->_imap, $this->_mbox); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); + } + return $result; + } + + /** + * Does the given folder exist? + * + * @param string $folder The folder to check. + * + * @return mixed True in case the folder exists, false otherwise + */ + function exists($folder) + { + $folders = $this->getMailboxes(); + if (is_a($folders, 'PEAR_Error')) { + return $folders; + } + return in_array($folder, $folders); + } + + /** + * Create the specified folder. + * + * @param string $folder The folder to create. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + function create($folder) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $mbox = $this->_base_mbox . $folder; + $result = @imap_createmailbox($this->_imap, $mbox); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); + } + return $result; + } + + /** + * Delete the specified folder. + * + * @param string $folder The folder to delete. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + function delete($folder) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $mbox = $this->_base_mbox . $folder; + $result = @imap_deletemailbox($this->_imap, $mbox); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); + } + return $result; + } + + /** + * Rename the specified folder. + * + * @param string $old The folder to rename. + * @param string $new The new name of the folder. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + function rename($old, $new) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $result = @imap_renamemailbox($this->_imap, + $this->_base_mbox . $old, + $this->_base_mbox . $new); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $old, @imap_last_error())); + } + return $result; + } + + /** + * Returns the status of the current folder. + * + * @return array An array that contains 'uidvalidity' and 'uidnext'. + */ + function status() + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $status = @imap_status_current($this->_imap, SA_MESSAGES | SA_UIDVALIDITY | SA_UIDNEXT); + if (!$status) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $this->_mbox, @imap_last_error())); + } + + return array('uidvalidity' => $status->uidvalidity, + 'uidnext' => $status->uidnext); + } + + /** + * Returns the uids of the messages in this folder. + * + * @return mixed The message ids or a PEAR error in case of an error. + */ + function getUids() + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $uids = @imap_search($this->_imap, 'UNDELETED', SE_UID); + if (!is_array($uids)) { + $uids = array(); + } + + return $uids; + } + + /** + * Searches the current folder using the given list of search criteria. + * + * @param string $search_list A list of search criteria. + * + * @return mixed The list of matching message ids or a PEAR error in case + * of an error. + */ + function search($search_list) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $result = @imap_search($this->_imap, $search_list, SE_UID); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $this->_mbox, @imap_last_error())); + } + return $result; + } + + /** + * Searches the headers of the messages. c-client does not allow using + * "HEADER" as it is possible with Net/IMAP, so we need a workaround. + * + * @param string $field The name of the header field. + * @param string $value The value that field should match. + * + * @return mixed The list of matching message ids or a PEAR error in case + * of an error. + */ + function searchHeaders($field, $value) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $uids = $this->getUids(); + if (is_a($uids, 'PEAR_Error')) { + return $uids; + } + + $result = array(); + foreach ($uids as $uid) { + $header = $this->getMessageHeader($uid, false); + if (is_a($header, 'PEAR_Error')) { + return $header; + } + $header_array = MIME_Headers::parseHeaders($header); + if (isset($header_array[$field]) && $header_array[$field] == $value) { + $result[] = $uid; + } + } + + return $result; + } + + /** + * Retrieves the message headers for a given message id. + * + * @param integer $uid The message id. + * @param boolean $peek_for_body Prefetch the body. + * + * @return mixed The message header or a PEAR error in case of an error. + */ + function getMessageHeader($uid, $peek_for_body = true) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $flags = FT_UID; + if ($peek_for_body) { + $flags |= FT_PREFETCHTEXT; + } + + $result = @imap_fetchheader($this->_imap, $uid, $flags); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), $uid, @imap_last_error())); + } + + return $result; + } + + /** + * Retrieves the message body for a given message id. + * + * @param integer $uid The message id. + * + * @return mixed The message body or a PEAR error in case of an error. + */ + function getMessageBody($uid) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $result = @imap_body($this->_imap, $uid, FT_UID); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), $uid, @imap_last_error())); + } + + return $result; + } + + /** + * Retrieves the full message text for a given message id. + * + * @param integer $uid The message id. + * + * @return mixed The message text or a PEAR error in case of an error. + */ + function getMessage($uid) + { + $header = $this->getMessageHeader($uid); + if (is_a($header, 'PEAR_Error')) { + return $header; + } + + $body = $this->getMessageBody($uid); + if (is_a($body, 'PEAR_Error')) { + return $body; + } + + return $header . $body; + } + + /** + * Retrieves a list of mailboxes on the server. + * + * @return mixed The list of mailboxes or a PEAR error in case of an + * error. + */ + function getMailboxes() + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $folders = array(); + + $result = @imap_list($this->_imap, $this->_base_mbox, '*'); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $this->_base_mbox, @imap_last_error())); + } + + $server_len = strlen($this->_base_mbox); + foreach ($result as $folder) { + if (substr($folder, 0, $server_len) == $this->_base_mbox) { + $folders[] = substr($folder, $server_len); + } + } + + return $folders; + } + + /** + * Fetches the annotation on a folder. + * + * @param string $entries The entry to fetch. + * @param string $value The specific value to fetch. + * @param string $mailbox_name The name of the folder. + * + * @return mixed The annotation value or a PEAR error in case of an error. + */ + function getAnnotation($entries, $value, $mailbox_name) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + static $annotations = array(); + + $signature = "$this->_signature|$entries|$value|$mailbox_name"; + + if (!isset($annotations[$signature])) { + $result = @imap_getannotation($this->_imap, $mailbox_name, $entries, $value); + if (isset($result[$value])) { + $annotations[$signature] = $result[$value]; + } else { + $annotations[$signature] = ''; + } + } + + return $annotations[$signature]; + } + + /** + * Sets the annotation on a folder. + * + * @param string $entries The entry to set. + * @param array $values The values to set + * @param string $mailbox_name The name of the folder. + * + * @return mixed True if successfull, a PEAR error otherwise. + */ + function setAnnotation($entries, $values, $mailbox_name) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + foreach ($values as $key => $value) { + $result = @imap_setannotation($this->_imap, $mailbox_name, $entries, $key, $value); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $mailbox_name, @imap_last_error())); + } + } + return true; + } + + /** + * Retrieve the access rights from a folder + * + * @param string $folder The folder to retrieve the ACLs from. + * + * @return mixed An array of rights if successfull, a PEAR error + * otherwise. + */ + function getACL($folder) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $result = @imap_getacl($this->_imap, $folder); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); + } + return $result; + } + + /** + * Retrieve the access rights from a folder not owned by the current user + * + * @param string $folder The folder to retrieve the ACLs from. + * + * @return mixed An array of rights if successfull, a PEAR error + * otherwise. + */ + function getMyRights($folder) + { + if (!function_exists('imap_myrights')) { + return PEAR::raiseError(sprintf(_("PHP does not support imap_myrights."), $folder, @imap_last_error())); + } + + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $result = @imap_myrights($this->_imap, $folder); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); + } + return $result; + + } + + /** + * Set the access rights for a folder + * + * @param string $folder The folder to retrieve the ACLs from. + * @param string $user The user to set the ACLs for + * @param string $acl The ACLs + * + * @return mixed True if successfull, a PEAR error otherwise. + */ + function setACL($folder, $user, $acl) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $result = @imap_setacl($this->_imap, $folder, $user, $acl); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $folder, @imap_last_error())); + } + return $result; + } + + /** + * Delete the access rights for a user. + * + * @param string $folder The folder that should be modified. + * @param string $user The user that should get the ACLs removed + * + * @return mixed True if successfull, a PEAR error otherwise. + */ + function deleteACL($folder, $user) + { + return $this->setACL($folder, $user, ''); + } + + /** + * Appends a message to the current folder. + * + * @param string $msg The message to append. + * + * @return mixed True or a PEAR error in case of an error. + */ + function appendMessage($msg) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $result = @imap_append($this->_imap, $this->_mbox, $msg); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $this->_mbox, @imap_last_error())); + } + return $result; + } + + /** + * Copies a message to a new folder. + * + * @param integer $uid IMAP message id. + * @param string $new_folder Target folder. + * + * @return mixed True or a PEAR error in case of an error. + */ + function copyMessage($uid, $new_folder) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $result = @imap_mail_copy($this->_imap, $uid, $new_folder, CP_UID); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $new_folder, @imap_last_error())); + } + return $result; + } + + /** + * Moves a message to a new folder. + * + * @param integer $uid IMAP message id. + * @param string $new_folder Target folder. + * + * @return mixed True or a PEAR error in case of an error. + */ + function moveMessage($uid, $new_folder) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $result = @imap_mail_move($this->_imap, $uid, $new_folder, CP_UID); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Folder: %s. Error: %s"), $new_folder, @imap_last_error())); + } + return $result; + } + + /** + * Deletes messages from the current folder. + * + * @param integer $uids IMAP message ids. + * + * @return mixed True or a PEAR error in case of an error. + */ + function deleteMessages($uids) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + if (!is_array($uids)) { + $uids = array($uids); + } + + foreach($uids as $uid) { + $result = @imap_delete($this->_imap, $uid, FT_UID); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), $uid, @imap_last_error())); + } + } + return true; + } + + /** + * Undeletes a message in the current folder. + * + * @param integer $uid IMAP message id. + * + * @return mixed True or a PEAR error in case of an error. + */ + function undeleteMessages($uid) + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $result = @imap_undelete($this->_imap, $uid, FT_UID); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), $uid, @imap_last_error())); + } + return $result; + } + + /** + * Expunges messages in the current folder. + * + * @return mixed True or a PEAR error in case of an error. + */ + function expunge() + { + if (!isset($this->_imap)) { + $result = $this->_connect(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + + $result = @imap_expunge($this->_imap); + if (!$result) { + return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), $this->_mbox, @imap_last_error())); + } + return $result; + } + + /** + * Return the currently selected mailbox + * + * @return string The mailbox currently selected + */ + function current() + { + return $this->_mbox; + } +} diff --git a/framework/Kolab_Session/lib/Horde/Kolab/IMAP/pear.php b/framework/Kolab_Session/lib/Horde/Kolab/IMAP/pear.php new file mode 100644 index 000000000..dbb71811a --- /dev/null +++ b/framework/Kolab_Session/lib/Horde/Kolab/IMAP/pear.php @@ -0,0 +1,519 @@ += 1.0.3 of Net_IMAP (i.e. a + * version that includes support for the ANNOTATEMORE IMAP extension). The + * latest version of Net_IMAP can be obtained from + * http://pear.php.net/get/Net_IMAP + */ +require_once 'Net/IMAP.php'; + +/** + * The Horde_Kolab_IMAP_Connection_pear class connects to an IMAP server using the + * Net_IMAP PEAR package. + * + * + * Copyright 2007-2009 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.fsf.org/copyleft/lgpl.html. + * + * @author Gunnar Wrobel + * @author Thomas Jarosch + * @package Kolab_Storage + */ +class Horde_Kolab_IMAP_pear extends Horde_Kolab_IMAP +{ + + /** + * The signature of the current connection + * + * @var string + */ + var $_signature; + + /** + * Connects to the IMAP server. + * + * @param string $login The user account name. + * @param string $password The user password. + * @param boolean $tls Should TLS be used for the connection? + * + * @return mixed True in case the connection was opened successfully, a + * PEAR error otherwise. + */ + function connect($login, $password, $tls = false) + { + $this->_signature = $this->_server . '|' . $this->_port . "|$login|$password|$tls"; + + // Reuse existing connection? + if ($this->_signature == $this->_reuse_detection) { + return true; + } + + $this->_imap = &new Net_IMAP($this->_server, $this->_port); + $result = $this->_imap->login($login, $password, true, false); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + + $this->_reuse_detection = $this->_signature; + + return true; + } + + /** + * Disconnects from the IMAP server. + * + * @return mixed True in case the connection was closed successfully, a + * PEAR error otherwise. + */ + function disconnect() + { + $this->_reuse_detection = null; + return $this->_imap->disconnect(); + } + + /** + * Opens the given folder. + * + * @param string $folder The folder to open + * + * @return mixed True in case the folder was opened successfully, a PEAR + * error otherwise. + */ + function select($folder) + { + return $this->_imap->selectMailbox($folder); + } + + /** + * Does the given folder exist? + * + * @param string $folder The folder to check. + * + * @return mixed True in case the folder exists, false otherwise + */ + function exists($folder) + { + return $this->_imap->mailboxExist($folder); + } + + /** + * Create the specified folder. + * + * @param string $folder The folder to create. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + function create($folder) + { + return $this->_imap->createMailbox($folder); + } + + /** + * Delete the specified folder. + * + * @param string $folder The folder to delete. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + function delete($folder) + { + return $this->_imap->deleteMailbox($folder); + } + + /** + * Rename the specified folder. + * + * @param string $old The folder to rename. + * @param string $new The new name of the folder. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + function rename($old, $new) + { + return $this->_imap->renameMailbox($old, $new); + } + + /** + * Returns the status of the current folder. + * + * @return array An array that contains 'uidvalidity' and 'uidnext'. + */ + function status() + { + $result = array(); + + $mailbox = $this->_imap->getCurrentMailbox(); + + // Net_IMAP is not very efficent here + $ret = $this->_imap->cmdStatus($mailbox, 'UIDVALIDITY'); + $result['uidvalidity'] = $ret['PARSED']['STATUS']['ATTRIBUTES']['UIDVALIDITY']; + + $ret = $this->_imap->cmdStatus($mailbox, 'UIDNEXT'); + $result['uidnext'] = $ret['PARSED']['STATUS']['ATTRIBUTES']['UIDNEXT']; + + return $result; + } + + /** + * Returns the message ids of the messages in this folder. + * + * @return array The message ids. + */ + function getUids() + { + $uids = $this->_imap->search('UNDELETED', true); + if (!is_array($uids)) { + $uids = array(); + } + return $uids; + } + + /** + * Searches the current folder using the given list of search criteria. + * + * @param string $search_list A list of search criteria. + * + * @return mixed The list of matching message ids or a PEAR error in case + * of an error. + */ + function search($search_list, $uidSearch = true) + { + return $this->_imap->search($search_list, $uidSearch); + } + + /** + * Searches the headers of the messages. + * + * @param string $field The name of the header field. + * @param string $value The value that field should match. + * + * @return mixed The list of matching message ids or a PEAR error in case + * of an error. + */ + function searchHeaders($field, $value) + { + return $this->_imap->search('HEADER "' . $field . '" "' . $value . '"', true); + } + + /** + * Retrieves the message headers for a given message id. + * + * @param int $uid The message id. + * @param boolean $peek_for_body Prefetch the body. + * + * @return mixed The message header or a PEAR error in case of an error. + */ + function getMessageHeader($uid, $peek_for_body = true) + { + $ret = $this->_imap->cmdUidFetch($uid, 'BODY[HEADER]'); + if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { + return PEAR::raiseError(sprintf(_("Failed fetching headers of IMAP message %s. Error was %s"), + $uid, + $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); + } + + if (isset($ret['PARSED'])) { + foreach ($ret['PARSED'] as $msg) { + if (isset($msg['EXT']['BODY[HEADER]']['CONTENT'])) { + return $msg['EXT']['BODY[HEADER]']['CONTENT']; + } + } + } + + return ''; + } + + /** + * Retrieves the message body for a given message id. + * + * @param integet $uid The message id. + * + * @return mixed The message body or a PEAR error in case of an error. + */ + function getMessageBody($uid) + { + $ret = $this->_imap->cmdUidFetch($uid, 'BODY[TEXT]'); + if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { + return PEAR::raiseError(sprintf(_("Failed fetching body of IMAP message %s. Error was %s"), + $uid, + $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); + } + + if (isset($ret['PARSED'])) { + foreach ($ret['PARSED'] as $msg) { + if (isset($msg['EXT']['BODY[TEXT]']['CONTENT'])) { + return $msg['EXT']['BODY[TEXT]']['CONTENT']; + } + } + } + + return ''; + } + + /** + * Retrieves the full message text for a given message id. + * + * @param integer $uid The message id. + * + * @return mixed The message text or a PEAR error in case of an error. + */ + function getMessage($uid) + { + $ret = $this->_imap->cmdUidFetch($uid, 'RFC822'); + if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { + return PEAR::raiseError(sprintf(_("Failed fetching IMAP message %s. Error was %s"), + $uid, + $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); + } + + if (isset($ret['PARSED'])) { + foreach ($ret['PARSED'] as $msg) { + if (isset($msg['EXT']['RFC822']['CONTENT'])) { + return $msg['EXT']['RFC822']['CONTENT']; + } + } + } + + return ''; + } + + /** + * Retrieves a list of mailboxes on the server. + * + * @return mixed The list of mailboxes or a PEAR error in case of an + * error. + */ + function getMailboxes() + { + return $this->_imap->getMailboxes(); + } + + /** + * Fetches the annotation on a folder. + * + * @param string $entries The entry to fetch. + * @param string $value The specific value to fetch. + * @param string $mailbox_name The name of the folder. + * + * @return mixed The annotation value or a PEAR error in case of an error. + */ + function getAnnotation($entries, $value, $mailbox_name) + { + static $annotations = array(); + + $signature = "$this->_signature|$entries|$value|$mailbox_name"; + + if (!isset($annotations[$signature])) { + $annotations[$signature] = $this->_imap->getAnnotation($entries, $value, $mailbox_name); + } + + return $annotations[$signature]; + } + + /** + * Sets the annotation on a folder. + * + * @param string $entries The entry to set. + * @param array $values The values to set + * @param string $mailbox_name The name of the folder. + * + * @return mixed True if successfull, a PEAR error otherwise. + */ + function setAnnotation($entries, $values, $mailbox_name) + { + return $this->_imap->setAnnotation($entries, $values, $mailbox_name); + } + + /** + * Retrieve the access rights from a folder + * + * @param string $folder The folder to retrieve the ACLs from. + * + * @return mixed An array of rights if successfull, a PEAR error + * otherwise. + */ + function getACL($folder) + { + $result = $this->_imap->getACL($folder); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + $acl = array(); + foreach ($result as $user) { + $acl[$user['USER']] = $user['RIGHTS']; + } + return $acl; + } + + /** + * Retrieve the access rights on a folder not owned by the current user + * + * @param string $folder The folder to retrieve the ACLs from. + * + * @return mixed An array of rights if successfull, a PEAR error + * otherwise. + */ + function getMyRights($folder) + { + $result = $this->_imap->getMyRights($folder); + return $result; + } + + /** + * Set the access rights for a folder + * + * @param string $folder The folder to retrieve the ACLs from. + * @param string $user The user to set the ACLs for + * @param string $acl The ACLs + * + * @return mixed True if successfull, a PEAR error otherwise. + */ + function setACL($folder, $user, $acl) + { + return $this->_imap->setACL($folder, $user, $acl); + } + + /** + * Delete the access rights for a user. + * + * @param string $folder The folder that should be modified. + * @param string $user The user that should get the ACLs removed + * + * @return mixed True if successfull, a PEAR error otherwise. + */ + function deleteACL($folder, $user) + { + return $this->_imap->deleteACL($folder, $user); + } + + /** + * Appends a message to the current folder. + * + * @param string $msg The message to append. + * + * @return mixed True or a PEAR error in case of an error. + */ + function appendMessage($msg) + { + return $this->_imap->appendMessage($msg); + } + + /** + * Copies a message to a new folder. + * + * @param integer $uid IMAP message id. + * @param string $new_folder Target folder. + * + * @return mixed True or a PEAR error in case of an error. + */ + function copyMessage($uid, $new_folder) + { + $ret = $this->_imap->cmdUidCopy($uid, $new_folder); + if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { + return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), + $uid, + $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); + } + return true; + } + + /** + * Moves a message to a new folder. + * + * @param integer $uid IMAP message id. + * @param string $new_folder Target folder. + * + * @return mixed True or a PEAR error in case of an error. + */ + function moveMessage($uid, $new_folder) + { + $result = $this->copyMessage($uid, $new_folder); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + + $result = $this->deleteMessages($uid); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + + $result = $this->expunge(); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + return true; + } + + /** + * Deletes messages from the current folder. + * + * @param integer $uids IMAP message ids. + * + * @return mixed True or a PEAR error in case of an error. + */ + function deleteMessages($uids) + { + if (!is_array($uids)) { + $uids = array($uids); + } + + foreach ($uids as $uid) { + $ret = $this->_imap->cmdUidStore($uid, '+FLAGS.SILENT', '\Deleted'); + if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { + return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), + $uid, + $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); + } + } + + return true; + } + + /** + * Undeletes a message in the current folder. + * + * @param integer $uid IMAP message id. + * + * @return mixed True or a PEAR error in case of an error. + */ + function undeleteMessages($uid) + { + $ret = $this->_imap->cmdUidStore($uid, '-FLAGS.SILENT', '\Deleted'); + if (String::upper($ret['RESPONSE']['CODE']) != 'OK') { + return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"), + $uid, + $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE'])); + } + return true; + } + + /** + * Expunges messages in the current folder. + * + * @return mixed True or a PEAR error in case of an error. + */ + function expunge() + { + return $this->_imap->expunge(); + } + + /** + * Return the currently selected mailbox + * + * @return string The mailbox currently selected + */ + function current() + { + return $this->_imap->getCurrentMailbox(); + } +} diff --git a/framework/Kolab_Session/lib/Horde/Kolab/IMAP/test.php b/framework/Kolab_Session/lib/Horde/Kolab/IMAP/test.php new file mode 100644 index 000000000..b95fe3968 --- /dev/null +++ b/framework/Kolab_Session/lib/Horde/Kolab/IMAP/test.php @@ -0,0 +1,727 @@ + + * @package Kolab_Storage + */ +class Horde_Kolab_IMAP_test extends Horde_Kolab_IMAP +{ + + /** + * If we are supposed to be connected this holds the user + * credentials and some connection details. + * + * @var string + */ + var $_connected; + + /** + * Login of the current user + * + * @var string + */ + var $_user; + + /** + * The data of the mailbox currently opened + * + * @var array + */ + var $_mbox = null; + + /** + * The name of the mailbox currently opened + * + * @var array + */ + var $_mboxname = null; + + /** + * Prepare the dummy server. + * + * @param string $login The user account name. + * @param string $password The user password. + * @param boolean $tls Should TLS be used for the connection? + * + * @return mixed True in case the connection was opened successfully, a + * PEAR error otherwise. + */ + function connect($login, $password, $tls = false) + { + if (!is_array($GLOBALS['KOLAB_TESTING'])) { + /* Simulate an empty IMAP server */ + $GLOBALS['KOLAB_TESTING'] = array(); + } + + $tls = ($tls) ? 'tls' : 'notls'; + $this->_connected = $login . ':' . $password . ':' . $tls; + $this->_user = $login; + $this->_mbox = null; + $this->_mboxname = null; + } + + /** + * Disconnects from the IMAP server. + * + * @return mixed True in case the connection was closed successfully, a + * PEAR error otherwise. + */ + function disconnect() + { + $this->_connected = null; + } + + function _parseFolder($folder) + { + if (substr($folder, 0, 5) == 'INBOX') { + $user = split('@', $this->_user); + return 'user/' . $user[0] . substr($folder, 5); + } + return $folder; + } + + /** + * Opens the given folder. + * + * @param string $folder The folder to open + * + * @return mixed True in case the folder was opened successfully, a PEAR + * error otherwise. + */ + function select($folder) + { + $folder = $this->_parseFolder($folder); + if (!isset($GLOBALS['KOLAB_TESTING'][$folder])) { + return PEAR::raiseError(sprintf("IMAP folder %s does not exist!", $folder)); + } + $this->_mbox = &$GLOBALS['KOLAB_TESTING'][$folder]; + $this->_mboxname = $folder; + return true; + } + + /** + * Does the given folder exist? + * + * @param string $folder The folder to check. + * + * @return mixed True in case the folder exists, false otherwise + */ + function exists($folder) + { + $folder = $this->_parseFolder($folder); + if (!isset($GLOBALS['KOLAB_TESTING'][$folder])) { + return false; + } + return true; + } + + /** + * Create the specified folder. + * + * @param string $folder The folder to create. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + function create($folder) + { + $folder = $this->_parseFolder($folder); + if (isset($GLOBALS['KOLAB_TESTING'][$folder])) { + return PEAR::raiseError(sprintf("IMAP folder %s does already exist!", $folder)); + } + $GLOBALS['KOLAB_TESTING'][$folder] = array( + 'status' => array( + 'uidvalidity' => time(), + 'uidnext' => 1), + 'mails' => array(), + 'permissions' => array(), + 'annotations' => array(), + ); + return true; + } + + /** + * Delete the specified folder. + * + * @param string $folder The folder to delete. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + function delete($folder) + { + $folder = $this->_parseFolder($folder); + if (!isset($GLOBALS['KOLAB_TESTING'][$folder])) { + return PEAR::raiseError(sprintf("IMAP folder %s does not exist!", $folder)); + } + unset($GLOBALS['KOLAB_TESTING'][$folder]); + return true; + } + + /** + * Rename the specified folder. + * + * @param string $old The folder to rename. + * @param string $new The new name of the folder. + * + * @return mixed True in case the operation was successfull, a + * PEAR error otherwise. + */ + function rename($old, $new) + { + $old = $this->_parseFolder($old); + $new = $this->_parseFolder($new); + + if (!isset($GLOBALS['KOLAB_TESTING'][$old])) { + return PEAR::raiseError(sprintf("IMAP folder %s does not exist!", $old)); + } + if (isset($GLOBALS['KOLAB_TESTING'][$new])) { + return PEAR::raiseError(sprintf("IMAP folder %s does already exist!", $new)); + } + $GLOBALS['KOLAB_TESTING'][$new] = $GLOBALS['KOLAB_TESTING'][$old]; + unset($GLOBALS['KOLAB_TESTING'][$old]); + return true; + } + + /** + * Returns the status of the current folder. + * + * @return array An array that contains 'uidvalidity' and 'uidnext'. + */ + function status() + { + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + return $this->_mbox['status']; + } + + /** + * Returns the message ids of the messages in this folder. + * + * @return array The message ids. + */ + function getUids() + { + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + $uids = array(); + foreach ($this->_mbox['mails'] as $uid => $mail) { + if (!($mail['flags'] & KOLAB_IMAP_FLAG_DELETED)) { + $uids[] = $uid; + } + } + return $uids; + } + + /** + * Searches the current folder using the given list of search criteria. + * + * @param string $search_list A list of search criteria. + * + * @return mixed The list of matching message ids or a PEAR error in case + * of an error. + */ + function search($search_list, $uidSearch = true) + { + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + $uids = array(); + if (substr($search_list, 0, 7) == 'SUBJECT') { + $needle = '^Subject: ' . substr($search_list, 8); + foreach ($this->_mbox['mails'] as $uid => $mail) { + if (preg_match($needle, $mail['header'])) { + $uids[] = $uid; + } + } + } else if (substr($search_list, 0, 6) == 'HEADER') { + preg_match('([^ ]*) ([^ ]*)', substr($search_list, 7), $matches); + $needle = '^' . $matches[0] . ': ' . $matches[1]; + foreach ($this->_mbox['mails'] as $uid => $mail) { + if (preg_match($needle, $mail['header'])) { + $uids[] = $uid; + } + } + + } + return $uids; + } + + /** + * Searches the headers of the messages. + * + * @param string $field The name of the header field. + * @param string $value The value that field should match. + * + * @return mixed The list of matching message ids or a PEAR error in case + * of an error. + */ + function searchHeaders($field, $value) + { + return $this->search('HEADER "' . $field . '" "' . $value . '"', true); + } + + /** + * Retrieves the message headers for a given message id. + * + * @param int $uid The message id. + * @param boolean $peek_for_body Prefetch the body. + * + * @return mixed The message header or a PEAR error in case of an error. + */ + function getMessageHeader($uid, $peek_for_body = true) + { + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + if (!isset($this->_mbox['mails'][$uid])) { + return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); + } + return $this->_mbox['mails'][$uid]['header']; + } + + /** + * Retrieves the message body for a given message id. + * + * @param integet $uid The message id. + * + * @return mixed The message body or a PEAR error in case of an error. + */ + function getMessageBody($uid) + { + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + if (!isset($this->_mbox['mails'][$uid])) { + return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); + } + return $this->_mbox['mails'][$uid]['body']; + } + + /** + * Retrieves the full message text for a given message id. + * + * @param integer $uid The message id. + * + * @return mixed The message text or a PEAR error in case of an error. + */ + function getMessage($uid) + { + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + if (!isset($this->_mbox['mails'][$uid])) { + return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); + } + return $this->_mbox['mails'][$uid]['header'] . $this->_mbox['mails'][$uid]['body']; + } + + /** + * Retrieves a list of mailboxes on the server. + * + * @return mixed The list of mailboxes or a PEAR error in case of an + * error. + */ + function getMailboxes() + { + $mboxes = array_keys($GLOBALS['KOLAB_TESTING']); + $user = split('@', $this->_user); + $pattern = '#^user/' . $user[0] . '#'; + $result = array(); + foreach ($mboxes as $mbox) { + $result[] = preg_replace($pattern, 'INBOX', $mbox); + } + return $result; + } + + /** + * Fetches the annotation on a folder. + * + * @param string $entries The entry to fetch. + * @param string $value The specific value to fetch. + * @param string $mailbox_name The name of the folder. + * + * @return mixed The annotation value or a PEAR error in case of an error. + */ + function getAnnotation($entries, $value, $mailbox_name) + { + $mailbox_name = $this->_parseFolder($mailbox_name); + $old_mbox = null; + if ($mailbox_name != $this->_mboxname) { + $old_mbox = $this->_mboxname; + $result = $this->select($mailbox_name); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + if (!isset($this->_mbox['annotations'][$entries]) + || !isset($this->_mbox['annotations'][$entries][$value])) { + return false; + } + $annotation = $this->_mbox['annotations'][$entries][$value]; + if ($old_mbox) { + $this->select($old_mbox); + } + return $annotation; + } + + /** + * Sets the annotation on a folder. + * + * @param string $entries The entry to set. + * @param array $values The values to set + * @param string $mailbox_name The name of the folder. + * + * @return mixed True if successfull, a PEAR error otherwise. + */ + function setAnnotation($entries, $values, $mailbox_name) + { + $mailbox_name = $this->_parseFolder($mailbox_name); + $old_mbox = null; + if ($mailbox_name != $this->_mboxname) { + $old_mbox = $this->_mboxname; + $result = $this->select($mailbox_name); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + if (!isset($this->_mbox['annotations'][$entries])) { + $this->_mbox['annotations'][$entries] = array(); + } + foreach ($values as $key => $value) { + $this->_mbox['annotations'][$entries][$key] = $value; + } + if ($old_mbox) { + $result = $this->select($old_mbox); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + return true; + } + + /** + * Retrieve the access rights from a folder + * + * @param string $folder The folder to retrieve the ACLs from. + * + * @return mixed An array of rights if successfull, a PEAR error + * otherwise. + */ + function getACL($folder) + { + $folder = $this->_parseFolder($folder); + $old_mbox = null; + if ($folder != $this->_mboxname) { + $old_mbox = $this->_mboxname; + $result = $this->select($folder); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + $acl = $this->_mbox['permissions']; + if ($old_mbox) { + $result = $this->select($old_mbox); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + return $acl; + } + + /** + * Retrieve the access rights on a folder not owned by the current user + * + * @param string $folder The folder to retrieve the ACLs from. + * + * @return mixed An array of rights if successfull, a PEAR error + * otherwise. + */ + function getMyRights($folder) + { + $folder = $this->_parseFolder($folder); + $old_mbox = null; + if ($folder != $this->_mboxname) { + $old_mbox = $this->_mboxname; + $result = $this->select($folder); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + $acl = ''; + if (isset($this->_mbox['permissions'][$this->_user])) { + $acl = $this->_mbox['permissions'][$this->_user]; + } + if ($old_mbox) { + $result = $this->select($old_mbox); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + return $acl; + } + + /** + * Set the access rights for a folder + * + * @param string $folder The folder to retrieve the ACLs from. + * @param string $user The user to set the ACLs for + * @param string $acl The ACLs + * + * @return mixed True if successfull, a PEAR error otherwise. + */ + function setACL($folder, $user, $acl) + { + $folder = $this->_parseFolder($folder); + $old_mbox = null; + if ($folder != $this->_mboxname) { + $old_mbox = $this->_mboxname; + $result = $this->select($folder); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + $this->_mbox['permissions'][$user] = $acl; + if ($old_mbox) { + $result = $this->select($old_mbox); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + return true; + } + + /** + * Delete the access rights for a user. + * + * @param string $folder The folder that should be modified. + * @param string $user The user that should get the ACLs removed + * + * @return mixed True if successfull, a PEAR error otherwise. + */ + function deleteACL($folder, $user) + { + $folder = $this->_parseFolder($folder); + $old_mbox = null; + if ($folder != $this->_mboxname) { + $old_mbox = $this->_mboxname; + $result = $this->select($folder); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + unset($this->_mbox['permissions'][$user]); + if ($old_mbox) { + $result = $this->select($old_mbox); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + return true; + } + + /** + * Appends a message to the current folder. + * + * @param string $msg The message to append. + * + * @return mixed True or a PEAR error in case of an error. + */ + function appendMessage($msg) + { + $split = strpos($msg, "\r\n\r\n"); + $mail = array('header' => substr($msg, 0, $split + 2), + 'body' => substr($msg, $split + 3)); + return $this->_appendMessage($mail); + } + + /** + * Appends a message to the current folder. + * + * @param array $msg The message to append. + * + * @return mixed True or a PEAR error in case of an error. + */ + function _appendMessage($msg) + { + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + $mail = array(); + $mail['flags'] = 0; + $mail['header'] = $msg['header']; + $mail['body'] = $msg['body']; + + + $this->_mbox['mails'][$this->_mbox['status']['uidnext']] = $mail; + $this->_mbox['status']['uidnext']++; + return true; + } + + /** + * Copies a message to a new folder. + * + * @param integer $uid IMAP message id. + * @param string $new_folder Target folder. + * + * @return mixed True or a PEAR error in case of an error. + */ + function copyMessage($uid, $new_folder) + { + $new_folder = $this->_parseFolder($new_folder); + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + if (!isset($this->_mbox['mails'][$uid])) { + return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); + } + $mail = $this->_mbox['mails'][$uid]; + + $old_mbox = null; + $result = $this->select($new_folder); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + $this->_appendMessage($mail); + if ($old_mbox) { + $result = $this->select($old_mbox); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + return true; + } + + /** + * Moves a message to a new folder. + * + * @param integer $uid IMAP message id. + * @param string $new_folder Target folder. + * + * @return mixed True or a PEAR error in case of an error. + */ + function moveMessage($uid, $new_folder) + { + $new_folder = $this->_parseFolder($new_folder); + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + if (!isset($this->_mbox['mails'][$uid])) { + return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); + } + $mail = $this->_mbox['mails'][$uid]; + unset($this->_mbox['mails'][$uid]); + + $old_mbox = null; + $result = $this->select($new_folder); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + $this->_appendMessage($mail); + if ($old_mbox) { + $result = $this->select($old_mbox); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + } + return true; + } + + /** + * Deletes messages from the current folder. + * + * @param integer $uids IMAP message ids. + * + * @return mixed True or a PEAR error in case of an error. + */ + function deleteMessages($uids) + { + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + + if (!is_array($uids)) { + $uids = array($uids); + } + + foreach ($uids as $uid) { + + if (!isset($this->_mbox['mails'][$uid])) { + return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); + } + $this->_mbox['mails'][$uid]['flags'] |= KOLAB_IMAP_FLAG_DELETED; + } + return true; + } + + /** + * Undeletes a message in the current folder. + * + * @param integer $uid IMAP message id. + * + * @return mixed True or a PEAR error in case of an error. + */ + function undeleteMessages($uid) + { + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + + if (!isset($this->_mbox['mails'][$uid])) { + return PEAR::raiseError(sprintf("No IMAP message %s!", $uid)); + } + $this->_mbox['mails'][$uid]['flags'] &= ~KOLAB_IMAP_FLAG_DELETED; + return true; + } + + /** + * Expunges messages in the current folder. + * + * @return mixed True or a PEAR error in case of an error. + */ + function expunge() + { + if (!$this->_mbox) { + return PEAR::raiseError("No IMAP folder selected!"); + } + + $remaining = array(); + foreach ($this->_mbox['mails'] as $uid => $mail) { + if (!($mail['flags'] & KOLAB_IMAP_FLAG_DELETED)) { + $remaining[$uid] = $mail; + } + } + $this->_mbox['mails'] = $remaining; + return true; + } + + /** + * Return the currently selected mailbox + * + * @return string The mailbox currently selected + */ + function current() + { + return $this->_mboxname; + } +} diff --git a/framework/Kolab_Session/lib/Horde/Kolab/Session.php b/framework/Kolab_Session/lib/Horde/Kolab/Session.php new file mode 100644 index 000000000..7f2c1318f --- /dev/null +++ b/framework/Kolab_Session/lib/Horde/Kolab/Session.php @@ -0,0 +1,357 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Server + */ + +/** We need the Auth library */ +require_once 'Horde/Auth.php'; + +/** + * The Horde_Kolab_Session class holds additional user details for the current + * session. + * + * The core user credentials (login, pass) are kept within the Auth module and + * can be retrieved using Auth::getAuth() respectively + * Auth::getCredential('password'). Any additional Kolab user data + * relevant for the user session should be accessed via the Horde_Kolab_Session + * class. + * + * + * Copyright 2008-2009 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.fsf.org/copyleft/lgpl.html. + * + * @category Kolab + * @package Kolab_Server + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Server + */ +class Horde_Kolab_Session +{ + + /** + * User ID. + * + * @var string + */ + var $user_id; + + /** + * User UID. + * + * @var string + */ + var $user_uid; + + /** + * Primary user mail address. + * + * @var string + */ + var $user_mail; + + /** + * Full name. + * + * @var string + */ + var $user_name = ''; + + /** + * True if the Kolab_Server login was successfull. + * + * @var boolean|PEAR_Error + */ + var $auth; + + /** + * The connection parameters for the IMAP server. + * + * @var array|PEAR_Error + */ + var $_imap_params; + + /** + * Our IMAP connection. + * + * @var Horde_Kolab_IMAP + */ + var $_imap; + + /** + * The free/busy server for the current user. + * + * @var array|PEAR_Error + */ + var $freebusy_server; + + /** + * Constructor. + * + * @param string $user The session will be setup for the user with + * this ID. + * @param array $credentials An array of login credentials. For Kolab, + * this must contain a "password" entry. + */ + function Horde_Kolab_Session($user = null, $credentials = null) + { + global $conf; + + if (empty($user)) { + $user = Auth::getAuth(); + if (empty($user)) { + $user = 'anonymous'; + } else if (!strpos($user, '@')) { + $user = $user . '@' . (!empty($_SERVER['SERVER_NAME']) ? + $_SERVER['SERVER_NAME'] : 'localhost'); + } + } + + $this->user_id = $user; + $this->_imap_params = array(); + + $user_object = null; + + if ($user != 'anonymous') { + $server = $this->getServer($user, $credentials); + $this->user_uid = $server->uid; + $user_object = $server->fetch(); + + if (empty($conf['kolab']['imap']['allow_special_users']) + && !is_a($user_object, 'Horde_Kolab_Server_Object_user')) { + throw new Horde_Kolab_Server_Exception(_('Access to special Kolab users is denied.')); + } + if (isset($conf['kolab']['server']['deny_group'])) { + $dn = $server->gidForMail($conf['kolab']['server']['deny_group']); + if (empty($dn)) { + Horde::logMessage('The Kolab configuratin setting $conf[\'kolab\'][\'server\'][\'deny_group\'] holds a non-existing group!', + __FILE__, __LINE__, PEAR_LOG_WARNING); + } else if (in_array($dn, $user_object->getGroups())) { + throw new Horde_Kolab_Server_Exception(_('You are member of a group that may not login on this server.')); + } + } + if (isset($conf['kolab']['server']['allow_group'])) { + $dn = $server->gidForMail($conf['kolab']['server']['allow_group']); + if (empty($dn)) { + Horde::logMessage('The Kolab configuratin setting $conf[\'kolab\'][\'server\'][\'allow_group\'] holds a non-existing group!', + __FILE__, __LINE__, PEAR_LOG_WARNING); + } else if (!in_array($dn, $user_object->getGroups())) { + throw new Horde_Kolab_Server_Exception(_('You are no member of a group that may login on this server.')); + } + } + + $result = $user_object->get(KOLAB_ATTR_MAIL); + if (!empty($result) && !is_a($result, 'PEAR_Error')) { + $this->user_mail = $result; + } + + $result = $user_object->get(KOLAB_ATTR_SID); + if (!empty($result) && !is_a($result, 'PEAR_Error')) { + $this->user_id = $result; + } + + $result = $user_object->get(KOLAB_ATTR_FNLN); + if (!empty($result) && !is_a($result, 'PEAR_Error')) { + $this->user_name = $result; + } + + $result = $user_object->getServer('imap'); + if (!empty($result) && !is_a($result, 'PEAR_Error')) { + $server = explode(':', $result, 2); + if (!empty($server[0])) { + $this->_imap_params['hostspec'] = $server[0]; + } + if (!empty($server[1])) { + $this->_imap_params['port'] = $server[1]; + } + } + + $result = $user_object->getServer('freebusy'); + if (!empty($result) && !is_a($result, 'PEAR_Error')) { + $this->freebusy_server = $result; + } + } + + if (empty($this->user_mail)) { + $this->user_mail = $user; + } + + if (!isset($this->_imap_params['hostspec'])) { + if (isset($conf['kolab']['imap']['server'])) { + $this->_imap_params['hostspec'] = $conf['kolab']['imap']['server']; + } else { + $this->_imap_params['hostspec'] = 'localhost'; + } + } + + if (!isset($this->_imap_params['port'])) { + if (isset($conf['kolab']['imap']['port'])) { + $this->_imap_params['port'] = $conf['kolab']['imap']['port']; + } else { + $this->_imap_params['port'] = 143; + } + } + + $this->_imap_params['protocol'] = 'imap/notls/novalidate-cert'; + } + + /** + * Returns the properties that need to be serialized. + * + * @return array List of serializable properties. + */ + function __sleep() + { + $properties = get_object_vars($this); + unset($properties['_imap']); + $properties = array_keys($properties); + return $properties; + } + + /** + * Get the Kolab Server connection. + * + * @param string $user The session will be setup for the user with + * this ID. + * @param array $credentials An array of login credentials. For Kolab, + * this must contain a "password" entry. + * + * @return Horde_Kolab_Server|PEAR_Error The Kolab Server connection. + */ + function &getServer($user = null, $credentials = null) + { + /** We need the Kolab Server access. */ + require_once 'Horde/Kolab/Server.php'; + + $params = array(); + if ($this->user_uid) { + $params['uid'] = $this->user_uid; + $params['pass'] = Auth::getCredential('password'); + } else if (isset($user)) { + $params['user'] = $user; + if (isset($credentials['password'])) { + $params['pass'] = $credentials['password']; + } else { + $params['pass'] = Auth::getCredential('password'); + } + } + return Horde_Kolab_Server::singleton($params); + } + + /** + * Get the IMAP connection parameters. + * + * @return array|PEAR_Error The IMAP connection parameters. + */ + function &getImapParams() + { + return $this->_imap_params; + } + + /** + * Create an IMAP connection. + * + * @return Horde_Kolab_IMAP|PEAR_Error The IMAP connection. + */ + function &getImap() + { + if (!isset($this->_imap)) { + + $params = $this->getImapParams(); + if (is_a($params, 'PEAR_Error')) { + return $params; + } + + /** We need the Kolab IMAP library now. */ + require_once 'Horde/Kolab/IMAP.php'; + + $imap = &Horde_Kolab_IMAP::singleton($params['hostspec'], + $params['port'], true, false); + if (is_a($imap, 'PEAR_Error')) { + return $imap; + } + + $result = $imap->connect(Auth::getAuth(), + Auth::getCredential('password')); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + $this->_imap = &$imap; + } + return $this->_imap; + } + + /** + * Attempts to return a reference to a concrete Horde_Kolab_Session instance. + * + * It will only create a new instance if no Horde_Kolab_Session instance + * currently exists or if a user ID has been specified that does not match the + * user ID/user mail of the current session. + * + * This method must be invoked as: + * $var = &Horde_Kolab_Session::singleton(); + * + * @param string $user The session will be setup for the user with + * this ID. + * @param array $credentials An array of login credentials. For Kolab, + * this must contain a "password" entry. + * + * @static + * + * @return Horde_Kolab_Session The concrete Session reference. + */ + function &singleton($user = null, $credentials = null, $destruct = false) + { + static $session; + + if (!isset($session)) { + /** + * Horde_Kolab_Server currently has no caching so we mainly + * cache some user information here as reading this data + * may be expensive when running in a multi-host + * environment. + */ + require_once 'Horde/SessionObjects.php'; + $hs = &Horde_SessionObjects::singleton(); + $session = $hs->query('kolab_session'); + } + + if (empty($user)) { + $user = Auth::getAuth(); + } + + if ($destruct || empty($session) + || ($user != $session->user_mail && $user != $session->user_id)) { + $session = new Horde_Kolab_Session($user, $credentials); + } + + register_shutdown_function(array(&$session, 'shutdown')); + + return $session; + } + + /** + * Stores the object in the session cache. + * + * @return NULL + */ + function shutdown() + { + require_once 'Horde/SessionObjects.php'; + $session = &Horde_SessionObjects::singleton(); + $session->overwrite('kolab_session', $this, false); + } + +} diff --git a/framework/Kolab_Session/package.xml b/framework/Kolab_Session/package.xml new file mode 100644 index 000000000..16e7c46a8 --- /dev/null +++ b/framework/Kolab_Session/package.xml @@ -0,0 +1,114 @@ + + + Kolab_Session + pear.horde.org + A package managing an active Kolab session. + This package handles a Kolab session. It allows to + authenticate against LDAP and provides the users storage locations. + + + Gunnar Wrobel + wrobel + p@rdus.de + yes + + + Chuck Hagenbuch + chuck + chuck@horde.org + yes + + + Jan Schneider + jan + jan@horde.org + yes + + 2009-03-02 + + 0.1.0 + 0.1.0 + + + alpha + alpha + + LGPL + + * Split package from Kolab_Server + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4.3.0 + + + 1.4.0b1 + + + Auth + pear.horde.org + + + + + Kolab_Server + pear.horde.org + + + Horde_SessionObjects + pear.horde.org + + + PHPUnit + pear.phpunit.de + + + ldap + + + + + + + + + + + + + + + + + diff --git a/framework/Kolab_Session/test/Horde/Kolab/Session/AllTests.php b/framework/Kolab_Session/test/Horde/Kolab/Session/AllTests.php new file mode 100644 index 000000000..7eebe26b1 --- /dev/null +++ b/framework/Kolab_Session/test/Horde/Kolab/Session/AllTests.php @@ -0,0 +1,85 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Session + */ + +/** + * Define the main method + */ +if (!defined('PHPUnit_MAIN_METHOD')) { + define('PHPUnit_MAIN_METHOD', 'Horde_Kolab_Session_AllTests::main'); +} + +/** + * The Autoloader allows us to omit "require/include" statements. + */ +require_once 'Horde/Autoloader.php'; + +/** + * Combine the tests for this package. + * + * + * Copyright 2007-2009 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.fsf.org/copyleft/lgpl.html. + * + * @category Kolab + * @package Kolab_Session + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Session + */ +class Horde_Kolab_Session_AllTests +{ + + /** + * Main entry point for running the suite. + * + * @return NULL + */ + public static function main() + { + PHPUnit_TextUI_TestRunner::run(self::suite()); + } + + /** + * Collect the unit tests of this directory into a new suite. + * + * @return PHPUnit_Framework_TestSuite The test suite. + */ + public static function suite() + { + $suite = new PHPUnit_Framework_TestSuite('Horde Framework - Kolab_Session'); + + $basedir = dirname(__FILE__); + $baseregexp = preg_quote($basedir . DIRECTORY_SEPARATOR, '/'); + + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($basedir)) as $file) { + if ($file->isFile() && preg_match('/Test.php$/', $file->getFilename())) { + $pathname = $file->getPathname(); + require $pathname; + + $class = str_replace(DIRECTORY_SEPARATOR, '_', + preg_replace("/^$baseregexp(.*)\.php/", '\\1', $pathname)); + $suite->addTestSuite('Horde_Kolab_Session_' . $class); + } + } + + return $suite; + } + +} + +if (PHPUnit_MAIN_METHOD == 'Horde_Kolab_Session_AllTests::main') { + Horde_Kolab_Session_AllTests::main(); +} diff --git a/framework/Kolab_Session/test/Horde/Kolab/Session/SessionTest.php b/framework/Kolab_Session/test/Horde/Kolab/Session/SessionTest.php new file mode 100644 index 000000000..eecc1975b --- /dev/null +++ b/framework/Kolab_Session/test/Horde/Kolab/Session/SessionTest.php @@ -0,0 +1,208 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Session + */ + +/** + * The Autoloader allows us to omit "require/include" statements. + */ +require_once 'Horde/Autoloader.php'; + +/** + * Test the Kolab session handler. + * + * Copyright 2008-2009 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.fsf.org/copyleft/lgpl.html. + * + * @category Kolab + * @package Kolab_Session + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Kolab_Session + */ +class Horde_Kolab_Session_SessionTest extends Horde_Kolab_Test_Session +{ + /** + * Test class construction. + * + * @return NULL + */ + public function testConstructEmpty() + { + global $conf; + $conf['kolab']['imap']['allow_special_users'] = true; + + $session = &Horde_Kolab_Session::singleton(); + + $this->assertEquals('anonymous', $session->user_mail); + + $params = $session->getImapParams(); + $this->assertNoError($params); + $this->assertEquals('localhost', $params['hostspec']); + $this->assertEquals(143, $params['port']); + } + + /** + * Test old style class construction. + * + * @return NULL + */ + public function testConstructSimple() + { + global $conf; + $conf['kolab']['imap']['server'] = 'example.com'; + $conf['kolab']['imap']['port'] = 200; + $conf['kolab']['freebusy']['server'] = 'fb.example.com'; + + $session = &new Horde_Kolab_Session(); + $params = $session->getImapParams(); + if (is_a($params, 'PEAR_Error')) { + $this->assertEquals('', $params->getMessage()); + } + $this->assertEquals('example.com', $params['hostspec']); + $this->assertEquals(200, $params['port']); + } + + /** + * Test IMAP server retrieval. + * + * @return NULL + */ + public function testGetSession() + { + $server = &$this->prepareEmptyKolabSession(); + $result = $server->add($this->provideBasicUserTwo()); + $this->assertNoError($result); + $this->assertEquals(1, count($GLOBALS['KOLAB_SERVER_TEST_DATA'])); + + $session = &Horde_Kolab_Session::singleton('test', + array('password' => 'test')); + + $this->assertNoError($session->auth); + $this->assertEquals('test@example.org', $session->user_mail); + + $params = $session->getImapParams(); + $this->assertNoError($params); + $this->assertEquals('home.example.org', $params['hostspec']); + $this->assertEquals(143, $params['port']); + $this->assertEquals('test@example.org', $session->user_mail); + + $session->shutdown(); + + $hs = &Horde_SessionObjects::singleton(); + + $recovered_session = &$hs->query('kolab_session'); + $params = $recovered_session->getImapParams(); + $this->assertNoError($params); + $this->assertEquals('home.example.org', $params['hostspec']); + $this->assertEquals(143, $params['port']); + $this->assertEquals('test@example.org', $session->user_mail); + + $this->assertEquals('https://fb.example.org/freebusy', $session->freebusy_server); + } + + /** + * Test retrieving the FreeBusy server for the unauthenticated state. + * + * @return NULL + */ + public function testGetFreeBusySession() + { + $server = &$this->prepareEmptyKolabSession(); + $result = $server->add($this->provideBasicUserTwo()); + $this->assertNoError($result); + $session = &Horde_Kolab_Session::singleton(); + $this->assertEquals('', $session->freebusy_server); + } + + /** + * Test group based login allow implemention. + * + * @return NULL + */ + public function testLoginAllow() + { + global $conf; + $conf['kolab']['server']['allow_group'] = 'group2@example.org'; + $conf['kolab']['server']['deny_group'] = null; + + $server = &$this->prepareEmptyKolabSession(); + $result = $server->add($this->provideBasicUserOne()); + $this->assertNoError($result); + $result = $server->add($this->provideBasicUserTwo()); + $this->assertNoError($result); + $groups = $this->validGroups(); + foreach ($groups as $group) { + $result = $server->add($group[0]); + $this->assertNoError($result); + } + + $session = &Horde_Kolab_Session::singleton('wrobel', + array('password' => 'none'), + true); + + $this->assertNoError($session->auth); + $this->assertEquals('wrobel@example.org', $session->user_mail); + + try { + $session = &Horde_Kolab_Session::singleton('test', + array('password' => 'test'), + true); + } catch (Horde_Kolab_Session_Exception $e) { + $this->assertError($e, 'You are no member of a group that may login on this server.'); + } + // FIXME: Ensure that the session gets overwritten + //$this->assertTrue(empty($session->user_mail)); + } + + /** + * Test group based login deny implemention. + * + * @return NULL + */ + public function testLoginDeny() + { + global $conf; + $conf['kolab']['server']['deny_group'] = 'group2@example.org'; + unset($conf['kolab']['server']['allow_group']); + + $server = &$this->prepareEmptyKolabSession(); + $result = $server->add($this->provideBasicUserOne()); + $this->assertNoError($result); + $result = $server->add($this->provideBasicUserTwo()); + $this->assertNoError($result); + $groups = $this->validGroups(); + foreach ($groups as $group) { + $result = $server->add($group[0]); + $this->assertNoError($result); + } + + $session = &Horde_Kolab_Session::singleton('test', + array('password' => 'test'), + true); + + $this->assertNoError($session->auth); + $this->assertEquals('test@example.org', $session->user_mail); + + try { + $session = &Horde_Kolab_Session::singleton('wrobel', + array('password' => 'none'), + true); + } catch (Horde_Kolab_Session_Exception $e) { + $this->assertError($e, 'You are member of a group that may not login on this server.'); + } + // FIXME: Ensure that the session gets overwritten + //$this->assertTrue(empty($session->user_mail)); + } + +}