From: Chuck Hagenbuch Date: Thu, 15 Jan 2009 05:50:17 +0000 (-0500) Subject: add Horde_Imap_Client_Utils to replace static utility functions X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=f941f97778321761d822ffcec3633748d4c1bc45;p=horde.git add Horde_Imap_Client_Utils to replace static utility functions Fix constant names since _Base doesn't extend H_I_C now. --- diff --git a/framework/Imap_Client/lib/Horde/Imap/Client.php b/framework/Imap_Client/lib/Horde/Imap/Client.php index 6de60e6c1..09d2c60df 100644 --- a/framework/Imap_Client/lib/Horde/Imap/Client.php +++ b/framework/Imap_Client/lib/Horde/Imap/Client.php @@ -59,10 +59,6 @@ * * Copyright 2008-2009 The Horde Project (http://www.horde.org/) * - * getBaseSubject() code adapted from imap-base-subject.c (Dovecot 1.2) - * Original code released under the LGPL v2.1 - * Copyright (c) 2002-2008 Timo Sirainen - * * See the enclosed file COPYING for license information (LGPL). If you * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. * diff --git a/framework/Imap_Client/lib/Horde/Imap/Client/Base.php b/framework/Imap_Client/lib/Horde/Imap/Client/Base.php index 9ea27db4b..41fe0e58a 100644 --- a/framework/Imap_Client/lib/Horde/Imap/Client/Base.php +++ b/framework/Imap_Client/lib/Horde/Imap/Client/Base.php @@ -62,9 +62,16 @@ abstract class Horde_Imap_Client_Base ); /** + * The Horde_Imap_Client_Utils object + * + * @var Horde_Imap_Client_Utils + */ + protected $_utils = null; + + /** * The Horde_Imap_Client_Cache object. * - * @var Horde_Cache + * @var Horde_Imap_Client_Cache */ protected $_cacheOb = null; @@ -76,350 +83,6 @@ abstract class Horde_Imap_Client_Base protected $_debug = null; /** - * Create an IMAP message sequence string from a list of indices. - * Format: range_start:range_end,uid,uid2,range2_start:range2_end,... - * - * @param array $in An array of indices. - * @param array $options Additional options: - *
-     * 'nosort' - (boolean) Do not numerically sort the IDs before creating
-     *            the range?
-     *            DEFAULT: IDs are sorted
-     * 
- * - * @return string The IMAP message sequence string. - */ - static public function toSequenceString($ids, $options = array()) - { - if (empty($ids)) { - return ''; - } - - // Make sure IDs are unique - $ids = array_keys(array_flip($ids)); - - if (empty($options['nosort'])) { - sort($ids, SORT_NUMERIC); - } - - $first = $last = array_shift($ids); - $out = array(); - - foreach ($ids as $val) { - if ($last + 1 == $val) { - $last = $val; - } else { - $out[] = $first . ($last == $first ? '' : (':' . $last)); - $first = $last = $val; - } - } - $out[] = $first . ($last == $first ? '' : (':' . $last)); - - return implode(',', $out); - } - - /** - * Parse an IMAP message sequence string into a list of indices. - * Format: range_start:range_end,uid,uid2,range2_start:range2_end,... - * - * @param string $str The IMAP message sequence string. - * - * @return array An array of indices. - */ - static public function fromSequenceString($str) - { - $ids = array(); - $str = trim($str); - - $idarray = explode(',', $str); - if (empty($idarray)) { - $idarray = array($str); - } - - foreach ($idarray as $val) { - $range = array_map('intval', explode(':', $val)); - if (count($range) == 1) { - $ids[] = $val; - } else { - list($low, $high) = ($range[0] < $range[1]) ? $range : array_reverse($range); - $ids = array_merge($ids, range($low, $high)); - } - } - - return $ids; - } - - /** - * Remove "bare newlines" from a string. - * - * @param string $str The original string. - * - * @return string The string with all bare newlines removed. - */ - static public function removeBareNewlines($str) - { - return str_replace(array("\r\n", "\n"), array("\n", "\r\n"), $str); - } - - /** - * Escape IMAP output via a quoted string (see RFC 3501 [4.3]). - * - * @param string $str The unescaped string. - * - * @return string The escaped string. - */ - static public function escape($str) - { - return '"' . addcslashes($str, '"\\') . '"'; - } - - /** - * Return the "base subject" defined in RFC 5256 [2.1]. - * - * @param string $str The original subject string. - * @param array $options Additional options: - *
-     * 'keepblob' - (boolean) Don't remove any "blob" information (i.e. text
-     *              leading text between square brackets) from string.
-     * 
- * - * @return string The cleaned up subject string. - */ - static public function getBaseSubject($str, $options = array()) - { - // Rule 1a: MIME decode to UTF-8 (if possible). - $str = Horde_Mime::decode($str, 'UTF-8'); - - // Rule 1b: Remove superfluous whitespace. - $str = preg_replace("/\s{2,}/", '', $str); - - if (!$str) { - return ''; - } - - do { - /* (2) Remove all trailing text of the subject that matches the - * the subj-trailer ABNF, repeat until no more matches are - * possible. */ - $str = preg_replace("/(?:\s*\(fwd\)\s*)+$/i", '', $str); - - do { - /* (3) Remove all prefix text of the subject that matches the - * subj-leader ABNF. */ - $found = self::_removeSubjLeader($str, !empty($options['keepblob'])); - - /* (4) If there is prefix text of the subject that matches - * the subj-blob ABNF, and removing that prefix leaves a - * non-empty subj-base, then remove the prefix text. */ - $found = (empty($options['keepblob']) && self::_removeBlobWhenNonempty($str)) || $found; - - /* (5) Repeat (3) and (4) until no matches remain. */ - } while ($found); - - /* (6) If the resulting text begins with the subj-fwd-hdr ABNF and - * ends with the subj-fwd-trl ABNF, remove the subj-fwd-hdr and - * subj-fwd-trl and repeat from step (2). */ - } while (self::_removeSubjFwdHdr($str)); - - return $str; - } - - /** - * Parse an IMAP URL (RFC 5092). - * - * @param string $url A IMAP URL string. - * - * @return mixed False if the URL is invalid. If valid, a URL with the - * following fields: - *
-     * 'auth' - (string) The authentication method to use.
-     * 'port' - (integer) The remote port
-     * 'hostspec' - (string) The remote server
-     * 'username' - (string) The username to use on the remote server.
-     * 
- */ - static public function parseImapUrl($url) - { - $url = trim($url); - if (stripos($url, 'imap://') !== 0) { - return false; - } - $url = substr($url, 7); - - /* At present, only support imap://[/] style URLs. */ - if (($pos = strpos($url, '/')) !== false) { - $url = substr($url, 0, $pos); - } - - $ret_array = array(); - - /* Check for username/auth information. */ - if (($pos = strpos($url, '@')) !== false) { - if ((($apos = stripos($url, ';AUTH=')) !== false) && - ($apos < $pos)) { - $auth = substr($url, $apos + 6, $pos - $apos - 6); - if ($auth != '*') { - $ret_array['auth'] = $auth; - } - if ($apos) { - $ret_array['username'] = substr($url, 0, $apos); - } - } - $url = substr($url, $pos + 1); - } - - /* Check for port information. */ - if (($pos = strpos($url, ':')) !== false) { - $ret_array['port'] = substr($url, $pos + 1); - $url = substr($url, 0, $pos); - } - - $ret_array['hostspec'] = $url; - - return $ret_array; - } - - /** - * Remove all prefix text of the subject that matches the subj-leader - * ABNF. - * - * @param string &$str The subject string. - * @param boolean $keepblob Remove blob information? - * - * @return boolean True if string was altered. - */ - static protected function _removeSubjLeader(&$str, $keepblob = false) - { - $ret = false; - - if (!$str) { - return $ret; - } - - if ($str[0] == ' ') { - $str = substr($str, 1); - $ret = true; - } - - $i = 0; - - if (!$keepblob) { - while ($str[$i] == '[') { - if (($i = self::_removeBlob($str, $i)) === false) { - return $ret; - } - } - } - - $cmp_str = substr($str, $i); - if (stripos($cmp_str, 're') === 0) { - $i += 2; - } elseif (stripos($cmp_str, 'fwd') === 0) { - $i += 3; - } elseif (stripos($cmp_str, 'fw') === 0) { - $i += 2; - } else { - return $ret; - } - - if ($str[$i] == ' ') { - ++$i; - } - - if (!$keepblob) { - while ($str[$i] == '[') { - if (($i = self::_removeBlob($str, $i)) === false) { - return $ret; - } - } - } - - if ($str[$i] != ':') { - return $ret; - } - - $str = substr($str, ++$i); - - return true; - } - - /** - * Remove "[...]" text. - * - * @param string &$str The subject string. - * - * @return boolean True if string was altered. - */ - static protected function _removeBlob($str, $i) - { - if ($str[$i] != '[') { - return false; - } - - ++$i; - - for ($cnt = strlen($str); $i < $cnt; ++$i) { - if ($str[$i] == ']') { - break; - } - - if ($str[$i] == '[') { - return false; - } - } - - if ($i == ($cnt - 1)) { - return false; - } - - ++$i; - - if ($str[$i] == ' ') { - ++$i; - } - - return $i; - } - - /** - * Remove "[...]" text if it doesn't result in the subject becoming - * empty. - * - * @param string &$str The subject string. - * - * @return boolean True if string was altered. - */ - static protected function _removeBlobWhenNonempty(&$str) - { - if ($str && - ($str[0] == '[') && - (($i = self::_removeBlob($str, 0)) !== false) && - ($i != strlen($str))) { - $str = substr($str, $i); - return true; - } - - return false; - } - - /** - * Remove a "[fwd: ... ]" string. - * - * @param string &$str The subject string. - * - * @return boolean True if string was altered. - */ - static protected function _removeSubjFwdHdr(&$str) - { - if ((stripos($str, '[fwd:') !== 0) || (substr($str, -1) != ']')) { - return false; - } - - $str = substr($str, 5, -1); - return true; - } - - /** * Constructs a new Horde_Imap_Client object. * Throws a Horde_Imap_Client_Exception on error. * @@ -448,11 +111,11 @@ abstract class Horde_Imap_Client_Base $params['cache'] = array('fields' => array()); } elseif (empty($params['cache']['fields'])) { $params['cache']['fields'] = array( - self::FETCH_STRUCTURE => 1, - self::FETCH_ENVELOPE => 1, - self::FETCH_FLAGS => 1, - self::FETCH_DATE => 1, - self::FETCH_SIZE => 1 + Horde_Imap_Client::FETCH_STRUCTURE => 1, + Horde_Imap_Client::FETCH_ENVELOPE => 1, + Horde_Imap_Client::FETCH_FLAGS => 1, + Horde_Imap_Client::FETCH_DATE => 1, + Horde_Imap_Client::FETCH_SIZE => 1 ); } else { $params['cache']['fields'] = array_flip($params['cache']['fields']); @@ -460,6 +123,8 @@ abstract class Horde_Imap_Client_Base $this->_params = $params; + $this->_utils = new Horde_Imap_Client_Utils(); + // This will initialize debugging, if needed. $this->__wakeup(); } @@ -674,7 +339,7 @@ abstract class Horde_Imap_Client_Base continue; } - $mbox = $this->listMailboxes($val, self::MBOX_ALL, array('delimiter' => true)); + $mbox = $this->listMailboxes($val, Horde_Imap_Client::MBOX_ALL, array('delimiter' => true)); $first = reset($mbox); if ($first && ($first['mailbox'] == $val)) { @@ -691,7 +356,7 @@ abstract class Horde_Imap_Client_Base /* This accurately determines the namespace information of the * base namespace if the NAMESPACE command is not supported. * See: RFC 3501 [6.3.8] */ - $mbox = $this->listMailboxes('', self::MBOX_ALL, array('delimiter' => true)); + $mbox = $this->listMailboxes('', Horde_Imap_Client::MBOX_ALL, array('delimiter' => true)); $first = reset($mbox); $ns[''] = array( 'name' => '', @@ -766,9 +431,9 @@ abstract class Horde_Imap_Client_Base } /* Check for ability to cache flags here. */ - if (isset($this->_params['cache']['fields'][self::FETCH_FLAGS]) && + if (isset($this->_params['cache']['fields'][Horde_Imap_Client::FETCH_FLAGS]) && !isset($this->_init['enabled']['CONDSTORE'])) { - unset($this->_params['cache']['fields'][self::FETCH_FLAGS]); + unset($this->_params['cache']['fields'][Horde_Imap_Client::FETCH_FLAGS]); } } @@ -927,15 +592,15 @@ abstract class Horde_Imap_Client_Base * Horde_Imap_Client::OPEN_READWRITE, or * Horde_Imap_Client::OPEN_AUTO. */ - public function openMailbox($mailbox, $mode = self::OPEN_AUTO) + public function openMailbox($mailbox, $mode = Horde_Imap_Client::OPEN_AUTO) { $change = false; $mailbox = Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($mailbox); - if ($mode == self::OPEN_AUTO) { + if ($mode == Horde_Imap_Client::OPEN_AUTO) { if (is_null($this->_selected) || ($this->_selected != $mailbox)) { - $mode = self::OPEN_READONLY; + $mode = Horde_Imap_Client::OPEN_READONLY; $change = true; } } elseif (is_null($this->_selected) || @@ -1052,7 +717,7 @@ abstract class Horde_Imap_Client_Base $new = Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($new); /* Check if old mailbox was subscribed to. */ - $subscribed = $this->listMailboxes($old, self::MBOX_SUBSCRIBED, array('flat' => true)); + $subscribed = $this->listMailboxes($old, Horde_Imap_Client::MBOX_SUBSCRIBED, array('flat' => true)); $this->_renameMailbox($old, $new); @@ -1143,7 +808,7 @@ abstract class Horde_Imap_Client_Base * if 'attributes' option is true), and 'delimiter' (only * if 'delimiter' option is true). */ - public function listMailboxes($pattern, $mode = self::MBOX_ALL, + public function listMailboxes($pattern, $mode = Horde_Imap_Client::MBOX_ALL, $options = array()) { $ret = $this->_listMailboxes(Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($pattern), $mode, $options); @@ -1236,15 +901,15 @@ abstract class Horde_Imap_Client_Base * * @return array An array with the requested keys (see above). */ - public function status($mailbox, $flags = self::STATUS_ALL) + public function status($mailbox, $flags = Horde_Imap_Client::STATUS_ALL) { - if ($flags & self::STATUS_ALL) { - $flags |= self::STATUS_MESSAGES | self::STATUS_RECENT | self::STATUS_UNSEEN | self::STATUS_UIDNEXT | self::STATUS_UIDVALIDITY; + if ($flags & Horde_Imap_Client::STATUS_ALL) { + $flags |= Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_RECENT | Horde_Imap_Client::STATUS_UNSEEN | Horde_Imap_Client::STATUS_UIDNEXT | Horde_Imap_Client::STATUS_UIDVALIDITY; } /* STATUS_PERMFLAGS requires a read/write mailbox. */ - if ($flags & self::STATUS_PERMFLAGS) { - $this->openMailbox($mailbox, self::OPEN_READWRITE); + if ($flags & Horde_Imap_Client::STATUS_PERMFLAGS) { + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_READWRITE); } return $this->_status(Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($mailbox), $flags); @@ -1258,7 +923,7 @@ abstract class Horde_Imap_Client_Base * @param string $flags A bitmask of information requested from the * server. * - * @return array See Horde_Imap_Client_Base::status(). + * @return array See self::status(). */ abstract protected function _status($mailbox, $flags); @@ -1425,7 +1090,7 @@ abstract class Horde_Imap_Client_Base */ public function expunge($mailbox, $options = array()) { - $this->openMailbox($mailbox, self::OPEN_READWRITE); + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_READWRITE); $this->_expunge($options); } @@ -1517,12 +1182,12 @@ abstract class Horde_Imap_Client_Base */ public function search($mailbox, $query = null, $options = array()) { - $this->openMailbox($mailbox, self::OPEN_AUTO); + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_AUTO); if (empty($options['results'])) { $options['results'] = array( - self::SORT_RESULTS_MATCH, - self::SORT_RESULTS_COUNT + Horde_Imap_Client::SORT_RESULTS_MATCH, + Horde_Imap_Client::SORT_RESULTS_COUNT ); } @@ -1538,14 +1203,14 @@ abstract class Horde_Imap_Client_Base * optimize with unseen queries because we may cause an infinite loop * between here and the status() call. */ if ((count($options['results']) == 1) && - (reset($options['results']) == self::SORT_RESULTS_COUNT)) { + (reset($options['results']) == Horde_Imap_Client::SORT_RESULTS_COUNT)) { switch ($options['_query']['query']) { case 'ALL': - $ret = $this->status($this->_selected, self::STATUS_MESSAGES); + $ret = $this->status($this->_selected, Horde_Imap_Client::STATUS_MESSAGES); return array('count' => $ret['messages']); case 'RECENT': - $ret = $this->status($this->_selected, self::STATUS_RECENT); + $ret = $this->status($this->_selected, Horde_Imap_Client::STATUS_RECENT); return array('count' => $ret['recent']); } } @@ -1662,7 +1327,7 @@ abstract class Horde_Imap_Client_Base */ public function thread($mailbox, $options = array()) { - $this->openMailbox($mailbox, self::OPEN_AUTO); + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_AUTO); $ret = $this->_thread($options); return new Horde_Imap_Client_Thread($ret, empty($options['sequence']) ? 'uid' : 'sequence'); @@ -2052,13 +1717,13 @@ abstract class Horde_Imap_Client_Base /* If using cache, we store by UID so we need to return UIDs. */ if ($seq && !empty($cf)) { - $criteria[self::FETCH_UID] = true; + $criteria[Horde_Imap_Client::FETCH_UID] = true; } - $this->openMailbox($mailbox, self::OPEN_AUTO); + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_AUTO); /* We need the UIDVALIDITY for the current mailbox. */ - $status_res = $this->status($this->_selected, self::STATUS_HIGHESTMODSEQ | self::STATUS_UIDVALIDITY); + $status_res = $this->status($this->_selected, Horde_Imap_Client::STATUS_HIGHESTMODSEQ | Horde_Imap_Client::STATUS_UIDVALIDITY); /* Determine if caching is available and if anything in $criteria is * cacheable. Do some sanity checking on criteria also. */ @@ -2066,7 +1731,7 @@ abstract class Horde_Imap_Client_Base $cache_field = null; switch ($k) { - case self::FETCH_STRUCTURE: + case Horde_Imap_Client::FETCH_STRUCTURE: /* Don't cache if 'noext' is present. It will probably be a * rare event anyway. */ if (empty($v['noext']) && isset($cf[$k])) { @@ -2077,20 +1742,20 @@ abstract class Horde_Imap_Client_Base } break; - case self::FETCH_BODYPARTSIZE: + case Horde_Imap_Client::FETCH_BODYPARTSIZE: if (!$this->queryCapability('BINARY')) { unset($criteria[$k]); } break; - case self::FETCH_ENVELOPE: + case Horde_Imap_Client::FETCH_ENVELOPE: if (isset($cf[$k])) { $cache_field = 'HICenv'; $fetch_field = 'envelope'; } break; - case self::FETCH_FLAGS: + case Horde_Imap_Client::FETCH_FLAGS: if (isset($cf[$k])) { /* QRESYNC would have already done syncing on mailbox * open, so no need to do again. */ @@ -2102,7 +1767,7 @@ abstract class Horde_Imap_Client_Base ($metadata['HICmodseq'] != $status_res['highestmodseq'])) { $uids = $this->_cacheOb->get($this->_selected, array(), array(), $status_res['uidvalidity']); if (!empty($uids)) { - $this->_fetch(array(self::FETCH_FLAGS => true), array('changedsince' => $metadata['HICmodseq'], 'ids' => $uids)); + $this->_fetch(array(Horde_Imap_Client::FETCH_FLAGS => true), array('changedsince' => $metadata['HICmodseq'], 'ids' => $uids)); } $this->_cacheOb->setMetaData($mailbox, array('HICmodseq' => $status_res['highestmodseq'])); } @@ -2113,21 +1778,21 @@ abstract class Horde_Imap_Client_Base } break; - case self::FETCH_DATE: + case Horde_Imap_Client::FETCH_DATE: if (isset($cf[$k])) { $cache_field = 'HICdate'; $fetch_field = 'date'; } break; - case self::FETCH_SIZE: + case Horde_Imap_Client::FETCH_SIZE: if (isset($cf[$k])) { $cache_field = 'HICsize'; $fetch_field = 'size'; } break; - case self::FETCH_MODSEQ: + case Horde_Imap_Client::FETCH_MODSEQ: if (!isset($this->_init['enabled']['CONDSTORE'])) { unset($criteria[$k]); } @@ -2183,7 +1848,7 @@ abstract class Horde_Imap_Client_Base } if (!$seq) { - unset($crit[self::FETCH_UID]); + unset($crit[Horde_Imap_Client::FETCH_UID]); } if (!empty($crit)) { @@ -2260,7 +1925,7 @@ abstract class Horde_Imap_Client_Base */ public function store($mailbox, $options = array()) { - $this->openMailbox($mailbox, self::OPEN_READWRITE); + $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_READWRITE); if (!empty($options['unchangedsince']) && !isset($this->_init['enabled']['CONDSTORE'])) { @@ -2276,7 +1941,7 @@ abstract class Horde_Imap_Client_Base * * @param array $options Additional options. * - * @return array See Horde_Imap_Client::store(). + * @return array See self::store(). */ abstract protected function _store($options); @@ -2306,7 +1971,7 @@ abstract class Horde_Imap_Client_Base */ public function copy($source, $dest, $options = array()) { - $this->openMailbox($source, empty($options['move']) ? self::OPEN_AUTO : self::OPEN_READWRITE); + $this->openMailbox($source, empty($options['move']) ? Horde_Imap_Client::OPEN_AUTO : Horde_Imap_Client::OPEN_READWRITE); return $this->_copy(Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($dest), $options); } @@ -2570,7 +2235,7 @@ abstract class Horde_Imap_Client_Base { $search = new Horde_Imap_Client_Search_Query(); $search->sequence($ids, $seq); - $res = $this->search($this->_selected, $search, array('sort' => array(self::SORT_ARRIVAL))); + $res = $this->search($this->_selected, $search, array('sort' => array(Horde_Imap_Client::SORT_ARRIVAL))); $ret = array('uids' => $res['sort']); if ($seq) { if (empty($ids)) { @@ -2615,7 +2280,7 @@ abstract class Horde_Imap_Client_Base $mailbox = empty($options['mailbox']) ? $this->_selected : $options['mailbox']; if (empty($options['uidvalid'])) { - $status_res = $this->status($mailbox, self::STATUS_HIGHESTMODSEQ | self::STATUS_UIDVALIDITY); + $status_res = $this->status($mailbox, Horde_Imap_Client::STATUS_HIGHESTMODSEQ | Horde_Imap_Client::STATUS_UIDVALIDITY); $uidvalid = $status_res['uidvalidity']; if (isset($status_res['highestmodseq'])) { $highestmodseq[] = $status_res['highestmodseq']; @@ -2633,19 +2298,19 @@ abstract class Horde_Imap_Client_Base while (list($label, $val) = each($v)) { switch ($label) { case 'structure': - if (isset($cf[self::FETCH_STRUCTURE])) { + if (isset($cf[Horde_Imap_Client::FETCH_STRUCTURE])) { $tmp[is_array($val) ? 'HICstructa' : 'HICstructm'] = $val; } break; case 'envelope': - if (isset($cf[self::FETCH_ENVELOPE])) { + if (isset($cf[Horde_Imap_Client::FETCH_ENVELOPE])) { $tmp['HICenv'] = $val; } break; case 'flags': - if (isset($cf[self::FETCH_FLAGS])) { + if (isset($cf[Horde_Imap_Client::FETCH_FLAGS])) { /* A FLAGS FETCH can only occur if we are in the * mailbox. So either HIGHESTMODSEQ has already been * updated or the flag FETCHs will provide the new @@ -2664,13 +2329,13 @@ abstract class Horde_Imap_Client_Base break; case 'date': - if (isset($cf[self::FETCH_DATE])) { + if (isset($cf[Horde_Imap_Client::FETCH_DATE])) { $tmp['HICdate'] = $val; } break; case 'size': - if (isset($cf[self::FETCH_SIZE])) { + if (isset($cf[Horde_Imap_Client::FETCH_SIZE])) { $tmp['HICsize'] = $val; } break; diff --git a/framework/Imap_Client/lib/Horde/Imap/Client/Cclient.php b/framework/Imap_Client/lib/Horde/Imap/Client/Cclient.php index cf6c4f80f..b9c071e1c 100644 --- a/framework/Imap_Client/lib/Horde/Imap/Client/Cclient.php +++ b/framework/Imap_Client/lib/Horde/Imap/Client/Cclient.php @@ -314,7 +314,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base protected function _openMailbox($mailbox, $mode) { $this->login(); - $flag = ($mode == self::OPEN_READONLY) ? OP_READONLY : 0; + $flag = ($mode == Horde_Imap_Client::OPEN_READONLY) ? OP_READONLY : 0; $old_error = error_reporting(0); if (version_compare(PHP_VERSION, '5.2.1') != -1) { @@ -432,7 +432,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base $this->login(); switch ($mode) { - case self::MBOX_ALL: + case Horde_Imap_Client::MBOX_ALL: if (!empty($options['flat'])) { $mboxes = $this->_getMailboxList($pattern, $mode); return (empty($options['utf8'])) ? $mboxes : array_map(array('Horde_Imap_Client_Utf7imap', 'Utf7ImapToUtf8'), $mboxes); @@ -440,18 +440,18 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base $check = false; break; - case self::MBOX_SUBSCRIBED: - case self::MBOX_UNSUBSCRIBED: - $sub = $this->_getMailboxList($pattern, self::MBOX_SUBSCRIBED); + case Horde_Imap_Client::MBOX_SUBSCRIBED: + case Horde_Imap_Client::MBOX_UNSUBSCRIBED: + $sub = $this->_getMailboxList($pattern, Horde_Imap_Client::MBOX_SUBSCRIBED); if (!empty($options['flat'])) { if (!empty($options['utf8'])) { $sub = array_map(array('Horde_Imap_Client_Utf7imap', 'Utf7ImapToUtf8'), $sub); } - if ($mode == self::MBOX_SUBSCRIBED) { + if ($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) { return $sub; } - $mboxes = $this->_getMailboxList($pattern, self::MBOX_ALL); + $mboxes = $this->_getMailboxList($pattern, Horde_Imap_Client::MBOX_ALL); if (!empty($options['utf8'])) { $sub = array_map(array('Horde_Imap_Client_Utf7imap', 'Utf7ImapToUtf8'), $sub); } @@ -480,9 +480,9 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base $mbox = substr($val->name, strpos($val->name, '}') + 1); if ($check && - ((($mode == self::MBOX_UNSUBSCRIBED) && + ((($mode == Horde_Imap_Client::MBOX_UNSUBSCRIBED) && isset($sub[$mbox])) || - (($mode == self::MBOX_SUBSCRIBED) && + (($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) && !isset($sub[$mbox])))) { continue; } @@ -524,7 +524,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base $mboxes = array(); $old_error = error_reporting(0); - if ($mode != self::MBOX_ALL) { + if ($mode != Horde_Imap_Client::MBOX_ALL) { $res = imap_list($this->_stream, $this->_connString(), $pattern); } else { $res = imap_lsub($this->_stream, $this->_connString(), $pattern); @@ -556,19 +556,19 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base /* If FLAGS/PERMFLAGS/HIGHESTMODSEQ/UIDNOTSTICKY are needed, we must * use the Socket driver. */ - if (($flags & self::STATUS_FLAGS) || - ($flags & self::STATUS_PERMFLAGS) || - ($flags & self::STATUS_HIGHESTMODSEQ) || - ($flags & self::STATUS_UIDNOTSTICKY)) { + if (($flags & Horde_Imap_Client::STATUS_FLAGS) || + ($flags & Horde_Imap_Client::STATUS_PERMFLAGS) || + ($flags & Horde_Imap_Client::STATUS_HIGHESTMODSEQ) || + ($flags & Horde_Imap_Client::STATUS_UIDNOTSTICKY)) { return $this->_getSocket()->status($mailbox, $flags); } $items = array( - self::STATUS_MESSAGES => SA_MESSAGES, - self::STATUS_RECENT => SA_RECENT, - self::STATUS_UIDNEXT => SA_UIDNEXT, - self::STATUS_UIDVALIDITY => SA_UIDVALIDITY, - self::STATUS_UNSEEN => SA_UNSEEN + Horde_Imap_Client::STATUS_MESSAGES => SA_MESSAGES, + Horde_Imap_Client::STATUS_RECENT => SA_RECENT, + Horde_Imap_Client::STATUS_UIDNEXT => SA_UIDNEXT, + Horde_Imap_Client::STATUS_UIDVALIDITY => SA_UIDVALIDITY, + Horde_Imap_Client::STATUS_UNSEEN => SA_UNSEEN ); $c_flag = 0; @@ -587,10 +587,10 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } } - if ($flags & self::STATUS_FIRSTUNSEEN) { + if ($flags & Horde_Imap_Client::STATUS_FIRSTUNSEEN) { $search_query = new Horde_Imap_Client_Search_Query(); $search_query->flag('\\unseen', false); - $search = $this->search($mailbox, $search_query, array('results' => array(self::SORT_RESULTS_MIN), 'sequence' => true)); + $search = $this->search($mailbox, $search_query, array('results' => array(Horde_Imap_Client::SORT_RESULTS_MIN), 'sequence' => true)); if (is_null($res)) { return array('firstunseen' => $search['min']); @@ -635,7 +635,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base while (list(,$val) = each($data)) { $old_error = error_reporting(0); $text = is_resource($val['data']) ? stream_get_contents($val['data']) : $val['data']; - $res = imap_append($this->_stream, $this->_connString($mailbox), $this->removeBareNewlines($text), empty($val['flags']) ? null : implode(' ', $val['flags'])); + $res = imap_append($this->_stream, $this->_connString($mailbox), $this->_utils->removeBareNewlines($text), empty($val['flags']) ? null : implode(' ', $val['flags'])); error_reporting($old_error); if ($res === false) { @@ -680,7 +680,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base if (!empty($options['expunge'])) { $this->expunge($this->_selected); } - $this->openMailbox($this->_selected, self::OPEN_READONLY); + $this->openMailbox($this->_selected, Horde_Imap_Client::OPEN_READONLY); } /** @@ -759,7 +759,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base if ($options['_query']['imap4'] || (!empty($options['sort']) && ((count($options['sort']) > 1) || - in_array(self::SORT_REVERSE, $options['sort'])))) { + in_array(Horde_Imap_Client::SORT_REVERSE, $options['sort'])))) { return $this->_getSocket()->search($this->_selected, $query, $options); } @@ -768,13 +768,13 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base $res = imap_search($this->_stream, $options['_query']['query'], empty($options['sequence']) ? SE_UID : 0, $options['_query']['charset']); } else { $sort_criteria = array( - self::SORT_ARRIVAL => SORTARRIVAL, - self::SORT_CC => SORTCC, - self::SORT_DATE => SORTDATE, - self::SORT_FROM => SORTFROM, - self::SORT_SIZE => SORTSIZE, - self::SORT_SUBJECT => SORTSUBJECT, - self::SORT_TO => SORTTO + Horde_Imap_Client::SORT_ARRIVAL => SORTARRIVAL, + Horde_Imap_Client::SORT_CC => SORTCC, + Horde_Imap_Client::SORT_DATE => SORTDATE, + Horde_Imap_Client::SORT_FROM => SORTFROM, + Horde_Imap_Client::SORT_SIZE => SORTSIZE, + Horde_Imap_Client::SORT_SUBJECT => SORTSUBJECT, + Horde_Imap_Client::SORT_TO => SORTTO ); $res = imap_sort($this->_stream, $sort_criteria[reset($options['sort'])], 0, empty($options['sequence']) ? SE_UID : 0, $options['_query']['query'], $options['_query']['charset']); @@ -785,19 +785,19 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base $ret = array(); foreach ($options['results'] as $val) { switch ($val) { - case self::SORT_RESULTS_COUNT: + case Horde_Imap_Client::SORT_RESULTS_COUNT: $ret['count'] = count($res); break; - case self::SORT_RESULTS_MATCH: + case Horde_Imap_Client::SORT_RESULTS_MATCH: $ret[empty($options['sort']) ? 'match' : 'sort'] = $res; break; - case self::SORT_RESULTS_MAX: + case Horde_Imap_Client::SORT_RESULTS_MAX: $ret['max'] = empty($res) ? null : max($res); break; - case self::SORT_RESULTS_MIN: + case Horde_Imap_Client::SORT_RESULTS_MIN: $ret['min'] = empty($res) ? null : min($res); break; } @@ -848,7 +848,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base * and does not support defining search criteria. */ if (!empty($options['search']) || (!empty($options['criteria']) && - $options['criteria'] != self::THREAD_REFERENCES)) { + $options['criteria'] != Horde_Imap_Client::THREAD_REFERENCES)) { return $this->_getSocket()->thread($this->_selected, $options); } @@ -944,7 +944,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base // These options are not supported by this driver. if (!empty($options['changedsince']) || - (reset($options['ids']) == self::USE_SEARCHRES)) { + (reset($options['ids']) == Horde_Imap_Client::USE_SEARCHRES)) { return $this->_getSocket()->fetch($this->_selected, $criteria, $options); } @@ -952,7 +952,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base $seq = '1:*'; $options['ids'] = range(1, imap_num_msg($this->_stream)); } else { - $seq = $this->toSequenceString($options['ids']); + $seq = $this->_utils->toSequenceString($options['ids']); } $ret = array_combine($options['ids'], array_fill(0, count($options['ids']), array())); @@ -963,7 +963,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } switch ($type) { - case self::FETCH_STRUCTURE: + case Horde_Imap_Client::FETCH_STRUCTURE: // 'noext' has no effect in this driver foreach ($options['ids'] as $id) { $structure = imap_fetchstructure($this->_stream, $id, empty($options['sequence']) ? FT_UID : 0); @@ -976,7 +976,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } break; - case self::FETCH_FULLMSG: + case Horde_Imap_Client::FETCH_FULLMSG: foreach ($options['ids'] as $id) { $tmp = imap_fetchheader($this->_stream, $id, (empty($options['sequence']) ? FT_UID : 0) | FT_PREFETCHTEXT) . imap_body($this->_stream, $id, (empty($options['sequence']) ? FT_UID : 0) | (empty($c_val['peek']) ? 0 : FT_PEEK)); @@ -988,10 +988,10 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } break; - case self::FETCH_HEADERTEXT: - case self::FETCH_BODYPART: + case Horde_Imap_Client::FETCH_HEADERTEXT: + case Horde_Imap_Client::FETCH_BODYPART: foreach ($c_val as $val) { - if ($type == self::FETCH_HEADERTEXT) { + if ($type == Horde_Imap_Client::FETCH_HEADERTEXT) { $label = 'headertext'; /* imap_fetchbody() can return header parts for a * given MIME part by appending '.0' (or 0 for the @@ -1029,7 +1029,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } break; - case self::FETCH_BODYTEXT: + case Horde_Imap_Client::FETCH_BODYTEXT: foreach ($c_val as $val) { // This is the base body. This is easily obtained via // imap_body(). @@ -1064,9 +1064,9 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } break; - case self::FETCH_MIMEHEADER: - case self::FETCH_HEADERS: - case self::FETCH_MODSEQ: + case Horde_Imap_Client::FETCH_MIMEHEADER: + case Horde_Imap_Client::FETCH_HEADERS: + case Horde_Imap_Client::FETCH_MODSEQ: // Can't do it. Nope. Nada. Without heavy duty parsing of the // full imap_body() object, it is impossible to retrieve the // MIME headers for each individual part. Ship it off to @@ -1074,15 +1074,15 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base // This goes for header field searches also. // MODSEQ isn't available in c-client either. switch ($type) { - case self::FETCH_MIMEHEADER: + case Horde_Imap_Client::FETCH_MIMEHEADER: $label = 'mimeheader'; break; - case self::FETCH_HEADERS: + case Horde_Imap_Client::FETCH_HEADERS: $label = 'headers'; break; - case self::FETCH_MODSEQ: + case Horde_Imap_Client::FETCH_MODSEQ: $label = 'modseq'; break; } @@ -1095,7 +1095,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } break; - case self::FETCH_ENVELOPE: + case Horde_Imap_Client::FETCH_ENVELOPE: if (is_null($hdrinfo)) { $hdrinfo = array(); foreach ($options['ids'] as $id) { @@ -1136,7 +1136,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } break; - case self::FETCH_FLAGS: + case Horde_Imap_Client::FETCH_FLAGS: if (is_null($overview)) { $overview = imap_fetch_overview($this->_stream, $seq, empty($options['sequence']) ? FT_UID : 0); if (!$overview) { @@ -1156,7 +1156,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } break; - case self::FETCH_DATE: + case Horde_Imap_Client::FETCH_DATE: if (is_null($hdrinfo)) { $hdrinfo = array(); foreach ($options['ids'] as $id) { @@ -1173,7 +1173,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } break; - case self::FETCH_SIZE: + case Horde_Imap_Client::FETCH_SIZE: if (!is_null($hdrinfo)) { foreach ($options['ids'] as $id) { $ret[$id]['size'] = $hdrinfo[$id]->Size; @@ -1192,7 +1192,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } break; - case self::FETCH_UID: + case Horde_Imap_Client::FETCH_UID: if (empty($options['sequence'])) { foreach ($options['ids'] as $id) { $ret[$id]['uid'] = $id; @@ -1211,7 +1211,7 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base } break; - case self::FETCH_SEQ: + case Horde_Imap_Client::FETCH_SEQ: if (!empty($options['sequence'])) { foreach ($options['ids'] as $id) { $ret[$id]['seq'] = $id; @@ -1328,14 +1328,14 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base // options, nor does it support using stored searches. if (!empty($options['unchangedsince']) || !empty($options['replace']) || - (reset($options['ids']) == self::USE_SEARCHRES)) { + (reset($options['ids']) == Horde_Imap_Client::USE_SEARCHRES)) { // Requires Socket driver. return $this->_getSocket()->store($this->_selected, $options); } $seq = empty($options['ids']) ? '1:*' - : $this->toSequenceString($options['ids']); + : $this->_utils->toSequenceString($options['ids']); $old_error = error_reporting(0); @@ -1378,14 +1378,14 @@ class Horde_Imap_Client_Cclient extends Horde_Imap_Client_Base $opts |= CP_MOVE; } - if (reset($options['ids']) == self::USE_SEARCHRES) { + if (reset($options['ids']) == Horde_Imap_Client::USE_SEARCHRES) { // Requires Socket driver. return $this->_getSocket()->copy($this->_selected, $options); } $seq = empty($options['ids']) ? '1:*' - : $this->toSequenceString($options['ids']); + : $this->_utils->toSequenceString($options['ids']); $old_error = error_reporting(0); $res = imap_mail_copy($this->_stream, $seq, $this->_connString($dest), $opts); diff --git a/framework/Imap_Client/lib/Horde/Imap/Client/Cclient/Pop3.php b/framework/Imap_Client/lib/Horde/Imap/Client/Cclient/Pop3.php index a68840533..329b3286a 100644 --- a/framework/Imap_Client/lib/Horde/Imap/Client/Cclient/Pop3.php +++ b/framework/Imap_Client/lib/Horde/Imap/Client/Cclient/Pop3.php @@ -238,7 +238,7 @@ class Horde_Imap_Client_Cclient_Pop3 extends Horde_Imap_Client_Cclient if ($search_query['imap4'] || (!empty($options['sort']) && ((count($options['sort']) > 1) || - in_array(self::SORT_REVERSE, $options['sort'])))) { + in_array(Horde_Imap_Client::SORT_REVERSE, $options['sort'])))) { throw new Horde_Imap_Client_Exception('Unsupported search criteria on POP3 server.', Horde_Imap_Client_Exception::POP3_NOTSUPPORTED); } @@ -282,7 +282,7 @@ class Horde_Imap_Client_Cclient_Pop3 extends Horde_Imap_Client_Cclient * and does not support defining search criteria. */ if (!empty($options['search']) || (!empty($options['criteria']) && - $options['criteria'] != self::THREAD_REFERENCES)) { + $options['criteria'] != Horde_Imap_Client::THREAD_REFERENCES)) { throw new Horde_Imap_Client_Exception('Unsupported threading criteria on POP3 server.', Horde_Imap_Client_Exception::POP3_NOTSUPPORTED); } @@ -315,7 +315,7 @@ class Horde_Imap_Client_Cclient_Pop3 extends Horde_Imap_Client_Cclient protected function _fetch($criteria, $options) { // No support for FETCH_MIMEHEADER or FETCH_HEADERS - $nosupport = array(self::FETCH_MIMEHEADER, self::FETCH_HEADERS); + $nosupport = array(Horde_Imap_Client::FETCH_MIMEHEADER, Horde_Imap_Client::FETCH_HEADERS); reset($criteria); while (list($val,) = each($criteria)) { diff --git a/framework/Imap_Client/lib/Horde/Imap/Client/Search/Query.php b/framework/Imap_Client/lib/Horde/Imap/Client/Search/Query.php index 392e283cc..242e5f4a1 100644 --- a/framework/Imap_Client/lib/Horde/Imap/Client/Search/Query.php +++ b/framework/Imap_Client/lib/Horde/Imap/Client/Search/Query.php @@ -66,6 +66,21 @@ class Horde_Imap_Client_Search_Query protected $_exts = array(); /** + * The Horde_Imap_Client_Utils object + * + * @var Horde_Imap_Client_Utils + */ + protected $_utils = null; + + /** + * Constructor + */ + public function __construct() + { + $this->_utils = new Horde_Imap_Client_Utils(); + } + + /** * Sets the charset of the search text. * * @param string $charset The charset to use for the search. @@ -140,7 +155,7 @@ class Horde_Imap_Client_Search_Query $tmp .= 'HEADER '; $imap4 = true; } - $cmds[] = $tmp . $val['header'] . ' ' . Horde_Imap_Client::escape($val['text']); + $cmds[] = $tmp . $val['header'] . ' ' . $this->_utils->escape($val['text']); } } @@ -152,7 +167,7 @@ class Horde_Imap_Client_Search_Query // NOT searches were not in IMAP2 $imap4 = true; } - $cmds[] = $tmp . $val['type'] . ' ' . Horde_Imap_Client::escape($val['text']); + $cmds[] = $tmp . $val['type'] . ' ' . $this->_utils->escape($val['text']); } } @@ -205,7 +220,7 @@ class Horde_Imap_Client_Search_Query 'MODSEQ ' . (is_null($ptr['modseq']['name']) ? '' - : Horde_Imap_Client::escape($ptr['modseq']['name']) . ' ' . $ptr['modseq']['type'] . ' ') . + : $this->_utils->escape($ptr['modseq']['name']) . ' ' . $ptr['modseq']['type'] . ' ') . $ptr['modseq']['value']; } @@ -372,7 +387,7 @@ class Horde_Imap_Client_Search_Query if (empty($ids)) { $ids = '1:*'; } else { - $ids = Horde_Imap_Client::toSequenceString($ids); + $ids = $this->_utils->toSequenceString($ids); } $this->_search['sequence'] = array( 'ids' => $ids, diff --git a/framework/Imap_Client/lib/Horde/Imap/Client/Socket.php b/framework/Imap_Client/lib/Horde/Imap/Client/Socket.php index 6536d2a11..9a400381e 100644 --- a/framework/Imap_Client/lib/Horde/Imap/Client/Socket.php +++ b/framework/Imap_Client/lib/Horde/Imap/Client/Socket.php @@ -522,7 +522,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base break; case 'LOGIN': - $this->_sendLine('LOGIN ' . $this->escape($this->_params['username']) . ' ' . $this->escape($this->_params['password']), array('debug' => '[LOGIN Command]')); + $this->_sendLine('LOGIN ' . $this->_utils->escape($this->_params['username']) . ' ' . $this->_utils->escape($this->_params['password']), array('debug' => '[LOGIN Command]')); break; case 'PLAIN': @@ -616,7 +616,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } else { $cmd = '('; foreach ($info as $key => $val) { - $cmd .= $this->escape(strtolower($key)) . ' ' . $this->escape($val); + $cmd .= $this->_utils->escape(strtolower($key)) . ' ' . $this->_utils->escape($val); } $cmd .= ')'; } @@ -670,7 +670,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base { $cmd = array(); foreach ($langs as $val) { - $cmd[] = $this->escape($val); + $cmd[] = $this->_utils->escape($val); } try { @@ -776,7 +776,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $this->_temp['qresyncmbox'] = $mailbox; } - $cmd = (($mode == self::OPEN_READONLY) ? 'EXAMINE' : 'SELECT') . ' ' . $this->escape($mailbox); + $cmd = (($mode == Horde_Imap_Client::OPEN_READONLY) ? 'EXAMINE' : 'SELECT') . ' ' . $this->_utils->escape($mailbox); /* If QRESYNC is available, synchronize the mailbox. */ if ($qresync) { @@ -795,7 +795,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base * response handlers. * TODO: Use 4th parameter (useful if we keep a sequence * number->UID lookup in the future). */ - $cmd .= ' (QRESYNC (' . $metadata['uidvalid'] . ' ' . $metadata['HICmodseq'] . ' ' . $this->toSequenceString($uids) . '))'; + $cmd .= ' (QRESYNC (' . $metadata['uidvalid'] . ' ' . $metadata['HICmodseq'] . ' ' . $this->_utils->toSequenceString($uids) . '))'; } } } elseif (!isset($this->_init['enabled']['CONDSTORE']) && @@ -843,7 +843,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $this->login(); // CREATE returns no untagged information (RFC 3501 [6.3.3]) - $this->_sendLine('CREATE ' . $this->escape($mailbox)); + $this->_sendLine('CREATE ' . $this->_utils->escape($mailbox)); } /** @@ -864,7 +864,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base try { // DELETE returns no untagged information (RFC 3501 [6.3.4]) - $this->_sendLine('DELETE ' . $this->escape($mailbox)); + $this->_sendLine('DELETE ' . $this->_utils->escape($mailbox)); } catch (Horde_Imap_Client_Exception $e) { // Some IMAP servers won't allow a mailbox delete unless all // messages in that mailbox are deleted. @@ -895,7 +895,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $this->login(); // RENAME returns no untagged information (RFC 3501 [6.3.5]) - $this->_sendLine('RENAME ' . $this->escape($old) . ' ' . $this->escape($new)); + $this->_sendLine('RENAME ' . $this->_utils->escape($old) . ' ' . $this->_utils->escape($new)); } /** @@ -911,7 +911,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base // SUBSCRIBE/UNSUBSCRIBE returns no untagged information (RFC 3501 // [6.3.6 & 6.3.7]) - $this->_sendLine(($subscribe ? '' : 'UN') . 'SUBSCRIBE ' . $this->escape($mailbox)); + $this->_sendLine(($subscribe ? '' : 'UN') . 'SUBSCRIBE ' . $this->_utils->escape($mailbox)); } /** @@ -931,11 +931,11 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base // Get the list of subscribed/unsubscribed mailboxes. Since LSUB is // not guaranteed to have correct attributes, we must use LIST to // ensure we receive the correct information. - if ($mode != self::MBOX_ALL) { - $subscribed = $this->_getMailboxList($pattern, self::MBOX_SUBSCRIBED, array('flat' => true)); + if ($mode != Horde_Imap_Client::MBOX_ALL) { + $subscribed = $this->_getMailboxList($pattern, Horde_Imap_Client::MBOX_SUBSCRIBED, array('flat' => true)); // If mode is subscribed, and 'flat' option is true, we can // return now. - if (($mode == self::MBOX_SUBSCRIBED) && !empty($options['flat'])) { + if (($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) && !empty($options['flat'])) { return $subscribed; } } else { @@ -959,7 +959,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base protected function _getMailboxList($pattern, $mode, $options, $subscribed = null) { - $check = (($mode != self::MBOX_ALL) && !is_null($subscribed)); + $check = (($mode != Horde_Imap_Client::MBOX_ALL) && !is_null($subscribed)); // Setup cache entry for use in _parseList() $t = &$this->_temp; @@ -970,7 +970,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base ); $t['listresponse'] = array(); - $this->_sendLine((($mode == self::MBOX_SUBSCRIBED) ? 'LSUB' : 'LIST') . ' "" ' . $this->escape($pattern)); + $this->_sendLine((($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) ? 'LSUB' : 'LIST') . ' "" ' . $this->_utils->escape($pattern)); return (empty($options['flat'])) ? $t['listresponse'] : array_values($t['listresponse']); } @@ -1033,31 +1033,31 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $search = null; $items = array( - self::STATUS_MESSAGES => 'messages', - self::STATUS_RECENT => 'recent', - self::STATUS_UIDNEXT => 'uidnext', - self::STATUS_UIDVALIDITY => 'uidvalidity', - self::STATUS_UNSEEN => 'unseen', - self::STATUS_FIRSTUNSEEN => 'firstunseen', - self::STATUS_FLAGS => 'flags', - self::STATUS_PERMFLAGS => 'permflags', - self::STATUS_UIDNOTSTICKY => 'uidnotsticky', + Horde_Imap_Client::STATUS_MESSAGES => 'messages', + Horde_Imap_Client::STATUS_RECENT => 'recent', + Horde_Imap_Client::STATUS_UIDNEXT => 'uidnext', + Horde_Imap_Client::STATUS_UIDVALIDITY => 'uidvalidity', + Horde_Imap_Client::STATUS_UNSEEN => 'unseen', + Horde_Imap_Client::STATUS_FIRSTUNSEEN => 'firstunseen', + Horde_Imap_Client::STATUS_FLAGS => 'flags', + Horde_Imap_Client::STATUS_PERMFLAGS => 'permflags', + Horde_Imap_Client::STATUS_UIDNOTSTICKY => 'uidnotsticky', ); /* Don't include 'highestmodseq' return if server does not support it. * OK to use queryCapability('CONDSTORE') here because we may not have * yet sent an enabling command. */ if ($this->queryCapability('CONDSTORE')) { - $items[self::STATUS_HIGHESTMODSEQ] = 'highestmodseq'; + $items[Horde_Imap_Client::STATUS_HIGHESTMODSEQ] = 'highestmodseq'; } /* If FLAGS/PERMFLAGS/UIDNOTSTICKY/FIRSTUNSEEN are needed, we must do * a SELECT/EXAMINE to get this information (data will be caught in * the code below). */ - if (($flags & self::STATUS_FIRSTUNSEEN) || - ($flags & self::STATUS_FLAGS) || - ($flags & self::STATUS_PERMFLAGS) || - ($flags & self::STATUS_UIDNOTSTICKY)) { + if (($flags & Horde_Imap_Client::STATUS_FIRSTUNSEEN) || + ($flags & Horde_Imap_Client::STATUS_FLAGS) || + ($flags & Horde_Imap_Client::STATUS_PERMFLAGS) || + ($flags & Horde_Imap_Client::STATUS_UIDNOTSTICKY)) { $this->openMailbox($mailbox); } else { $this->login(); @@ -1069,17 +1069,17 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base if (isset($this->_temp['mailbox'][$val])) { $data[$val] = $this->_temp['mailbox'][$val]; } else { - if ($key == self::STATUS_UIDNOTSTICKY) { + if ($key == Horde_Imap_Client::STATUS_UIDNOTSTICKY) { /* In the absence of uidnotsticky information, or * if UIDPLUS is not supported, we assume the UIDs * are sticky. */ $data[$val] = false; - } elseif (in_array($key, array(self::STATUS_FIRSTUNSEEN, self::STATUS_UNSEEN))) { + } elseif (in_array($key, array(Horde_Imap_Client::STATUS_FIRSTUNSEEN, Horde_Imap_Client::STATUS_UNSEEN))) { /* If we already know there are no messages in the * current mailbox, we know there is no * firstunseen and unseen info also. */ if (empty($this->_temp['mailbox']['messages'])) { - $data[$val] = ($key == self::STATUS_FIRSTUNSEEN) ? null : 0; + $data[$val] = ($key == Horde_Imap_Client::STATUS_FIRSTUNSEEN) ? null : 0; } else { /* RFC 3501 [6.3.1] - FIRSTUNSEEN information * is not mandatory. If missing EXAMINE/SELECT @@ -1088,10 +1088,10 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base if (is_null($search)) { $search_query = new Horde_Imap_Client_Search_Query(); $search_query->flag('\\seen', false); - $search = $this->search($mailbox, $search_query, array('results' => array(($key == self::STATUS_FIRSTUNSEEN) ? self::SORT_RESULTS_MIN : self::SORT_RESULTS_COUNT), 'sequence' => true)); + $search = $this->search($mailbox, $search_query, array('results' => array(($key == Horde_Imap_Client::STATUS_FIRSTUNSEEN) ? Horde_Imap_Client::SORT_RESULTS_MIN : Horde_Imap_Client::SORT_RESULTS_COUNT), 'sequence' => true)); } - $data[$val] = $search[($key == self::STATUS_FIRSTUNSEEN) ? 'min' : 'count']; + $data[$val] = $search[($key == Horde_Imap_Client::STATUS_FIRSTUNSEEN) ? 'min' : 'count']; } } } @@ -1106,7 +1106,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } $this->_temp['status'] = array(); - $this->_sendLine('STATUS ' . $this->escape($mailbox) . ' (' . implode(' ', array_map('strtoupper', $query)) . ')'); + $this->_sendLine('STATUS ' . $this->_utils->escape($mailbox) . ' (' . implode(' ', array_map('strtoupper', $query)) . ')'); return $this->_temp['status']; } @@ -1166,7 +1166,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base reset($data); while (list(,$m_data) = each($data)) { if (!$i++ || !$multiappend) { - $cmd = 'APPEND ' . $this->escape($mailbox); + $cmd = 'APPEND ' . $this->_utils->escape($mailbox); } else { $cmd = ''; $notag = true; @@ -1177,7 +1177,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } if (!empty($m_data['internaldate'])) { - $cmd .= ' ' . $this->escape($m_data['internaldate']->format('j-M-Y H:i:s O')); + $cmd .= ' ' . $this->_utils->escape($m_data['internaldate']->format('j-M-Y H:i:s O')); } /* @todo There is no way I am aware of to determine the length of @@ -1187,7 +1187,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base * for now, simply grab the contents of the stream and do a * strlen() call to determine the literal size to send to the * IMAP server. */ - $text = $this->removeBareNewlines(is_resource($m_data['data']) ? stream_get_contents($m_data['data']) : $m_data['data']); + $text = $this->_utils->removeBareNewlines(is_resource($m_data['data']) ? stream_get_contents($m_data['data']) : $m_data['data']); $datalength = strlen($text); /* RFC 3516/4466 says we should be able to append binary data @@ -1300,19 +1300,19 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $uid_string = '1:*'; } elseif ($uidplus) { /* UID EXPUNGE command needs UIDs. */ - if (reset($options['ids']) === self::USE_SEARCHRES) { + if (reset($options['ids']) === Horde_Imap_Client::USE_SEARCHRES) { $uid_string = '$'; } elseif ($seq) { - $results = array(self::SORT_RESULTS_MATCH); + $results = array(Horde_Imap_Client::SORT_RESULTS_MATCH); if ($this->queryCapability('SEARCHRES')) { - $results[] = self::SORT_RESULTS_SAVE; + $results[] = Horde_Imap_Client::SORT_RESULTS_SAVE; } $s_res = $this->search($mailbox, null, array('results' => $results)); - $uid_string = (in_array(self::SORT_RESULTS_SAVE, $results) && !empty($s_res['save'])) + $uid_string = (in_array(Horde_Imap_Client::SORT_RESULTS_SAVE, $results) && !empty($s_res['save'])) ? '$' - : $this->toSequenceString($s_res['match']); + : $this->_utils->toSequenceString($s_res['match']); } else { - $uid_string = $this->toSequenceString($options['ids']); + $uid_string = $this->_utils->toSequenceString($options['ids']); } } else { /* Without UIDPLUS, need to temporarily unflag all messages marked @@ -1320,7 +1320,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base * searches to accomplish this goal. */ $search_query = new Horde_Imap_Client_Search_Query(); $search_query->flag('\\deleted', true); - if (reset($options['ids']) === self::USE_SEARCHRES) { + if (reset($options['ids']) === Horde_Imap_Client::USE_SEARCHRES) { $search_query->previousSearch(true); } else { $search_query->sequence($options['ids'], $seq, true); @@ -1338,7 +1338,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base * we will get VANISHED responses, so we need to do this. */ if ($use_cache && is_null($s_res)) { /* Keys in $s_res['sort'] start at 0, not 1. */ - $s_res = $this->search($mailbox, null, array('sort' => array(self::SORT_ARRIVAL))); + $s_res = $this->search($mailbox, null, array('sort' => array(Horde_Imap_Client::SORT_ARRIVAL))); } $tmp = &$this->_temp; @@ -1412,13 +1412,13 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base * the tagged response. */ if (is_array($data[0])) { if (strtoupper(reset($data[0])) == 'EARLIER') { - $this->_cacheOb->deleteMsgs($this->_temp['mailbox']['name'], $this->fromSequenceString($data[1])); + $this->_cacheOb->deleteMsgs($this->_temp['mailbox']['name'], $this->_utils->fromSequenceString($data[1])); } } else { /* The second form is just VANISHED. This is returned from an * EXPUNGE command and will be processed in _expunge() (since * we need to adjust message counts in the current mailbox). */ - $this->_temp['vanished'] = $this->fromSequenceString($data[0]); + $this->_temp['vanished'] = $this->_utils->fromSequenceString($data[0]); } } @@ -1458,22 +1458,22 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } $sort_criteria = array( - self::SORT_ARRIVAL => 'ARRIVAL', - self::SORT_CC => 'CC', - self::SORT_DATE => 'DATE', - self::SORT_FROM => 'FROM', - self::SORT_REVERSE => 'REVERSE', - self::SORT_SIZE => 'SIZE', - self::SORT_SUBJECT => 'SUBJECT', - self::SORT_TO => 'TO' + Horde_Imap_Client::SORT_ARRIVAL => 'ARRIVAL', + Horde_Imap_Client::SORT_CC => 'CC', + Horde_Imap_Client::SORT_DATE => 'DATE', + Horde_Imap_Client::SORT_FROM => 'FROM', + Horde_Imap_Client::SORT_REVERSE => 'REVERSE', + Horde_Imap_Client::SORT_SIZE => 'SIZE', + Horde_Imap_Client::SORT_SUBJECT => 'SUBJECT', + Horde_Imap_Client::SORT_TO => 'TO' ); $results_criteria = array( - self::SORT_RESULTS_COUNT => 'COUNT', - self::SORT_RESULTS_MATCH => 'ALL', - self::SORT_RESULTS_MAX => 'MAX', - self::SORT_RESULTS_MIN => 'MIN', - self::SORT_RESULTS_SAVE => 'SAVE' + Horde_Imap_Client::SORT_RESULTS_COUNT => 'COUNT', + Horde_Imap_Client::SORT_RESULTS_MATCH => 'ALL', + Horde_Imap_Client::SORT_RESULTS_MAX => 'MAX', + Horde_Imap_Client::SORT_RESULTS_MIN => 'MIN', + Horde_Imap_Client::SORT_RESULTS_SAVE => 'SAVE' ); // Check if the server supports server-side sorting (RFC 5256). @@ -1485,7 +1485,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base /* Make sure sort options are correct. If not, default to ARRIVAL * sort. */ if (count(array_intersect($options['sort'], array_keys($sort_criteria))) === 0) { - $options['sort'] = array(self::SORT_ARRIVAL); + $options['sort'] = array(Horde_Imap_Client::SORT_ARRIVAL); } } @@ -1495,7 +1495,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $results = array(); foreach ($options['results'] as $val) { if (isset($results_criteria[$val]) && - ($val != self::SORT_RESULTS_SAVE)) { + ($val != Horde_Imap_Client::SORT_RESULTS_SAVE)) { $results[] = $results_criteria[$val]; } } @@ -1545,23 +1545,23 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $ret = array(); foreach ($options['results'] as $val) { switch ($val) { - case self::SORT_RESULTS_COUNT: + case Horde_Imap_Client::SORT_RESULTS_COUNT: $ret['count'] = $esearch ? $er['count'] : count($sr); break; - case self::SORT_RESULTS_MATCH: + case Horde_Imap_Client::SORT_RESULTS_MATCH: $ret[$return_sort ? 'sort' : 'match'] = $sr; break; - case self::SORT_RESULTS_MAX: + case Horde_Imap_Client::SORT_RESULTS_MAX: $ret['max'] = $esearch ? (isset($er['max']) ? $er['max'] : null) : (empty($sr) ? null : max($sr)); break; - case self::SORT_RESULTS_MIN: + case Horde_Imap_Client::SORT_RESULTS_MIN: $ret['min'] = $esearch ? (isset($er['min']) ? $er['min'] : null) : (empty($sr) ? null : min($sr)); break; - case self::SORT_RESULTS_SAVE: + case Horde_Imap_Client::SORT_RESULTS_SAVE: $ret['save'] = $esearch ? empty($this->_temp['searchnotsaved']) : false; } } @@ -1622,7 +1622,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $tag = strtoupper($data[$i]); switch ($tag) { case 'ALL': - $this->_temp['searchresp'] = $this->fromSequenceString($val); + $this->_temp['searchresp'] = $this->_utils->fromSequenceString($val); break; case 'COUNT': @@ -1655,19 +1655,19 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $criteria = array(); foreach ($opts['sort'] as $val) { switch ($val) { - case self::SORT_DATE: - $criteria[self::FETCH_DATE] = true; + case Horde_Imap_Client::SORT_DATE: + $criteria[Horde_Imap_Client::FETCH_DATE] = true; // Fall through - case self::SORT_CC: - case self::SORT_FROM: - case self::SORT_SUBJECT: - case self::SORT_TO: - $criteria[self::FETCH_ENVELOPE] = true; + case Horde_Imap_Client::SORT_CC: + case Horde_Imap_Client::SORT_FROM: + case Horde_Imap_Client::SORT_SUBJECT: + case Horde_Imap_Client::SORT_TO: + $criteria[Horde_Imap_Client::FETCH_ENVELOPE] = true; break; - case self::SORT_SIZE: - $criteria[self::FETCH_SIZE] = true; + case Horde_Imap_Client::SORT_SIZE: + $criteria[Horde_Imap_Client::FETCH_SIZE] = true; break; } } @@ -1682,7 +1682,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $reverse = false; foreach ($opts['sort'] as $val) { - if ($val == self::SORT_REVERSE) { + if ($val == Horde_Imap_Client::SORT_REVERSE) { $reverse = true; continue; } @@ -1698,7 +1698,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } switch ($val) { - case self::SORT_ARRIVAL: + case Horde_Imap_Client::SORT_ARRIVAL: /* There is no requirement that IDs be returned in * sequence order (see RFC 4549 [4.3.1]). So we must sort * ourselves. */ @@ -1706,19 +1706,19 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base sort($sorted, SORT_NUMERIC); break; - case self::SORT_SIZE: + case Horde_Imap_Client::SORT_SIZE: foreach ($slice as $num) { $sorted[$num] = $fetch_res[$num]['size']; } asort($sorted, SORT_NUMERIC); break; - case self::SORT_CC: - case self::SORT_FROM: - case self::SORT_TO: - if ($val == self::SORT_CC) { + case Horde_Imap_Client::SORT_CC: + case Horde_Imap_Client::SORT_FROM: + case Horde_Imap_Client::SORT_TO: + if ($val == Horde_Imap_Client::SORT_CC) { $field = 'cc'; - } elseif ($val = self::SORT_FROM) { + } elseif ($val = Horde_Imap_Client::SORT_FROM) { $field = 'from'; } else { $field = 'to'; @@ -1732,18 +1732,18 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base asort($sorted, SORT_LOCALE_STRING); break; - case self::SORT_DATE: + case Horde_Imap_Client::SORT_DATE: // Date sorting rules in RFC 5256 [2.2] $sorted = $this->_getSentDates($fetch_res, $slice); asort($sorted, SORT_NUMERIC); break; - case self::SORT_SUBJECT: + case Horde_Imap_Client::SORT_SUBJECT: // Subject sorting rules in RFC 5256 [2.1] foreach ($slice as $num) { $sorted[$num] = empty($fetch_res[$num]['envelope']['subject']) ? '' - : $this->getBaseSubject($fetch_res[$num]['envelope']['subject']); + : $this->_utils->getBaseSubject($fetch_res[$num]['envelope']['subject']); } asort($sorted, SORT_LOCALE_STRING); break; @@ -1829,7 +1829,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $cmd = array(); foreach (explode(' ', $comparator) as $val) { - $cmd[] = $this->escape($val); + $cmd[] = $this->_utils->escape($val); } $this->_sendLine('COMPARATOR ' . implode(' ', $cmd)); @@ -1872,8 +1872,8 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base protected function _thread($options) { $thread_criteria = array( - self::THREAD_ORDEREDSUBJECT => 'ORDEREDSUBJECT', - self::THREAD_REFERENCES => 'REFERENCES' + Horde_Imap_Client::THREAD_ORDEREDSUBJECT => 'ORDEREDSUBJECT', + Horde_Imap_Client::THREAD_REFERENCES => 'REFERENCES' ); $tsort = (isset($options['criteria'])) @@ -1891,7 +1891,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } /* Do client-side ORDEREDSUBJECT threading. */ - $fetch_res = $this->fetch($this->_selected, array(self::FETCH_ENVELOPE => true, self::FETCH_DATE => true), array('ids' => $ids, 'sequence' => !empty($options['sequence']))); + $fetch_res = $this->fetch($this->_selected, array(Horde_Imap_Client::FETCH_ENVELOPE => true, Horde_Imap_Client::FETCH_DATE => true), array('ids' => $ids, 'sequence' => !empty($options['sequence']))); return $this->_clientThreadOrderedsubject($fetch_res); } else { throw new Horde_Imap_Client_Exception('Server does not support REFERENCES thread sort.', Horde_Imap_Client_Exception::NOSUPPORTIMAPEXT); @@ -1967,7 +1967,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base while(list($k, $v) = each($data)) { $subject = empty($v['envelope']['subject']) ? '' - : $this->getBaseSubject($v['envelope']['subject']); + : $this->_utils->getBaseSubject($v['envelope']['subject']); if (!isset($sorted[$subject])) { $sorted[$subject] = array(); } @@ -2052,14 +2052,14 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } switch ($type) { - case self::FETCH_STRUCTURE: + case Horde_Imap_Client::FETCH_STRUCTURE: $fp['parsestructure'] = !empty($c_val['parse']); $fetch[] = !empty($c_val['noext']) ? 'BODY' : 'BODYSTRUCTURE'; break; - case self::FETCH_FULLMSG: + case Horde_Imap_Client::FETCH_FULLMSG: if (empty($c_val['peek'])) { - $this->openMailbox($this->_selected, self::OPEN_READWRITE); + $this->openMailbox($this->_selected, Horde_Imap_Client::OPEN_READWRITE); } $fetch[] = 'BODY' . (!empty($c_val['peek']) ? '.PEEK' : '') . @@ -2067,11 +2067,11 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base (isset($c_val['start']) && !empty($c_val['length']) ? ('<' . $c_val['start'] . '.' . $c_val['length'] . '>') : ''); break; - case self::FETCH_HEADERTEXT: - case self::FETCH_BODYTEXT: - case self::FETCH_MIMEHEADER: - case self::FETCH_BODYPART: - case self::FETCH_HEADERS: + case Horde_Imap_Client::FETCH_HEADERTEXT: + case Horde_Imap_Client::FETCH_BODYTEXT: + case Horde_Imap_Client::FETCH_MIMEHEADER: + case Horde_Imap_Client::FETCH_BODYPART: + case Horde_Imap_Client::FETCH_HEADERS: foreach ($c_val as $val) { $main_cmd = 'BODY'; @@ -2082,23 +2082,23 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } switch ($type) { - case self::FETCH_HEADERTEXT: + case Horde_Imap_Client::FETCH_HEADERTEXT: $fp['parseheadertext'] = !empty($val['parse']); $cmd .= 'HEADER'; break; - case self::FETCH_BODYTEXT: + case Horde_Imap_Client::FETCH_BODYTEXT: $cmd .= 'TEXT'; break; - case self::FETCH_MIMEHEADER: + case Horde_Imap_Client::FETCH_MIMEHEADER: if (empty($val['id'])) { throw new Horde_Imap_Client_Exception('Need a MIME ID when retrieving a MIME header.'); } $cmd .= 'MIME'; break; - case self::FETCH_BODYPART: + case Horde_Imap_Client::FETCH_BODYPART: if (empty($val['id'])) { throw new Horde_Imap_Client_Exception('Need a MIME ID when retrieving a MIME body part.'); } @@ -2111,7 +2111,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } break; - case self::FETCH_HEADERS: + case Horde_Imap_Client::FETCH_HEADERS: if (empty($val['label'])) { throw new Horde_Imap_Client_Exception('Need a unique label when doing a headers field search.'); } @@ -2135,7 +2135,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } if (empty($val['peek'])) { - $this->openMailbox($this->_selected, self::OPEN_READWRITE); + $this->openMailbox($this->_selected, Horde_Imap_Client::OPEN_READWRITE); } $fetch[] = $main_cmd . @@ -2145,7 +2145,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } break; - case self::FETCH_BODYPARTSIZE: + case Horde_Imap_Client::FETCH_BODYPARTSIZE: foreach ($c_val as $val) { if (empty($val['id'])) { throw new Horde_Imap_Client_Exception('Need a MIME ID when retrieving unencoded MIME body part size.'); @@ -2154,31 +2154,31 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base } break; - case self::FETCH_ENVELOPE: + case Horde_Imap_Client::FETCH_ENVELOPE: $fetch[] = 'ENVELOPE'; break; - case self::FETCH_FLAGS: + case Horde_Imap_Client::FETCH_FLAGS: $fetch[] = 'FLAGS'; break; - case self::FETCH_DATE: + case Horde_Imap_Client::FETCH_DATE: $fetch[] = 'INTERNALDATE'; break; - case self::FETCH_SIZE: + case Horde_Imap_Client::FETCH_SIZE: $fetch[] = 'RFC822.SIZE'; break; - case self::FETCH_UID: + case Horde_Imap_Client::FETCH_UID: $fetch[] = 'UID'; break; - case self::FETCH_SEQ: + case Horde_Imap_Client::FETCH_SEQ: // Nothing we need to add to fetch criteria. break; - case self::FETCH_MODSEQ: + case Horde_Imap_Client::FETCH_MODSEQ: /* RFC 4551 [3.1] - trying to do a FETCH of MODSEQ on a * mailbox that doesn't support it will return BAD. Catch that * here and throw an exception. */ @@ -2192,9 +2192,9 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $seq = empty($options['ids']) ? '1:*' - : ((reset($options['ids']) === self::USE_SEARCHRES) + : ((reset($options['ids']) === Horde_Imap_Client::USE_SEARCHRES) ? '$' - : $this->toSequenceString($options['ids'])); + : $this->_utils->toSequenceString($options['ids'])); $use_seq = !empty($options['sequence']); $cmd = ($use_seq ? '' : 'UID ') . 'FETCH ' . $seq . ' (' . implode(' ', $fetch) . ')'; @@ -2580,9 +2580,9 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base { $seq = empty($options['ids']) ? '1:*' - : ((reset($options['ids']) === self::USE_SEARCHRES) + : ((reset($options['ids']) === Horde_Imap_Client::USE_SEARCHRES) ? '$' - : $this->toSequenceString($options['ids'])); + : $this->_utils->toSequenceString($options['ids'])); $cmd_prefix = (empty($options['sequence']) ? 'UID ' : '') . 'STORE ' . $seq . ' '; @@ -2676,13 +2676,13 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $seq = empty($options['ids']) ? '1:*' - : ((reset($options['ids']) === self::USE_SEARCHRES) + : ((reset($options['ids']) === Horde_Imap_Client::USE_SEARCHRES) ? '$' - : $this->toSequenceString($options['ids'])); + : $this->_utils->toSequenceString($options['ids'])); // COPY returns no untagged information (RFC 3501 [6.4.7]) try { - $this->_sendLine((empty($options['sequence']) ? 'UID ' : '') . 'COPY ' . $seq . ' ' . $this->escape($dest)); + $this->_sendLine((empty($options['sequence']) ? 'UID ' : '') . 'COPY ' . $seq . ' ' . $this->_utils->escape($dest)); } catch (Horde_Imap_Client_Exception $e) { if (!empty($options['create']) && $this->_temp['trycreate']) { $this->createMailbox($dest); @@ -2728,7 +2728,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $limits[] = 'STORAGE ' . $options['storage']; } - $this->_sendLine('SETQUOTA ' . $this->escape($root) . ' (' . implode(' ', $limits) . ')'); + $this->_sendLine('SETQUOTA ' . $this->_utils->escape($root) . ' (' . implode(' ', $limits) . ')'); } /** @@ -2746,7 +2746,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $this->login(); $this->_temp['quotaresp'] = array(); - $this->_sendLine('GETQUOTA ' . $this->escape($root)); + $this->_sendLine('GETQUOTA ' . $this->_utils->escape($root)); return reset($this->_temp['quotaresp']); } @@ -2786,7 +2786,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $this->login(); $this->_temp['quotaresp'] = array(); - $this->_sendLine('GETQUOTAROOT ' . $this->escape($mailbox)); + $this->_sendLine('GETQUOTAROOT ' . $this->_utils->escape($mailbox)); return $this->_temp['quotaresp']; } @@ -2805,9 +2805,9 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base // SETACL/DELETEACL returns no untagged information (RFC 4314 [3.1 & // 3.2]). if (empty($options['rights']) && !empty($options['remove'])) { - $this->_sendLine('DELETEACL ' . $this->escape($mailbox) . ' ' . $identifier); + $this->_sendLine('DELETEACL ' . $this->_utils->escape($mailbox) . ' ' . $identifier); } else { - $this->_sendLine('SETACL ' . $this->escape($mailbox) . ' ' . $identifier . ' ' . $options['rights']); + $this->_sendLine('SETACL ' . $this->_utils->escape($mailbox) . ' ' . $identifier . ' ' . $options['rights']); } } @@ -2825,7 +2825,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $this->login(); $this->_temp['getacl'] = array(); - $this->_sendLine('GETACL ' . $this->escape($mailbox)); + $this->_sendLine('GETACL ' . $this->_utils->escape($mailbox)); return $this->_temp['getacl']; } @@ -2858,7 +2858,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $this->login(); $this->_temp['listaclrights'] = array(); - $this->_sendLine('LISTRIGHTS ' . $this->escape($mailbox) . ' ' . $identifier); + $this->_sendLine('LISTRIGHTS ' . $this->_utils->escape($mailbox) . ' ' . $identifier); return $this->_temp['listaclrights']; } @@ -2889,7 +2889,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $this->login(); $this->_temp['myrights'] = array(); - $this->_sendLine('MYRIGHTS ' . $this->escape($mailbox)); + $this->_sendLine('MYRIGHTS ' . $this->_utils->escape($mailbox)); return $this->_temp['myrights']; } @@ -3474,7 +3474,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base case 'REFERRAL': // Defined by RFC 2221 - $this->_temp['referral'] = $this->parseImapUrl($data); + $this->_temp['referral'] = $this->_utils->parseImapUrl($data); break; case 'UNKNOWN-CTE': @@ -3502,9 +3502,9 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base $this->_updateCache(array(), array('mailbox' => $this->_temp['uidplusmbox'], 'uidvalid' => $parts[0])); if ($code == 'APPENDUID') { - $this->_temp['appenduid'] = array_merge($this->_temp['appenduid'], $this->fromSequenceString($parts[1])); + $this->_temp['appenduid'] = array_merge($this->_temp['appenduid'], $this->_utils->fromSequenceString($parts[1])); } else { - $this->_temp['copyuid'] = array_combine($this->fromSequenceString($parts[1]), $this->fromSequenceString($parts[2])); + $this->_temp['copyuid'] = array_combine($this->_utils->fromSequenceString($parts[1]), $this->_utils->fromSequenceString($parts[2])); } break; @@ -3521,7 +3521,7 @@ class Horde_Imap_Client_Socket extends Horde_Imap_Client_Base case 'MODIFIED': // Defined by RFC 4551 [3.2] - $this->_temp['modified'] = $this->fromSequenceString($data); + $this->_temp['modified'] = $this->_utils->fromSequenceString($data); break; case 'CLOSED': diff --git a/framework/Imap_Client/lib/Horde/Imap/Client/Utils.php b/framework/Imap_Client/lib/Horde/Imap/Client/Utils.php new file mode 100644 index 000000000..621a01a18 --- /dev/null +++ b/framework/Imap_Client/lib/Horde/Imap/Client/Utils.php @@ -0,0 +1,364 @@ + + * + * 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 Michael Slusarz + * @category Horde + * @package Horde_Imap_Client + */ +class Horde_Imap_Client_Utils +{ + /** + * Create an IMAP message sequence string from a list of indices. + * Format: range_start:range_end,uid,uid2,range2_start:range2_end,... + * + * @param array $in An array of indices. + * @param array $options Additional options: + *
+     * 'nosort' - (boolean) Do not numerically sort the IDs before creating
+     *            the range?
+     *            DEFAULT: IDs are sorted
+     * 
+ * + * @return string The IMAP message sequence string. + */ + public function toSequenceString($ids, $options = array()) + { + if (empty($ids)) { + return ''; + } + + // Make sure IDs are unique + $ids = array_keys(array_flip($ids)); + + if (empty($options['nosort'])) { + sort($ids, SORT_NUMERIC); + } + + $first = $last = array_shift($ids); + $out = array(); + + foreach ($ids as $val) { + if ($last + 1 == $val) { + $last = $val; + } else { + $out[] = $first . ($last == $first ? '' : (':' . $last)); + $first = $last = $val; + } + } + $out[] = $first . ($last == $first ? '' : (':' . $last)); + + return implode(',', $out); + } + + /** + * Parse an IMAP message sequence string into a list of indices. + * Format: range_start:range_end,uid,uid2,range2_start:range2_end,... + * + * @param string $str The IMAP message sequence string. + * + * @return array An array of indices. + */ + public function fromSequenceString($str) + { + $ids = array(); + $str = trim($str); + + $idarray = explode(',', $str); + if (empty($idarray)) { + $idarray = array($str); + } + + foreach ($idarray as $val) { + $range = array_map('intval', explode(':', $val)); + if (count($range) == 1) { + $ids[] = $val; + } else { + list($low, $high) = ($range[0] < $range[1]) ? $range : array_reverse($range); + $ids = array_merge($ids, range($low, $high)); + } + } + + return $ids; + } + + /** + * Remove "bare newlines" from a string. + * + * @param string $str The original string. + * + * @return string The string with all bare newlines removed. + */ + public function removeBareNewlines($str) + { + return str_replace(array("\r\n", "\n"), array("\n", "\r\n"), $str); + } + + /** + * Escape IMAP output via a quoted string (see RFC 3501 [4.3]). + * + * @param string $str The unescaped string. + * + * @return string The escaped string. + */ + public function escape($str) + { + return '"' . addcslashes($str, '"\\') . '"'; + } + + /** + * Return the "base subject" defined in RFC 5256 [2.1]. + * + * @param string $str The original subject string. + * @param array $options Additional options: + *
+     * 'keepblob' - (boolean) Don't remove any "blob" information (i.e. text
+     *              leading text between square brackets) from string.
+     * 
+ * + * @return string The cleaned up subject string. + */ + public function getBaseSubject($str, $options = array()) + { + // Rule 1a: MIME decode to UTF-8 (if possible). + $str = Horde_Mime::decode($str, 'UTF-8'); + + // Rule 1b: Remove superfluous whitespace. + $str = preg_replace("/\s{2,}/", '', $str); + + if (!$str) { + return ''; + } + + do { + /* (2) Remove all trailing text of the subject that matches the + * the subj-trailer ABNF, repeat until no more matches are + * possible. */ + $str = preg_replace("/(?:\s*\(fwd\)\s*)+$/i", '', $str); + + do { + /* (3) Remove all prefix text of the subject that matches the + * subj-leader ABNF. */ + $found = $this->_removeSubjLeader($str, !empty($options['keepblob'])); + + /* (4) If there is prefix text of the subject that matches + * the subj-blob ABNF, and removing that prefix leaves a + * non-empty subj-base, then remove the prefix text. */ + $found = (empty($options['keepblob']) && $this->_removeBlobWhenNonempty($str)) || $found; + + /* (5) Repeat (3) and (4) until no matches remain. */ + } while ($found); + + /* (6) If the resulting text begins with the subj-fwd-hdr ABNF and + * ends with the subj-fwd-trl ABNF, remove the subj-fwd-hdr and + * subj-fwd-trl and repeat from step (2). */ + } while ($this->_removeSubjFwdHdr($str)); + + return $str; + } + + /** + * Parse an IMAP URL (RFC 5092). + * + * @param string $url A IMAP URL string. + * + * @return mixed False if the URL is invalid. If valid, a URL with the + * following fields: + *
+     * 'auth' - (string) The authentication method to use.
+     * 'port' - (integer) The remote port
+     * 'hostspec' - (string) The remote server
+     * 'username' - (string) The username to use on the remote server.
+     * 
+ */ + public function parseImapUrl($url) + { + $url = trim($url); + if (stripos($url, 'imap://') !== 0) { + return false; + } + $url = substr($url, 7); + + /* At present, only support imap://[/] style URLs. */ + if (($pos = strpos($url, '/')) !== false) { + $url = substr($url, 0, $pos); + } + + $ret_array = array(); + + /* Check for username/auth information. */ + if (($pos = strpos($url, '@')) !== false) { + if ((($apos = stripos($url, ';AUTH=')) !== false) && + ($apos < $pos)) { + $auth = substr($url, $apos + 6, $pos - $apos - 6); + if ($auth != '*') { + $ret_array['auth'] = $auth; + } + if ($apos) { + $ret_array['username'] = substr($url, 0, $apos); + } + } + $url = substr($url, $pos + 1); + } + + /* Check for port information. */ + if (($pos = strpos($url, ':')) !== false) { + $ret_array['port'] = substr($url, $pos + 1); + $url = substr($url, 0, $pos); + } + + $ret_array['hostspec'] = $url; + + return $ret_array; + } + + /** + * Remove all prefix text of the subject that matches the subj-leader + * ABNF. + * + * @param string &$str The subject string. + * @param boolean $keepblob Remove blob information? + * + * @return boolean True if string was altered. + */ + protected function _removeSubjLeader(&$str, $keepblob = false) + { + $ret = false; + + if (!$str) { + return $ret; + } + + if ($str[0] == ' ') { + $str = substr($str, 1); + $ret = true; + } + + $i = 0; + + if (!$keepblob) { + while ($str[$i] == '[') { + if (($i = $this->_removeBlob($str, $i)) === false) { + return $ret; + } + } + } + + $cmp_str = substr($str, $i); + if (stripos($cmp_str, 're') === 0) { + $i += 2; + } elseif (stripos($cmp_str, 'fwd') === 0) { + $i += 3; + } elseif (stripos($cmp_str, 'fw') === 0) { + $i += 2; + } else { + return $ret; + } + + if ($str[$i] == ' ') { + ++$i; + } + + if (!$keepblob) { + while ($str[$i] == '[') { + if (($i = $this->_removeBlob($str, $i)) === false) { + return $ret; + } + } + } + + if ($str[$i] != ':') { + return $ret; + } + + $str = substr($str, ++$i); + + return true; + } + + /** + * Remove "[...]" text. + * + * @param string &$str The subject string. + * + * @return boolean True if string was altered. + */ + protected function _removeBlob($str, $i) + { + if ($str[$i] != '[') { + return false; + } + + ++$i; + + for ($cnt = strlen($str); $i < $cnt; ++$i) { + if ($str[$i] == ']') { + break; + } + + if ($str[$i] == '[') { + return false; + } + } + + if ($i == ($cnt - 1)) { + return false; + } + + ++$i; + + if ($str[$i] == ' ') { + ++$i; + } + + return $i; + } + + /** + * Remove "[...]" text if it doesn't result in the subject becoming + * empty. + * + * @param string &$str The subject string. + * + * @return boolean True if string was altered. + */ + protected function _removeBlobWhenNonempty(&$str) + { + if ($str && + ($str[0] == '[') && + (($i = $this->_removeBlob($str, 0)) !== false) && + ($i != strlen($str))) { + $str = substr($str, $i); + return true; + } + + return false; + } + + /** + * Remove a "[fwd: ... ]" string. + * + * @param string &$str The subject string. + * + * @return boolean True if string was altered. + */ + protected function _removeSubjFwdHdr(&$str) + { + if ((stripos($str, '[fwd:') !== 0) || (substr($str, -1) != ']')) { + return false; + } + + $str = substr($str, 5, -1); + return true; + } + +} diff --git a/framework/Imap_Client/package.xml b/framework/Imap_Client/package.xml index 8c578bb61..b30164203 100644 --- a/framework/Imap_Client/package.xml +++ b/framework/Imap_Client/package.xml @@ -54,6 +54,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + @@ -111,6 +112,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> + diff --git a/framework/Imap_Client/test/Horde/Imap/test_client.php b/framework/Imap_Client/test/Horde/Imap/test_client.php index 25acc9c48..161be14f3 100644 --- a/framework/Imap_Client/test/Horde/Imap/test_client.php +++ b/framework/Imap_Client/test/Horde/Imap/test_client.php @@ -74,7 +74,7 @@ if (empty($argv[2])) { } if (!empty($argv[3])) { - $params = array_merge($params, Horde_Imap_Client::parseImapUrl($argv[3])); + $params = array_merge($params, $imap_utils->parseImapUrl($argv[3])); } function exception_handler($exception) { @@ -92,6 +92,7 @@ if (@include_once 'Benchmark/Timer.php') { // Add an ID field to send to server (ID extension) $params['id'] = array('name' => 'Horde_Imap_Client test program'); +$imap_utils = new Horde_Imap_Client_Utils(); $imap_client = Horde_Imap_Client::getInstance($driver, $params); if ($driver == 'Cclient_Pop3') { $test_mbox = $test_mbox_utf8 = 'INBOX'; @@ -536,7 +537,7 @@ try { print "\nSort 1st 5 messages in " . $test_mbox . " by thread - references algorithm (UIDs).\n"; try { $ten_query = new Horde_Imap_Client_Search_Query(); - $ten_query->sequence(Horde_Imap_Client::fromSequenceString('1:5'), true); + $ten_query->sequence($imap_utils->fromSequenceString('1:5'), true); print_r($imap_client->thread($test_mbox, array('search' => $ten_query, 'criteria' => Horde_Imap_Client::THREAD_REFERENCES))); print "Thread search: OK\n"; } catch (Horde_Imap_Client_Exception $e) { @@ -854,7 +855,7 @@ $subject_lines = array( print "\nBase subject parsing:\n"; foreach ($subject_lines as $val) { print " ORIGINAL: \"" . $val . "\"\n"; - print " BASE: \"" . Horde_Imap_Client::getBaseSubject($val) . "\"\n\n"; + print " BASE: \"" . $imap_utils->getBaseSubject($val) . "\"\n\n"; } $imap_urls = array( @@ -874,7 +875,7 @@ print "\nRFC 5092 URL parsing:\n"; foreach ($imap_urls as $val) { print "URL: " . $val . "\n"; print "PARSED:\n"; - print_r(Horde_Imap_Client::parseImapUrl($val)); + print_r($imap_utils->parseImapUrl($val)); print "\n"; }