Skip to content

Commit

Permalink
[mms] Use the new command length limitations defined in RFC 7162.
Browse files Browse the repository at this point in the history
Update RFC 4551/5162 references to RFC 7162 also.
  • Loading branch information
slusarz committed May 23, 2014
1 parent 07ddc8c commit 7edef67
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 34 deletions.
2 changes: 1 addition & 1 deletion framework/Imap_Client/lib/Horde/Imap/Client.php
Expand Up @@ -176,7 +176,7 @@ class Horde_Imap_Client
* @var array
*/
static public $capability_deps = array(
// RFC 5162 [1]
// RFC 7162 [3.2]
'QRESYNC' => array(
// QRESYNC requires CONDSTORE, but the latter is implied and is
// not required to be listed.
Expand Down
33 changes: 25 additions & 8 deletions framework/Imap_Client/lib/Horde/Imap/Client/Base.php
Expand Up @@ -344,6 +344,12 @@ public function _setInit($key = null, $val = null)
);
} elseif (is_null($val)) {
unset($this->_init[$key]);

switch ($key) {
case 'capability':
unset($this->_init['cmdlength']);
break;
}
} else {
switch ($key) {
case 'capability':
Expand All @@ -359,12 +365,23 @@ public function _setInit($key = null, $val = null)
$val = array_diff_key($val, array_flip($ci));
}

/* RFC 5162 [1] - QRESYNC implies CONDSTORE and ENABLE, even
* if not listed as a capability. */
/* RFC 7162 [3.2.3] - QRESYNC implies CONDSTORE and ENABLE,
* even if not listed as a capability. */
if (!empty($val['QRESYNC'])) {
$val['CONDSTORE'] = true;
$val['ENABLE'] = true;
}

/* RFC 2683 [3.2.1.5] originally recommended that lines should
* be limited to "approximately 1000 octets". However, servers
* should allow a command line of at least "8000 octets".
* RFC 7162 [4] updates the recommendation to 8192 octets.
* As a compromise, assume all modern IMAP servers handle
* ~2000 octets and, if CONDSTORE/ENABLE is supported, assume
* they can handle ~8000 octets. */
$this->_init['cmdlength'] = (isset($val['CONDSTORE']) || isset($val['QRESYNC']))
? 8000
: 2000;
break;
}

