From 8bc8f6433f808c5761bee3d609d230daf4281f23 Mon Sep 17 00:00:00 2001 From: Michael J Rubinsky Date: Fri, 14 Feb 2014 14:19:54 -0500 Subject: [PATCH] Compress UID lists before serialization, if large enough. --- .../lib/Horde/ActiveSync/Folder/Imap.php | 97 ++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Folder/Imap.php b/framework/ActiveSync/lib/Horde/ActiveSync/Folder/Imap.php index 4cf38ba8d45..6acc1c3a4cb 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Folder/Imap.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Folder/Imap.php @@ -37,6 +37,9 @@ class Horde_ActiveSync_Folder_Imap extends Horde_ActiveSync_Folder_Base implemen /* Serialize version */ const VERSION = 2; + /* The UID count at which UID lists will be compressed before serialization */ + const COMPRESSION_LIMIT = 500; + /** * The folder's current message list. * Note: This represents the folder list on the client and is affected by @@ -359,9 +362,14 @@ public function minuid() */ public function serialize() { + if (!empty($this->_status[self::HIGHESTMODSEQ]) && count($this->_messages) > self::COMPRESSION_LIMIT) { + $msgs = $this->_toSequenceString($this->_messages); + } else { + $msgs = $this->_messages; + } return json_encode(array( 's' => $this->_status, - 'm' => $this->_messages, + 'm' => $msgs, 'f' => $this->_serverid, 'c' => $this->_class, 'lsd' => $this->_lastSinceDate, @@ -392,6 +400,10 @@ public function unserialize($data) $this->_class = $d_data['c']; $this->_lastSinceDate = $d_data['lsd']; $this->_softDelete = $d_data['sd']; + + if (!empty($this->_status[self::HIGHESTMODSEQ]) && is_string($this->_messages)) { + $this->_messages = $this->_fromSequenceString($this->_messages); + } } /** @@ -410,4 +422,87 @@ public function __toString() ); } + /** + * Create an IMAP message sequence string from a list of indices. + * + * Index Format: range_start:range_end,uid,uid2,... + * + * @param array $ids An array of UIDs. + * + * @return string The IMAP message sequence string. + */ + protected function _toSequenceString(array $ids) + { + if (empty($ids)) { + return ''; + } + + $in = $ids; + sort($in, SORT_NUMERIC); + $first = $last = array_shift($in); + $i = count($in) - 1; + $out = array(); + + reset($in); + while (list($key, $val) = each($in)) { + if (($last + 1) == $val) { + $last = $val; + } + + if (($i == $key) || ($last != $val)) { + if ($last == $first) { + $out[] = $first; + if ($i == $key) { + $out[] = $val; + } + } else { + $out[] = $first . ':' . $last; + if (($i == $key) && ($last != $val)) { + $out[] = $val; + } + } + $first = $last = $val; + } + } + + return empty($out) + ? $first + : implode(',', $out); + } + + /** + * Parse an IMAP message sequence string into a list of indices. + * + * @see _toSequenceString() + * + * @param string $str The IMAP message sequence string. + * + * @return array An array of indices. + */ + protected function _fromSequenceString($str) + { + $ids = array(); + $str = trim($str); + + if (!strlen($str)) { + return $ids; + } + + $idarray = explode(',', $str); + + reset($idarray); + while (list(,$val) = each($idarray)) { + $range = explode(':', $val); + if (isset($range[1])) { + for ($i = min($range), $j = max($range); $i <= $j; ++$i) { + $ids[] = $i; + } + } else { + $ids[] = $val; + } + } + + return $ids; + } + }