Copyright 2008-2012 Horde LLC (http://www.horde.org/) See the enclosed file COPYING for license information (LGPL). If you did not receive this file, see http://www.horde.org/licenses/lgpl21.
Author: Michael Slusarz (slusarz@horde.org)
Inheritance: implements Serializable
Example #1
0
 /**
  * Checks whether a mailbox exists and is set up properly.
  *
  * @param string $user    The name of the mailbox to check.
  * @param string $domain  The mailbox' domain.
  *
  * @return boolean  True if the mailbox exists.
  * @throws Vilma_Exception if the mailbox doesn't exist.
  */
 public function checkMailbox($user, $domain)
 {
     if (!$this->_imap->listMailboxes($this->_params['userhierarchy'] . $user . '@' . $domain)) {
         throw new Vilma_Exception(sprintf(_("Mailbox \"%s\" does not exist."), $user . '@' . $domain));
     }
     return true;
 }
Example #2
0
 /**
  * Query the validity of a charset.
  *
  * @param string $charset  The charset to query.
  * @param boolean $cached  If true, only query cached values.
  *
  * @return boolean  True if the charset is valid for searching.
  */
 public function query($charset, $cached = false)
 {
     $charset = Horde_String::upper($charset);
     if (isset($this->_charsets[$charset])) {
         return $this->_charsets[$charset];
     } elseif ($cached) {
         return null;
     }
     if (!$this->_baseob) {
         throw new RuntimeException('Base object needs to be defined to query for charset.');
     }
     /* Use a dummy search query and search for BADCHARSET response. */
     $query = new Horde_Imap_Client_Search_Query();
     $query->charset($charset, false);
     $query->ids($this->_baseob->getIdsOb(1, true));
     $query->text('a');
     try {
         $this->_baseob->search('INBOX', $query, array('nocache' => true, 'sequence' => true));
         $this->_charsets[$charset] = true;
     } catch (Horde_Imap_Client_Exception $e) {
         $this->_charsets[$charset] = $e->getCode() !== Horde_Imap_Client_Exception::BADCHARSET;
     }
     $this->notify();
     return $this->_charsets[$charset];
 }
Example #3
0
 /**
  * Gets the raw text for one section of the message.
  *
  * @param integer $id     The ID of the MIME part.
  * @param array $options  Additional options:
  *   - decode: (boolean) Attempt to decode the bodypart on the remote
  *             server. If successful, sets self::$_lastBodyPartDecode to
  *             the content-type of the decoded data.
  *             DEFAULT: No
  *   - length: (integer) If set, only download this many bytes of the
  *             bodypart from the server.
  *             DEFAULT: All data is retrieved.
  *   - mimeheaders: (boolean) Include the MIME headers also?
  *                  DEFAULT: No
  *   - stream: (boolean) If true, return a stream.
  *             DEFAULT: No
  *
  * @return mixed  The text of the part or a stream resource if 'stream'
  *                is true.
  * @todo Simplify by removing 'mimeheaders' parameter (not used).
  */
 public function getBodyPart($id, $options)
 {
     $options = array_merge(array('decode' => false, 'mimeheaders' => false, 'stream' => false), $options);
     $this->_lastBodyPartDecode = null;
     $query = new Horde_Imap_Client_Fetch_Query();
     if (!isset($options['length']) || !empty($options['length'])) {
         $bodypart_params = array('decode' => true, 'peek' => true);
         if (isset($options['length'])) {
             $bodypart_params['start'] = 0;
             $bodypart_params['length'] = $options['length'];
         }
         $query->bodyPart($id, $bodypart_params);
     }
     if (!empty($options['mimeheaders'])) {
         $query->mimeHeader($id, array('peek' => true));
     }
     $fetch_res = $this->_imap->fetch($this->_mbox, $query, array('ids' => new Horde_Imap_Client_Ids(array($this->uid))));
     if (empty($options['mimeheaders'])) {
         $this->_lastBodyPartDecode = $fetch_res[$this->uid]->getBodyPartDecode($id);
         return $fetch_res[$this->uid]->getBodyPart($id, $options['stream']);
     } elseif (empty($options['stream'])) {
         return $fetch_res[$this->uid]->getMimeHeader($id) . $fetch_res[$this->uid]->getBodyPart($id);
     } else {
         $swrapper = new Horde_Support_CombineStream(array($fetch_res[$this->uid]->getMimeHeader($id, Horde_Imap_Client_Data_Fetch::HEADER_STREAM), $fetch_res[$this->uid]->getBodyPart($id, true)));
         return $swrapper->fopen();
     }
 }
Example #4
0
 /**
  * Returns a unique identifier for the current mailbox status.
  *
  * @param Horde_Imap_Client_Base $base_ob  The base driver object.
  * @param mixed $mailbox                   A mailbox. Either a
  *                                         Horde_Imap_Client_Mailbox
  *                                         object or a string (UTF-8).
  * @param boolean $condstore               Is CONDSTORE enabled?
  * @param array $addl                      Additional cache info to add to
  *                                         the cache ID string.
  *
  * @return string  The cache ID string, which will change when the
  *                 composition of the mailbox changes. The uidvalidity
  *                 will always be the first element, and will be delimited
  *                 by the '|' character.
  *
  * @throws Horde_Imap_Client_Exception
  */
 public static function getCacheId($base_ob, $mailbox, $condstore, array $addl = array())
 {
     $query = Horde_Imap_Client::STATUS_UIDVALIDITY | Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_UIDNEXT;
     /* Use MODSEQ as cache ID if CONDSTORE extension is available. */
     if ($condstore) {
         $query |= Horde_Imap_Client::STATUS_HIGHESTMODSEQ;
     } else {
         $query |= Horde_Imap_Client::STATUS_UIDNEXT_FORCE;
     }
     $status = $base_ob->status($mailbox, $query);
     if (empty($status['highestmodseq'])) {
         $parts = array('V' . $status['uidvalidity'], 'U' . $status['uidnext'], 'M' . $status['messages']);
     } else {
         $parts = array('V' . $status['uidvalidity'], 'H' . $status['highestmodseq']);
     }
     return implode('|', array_merge($parts, $addl));
 }
Example #5
0
 /**
  * Delete messages in the cache.
  *
  * @param string $mailbox  An IMAP mailbox string.
  * @param array $uids      The list of message UIDs to delete.
  */
 public function deleteMsgs($mailbox, $uids)
 {
     if (empty($uids)) {
         return;
     }
     $mailbox = strval($mailbox);
     $this->_backend->deleteMsgs($mailbox, $uids);
     if ($this->_debug) {
         $this->_debug->info(sprintf('CACHE: Deleted messages [%s; %s]', $mailbox, $this->_baseob->getIdsOb($uids)->tostring_sort));
     }
 }
Example #6
0
 /**
  * Delete a mailbox from the cache.
  *
  * @param string $mbox  The mailbox to delete.
  */
 protected function _deleteMailbox($mbox)
 {
     foreach (array_merge(array_keys(array_flip($this->_slicemap[$mbox]['s'])), array('slicemap')) as $slice) {
         $cid = $this->_getCid($mbox, $slice);
         $this->_cache->expire($cid);
         unset($this->_loaded[$cid]);
     }
     unset($this->_data[$mbox], $this->_slicemap[$mbox], $this->_update[$mbox]);
     if ($this->_params['debug']) {
         $this->_base->writeDebug('CACHE: Deleted mailbox (mailbox: ' . $mbox . ")\n", Horde_Imap_Client::DEBUG_INFO);
     }
 }
Example #7
0
 /**
  */
 protected function _initCache($current = false)
 {
     return parent::_initCache($current) && $this->_capability('UIDL');
 }
Example #8
0
 /**
  * @param array $opts  Options:
  *   - decrement: (boolean) If true, decrement the message count.
  *   - pipeline: (Horde_Imap_Client_Interaction_Pipeline) Pipeline object.
  */
 protected function _deleteMsgs(Horde_Imap_Client_Mailbox $mailbox, Horde_Imap_Client_Ids $ids, array $opts = array())
 {
     /* If there are pending FETCH cache writes, we need to write them
      * before the UID -> sequence number mapping changes. */
     if (isset($opts['pipeline'])) {
         $this->_updateCache($opts['pipeline']->fetch);
     }
     $res = parent::_deleteMsgs($mailbox, $ids);
     if (isset($this->_temp['expunged'])) {
         $this->_temp['expunged']->add($res);
     }
     if (!empty($opts['decrement'])) {
         $mbox_ob = $this->_mailboxOb();
         $mbox_ob->setStatus(Horde_Imap_Client::STATUS_MESSAGES, $mbox_ob->getStatus(Horde_Imap_Client::STATUS_MESSAGES) - count($ids));
     }
 }
Example #9
0
 /**
  */
 protected function _syncMailbox()
 {
     /* QRESYNC would have already synced the mailbox. */
     if (empty($this->_init['enabled']['QRESYNC'])) {
         parent::_syncMailbox();
     }
 }
Example #10
0
 /**
  * Constructor.
  *
  * @param Horde_Imap_Client_Base $base_ob  Base driver object.
  * @param mixed $mailbox                   Mailbox to sync.
  * @param array $sync                      Token sync data.
  * @param array $curr                      Current sync data.
  * @param integer $criteria                Mask of criteria to return.
  * @param Horde_Imap_Client_Ids $ids       List of known UIDs.
  *
  * @throws Horde_Imap_Client_Exception
  * @throws Horde_Imap_Client_Exception_Sync
  */
 public function __construct(Horde_Imap_Client_Base $base_ob, $mailbox, $sync, $curr, $criteria, $ids)
 {
     foreach (self::$map as $key => $val) {
         if (isset($sync[$key])) {
             $this->{$val} = $sync[$key];
         }
     }
     /* Check uidvalidity. */
     if (!$this->uidvalidity || $curr['V'] != $this->uidvalidity) {
         throw new Horde_Imap_Client_Exception_Sync('UIDs in cached mailbox have changed.', Horde_Imap_Client_Exception_Sync::UIDVALIDITY_CHANGED);
     }
     $this->mailbox = $mailbox;
     /* This was a UIDVALIDITY check only. */
     if (!$criteria) {
         return;
     }
     $sync_all = $criteria & Horde_Imap_Client::SYNC_ALL;
     /* New messages. */
     if ($sync_all || $criteria & Horde_Imap_Client::SYNC_NEWMSGS || $criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS) {
         $this->newmsgs = empty($this->uidnext) ? !empty($curr['U']) : !empty($curr['U']) && $curr['U'] > $this->uidnext;
         if ($this->newmsgs && ($sync_all || $criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS)) {
             $new_ids = empty($this->uidnext) ? Horde_Imap_Client_Ids::ALL : $this->uidnext . ':' . $curr['U'];
             $squery = new Horde_Imap_Client_Search_Query();
             $squery->ids(new Horde_Imap_Client_Ids($new_ids));
             $sres = $base_ob->search($mailbox, $squery);
             $this->_newmsgsuids = $sres['match'];
         }
     }
     /* Do single status call to get all necessary data. */
     if ($this->highestmodseq && ($sync_all || $criteria & Horde_Imap_Client::SYNC_FLAGS || $criteria & Horde_Imap_Client::SYNC_FLAGSUIDS || $criteria & Horde_Imap_Client::SYNC_VANISHED || $criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS)) {
         $status_sync = $base_ob->status($mailbox, Horde_Imap_Client::STATUS_SYNCMODSEQ | Horde_Imap_Client::STATUS_SYNCFLAGUIDS | Horde_Imap_Client::STATUS_SYNCVANISHED);
         if (!is_null($ids)) {
             $ids = $base_ob->resolveIds($mailbox, $ids);
         }
     }
     /* Flag changes. */
     if ($sync_all || $criteria & Horde_Imap_Client::SYNC_FLAGS) {
         $this->flags = $this->highestmodseq ? $this->highestmodseq != $curr['H'] : true;
     }
     if ($sync_all || $criteria & Horde_Imap_Client::SYNC_FLAGSUIDS) {
         if ($this->highestmodseq) {
             if ($this->highestmodseq == $status_sync['syncmodseq']) {
                 $this->_flagsuids = is_null($ids) ? $status_sync['syncflaguids'] : $base_ob->getIdsOb(array_intersect($ids->ids, $status_sync['syncflaguids']->ids));
             } else {
                 $squery = new Horde_Imap_Client_Search_Query();
                 $squery->modseq($this->highestmodseq + 1);
                 $sres = $base_ob->search($mailbox, $squery, array('ids' => $ids));
                 $this->_flagsuids = $sres['match'];
             }
         } else {
             /* Without MODSEQ, need to mark all FLAGS as changed. */
             $this->_flagsuids = $base_ob->resolveIds($mailbox, is_null($ids) ? $base_ob->getIdsOb(Horde_Imap_Client_Ids::ALL) : $ids);
         }
     }
     /* Vanished messages. */
     if ($sync_all || $criteria & Horde_Imap_Client::SYNC_VANISHED || $criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS) {
         if ($this->highestmodseq && $this->highestmodseq == $status_sync['syncmodseq']) {
             $vanished = is_null($ids) ? $status_sync['syncvanished'] : $base_ob->getIdsOb(array_intersect($ids->ids, $status_sync['syncvanished']->ids));
         } else {
             $vanished = $base_ob->vanished($mailbox, $this->highestmodseq ? $this->highestmodseq : 1, array('ids' => $ids));
         }
         $this->vanished = (bool) count($vanished);
         $this->_vanisheduids = $vanished;
     }
 }
Example #11
0
 /**
  * All other calls to this class are routed to the underlying
  * Horde_Imap_Client_Base object.
  *
  * @param string $method  Method name.
  * @param array $params   Method parameters.
  *
  * @return mixed  The return from the requested method.
  * @throws BadMethodCallException
  * @throws IMP_Imap_Exception
  */
 public function __call($method, $params)
 {
     global $injector;
     if (!$this->init) {
         /* Fallback for these methods. */
         switch ($method) {
             case 'getIdsOb':
                 $ob = new Horde_Imap_Client_Ids();
                 call_user_func_array(array($ob, 'add'), $params);
                 return $ob;
         }
         throw new Horde_Exception_AuthenticationFailure('IMP is marked as authenticated, but no credentials can be found in the session.', Horde_Auth::REASON_SESSION);
     }
     switch ($method) {
         case 'append':
         case 'createMailbox':
         case 'deleteMailbox':
         case 'expunge':
         case 'fetch':
         case 'getACL':
         case 'getMetadata':
         case 'getMyACLRights':
         case 'getQuota':
         case 'getQuotaRoot':
         case 'getSyncToken':
         case 'setMetadata':
         case 'setQuota':
         case 'store':
         case 'subscribeMailbox':
         case 'sync':
         case 'thread':
             // Horde_Imap_Client_Mailbox: these calls all have the mailbox as
             // their first parameter.
             $params[0] = IMP_Mailbox::getImapMboxOb($params[0]);
             break;
         case 'copy':
         case 'renameMailbox':
             // These calls may hit multiple servers.
             $source = IMP_Mailbox::get($params[0]);
             $dest = IMP_Mailbox::get($params[1]);
             if ($source->remote_account != $dest->remote_account) {
                 return call_user_func_array(array($this, '_' . $method), $params);
             }
             // Horde_Imap_Client_Mailbox: these calls all have the mailbox as
             // their first two parameters.
             $params[0] = $source->imap_mbox_ob;
             $params[1] = $dest->imap_mbox_ob;
             break;
         case 'getNamespaces':
             if (isset($this->_temp['ns'])) {
                 return $this->_temp['ns'];
             }
             $nsconfig = $this->config->namespace;
             $params[0] = is_null($nsconfig) ? array() : $nsconfig;
             $params[1] = array('ob_return' => true);
             break;
         case 'impStatus':
             /* Internal method: allows status call with array of mailboxes,
              * guaranteeing they are all on this server. */
             $params[0] = IMP_Mailbox::getImapMboxOb($params[0]);
             $method = 'status';
             break;
         case 'openMailbox':
             $mbox = IMP_Mailbox::get($params[0]);
             if ($mbox->search) {
                 /* Can't open a search mailbox. */
                 return;
             }
             $params[0] = $mbox->imap_mbox_ob;
             break;
         case 'search':
             $params = call_user_func_array(array($this, '_search'), $params);
             break;
         case 'status':
             if (is_array($params[0])) {
                 return $this->_status($params);
             }
             $params[0] = IMP_Mailbox::getImapMboxOb($params[0]);
             break;
         default:
             if (!method_exists($this->_ob, $method)) {
                 throw new BadMethodCallException(sprintf('%s: Invalid method call "%s".', __CLASS__, $method));
             }
             break;
     }
     try {
         $result = call_user_func_array(array($this->_ob, $method), $params);
     } catch (Horde_Imap_Client_Exception $e) {
         switch ($method) {
             case 'getNamespaces':
                 return new Horde_Imap_Client_Namespace_List();
         }
         Horde::log(new Exception(sprintf('[%s] %s', $method, $e->raw_msg), $e->getCode(), $e), 'WARN');
         $error = new IMP_Imap_Exception($e);
         throw ($auth_e = $error->authException(false)) ? $auth_e : $error;
     }
     /* Special handling for various methods. */
     switch ($method) {
         case 'createMailbox':
         case 'deleteMailbox':
         case 'renameMailbox':
             $injector->getInstance('IMP_Mailbox_SessionCache')->expire(null, IMP_Mailbox::get($params[0]));
             break;
         case 'getNamespaces':
             $this->_temp['ns'] = $result;
             break;
         case 'login':
             if (!$this->_ob->getParam('imp:login')) {
                 /* Check for POP3 UIDL support. */
                 if ($this->isPop3() && !$this->queryCapability('UIDL')) {
                     Horde::log(sprintf('The POP3 server does not support the REQUIRED UIDL capability. [server key: %s]', $this->server_key), 'CRIT');
                     throw new Horde_Exception_AuthenticationFailure(_("The mail server is not currently avaliable."), Horde_Auth::REASON_MESSAGE);
                 }
                 $this->_ob->setParam('imp:login', true);
                 $this->_changed = true;
             }
             break;
         case 'setACL':
             $injector->getInstance('IMP_Mailbox_SessionCache')->expire(IMP_Mailbox_SessionCache::CACHE_ACL, IMP_Mailbox::get($params[0]));
             break;
     }
     return $result;
 }
Example #12
0
 /**
  * Delete a set of authentication credentials.
  *
  * @param string $userId  The userId to delete.
  *
  * @throws Horde_Auth_Exception
  */
 public function removeUser($userId)
 {
     if (!empty($this->_params['domain_field']) && $this->_params['domain_field'] != 'none') {
         list($name, $domain) = explode('@', $userId);
         /* Build the SQL query. */
         $query = sprintf('DELETE FROM %s WHERE %s = ? and %s = ?', $this->_params['table'], $this->_params['username_field'], $this->_params['domain_field']);
         $values = array($name, $domain);
         $query2 = 'DELETE FROM virtual WHERE dest = ?';
         $values2 = array($userId);
         try {
             $this->_db->delete($query, $values);
             $this->_db->delete($query2, $values2);
         } catch (Horde_Db_Exception $e) {
             throw new Horde_Auth_Exception($e);
         }
     } else {
         parent::removeUser($userId);
     }
     /* Set ACL for mailbox deletion. */
     list($admin) = explode('@', $this->_params['cyradmin']);
     $mailbox = $this->_params['userhierarchy'];
     try {
         $this->_imap->setACL($mailbox, $admin, array('rights' => 'lrswipcda'));
         $this->_imap->deleteMailbox($mailbox);
     } catch (Horde_Imap_Client_Exception $e) {
         throw new Horde_Auth_Exception($e);
     }
 }