Expand All @@ -389,7 +406,7 @@ public function _setInit($key = null, $val = null)
*/
protected function _enabled($exts, $status)
{
/* RFC 5162 [1] - Enabling QRESYNC also implies enabling of
/* RFC 7162 [3.2.3] - Enabling QRESYNC also implies enabling of
* CONDSTORE. */
if (in_array('QRESYNC', $exts)) {
$exts[] = 'CONDSTORE';
Expand Down Expand Up @@ -2139,8 +2156,8 @@ public function search($mailbox, $query = null, array $options = array())
$status_res = $this->status($this->_selected, Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_HIGHESTMODSEQ);
if ($status_res['messages'] ||
in_array(Horde_Imap_Client::SEARCH_RESULTS_SAVE, $options['results'])) {
/* RFC 4551 [3.1] - trying to do a MODSEQ SEARCH on a mailbox that
* doesn't support it will return BAD. */
/* RFC 7162 [3.1.2.2] - trying to do a MODSEQ SEARCH on a mailbox
* that doesn't support it will return BAD. */
if (in_array('CONDSTORE', $options['_query']['exts']) &&
!$this->_mailboxOb()->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ)) {
throw new Horde_Imap_Client_Exception(
Expand Down Expand Up @@ -2430,8 +2447,8 @@ private function _fetchWrapper($mailbox, $query, $options)

if ($modseq_check &&
!$mbox_ob->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ)) {
/* RFC 4551 [3.1] - trying to do a MODSEQ FETCH on a mailbox that
* doesn't support it will return BAD. */
/* RFC 7162 [3.1.2.2] - trying to do a MODSEQ FETCH on a mailbox
* that doesn't support it will return BAD. */
throw new Horde_Imap_Client_Exception(
Horde_Imap_Client_Translation::r("Mailbox does not support mod-sequences."),
Horde_Imap_Client_Exception::MBOXNOMODSEQ
Expand Down Expand Up @@ -2782,7 +2799,7 @@ public function store($mailbox, array $options = array())
throw new Horde_Imap_Client_Exception_NoSupportExtension('CONDSTORE');
}

/* RFC 4551 [3.1] - trying to do a UNCHANGEDSINCE STORE on a
/* RFC 7162 [3.1.2.2] - trying to do a UNCHANGEDSINCE STORE on a
* mailbox that doesn't support it will return BAD. */
if (!$this->_mailboxOb()->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ)) {
throw new Horde_Imap_Client_Exception(
Expand Down
2 changes: 1 addition & 1 deletion framework/Imap_Client/lib/Horde/Imap/Client/Exception.php
Expand Up @@ -64,7 +64,7 @@ class Horde_Imap_Client_Exception extends Horde_Exception_Wrapped
const BADCOMPARATOR = 9;

/**
* RFC 4551 [3.1.2] - All mailboxes are not required to support
* RFC 7162 [3.1.2.2] - All mailboxes are not required to support
* mod-sequences.
*/
const MBOXNOMODSEQ = 10;
Expand Down
Expand Up @@ -662,7 +662,7 @@ public function orSearch($queries)

/**
* Search for messages modified since a specific moment. The IMAP server
* must support the CONDSTORE extension (RFC 4551) for this query to be
* must support the CONDSTORE extension (RFC 7162) for this query to be
* used.
*
* @param integer $value The mod-sequence value.
Expand Down
42 changes: 20 additions & 22 deletions framework/Imap_Client/lib/Horde/Imap/Client/Socket.php
Expand Up @@ -44,12 +44,10 @@
* - RFC 4422: SASL Authentication (for DIGEST-MD5)
* - RFC 4466: Collected extensions (updates RFCs 2088, 3501, 3502, 3516)
* - RFC 4469/5550: CATENATE
* - RFC 4551: CONDSTORE
* - RFC 4731: ESEARCH
* - RFC 4959: SASL-IR
* - RFC 5032: WITHIN
* - RFC 5161: ENABLE
* - RFC 5162: QRESYNC
* - RFC 5182: SEARCHRES
* - RFC 5255: LANGUAGE/I18NLEVEL
* - RFC 5256: THREAD/SORT
Expand All @@ -63,6 +61,7 @@
* - RFC 6203: SEARCH=FUZZY
* - RFC 6851: MOVE
* - RFC 6858: DOWNGRADED response code
* - RFC 7162: CONDSTORE/QRESYNC
* </pre>
*
* Implements the following non-RFC extensions:
Expand Down Expand Up @@ -1566,7 +1565,7 @@ protected function _status($mboxes, $flags)
}

/**
* Parse a STATUS response (RFC 3501 [7.2.4], RFC 4551 [3.6])
* Parse a STATUS response (RFC 3501 [7.2.4]).
*
* @param Horde_Imap_Client_Tokenize $data Token data
*/
Expand Down Expand Up @@ -2006,7 +2005,7 @@ protected function _expunge($options)
}

/**
* Parse a VANISHED response (RFC 5162 [3.6]).
* Parse a VANISHED response (RFC 7162 [3.2.10]).
*
* @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline
* object.
Expand Down Expand Up @@ -2670,7 +2669,7 @@ protected function _fetchCmd(
* ENVELOPE
* FLAGS
* INTERNALDATE
* MODSEQ (RFC 4551)
* MODSEQ (RFC 7162)
* RFC822.SIZE
* UID
*
Expand Down Expand Up @@ -2806,7 +2805,7 @@ protected function _fetchCmd(

case Horde_Imap_Client::FETCH_MODSEQ:
/* The 'changedsince' modifier implicitly adds the MODSEQ
* FETCH item (RFC 4551 [3.3.1]). Don't add to query as it
* FETCH item (RFC 7162 [3.1.4.1]). Don't add to query as it
* just creates a longer FETCH command. */
if (empty($options['changedsince'])) {
$fetch->add('MODSEQ');
Expand All @@ -2833,15 +2832,13 @@ protected function _fetchCmd(
);
}

/* RFC 2683 [3.2.1.5] recommends that lines should be limited to
* "approximately 1000 octets". However, servers should allow a
* command line of at least "8000 octets". As a compromise, assume
* all modern IMAP servers handle ~2000 octets. The FETCH command
* should be the only command issued by this library that should ever
* approach this limit. For simplification, assume that the UID list
* is the limiting factor and split this list at a sequence comma
* delimiter if it exceeds 2000 characters. */
foreach ($options['ids']->split(2000) as $val) {
/* The FETCH command should be the only command issued by this library
* that should ever approach this limit.
* @todo Move this check to a more centralized location (_command()?).
* For simplification, assume that the UID list is the limiting factor
* and split this list at a sequence comma delimiter if it exceeds
* the character limit. */
foreach ($options['ids']->split($this->_init['cmdlength']) as $val) {
$cmd = $this->_command(
$sequence ? 'FETCH' : 'UID FETCH'
)->add(array(
Expand Down Expand Up @@ -2940,7 +2937,7 @@ protected function _parseFetch(
$ob->setModSeq($modseq);

/* Store MODSEQ value. It may be used as the highestmodseq
* once a tagged response is received (RFC 5162 [5]). */
* once a tagged response is received (RFC 7162 [6]). */
$pipeline->data['modseqs'][] = $modseq;
}
break;
Expand Down Expand Up @@ -3060,7 +3057,8 @@ protected function _parseFetch(
* In the (rare) event that there is, don't cache anything and
* immediately close the mailbox: flags will be correctly sync'd next
* mailbox open so we only lose a bit of caching efficiency.
* Otherwise, we could end up with an inconsistent cached state. */
* Otherwise, we could end up with an inconsistent cached state.
* This Errata has been fixed in 7162 [3.2.4]. */
if ($flags && $modseq && !$uid) {
$pipeline->data['modseqs_nouid'][] = $id;
}
Expand Down Expand Up @@ -4391,7 +4389,7 @@ protected function _serverResponse(
break;

case 'VANISHED':
// QRESYNC extension (RFC 5162 [3.6])
// QRESYNC extension (RFC 7162 [3.2.10])
$this->_parseVanished($pipeline, $token);
break;

Expand Down Expand Up @@ -4602,22 +4600,22 @@ protected function _responseCode(
);

case 'HIGHESTMODSEQ':
// Defined by RFC 4551 [3.1.1]
// Defined by RFC 7162 [3.1.2.1]
$pipeline->data['modseqs'][] = $rc->data[0];
break;

case 'NOMODSEQ':
// Defined by RFC 4551 [3.1.2]
// Defined by RFC 7162 [3.1.2.2]
$pipeline->data['modseqs'][] = 0;
break;

case 'MODIFIED':
// Defined by RFC 4551 [3.2]
// Defined by RFC 7162 [3.1.3]
$pipeline->data['modified']->add($rc->data[0]);
break;

case 'CLOSED':
// Defined by RFC 5162 [3.7]
// Defined by RFC 7162 [3.2.11]
if (isset($pipeline->data['qresyncmbox'])) {
/* If there is any pending FETCH cache entries, flush them
* now before changing mailboxes. */
Expand Down
2 changes: 2 additions & 0 deletions framework/Imap_Client/package.xml
Expand Up @@ -21,6 +21,7 @@
</stability>
<license uri="http://www.horde.org/licenses/lgpl21">LGPL-2.1</license>
<notes>
* [mms] Use the new command length limitations defined in RFC 7162.
* [mms] A noop() call before authentication will now correctly throw an exception on a connection issue (Bug #13205).
</notes>
<contents>
Expand Down Expand Up @@ -2425,6 +2426,7 @@
<date>2014-05-21</date>
<license uri="http://www.horde.org/licenses/lgpl21">LGPL-2.1</license>
<notes>
* [mms] Use the new command length limitations defined in RFC 7162.
* [mms] A noop() call before authentication will now correctly throw an exception on a connection issue (Bug #13205).
</notes>
</release>
Expand Down
3 changes: 2 additions & 1 deletion framework/Imap_Client/test/Horde/Imap/Client/SocketTest.php
Expand Up @@ -295,7 +295,8 @@ public function testBug11946()

/* See RFC 5162 (Errata #1807) - QRESYNC/CONDSTORE has design flaw where
* it is allowable to send FETCH responses with MODSEQ/FLAGS but without
* UID. This makes the responses practically useless. */
* UID. This makes the responses practically useless. This has been
* fixed in RFC 7162. */
public function testModseqFlagsWithoutUid()
{
$test = '* 1 FETCH (UID 2 MODSEQ (5) FLAGS (\Seen \Flagged))';
Expand Down

0 comments on commit 7edef67

Please sign in to comment.