<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[2318] 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client: Reverted Socket.php, Socket/Pop3.php and Base.php to d5ac35d (before continuations were introduced)</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://gsoc.trac.wordpress.org/changeset/2318">2318</a></dd>
<dt>Author</dt> <dd>codebykat</dd>
<dt>Date</dt> <dd>2013-09-16 02:11:57 +0000 (Mon, 16 Sep 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Reverted Socket.php, Socket/Pop3.php and Base.php to d5ac35d (before continuations were introduced)</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientBasephp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientSocketPop3php">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Pop3.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientSocketphp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientBasephp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base.php (2317 => 2318)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base.php    2013-09-16 02:11:45 UTC (rev 2317)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base.php       2013-09-16 02:11:57 UTC (rev 2318)
</span><span class="lines">@@ -32,9 +32,6 @@
</span><span class="cx">     /* @since 2.9.0 */
</span><span class="cx">     const CACHE_SEARCHID = '_i';
</span><span class="cx"> 
</span><del>-    /* Cache names used exclusively within this class. @since 2.11.0 */
-    const CACHE_DOWNGRADED = 'HICdg';
-
</del><span class="cx">     /**
</span><span class="cx">      * The list of fetch fields that can be cached, and their cache names.
</span><span class="cx">      *
</span><span class="lines">@@ -57,19 +54,6 @@
</span><span class="cx">     public $changed = false;
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Horde_Imap_Client is optimized for short (i.e. 1 seconds) scripts. It
-     * makes heavy use of mailbox caching to save on server accesses. This
-     * property should be set to false for long-running scripts, or else
-     * status() data may not reflect the current state of the mailbox on the
-     * server.
-     *
-     * @since 2.14.0
-     *
-     * @var boolean
-     */
-    public $statuscache = true;
-
-    /**
</del><span class="cx">      * The Horde_Imap_Client_Cache object.
</span><span class="cx">      *
</span><span class="cx">      * @var Horde_Imap_Client_Cache
</span><span class="lines">@@ -77,13 +61,6 @@
</span><span class="cx">     protected $_cache = null;
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Connection to the IMAP server.
-     *
-     * @var Horde_Imap_Client_Base_Connection
-     */
-    protected $_connection = null;
-
-    /**
</del><span class="cx">      * The debug object.
</span><span class="cx">      *
</span><span class="cx">      * @var Horde_Imap_Client_Base_Debug
</span><span class="lines">@@ -91,14 +68,6 @@
</span><span class="cx">     protected $_debug = null;
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * The default ports to use for a connection.
-     * First element is non-secure, second is SSL.
-     *
-     * @var array
-     */
-    protected $_defaultPorts = array();
-
-    /**
</del><span class="cx">      * The fetch data object type to return.
</span><span class="cx">      *
</span><span class="cx">      * @var string
</span><span class="lines">@@ -120,6 +89,13 @@
</span><span class="cx">     protected $_isAuthenticated = false;
</span><span class="cx"> 
</span><span class="cx">     /**
</span><ins>+     * Is there a secure connection to the IMAP Server?
+     *
+     * @var boolean
+     */
+    protected $_isSecure = false;
+
+    /**
</ins><span class="cx">      * The current mailbox selection mode.
</span><span class="cx">      *
</span><span class="cx">      * @var integer
</span><span class="lines">@@ -146,9 +122,7 @@
</span><span class="cx">      *
</span><span class="cx">      * @var array
</span><span class="cx">      */
</span><del>-    protected $_temp = array(
-        'enabled' => array()
-    );
</del><ins>+    protected $_temp = array();
</ins><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Constructor.
</span><span class="lines">@@ -157,9 +131,7 @@
</span><span class="cx">      * <ul>
</span><span class="cx">      *  <li>REQUIRED Parameters
</span><span class="cx">      *   <ul>
</span><del>-     *    <li>password: (mixed) The IMAP user password. Either a string or
-     *                  a Horde_Imap_Client_Base_Password object (since
-     *                  2.14.0).</li>
</del><ins>+     *    <li>password: (string) The IMAP user password.</li>
</ins><span class="cx">      *    <li>username: (string) The IMAP username.</li>
</span><span class="cx">      *   </ul>
</span><span class="cx">      *  </li>
</span><span class="lines">@@ -176,6 +148,10 @@
</span><span class="cx">      *                Backend cache driver (as of 2.9.0).
</span><span class="cx">      *      </li>
</span><span class="cx">      *      <li>
</span><ins>+     *       cacheob: [REQUIRED (or backend)] (Horde_Cache) The cache object to
+     *                use (DEPRECATED).
+     *      </li>
+     *      <li>
</ins><span class="cx">      *       fetch_ignore: (array) A list of mailboxes to ignore when storing
</span><span class="cx">      *                     fetch data.
</span><span class="cx">      *      </li>
</span><span class="lines">@@ -224,6 +200,12 @@
</span><span class="cx">      *            DEFAULT: No debug output
</span><span class="cx">      *    </li>
</span><span class="cx">      *    <li>
</span><ins>+     *     encryptKey: (array) A callback to a function that returns the key
+     *                 used to encrypt the password. This function MUST be
+     *                 static.
+     *                 DEFAULT: No encryption
+     *    </li>
+     *    <li>
</ins><span class="cx">      *     hostspec: (string) The hostname or IP address of the server.
</span><span class="cx">      *               DEFAULT: 'localhost'
</span><span class="cx">      *    </li>
</span><span class="lines">@@ -247,14 +229,13 @@
</span><span class="cx">      *     secure: (string) Use SSL or TLS to connect.
</span><span class="cx">      *             VALUES:
</span><span class="cx">      *     <ul>
</span><del>-     *      <li>false (No encryption)</li>
</del><ins>+     *      <li>false</li>
</ins><span class="cx">      *      <li>'ssl' (Auto-detect SSL version)</li>
</span><span class="cx">      *      <li>'sslv2' (Force SSL version 3)</li>
</span><span class="cx">      *      <li>'sslv3' (Force SSL version 2)</li>
</span><del>-     *      <li>'tls' (TLS)</li>
-     *      <li>true (TLS if available/necessary) [since 2.15.0]</li>
</del><ins>+     *      <li>'tls'</li>
</ins><span class="cx">      *     </ul>
</span><del>-     *             DEFAULT: false</li>
</del><ins>+     *             DEFAULT: No encryption</li>
</ins><span class="cx">      *    </li>
</span><span class="cx">      *    <li>
</span><span class="cx">      *     timeout: (integer)  Connection timeout, in seconds.
</span><span class="lines">@@ -280,10 +261,14 @@
</span><span class="cx">             'timeout' => 30
</span><span class="cx">         ), array_filter($params));
</span><span class="cx"> 
</span><ins>+        if ($params['secure'] === true) {
+            $params['secure'] = 'tls';
+        }
+
</ins><span class="cx">         if (!isset($params['port'])) {
</span><del>-            $params['port'] = (!empty($params['secure']) && in_array($params['secure'], array('ssl', 'sslv2', 'sslv3'), true))
-                ? $this->_defaultPorts[1]
-                : $this->_defaultPorts[0];
</del><ins>+            $params['port'] = (isset($params['secure']) && in_array($params['secure'], array('ssl', 'sslv2', 'sslv3')))
+                ? 993
+                : 143;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (empty($params['cache'])) {
</span><span class="lines">@@ -299,7 +284,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         $this->_params = $params;
</span><del>-        $this->setParam('password', $params['password']);
</del><ins>+        $this->setParam('password', $this->_params['password']);
</ins><span class="cx"> 
</span><span class="cx">         $this->changed = true;
</span><span class="cx">         $this->_initOb();
</span><span class="lines">@@ -308,14 +293,12 @@
</span><span class="cx">     /**
</span><span class="cx">      * Get encryption key.
</span><span class="cx">      *
</span><del>-     * @deprecated  Pass callable into 'password' parameter instead.
-     *
</del><span class="cx">      * @return string  The encryption key.
</span><span class="cx">      */
</span><span class="cx">     protected function _getEncryptKey()
</span><span class="cx">     {
</span><del>-        if (is_callable($ekey = $this->getParam('encryptKey'))) {
-            return call_user_func($ekey);
</del><ins>+        if (is_callable($this->_params['encryptKey'])) {
+            return call_user_func($this->_params['encryptKey']);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         throw new InvalidArgumentException('encryptKey parameter is not a valid callback.');
</span><span class="lines">@@ -327,9 +310,9 @@
</span><span class="cx">     protected function _initOb()
</span><span class="cx">     {
</span><span class="cx">         register_shutdown_function(array($this, 'shutdown'));
</span><del>-        $this->_debug = ($debug = $this->getParam('debug'))
-            ? new Horde_Imap_Client_Base_Debug($debug)
-            : new Horde_Support_Stub();
</del><ins>+        $this->_debug = empty($this->_params['debug'])
+            ? new Horde_Support_Stub()
+            : new Horde_Imap_Client_Base_Debug($this->_params['debug']);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -386,6 +369,7 @@
</span><span class="cx">     {
</span><span class="cx">         if (is_null($key)) {
</span><span class="cx">             $this->_init = array(
</span><ins>+                'enabled' => array(),
</ins><span class="cx">                 'namespace' => array(),
</span><span class="cx">                 's_charset' => array()
</span><span class="cx">             );
</span><span class="lines">@@ -394,13 +378,13 @@
</span><span class="cx">         } else {
</span><span class="cx">             switch ($key) {
</span><span class="cx">             case 'capability':
</span><del>-                if ($ci = $this->getParam('capability_ignore')) {
</del><ins>+                if (!empty($this->_params['capability_ignore'])) {
</ins><span class="cx">                     if ($this->_debug->debug &&
</span><del>-                        ($ignored = array_intersect_key($val, array_flip($ci)))) {
</del><ins>+                        ($ignored = array_intersect_key($val, array_flip($this->_params['capability_ignore'])))) {
</ins><span class="cx">                         $this->_debug->info(sprintf("CONFIG: IGNORING these IMAP capabilities: %s", implode(', ', array_keys($ignored))));
</span><span class="cx">                     }
</span><span class="cx"> 
</span><del>-                    $val = array_diff_key($val, array_flip($ci));
</del><ins>+                    $val = array_diff_key($val, array_flip($this->_params['capability_ignore']));
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 /* RFC 5162 [1] - QRESYNC implies CONDSTORE and ENABLE, even
</span><span class="lines">@@ -410,54 +394,22 @@
</span><span class="cx">                     $val['ENABLE'] = true;
</span><span class="cx">                 }
</span><span class="cx">                 break;
</span><del>-            }
</del><span class="cx"> 
</span><del>-            /* Nothing has changed. */
-            if (isset($this->_init[$key]) && ($this->_init[$key] == $val)) {
-                return;
</del><ins>+            case 'enabled':
+                /* RFC 5162 [1] - Enabling QRESYNC also implies enabling of
+                 * CONDSTORE. */
+                if (isset($val['QRESYNC'])) {
+                    $val['CONDSTORE'] = true;
+                }
+                break;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             $this->_init[$key] = $val;
</span><span class="cx">         }
</span><del>-
</del><span class="cx">         $this->changed = true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Set the list of enabled extensions.
-     *
-     * @param array $exts      The list of extensions.
-     * @param integer $status  1 means to report as ENABLED, although it has
-     *                         not been formally enabled on server yet. 2 is
-     *                         verified enabled on the server.
-     */
-    protected function _enabled($exts, $status)
-    {
-        /* RFC 5162 [1] - Enabling QRESYNC also implies enabling of
-         * CONDSTORE. */
-        if (in_array('QRESYNC', $exts)) {
-            $exts[] = 'CONDSTORE';
-        }
-
-        switch ($status) {
-        case 2:
-            $enabled_list = array_intersect(array(2), $this->_temp['enabled']);
-            break;
-
-        case 1:
-        default:
-            $enabled_list = $this->_temp['enabled'];
-            $status = 1;
-            break;
-        }
-
-        $this->_temp['enabled'] = array_merge(
-            $enabled_list,
-            array_fill_keys($exts, $status)
-        );
-    }
-
-    /**
</del><span class="cx">      * Initialize the Horde_Imap_Client_Cache object, if necessary.
</span><span class="cx">      *
</span><span class="cx">      * @param boolean $current  If true, we are going to update the currently
</span><span class="lines">@@ -469,13 +421,13 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _initCache($current = false)
</span><span class="cx">     {
</span><del>-        $c = $this->getParam('cache');
-
-        if (empty($c['fields'])) {
</del><ins>+        if (empty($this->_params['cache']['fields'])) {
</ins><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (is_null($this->_cache)) {
</span><ins>+            $c = $this->getParam('cache');
+
</ins><span class="cx">             if (isset($c['backend']) &&
</span><span class="cx">                 ($c['backend'] instanceof Horde_Imap_Client_Cache_Backend)) {
</span><span class="cx">                 $backend = $c['backend'];
</span><span class="lines">@@ -510,22 +462,13 @@
</span><span class="cx">     public function getParam($key)
</span><span class="cx">     {
</span><span class="cx">         /* Passwords may be stored encrypted. */
</span><del>-        switch ($key) {
-        case 'password':
-            if ($this->_params[$key] instanceof Horde_Imap_Client_Base_Password) {
-                return $this->_params[$key]->getPassword();
</del><ins>+        if (($key == 'password') && !empty($this->_params['_passencrypt'])) {
+            try {
+                $secret = new Horde_Secret();
+                return $secret->read($this->_getEncryptKey(), $this->_params['password']);
+            } catch (Exception $e) {
+                return null;
</ins><span class="cx">             }
</span><del>-
-            // DEPRECATED
-            if (!empty($this->_params['_passencrypt'])) {
-                try {
-                    $secret = new Horde_Secret();
-                    return $secret->read($this->_getEncryptKey(), $this->_params['password']);
-                } catch (Exception $e) {
-                    return null;
-                }
-            }
-            break;
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return isset($this->_params[$key])
</span><span class="lines">@@ -543,11 +486,7 @@
</span><span class="cx">     {
</span><span class="cx">         switch ($key) {
</span><span class="cx">         case 'password':
</span><del>-            if ($val instanceof Horde_Imap_Client_Base_Password) {
-                break;
-            }
-
-            // DEPRECATED: Encrypt password.
</del><ins>+            // Encrypt password.
</ins><span class="cx">             try {
</span><span class="cx">                 $encrypt_key = $this->_getEncryptKey();
</span><span class="cx">                 if (strlen($encrypt_key)) {
</span><span class="lines">@@ -555,7 +494,9 @@
</span><span class="cx">                     $val = $secret->write($encrypt_key, $val);
</span><span class="cx">                     $this->_params['_passencrypt'] = true;
</span><span class="cx">                 }
</span><del>-            } catch (Exception $e) {}
</del><ins>+            } catch (Exception $e) {
+                $this->_params['_passencrypt'] = false;
+            }
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -599,10 +540,12 @@
</span><span class="cx">      */
</span><span class="cx">     public function queryCapability($capability)
</span><span class="cx">     {
</span><del>-        try {
-            $this->capability();
-        } catch (Horde_Imap_Client_Exception $e) {
-            return false;
</del><ins>+        if (!isset($this->_init['capability'])) {
+            try {
+                $this->capability();
+            } catch (Horde_Imap_Client_Exception $e) {
+                return false;
+            }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         $capability = strtoupper($capability);
</span><span class="lines">@@ -633,15 +576,17 @@
</span><span class="cx">     public function capability()
</span><span class="cx">     {
</span><span class="cx">         if (!isset($this->_init['capability'])) {
</span><del>-            $this->_capability();
</del><ins>+            $this->_setInit('capability', $this->_capability());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return $this->_init['capability'];
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Retrieve CAPABILITY information from the IMAP server.
</del><ins>+     * Get CAPABILITY information from the IMAP server.
</ins><span class="cx">      *
</span><ins>+     * @return array  The capability array.
+     *
</ins><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      */
</span><span class="cx">     abstract protected function _capability();
</span><span class="lines">@@ -710,13 +655,19 @@
</span><span class="cx"> 
</span><span class="cx">         $ns = $this->_getNamespaces();
</span><span class="cx"> 
</span><del>-        /* Skip namespaces if we have already auto-detected them. Also, hidden
-         * namespaces cannot be empty. */
-        $to_process = array_diff(array_filter($additional, 'strlen'), array_keys($ns));;
-        if (!empty($to_process)) {
-            foreach ($this->listMailboxes($to_process, Horde_Imap_Client::MBOX_ALL, array('delimiter' => true)) as $val) {
</del><ins>+        foreach ($additional as $val) {
+            /* Skip namespaces if we have already auto-detected them. Also,
+             * hidden namespaces cannot be empty. */
+            if (!strlen($val) || isset($ns[$val])) {
+                continue;
+            }
+
+            $mbox = $this->listMailboxes($val, Horde_Imap_Client::MBOX_ALL, array('delimiter' => true));
+            $first = reset($mbox);
+
+            if ($first && ($first['mailbox'] == $val)) {
</ins><span class="cx">                 $ns[$val] = array(
</span><del>-                    'delimiter' => $val['delimiter'],
</del><ins>+                    'delimiter' => $first['delimiter'],
</ins><span class="cx">                     'hidden' => true,
</span><span class="cx">                     'name' => $val,
</span><span class="cx">                     'translation' => '',
</span><span class="lines">@@ -762,17 +713,10 @@
</span><span class="cx">      */
</span><span class="cx">     public function isSecureConnection()
</span><span class="cx">     {
</span><del>-        return ($this->_connection && $this->_connection->secure);
</del><ins>+        return $this->_isSecure;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Connect to the remote server.
-     *
-     * @throws Horde_Imap_Client_Exception
-     */
-    abstract protected function _connect();
-
-    /**
</del><span class="cx">      * Return a list of alerts that MUST be presented to the user (RFC 3501
</span><span class="cx">      * [7.1]).
</span><span class="cx">      *
</span><span class="lines">@@ -787,8 +731,12 @@
</span><span class="cx">      */
</span><span class="cx">     public function login()
</span><span class="cx">     {
</span><del>-        if (!$this->_isAuthenticated && $this->_login()) {
-            if ($this->getParam('id')) {
</del><ins>+        if ($this->_isAuthenticated) {
+            return;
+        }
+
+        if ($this->_login()) {
+            if (!empty($this->_params['id'])) {
</ins><span class="cx">                 try {
</span><span class="cx">                     $this->sendID();
</span><span class="cx">                 } catch (Horde_Imap_Client_Exception_NoSupportExtension $e) {
</span><span class="lines">@@ -796,7 +744,7 @@
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            if ($this->getParam('comparator')) {
</del><ins>+            if (!empty($this->_params['comparator'])) {
</ins><span class="cx">                 try {
</span><span class="cx">                     $this->setComparator();
</span><span class="cx">                 } catch (Horde_Imap_Client_Exception_NoSupportExtension $e) {
</span><span class="lines">@@ -822,13 +770,11 @@
</span><span class="cx">      */
</span><span class="cx">     public function logout()
</span><span class="cx">     {
</span><del>-        if ($this->_isAuthenticated && $this->_connection->connected) {
</del><ins>+        if ($this->_isAuthenticated) {
</ins><span class="cx">             $this->_logout();
</span><del>-            $this->_connection->close();
</del><ins>+            $this->_isAuthenticated = false;
</ins><span class="cx">         }
</span><del>-
-        $this->_connection = $this->_selected = null;
-        $this->_isAuthenticated = false;
</del><ins>+        $this->_selected = null;
</ins><span class="cx">         $this->_mode = 0;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -852,7 +798,7 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_NoSupportExtension('ID');
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $this->_sendID(is_null($info) ? ($this->getParam('id') ?: array()) : $info);
</del><ins>+        $this->_sendID(is_null($info) ? (empty($this->_params['id']) ? array() : $this->_params['id']) : $info);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -911,7 +857,7 @@
</span><span class="cx"> 
</span><span class="cx">         if ($this->queryCapability('LANGUAGE')) {
</span><span class="cx">             $lang = is_null($langs)
</span><del>-                ? $this->getParam('lang')
</del><ins>+                ? (empty($this->_params['lang']) ? null : $this->_params['lang'])
</ins><span class="cx">                 : $langs;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -1380,7 +1326,8 @@
</span><span class="cx"> 
</span><span class="cx">         if (!empty($options['status']) &&
</span><span class="cx">             !$this->queryCapability('LIST-STATUS')) {
</span><del>-            foreach ($this->status(array_keys($ret), $options['status']) as $key => $val) {
</del><ins>+            $status = $this->statusMultiple($this->_selected, $options['status']);
+            foreach ($status as $key => $val) {
</ins><span class="cx">                 $ret[$key]['status'] = $val;
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -1423,10 +1370,9 @@
</span><span class="cx">     /**
</span><span class="cx">      * Obtain status information for a mailbox.
</span><span class="cx">      *
</span><del>-     * @param mixed $mailbox  The mailbox(es) to query. Either a
-     *                        Horde_Imap_Client_Mailbox object, a string
-     *                        (UTF-8), or an array of objects/strings (since
-     *                        2.10.0).
</del><ins>+     * @param mixed $mailbox  The mailbox to query. Either a
+     *                        Horde_Imap_Client_Mailbox object or a string
+     *                        (UTF-8).
</ins><span class="cx">      * @param integer $flags  A bitmask of information requested from the
</span><span class="cx">      *                        server. Allowed flags:
</span><span class="cx">      * <ul>
</span><span class="lines">@@ -1449,25 +1395,11 @@
</span><span class="cx">      *    </li>
</span><span class="cx">      *    <li>
</span><span class="cx">      *     Return format: (integer) The number of messages with the \Recent
</span><del>-     *     flag set as currently reported in the mailbox
</del><ins>+     *     flag set
</ins><span class="cx">      *    </li>
</span><span class="cx">      *   </ul>
</span><span class="cx">      *  </li>
</span><span class="cx">      *  <li>
</span><del>-     *   Horde_Imap_Client::STATUS_RECENT_TOTAL
-     *   <ul>
-     *    <li>
-     *     Return key: recent_total
-     *    </li>
-     *    <li>
-     *     Return format: (integer) The number of messages with the \Recent
-     *     flag set. This returns the total number of messages that have
-     *     been marked as recent in this mailbox since the PHP process began.
-     *     (since 2.12.0)
-     *    </li>
-     *   </ul>
-     *  </li>
-     *  <li>
</del><span class="cx">      *   Horde_Imap_Client::STATUS_UIDNEXT
</span><span class="cx">      *   <ul>
</span><span class="cx">      *    <li>
</span><span class="lines">@@ -1626,19 +1558,6 @@
</span><span class="cx">      *   </ul>
</span><span class="cx">      *  </li>
</span><span class="cx">      *  <li>
</span><del>-     *   Horde_Imap_Client::STATUS_FORCE_REFRESH
-     *   <ul>
-     *    <li>
-     *     Normally, the status information will be cached for a given
-     *     mailbox. Since most PHP requests are generally less than a second,
-     *     this is fine. However, if your script is long running, the status
-     *     information may not be up-to-date. Specifying this flag will ensure
-     *     that the server is always polled for the current mailbox status
-     *     before results are returned. (since 2.14.0)
-     *    </li>
-     *   </ul>
-     *  </li>
-     *  <li>
</del><span class="cx">      *   Horde_Imap_Client::STATUS_ALL (DEFAULT)
</span><span class="cx">      *   <ul>
</span><span class="cx">      *    <li>
</span><span class="lines">@@ -1648,201 +1567,95 @@
</span><span class="cx">      *   </ul>
</span><span class="cx">      *  </li>
</span><span class="cx">      * </ul>
</span><del>-     * @param array $opts     Additional options:
-     *   - sort: (boolean) If true, sort the list of mailboxes? (since 2.10.0)
-     *           DEFAULT: Do not sort the list.
-     *   - sort_delimiter: (string) If 'sort' is true, this is the delimiter
-     *                     used to sort the mailboxes. (since 2.10.0)
-     *                     DEFAULT: '.'
</del><span class="cx">      *
</span><del>-     * @return array  If $mailbox contains multiple mailboxes, an array with
-     *                keys being the UTF-8 mailbox name and values as arrays
-     *                containing the requested keys (see above).
-     *                Otherwise, an array with keys as the requested keys (see
-     *                above) and values as the key data.
</del><ins>+     * @return array  An array with the requested keys (see above).
</ins><span class="cx">      *
</span><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      */
</span><del>-    public function status($mailbox, $flags = Horde_Imap_Client::STATUS_ALL,
-                           array $opts = array())
</del><ins>+    public function status($mailbox, $flags = Horde_Imap_Client::STATUS_ALL)
</ins><span class="cx">     {
</span><del>-        $opts = array_merge(array(
-            'sort' => false,
-            'sort_delimiter' => '.'
-        ), $opts);
-
</del><span class="cx">         $this->login();
</span><span class="cx"> 
</span><del>-        if (is_array($mailbox)) {
-            if (empty($mailbox)) {
-                return array();
-            }
-            $ret_array = true;
-        } else {
-            $mailbox = array($mailbox);
-            $ret_array = false;
-        }
-
-        $mlist = array_map(array('Horde_Imap_Client_Mailbox', 'get'), $mailbox);
-
</del><span class="cx">         $unselected_flags = array(
</span><span class="cx">             'messages' => Horde_Imap_Client::STATUS_MESSAGES,
</span><span class="cx">             'recent' => Horde_Imap_Client::STATUS_RECENT,
</span><ins>+            'unseen' => Horde_Imap_Client::STATUS_UNSEEN,
</ins><span class="cx">             'uidnext' => Horde_Imap_Client::STATUS_UIDNEXT,
</span><del>-            'uidvalidity' => Horde_Imap_Client::STATUS_UIDVALIDITY,
-            'unseen' => Horde_Imap_Client::STATUS_UNSEEN
</del><ins>+            'uidvalidity' => Horde_Imap_Client::STATUS_UIDVALIDITY
</ins><span class="cx">         );
</span><span class="cx"> 
</span><del>-        if (!$this->statuscache) {
-            $flags |= Horde_Imap_Client::STATUS_FORCE_REFRESH;
-        }
-
</del><span class="cx">         if ($flags & Horde_Imap_Client::STATUS_ALL) {
</span><span class="cx">             foreach ($unselected_flags as $val) {
</span><span class="cx">                 $flags |= $val;
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $master = $ret = array();
</del><ins>+        $mailbox = Horde_Imap_Client_Mailbox::get($mailbox);
+        $ret = array();
</ins><span class="cx"> 
</span><span class="cx">         /* Catch flags that are not supported. */
</span><span class="cx">         if (($flags & Horde_Imap_Client::STATUS_HIGHESTMODSEQ) &&
</span><del>-            !isset($this->_temp['enabled']['CONDSTORE'])) {
-            $master['highestmodseq'] = 0;
</del><ins>+            !isset($this->_init['enabled']['CONDSTORE'])) {
+            $ret['highestmodseq'] = 0;
</ins><span class="cx">             $flags &= ~Horde_Imap_Client::STATUS_HIGHESTMODSEQ;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (($flags & Horde_Imap_Client::STATUS_UIDNOTSTICKY) &&
</span><span class="cx">             !$this->queryCapability('UIDPLUS')) {
</span><del>-            $master['uidnotsticky'] = false;
</del><ins>+            $ret['uidnotsticky'] = false;
</ins><span class="cx">             $flags &= ~Horde_Imap_Client::STATUS_UIDNOTSTICKY;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        /* UIDNEXT return options. */
-        if ($flags & Horde_Imap_Client::STATUS_UIDNEXT_FORCE) {
-            $flags |= Horde_Imap_Client::STATUS_UIDNEXT;
</del><ins>+        /* Handle SYNC related return options. These require the mailbox
+         * to be opened at least once. */
+        if ($flags & Horde_Imap_Client::STATUS_SYNCMODSEQ) {
+            $this->openMailbox($mailbox);
+            $ret['syncmodseq'] = $this->_mailboxOb($mailbox)->getStatus(Horde_Imap_Client::STATUS_SYNCMODSEQ);
+            $flags &= ~Horde_Imap_Client::STATUS_SYNCMODSEQ;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        foreach ($mlist as $val) {
-            $name = strval($val);
-            $tmp_flags = $flags;
</del><ins>+        if ($flags & Horde_Imap_Client::STATUS_SYNCFLAGUIDS) {
+            $this->openMailbox($mailbox);
+            $ret['syncflaguids'] = $this->getIdsOb($this->_mailboxOb($mailbox)->getStatus(Horde_Imap_Client::STATUS_SYNCFLAGUIDS));
+            $flags &= ~Horde_Imap_Client::STATUS_SYNCFLAGUIDS;
+        }
</ins><span class="cx"> 
</span><del>-            if ($val->equals($this->_selected)) {
-                /* Check if already in mailbox. */
-                $opened = true;
-
-                if ($flags & Horde_Imap_Client::STATUS_FORCE_REFRESH) {
-                    $this->noop();
-                }
-            } else {
-                /* A list of STATUS options (other than those handled directly
-                 * below) that require the mailbox to be explicitly opened. */
-                $opened = ($flags & Horde_Imap_Client::STATUS_FIRSTUNSEEN) ||
-                    ($flags & Horde_Imap_Client::STATUS_FLAGS) ||
-                    ($flags & Horde_Imap_Client::STATUS_PERMFLAGS) ||
-                    ($flags & Horde_Imap_Client::STATUS_UIDNOTSTICKY) ||
-                    /* Force mailboxes containing wildcards to be accessed via
-                     * STATUS so that wildcards do not return a bunch of
-                     * mailboxes in the LIST-STATUS response. */
-                    (strpbrk($name, '*%') !== false);
-            }
-
-            $ret[$name] = $master;
-            $ptr = &$ret[$name];
-
-            /* STATUS_PERMFLAGS requires a read/write mailbox. */
-            if ($flags & Horde_Imap_Client::STATUS_PERMFLAGS) {
-                $this->openMailbox($val, Horde_Imap_Client::OPEN_READWRITE);
-                $opened = true;
-            }
-
-            /* Handle SYNC related return options. These require the mailbox
-             * to be opened at least once. */
-            if ($flags & Horde_Imap_Client::STATUS_SYNCMODSEQ) {
-                $this->openMailbox($val);
-                $ptr['syncmodseq'] = $this->_mailboxOb($val)->getStatus(Horde_Imap_Client::STATUS_SYNCMODSEQ);
-                $tmp_flags &= ~Horde_Imap_Client::STATUS_SYNCMODSEQ;
-                $opened = true;
-            }
-
-            if ($flags & Horde_Imap_Client::STATUS_SYNCFLAGUIDS) {
-                $this->openMailbox($val);
-                $ptr['syncflaguids'] = $this->getIdsOb($this->_mailboxOb($val)->getStatus(Horde_Imap_Client::STATUS_SYNCFLAGUIDS));
-                $tmp_flags &= ~Horde_Imap_Client::STATUS_SYNCFLAGUIDS;
-                $opened = true;
-            }
-
-            if ($flags & Horde_Imap_Client::STATUS_SYNCVANISHED) {
-                $this->openMailbox($val);
-                $ptr['syncvanished'] = $this->getIdsOb($this->_mailboxOb($val)->getStatus(Horde_Imap_Client::STATUS_SYNCVANISHED));
-                $tmp_flags &= ~Horde_Imap_Client::STATUS_SYNCVANISHED;
-                $opened = true;
-            }
-
-            /* Handle RECENT_TOTAL option. */
-            if ($flags & Horde_Imap_Client::STATUS_RECENT_TOTAL) {
-                $this->openMailbox($val);
-                $ptr['recent_total'] = $this->_mailboxOb($val)->getStatus(Horde_Imap_Client::STATUS_RECENT_TOTAL);
-                $tmp_flags &= ~Horde_Imap_Client::STATUS_RECENT_TOTAL;
-                $opened = true;
-            }
-
-            if ($opened) {
-                if ($tmp_flags) {
-                    $tmp = $this->_status(array($val), $tmp_flags);
-                    $ptr += reset($tmp);
-                }
-            } else {
-                $to_process[] = $val;
-            }
</del><ins>+        if ($flags & Horde_Imap_Client::STATUS_SYNCVANISHED) {
+            $this->openMailbox($mailbox);
+            $ret['syncvanished'] = $this->getIdsOb($this->_mailboxOb($mailbox)->getStatus(Horde_Imap_Client::STATUS_SYNCVANISHED));
+            $flags &= ~Horde_Imap_Client::STATUS_SYNCVANISHED;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if ($flags && !empty($to_process)) {
-            if ((count($to_process) > 1) &&
-                $this->queryCapability('LIST-STATUS')) {
-                foreach ($this->listMailboxes($to_process, Horde_Imap_Client::MBOX_ALL, array('status' => $flags)) as $key => $val) {
-                    if (isset($val['status'])) {
-                        $ret[$key] += $val['status'];
-                    }
-                }
-            } else {
-                foreach ($this->_status($to_process, $flags) as $key => $val) {
-                    $ret[$key] += $val;
-                }
-            }
</del><ins>+        /* UIDNEXT return options. */
+        if ($flags & Horde_Imap_Client::STATUS_UIDNEXT_FORCE) {
+            $flags |= Horde_Imap_Client::STATUS_UIDNEXT;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!$opts['sort'] || (count($ret) == 1)) {
-            return $ret_array
-                ? $ret
-                : reset($ret);
</del><ins>+        if (!$flags) {
+            return $ret;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $list_ob = new Horde_Imap_Client_Mailbox_List(array_keys($ret));
-        $sorted = $list_ob->sort(array(
-            'delimiter' => $opts['sort_delimiter']
-        ));
-
-        $out = array();
-        foreach ($sorted as $val) {
-            $out[$val] = $ret[$val];
</del><ins>+        /* STATUS_PERMFLAGS requires a read/write mailbox. */
+        if ($flags & Horde_Imap_Client::STATUS_PERMFLAGS) {
+            $this->openMailbox($mailbox, Horde_Imap_Client::OPEN_READWRITE);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return $out;
</del><ins>+        return array_merge($ret, $this->_status($mailbox, $flags));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Obtain status information for mailboxes.
</del><ins>+     * Obtain status information for a mailbox.
</ins><span class="cx">      *
</span><del>-     * @param array $mboxes   The list of mailbox objects to query.
-     * @param integer $flags  A bitmask of information requested from the
-     *                        server.
</del><ins>+     * @param Horde_Imap_Client_Mailbox $mailbox  The mailbox to query.
+     * @param integer $flags                      A bitmask of information
+     *                                            requested from the server.
</ins><span class="cx">      *
</span><del>-     * @return array  See array return for status().
</del><ins>+     * @return array  See status().
</ins><span class="cx">      *
</span><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      */
</span><del>-    abstract protected function _status($mboxes, $flags);
</del><ins>+    abstract protected function _status(Horde_Imap_Client_Mailbox $mailbox,
+                                        $flags);
</ins><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Perform a STATUS call on multiple mailboxes at the same time.
</span><span class="lines">@@ -1850,8 +1663,6 @@
</span><span class="cx">      * This method leverages the LIST-EXTENDED and LIST-STATUS extensions on
</span><span class="cx">      * the IMAP server to improve the efficiency of this operation.
</span><span class="cx">      *
</span><del>-     * @deprecated  Use status() instead.
-     *
</del><span class="cx">      * @param array $mailboxes  The mailboxes to query. Either
</span><span class="cx">      *                          Horde_Imap_Client_Mailbox objects, strings
</span><span class="cx">      *                          (UTF-8), or a combination of the two.
</span><span class="lines">@@ -1871,7 +1682,76 @@
</span><span class="cx">                                    $flags = Horde_Imap_Client::STATUS_ALL,
</span><span class="cx">                                    array $opts = array())
</span><span class="cx">     {
</span><del>-        return $this->status($mailboxes, $flags, $opts);
</del><ins>+        if (empty($mailboxes)) {
+            return array();
+        }
+
+        $this->login();
+
+        $opts = array_merge(array(
+            'sort' => false,
+            'sort_delimiter' => '.'
+        ), $opts);
+
+        $need_status = true;
+        $ret = array();
+
+        /* Optimization: If there is one mailbox in list, and we are already
+         * in that mailbox, we should just do a straight STATUS call. */
+        if ($this->queryCapability('LIST-STATUS') &&
+            ((count($mailboxes) != 1) ||
+            !Horde_Imap_Client_Mailbox::get(reset($mailboxes))->equals($this->_selected))) {
+            $status = $to_process = array();
+            foreach ($mailboxes as $val) {
+                // Force mailboxes containing wildcards to be accessed via
+                // STATUS so that wildcards do not return a bunch of mailboxes
+                // in the LIST-STATUS response.
+                if (strpbrk($val, '*%') === false) {
+                    $to_process[] = $val;
+                }
+                $status[strval($val)] = 1;
+            }
+
+            try {
+                foreach ($this->listMailboxes($to_process, Horde_Imap_Client::MBOX_ALL, array_merge($opts, array('status' => $flags))) as $val) {
+                    if (isset($val['status'])) {
+                        $ret[strval($val['mailbox'])] = $val['status'];
+                    }
+                    unset($status[strval($val['mailbox'])]);
+                }
+            } catch (Horde_Imap_Client_Exception $e) {}
+
+            if (empty($status)) {
+                $need_status = false;
+            } else {
+                $mailboxes = array_keys($status);
+            }
+        }
+
+        if ($need_status) {
+            foreach ($mailboxes as $val) {
+                $val = Horde_Imap_Client_Mailbox::get($val);
+                try {
+                    $ret[strval($val)] = $this->status($val, $flags);
+                } catch (Horde_Imap_Client_Exception $e) {}
+            }
+        }
+
+        if (!$opts['sort']) {
+            return $ret;
+        }
+
+        $list_ob = new Horde_Imap_Client_Mailbox_List(array_keys($ret));
+        $sorted = $list_ob->sort(array(
+            'delimiter' => $opts['sort_delimiter']
+        ));
+
+        $out = array();
+        foreach ($sorted as $val) {
+            $out[$val] = $ret[$val];
+        }
+
+        return $out;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -2064,12 +1944,8 @@
</span><span class="cx">      *                        Horde_Imap_Client_Mailbox object or a string
</span><span class="cx">      *                        (UTF-8).
</span><span class="cx">      * @param array $options  Additional options:
</span><del>-     *   - delete: (boolean) If true, will flag all messages in 'ids' as
-     *             deleted (since 2.10.0).
-     *             DEFAULT: false
-     *   - ids: (Horde_Imap_Client_Ids) A list of messages to expunge. These
-     *          messages must already be flagged as deleted (unless 'delete'
-     *          is true).
</del><ins>+     *   - ids: (Horde_Imap_Client_Ids) A list of messages to expunge, but
+     *          only if they are also flagged as deleted.
</ins><span class="cx">      *          DEFAULT: All messages marked as deleted will be expunged.
</span><span class="cx">      *   - list: (boolean) If true, returns the list of expunged messages
</span><span class="cx">      *           (UIDs only).
</span><span class="lines">@@ -2245,8 +2121,6 @@
</span><span class="cx">                 Horde_Imap_Client::SEARCH_RESULTS_MATCH,
</span><span class="cx">                 Horde_Imap_Client::SEARCH_RESULTS_COUNT
</span><span class="cx">             );
</span><del>-        } elseif (!in_array(Horde_Imap_Client::SEARCH_RESULTS_COUNT, $options['results'])) {
-            $options['results'][] = Horde_Imap_Client::SEARCH_RESULTS_COUNT;
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Default to an ALL search.
</span><span class="lines">@@ -2338,7 +2212,7 @@
</span><span class="cx">         $cache = null;
</span><span class="cx">         if (empty($options['nocache']) &&
</span><span class="cx">             $this->_initCache(true) &&
</span><del>-            (isset($this->_temp['enabled']['CONDSTORE']) ||
</del><ins>+            (isset($this->_init['enabled']['CONDSTORE']) ||
</ins><span class="cx">              !$query->flagSearch())) {
</span><span class="cx">             $cache = $this->_getSearchCache('search', $options);
</span><span class="cx">             if (isset($cache['data'])) {
</span><span class="lines">@@ -2365,14 +2239,12 @@
</span><span class="cx"> 
</span><span class="cx">             $ret = $this->_search($query, $options);
</span><span class="cx">         } else {
</span><del>-            $ret = array();
</del><ins>+            $ret = array(
+                'count' => 0
+            );
</ins><span class="cx"> 
</span><span class="cx">             foreach ($options['results'] as $val) {
</span><span class="cx">                 switch ($val) {
</span><del>-                case Horde_Imap_Client::SEARCH_RESULTS_COUNT:
-                    $ret['count'] = 0;
-                    break;
-
</del><span class="cx">                 case Horde_Imap_Client::SEARCH_RESULTS_MATCH:
</span><span class="cx">                     $ret['match'] = $this->getIdsOb();
</span><span class="cx">                     break;
</span><span class="lines">@@ -2436,7 +2308,7 @@
</span><span class="cx">     public function setComparator($comparator = null)
</span><span class="cx">     {
</span><span class="cx">         $comp = is_null($comparator)
</span><del>-            ? $this->getParam('comparator')
</del><ins>+            ? (empty($this->_params['comparator']) ? null : $this->_params['comparator'])
</ins><span class="cx">             : $comparator;
</span><span class="cx">         if (is_null($comp)) {
</span><span class="cx">             return;
</span><span class="lines">@@ -2544,7 +2416,7 @@
</span><span class="cx">          * that don't involve flags. See search() for similar caching. */
</span><span class="cx">         $cache = null;
</span><span class="cx">         if ($this->_initCache(true) &&
</span><del>-            (isset($this->_temp['enabled']['CONDSTORE']) ||
</del><ins>+            (isset($this->_init['enabled']['CONDSTORE']) ||
</ins><span class="cx">              empty($options['search']) ||
</span><span class="cx">              !$options['search']->flagSearch())) {
</span><span class="cx">             $cache = $this->_getSearchCache('thread', $options);
</span><span class="lines">@@ -2666,7 +2538,7 @@
</span><span class="cx"> 
</span><span class="cx">         $modseq_check = !empty($options['changedsince']);
</span><span class="cx">         if ($query->contains(Horde_Imap_Client::FETCH_MODSEQ)) {
</span><del>-            if (!isset($this->_temp['enabled']['CONDSTORE'])) {
</del><ins>+            if (!isset($this->_init['enabled']['CONDSTORE'])) {
</ins><span class="cx">                 unset($query[Horde_Imap_Client::FETCH_MODSEQ]);
</span><span class="cx">             } elseif (empty($options['changedsince'])) {
</span><span class="cx">                 $modseq_check = true;
</span><span class="lines">@@ -2684,7 +2556,8 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         /* Determine if caching is available and if anything in $query is
</span><del>-         * cacheable. */
</del><ins>+         * cacheable.
+         * TODO: Re-add base headertext caching. */
</ins><span class="cx">         foreach ($cf as $k => $v) {
</span><span class="cx">             if (isset($query[$k])) {
</span><span class="cx">                 switch ($k) {
</span><span class="lines">@@ -2720,8 +2593,7 @@
</span><span class="cx"> 
</span><span class="cx">         /* If nothing is cacheable, we can do a straight search. */
</span><span class="cx">         if (empty($cache_array)) {
</span><del>-            $options['_query'] = $query;
-            $this->_fetch($ret, array($options));
</del><ins>+            $this->_fetch($ret, $query, $options);
</ins><span class="cx">             return $ret;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -2732,9 +2604,6 @@
</span><span class="cx">         /* Convert special searches to UID lists and create mapping. */
</span><span class="cx">         $ids = $this->resolveIds($this->_selected, $options['ids'], empty($options['exists']) ? 1 : 2);
</span><span class="cx"> 
</span><del>-        /* Add non-user settable cache fields. */
-        $cache_array[Horde_Imap_Client::FETCH_DOWNGRADED] = self::CACHE_DOWNGRADED;
-
</del><span class="cx">         /* Get the cached values. */
</span><span class="cx">         $data = $this->_cache->get($this->_selected, $ids->ids, array_values($cache_array), $mbox_ob->getStatus(Horde_Imap_Client::STATUS_UIDVALIDITY));
</span><span class="cx"> 
</span><span class="lines">@@ -2765,12 +2634,6 @@
</span><span class="cx"> 
</span><span class="cx">             foreach ($cache_array as $key => $cid) {
</span><span class="cx">                 switch ($key) {
</span><del>-                case Horde_Imap_Client::FETCH_DOWNGRADED:
-                    if (!empty($data[$uid][$cid])) {
-                        $entry->setDowngraded(true);
-                    }
-                    break;
-
</del><span class="cx">                 case Horde_Imap_Client::FETCH_ENVELOPE:
</span><span class="cx">                     if (isset($data[$uid][$cid]) &&
</span><span class="cx">                         ($data[$uid][$cid] instanceof Horde_Imap_Client_Data_Envelope)) {
</span><span class="lines">@@ -2788,6 +2651,7 @@
</span><span class="cx">                     break;
</span><span class="cx"> 
</span><span class="cx">                 case Horde_Imap_Client::FETCH_HEADERS:
</span><ins>+                    /* HEADERS caching. */
</ins><span class="cx">                     foreach ($header_cache as $hkey => $hval) {
</span><span class="cx">                         if (isset($data[$uid][$cid][$hval])) {
</span><span class="cx">                             /* We have found a cached entry with the same
</span><span class="lines">@@ -2838,21 +2702,15 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $to_fetch = array();
</del><span class="cx">         foreach ($new_query as $val) {
</span><span class="cx">             $ids_ob = $this->getIdsOb(null, $sequence);
</span><span class="cx">             $ids_ob->duplicates = true;
</span><span class="cx">             $ids_ob->add($val['i']);
</span><del>-            $to_fetch[] = array_merge($options, array(
-                '_query' => $val['c'],
</del><ins>+            $this->_fetch(is_null($cs_ret) ? $ret : $cs_ret, $val['c'], array_merge($options, array(
</ins><span class="cx">                 'ids' => $ids_ob
</span><del>-            ));
</del><ins>+            )));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!empty($to_fetch)) {
-            $this->_fetch(is_null($cs_ret) ? $ret : $cs_ret, $to_fetch);
-        }
-
</del><span class="cx">         if (is_null($cs_ret)) {
</span><span class="cx">             return $ret;
</span><span class="cx">         }
</span><span class="lines">@@ -2889,18 +2747,15 @@
</span><span class="cx">     /**
</span><span class="cx">      * Fetch message data.
</span><span class="cx">      *
</span><del>-     * Fetch queries should be grouped in the $queries argument. Each value
-     * is an array of fetch options, with the fetch query stored in the
-     * '_query' parameter. IMPORTANT: All queries must have the same ID
-     * type (either sequence or UID).
-     *
</del><span class="cx">      * @param Horde_Imap_Client_Fetch_Results $results  Fetch results.
</span><del>-     * @param array $queries                            The list of queries.
</del><ins>+     * @param Horde_Imap_Client_Fetch_Query $query      Fetch query object.
+     * @param array $options                            Additional options.
</ins><span class="cx">      *
</span><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      */
</span><span class="cx">     abstract protected function _fetch(Horde_Imap_Client_Fetch_Results $results,
</span><del>-                                       $queries);
</del><ins>+                                       Horde_Imap_Client_Fetch_Query $query,
+                                       $options);
</ins><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Get the list of vanished messages (UIDs that have been expunged since a
</span><span class="lines">@@ -3020,7 +2875,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (!empty($options['unchangedsince'])) {
</span><del>-            if (!isset($this->_temp['enabled']['CONDSTORE'])) {
</del><ins>+            if (!isset($this->_init['enabled']['CONDSTORE'])) {
</ins><span class="cx">                 throw new Horde_Imap_Client_Exception_NoSupportExtension('CONDSTORE');
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -3570,7 +3425,7 @@
</span><span class="cx">      */
</span><span class="cx">     public function getCacheId($mailbox, array $addl = array())
</span><span class="cx">     {
</span><del>-        return Horde_Imap_Client_Base_Deprecated::getCacheId($this, $mailbox, isset($this->_temp['enabled']['CONDSTORE']), $addl);
</del><ins>+        return Horde_Imap_Client_Base_Deprecated::getCacheId($this, $mailbox, isset($this->_init['enabled']['CONDSTORE']), $addl);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -3616,9 +3471,7 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             $convert = 2;
</span><del>-        } elseif (!$convert ||
-                  (!$ids->sequence && ($convert == 1)) ||
-                  $ids->isEmpty()) {
</del><ins>+        } elseif (!$convert || (!$ids->sequence && ($convert == 1))) {
</ins><span class="cx">             return clone $ids;
</span><span class="cx">         } else {
</span><span class="cx">             /* Do an all or nothing: either we have all the numbers/UIDs in
</span><span class="lines">@@ -3652,7 +3505,7 @@
</span><span class="cx">                 return $res['match'];
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            $map->update(array_combine(array_slice($ids->ids, 0, count($res['match'])), $res['match']->ids));
</del><ins>+            $map->update(array_combine($ids->ids, $res['match']->ids));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return $res['match'];
</span><span class="lines">@@ -3782,8 +3635,7 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $c = $this->getParam('cache');
-        if (in_array(strval($this->_selected), $c['fetch_ignore'])) {
</del><ins>+        if (in_array(strval($this->_selected), $this->_params['cache']['fetch_ignore'])) {
</ins><span class="cx">             $this->_debug->info(sprintf("CACHE: Ignoring FETCH data (mailbox: %s)", $this->_selected));
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -3808,10 +3660,6 @@
</span><span class="cx"> 
</span><span class="cx">             $tmp = array();
</span><span class="cx"> 
</span><del>-            if ($v->isDowngraded()) {
-                $tmp[self::CACHE_DOWNGRADED] = true;
-            }
-
</del><span class="cx">             foreach ($cf as $key => $val) {
</span><span class="cx">                 if ($v->exists($key)) {
</span><span class="cx">                     switch ($key) {
</span><span class="lines">@@ -3888,8 +3736,7 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $c = $this->getParam('cache');
-        if (in_array(strval($to), $c['fetch_ignore'])) {
</del><ins>+        if (in_array(strval($to), $this->_params['cache']['fetch_ignore'])) {
</ins><span class="cx">             $this->_debug->info(sprintf("CACHE: Ignoring moving FETCH data (%s => %s)", $this->_selected, $to));
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -3914,15 +3761,12 @@
</span><span class="cx">      * @param Horde_Imap_Client_Mailbox $mailbox  The mailbox.
</span><span class="cx">      * @param Horde_Imap_Client_Ids $ids          The list of IDs to delete in
</span><span class="cx">      *                                            $mailbox.
</span><del>-     * @param array $opts                         Additional options (not used
-     *                                            in base class).
</del><span class="cx">      *
</span><span class="cx">      * @return Horde_Imap_Client_Ids  UIDs that were deleted.
</span><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      */
</span><span class="cx">     protected function _deleteMsgs(Horde_Imap_Client_Mailbox $mailbox,
</span><del>-                                   Horde_Imap_Client_Ids $ids,
-                                   array $opts = array())
</del><ins>+                                   Horde_Imap_Client_Ids $ids)
</ins><span class="cx">     {
</span><span class="cx">         if (!$this->_initCache()) {
</span><span class="cx">             return $ids;
</span><span class="lines">@@ -4078,12 +3922,9 @@
</span><span class="cx">             $fquery->flags();
</span><span class="cx"> 
</span><span class="cx">             /* Update flags in cache. Cache will be updated in _fetch(). */
</span><del>-            $this->_fetch(new Horde_Imap_Client_Fetch_Results(), array(
-                array(
-                    '_query' => $fquery,
-                    'changedsince' => $modseq,
-                    'ids' => $uids_ob
-                )
</del><ins>+            $this->_fetch(new Horde_Imap_Client_Fetch_Results(), $fquery, array(
+                'changedsince' => $modseq,
+                'ids' => $uids_ob
</ins><span class="cx">             ));
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -4105,10 +3946,9 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _cacheFields()
</span><span class="cx">     {
</span><del>-        $c = $this->getParam('cache');
-        $out = $c['fields'];
</del><ins>+        $out = $this->_params['cache']['fields'];
</ins><span class="cx"> 
</span><del>-        if (!isset($this->_temp['enabled']['CONDSTORE'])) {
</del><ins>+        if (!isset($this->_init['enabled']['CONDSTORE'])) {
</ins><span class="cx">             unset($out[Horde_Imap_Client::FETCH_FLAGS]);
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientSocketPop3php"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Pop3.php (2317 => 2318)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Pop3.php     2013-09-16 02:11:45 UTC (rev 2317)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Pop3.php        2013-09-16 02:11:57 UTC (rev 2318)
</span><span class="lines">@@ -61,8 +61,7 @@
</span><span class="cx">  *   - RFC 2595/4616: PLAIN authentication
</span><span class="cx">  *   - RFC 2831: DIGEST-MD5 SASL Authentication (obsoleted by RFC 6331)
</span><span class="cx">  *   - RFC 3206: AUTH/SYS response codes
</span><del>- *   - RFC 4616: AUTH=PLAIN
- *   - RFC 5034: POP3 SASL
</del><ins>+ *   - RFC 1734/5034: POP3 SASL
</ins><span class="cx">  *
</span><span class="cx">  * @author    Richard Heyes <richard@phpguru.org>
</span><span class="cx">  * @author    Michael Slusarz <slusarz@horde.org>
</span><span class="lines">@@ -75,13 +74,6 @@
</span><span class="cx"> class Horde_Imap_Client_Socket_Pop3 extends Horde_Imap_Client_Base
</span><span class="cx"> {
</span><span class="cx">     /**
</span><del>-     * The default ports to use for a connection.
-     *
-     * @var array
-     */
-    protected $_defaultPorts = array(110, 995);
-
-    /**
</del><span class="cx">      * The list of deleted messages.
</span><span class="cx">      *
</span><span class="cx">      * @var array
</span><span class="lines">@@ -96,7 +88,27 @@
</span><span class="cx">     protected $_fetchDataClass = 'Horde_Imap_Client_Data_Fetch_Pop3';
</span><span class="cx"> 
</span><span class="cx">     /**
</span><ins>+     * The socket connection to the POP3 server.
+     *
+     * @var resource
</ins><span class="cx">      */
</span><ins>+    protected $_stream = null;
+
+    /**
+     */
+    public function __construct(array $params = array())
+    {
+        parent::__construct($params);
+
+        if (empty($params['port'])) {
+            $this->_params['port'] = (isset($this->_params['secure']) && in_array($this->_params['secure'], array('ssl', 'sslv2', 'sslv3')))
+                ? 995
+                : 110;
+        }
+    }
+
+    /**
+     */
</ins><span class="cx">     protected function _initCache($current = false)
</span><span class="cx">     {
</span><span class="cx">         return parent::_initCache($current) &&
</span><span class="lines">@@ -119,39 +131,36 @@
</span><span class="cx">         $capability = array();
</span><span class="cx"> 
</span><span class="cx">         try {
</span><del>-            $res = $this->_sendLine('CAPA', array(
-                'multiline' => 'array'
-            ));
</del><ins>+            $this->_sendLine('CAPA');
</ins><span class="cx"> 
</span><del>-            foreach ($res['data'] as $val) {
</del><ins>+            foreach ($this->_getMultiline(true) as $val) {
</ins><span class="cx">                 $prefix = explode(' ', $val);
</span><ins>+
</ins><span class="cx">                 $capability[strtoupper($prefix[0])] = (count($prefix) > 1)
</span><span class="cx">                     ? array_slice($prefix, 1)
</span><span class="cx">                     : true;
</span><span class="cx">             }
</span><span class="cx">         } catch (Horde_Imap_Client_Exception $e) {
</span><del>-            $this->_temp['no_capa'] = true;
-
</del><span class="cx">             /* Need to probe for capabilities if CAPA command is not
</span><span class="cx">              * available. */
</span><del>-            $capability = array('USER' => true);
</del><ins>+            $capability = array('USER', 'SASL');
</ins><span class="cx"> 
</span><del>-            /* Capability sniffing only guaranteed after authentication is
-             * completed (if any). */
-            if (!empty($this->_init['authmethod'])) {
-                $this->_pop3Cache('uidl');
-                if (empty($this->_temp['no_uidl'])) {
-                    $capability['UIDL'] = true;
-                }
</del><ins>+            try {
+                $this->_sendLine('UIDL');
+                fclose($this->_getMultiline());
+                $capability[] = 'UIDL';
+            } catch (Horde_Imap_Client_Exception $e) {}
</ins><span class="cx"> 
</span><del>-                $this->_pop3Cache('top', 1);
-                if (empty($this->_temp['no_top'])) {
-                    $capability['TOP'] = true;
-                }
-            }
</del><ins>+            try {
+                $this->_sendLine('TOP 1 0');
+                fclose($this->_getMultiline());
+                $capability[] = 'TOP';
+            } catch (Horde_Imap_Client_Exception $e) {}
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         $this->_setInit('capability', $capability);
</span><ins>+
+        return $this->_init['capability'];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -182,37 +191,33 @@
</span><span class="cx">     {
</span><span class="cx">         $this->_connect();
</span><span class="cx"> 
</span><del>-        $secure = $this->getParam('secure');
-
</del><span class="cx">         // Switch to secure channel if using TLS.
</span><del>-        if (!$this->isSecureConnection() &&
-            (($secure === 'tls') || $secure === true)) {
</del><ins>+        if (!$this->_isSecure &&
+            ($this->_params['secure'] == 'tls')) {
</ins><span class="cx">             // Switch over to a TLS connection.
</span><span class="cx">             if (!$this->queryCapability('STLS')) {
</span><del>-                if ($secure === 'tls') {
-                    throw new Horde_Imap_Client_Exception(
-                        Horde_Imap_Client_Translation::t("Could not open secure connection to the POP3 server.") . ' ' . Horde_Imap_Client_Translation::t("Server does not support secure connections."),
-                        Horde_Imap_Client_Exception::LOGIN_TLSFAILURE
-                    );
-                } else {
-                    $this->setParam('secure', false);
-                }
-            } else {
-                $this->_sendLine('STLS');
</del><ins>+                throw new Horde_Imap_Client_Exception(
+                    Horde_Imap_Client_Translation::t("Could not open secure connection to the POP3 server.") . ' ' . Horde_Imap_Client_Translation::t("Server does not support secure connections."),
+                    Horde_Imap_Client_Exception::LOGIN_TLSFAILURE
+                );
+            }
</ins><span class="cx"> 
</span><del>-                $this->setParam('secure', 'tls');
</del><ins>+            $this->_sendLine('STLS');
</ins><span class="cx"> 
</span><del>-                if (!$this->_connection->startTls()) {
-                    $this->logout();
-                    throw new Horde_Imap_Client_Exception(
-                        Horde_Imap_Client_Translation::t("Could not open secure connection to the POP3 server."),
-                        Horde_Imap_Client_Exception::LOGIN_TLSFAILURE
-                    );
-                }
</del><ins>+            $res = @stream_socket_enable_crypto($this->_stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
+
+            if (!$res) {
+                $this->logout();
+                throw new Horde_Imap_Client_Exception(
+                    Horde_Imap_Client_Translation::t("Could not open secure connection to the POP3 server."),
+                    Horde_Imap_Client_Exception::LOGIN_TLSFAILURE
+                );
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             // Expire cached CAPABILITY information
</span><span class="cx">             $this->_setInit('capability');
</span><ins>+
+            $this->_isSecure = true;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (empty($this->_init['authmethod'])) {
</span><span class="lines">@@ -233,12 +238,6 @@
</span><span class="cx">             try {
</span><span class="cx">                 $this->_tryLogin($method);
</span><span class="cx">                 $this->_setInit('authmethod', $method);
</span><del>-
-                if (!empty($this->_temp['no_capa']) ||
-                    !$this->queryCapability('UIDL')) {
-                    $this->_capability();
-                }
-
</del><span class="cx">                 return true;
</span><span class="cx">             } catch (Horde_Imap_Client_Exception $e) {
</span><span class="cx">                 if (!empty($this->_init['authmethod'])) {
</span><span class="lines">@@ -261,16 +260,47 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _connect()
</span><span class="cx">     {
</span><del>-        if (!is_null($this->_connection)) {
</del><ins>+        if (!is_null($this->_stream)) {
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $this->_connection = new Horde_Imap_Client_Socket_Connection_Pop3($this, $this->_debug);
</del><ins>+        if (!empty($this->_params['secure']) && !extension_loaded('openssl')) {
+            new InvalidArgumentException('Secure connections require the PHP openssl extension.');
+        }
</ins><span class="cx"> 
</span><del>-        $line = $this->_getResponse();
</del><ins>+        switch ($this->_params['secure']) {
+        case 'ssl':
+        case 'sslv2':
+        case 'sslv3':
+            $conn = $this->_params['secure'] . '://';
+            $this->_isSecure = true;
+            break;
</ins><span class="cx"> 
</span><ins>+        case 'tls':
+        default:
+            $conn = 'tcp://';
+            break;
+        }
+
+        $this->_stream = @stream_socket_client($conn . $this->_params['hostspec'] . ':' . $this->_params['port'], $error_number, $error_string, $this->_params['timeout']);
+
+        if ($this->_stream === false) {
+            $this->_stream = null;
+            $this->_isSecure = false;
+            $e = new Horde_Imap_Client_Exception(
+                Horde_Imap_Client_Translation::t("Error connecting to POP3 server."),
+                Horde_Imap_Client_Exception::SERVER_CONNECT
+            );
+            $e->details = sprintf("[%u] %s.", $error_number, $error_string);
+            throw $e;
+        }
+
+        stream_set_timeout($this->_stream, $this->_params['timeout']);
+
+        $line = $this->_getLine();
+
</ins><span class="cx">         // Check for string matching APOP timestamp
</span><del>-        if (preg_match('/<.+@.+>/U', $line['resp'], $matches)) {
</del><ins>+        if (preg_match('/<.+@.+>/U', $line['line'], $matches)) {
</ins><span class="cx">             $this->_temp['pop3timestamp'] = $matches[0];
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -284,9 +314,6 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _tryLogin($method)
</span><span class="cx">     {
</span><del>-        $username = $this->getParam('username');
-        $password = $this->getParam('password');
-
</del><span class="cx">         switch ($method) {
</span><span class="cx">         case 'CRAM-MD5':
</span><span class="cx">         case 'CRAM-SHA1':
</span><span class="lines">@@ -294,9 +321,9 @@
</span><span class="cx">             // RFC 5034: CRAM-MD5
</span><span class="cx">             // CRAM-SHA1 & CRAM-SHA256 supported by Courier SASL library
</span><span class="cx">             $challenge = $this->_sendLine('AUTH ' . $method);
</span><del>-            $response = base64_encode($username . ' ' . hash_hmac(strtolower(substr($method, 5)), base64_decode(substr($challenge['resp'], 2)), $password, true));
</del><ins>+            $response = base64_encode($this->_params['username'] . ' ' . hash_hmac(strtolower(substr($method, 5)), base64_decode(substr($challenge['line'], 2)), $this->getParam('password'), true));
</ins><span class="cx">             $this->_sendLine($response, array(
</span><del>-                'debug' => sprintf('[%s Response - username: %s]', $method, $username)
</del><ins>+                'debug' => '[' . $method . ' Response]'
</ins><span class="cx">             ));
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="lines">@@ -304,16 +331,16 @@
</span><span class="cx">             // RFC 2831; Obsoleted by RFC 6331
</span><span class="cx">             $challenge = $this->_sendLine('AUTH DIGEST-MD5');
</span><span class="cx">             $response = base64_encode(new Horde_Imap_Client_Auth_DigestMD5(
</span><del>-                $username,
-                $password,
-                base64_decode(substr($challenge['resp'], 2)),
-                $this->getParam('hostspec'),
</del><ins>+                $this->_params['username'],
+                $this->getParam('password'),
+                base64_decode(substr($challenge['line'], 2)),
+                $this->_params['hostspec'],
</ins><span class="cx">                 'pop3'
</span><span class="cx">             ));
</span><span class="cx">             $sresponse = $this->_sendLine($response, array(
</span><del>-                'debug' => sprintf('[%s Response - username: %s]', $method, $username)
</del><ins>+                'debug' => '[DIGEST-MD5 Response]'
</ins><span class="cx">             ));
</span><del>-            if (stripos(base64_decode(substr($sresponse['resp'], 2)), 'rspauth=') === false) {
</del><ins>+            if (stripos(base64_decode(substr($sresponse['line'], 2)), 'rspauth=') === false) {
</ins><span class="cx">                 throw new Horde_Imap_Client_Exception(
</span><span class="cx">                     Horde_Imap_Client_Translation::t("Unexpected response from server when authenticating."),
</span><span class="cx">                     Horde_Imap_Client_Exception::SERVER_CONNECT
</span><span class="lines">@@ -325,36 +352,30 @@
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'LOGIN':
</span><del>-            // RFC 4616 (AUTH=PLAIN) & 5034 (POP3 SASL)
</del><ins>+            // RFC 5034
</ins><span class="cx">             $this->_sendLine('AUTH LOGIN');
</span><del>-            $this->_sendLine(base64_encode($username), array(
-                'debug' => sprintf('[AUTH LOGIN Command - username: %s]', $username)
-            ));
-            $this->_sendLine(base64_encode($password), array(
</del><ins>+            $this->_sendLine(base64_encode($this->_params['username']));
+            $this->_sendLine(base64_encode($this->getParam('password')), array(
</ins><span class="cx">                 'debug' => '[AUTH LOGIN Command - password]'
</span><span class="cx">             ));
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'PLAIN':
</span><span class="cx">             // RFC 5034
</span><del>-            $this->_sendLine('AUTH PLAIN ' . base64_encode(implode("\0", array(
-                $username,
-                $username,
-                $password
-            ))), array(
-                'debug' => sprintf('[AUTH PLAIN Command - username: %s]', $username)
</del><ins>+            $this->_sendLine('AUTH PLAIN ' . base64_encode(implode("\0", array($this->_params['username'], $this->getParam('password')))), array(
+                'debug' => sprintf('[AUTH PLAIN Command - username: %s]', $this->_params['username'])
</ins><span class="cx">             ));
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'APOP':
</span><span class="cx">             // RFC 1939 [7]
</span><del>-            $this->_sendLine('APOP ' . $username . ' ' . hash('md5', $this->_temp['pop3timestamp'] . $password));
</del><ins>+            $this->_sendLine('APOP ' . $this->_params['username'] . ' ' . hash('md5', $this->_temp['pop3timestamp'] . $this->_params['password']));
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'USER':
</span><span class="cx">             // RFC 1939 [7]
</span><del>-            $this->_sendLine('USER ' . $username);
-            $this->_sendLine('PASS ' . $password, array(
</del><ins>+            $this->_sendLine('USER ' . $this->_params['username']);
+            $this->_sendLine('PASS ' . $this->getParam('password'), array(
</ins><span class="cx">                 'debug' => '[USER Command - password]'
</span><span class="cx">             ));
</span><span class="cx">             break;
</span><span class="lines">@@ -371,10 +392,14 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _logout()
</span><span class="cx">     {
</span><del>-        try {
-            $this->_sendLine('QUIT');
-        } catch (Horde_Imap_Client_Exception $e) {}
-        $this->_deleted = array();
</del><ins>+        if (!is_null($this->_stream)) {
+            try {
+                $this->_sendLine('QUIT');
+            } catch (Horde_Imap_Client_Exception $e) {}
+            fclose($this->_stream);
+            $this->_stream = null;
+            $this->_deleted = array();
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -417,7 +442,7 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _openMailbox(Horde_Imap_Client_Mailbox $mailbox, $mode)
</span><span class="cx">     {
</span><del>-        if ($mailbox != 'INBOX') {
</del><ins>+        if (strcasecmp($mailbox, 'INBOX') !== 0) {
</ins><span class="cx">             throw new Horde_Imap_Client_Exception_NoSupportPop3('Mailboxes other than INBOX');
</span><span class="cx">         }
</span><span class="cx">         $this->_changeSelected($mailbox, $mode);
</span><span class="lines">@@ -480,14 +505,10 @@
</span><span class="cx">      *                         under Horde_Imap_Client::STATUS_ALL.
</span><span class="cx">      * @throws Horde_Imap_Client_Exception_NoSupportPop3
</span><span class="cx">      */
</span><del>-    protected function _status($mboxes, $flags)
</del><ins>+    protected function _status(Horde_Imap_Client_Mailbox $mailbox, $flags)
</ins><span class="cx">     {
</span><del>-        if ((count($mboxes) > 1) || (reset($mboxes) != 'INBOX')) {
-            throw new Horde_Imap_Client_Exception_NoSupportPop3('Mailboxes other than INBOX');
-        }
</del><ins>+        $this->openMailbox($mailbox);
</ins><span class="cx"> 
</span><del>-        $this->openMailbox('INBOX');
-
</del><span class="cx">         $ret = array();
</span><span class="cx"> 
</span><span class="cx">         if ($flags & Horde_Imap_Client::STATUS_MESSAGES) {
</span><span class="lines">@@ -517,7 +538,7 @@
</span><span class="cx">             $ret['unseen'] = 0;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return array('INBOX' => $ret);
</del><ins>+        return $ret;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -636,26 +657,12 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><ins>+     * @throws Horde_Imap_Client_Exception_NoSupportPop3
</ins><span class="cx">      */
</span><span class="cx">     protected function _fetch(Horde_Imap_Client_Fetch_Results $results,
</span><del>-                              $queries)
</del><ins>+                              Horde_Imap_Client_Fetch_Query $query,
+                              $options)
</ins><span class="cx">     {
</span><del>-        foreach ($queries as $options) {
-            $this->_fetchCmd($results, $options);
-        }
-
-        $this->_updateCache($results);
-    }
-
-     /**
-     * Fetch data for a given fetch query.
-     *
-     * @param Horde_Imap_Client_Fetch_Results $results  Fetch results.
-     * @param array $options                            Fetch query options.
-     */
-    protected function _fetchCmd(Horde_Imap_Client_Fetch_Results $results,
-                                 $options)
-    {
</del><span class="cx">         // Grab sequence IDs - IDs will always be the message number for
</span><span class="cx">         // POP3 fetch commands.
</span><span class="cx">         $seq_ids = $this->_getSeqIds($options['ids']);
</span><span class="lines">@@ -667,7 +674,7 @@
</span><span class="cx">             ? array_combine($seq_ids, $seq_ids)
</span><span class="cx">             : $this->_pop3Cache('uidl');
</span><span class="cx"> 
</span><del>-        foreach ($options['_query'] as $type => $c_val) {
</del><ins>+        foreach ($query as $type => $c_val) {
</ins><span class="cx">             switch ($type) {
</span><span class="cx">             case Horde_Imap_Client::FETCH_FULLMSG:
</span><span class="cx">                 foreach ($seq_ids as $id) {
</span><span class="lines">@@ -761,7 +768,7 @@
</span><span class="cx">                 foreach ($seq_ids as $id) {
</span><span class="cx">                     if ($ptr = $this->_pop3Cache('msg', $id)) {
</span><span class="cx">                         try {
</span><del>-                            $results->get($lookup[$id])->setStructure(Horde_Mime_Part::parseMessage(stream_get_contents($ptr), array('no_body' => true)));
</del><ins>+                            $results->get($lookup[$id])->setStructure(Horde_Mime_Part::parseMessage(stream_get_contents($ptr)));
</ins><span class="cx">                         } catch (Horde_Exception $e) {}
</span><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="lines">@@ -815,13 +822,15 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         }
</span><ins>+
+        $this->_updateCache($results);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Retrieve locally cached message data.
</span><span class="cx">      *
</span><span class="cx">      * @param string $type    Either 'hdr', 'hdrob', 'msg', 'size', 'stat',
</span><del>-     *                        'top', or 'uidl'.
</del><ins>+     *                        or 'uidl'.
</ins><span class="cx">      * @param integer $index  The message index.
</span><span class="cx">      * @param mixed $data     Additional information needed.
</span><span class="cx">      *
</span><span class="lines">@@ -841,22 +850,15 @@
</span><span class="cx"> 
</span><span class="cx">         switch ($type) {
</span><span class="cx">         case 'hdr':
</span><del>-        case 'top':
</del><span class="cx">             $data = null;
</span><del>-            if ($this->queryCapability('TOP') || ($type == 'top')) {
</del><ins>+            if ($this->queryCapability('TOP')) {
</ins><span class="cx">                 try {
</span><del>-                    $res = $this->_sendLine('TOP ' . $index . ' 0', array(
-                        'multiline' => 'stream'
-                    ));
-                    rewind($res['data']);
-                    $data = stream_get_contents($res['data']);
-                    fclose($res['data']);
-                } catch (Horde_Imap_Client_Exception $e) {
-                    $this->_temp['no_top'] = true;
-                    if ($type == 'top') {
-                        return null;
-                    }
-                }
</del><ins>+                    $resp = $this->_sendLine('TOP ' . $index . ' 0');
+                    $ptr = $this->_getMultiline();
+                    rewind($ptr);
+                    $data = stream_get_contents($ptr);
+                    fclose($ptr);
+                } catch (Horde_Imap_Client_Exception $e) {}
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             if (is_null($data)) {
</span><span class="lines">@@ -869,10 +871,8 @@
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'msg':
</span><del>-            $res = $this->_sendLine('RETR ' . $index, array(
-                'multiline' => 'stream'
-            ));
-            $data = $res['data'];
</del><ins>+            $resp = $this->_sendLine('RETR ' . $index);
+            $data = $this->_getMultiline();
</ins><span class="cx">             rewind($data);
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="lines">@@ -880,23 +880,17 @@
</span><span class="cx">         case 'uidl':
</span><span class="cx">             $data = array();
</span><span class="cx">             try {
</span><del>-                $res = $this->_sendLine(($type == 'size') ? 'LIST' : 'UIDL', array(
-                    'multiline' => 'array'
-                ));
-                foreach ($res['data'] as $val) {
</del><ins>+                $this->_sendLine(($type == 'size') ? 'LIST' : 'UIDL');
+                foreach ($this->_getMultiline(true) as $val) {
</ins><span class="cx">                     $resp_data = explode(' ', $val, 2);
</span><span class="cx">                     $data[$resp_data[0]] = $resp_data[1];
</span><span class="cx">                 }
</span><del>-            } catch (Horde_Imap_Client_Exception $e) {
-                if ($type == 'uidl') {
-                    $this->_temp['no_uidl'] = true;
-                }
-            }
</del><ins>+            } catch (Horde_Imap_Client_Exception $e) {}
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'stat':
</span><span class="cx">             $resp = $this->_sendLine('STAT');
</span><del>-            $resp_data = explode(' ', $resp['resp'], 2);
</del><ins>+            $resp_data = explode(' ', $resp['line'], 2);
</ins><span class="cx">             $data = array('msgs' => $resp_data[0], 'size' => $resp_data[1]);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -967,7 +961,6 @@
</span><span class="cx">             foreach ($this->_getSeqIds($options['ids']) as $id) {
</span><span class="cx">                 try {
</span><span class="cx">                     $this->_sendLine('DELE ' . $id);
</span><del>-                    $this->_deleted[] = $id;
</del><span class="cx">                 } catch (Horde_Imap_Client_Exception $e) {}
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -1074,186 +1067,165 @@
</span><span class="cx">         return null;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    /**
-     */
-    public function resolveIds(Horde_Imap_Client_Mailbox $mailbox,
-                               Horde_Imap_Client_Ids $ids, $convert = 0)
-    {
-        if (!$ids->special &&
-            (!$convert ||
-             (!$ids->sequence && ($convert == 1)) ||
-             $ids->isEmpty())) {
-            return clone $ids;
-        }
-
-        $uids = $this->_pop3Cache('uidl');
-
-        return $this->getIdsOb(
-            $ids->all ? array_values($uids) : array_intersect_keys($uids, $ids->ids)
-        );
-    }
-
</del><span class="cx">     /* Internal functions. */
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Perform a command on the server. A connection to the server must have
</span><span class="cx">      * already been made.
</span><span class="cx">      *
</span><del>-     * @param string $cmd     The command to execute.
</del><ins>+     * @param string $query   The command to execute.
</ins><span class="cx">      * @param array $options  Additional options:
</span><del>-     * <pre>
</del><span class="cx">      *   - debug: (string) When debugging, send this string instead of the
</span><span class="cx">      *            actual command/data sent.
</span><span class="cx">      *            DEFAULT: Raw data output to debug stream.
</span><del>-     *   - multiline: (mixed) 'array', 'none', or 'stream'.
-     * </pre>
-     *
-     * @return array  See _getResponse().
-     *
-     * @throws Horde_Imap_Client_Exception
</del><span class="cx">      */
</span><del>-    protected function _sendLine($cmd, $options = array())
</del><ins>+    protected function _sendLine($query, $options = array())
</ins><span class="cx">     {
</span><del>-        $old_debug = $this->_debug->debug;
-        if (!empty($options['debug'])) {
-            $this->_debug->raw($options['debug'] . "\n");
-            $this->_debug->debug = false;
-        }
</del><ins>+        $this->_debug->client(empty($options['debug']) ? $query : $options['debug']);
</ins><span class="cx"> 
</span><del>-        try {
-            $this->_connection->write($cmd);
-        } catch (Horde_Imap_Client_Exception $e) {
-            $this->_debug->debug = $old_debug;
-            throw $e;
-        }
</del><ins>+        fwrite($this->_stream, $query . "\r\n");
</ins><span class="cx"> 
</span><del>-        $this->_debug->debug = $old_debug;
-
-        return $this->_getResponse(
-            empty($options['multiline']) ? false : $options['multiline']
-        );
</del><ins>+        return $this->_getLine();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Gets a line from the stream and parses it.
</span><span class="cx">      *
</span><del>-     * @param mixed $multiline  'array', 'none', 'stream', or null.
-     *
</del><span class="cx">      * @return array  An array with the following keys:
</span><del>-     *   - data: (mixed) Stream, array, or null.
-     *   - resp: (string) The server response text.
</del><ins>+     *   - line: (string) The server response text.
+     *   - response: (string) Either 'OK', 'END', '+', or ''.
</ins><span class="cx">      *
</span><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      */
</span><del>-    protected function _getResponse($multiline = false)
</del><ins>+    protected function _getLine()
</ins><span class="cx">     {
</span><del>-        $ob = array('resp' => '');
</del><ins>+        $ob = array('line' => '', 'response' => '');
</ins><span class="cx"> 
</span><del>-        $read = explode(' ', rtrim($this->_connection->read(), "\r\n"), 2);
-        if (!in_array($read[0], array('+OK', '-ERR', '+'))) {
-            $this->_debug->info("ERROR: IMAP read/timeout error.");
</del><ins>+        if (feof($this->_stream)) {
+            $this->logout();
</ins><span class="cx">             throw new Horde_Imap_Client_Exception(
</span><del>-                Horde_Imap_Client_Translation::t("Error when communicating with the mail server."),
-                Horde_Imap_Client_Exception::SERVER_READERROR
</del><ins>+                Horde_Imap_Client_Translation::t("POP3 Server closed the connection unexpectedly."),
+                Horde_Imap_Client_Exception::DISCONNECT
</ins><span class="cx">             );
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $respcode = null;
-        if (isset($read[1]) &&
-            isset($this->_init['capability']) &&
-            $this->queryCapability('RESP-CODES')) {
-            $respcode = $this->_parseResponseCode($read[1]);
</del><ins>+        $read = rtrim(fgets($this->_stream));
+        if (empty($read)) {
+            return;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        $this->_debug->server($read);
+
+        $orig_read = $read;
+        $read = explode(' ', $read, 2);
+
</ins><span class="cx">         switch ($read[0]) {
</span><span class="cx">         case '+OK':
</span><del>-        case '+':
-            if ($respcode) {
-                $ob['resp'] = $respcode->text;
-            } elseif (isset($read[1])) {
-                $ob['resp'] = $read[1];
</del><ins>+            $ob['response'] = 'OK';
+            if (isset($read[1])) {
+                if ($this->queryCapability('RESP-CODES')) {
+                    $response = $this->_parseResponseCode($read[1]);
+                    $ob['line'] = $response->text;
+                } else {
+                    $ob['line'] = $read[1];
+                }
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case '-ERR':
</span><span class="cx">             $errcode = 0;
</span><del>-            if ($respcode) {
-                $errtext = $respcode->text;
</del><ins>+            if (isset($read[1])) {
+                if ($this->queryCapability('RESP-CODES')) {
+                    $response = $this->_parseResponseCode($read[1]);
+                    $errtext = $response->text;
</ins><span class="cx"> 
</span><del>-                if (isset($respcode->code)) {
-                    switch ($respcode->code) {
-                    // RFC 2449 [8.1.1]
-                    case 'IN-USE':
-                    // RFC 2449 [8.1.2]
-                    case 'LOGIN-DELAY':
-                        $errcode = Horde_Imap_Client_Exception::LOGIN_UNAVAILABLE;
-                        break;
</del><ins>+                    if (isset($response->code)) {
+                        switch ($response->code) {
+                        // RFC 2449 [8.1.1]
+                        case 'IN-USE':
+                        // RFC 2449 [8.1.2]
+                        case 'LOGIN-DELAY':
+                            $errcode = Horde_Imap_Client_Exception::LOGIN_UNAVAILABLE;
+                            break;
</ins><span class="cx"> 
</span><del>-                    // RFC 3206 [4]
-                    case 'SYS/TEMP':
-                        $errcode = Horde_Imap_Client_Exception::POP3_TEMP_ERROR;
-                        break;
</del><ins>+                        // RFC 3206 [4]
+                        case 'SYS/TEMP':
+                            $errcode = Horde_Imap_Client_Exception::POP3_TEMP_ERROR;
+                            break;
</ins><span class="cx"> 
</span><del>-                    // RFC 3206 [4]
-                    case 'SYS/PERM':
-                        $errcode = Horde_Imap_Client_Exception::POP3_PERM_ERROR;
-                        break;
</del><ins>+                        // RFC 3206 [4]
+                        case 'SYS/PERM':
+                            $errcode = Horde_Imap_Client_Exception::POP3_PERM_ERROR;
+                            break;
</ins><span class="cx"> 
</span><del>-                    // RFC 3206 [5]
-                    case 'AUTH':
-                        $errcode = Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED;
-                        break;
</del><ins>+                        // RFC 3206 [5]
+                        case 'AUTH':
+                            $errcode = Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED;
+                            break;
+                        }
</ins><span class="cx">                     }
</span><ins>+                } else {
+                    $errtext = $read[1];
</ins><span class="cx">                 }
</span><del>-            } elseif (isset($read[1])) {
-                $errtext = $read[1];
</del><span class="cx">             } else {
</span><span class="cx">                 $errtext = '[No error message provided by server]';
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            $e = new Horde_Imap_Client_Exception(
</del><ins>+            throw new Horde_Imap_Client_Exception_ServerResponse(
</ins><span class="cx">                 Horde_Imap_Client_Translation::t("POP3 error reported by server."),
</span><del>-                $errcode
</del><ins>+                $errcode,
+                '-ERR',
+                $errtext
</ins><span class="cx">             );
</span><del>-            $e->details = $errtext;
-            throw $e;
-        }
</del><span class="cx"> 
</span><del>-        switch ($multiline) {
-        case 'array':
-            $ob['data'] = array();
</del><ins>+        case '.':
+            $ob['response'] = 'END';
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><del>-        case 'none':
-            $ob['data'] = null;
</del><ins>+        case '+':
+            $ob['response'] = '+';
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><del>-        case 'stream':
-            $ob['data'] = fopen('php://temp', 'r+');
</del><ins>+        default:
+            $ob['line'] = $orig_read;
</ins><span class="cx">             break;
</span><del>-
-        default:
-            return $ob;
</del><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        return $ob;
+    }
+
+    /**
+     * Obtain multiline input.
+     *
+     * @param boolean $retarray  Return an array?
+     *
+     * @return mixed  An array if $retarray is true, a stream resource
+     *                otherwise.
+     *
+     * @throws Horde_Imap_Client_Exception
+     */
+    protected function _getMultiline($retarray = false)
+    {
+        $data = $retarray
+            ? array()
+            : fopen('php://temp', 'r+');
+
</ins><span class="cx">         do {
</span><del>-            $orig_read = $this->_connection->read();
-            $read = rtrim($orig_read, "\r\n");
</del><ins>+            $line = $this->_getLine();
+            if (empty($line['response'])) {
+                if (substr($line['line'], 0, 2) == '..') {
+                    $line['line'] = substr($line['line'], 1);
+                }
</ins><span class="cx"> 
</span><del>-            if ($read == '.') {
-                break;
-            } elseif (substr($read, 0, 2) == '..') {
-                $read = substr($read, 1);
</del><ins>+                if ($retarray) {
+                    $data[] = $line['line'];
+                } else {
+                    fwrite($data, $line['line'] . "\r\n");
+                }
</ins><span class="cx">             }
</span><ins>+        } while ($line['response'] != 'END');
</ins><span class="cx"> 
</span><del>-            if (is_array($ob['data'])) {
-                $ob['data'][] = $read;
-            } elseif (!is_null($ob['data'])) {
-                fwrite($ob['data'], $orig_read);
-            }
-        } while (true);
-
-        return $ob;
</del><ins>+        return $data;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientSocketphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket.php (2317 => 2318)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket.php  2013-09-16 02:11:45 UTC (rev 2317)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket.php     2013-09-16 02:11:57 UTC (rev 2318)
</span><span class="lines">@@ -61,7 +61,6 @@
</span><span class="cx">  *   - RFC 6154: SPECIAL-USE/CREATE-SPECIAL-USE
</span><span class="cx">  *   - RFC 6203: SEARCH=FUZZY
</span><span class="cx">  *   - RFC 6851: MOVE
</span><del>- *   - RFC 6858: DOWNGRADED response code
</del><span class="cx">  *
</span><span class="cx">  * Implements the following non-RFC extensions:
</span><span class="cx">  * <ul>
</span><span class="lines">@@ -76,11 +75,6 @@
</span><span class="cx">  *    </li>
</span><span class="cx">  *   </ul>
</span><span class="cx">  *  </li>
</span><del>- *  <li>AUTH=XOAUTH2
- *   <ul>
- *    <li>https://developers.google.com/gmail/xoauth2_protocol</li>
- *   </ul>
- *  </li>
</del><span class="cx">  * </ul>
</span><span class="cx">  *
</span><span class="cx">  * TODO (or not necessary?):
</span><span class="lines">@@ -106,8 +100,8 @@
</span><span class="cx">  *  <li>RFC 5267: CONTEXT=SEARCH; CONTEXT=SORT</li>
</span><span class="cx">  *  <li>RFC 5465: NOTIFY</li>
</span><span class="cx">  *  <li>RFC 5466: FILTERS</li>
</span><ins>+ *  <li>RFC 5738: UTF8 (Experimental; Very limited support currently)</li>
</ins><span class="cx">  *  <li>RFC 6237: MULTISEARCH (Experimental)</li>
</span><del>- *  <li>RFC 6855: UTF8
</del><span class="cx">  * </ul>
</span><span class="cx">  *
</span><span class="cx">  * @author    Michael Slusarz <slusarz@horde.org>
</span><span class="lines">@@ -123,20 +117,13 @@
</span><span class="cx">     const CACHE_FLAGS = 'HICflags';
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Queued commands to send to the server.
</del><ins>+     * Fetch cached entries.
</ins><span class="cx">      *
</span><del>-     * @var array
</del><ins>+     * @var Horde_Imap_Client_Fetch_Results
</ins><span class="cx">      */
</span><del>-    protected $_cmdQueue = array();
</del><ins>+    protected $_fetch;
</ins><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * The default ports to use for a connection.
-     *
-     * @var array
-     */
-    protected $_defaultPorts = array(143, 993);
-
-    /**
</del><span class="cx">      * Mapping of status fields to IMAP names.
</span><span class="cx">      *
</span><span class="cx">      * @var array
</span><span class="lines">@@ -155,6 +142,13 @@
</span><span class="cx">     );
</span><span class="cx"> 
</span><span class="cx">     /**
</span><ins>+     * The socket connection to the IMAP server.
+     *
+     * @var resource
+     */
+    protected $_stream = null;
+
+    /**
</ins><span class="cx">      * The unique tag to use when making an IMAP query.
</span><span class="cx">      *
</span><span class="cx">      * @var integer
</span><span class="lines">@@ -170,37 +164,31 @@
</span><span class="cx">      *   - envelope_addrs: (integer) The maximum number of address entries to
</span><span class="cx">      *                     read for FETCH ENVELOPE address fields.
</span><span class="cx">      *                     DEFAULT: 1000
</span><del>-     *   - envelope_string: (integer) The maximum length of string fields
</del><ins>+     *   * envelope_string: (integer) The maximum length of string fields
</ins><span class="cx">      *                      returned by the FETCH ENVELOPE command.
</span><span class="cx">      *                      DEFAULT: 2048
</span><del>-     *   - xoauth2_token: (mixed) If set, will authenticate via the XOAUTH2
-     *                    mechanism (if available) with this token. Either a
-     *                    string (since 2.13.0) or a
-     *                    Horde_Imap_Client_Base_Password object (since
-     *                    2.14.0).
</del><span class="cx">      */
</span><span class="cx">     public function __construct(array $params = array())
</span><span class="cx">     {
</span><del>-        parent::__construct(array_merge(array(
</del><ins>+        $params = array_merge(array(
</ins><span class="cx">             'debug_literal' => false,
</span><span class="cx">             'envelope_addrs' => 1000,
</span><span class="cx">             'envelope_string' => 2048
</span><del>-        ), $params));
</del><ins>+        ), $params);
+
+        parent::__construct($params);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      */
</span><del>-    public function getParam($key)
</del><ins>+    protected function _initOb()
</ins><span class="cx">     {
</span><del>-        switch ($key) {
-        case 'xoauth2_token':
-            if ($this->_params[$key] instanceof Horde_Imap_Client_Base_Password) {
-                return $this->_params[$key]->getPassword();
-            }
-            break;
-        }
</del><ins>+        parent::_initOb();
</ins><span class="cx"> 
</span><del>-        return parent::getParam($key);
</del><ins>+        $this->_fetch = new Horde_Imap_Client_Fetch_Results(
+            $this->_fetchDataClass,
+            Horde_Imap_Client_Fetch_Results::SEQUENCE
+        );
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -214,30 +202,33 @@
</span><span class="cx">         // It is possible the server provided capability information on
</span><span class="cx">         // connect, so check for it now.
</span><span class="cx">         if (!isset($this->_init['capability'])) {
</span><del>-            $this->_sendCmd($this->_command('CAPABILITY'));
</del><ins>+            $this->_sendLine($this->_clientCommand('CAPABILITY'));
</ins><span class="cx">         }
</span><ins>+
+        return isset($this->_init['capability'])
+            ? $this->_init['capability']
+            : array();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Parse a CAPABILITY Response (RFC 3501 [7.2.1]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param array $data  An array of CAPABILITY strings.
</span><span class="cx">      */
</span><del>-    protected function _parseCapability(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        $data
-    )
</del><ins>+    protected function _parseCapability($data)
</ins><span class="cx">     {
</span><span class="cx">         if (!empty($this->_temp['no_cap'])) {
</span><ins>+            unset($this->_temp['no_cap']);
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $pipeline->data['capability_set'] = true;
</del><ins>+        if (empty($this->_temp['in_login'])) {
+            $c = array();
+        } else {
+            $c = $this->_init['capability'];
+            $this->_temp['logincapset'] = true;
+        }
</ins><span class="cx"> 
</span><del>-        $c = array();
-
</del><span class="cx">         foreach ($data as $val) {
</span><span class="cx">             $cap_list = explode('=', $val);
</span><span class="cx">             $cap_list[0] = strtoupper($cap_list[0]);
</span><span class="lines">@@ -271,33 +262,28 @@
</span><span class="cx">     protected function _noop()
</span><span class="cx">     {
</span><span class="cx">         // NOOP doesn't return any specific response
</span><del>-        $this->_sendCmd($this->_command('NOOP'));
</del><ins>+        $this->_sendLine($this->_clientCommand('NOOP'));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      */
</span><span class="cx">     protected function _getNamespaces()
</span><span class="cx">     {
</span><del>-        $data = $this->queryCapability('NAMESPACE')
-            ? $this->_sendCmd($this->_command('NAMESPACE'))->data
-            : array();
</del><ins>+        if (!$this->queryCapability('NAMESPACE')) {
+            return array();
+        }
</ins><span class="cx"> 
</span><del>-        return isset($data['namespace'])
-            ? $data['namespace']
-            : array();
</del><ins>+        $this->_sendLine($this->_clientCommand('NAMESPACE'));
+
+        return $this->_temp['namespace'];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Parse a NAMESPACE response (RFC 2342 [5] & RFC 5255 [3.4]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The NAMESPACE data.
</span><span class="cx">      */
</span><del>-    protected function _parseNamespace(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseNamespace(Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><span class="cx">         $namespace_array = array(
</span><span class="cx">             Horde_Imap_Client::NS_PERSONAL,
</span><span class="lines">@@ -305,6 +291,7 @@
</span><span class="cx">             Horde_Imap_Client::NS_SHARED
</span><span class="cx">         );
</span><span class="cx"> 
</span><ins>+        $c = &$this->_temp['namespace'];
</ins><span class="cx">         $c = array();
</span><span class="cx"> 
</span><span class="cx">         // Per RFC 2342, response from NAMESPACE command is:
</span><span class="lines">@@ -340,8 +327,6 @@
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">         }
</span><del>-
-        $pipeline->data['namespace'] = $c;
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -367,15 +352,14 @@
</span><span class="cx">         $this->_connect();
</span><span class="cx"> 
</span><span class="cx">         $first_login = empty($this->_init['authmethod']);
</span><del>-        $secure = $this->getParam('secure');
</del><ins>+        $t = &$this->_temp;
</ins><span class="cx"> 
</span><span class="cx">         // Switch to secure channel if using TLS.
</span><del>-        if (!$this->isSecureConnection() &&
-            (($secure === 'tls') ||
-             (($secure === true) && $this->queryCapability('LOGINDISABLED')))) {
</del><ins>+        if (!$this->_isSecure &&
+            ($this->_params['secure'] == 'tls')) {
</ins><span class="cx">             if ($first_login && !$this->queryCapability('STARTTLS')) {
</span><del>-                /* We should never hit this - STARTTLS is required pursuant to
-                 * RFC 3501 [6.2.1]. */
</del><ins>+                // We should never hit this - STARTTLS is required pursuant
+                // to RFC 3501 [6.2.1].
</ins><span class="cx">                 throw new Horde_Imap_Client_Exception(
</span><span class="cx">                     Horde_Imap_Client_Translation::t("Server does not support TLS connections."),
</span><span class="cx">                     Horde_Imap_Client_Exception::LOGIN_TLSFAILURE
</span><span class="lines">@@ -384,9 +368,9 @@
</span><span class="cx"> 
</span><span class="cx">             // Switch over to a TLS connection.
</span><span class="cx">             // STARTTLS returns no untagged response.
</span><del>-            $this->_sendCmd($this->_command('STARTTLS'));
</del><ins>+            $this->_sendLine($this->_clientCommand('STARTTLS'));
</ins><span class="cx"> 
</span><del>-            if (!$this->_connection->startTls()) {
</del><ins>+            if (@stream_socket_enable_crypto($this->_stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT) !== true) {
</ins><span class="cx">                 $this->logout();
</span><span class="cx">                 throw new Horde_Imap_Client_Exception(
</span><span class="cx">                     Horde_Imap_Client_Translation::t("Could not open secure TLS connection to the IMAP server."),
</span><span class="lines">@@ -394,8 +378,6 @@
</span><span class="cx">                 );
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            $this->setParam('secure', 'tls');
-
</del><span class="cx">             if ($first_login) {
</span><span class="cx">                 // Expire cached CAPABILITY information (RFC 3501 [6.2.1])
</span><span class="cx">                 $this->_setInit('capability');
</span><span class="lines">@@ -408,106 +390,111 @@
</span><span class="cx">             if (!empty($this->_init['imapproxy'])) {
</span><span class="cx">                 $this->setLanguage();
</span><span class="cx">             }
</span><ins>+
+            $this->_isSecure = true;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if ($first_login) {
</span><del>-            // Add authentication methods.
-            $auth_mech = array();
</del><ins>+            $imap_auth_mech = array();
</ins><span class="cx"> 
</span><del>-            $auth = ($auth = $this->queryCapability('AUTH'))
-                ? array_flip($auth)
-                : array();
</del><ins>+            $auth_methods = $this->queryCapability('AUTH');
+            if (!empty($auth_methods)) {
+                // Add SASL methods. Prefer CRAM-MD5 over DIGEST-MD5, as the
+                // latter has been obsoleted (RFC 6331).
+                $imap_auth_mech = array_intersect(array('CRAM-MD5', 'DIGEST-MD5'), $auth_methods);
</ins><span class="cx"> 
</span><del>-            // XOAUTH2
-            if (isset($auth['XOAUTH2']) && $this->getParam('xoauth2_token')) {
-                $auth_mech[] = 'XOAUTH2';
-                unset($auth['XOAUTH2']);
</del><ins>+                // Next, try 'PLAIN' authentication.
+                if (in_array('PLAIN', $auth_methods)) {
+                    $imap_auth_mech[] = 'PLAIN';
+                }
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            // 'PLAIN' authentication always exists if under TLS. Use it over
-            // all over authentication methods.
-            if ($this->isSecureConnection()) {
-                $auth_mech[] = 'PLAIN';
-                unset($auth['PLAIN']);
-            }
-
-            // Prefer CRAM-MD5 over DIGEST-MD5, as the latter has been
-            // obsoleted (RFC 6331).
-            if (isset($auth['CRAM-MD5'])) {
-                $auth_mech[] = 'CRAM-MD5';
-            } elseif (isset($auth['DIGEST-MD5'])) {
-                $auth_mech[] = 'DIGEST-MD5';
-            }
-            unset($auth['CRAM-MD5'], $auth['DIGEST-MD5']);
-
</del><span class="cx">             // Fall back to 'LOGIN' if available.
</span><del>-            $auth_mech = array_merge($auth_mech, array_keys($auth));
</del><span class="cx">             if (!$this->queryCapability('LOGINDISABLED')) {
</span><del>-                $auth_mech[] = 'LOGIN';
</del><ins>+                $imap_auth_mech[] = 'LOGIN';
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            if (empty($auth_mech)) {
</del><ins>+            if (empty($imap_auth_mech)) {
</ins><span class="cx">                 throw new Horde_Imap_Client_Exception(
</span><span class="cx">                     Horde_Imap_Client_Translation::t("No supported IMAP authentication method could be found."),
</span><span class="cx">                     Horde_Imap_Client_Exception::LOGIN_NOAUTHMETHOD
</span><span class="cx">                 );
</span><span class="cx">             }
</span><ins>+
+            /* Use MD5 authentication first, if available. But no need to use
+             * special authentication if we are already using an encrypted
+             * connection. */
+            if ($this->_isSecure) {
+                $imap_auth_mech = array_reverse($imap_auth_mech);
+            }
</ins><span class="cx">         } else {
</span><del>-            $auth_mech = array($this->_init['authmethod']);
</del><ins>+            $imap_auth_mech = array($this->_init['authmethod']);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $login_err = null;
</del><ins>+        /* Default to AUTHENTICATIONFAILED error (see RFC 5530[3]). */
+        $t['loginerr'] = new Horde_Imap_Client_Exception(
+            Horde_Imap_Client_Translation::t("Mail server denied authentication."),
+            Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED
+        );
</ins><span class="cx"> 
</span><del>-        foreach ($auth_mech as $method) {
</del><ins>+        foreach ($imap_auth_mech as $method) {
+            $t['referral'] = null;
+
+            /* Set a flag indicating whether we have received a CAPABILITY
+             * response after we successfully login. Since capabilities may
+             * be different after login, we need to merge this information into
+             * the current CAPABILITY array (since some servers, e.g. Cyrus,
+             * may not include authentication capabilities that are still
+             * needed in the event this object is eventually serialized). */
+            $t['in_login'] = true;
+
</ins><span class="cx">             try {
</span><del>-                $resp = $this->_tryLogin($method);
-                $data = $resp->data;
</del><ins>+                $this->_tryLogin($method);
+                $success = true;
</ins><span class="cx">                 $this->_setInit('authmethod', $method);
</span><del>-                unset($this->_temp['referralcount']);
-            } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
-                $data = $e->resp_data;
-                if (isset($data['loginerr'])) {
-                    $login_err = $data['loginerr'];
-                }
-                $resp = false;
</del><ins>+                unset($t['referralcount']);
</ins><span class="cx">             } catch (Horde_Imap_Client_Exception $e) {
</span><del>-                $resp = false;
</del><ins>+                $success = false;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><ins>+            unset($t['in_login']);
+
</ins><span class="cx">             // Check for login referral (RFC 2221) response - can happen for
</span><span class="cx">             // an OK, NO, or BYE response.
</span><del>-            if (isset($data['referral'])) {
</del><ins>+            if (!is_null($t['referral'])) {
</ins><span class="cx">                 foreach (array('hostspec', 'port', 'username') as $val) {
</span><del>-                    if (!is_null($data['referral']->$val)) {
-                        $this->setParam($val, $data['referral']->$val);
</del><ins>+                    if (!is_null($t['referral']->$val)) {
+                        $this->_params[$val] = $t['referral']->$val;
</ins><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                if (!is_null($data['referral']->auth)) {
-                    $this->_setInit('authmethod', $data['referral']->auth);
</del><ins>+                if (!is_null($t['referral']->auth)) {
+                    $this->_setInit('authmethod', $t['referral']->auth);
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                if (!isset($this->_temp['referralcount'])) {
-                    $this->_temp['referralcount'] = 0;
</del><ins>+                if (!isset($t['referralcount'])) {
+                    $t['referralcount'] = 0;
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 // RFC 2221 [3] - Don't follow more than 10 levels of referral
</span><span class="cx">                 // without consulting the user.
</span><del>-                if (++$this->_temp['referralcount'] < 10) {
</del><ins>+                if (++$t['referralcount'] < 10) {
</ins><span class="cx">                     $this->logout();
</span><span class="cx">                     $this->_setInit('capability');
</span><span class="cx">                     $this->_setInit('namespace', array());
</span><span class="cx">                     return $this->login();
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                unset($this->_temp['referralcount']);
</del><ins>+                unset($t['referralcount']);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            if ($resp) {
-                return $this->_loginTasks($first_login, $resp->data);
</del><ins>+            if ($success) {
+                return $this->_loginTasks($first_login);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        $ex = $t['loginerr'];
+
</ins><span class="cx">         /* Try again from scratch if authentication failed in an established,
</span><span class="cx">          * previously-authenticated object. */
</span><span class="cx">         if (!empty($this->_init['authmethod'])) {
</span><span class="lines">@@ -517,15 +504,7 @@
</span><span class="cx">             } catch (Horde_Imap_Client_Exception $e) {}
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        /* Default to AUTHENTICATIONFAILED error (see RFC 5530[3]). */
-        if (is_null($login_err)) {
-            throw new Horde_Imap_Client_Exception(
-                Horde_Imap_Client_Translation::t("Mail server denied authentication."),
-                Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED
-            );
-        }
-
-        throw $login_err;
</del><ins>+        throw $ex;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -535,21 +514,53 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _connect()
</span><span class="cx">     {
</span><del>-        if (!is_null($this->_connection)) {
</del><ins>+        if (!is_null($this->_stream)) {
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $this->_connection = new Horde_Imap_Client_Socket_Connection_Socket($this, $this->_debug);
</del><ins>+        if (!empty($this->_params['secure']) && !extension_loaded('openssl')) {
+            throw new InvalidArgumentException('Secure connections require the PHP openssl extension.');
+        }
</ins><span class="cx"> 
</span><ins>+        switch ($this->_params['secure']) {
+        case 'ssl':
+        case 'sslv2':
+        case 'sslv3':
+            $conn = $this->_params['secure'] . '://';
+            $this->_isSecure = true;
+            break;
+
+        case 'tls':
+        default:
+            $conn = 'tcp://';
+            break;
+        }
+
+        $this->_stream = @stream_socket_client($conn . $this->_params['hostspec'] . ':' . $this->_params['port'], $error_number, $error_string, $this->_params['timeout']);
+
+        if ($this->_stream === false) {
+            $this->_stream = null;
+            $this->_isSecure = false;
+            $e = new Horde_Imap_Client_Exception(
+                Horde_Imap_Client_Translation::t("Error connecting to mail server."),
+                Horde_Imap_Client_Exception::SERVER_CONNECT
+            );
+            $e->details = sprintf("[%u] %s", $error_number, $error_string);
+            throw $e;
+        }
+
+        stream_set_timeout($this->_stream, $this->_params['timeout']);
+
</ins><span class="cx">         // If we already have capability information, don't re-set with
</span><del>-        // (possibly) limited information sent in the initial banner.
</del><ins>+        // (possibly) limited information sent in the inital banner.
</ins><span class="cx">         if (isset($this->_init['capability'])) {
</span><span class="cx">             $this->_temp['no_cap'] = true;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        /* Get greeting information (untagged response). */
</del><ins>+        /* Get greeting information.  This is untagged so we need to specially
+         * deal with it here. */
</ins><span class="cx">         try {
</span><del>-            $this->_getLine($this->_pipeline());
</del><ins>+            $this->_getLine();
</ins><span class="cx">         } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
</span><span class="cx">             if ($e->status == Horde_Imap_Client_Interaction_Server::BYE) {
</span><span class="cx">                 /* Server is explicitly rejecting our connection (RFC 3501
</span><span class="lines">@@ -588,103 +599,89 @@
</span><span class="cx">      *
</span><span class="cx">      * @param string $method  IMAP login method.
</span><span class="cx">      *
</span><del>-     * @return Horde_Imap_Client_Interaction_Pipeline  Pipeline object.
-     *
</del><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      */
</span><span class="cx">     protected function _tryLogin($method)
</span><span class="cx">     {
</span><del>-        $username = $this->getParam('username');
-        $password = $this->getParam('password');
-
-        $authenticate_cmd = false;
-
</del><span class="cx">         switch ($method) {
</span><span class="cx">         case 'CRAM-MD5':
</span><span class="cx">         case 'CRAM-SHA1':
</span><span class="cx">         case 'CRAM-SHA256':
</span><span class="cx">             // RFC 2195: CRAM-MD5
</span><span class="cx">             // CRAM-SHA1 & CRAM-SHA256 supported by Courier SASL library
</span><ins>+            $ob = $this->_sendLine(
+                $this->_clientCommand(array('AUTHENTICATE', $method))
+            );
</ins><span class="cx"> 
</span><del>-            // Need $args because PHP 5.3 doesn't allow access to $this in
-            // anonymous functions.
-            $args = array(
-                $username,
-                strtolower(substr($method, 5)),
-                $password
</del><ins>+            $cmd = new Horde_Imap_Client_Data_Format_List(
+                base64_encode($this->_params['username'] . ' ' . hash_hmac(strtolower(substr($method, 5)), base64_decode($ob->token->current()), $this->getParam('password'), false))
</ins><span class="cx">             );
</span><del>-
-            $cmd = $this->_command('AUTHENTICATE')->add(array(
-                $method,
-                new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) use ($args) {
-                    return new Horde_Imap_Client_Data_Format_List(
-                        base64_encode($args[0] . ' ' . hash_hmac($args[1], base64_decode($ob->token->current()), $args[2], false))
-                    );
-                })
</del><ins>+            $this->_sendLine($cmd, array(
+                'debug' => '[' . $method . ' Response]'
</ins><span class="cx">             ));
</span><del>-            $cmd->debug = sprintf('[AUTHENTICATE %s Command - username: %s]', $method, $username);
</del><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'DIGEST-MD5':
</span><span class="cx">             // RFC 2831/4422; obsoleted by RFC 6331
</span><ins>+            $ob = $this->_sendLine(
+                $this->_clientCommand(array('AUTHENTICATE', $method))
+            );
</ins><span class="cx"> 
</span><del>-            // Need $args because PHP 5.3 doesn't allow access to $this in
-            // anonymous functions.
-            $args = array(
-                $username,
-                $password,
-                $this->getParam('hostspec')
</del><ins>+            $cmd = new Horde_Imap_Client_Data_Format_List(
+                base64_encode(new Horde_Imap_Client_Auth_DigestMD5(
+                    $this->_params['username'],
+                    $this->getParam('password'),
+                    base64_decode($ob->token->current()),
+                    $this->_params['hostspec'],
+                    'imap'
+                ))
</ins><span class="cx">             );
</span><ins>+            $ob = $this->_sendLine($cmd, array(
+                'debug' => '[DIGEST-MD5 Response]'
+            ));
</ins><span class="cx"> 
</span><del>-            $cmd = $this->_command('AUTHENTICATE')->add(array(
-                $method,
-                new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) use ($args) {
-                    return new Horde_Imap_Client_Data_Format_List(
-                        base64_encode(new Horde_Imap_Client_Auth_DigestMD5(
-                            $args[0],
-                            $args[1],
-                            base64_decode($ob->token->current()),
-                            $args[2],
-                            'imap'
-                        ))
-                    );
-                }),
-                new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) {
-                    if (strpos(base64_decode($ob->token->current()), 'rspauth=') === false) {
-                        throw new Horde_Imap_Client_Exception(
-                            Horde_Imap_Client_Translation::t("Unexpected response from server when authenticating."),
-                            Horde_Imap_Client_Exception::SERVER_CONNECT
-                        );
-                    }
-
-                    return new Horde_Imap_Client_Data_Format_List();
-                })
-            ));
-            $cmd->debug = sprintf('[AUTHENTICATE DIGEST-MD5 Command - username: %s]', $username);
</del><ins>+            if (strpos(base64_decode($ob->token->current()), 'rspauth=') === false) {
+                throw new Horde_Imap_Client_Exception(
+                    Horde_Imap_Client_Translation::t("Unexpected response from server when authenticating."),
+                    Horde_Imap_Client_Exception::SERVER_CONNECT
+                );
+            }
+            $this->_sendLine(new Horde_Imap_Client_Data_Format_List());
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'LOGIN':
</span><del>-            $cmd = $this->_command('LOGIN')->add(array(
-                new Horde_Imap_Client_Data_Format_Astring($username),
-                new Horde_Imap_Client_Data_Format_Astring($password)
</del><ins>+            $cmd = $this->_clientCommand(array(
+                'LOGIN',
+                new Horde_Imap_Client_Data_Format_Astring($this->_params['username']),
+                new Horde_Imap_Client_Data_Format_Astring($this->getParam('password'))
</ins><span class="cx">             ));
</span><del>-            $cmd->debug = sprintf('[LOGIN Command - username: %s]', $username);
</del><ins>+            $this->_sendLine($cmd, array(
+                'debug' => sprintf('[LOGIN Command - username: %s]', $this->_params['username'])
+            ));
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'PLAIN':
</span><span class="cx">             // RFC 2595/4616 - PLAIN SASL mechanism
</span><del>-            $auth = base64_encode(implode("\0", array(
-                $username,
-                $username,
-                $password
-            )));
-            $authenticate_cmd = true;
-            break;
</del><ins>+            $auth = base64_encode(implode("\0", array($this->_params['username'], $this->_params['username'], $this->getParam('password'))));
+            $cmd = $this->_clientCommand(array(
+                'AUTHENTICATE',
+                'PLAIN'
+            ));
</ins><span class="cx"> 
</span><del>-        case 'XOAUTH2':
-            // Google XOAUTH2
-            $auth = $this->getParam('xoauth2_token');
-            $authenticate_cmd = true;
</del><ins>+            if ($this->queryCapability('SASL-IR')) {
+                // IMAP Extension for SASL Initial Client Response (RFC 4959)
+                $cmd->add($auth);
+                $this->_sendLine($cmd, array(
+                    'debug' => sprintf('[SASL-IR AUTHENTICATE Command - username: %s]', $this->_params['username'])
+                ));
+            } else {
+                $this->_sendLine($cmd);
+
+                $cmd = new Horde_Imap_Client_Data_Format_List($auth);
+                $this->_sendLine($cmd, array(
+                    'debug' => sprintf('[AUTHENTICATE Command - username: %s]', $this->_params['username'])
+                ));
+            }
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         default:
</span><span class="lines">@@ -693,71 +690,35 @@
</span><span class="cx">                 Horde_Imap_Client_Exception::SERVER_CONNECT
</span><span class="cx">             );
</span><span class="cx">         }
</span><del>-
-        if ($authenticate_cmd) {
-            $cmd = $this->_command('AUTHENTICATE')->add($method);
-
-            if ($this->queryCapability('SASL-IR')) {
-                // IMAP Extension for SASL Initial Client Response (RFC 4959)
-                $cmd->add($auth);
-                $cmd->debug = sprintf('[SASL-IR AUTHENTICATE Command - method: %s, username: %s]', $method, $username);
-            } else {
-                $cmd->add(new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) use ($auth) {
-                    return new Horde_Imap_Client_Data_Format_List($auth);
-                }));
-                $cmd->debug = sprintf('[AUTHENTICATE Command - method: %s, username: %s]', $method, $username);
-            }
-
-            /* This is an optional command continuation. E.g. XOAUTH2 will
-             * return error information in continuation response. */
-            $error_continuation = new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) {
-                return new Horde_Imap_Client_Data_Format_List();
-            });
-            $error_continuation->optional = true;
-            $cmd->add($error_continuation);
-        }
-
-        return $this->_sendCmd($this->_pipeline($cmd));
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Perform login tasks.
</span><span class="cx">      *
</span><span class="cx">      * @param boolean $firstlogin  Is this the first login?
</span><del>-     * @param array $resp          The data response from the login command.
-     *                             May include:
-     *   - capability_set: (boolean) True if CAPABILITY was set after login.
-     *   - proxyreuse: (boolean) True if re-used connection via imapproxy.
</del><span class="cx">      *
</span><span class="cx">      * @return boolean  True if global login tasks should be performed.
</span><span class="cx">      */
</span><del>-    protected function _loginTasks($firstlogin = true, array $resp = array())
</del><ins>+    protected function _loginTasks($firstlogin = true)
</ins><span class="cx">     {
</span><span class="cx">         /* If reusing an imapproxy connection, no need to do any of these
</span><span class="cx">          * login tasks again. */
</span><del>-        if (!$firstlogin && !empty($resp['proxyreuse'])) {
-            if (isset($this->_init['enabled'])) {
-                $this->_temp['enabled'] = $this->_init['enabled'];
-            }
-
</del><ins>+        if (!$firstlogin && !empty($this->_temp['proxyreuse'])) {
</ins><span class="cx">             // If we have not yet set the language, set it now.
</span><span class="cx">             if (!isset($this->_init['lang'])) {
</span><del>-                $this->_temp['lang_queue'] = true;
</del><span class="cx">                 $this->setLanguage();
</span><del>-                unset($this->_temp['lang_queue']);
</del><span class="cx">             }
</span><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        $this->_setInit('enabled', array());
+
</ins><span class="cx">         /* If we logged in for first time, and server did not return
</span><del>-         * capability information, we need to mark for retrieval. */
-        if ($firstlogin && empty($resp['capability_set'])) {
</del><ins>+         * capability information, we need to grab it now. */
+        if ($firstlogin && empty($this->_temp['logincapset'])) {
</ins><span class="cx">             $this->_setInit('capability');
</span><span class="cx">         }
</span><del>-
-        $this->_temp['lang_queue'] = true;
</del><span class="cx">         $this->setLanguage();
</span><del>-        unset($this->_temp['lang_queue']);
</del><span class="cx"> 
</span><span class="cx">         /* Only active QRESYNC/CONDSTORE if caching is enabled. */
</span><span class="cx">         if ($this->_initCache()) {
</span><span class="lines">@@ -775,30 +736,28 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _logout()
</span><span class="cx">     {
</span><del>-        if (empty($this->_temp['logout'])) {
-            /* If using imapproxy, force sending these commands, since they
-             * may not be sent again if they are (likely) initialization
-             * commands. */
-            if (!empty($this->_cmdQueue) &&
-                !empty($this->_init['imapproxy'])) {
-                $this->_sendCmd($this->_pipeline());
</del><ins>+        if (!is_null($this->_stream)) {
+            if (empty($this->_temp['logout'])) {
+                $this->_temp['logout'] = true;
+                try {
+                    $this->_sendLine($this->_clientCommand('LOGOUT'));
+                } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
+                    // Ignore server errors
+                }
</ins><span class="cx">             }
</span><del>-
-            $this->_temp['logout'] = true;
-            try {
-                $this->_sendCmd($this->_command('LOGOUT'));
-            } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
-                // Ignore server errors
-            }
</del><span class="cx">             unset($this->_temp['logout']);
</span><ins>+            @fclose($this->_stream);
+            $this->_stream = null;
</ins><span class="cx">         }
</span><ins>+
+        unset($this->_temp['proxyreuse']);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      */
</span><span class="cx">     protected function _sendID($info)
</span><span class="cx">     {
</span><del>-        $cmd = $this->_command('ID');
</del><ins>+        $cmd = $this->_clientCommand('ID');
</ins><span class="cx"> 
</span><span class="cx">         if (empty($info)) {
</span><span class="cx">             $cmd->add(new Horde_Imap_Client_Data_Format_Nil());
</span><span class="lines">@@ -813,32 +772,25 @@
</span><span class="cx">             $cmd->add($tmp);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $this->_temp['id'] = $this->_sendCmd($cmd)->data['id'];
</del><ins>+        $this->_sendLine($cmd);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Parse an ID response (RFC 2971 [3.2]).
</del><ins>+     * Parse an ID response (RFC 2971 [3.2])
</ins><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The server response.
</span><span class="cx">      */
</span><del>-    protected function _parseID(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseID(Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><del>-        $ids = array();
</del><ins>+        $this->_temp['id'] = array();
</ins><span class="cx"> 
</span><span class="cx">         if (!is_null($data->next())) {
</span><span class="cx">             while (($curr = $data->next()) !== false) {
</span><span class="cx">                 if (!is_null($id = $data->next())) {
</span><del>-                    $ids[$curr] = $id;
</del><ins>+                    $this->_temp['id'][$curr] = $id;
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">         }
</span><del>-
-        $pipeline->data['id'] = $ids;
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -848,7 +800,6 @@
</span><span class="cx">         if (!isset($this->_temp['id'])) {
</span><span class="cx">             $this->sendID();
</span><span class="cx">         }
</span><del>-
</del><span class="cx">         return $this->_temp['id'];
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -856,18 +807,13 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _setLanguage($langs)
</span><span class="cx">     {
</span><del>-        $cmd = $this->_command('LANGUAGE');
</del><ins>+        $cmd = $this->_clientCommand('LANGUAGE');
</ins><span class="cx">         foreach ($langs as $lang) {
</span><span class="cx">             $cmd->add(new Horde_Imap_Client_Data_Format_Astring($lang));
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!empty($this->_temp['lang_queue'])) {
-            $this->_cmdQueue[] = $cmd;
-            return array();
-        }
-
</del><span class="cx">         try {
</span><del>-            $this->_sendCmd($cmd);
</del><ins>+            $this->_sendLine($cmd);
</ins><span class="cx">         } catch (Horde_Imap_Client_Exception $e) {
</span><span class="cx">             $this->_setInit('lang', false);
</span><span class="cx">             return null;
</span><span class="lines">@@ -888,7 +834,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (!isset($this->_init['langavail'])) {
</span><span class="cx">             try {
</span><del>-                $this->_sendCmd($this->_command('LANGUAGE'));
</del><ins>+                $this->_sendLine($this->_clientCommand('LANGUAGE'));
</ins><span class="cx">             } catch (Horde_Imap_Client_Exception $e) {
</span><span class="cx">                 $this->_setInit('langavail', array());
</span><span class="cx">             }
</span><span class="lines">@@ -925,11 +871,14 @@
</span><span class="cx">     protected function _enable($exts)
</span><span class="cx">     {
</span><span class="cx">         if ($this->queryCapability('ENABLE')) {
</span><del>-            // Only enable non-enabled extensions.
-            $exts = array_diff($exts, array_keys($this->_temp['enabled']));
</del><ins>+            // Only enable non-enabled extensions
+            $exts = array_diff($exts, array_keys($this->_init['enabled']));
</ins><span class="cx">             if (!empty($exts)) {
</span><del>-                $this->_cmdQueue[] = $this->_command('ENABLE')->add($exts);
-                $this->_enabled($exts, 1);
</del><ins>+                $cmd = $this->_clientCommand(array(
+                    'ENABLE',
+                    $exts
+                ));
+                $this->_sendLine($cmd);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -941,32 +890,22 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _parseEnabled(Horde_Imap_Client_Tokenize $data)
</span><span class="cx">     {
</span><del>-        $this->_enabled($data->flushIterator(), 2);
</del><ins>+        $this->_setInit('enabled', array_merge(
+            $this->_init['enabled'],
+            array_flip($data->flushIterator())
+        ));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      */
</span><del>-    protected function _enabled($exts, $status)
-    {
-        parent::_enabled($exts, $status);
-
-        if (($status == 2) && !empty($this->_init['imapproxy'])) {
-            $this->_setInit('enabled', $this->_temp['enabled']);
-        }
-    }
-
-    /**
-     */
</del><span class="cx">     protected function _openMailbox(Horde_Imap_Client_Mailbox $mailbox, $mode)
</span><span class="cx">     {
</span><del>-        $qresync = isset($this->_temp['enabled']['QRESYNC']);
</del><ins>+        $qresync = isset($this->_init['enabled']['QRESYNC']);
</ins><span class="cx"> 
</span><del>-        $cmd = $this->_command(
-            ($mode == Horde_Imap_Client::OPEN_READONLY) ? 'EXAMINE' : 'SELECT'
-        )->add(
</del><ins>+        $cmd = $this->_clientCommand(array(
+            ($mode == Horde_Imap_Client::OPEN_READONLY) ? 'EXAMINE' : 'SELECT',
</ins><span class="cx">             new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
</span><del>-        );
-        $pipeline = $this->_pipeline($cmd);
</del><ins>+        ));
</ins><span class="cx"> 
</span><span class="cx">         /* If QRESYNC is available, synchronize the mailbox. */
</span><span class="cx">         if ($qresync) {
</span><span class="lines">@@ -1011,24 +950,27 @@
</span><span class="cx">             /* Let the 'CLOSED' response code handle mailbox switching if
</span><span class="cx">              * QRESYNC is active. */
</span><span class="cx">             if ($this->_selected) {
</span><del>-                $pipeline->data['qresyncmbox'] = array($mailbox, $mode);
</del><ins>+                $this->_temp['qresyncmbox'] = array($mailbox, $mode);
</ins><span class="cx">             } else {
</span><span class="cx">                 $this->_changeSelected($mailbox, $mode);
</span><span class="cx">             }
</span><span class="cx">         } else {
</span><del>-            if (!isset($this->_temp['enabled']['CONDSTORE']) &&
</del><ins>+            if (!isset($this->_init['enabled']['CONDSTORE']) &&
</ins><span class="cx">                 $this->_initCache() &&
</span><span class="cx">                 $this->queryCapability('CONDSTORE')) {
</span><span class="cx">                 /* Activate CONDSTORE now if ENABLE is not available. */
</span><span class="cx">                 $cmd->add(new Horde_Imap_Client_Data_Format_List('CONDSTORE'));
</span><del>-                $this->_enabled(array('CONDSTORE'), 2);
</del><ins>+                $this->_setInit('enabled', array_merge(
+                    $this->_init['enabled'],
+                    array('CONDSTORE' => true)
+                ));
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             $this->_changeSelected($mailbox, $mode);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         try {
</span><del>-            $this->_sendCmd($pipeline);
</del><ins>+            $this->_sendLine($cmd);
</ins><span class="cx">         } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
</span><span class="cx">             // An EXAMINE/SELECT failure with a return of 'NO' will cause the
</span><span class="cx">             // current mailbox to be unselected.
</span><span class="lines">@@ -1055,9 +997,10 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _createMailbox(Horde_Imap_Client_Mailbox $mailbox, $opts)
</span><span class="cx">     {
</span><del>-        $cmd = $this->_command('CREATE')->add(
</del><ins>+        $cmd = $this->_clientCommand(array(
+            'CREATE',
</ins><span class="cx">             new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
</span><del>-        );
</del><ins>+        ));
</ins><span class="cx"> 
</span><span class="cx">         if (!empty($opts['special_use'])) {
</span><span class="cx">             $cmd->add(array(
</span><span class="lines">@@ -1067,7 +1010,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // CREATE returns no untagged information (RFC 3501 [6.3.3])
</span><del>-        $this->_sendCmd($cmd);
</del><ins>+        $this->_sendLine($cmd);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -1080,21 +1023,29 @@
</span><span class="cx">             $this->close();
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $cmd = $this->_command('DELETE')->add(
-            new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
-        );
-
</del><span class="cx">         try {
</span><span class="cx">             // DELETE returns no untagged information (RFC 3501 [6.3.4])
</span><del>-            $this->_sendCmd($cmd);
</del><ins>+            $cmd = $this->_clientCommand(array(
+                'DELETE',
+                new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
+            ));
+            $this->_sendLine($cmd);
</ins><span class="cx">         } catch (Horde_Imap_Client_Exception $e) {
</span><span class="cx">             // Some IMAP servers won't allow a mailbox delete unless all
</span><span class="cx">             // messages in that mailbox are deleted.
</span><del>-            $this->expunge($mailbox, array(
-                'delete' => true
-            ));
-            $this->_sendCmd($cmd);
</del><ins>+            if (!empty($this->_temp['deleteretry'])) {
+                unset($this->_temp['deleteretry']);
+                throw $e;
+            }
+
+            $this->store($mailbox, array('add' => array(Horde_Imap_Client::FLAG_DELETED)));
+            $this->expunge($mailbox);
+
+            $this->_temp['deleteretry'] = true;
+            $this->deleteMailbox($mailbox);
</ins><span class="cx">         }
</span><ins>+
+        unset($this->_temp['deleteretry']);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -1109,12 +1060,12 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // RENAME returns no untagged information (RFC 3501 [6.3.5])
</span><del>-        $this->_sendCmd(
-            $this->_command('RENAME')->add(array(
-                new Horde_Imap_Client_Data_Format_Mailbox($old),
-                new Horde_Imap_Client_Data_Format_Mailbox($new)
-            ))
-        );
</del><ins>+        $cmd = $this->_clientCommand(array(
+            'RENAME',
+            new Horde_Imap_Client_Data_Format_Mailbox($old),
+            new Horde_Imap_Client_Data_Format_Mailbox($new)
+        ));
+        $this->_sendLine($cmd);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -1124,13 +1075,11 @@
</span><span class="cx">     {
</span><span class="cx">         // SUBSCRIBE/UNSUBSCRIBE returns no untagged information (RFC 3501
</span><span class="cx">         // [6.3.6 & 6.3.7])
</span><del>-        $this->_sendCmd(
-            $this->_command(
-                $subscribe ? 'SUBSCRIBE' : 'UNSUBSCRIBE'
-            )->add(
-                new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
-            )
-        );
</del><ins>+        $cmd = $this->_clientCommand(array(
+            $subscribe ? 'SUBSCRIBE' : 'UNSUBSCRIBE',
+            new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
+        ));
+        $this->_sendLine($cmd);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -1195,24 +1144,22 @@
</span><span class="cx">     {
</span><span class="cx">         $check = (($mode != Horde_Imap_Client::MBOX_ALL) && !is_null($subscribed));
</span><span class="cx"> 
</span><del>-        // Setup entry for use in _parseList().
-        $pipeline = $this->_pipeline();
-        $pipeline->data['mailboxlist'] = array(
</del><ins>+        // Setup cache entry for use in _parseList()
+        $t = &$this->_temp;
+        $t['mailboxlist'] = array(
</ins><span class="cx">             'check' => $check,
</span><span class="cx">             'ext' => false,
</span><span class="cx">             'options' => $options,
</span><span class="cx">             'subexist' => ($mode == Horde_Imap_Client::MBOX_SUBSCRIBED_EXISTS),
</span><span class="cx">             'subscribed' => ($check ? array_flip(array_map('strval', $subscribed)) : null)
</span><span class="cx">         );
</span><del>-        $pipeline->data['listresponse'] = array();
-
-        $cmds = array();
</del><ins>+        $t['listresponse'] = array();
</ins><span class="cx">         $return_opts = new Horde_Imap_Client_Data_Format_List();
</span><span class="cx"> 
</span><span class="cx">         if ($this->queryCapability('LIST-EXTENDED') &&
</span><span class="cx">             empty($options['no_listext'])) {
</span><del>-            $cmd = $this->_command('LIST');
-            $pipeline->data['mailboxlist']['ext'] = true;
</del><ins>+            $cmd = $this->_clientCommand('LIST');
+            $t['mailboxlist']['ext'] = true;
</ins><span class="cx"> 
</span><span class="cx">             $select_opts = new Horde_Imap_Client_Data_Format_List();
</span><span class="cx"> 
</span><span class="lines">@@ -1248,17 +1195,18 @@
</span><span class="cx">             if (!empty($options['special_use'])) {
</span><span class="cx">                 $return_opts->add('SPECIAL-USE');
</span><span class="cx">             }
</span><del>-
-            $cmds[] = $cmd;
-        } else {
</del><ins>+        } elseif (count($pattern) > 1) {
+            $return_array = array();
</ins><span class="cx">             foreach ($pattern as $val) {
</span><del>-                $cmds[] = $this->_command(
-                    ($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) ? 'LSUB' : 'LIST'
-                )->add(array(
-                    '',
-                    new Horde_Imap_Client_Data_Format_ListMailbox($val)
-                ));
</del><ins>+                $return_array = array_merge($return_array, $this->_getMailboxList(array($val), $mode, $options, $subscribed));
</ins><span class="cx">             }
</span><ins>+            return $return_array;
+        } else {
+            $cmd = $this->_clientCommand(array(
+                ($mode == Horde_Imap_Client::MBOX_SUBSCRIBED) ? 'LSUB' : 'LIST',
+                '',
+                new Horde_Imap_Client_Data_Format_ListMailbox(reset($pattern))
+            ));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         /* LIST-STATUS does NOT depend on LIST-EXTENDED. */
</span><span class="lines">@@ -1290,19 +1238,15 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        foreach ($cmds as $val) {
-            if (count($return_opts)) {
-                $val->add(array(
-                    'RETURN',
-                    $return_opts
-                ));
-            }
-
-            $pipeline->add($val);
</del><ins>+        if (count($return_opts)) {
+            $cmd->add(array(
+                'RETURN',
+                $return_opts
+            ));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         try {
</span><del>-            $lr = $this->_sendCmd($pipeline)->data['listresponse'];
</del><ins>+            $this->_sendLine($cmd);
</ins><span class="cx">         } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
</span><span class="cx">             /* Archiveopteryx 3.1.3 can't process empty list-select-opts list.
</span><span class="cx">              * Retry using base IMAP4rev1 functionality. */
</span><span class="lines">@@ -1316,42 +1260,43 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (!empty($options['flat'])) {
</span><del>-            return array_values($lr);
</del><ins>+            return array_values($t['listresponse']);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         /* Add in STATUS return, if needed. */
</span><span class="cx">         if (!empty($options['status'])) {
</span><span class="cx">             foreach ($pattern as $val) {
</span><span class="cx">                 $val_utf8 = Horde_Imap_Client_Utf7imap::Utf7ImapToUtf8($val);
</span><del>-                if (isset($lr[$val_utf8])) {
-                    $lr[$val_utf8]['status'] = $this->_prepareStatusResponse($status_opts, $val_utf8);
</del><ins>+                if (isset($t['listresponse'][$val_utf8])) {
+                    $t['listresponse'][$val_utf8]['status'] = $this->_prepareStatusResponse($status_opts, $val_utf8);
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return $lr;
</del><ins>+        $out = $t['listresponse'];
+        unset($t['listresponse']);
+
+        return $out;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Parse a LIST/LSUB response (RFC 3501 [7.2.2 & 7.2.3]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The server response (includes
</span><span class="cx">      *                                          type as first token).
</span><span class="cx">      *
</span><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      */
</span><del>-    protected function _parseList(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseList(Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><ins>+        $ml = $this->_temp['mailboxlist'];
+        $mlo = $ml['options'];
+        $lr = &$this->_temp['listresponse'];
+
</ins><span class="cx">         $data->next();
</span><span class="cx">         $attr = $data->flushIterator();
</span><span class="cx">         $delimiter = $data->next();
</span><span class="cx">         $mbox = Horde_Imap_Client_Mailbox::get($data->next(), true);
</span><del>-        $ml = $pipeline->data['mailboxlist'];
</del><span class="cx"> 
</span><span class="cx">         if ($ml['check'] &&
</span><span class="cx">             $ml['subexist'] &&
</span><span class="lines">@@ -1359,8 +1304,7 @@
</span><span class="cx">             !isset($ml['subscribed'][strval($mbox)])) {
</span><span class="cx">             return;
</span><span class="cx">         } elseif ((!$ml['check'] && $ml['subexist']) ||
</span><del>-                   (empty($ml['options']['flat']) &&
-                    !empty($ml['options']['attributes']))) {
</del><ins>+                  (empty($mlo['flat']) && !empty($mlo['attributes']))) {
</ins><span class="cx">             $attr = array_flip(array_map('strtolower', $attr));
</span><span class="cx">             if ($ml['subexist'] &&
</span><span class="cx">                 !$ml['check'] &&
</span><span class="lines">@@ -1369,12 +1313,12 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (empty($ml['options']['flat'])) {
</del><ins>+        if (empty($mlo['flat'])) {
</ins><span class="cx">             $tmp = array(
</span><span class="cx">                 'mailbox' => $mbox
</span><span class="cx">             );
</span><span class="cx"> 
</span><del>-            if (!empty($ml['options']['attributes'])) {
</del><ins>+            if (!empty($mlo['attributes'])) {
</ins><span class="cx">                 /* RFC 5258 [3.4]: inferred attributes. */
</span><span class="cx">                 if ($ml['ext']) {
</span><span class="cx">                     if (isset($attr['\\noinferiors'])) {
</span><span class="lines">@@ -1386,127 +1330,118 @@
</span><span class="cx">                 }
</span><span class="cx">                 $tmp['attributes'] = array_keys($attr);
</span><span class="cx">             }
</span><del>-            if (!empty($ml['options']['delimiter'])) {
</del><ins>+            if (!empty($mlo['delimiter'])) {
</ins><span class="cx">                 $tmp['delimiter'] = $delimiter;
</span><span class="cx">             }
</span><span class="cx">             if ($data->next() !== false) {
</span><span class="cx">                 $tmp['extended'] = $data->flushIterator();
</span><span class="cx">             }
</span><del>-            $pipeline->data['listresponse'][strval($mbox)] = $tmp;
</del><ins>+            $lr[strval($mbox)] = $tmp;
</ins><span class="cx">         } else {
</span><del>-            $pipeline->data['listresponse'][] = $mbox;
</del><ins>+            $lr[] = $mbox;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      */
</span><del>-    protected function _status($mboxes, $flags)
</del><ins>+    protected function _status(Horde_Imap_Client_Mailbox $mailbox, $flags)
</ins><span class="cx">     {
</span><del>-        $out = $to_process = array();
-        $pipeline = $this->_pipeline();
</del><ins>+        $data = $query = array();
</ins><span class="cx">         $unseen_flags = array(
</span><span class="cx">             Horde_Imap_Client::STATUS_FIRSTUNSEEN,
</span><span class="cx">             Horde_Imap_Client::STATUS_UNSEEN
</span><span class="cx">         );
</span><span class="cx"> 
</span><del>-        foreach ($mboxes as $mailbox) {
-            /* 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 & 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);
</del><ins>+        /* 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 & 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);
+        }
+
+        $mbox_ob = $this->_mailboxOb($mailbox);
+
+        foreach ($this->_statusFields as $key => $val) {
+            if (!($val & $flags)) {
+                continue;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            $mbox_ob = $this->_mailboxOb($mailbox);
-            $data = $query = array();
-
-            foreach ($this->_statusFields as $key => $val) {
-                if (!($val & $flags)) {
</del><ins>+            if ($val == Horde_Imap_Client::STATUS_HIGHESTMODSEQ) {
+                /* Don't include modseq returns if server does not support
+                 * it. */
+                if (!$this->queryCapability('CONDSTORE')) {
</ins><span class="cx">                     continue;
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                if ($val == Horde_Imap_Client::STATUS_HIGHESTMODSEQ) {
-                    /* Don't include modseq returns if server does not support
-                     * it. */
-                    if (!$this->queryCapability('CONDSTORE')) {
-                        continue;
-                    }
-
-                    /* Even though CONDSTORE is available, it may not yet have
-                     * been enabled. */
-                    if (!isset($this->_temp['enabled']['CONDSTORE'])) {
-                        $this->_enabled(array('CONDSTORE'), 2);
-                    }
</del><ins>+                /* Even though CONDSTORE is available, it may not yet have
+                 * been enabled. */
+                if (!isset($this->_init['enabled']['CONDSTORE'])) {
+                    $this->_setInit('enabled', array_merge(
+                        $this->_init['enabled'],
+                        array('CONDSTORE' => true)
+                    ));
</ins><span class="cx">                 }
</span><ins>+            }
</ins><span class="cx"> 
</span><del>-                if ($mailbox->equals($this->_selected)) {
-                    if (!is_null($tmp = $mbox_ob->getStatus($val))) {
-                        $data[$key] = $tmp;
-                    } elseif (($val == Horde_Imap_Client::STATUS_UIDNEXT) &&
-                              ($flags & Horde_Imap_Client::STATUS_UIDNEXT_FORCE)) {
-                        /* UIDNEXT is not mandatory. */
-                        if ($mbox_ob->getStatus(Horde_Imap_Client::STATUS_MESSAGES) == 0) {
-                            $data[$key] = 0;
-                        } else {
-                            $fquery = new Horde_Imap_Client_Fetch_Query();
-                            $fquery->uid();
-                            $fetch_res = $this->fetch($this->_selected, $fquery, array(
-                                'ids' => $this->getIdsOb(Horde_Imap_Client_Ids::LARGEST)
-                            ));
-                            $data[$key] = $fetch_res->first()->getUid() + 1;
-                        }
-                    } elseif (in_array($val, $unseen_flags)) {
-                        /* RFC 3501 [6.3.1] - FIRSTUNSEEN information is not
-                         * mandatory. If missing in EXAMINE/SELECT results, we
-                         * need to do a search. An UNSEEN count also requires
-                         * a search. */
-                        $squery = new Horde_Imap_Client_Search_Query();
-                        $squery->flag(Horde_Imap_Client::FLAG_SEEN, false);
-                        $search = $this->search($mailbox, $squery, array(
-                            'results' => array(
-                                Horde_Imap_Client::SEARCH_RESULTS_MIN,
-                                Horde_Imap_Client::SEARCH_RESULTS_COUNT
-                            ),
-                            'sequence' => true
</del><ins>+            if ($mailbox->equals($this->_selected)) {
+                if (!is_null($tmp = $mbox_ob->getStatus($val))) {
+                    $data[$key] = $tmp;
+                } elseif (($val == Horde_Imap_Client::STATUS_UIDNEXT) &&
+                          ($flags & Horde_Imap_Client::STATUS_UIDNEXT_FORCE)) {
+                    /* UIDNEXT is not mandatory. */
+                    if ($mbox_ob->getStatus(Horde_Imap_Client::STATUS_MESSAGES) == 0) {
+                        $data[$key] = 0;
+                    } else {
+                        $fquery = new Horde_Imap_Client_Fetch_Query();
+                        $fquery->uid();
+                        $fetch_res = $this->fetch($this->_selected, $fquery, array(
+                            'ids' => $this->getIdsOb(Horde_Imap_Client_Ids::LARGEST)
</ins><span class="cx">                         ));
</span><ins>+                        $data[$key] = $fetch_res->first()->getUid() + 1;
+                    }
+                } elseif (in_array($val, $unseen_flags)) {
+                    /* RFC 3501 [6.3.1] - FIRSTUNSEEN information is not
+                     * mandatory. If missing in EXAMINE/SELECT results, we
+                     * need to do a search. An UNSEEN count also requires a
+                     * search. */
+                    $squery = new Horde_Imap_Client_Search_Query();
+                    $squery->flag(Horde_Imap_Client::FLAG_SEEN, false);
+                    $search = $this->search($mailbox, $squery, array(
+                        'results' => array(
+                            Horde_Imap_Client::SEARCH_RESULTS_MIN,
+                            Horde_Imap_Client::SEARCH_RESULTS_COUNT
+                        ),
+                        'sequence' => true
+                    ));
</ins><span class="cx"> 
</span><del>-                        $mbox_ob->setStatus(Horde_Imap_Client::STATUS_FIRSTUNSEEN, $search['min']);
-                        $mbox_ob->setStatus(Horde_Imap_Client::STATUS_UNSEEN, $search['count']);
</del><ins>+                    $mbox_ob->setStatus(Horde_Imap_Client::STATUS_FIRSTUNSEEN, $search['min']);
+                    $mbox_ob->setStatus(Horde_Imap_Client::STATUS_UNSEEN, $search['count']);
</ins><span class="cx"> 
</span><del>-                        $data[$key] = $mbox_ob->getStatus($val);
-                    }
-                } else {
-                    $query[] = $key;
</del><ins>+                    $data[$key] = $mbox_ob->getStatus($val);
</ins><span class="cx">                 }
</span><ins>+            } else {
+                $query[] = $key;
</ins><span class="cx">             }
</span><ins>+        }
</ins><span class="cx"> 
</span><del>-            $out[strval($mailbox)] = $data;
-
-            if (count($query)) {
-                $pipeline->add(
-                    $this->_command('STATUS')->add(array(
-                        new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
-                        new Horde_Imap_Client_Data_Format_List(
-                            array_map('strtoupper', $query)
-                        )
-                    ))
-                );
-                $to_process[] = array($query, $mailbox);
-            }
</del><ins>+        if (!count($query)) {
+            return $data;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (count($pipeline)) {
-            $this->_sendCmd($pipeline);
</del><ins>+        $cmd = $this->_clientCommand(array(
+            'STATUS',
+            new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
+            new Horde_Imap_Client_Data_Format_List(
+                array_map('strtoupper', $query)
+            )
+        ));
</ins><span class="cx"> 
</span><del>-            foreach ($to_process as $val) {
-                $out[strval($val[1])] += $this->_prepareStatusResponse($val[0], $val[1]);
-            }
-        }
</del><ins>+        $this->_sendLine($cmd);
</ins><span class="cx"> 
</span><del>-        return $out;
</del><ins>+        return $this->_prepareStatusResponse($query, $mailbox);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -1571,12 +1506,15 @@
</span><span class="cx">         // Check for CATENATE extension (RFC 4469)
</span><span class="cx">         $catenate = $this->queryCapability('CATENATE');
</span><span class="cx"> 
</span><del>-        $asize = 0;
</del><ins>+        $t = &$this->_temp;
+        $t['appendsize'] = 0;
+        $t['appenduid'] = true;
+        $t['trycreate'] = null;
</ins><span class="cx"> 
</span><del>-        $cmd = $this->_command('APPEND')->add(
</del><ins>+        $cmd = $this->_clientCommand(array(
+            'APPEND',
</ins><span class="cx">             new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
</span><del>-        );
-        $cmd->literal8 = true;
</del><ins>+        ));
</ins><span class="cx"> 
</span><span class="cx">         foreach (array_keys($data) as $key) {
</span><span class="cx">             if (!empty($data[$key]['flags'])) {
</span><span class="lines">@@ -1609,7 +1547,7 @@
</span><span class="cx">                         if ($catenate) {
</span><span class="cx">                             $tmp->add(array(
</span><span class="cx">                                 'TEXT',
</span><del>-                                $this->_appendData($v['v'], $asize)
</del><ins>+                                $this->_appendData($v['v'])
</ins><span class="cx">                             ));
</span><span class="cx">                         } else {
</span><span class="cx">                             if (is_resource($v['v'])) {
</span><span class="lines">@@ -1635,21 +1573,23 @@
</span><span class="cx">                 if ($catenate) {
</span><span class="cx">                     $cmd->add($tmp);
</span><span class="cx">                 } else {
</span><del>-                    $cmd->add($this->_appendData($data_stream->stream, $asize));
</del><ins>+                    $cmd->add($this->_appendData($data_stream->stream));
</ins><span class="cx">                 }
</span><span class="cx">             } else {
</span><del>-                $cmd->add($this->_appendData($data[$key]['data'], $asize));
</del><ins>+                $cmd->add($this->_appendData($data[$key]['data']));
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         /* Although it is normally more efficient to use LITERAL+, disable if
</span><span class="cx">          * payload is over 0.5 MB because it allows the server to throw error
</span><span class="cx">          * before we potentially push a lot of data to server that would
</span><del>-         * otherwise be ignored (see RFC 4549 [4.2.2.3]).
-         * Additionally, if using BINARY, since so many IMAP servers have
-         * issues with APPEND + BINARY, don't use LITERAL+ since servers may
-         * send BAD after initial command. */
-        $cmd->literalplus = (($asize < 524288) && !$this->queryCapability('BINARY'));
</del><ins>+         * otherwise be ignored (see RFC 4549 [4.2.2.3]). */
+        if (!($noliteralplus = ($this->_temp['appendsize'] > 524288))) {
+            /* Additionally, if using BINARY, since so many IMAP servers have
+             * issues with APPEND + BINARY, don't use LITERAL+ since servers
+             * may send BAD after initial command. */
+            $noliteralplus = $this->queryCapability('BINARY');
+        }
</ins><span class="cx"> 
</span><span class="cx">         // If the mailbox is currently selected read-only, we need to close
</span><span class="cx">         // because some IMAP implementations won't allow an append. And some
</span><span class="lines">@@ -1658,7 +1598,9 @@
</span><span class="cx">         $this->close();
</span><span class="cx"> 
</span><span class="cx">         try {
</span><del>-            $resp = $this->_sendCmd($cmd);
</del><ins>+            $this->_sendLine($cmd, array(
+                'noliteralplus' => $noliteralplus
+            ));
</ins><span class="cx">         } catch (Horde_Imap_Client_Exception $e) {
</span><span class="cx">             switch ($e->getCode()) {
</span><span class="cx">             case $e::CATENATE_BADURL:
</span><span class="lines">@@ -1680,8 +1622,7 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            if (!empty($options['create']) &&
-                !empty($e->resp_data['trycreate'])) {
</del><ins>+            if (!empty($options['create']) && $this->_temp['trycreate']) {
</ins><span class="cx">                 $this->createMailbox($mailbox);
</span><span class="cx">                 unset($options['create']);
</span><span class="cx">                 return $this->_append($mailbox, $data, $options);
</span><span class="lines">@@ -1706,21 +1647,18 @@
</span><span class="cx"> 
</span><span class="cx">         /* If we reach this point and have data in 'appenduid', UIDPLUS (RFC
</span><span class="cx">          * 4315) has done the dirty work for us. */
</span><del>-        return isset($resp->data['appenduid'])
-            ? $resp->data['appenduid']
-            : true;
</del><ins>+        return $t['appenduid'];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Prepares append message data for insertion into the IMAP command
</span><span class="cx">      * string.
</span><span class="cx">      *
</span><del>-     * @param mixed $data      Either a resource or a string.
-     * @param integer &$asize  Total append size.
</del><ins>+     * @param mixed $data  Either a resource or a string.
</ins><span class="cx">      *
</span><span class="cx">      * @return Horde_Imap_Client_Data_Format_String  The data object.
</span><span class="cx">      */
</span><del>-    protected function _appendData($data, &$asize)
</del><ins>+    protected function _appendData($data)
</ins><span class="cx">     {
</span><span class="cx">         if (is_resource($data)) {
</span><span class="cx">             rewind($data);
</span><span class="lines">@@ -1731,10 +1669,11 @@
</span><span class="cx">             'skipscan' => true
</span><span class="cx">         ));
</span><span class="cx"> 
</span><del>-        // APPEND data MUST be sent in a literal (RFC 3501 [6.3.11]).
-        $ob->forceLiteral();
</del><ins>+        // Force output to binary. Not much we can do if server doesn't
+        // support, so just deal with it at send-time.
+        $ob->forceBinary();
</ins><span class="cx"> 
</span><del>-        $asize += $ob->length();
</del><ins>+        $this->_temp['appendsize'] += $ob->length();
</ins><span class="cx"> 
</span><span class="cx">         return $ob;
</span><span class="cx">     }
</span><span class="lines">@@ -1784,7 +1723,7 @@
</span><span class="cx">     protected function _check()
</span><span class="cx">     {
</span><span class="cx">         // CHECK returns no untagged information (RFC 3501 [6.4.1])
</span><del>-        $this->_sendCmd($this->_command('CHECK'));
</del><ins>+        $this->_sendLine($this->_clientCommand('CHECK'));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -1794,19 +1733,15 @@
</span><span class="cx">         if (empty($options['expunge'])) {
</span><span class="cx">             if ($this->queryCapability('UNSELECT')) {
</span><span class="cx">                 // RFC 3691 defines 'UNSELECT' for precisely this purpose
</span><del>-                $this->_sendCmd($this->_command('UNSELECT'));
</del><ins>+                $this->_sendLine($this->_clientCommand('UNSELECT'));
</ins><span class="cx">             } else {
</span><del>-                /* RFC 3501 [6.4.2]: to close a mailbox without expunge,
-                 * select a non-existent mailbox. */
</del><ins>+                // RFC 3501 [6.4.2]: to close a mailbox without expunge,
+                // select a non-existent mailbox. Selecting a null mailbox
+                // should do the trick.
</ins><span class="cx">                 try {
</span><del>-                    $this->_sendCmd($this->_command('EXAMINE')->add(
-                        new Horde_Imap_Client_Data_Format_Mailbox("\24nonexist\24")
-                    ));
-
-                    /* Not pipelining, since the odds that this CLOSE is even
-                     * needed is tiny; and it returns BAD, which should be
-                     * avoided, if possible. */
-                    $this->_sendCmd($this->_command('CLOSE'));
</del><ins>+                    $cmd = $this->_clientCommand('SELECT');
+                    $cmd->add('');
+                    $this->_sendLine($cmd);
</ins><span class="cx">                 } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
</span><span class="cx">                     // Ignore error; it is expected.
</span><span class="cx">                 }
</span><span class="lines">@@ -1819,7 +1754,7 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             // CLOSE returns no untagged information (RFC 3501 [6.4.2])
</span><del>-            $this->_sendCmd($this->_command('CLOSE'));
</del><ins>+            $this->_sendLine($this->_clientCommand('CLOSE'));
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1835,7 +1770,7 @@
</span><span class="cx">         $use_cache = $this->_initCache(true);
</span><span class="cx"> 
</span><span class="cx">         if ($ids->all) {
</span><del>-            if (!$uidplus || $list_msgs || $use_cache) {
</del><ins>+            if (!$uidplus && ($list_msgs || $use_cache)) {
</ins><span class="cx">                 $ids = $this->resolveIds($this->_selected, $ids, 2);
</span><span class="cx">             }
</span><span class="cx">         } elseif ($uidplus) {
</span><span class="lines">@@ -1846,10 +1781,11 @@
</span><span class="cx">              * even if the server returns EXPUNGEs instead, we can use
</span><span class="cx">              * vanished() to grab the list. */
</span><span class="cx">             unset($this->_temp['search_save']);
</span><del>-            if (isset($this->_temp['enabled']['QRESYNC'])) {
</del><ins>+            if (isset($this->_init['enabled']['QRESYNC'])) {
</ins><span class="cx">                 $ids = $this->resolveIds($this->_selected, $ids, 1);
</span><span class="cx">                 if ($list_msgs) {
</span><span class="cx">                     $modseq = $this->_mailboxOb()->getStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ);
</span><ins>+                    unset($this->_temp['expunge_seen']);
</ins><span class="cx">                 }
</span><span class="cx">             } else {
</span><span class="cx">                 $ids = $this->resolveIds($this->_selected, $ids, ($list_msgs || $use_cache) ? 2 : 1);
</span><span class="lines">@@ -1887,42 +1823,20 @@
</span><span class="cx"> 
</span><span class="cx">         /* Always use UID EXPUNGE if available. */
</span><span class="cx">         if ($uidplus) {
</span><del>-            /* We can only pipeline STORE w/ EXPUNGE if using UIDs and UIDPLUS
-             * is available. */
-            if (empty($options['delete'])) {
-                $pipeline = $this->_pipeline();
-            } else {
-                $pipeline = $this->_storeCmd(array(
-                    'add' => array(
-                        Horde_Imap_Client::FLAG_DELETED
-                    ),
-                    'ids' => $ids
-                ));
-            }
-
</del><span class="cx">             foreach ($ids->split(2000) as $val) {
</span><del>-                $pipeline->add(
-                    $this->_command('UID EXPUNGE')->add($val)
-                );
</del><ins>+                $this->_sendLine($this->_clientCommand(array(
+                    'UID',
+                    'EXPUNGE',
+                    $val
+                )));
</ins><span class="cx">             }
</span><del>-
-            $resp = $this->_sendCmd($pipeline);
</del><ins>+        } elseif ($use_cache || $list_msgs) {
+            $this->_sendLine($this->_clientCommand('EXPUNGE'));
</ins><span class="cx">         } else {
</span><del>-            if (!empty($options['delete'])) {
-                $this->store($this->_selected, array(
-                    'add' => array(Horde_Imap_Client::FLAG_DELETED),
-                    'ids' => $ids
-                ));
-            }
-
-            if ($use_cache || $list_msgs) {
-                $this->_sendCmd($this->_command('EXPUNGE'));
-            } else {
-                /* This is faster than an EXPUNGE because the server will not
-                 * return untagged EXPUNGE responses. We can only do this if
-                 * we are not updating cache information. */
-                $this->close(array('expunge' => true));
-            }
</del><ins>+            /* This is faster than an EXPUNGE because the server will not
+             * return untagged EXPUNGE responses. We can only do this if
+             * we are not updating cache information. */
+            $this->close(array('expunge' => true));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         unset($this->_temp['expunged']);
</span><span class="lines">@@ -1934,16 +1848,14 @@
</span><span class="cx">             ));
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!is_null($modseq) && !empty($resp->data['expunge_seen'])) {
</del><ins>+        if (!is_null($modseq) && !empty($this->_temp['expunge_seen'])) {
</ins><span class="cx">             /* There's a chance we actually did a full map of sequence -> UID,
</span><span class="cx">              * but this code should never be reached in the first place so
</span><span class="cx">              * be ultra-safe and just do a full VANISHED search. */
</span><span class="cx">             $expunged_ob = $this->vanished($this->_selected, $modseq, array(
</span><span class="cx">                 'ids' => $ids
</span><span class="cx">             ));
</span><del>-            $this->_deleteMsgs($this->_selected, $expunged_ob, array(
-                'pipeline' => $resp
-            ));
</del><ins>+            $this->_deleteMsgs($this->_selected, $expunged_ob);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return $expunged_ob;
</span><span class="lines">@@ -1952,14 +1864,9 @@
</span><span class="cx">     /**
</span><span class="cx">      * Parse a VANISHED response (RFC 5162 [3.6]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The response data.
</span><span class="cx">      */
</span><del>-    protected function _parseVanished(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseVanished(Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><span class="cx">         /* There are two forms of VANISHED.  VANISHED (EARLIER) will be sent
</span><span class="cx">          * in a FETCH (VANISHED) or SELECT/EXAMINE (QRESYNC) call.
</span><span class="lines">@@ -1973,21 +1880,16 @@
</span><span class="cx">                  * QRESYNC. */
</span><span class="cx">                 $data->next();
</span><span class="cx">                 $vanished = $this->getIdsOb($data->next());
</span><del>-                if (isset($pipeline->data['vanished'])) {
-                    $pipeline->data['vanished']->add($vanished);
</del><ins>+                if (isset($this->_temp['vanished'])) {
+                    $this->_temp['vanished']->add($vanished);
</ins><span class="cx">                 } else {
</span><del>-                    $this->_deleteMsgs($this->_selected, $vanished, array(
-                        'pipeline' => $pipeline
-                    ));
</del><ins>+                    $this->_deleteMsgs($this->_selected, $vanished);
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">         } else {
</span><span class="cx">             /* The second form is just VANISHED. This is analogous to EXPUNGE
</span><span class="cx">              * and requires the message count to decrement. */
</span><del>-            $this->_deleteMsgs($this->_selected, $this->getIdsOb($curr), array(
-                'decrement' => true,
-                'pipeline' => $pipeline
-            ));
</del><ins>+            $this->_deleteMsgs($this->_selected, $this->getIdsOb($curr), true);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1997,6 +1899,8 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _search($query, $options)
</span><span class="cx">     {
</span><ins>+        $cmd = $this->_clientCommand(empty($options['sequence']) ? 'UID' : null);
+
</ins><span class="cx">         $sort_criteria = array(
</span><span class="cx">             Horde_Imap_Client::SORT_ARRIVAL => 'ARRIVAL',
</span><span class="cx">             Horde_Imap_Client::SORT_CC => 'CC',
</span><span class="lines">@@ -2067,9 +1971,7 @@
</span><span class="cx">             : $options['_query']['charset'];
</span><span class="cx"> 
</span><span class="cx">         if ($server_sort) {
</span><del>-            $cmd = $this->_command(
-                empty($options['sequence']) ? 'UID SORT' : 'SORT'
-            );
</del><ins>+            $cmd->add('SORT');
</ins><span class="cx">             $results = array();
</span><span class="cx"> 
</span><span class="cx">             // Use ESEARCH (RFC 4466) response if server supports.
</span><span class="lines">@@ -2121,12 +2023,11 @@
</span><span class="cx">             // Charset is mandatory for SORT (RFC 5256 [3]).
</span><span class="cx">             $cmd->add($charset);
</span><span class="cx">         } else {
</span><del>-            $cmd = $this->_command(
-                empty($options['sequence']) ? 'UID SEARCH' : 'SEARCH'
-            );
</del><span class="cx">             $esearch = false;
</span><span class="cx">             $results = array();
</span><span class="cx"> 
</span><ins>+            $cmd->add('SEARCH');
+
</ins><span class="cx">             // Check if the server supports ESEARCH (RFC 4731).
</span><span class="cx">             if ($this->queryCapability('ESEARCH')) {
</span><span class="cx">                 foreach ($options['results'] as $val) {
</span><span class="lines">@@ -2170,18 +2071,20 @@
</span><span class="cx">                     $options['_query']['charset']
</span><span class="cx">                 ));
</span><span class="cx">             }
</span><ins>+
+            // SEARCHRES requires ESEARCH
+            unset($this->_temp['searchnotsaved']);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        $er = &$this->_temp['esearchresp'];
+        $er = array();
+        $sr = &$this->_temp['searchresp'];
+        $sr = $this->getIdsOb(array(), !empty($options['sequence']));
+
</ins><span class="cx">         $cmd->add($options['_query']['query'], true);
</span><span class="cx"> 
</span><del>-        $pipeline = $this->_pipeline($cmd);
-        $pipeline->data['esearchresp'] = array();
-        $er = &$pipeline->data['esearchresp'];
-        $pipeline->data['searchresp'] = $this->getIdsOb(array(), !empty($options['sequence']));
-        $sr = &$pipeline->data['searchresp'];
-
</del><span class="cx">         try {
</span><del>-            $resp = $this->_sendCmd($pipeline);
</del><ins>+            $this->_sendLine($cmd);
</ins><span class="cx">         } catch (Horde_Imap_Client_Exception $e) {
</span><span class="cx">             if (($e instanceof Horde_Imap_Client_Exception_ServerResponse) &&
</span><span class="cx">                 ($e->status == Horde_Imap_Client_Interaction_Server::NO) &&
</span><span class="lines">@@ -2273,7 +2176,7 @@
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             case Horde_Imap_Client::SEARCH_RESULTS_SAVE:
</span><del>-                $this->_temp['search_save'] = $ret['save'] = $esearch ? empty($resp->data['searchnotsaved']) : false;
</del><ins>+                $this->_temp['search_save'] = $ret['save'] = $esearch ? empty($this->_temp['searchnotsaved']) : false;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -2286,7 +2189,8 @@
</span><span class="cx">         unset($this->_temp['search_retry']);
</span><span class="cx"> 
</span><span class="cx">         /* Check for EXPUNGEISSUED (RFC 2180 [4.3]/RFC 5530 [3]). */
</span><del>-        if (!empty($resp->data['expungeissued'])) {
</del><ins>+        if (!empty($this->_temp['expungeissued'])) {
+            unset($this->_temp['expungeissued']);
</ins><span class="cx">             $this->noop();
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -2297,31 +2201,21 @@
</span><span class="cx">      * Parse a SEARCH/SORT response (RFC 3501 [7.2.5]; RFC 4466 [3];
</span><span class="cx">      * RFC 5256 [4]; RFC 5267 [3]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param array $data  A list of IDs (message sequence numbers or UIDs).
</span><span class="cx">      */
</span><del>-    protected function _parseSearch(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        $data
-    )
</del><ins>+    protected function _parseSearch($data)
</ins><span class="cx">     {
</span><span class="cx">         /* More than one search response may be sent. */
</span><del>-        $pipeline->data['searchresp']->add($data);
</del><ins>+        $this->_temp['searchresp']->add($data);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Parse an ESEARCH response (RFC 4466 [2.6.2])
</span><span class="cx">      * Format: (TAG "a567") UID COUNT 5 ALL 4:19,21,28
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The server response.
</span><span class="cx">      */
</span><del>-    protected function _parseEsearch(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseEsearch(Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><span class="cx">         // Ignore search correlator information
</span><span class="cx">         if ($data->next() === true) {
</span><span class="lines">@@ -2340,7 +2234,7 @@
</span><span class="cx"> 
</span><span class="cx">             switch ($tag) {
</span><span class="cx">             case 'ALL':
</span><del>-                $this->_parseSearch($pipeline, $val);
</del><ins>+                $this->_parseSearch($val);
</ins><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             case 'COUNT':
</span><span class="lines">@@ -2348,13 +2242,13 @@
</span><span class="cx">             case 'MIN':
</span><span class="cx">             case 'MODSEQ':
</span><span class="cx">             case 'RELEVANCY':
</span><del>-                $pipeline->data['esearchresp'][strtolower($tag)] = $val;
</del><ins>+                $this->_temp['esearchresp'][strtolower($tag)] = $val;
</ins><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             case 'PARTIAL':
</span><span class="cx">                 // RFC 5267 [4.4]
</span><span class="cx">                 $partial = $val->flushIterator();
</span><del>-                $this->_parseSearch($pipeline, end($partial));
</del><ins>+                $this->_parseSearch(end($partial));
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         } while (($current = $data->next()) !== false);
</span><span class="lines">@@ -2364,37 +2258,32 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _setComparator($comparator)
</span><span class="cx">     {
</span><del>-        $cmd = $this->_command('COMPARATOR');
</del><ins>+        $cmd = $this->_clientCommand('COMPARATOR');
</ins><span class="cx">         foreach ($comparator as $val) {
</span><span class="cx">             $cmd->add(new Horde_Imap_Client_Data_Format_Astring($val));
</span><span class="cx">         }
</span><del>-        $this->_sendCmd($cmd);
</del><ins>+        $this->_sendLine($cmd);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      */
</span><span class="cx">     protected function _getComparator()
</span><span class="cx">     {
</span><del>-        $resp = $this->_sendCmd($this->_command('COMPARATOR'));
</del><ins>+        $this->_sendLine($this->_clientCommand('COMPARATOR'));
</ins><span class="cx"> 
</span><del>-        return isset($resp->data['comparator'])
-            ? $resp->data['comparator']
</del><ins>+        return isset($this->_temp['comparator'])
+            ? $this->_temp['comparator']
</ins><span class="cx">             : null;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Parse a COMPARATOR response (RFC 5255 [4.8])
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The server response.
</span><span class="cx">      */
</span><del>-    protected function _parseComparator(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        $data
-    )
</del><ins>+    protected function _parseComparator($data)
</ins><span class="cx">     {
</span><del>-        $pipeline->data['comparator'] = $data->next();
</del><ins>+        $this->_temp['comparator'] = $data->next();
</ins><span class="cx">         // Ignore optional matching comparator list
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -2447,9 +2336,11 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $cmd = $this->_command(
-            empty($options['sequence']) ? 'UID THREAD' : 'THREAD'
-        )->add($tsort);
</del><ins>+        $cmd = $this->_clientCommand(array(
+            empty($options['sequence']) ? 'UID' : null,
+            'THREAD',
+            $tsort
+        ));
</ins><span class="cx"> 
</span><span class="cx">         if (empty($options['search'])) {
</span><span class="cx">             $cmd->add(array(
</span><span class="lines">@@ -2462,23 +2353,17 @@
</span><span class="cx">             $cmd->add($search_query['query'], true);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return new Horde_Imap_Client_Data_Thread(
-            $this->_sendCmd($cmd)->data['threadparse'],
-            empty($options['sequence']) ? 'uid' : 'sequence'
-        );
</del><ins>+        $this->_sendLine($cmd);
+
+        return new Horde_Imap_Client_Data_Thread($this->_temp['threadparse'], empty($options['sequence']) ? 'uid' : 'sequence');
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Parse a THREAD response (RFC 5256 [4]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  Thread data.
</span><span class="cx">      */
</span><del>-    protected function _parseThread(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseThread(Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><span class="cx">         $out = array();
</span><span class="cx"> 
</span><span class="lines">@@ -2488,7 +2373,7 @@
</span><span class="cx">             $out[] = $thread;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $pipeline->data['threadparse'] = $out;
</del><ins>+        $this->_temp['threadparse'] = $out;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -2514,54 +2399,11 @@
</span><span class="cx">     /**
</span><span class="cx">      */
</span><span class="cx">     protected function _fetch(Horde_Imap_Client_Fetch_Results $results,
</span><del>-                              $queries)
</del><ins>+                              Horde_Imap_Client_Fetch_Query $query,
+                              $options)
</ins><span class="cx">     {
</span><del>-        $pipeline = $this->_pipeline();
-        $pipeline->data['fetch_lookup'] = array();
-
-        foreach ($queries as $options) {
-            $this->_fetchCmd($pipeline, $options);
-            $sequence = $options['ids']->sequence;
-        }
-
-        try {
-            $resp = $this->_sendCmd($pipeline);
-
-            /* Check for EXPUNGEISSUED (RFC 2180 [4.1]/RFC 5530 [3]). */
-            if (!empty($resp->data['expungeissued'])) {
-                $this->noop();
-            }
-        } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
-            // A NO response, when coupled with a sequence FETCH, most
-            // likely means that messages were expunged. RFC 2180 [4.1]
-            if ($sequence &&
-                ($e->status == Horde_Imap_Client_Interaction_Server::NO)) {
-                $this->noop();
-            }
-        } catch (Exception $e) {
-            // For any other error, ignore the Exception - fetch() is nice in
-            // that the return value explicitly handles missing data for any
-            // given message.
-        }
-
-        foreach ($resp->fetch as $k => $v) {
-            $results->get($sequence ? $k : $v->getUid())->merge($v);
-        }
-    }
-
-    /**
-     * Add a FETCH command to the given pipeline.
-     *
-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
-     * @param array $options                                    Fetch query
-     *                                                          options
-     */
-    protected function _fetchCmd(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        $options
-    )
-    {
</del><ins>+        $t = &$this->_temp;
+        $t['fetchcmd'] = array();
</ins><span class="cx">         $fetch = new Horde_Imap_Client_Data_Format_List();
</span><span class="cx">         $sequence = $options['ids']->sequence;
</span><span class="cx"> 
</span><span class="lines">@@ -2593,7 +2435,7 @@
</span><span class="cx">          *   RFC822.TEXT => BODY[TEXT]
</span><span class="cx">          */
</span><span class="cx"> 
</span><del>-        foreach ($options['_query'] as $type => $c_val) {
</del><ins>+        foreach ($query as $type => $c_val) {
</ins><span class="cx">             switch ($type) {
</span><span class="cx">             case Horde_Imap_Client::FETCH_STRUCTURE:
</span><span class="cx">                 $fetch->add('BODYSTRUCTURE');
</span><span class="lines">@@ -2654,7 +2496,7 @@
</span><span class="cx"> 
</span><span class="cx">                         // Maintain a command -> label lookup so we can put
</span><span class="cx">                         // the results in the proper location.
</span><del>-                        $pipeline->data['fetch_lookup'][$cmd] = $key;
</del><ins>+                        $t['fetchcmd'][$cmd] = $key;
</ins><span class="cx">                     }
</span><span class="cx"> 
</span><span class="cx">                     if (empty($val['peek'])) {
</span><span class="lines">@@ -2698,15 +2540,15 @@
</span><span class="cx">                 /* A UID FETCH will always return UID information (RFC 3501
</span><span class="cx">                  * [6.4.8]). Don't add to query as it just creates a longer
</span><span class="cx">                  * FETCH command. */
</span><del>-                if ($sequence || (count($options['_query']) == 1)) {
</del><ins>+                if ($sequence || (count($query) == 1)) {
</ins><span class="cx">                     $fetch->add('UID');
</span><span class="cx">                 }
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             case Horde_Imap_Client::FETCH_SEQ:
</span><del>-                // Nothing we need to add to fetch request unless sequence is
-                // the only criteria.
-                if (count($options['_query']) == 1) {
</del><ins>+                // Nothing we need to add to fetch request unless sequence
+                // is the only criteria.
+                if (count($query) == 1) {
</ins><span class="cx">                     $fetch->add('UID');
</span><span class="cx">                 }
</span><span class="cx">                 break;
</span><span class="lines">@@ -2748,15 +2590,42 @@
</span><span class="cx">          * approach this limit. For simplification, assume that the UID list
</span><span class="cx">          * is the limiting factor and split this list at a sequence comma
</span><span class="cx">          * delimiter if it exceeds 2000 characters. */
</span><ins>+        $cmd_list = array();
</ins><span class="cx">         foreach ($options['ids']->split(2000) as $val) {
</span><del>-            $cmd = $this->_command(
-                $sequence ? 'FETCH' : 'UID FETCH'
-            )->add(array(
</del><ins>+            $cmd_list[] = $this->_clientCommand(array_filter(array(
+                $sequence ? null : 'UID',
+                'FETCH',
</ins><span class="cx">                 $val,
</span><span class="cx">                 $fetch_cmd
</span><del>-            ));
-            $pipeline->add($cmd);
</del><ins>+            )));
</ins><span class="cx">         }
</span><ins>+
+        foreach ($cmd_list as $val) {
+            try {
+                $this->_sendLine($val, array(
+                   'keep_fetch' => true
+                ));
+            } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
+                // A NO response, when coupled with a sequence FETCH, most
+                // likely means that messages were expunged. RFC 2180 [4.1]
+                if ($sequence &&
+                    ($e->status == Horde_Imap_Client_Interaction_Server::NO)) {
+                    $this->_temp['expungeissued'] = true;
+                }
+            }
+        }
+
+        /* Check for EXPUNGEISSUED (RFC 2180 [4.1]/RFC 5530 [3]). */
+        if (!empty($this->_temp['expungeissued'])) {
+            unset($this->_temp['expungeissued']);
+            $this->noop();
+        }
+
+        foreach ($this->_fetch as $k => $v) {
+            $results->get($sequence ? $k : $v->getUid())->merge($v);
+        }
+
+        $this->_fetch->clear();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -2782,22 +2651,16 @@
</span><span class="cx">      * due to a FETCH command, or due to a change in a message's state (i.e.
</span><span class="cx">      * the flags change).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param integer $id                       The message sequence number.
</span><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The server response.
</span><span class="cx">      */
</span><del>-    protected function _parseFetch(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        $id,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseFetch($id, Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><span class="cx">         if ($data->next() !== true) {
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $ob = $pipeline->fetch->get($id);
</del><ins>+        $ob = $this->_fetch->get($id);
</ins><span class="cx">         $ob->setSeq($id);
</span><span class="cx"> 
</span><span class="cx">         $flags = $modseq = $uid = false;
</span><span class="lines">@@ -2848,7 +2711,7 @@
</span><span class="cx"> 
</span><span class="cx">                     /* Store MODSEQ value. It may be used as the highestmodseq
</span><span class="cx">                      * once a tagged response is received (RFC 5162 [5]). */
</span><del>-                    $pipeline->data['modseqs'][] = $modseq;
</del><ins>+                    $this->_temp['modseqs'][] = $modseq;
</ins><span class="cx">                 }
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="lines">@@ -2859,7 +2722,7 @@
</span><span class="cx">                     $tag = substr($tag, 5);
</span><span class="cx"> 
</span><span class="cx">                     // BODY[HEADER.FIELDS] request
</span><del>-                    if (!empty($pipeline->data['fetch_lookup']) &&
</del><ins>+                    if (!empty($this->_temp['fetchcmd']) &&
</ins><span class="cx">                         (strpos($tag, 'HEADER.FIELDS') !== false)) {
</span><span class="cx">                         $data->next();
</span><span class="cx">                         $sig = $tag . ' (' . implode(' ', array_map('strtoupper', $data->flushIterator())) . ')';
</span><span class="lines">@@ -2867,7 +2730,7 @@
</span><span class="cx">                         // Ignore the trailing bracket
</span><span class="cx">                         $data->next();
</span><span class="cx"> 
</span><del>-                        $ob->setHeaders($pipeline->data['fetch_lookup'][$sig], $data->next());
</del><ins>+                        $ob->setHeaders($this->_temp['fetchcmd'][$sig], $data->next());
</ins><span class="cx">                     } else {
</span><span class="cx">                         // Remove trailing bracket and octet start info
</span><span class="cx">                         $tag = substr($tag, 0, strrpos($tag, ']'));
</span><span class="lines">@@ -2943,7 +2806,7 @@
</span><span class="cx">          * mailbox open so we only lose a bit of caching efficiency.
</span><span class="cx">          * Otherwise, we could end up with an inconsistent cached state. */
</span><span class="cx">         if ($flags && $modseq && !$uid) {
</span><del>-            $pipeline->data['modseqs_nouid'][] = $id;
</del><ins>+            $this->_temp['modseqs_nouid'][] = $id;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -3115,8 +2978,8 @@
</span><span class="cx">         );
</span><span class="cx"> 
</span><span class="cx">         $addr_ob = new Horde_Mail_Rfc822_Address();
</span><del>-        $env_addrs = $this->getParam('envelope_addrs');
-        $env_str = $this->getParam('envelope_string');
</del><ins>+        $env_addrs = $this->_params['envelope_addrs'];
+        $env_str = $this->_params['envelope_string'];
</ins><span class="cx">         $key = 0;
</span><span class="cx">         $ret = new Horde_Imap_Client_Data_Envelope();
</span><span class="cx"> 
</span><span class="lines">@@ -3183,127 +3046,118 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _vanished($modseq, Horde_Imap_Client_Ids $ids)
</span><span class="cx">     {
</span><del>-        $pipeline = $this->_pipeline(
-            $this->_command('UID FETCH')->add(array(
-                strval($ids),
-                'UID',
-                new Horde_Imap_Client_Data_Format_List(array(
-                    'VANISHED',
-                    'CHANGEDSINCE',
-                    new Horde_Imap_Client_Data_Format_Number($modseq)
-                ))
</del><ins>+        $vanished_ob = $this->getIdsOb();
+        $this->_temp['vanished'] = $vanished_ob;
+
+        $cmd = $this->_clientCommand(array(
+            'UID',
+            'FETCH',
+            strval($ids),
+            'UID',
+            new Horde_Imap_Client_Data_Format_List(array(
+                'VANISHED',
+                'CHANGEDSINCE',
+                new Horde_Imap_Client_Data_Format_Number($modseq)
</ins><span class="cx">             ))
</span><del>-        );
-        $pipeline->data['vanished'] = $this->getIdsOb();
</del><ins>+        ));
</ins><span class="cx"> 
</span><del>-        return $this->_sendCmd($pipeline)->data['vanished'];
</del><ins>+        $this->_sendLine($cmd);
+
+        unset($this->_temp['vanished']);
+
+        return $vanished_ob;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      */
</span><span class="cx">     protected function _store($options)
</span><span class="cx">     {
</span><del>-        $pipeline = $this->_storeCmd($options);
-        $pipeline->data['modified'] = $this->getIdsOb();
</del><ins>+        $cmd = $this->_clientCommand(array(
+            empty($options['sequence']) ? 'UID' : null,
+            'STORE',
+            strval($options['ids'])
+        ));
</ins><span class="cx"> 
</span><del>-        try {
-            $resp = $this->_sendCmd($pipeline);
-
-            /* Check for EXPUNGEISSUED (RFC 2180 [4.2]/RFC 5530 [3]). */
-            if (!empty($resp->data['expungeissued'])) {
-                $this->noop();
-            }
-
-            return $resp->data['modified'];
-        } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
-            /* A NO response, when coupled with a sequence STORE and
-             * non-SILENT behavior, most likely means that messages were
-             * expunged. RFC 2180 [4.2] */
-            if (empty($pipeline->data['store_silent']) &&
-                !empty($options['sequence']) &&
-                ($e->status == Horde_Imap_Client_Interaction_Server::NO)) {
-                $this->noop();
-            }
-
-            return $pipeline->data['modified'];
</del><ins>+        if (empty($options['unchangedsince'])) {
+            $silent = !($this->_debug->debug || $this->_initCache(true));
+        } else {
+            $cmd->add(new Horde_Imap_Client_Data_Format_List(array(
+                'UNCHANGEDSINCE',
+                new Horde_Imap_Client_Data_Format_Number(intval($options['unchangedsince']))
+            )));
+            $silent = false;
</ins><span class="cx">         }
</span><del>-    }
</del><span class="cx"> 
</span><del>-    /**
-     * Create a store command.
-     *
-     * @param array $options  See Horde_Imap_Client_Base#_store().
-     *
-     * @return Horde_Imap_Client_Interaction_Pipeline  Pipeline object.
-     */
-    protected function _storeCmd($options)
-    {
</del><span class="cx">         $cmds = array();
</span><del>-        $silent = empty($options['unchangedsince'])
-             ? !($this->_debug->debug || $this->_initCache(true))
-             : false;
</del><ins>+        $this->_temp['modified'] = $this->getIdsOb();
</ins><span class="cx"> 
</span><span class="cx">         if (!empty($options['replace'])) {
</span><del>-            $cmds[] = array(
</del><ins>+            $cmd->add(array(
</ins><span class="cx">                 'FLAGS' . ($silent ? '.SILENT' : ''),
</span><span class="cx">                 $options['replace']
</span><del>-            );
</del><ins>+            ));
+            $cmds[] = $cmd;
</ins><span class="cx">         } else {
</span><span class="cx">             foreach (array('add' => '+', 'remove' => '-') as $k => $v) {
</span><span class="cx">                 if (!empty($options[$k])) {
</span><del>-                    $cmds[] = array(
</del><ins>+                    $cmdtmp = clone $cmd;
+                    $cmdtmp->add(array(
</ins><span class="cx">                         $v . 'FLAGS' . ($silent ? '.SILENT' : ''),
</span><span class="cx">                         $options[$k]
</span><del>-                    );
</del><ins>+                    ));
+                    $cmds[] = $cmdtmp;
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $pipeline = $this->_pipeline();
-        $pipeline->data['store_silent'] = $silent;
-
</del><span class="cx">         foreach ($cmds as $val) {
</span><del>-            $cmd = $this->_command(
-                empty($options['sequence']) ? 'UID STORE' : 'STORE'
-            )->add(strval($options['ids']));
-            if (!empty($options['unchangedsince'])) {
-                $cmd->add(new Horde_Imap_Client_Data_Format_List(array(
-                    'UNCHANGEDSINCE',
-                    new Horde_Imap_Client_Data_Format_Number(intval($options['unchangedsince']))
-                )));
</del><ins>+            try {
+                $this->_sendLine($val);
+            } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
+                /* A NO response, when coupled with a sequence STORE and
+                 * non-SILENT behavior, most likely means that messages were
+                 * expunged. RFC 2180 [4.2] */
+                if (!$silent &&
+                    !empty($options['sequence']) &&
+                    ($e->status == Horde_Imap_Client_Interaction_Server::NO)) {
+                    $this->_temp['expungeissued'] = true;
+                }
</ins><span class="cx">             }
</span><del>-            $cmd->add($val);
</del><span class="cx"> 
</span><del>-            $pipeline->add($cmd);
</del><ins>+            /* Check for EXPUNGEISSUED (RFC 2180 [4.2]/RFC 5530 [3]). */
+            if (!empty($this->_temp['expungeissued'])) {
+                unset($this->_temp['expungeissued']);
+                $this->noop();
+            }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return $pipeline;
</del><ins>+        return $this->_temp['modified'];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      */
</span><span class="cx">     protected function _copy(Horde_Imap_Client_Mailbox $dest, $options)
</span><span class="cx">     {
</span><ins>+        $this->_temp['copydest'] = $dest;
+        $this->_temp['copyuid'] = true;
+        $this->_temp['trycreate'] = null;
+
</ins><span class="cx">         /* Check for MOVE command (RFC 6851). */
</span><span class="cx">         $move_cmd = (!empty($options['move']) &&
</span><span class="cx">                      $this->queryCapability('MOVE'));
</span><span class="cx"> 
</span><del>-        $cmd = $this->_pipeline(
-            $this->_command(
-                ($options['ids']->sequence ? '' : 'UID ') . ($move_cmd ? 'MOVE' : 'COPY')
-            )->add(array(
</del><ins>+        // COPY returns no untagged information (RFC 3501 [6.4.7])
+        try {
+            $cmd = $this->_clientCommand(array_filter(array(
+                $options['ids']->sequence ? null : 'UID',
+                $move_cmd ? 'MOVE' : 'COPY',
</ins><span class="cx">                 strval($options['ids']),
</span><span class="cx">                 new Horde_Imap_Client_Data_Format_Mailbox($dest)
</span><del>-            ))
-        );
-        $cmd->data['copydest'] = $dest;
</del><ins>+            )));
</ins><span class="cx"> 
</span><del>-        // COPY returns no untagged information (RFC 3501 [6.4.7])
-        try {
-            $resp = $this->_sendCmd($cmd);
</del><ins>+            $this->_sendLine($cmd);
</ins><span class="cx">         } catch (Horde_Imap_Client_Exception $e) {
</span><del>-            if (!empty($options['create']) &&
-                !empty($e->resp_data['trycreate'])) {
</del><ins>+            if (!empty($options['create']) && $this->_temp['trycreate']) {
</ins><span class="cx">                 $this->createMailbox($dest);
</span><span class="cx">                 unset($options['create']);
</span><span class="cx">                 return $this->_copy($dest, $options);
</span><span class="lines">@@ -3315,17 +3169,16 @@
</span><span class="cx">         // was moved.
</span><span class="cx">         if (!$move_cmd &&
</span><span class="cx">             !empty($options['move']) &&
</span><del>-            (isset($resp->data['copyuid']) ||
-             !$this->queryCapability('UIDPLUS'))) {
-            $this->expunge($this->_selected, array(
-                'delete' => true,
-                'ids' => $options['ids']
-            ));
</del><ins>+            (($this->_temp['copyuid'] !== true) ||
+             !$this->_queryCapability('UIDPLUS'))) {
+            $opts = array('ids' => $options['ids']);
+            $this->store($this->_selected, array_merge(array(
+                'add' => array(Horde_Imap_Client::FLAG_DELETED)
+            ), $opts));
+            $this->expunge($this->_selected, $opts);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return isset($resp->data['copyuid'])
-            ? $resp->data['copyuid']
-            : true;
</del><ins>+        return $this->_temp['copyuid'];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -3341,41 +3194,39 @@
</span><span class="cx">             ));
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $this->_sendCmd(
-            $this->_command('SETQUOTA')->add(array(
-                new Horde_Imap_Client_Data_Format_Mailbox($root),
-                $limits
-            ))
-        );
</del><ins>+        $cmd = $this->_clientCommand(array(
+            'SETQUOTA',
+            new Horde_Imap_Client_Data_Format_Mailbox($root),
+            $limits
+        ));
+
+        $this->_sendLine($cmd);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      */
</span><span class="cx">     protected function _getQuota(Horde_Imap_Client_Mailbox $root)
</span><span class="cx">     {
</span><del>-        $pipeline = $this->_pipeline(
-            $this->_command('GETQUOTA')->add(
-                new Horde_Imap_Client_Data_Format_Mailbox($root)
-            )
-        );
-        $pipeline->data['quotaresp'] = array();
</del><ins>+        $this->_temp['quotaresp'] = array();
</ins><span class="cx"> 
</span><del>-        return reset($this->_sendCmd($pipeline)->data['quotaresp']);
</del><ins>+        $cmd = $this->_clientCommand(array(
+            'GETQUOTA',
+            new Horde_Imap_Client_Data_Format_Mailbox($root)
+        ));
+
+        $this->_sendLine($cmd);
+
+        return reset($this->_temp['quotaresp']);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Parse a QUOTA response (RFC 2087 [5.1]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The server response.
</span><span class="cx">      */
</span><del>-    protected function _parseQuota(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseQuota(Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><del>-        $c = &$pipeline->data['quotaresp'];
</del><ins>+        $c = &$this->_temp['quotaresp'];
</ins><span class="cx"> 
</span><span class="cx">         $root = $data->next();
</span><span class="cx">         $c[$root] = array();
</span><span class="lines">@@ -3394,14 +3245,16 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _getQuotaRoot(Horde_Imap_Client_Mailbox $mailbox)
</span><span class="cx">     {
</span><del>-        $pipeline = $this->_pipeline(
-            $this->_command('GETQUOTAROOT')->add(
-                new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
-            )
-        );
-        $pipeline->data['quotaresp'] = array();
</del><ins>+        $this->_temp['quotaresp'] = array();
</ins><span class="cx"> 
</span><del>-        return $this->_sendCmd($pipeline)->data['quotaresp'];
</del><ins>+        $cmd = $this->_clientCommand(array(
+            'GETQUOTAROOT',
+            new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
+        ));
+
+        $this->_sendLine($cmd);
+
+        return $this->_temp['quotaresp'];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -3410,13 +3263,14 @@
</span><span class="cx">                                $options)
</span><span class="cx">     {
</span><span class="cx">         // SETACL returns no untagged information (RFC 4314 [3.1]).
</span><del>-        $this->_sendCmd(
-            $this->_command('SETACL')->add(array(
-                new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
-                new Horde_Imap_Client_Data_Format_Astring($identifier),
-                new Horde_Imap_Client_Data_Format_Astring($options['rights'])
-            ))
-        );
</del><ins>+        $cmd = $this->_clientCommand(array(
+            'SETACL',
+            new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
+            new Horde_Imap_Client_Data_Format_Astring($identifier),
+            new Horde_Imap_Client_Data_Format_Astring($options['rights'])
+        ));
+
+        $this->_sendLine($cmd);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -3424,38 +3278,39 @@
</span><span class="cx">     protected function _deleteACL(Horde_Imap_Client_Mailbox $mailbox, $identifier)
</span><span class="cx">     {
</span><span class="cx">         // DELETEACL returns no untagged information (RFC 4314 [3.2]).
</span><del>-        $this->_sendCmd(
-            $this->_command('DELETEACL')->add(array(
-                new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
-                new Horde_Imap_Client_Data_Format_Astring($identifier)
-            ))
-        );
</del><ins>+        $cmd = $this->_clientCommand(array(
+            'DELETEACL',
+            new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
+            new Horde_Imap_Client_Data_Format_Astring($identifier)
+        ));
+
+        $this->_sendLine($cmd);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      */
</span><span class="cx">     protected function _getACL(Horde_Imap_Client_Mailbox $mailbox)
</span><span class="cx">     {
</span><del>-        return $this->_sendCmd(
-            $this->_command('GETACL')->add(
-                new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
-            )
-        )->data['getacl'];
</del><ins>+        $this->_temp['getacl'] = array();
+
+        $cmd = $this->_clientCommand(array(
+            'GETACL',
+            new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
+        ));
+
+        $this->_sendLine($cmd);
+
+        return $this->_temp['getacl'];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Parse an ACL response (RFC 4314 [3.6]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The server response.
</span><span class="cx">      */
</span><del>-    protected function _parseACL(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseACL(Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><del>-        $acl = array();
</del><ins>+        $acl = &$this->_temp['getacl'];
</ins><span class="cx"> 
</span><span class="cx">         // Ignore mailbox argument -> index 1
</span><span class="cx">         $data->next();
</span><span class="lines">@@ -3465,8 +3320,6 @@
</span><span class="cx">                 ? new Horde_Imap_Client_Data_AclNegative($data->next())
</span><span class="cx">                 : new Horde_Imap_Client_Data_Acl($data->next());
</span><span class="cx">         }
</span><del>-
-        $pipeline->data['getacl'] = $acl;
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -3474,35 +3327,33 @@
</span><span class="cx">     protected function _listACLRights(Horde_Imap_Client_Mailbox $mailbox,
</span><span class="cx">                                       $identifier)
</span><span class="cx">     {
</span><del>-        $resp = $this->_sendCmd(
-            $this->_command('LISTRIGHTS')->add(array(
-                new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
-                new Horde_Imap_Client_Data_Format_Astring($identifier)
-            ))
-        );
</del><ins>+        unset($this->_temp['listaclrights']);
</ins><span class="cx"> 
</span><del>-        return isset($resp->data['listaclrights'])
-            ? $resp->data['listaclrights']
</del><ins>+        $cmd = $this->_clientCommand(array(
+            'LISTRIGHTS',
+            new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
+            new Horde_Imap_Client_Data_Format_Astring($identifier)
+        ));
+
+        $this->_sendLine($cmd);
+
+        return isset($this->_temp['listaclrights'])
+            ? $this->_temp['listaclrights']
</ins><span class="cx">             : new Horde_Imap_Client_Data_AclRights();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Parse a LISTRIGHTS response (RFC 4314 [3.7]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The server response.
</span><span class="cx">      */
</span><del>-    protected function _parseListRights(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseListRights(Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><span class="cx">         // Ignore mailbox and identifier arguments
</span><span class="cx">         $data->next();
</span><span class="cx">         $data->next();
</span><span class="cx"> 
</span><del>-        $pipeline->data['listaclrights'] = new Horde_Imap_Client_Data_AclRights(
</del><ins>+        $this->_temp['listaclrights'] = new Horde_Imap_Client_Data_AclRights(
</ins><span class="cx">             str_split($data->next()),
</span><span class="cx">             $data->flushIterator()
</span><span class="cx">         );
</span><span class="lines">@@ -3512,33 +3363,31 @@
</span><span class="cx">      */
</span><span class="cx">     protected function _getMyACLRights(Horde_Imap_Client_Mailbox $mailbox)
</span><span class="cx">     {
</span><del>-        $resp = $this->_sendCmd(
-            $this->_command('MYRIGHTS')->add(
-                new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
-            )
-        );
</del><ins>+        unset($this->_temp['myrights']);
</ins><span class="cx"> 
</span><del>-        return isset($resp->data['myrights'])
-            ? $resp->data['myrights']
</del><ins>+        $cmd = $this->_clientCommand(array(
+            'MYRIGHTS',
+            new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
+        ));
+
+        $this->_sendLine($cmd);
+
+        return isset($this->_temp['myrights'])
+            ? $this->_temp['myrights']
</ins><span class="cx">             : new Horde_Imap_Client_Data_Acl();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Parse a MYRIGHTS response (RFC 4314 [3.8]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The server response.
</span><span class="cx">      */
</span><del>-    protected function _parseMyRights(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseMyRights(Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><span class="cx">         // Ignore 1st token (mailbox name)
</span><span class="cx">         $data->next();
</span><span class="cx"> 
</span><del>-        $pipeline->data['myrights'] = new Horde_Imap_Client_Data_Acl($data->next());
</del><ins>+        $this->_temp['myrights'] = new Horde_Imap_Client_Data_Acl($data->next());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -3546,8 +3395,7 @@
</span><span class="cx">     protected function _getMetadata(Horde_Imap_Client_Mailbox $mailbox,
</span><span class="cx">                                     $entries, $options)
</span><span class="cx">     {
</span><del>-        $pipeline = $this->_pipeline();
-        $pipeline->data['metadata'] = array();
</del><ins>+        $this->_temp['metadata'] = array();
</ins><span class="cx"> 
</span><span class="cx">         if ($this->queryCapability('METADATA') ||
</span><span class="cx">             ((strlen($mailbox) == 0) &&
</span><span class="lines">@@ -3572,44 +3420,51 @@
</span><span class="cx">                 $queries->add(new Horde_Imap_Client_Data_Format_Astring($md_entry));
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            $cmd = $this->_command('GETMETADATA')->add(
</del><ins>+            $cmd = $this->_clientCommand(array(
+                'GETMETADATA',
</ins><span class="cx">                 new Horde_Imap_Client_Data_Format_Mailbox($mailbox)
</span><del>-            );
</del><ins>+            ));
</ins><span class="cx">             if (count($cmd_options)) {
</span><span class="cx">                 $cmd->add($cmd_options);
</span><span class="cx">             }
</span><span class="cx">             $cmd->add($queries);
</span><span class="cx"> 
</span><del>-            $pipeline->add($cmd);
-        } else {
-            if (!$this->queryCapability('ANNOTATEMORE') &&
-                !$this->queryCapability('ANNOTATEMORE2')) {
-                throw new Horde_Imap_Client_Exception_NoSupportExtension('METADATA');
-            }
</del><ins>+            $this->_sendLine($cmd);
</ins><span class="cx"> 
</span><del>-            $queries = array();
-            foreach ($entries as $md_entry) {
-                list($entry, $type) = $this->_getAnnotateMoreEntry($md_entry);
</del><ins>+            return $this->_temp['metadata'];
+        }
</ins><span class="cx"> 
</span><del>-                if (!isset($queries[$type])) {
-                    $queries[$type] = new Horde_Imap_Client_Data_Format_List();
-                }
-                $queries[$type]->add(new Horde_Imap_Client_Data_Format_String($entry));
-            }
</del><ins>+        if (!$this->queryCapability('ANNOTATEMORE') &&
+            !$this->queryCapability('ANNOTATEMORE2')) {
+            throw new Horde_Imap_Client_Exception_NoSupportExtension('METADATA');
+        }
</ins><span class="cx"> 
</span><del>-            foreach ($queries as $key => $val) {
-                // TODO: Honor maxsize and depth options.
-                $pipeline->add(
-                    $this->_command('GETANNOTATION')->add(array(
-                        new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
-                        $val,
-                        new Horde_Imap_Client_Data_Format_String($key)
-                    ))
-                );
</del><ins>+        $queries = array();
+        foreach ($entries as $md_entry) {
+            list($entry, $type) = $this->_getAnnotateMoreEntry($md_entry);
+
+            if (!isset($queries[$type])) {
+                $queries[$type] = new Horde_Imap_Client_Data_Format_List();
</ins><span class="cx">             }
</span><ins>+            $queries[$type]->add(new Horde_Imap_Client_Data_Format_String($entry));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return $this->_sendCmd($pipeline)->data['metadata'];
</del><ins>+        $result = array();
+        foreach ($queries as $key => $val) {
+            // TODO: Honor maxsize and depth options.
+            $cmd = $this->_clientCommand(array(
+                'GETANNOTATION',
+                new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
+                $val,
+                new Horde_Imap_Client_Data_Format_String($key)
+            ));
+
+            $this->_sendLine($cmd);
+
+            $result = array_merge($result, $this->_temp['metadata']);
+        }
+
+        return $result;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="lines">@@ -3653,120 +3508,104 @@
</span><span class="cx">                 ));
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            $cmd = $this->_command('SETMETADATA')->add(array(
</del><ins>+            $cmd = $this->_clientCommand(array(
+                'SETMETADATA',
</ins><span class="cx">                 new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
</span><span class="cx">                 $data_elts
</span><span class="cx">             ));
</span><del>-        } else {
-            if (!$this->queryCapability('ANNOTATEMORE') &&
-                !$this->queryCapability('ANNOTATEMORE2')) {
-                throw new Horde_Imap_Client_Exception_NoSupportExtension('METADATA');
-            }
</del><span class="cx"> 
</span><del>-            $cmd = $this->_pipeline();
</del><ins>+            $this->_sendLine($cmd);
</ins><span class="cx"> 
</span><del>-            foreach ($data as $md_entry => $value) {
-                list($entry, $type) = $this->_getAnnotateMoreEntry($md_entry);
</del><ins>+            return;
+        }
</ins><span class="cx"> 
</span><del>-                $cmd->add(
-                    $this->_command('SETANNOTATION')->add(array(
-                        new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
-                        new Horde_Imap_Client_Data_Format_String($entry),
-                        new Horde_Imap_Client_Data_Format_List(array(
-                            new Horde_Imap_Client_Data_Format_String($type),
-                            new Horde_Imap_Client_Data_Format_Nstring($value)
-                        ))
-                    ))
-                );
-            }
</del><ins>+        if (!$this->queryCapability('ANNOTATEMORE') &&
+            !$this->queryCapability('ANNOTATEMORE2')) {
+            throw new Horde_Imap_Client_Exception_NoSupportExtension('METADATA');
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $this->_sendCmd($cmd);
</del><ins>+        foreach ($data as $md_entry => $value) {
+            list($entry, $type) = $this->_getAnnotateMoreEntry($md_entry);
+
+            $cmd = $this->_clientCommand(array(
+                'SETANNOTATION',
+                new Horde_Imap_Client_Data_Format_Mailbox($mailbox),
+                new Horde_Imap_Client_Data_Format_String($entry),
+                new Horde_Imap_Client_Data_Format_List(array(
+                    new Horde_Imap_Client_Data_Format_String($type),
+                    new Horde_Imap_Client_Data_Format_Nstring($value)
+                ))
+            ));
+
+            $this->_sendLine($cmd);
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Parse an ANNOTATION response (ANNOTATEMORE/ANNOTATEMORE2).
</del><ins>+     * Parse a METADATA response (RFC 5464 [4.4]).
</ins><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
</del><span class="cx">      * @param Horde_Imap_Client_Tokenize $data  The server response.
</span><span class="cx">      *
</span><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      */
</span><del>-    protected function _parseAnnotation(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
</del><ins>+    protected function _parseMetadata(Horde_Imap_Client_Tokenize $data)
</ins><span class="cx">     {
</span><del>-        // Mailbox name is in UTF7-IMAP.
-        $mbox = Horde_Imap_Client_Mailbox::get($data->next(), true);
-        $entry = $data->next();
</del><ins>+        switch ($data->current()) {
+        case 'ANNOTATION':
+            $mbox = $data->next();
+            $entry = $data->next();
</ins><span class="cx"> 
</span><del>-        // Ignore unsolicited responses.
-        if ($data->next() !== true) {
-            return;
-        }
-
-        while (($type = $data->next()) !== false) {
-            switch ($type) {
-            case 'value.priv':
-                $pipeline->data['metadata'][strval($mbox)]['/private' . $entry] = $data->next();
</del><ins>+            // Ignore unsolicited responses.
+            if ($data->next() !== true) {
</ins><span class="cx">                 break;
</span><ins>+            }
</ins><span class="cx"> 
</span><del>-            case 'value.shared':
-                $pipeline->data['metadata'][strval($mbox)]['/shared' . $entry] = $data->next();
-                break;
</del><ins>+            while (($type = $data->next()) !== false) {
+                switch ($type) {
+                case 'value.priv':
+                    $this->_temp['metadata'][$mbox]['/private' . $entry] = $data->next();
+                    break;
</ins><span class="cx"> 
</span><del>-            default:
-                throw new Horde_Imap_Client_Exception(
-                    sprintf(Horde_Imap_Client_Translation::t("Invalid METADATA value type \"%s\"."), $type),
-                    Horde_Imap_Client_Exception::METADATA_INVALID
-                );
</del><ins>+                case 'value.shared':
+                    $this->_temp['metadata'][$mbox]['/shared' . $entry] = $data->next();
+                    break;
+
+                default:
+                    throw new Horde_Imap_Client_Exception(
+                        sprintf(Horde_Imap_Client_Translation::t("Invalid METADATA value type \"%s\"."), $type),
+                        Horde_Imap_Client_Exception::METADATA_INVALID
+                    );
+                }
</ins><span class="cx">             }
</span><del>-        }
-    }
</del><ins>+            break;
</ins><span class="cx"> 
</span><del>-    /**
-     * Parse a METADATA response (RFC 5464 [4.4]).
-     *
-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
-     * @param Horde_Imap_Client_Tokenize $data  The server response.
-     *
-     * @throws Horde_Imap_Client_Exception
-     */
-    protected function _parseMetadata(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Tokenize $data
-    )
-    {
-        // Mailbox name is in UTF7-IMAP.
-        $mbox = Horde_Imap_Client_Mailbox::get($data->next(), true);
</del><ins>+        case 'METADATA':
+            $mbox = $data->next();
</ins><span class="cx"> 
</span><del>-        // Ignore unsolicited responses.
-        if ($data->next() === true) {
</del><ins>+            // Ignore unsolicited responses.
+            if ($data->next() !== true) {
+                break;
+            }
+
</ins><span class="cx">             while (($entry = $data->next()) !== false) {
</span><del>-                $pipeline->data['metadata'][strval($mbox)][$entry] = $data->next();
</del><ins>+                $this->_temp['metadata'][$mbox][$entry] = $data->next();
</ins><span class="cx">             }
</span><ins>+            break;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /* Overriden methods. */
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * @param array $opts  Options:
-     *   - decrement: (boolean) If true, decrement the message count.
-     *   - pipeline: (Horde_Imap_Client_Interaction_Pipeline) Pipeline object.
</del><ins>+     * @param boolean $decrement  If true, decrement the message count.
</ins><span class="cx">      */
</span><span class="cx">     protected function _deleteMsgs(Horde_Imap_Client_Mailbox $mailbox,
</span><span class="cx">                                    Horde_Imap_Client_Ids $ids,
</span><del>-                                   array $opts = array())
</del><ins>+                                   $decrement = false)
</ins><span class="cx">     {
</span><span class="cx">         /* If there are pending FETCH cache writes, we need to write them
</span><span class="cx">          * before the UID -> sequence number mapping changes. */
</span><del>-        if (isset($opts['pipeline'])) {
-            $this->_updateCache($opts['pipeline']->fetch);
-        }
</del><ins>+        $this->_updateCache($this->_fetch);
</ins><span class="cx"> 
</span><span class="cx">         $res = parent::_deleteMsgs($mailbox, $ids);
</span><span class="cx"> 
</span><span class="lines">@@ -3774,7 +3613,7 @@
</span><span class="cx">             $this->_temp['expunged']->add($res);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!empty($opts['decrement'])) {
</del><ins>+        if ($decrement) {
</ins><span class="cx">             $mbox_ob = $this->_mailboxOb();
</span><span class="cx">             $mbox_ob->setStatus(
</span><span class="cx">                 Horde_Imap_Client::STATUS_MESSAGES,
</span><span class="lines">@@ -3786,326 +3625,274 @@
</span><span class="cx">     /* Internal functions. */
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Sends command(s) to the IMAP server. A connection to the server must
</del><ins>+     * Perform a command on the IMAP server. A connection to the server must
</ins><span class="cx">      * have already been made.
</span><span class="cx">      *
</span><del>-     * @param mixed $cmd  Either a Command object or a Pipeline object.
</del><ins>+     * RFC 3501 allows the sending of multiple commands at once. For
+     * simplicity of implementation, we will execute commands one at a time.
+     * This allows us to easily determine data meant for a command while
+     * scanning for untagged responses unilaterally sent by the server.
+     * The only advantage of pipelining commands is to reduce the (small)
+     * amount of overhead needed to send commands. Modern IMAP servers do not
+     * meaningfully optimize response order internally, so that is not a
+     * worthwhile reason to implement pipelining. Even the IMAP gurus admit
+     * that pipelining is probably more trouble than it is worth.
</ins><span class="cx">      *
</span><del>-     * @return Horde_Imap_Client_Interaction_Pipeline  A pipeline object.
</del><ins>+     * @param Horde_Imap_Client_Data_Format_List $data  The IMAP commands to
+     *                                                  execute.
+     * @param array $opts                               Additional options:
+     *   - debug: (string) When debugging, send this string instead of the
+     *            actual command/data sent.
+     *            DEFAULT: Raw data output to debug stream.
+     *   - keep_fetch: (boolean) Don't delete fetch cache object.
+     *                 DEFAULT: false
+     *   - noliteralplus: (boolean) If true, don't use LITERAL+ extension.
+     *                    DEFAULT: false
+     *
+     * @return Horde_Imap_Client_Interaction_Server  Server object.
+     *
</ins><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      */
</span><del>-    protected function _sendCmd($cmd)
</del><ins>+    protected function _sendLine(Horde_Imap_Client_Data_Format_List $data,
+                                 array $opts = array())
</ins><span class="cx">     {
</span><del>-        $pipeline = ($cmd instanceof Horde_Imap_Client_Interaction_Command)
-            ? $this->_pipeline($cmd)
-            : $cmd;
</del><ins>+        /* Initialize internal data items at the beginning of a command. */
+        if ($data instanceof Horde_Imap_Client_Interaction_Client) {
+            $this->_fetch->clear();
+            $this->_temp['lastcmd'] = $data;
+            $this->_temp['modseqs'] = array();
+            $this->_temp['modseqs_nouid'] = array();
+        }
</ins><span class="cx"> 
</span><del>-        if (!empty($this->_cmdQueue)) {
-            /* Add commands in reverse order. */
-            foreach (array_reverse($this->_cmdQueue) as $val) {
-                $pipeline->add($val, true);
-            }
</del><ins>+        try {
+            $this->_debug->client('', false);
</ins><span class="cx"> 
</span><del>-            $this->_cmdQueue = array();
-        }
</del><ins>+            $this->_processSendList($data, $opts);
</ins><span class="cx"> 
</span><del>-        $cmd_list = array();
-
-        foreach ($pipeline as $val) {
-            if ($val->continuation) {
-                $this->_sendCmdChunk($pipeline, $cmd_list);
-                $this->_sendCmdChunk($pipeline, array($val));
-                $cmd_list = array();
-            } else {
-                $cmd_list[] = $val;
</del><ins>+            if (!empty($opts['debug'])) {
+                $this->_debug->raw($opts['debug']);
</ins><span class="cx">             }
</span><del>-        }
</del><span class="cx"> 
</span><del>-        $this->_sendCmdChunk($pipeline, $cmd_list);
-
-        /* If any FLAGS responses contain MODSEQs but not UIDs, don't
-         * cache any data and immediately close the mailbox. */
-        foreach ($pipeline->data['modseqs_nouid'] as $val) {
-            if (!$pipeline->fetch[$val]->getUid()) {
-                $this->_debug->info('Server provided FLAGS MODSEQ without providing UID.');
-                $this->close();
-                return $pipeline;
</del><ins>+            $this->_writeStream('', array('eol' => true));
+        } catch (Horde_Imap_Client_Exception $e) {
+            switch ($e->getCode()) {
+            case Horde_Imap_Client_Exception::SERVER_WRITEERROR:
+                $this->_temp['logout'] = true;
+                $this->logout();
+                break;
</ins><span class="cx">             }
</span><del>-        }
</del><span class="cx"> 
</span><del>-        /* Update HIGHESTMODSEQ value. */
-        if (!empty($pipeline->data['modseqs'])) {
-            $modseq = max($pipeline->data['modseqs']);
-            $this->_mailboxOb()->setStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ, $modseq);
-            $this->_updateModSeq($modseq);
</del><ins>+            throw $e;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        /* Update cache items. */
-        $this->_updateCache($pipeline->fetch);
</del><ins>+        while ($ob = $this->_getLine()) {
+            switch (get_class($ob)) {
+            case 'Horde_Imap_Client_Interaction_Server_Continuation':
+                break 2;
</ins><span class="cx"> 
</span><del>-        return $pipeline;
-    }
-
-    /**
-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  The pipeline
-     *                                                          object.
-     * @param array $chunk  List of commands to send.
-     *
-     * @throws Horde_Imap_Client_Exception
-     */
-    protected function _sendCmdChunk($pipeline, $chunk)
-    {
-        if (empty($chunk)) {
-            return;
-        }
-
-        $cmd_count = count($chunk);
-        $exception = null;
-
-        foreach ($chunk as $val) {
-            try {
-                $old_debug = $this->_debug->debug;
-                if (!is_null($val->debug)) {
-                    $this->_debug->raw($val->tag . ' ' . $val->debug . "\n");
-                    $this->_debug->debug = false;
</del><ins>+            case 'Horde_Imap_Client_Interaction_Server_Tagged':
+                if (empty($opts['keep_fetch'])) {
+                    $this->_fetch->clear();
</ins><span class="cx">                 }
</span><del>-                if ($this->_processCmd($pipeline, $val, $val)) {
-                    $this->_connection->write('', true);
-                } else {
-                    $cmd_count = 0;
-                }
-                $this->_debug->debug = $old_debug;
-            } catch (Horde_Imap_Client_Exception $e) {
-                $this->_debug->debug = $old_debug;
-
-                switch ($e->getCode()) {
-                case Horde_Imap_Client_Exception::SERVER_WRITEERROR:
-                    $this->_temp['logout'] = true;
-                    $this->logout();
-                    break;
-                }
-
-                throw $e;
</del><ins>+                break 2;
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        while ($cmd_count) {
-            try {
-                if ($this->_getLine($pipeline) instanceof Horde_Imap_Client_Interaction_Server_Tagged) {
-                    --$cmd_count;
-                }
-            } catch (Horde_Imap_Client_Exception $e) {
-                switch ($e->getCode()) {
-                case $e::DISCONNECT:
-                    $this->_temp['logout'] = true;
-                    // Fall-through
-
-                case $e::SERVER_READERROR:
-                    $this->logout();
-                    throw $e;
-                }
-
-                // Catch and store exception; don't throw until all input
-                // is read. (For now, only store first exception.)
-                if (is_null($exception)) {
-                    $exception = $e;
-                }
-
-                if (($e instanceof Horde_Imap_Client_Exception_ServerResponse) &&
-                    $e->command) {
-                    --$cmd_count;
-                }
-            }
-        }
-
-        if (!is_null($exception)) {
-            throw $exception;
-        }
</del><ins>+        return $ob;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Process/send a command to the remote server.
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline The pipeline
-     *                                                         object.
-     * @param Horde_Imap_Client_Interaction_Command $cmd  The master command.
-     * @param Horde_Imap_Client_Data_Format_List $data    Commands to send.
</del><ins>+     * @param Horde_Imap_Client_Data_Format_List $data  Commands to send.
+     * @param array $opts                               Options:
+     *   - debug: (boolean) Whether debug info should be output.
+     *   - noliteralplus: (boolean) If true, don't use LITERAL+ extension.
</ins><span class="cx">      *
</span><del>-     * @return boolean  True if EOL needed to finish command.
</del><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      * @throws Horde_Imap_Client_Exception_NoSupport
</span><span class="cx">      */
</span><del>-    protected function _processCmd($pipeline, $cmd, $data)
</del><ins>+    protected function _processSendList($data, $opts)
</ins><span class="cx">     {
</span><ins>+        $s_opts = array('nodebug' => !empty($opts['debug']));
+
</ins><span class="cx">         foreach ($data as $key => $val) {
</span><del>-            if ($val instanceof Horde_Imap_Client_Interaction_Command_Continuation) {
-                $this->_connection->write('', true);
-
-                /* Check for optional continuation responses when the command
-                 * has already finished. */
-                if (!$cmd_continuation = $this->_processCmdContinuation($pipeline, $val->optional)) {
-                    return false;
-                }
-
-                $this->_processCmd(
-                    $pipeline,
-                    $cmd,
-                    $val->getCommands($cmd_continuation)
-                );
-                continue;
-            }
-
</del><span class="cx">             if ($key) {
</span><del>-                $this->_connection->write(' ');
</del><ins>+                $this->_writeStream(' ', $s_opts);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             if ($val instanceof Horde_Imap_Client_Data_Format_List) {
</span><del>-                $this->_connection->write('(');
-                $this->_processCmd($pipeline, $cmd, $val);
-                $this->_connection->write(')');
-            } elseif (($val instanceof Horde_Imap_Client_Data_Format_String) &&
-                      $val->literal()) {
-                /* RFC 3516/4466: Send literal8 if we have binary data. */
-                if ($cmd->literal8 &&
-                    $val->binary() &&
-                    $this->queryCapability('BINARY')) {
-                    $binary = true;
-                    $this->_connection->write('~');
-                } else {
-                    $binary = false;
-                }
</del><ins>+                $this->_writeStream('(', $s_opts);
+                $this->_processSendList($val, $opts);
+                $this->_writeStream(')', $s_opts);
+            } elseif ($val instanceof Horde_Imap_Client_Data_Format_String) {
+                if ($val->literal()) {
+                    /* RFC 3516/4466: Send literal8 if we have binary data. */
+                    if ($val->binary() && $this->queryCapability('BINARY')) {
+                        $binary = true;
+                        $literal = '~';
+                    } else {
+                        $binary = false;
+                        $literal = '';
+                    }
</ins><span class="cx"> 
</span><del>-                $literal_len = $val->length();
-                $this->_connection->write('{' . $literal_len);
</del><ins>+                    $literal_len = $val->length();
+                    $literal .= '{' . $literal_len;
</ins><span class="cx"> 
</span><del>-                /* RFC 2088 - If LITERAL+ is available, saves a roundtrip from
-                 * the server. */
-                if ($cmd->literalplus && $this->queryCapability('LITERAL+')) {
-                    $this->_connection->write('+}', true);
</del><ins>+                    /* RFC 2088 - If LITERAL+ is available, saves a roundtrip
+                     * from the server. */
+                    if (empty($opts['noliteralplus']) &&
+                        $this->queryCapability('LITERAL+')) {
+                        $this->_writeStream($literal . "+}", array_merge($s_opts, array(
+                            'eol' => true
+                        )));
+                    } else {
+                        $this->_writeStream($literal . "}", array_merge($s_opts, array(
+                            'eol' => true
+                        )));
+
+                        $ob = $this->_getLine();
+                        if (!($ob instanceof Horde_Imap_Client_Interaction_Server_Continuation)) {
+                            $this->_debug->info("ERROR: Unexpected response from server while waiting for a continuation request.");
+                            $e = new Horde_Imap_Client_Exception(
+                                Horde_Imap_Client_Translation::t("Error when communicating with the mail server."),
+                                Horde_Imap_Client_Exception::SERVER_READERROR
+                            );
+                            $e->details = strval($ob);
+                            throw $e;
+                        }
+                    }
+
+                    $this->_writeStream($val->getStream()->stream, array_merge($s_opts, array(
+                        'binary' => $binary,
+                        'literal' => $literal_len
+                    )));
</ins><span class="cx">                 } else {
</span><del>-                    $this->_connection->write('}', true);
-                    $this->_processCmdContinuation($pipeline);
</del><ins>+                    $this->_writeStream($val->escapeStream(), $s_opts);
</ins><span class="cx">                 }
</span><del>-
-                $this->_connection->writeLiteral($val->getStream(), $literal_len, $binary);
</del><span class="cx">             } else {
</span><del>-                $this->_connection->write($val->escape());
</del><ins>+                $this->_writeStream($val->escape(), $s_opts);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><del>-
-        return true;
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Process a command continuation response.
</del><ins>+     * Shortcut to creating a new IMAP client command object.
</ins><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  The pipeline
-     *                                                          object.
-     * @param boolean $noexception                              Don't throw
-     *                                                          exception if
-     *                                                          continuation
-     *                                                          does not occur.
-     *
-     * @return mixed  A Horde_Imap_Client_Interaction_Server_Continuation
-     *                object or false.
-     *
-     * @throws Horde_Imap_Client_Exception
</del><ins>+     * @param mixed $cmd  The IMAP command(s) to add.
</ins><span class="cx">      */
</span><del>-    protected function _processCmdContinuation($pipeline, $noexception = false)
</del><ins>+    protected function _clientCommand($cmd = null)
</ins><span class="cx">     {
</span><del>-        do {
-            $ob = $this->_getLine($pipeline);
-        } while ($ob instanceof Horde_Imap_Client_Interaction_Server_Untagged);
-
-        if ($ob instanceof Horde_Imap_Client_Interaction_Server_Continuation) {
-            return $ob;
-        } elseif ($noexception) {
-            return false;
</del><ins>+        $ob = new Horde_Imap_Client_Interaction_Client(++$this->_tag);
+        if (!is_null($cmd)) {
+            $ob->add($cmd);
</ins><span class="cx">         }
</span><del>-
-        $this->_debug->info("ERROR: Unexpected response from server while waiting for a continuation request.");
-        $e = new Horde_Imap_Client_Exception(
-            Horde_Imap_Client_Translation::t("Error when communicating with the mail server."),
-            Horde_Imap_Client_Exception::SERVER_READERROR
-        );
-        $e->details = strval($ob);
-
-        throw $e;
</del><ins>+        return $ob;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><del>-     * Shortcut to creating a new IMAP client command object.
</del><ins>+     * Writes data to the IMAP output stream and handles debug output.
</ins><span class="cx">      *
</span><del>-     * @param string $cmd  The IMAP command.
</del><ins>+     * @param mixed $data  Either a string or stream resource.
+     * @param array $opts  Additional options:
+     *   - binary: (boolean) If true, the literal data is binary.
+     *   - eol: (boolean) If true, output EOL.
+     *   - literal: (integer) If set, the length of the literal data.
+     *   - nodebug: (boolean) If true, don't output debug data.
</ins><span class="cx">      *
</span><del>-     * @return Horde_Imap_Client_Interaction_Command  A command object.
</del><ins>+     * @throws Horde_Imap_Client_Exception
</ins><span class="cx">      */
</span><del>-    protected function _command($cmd)
</del><ins>+    protected function _writeStream($data, array $opts = array())
</ins><span class="cx">     {
</span><del>-        return new Horde_Imap_Client_Interaction_Command($cmd, ++$this->_tag);
-    }
</del><ins>+        $write_error = false;
</ins><span class="cx"> 
</span><del>-    /**
-     * Shortcut to creating a new pipeline object.
-     *
-     * @param Horde_Imap_Client_Interaction_Command $cmd  An IMAP command to
-     *                                                    add.
-     *
-     * @return Horde_Imap_Client_Interaction_Pipeline  A pipeline object.
-     */
-    protected function _pipeline($cmd = null)
-    {
-        if (!isset($this->_temp['fetchob'])) {
-            $this->_temp['fetchob'] = new Horde_Imap_Client_Fetch_Results(
-                $this->_fetchDataClass,
-                Horde_Imap_Client_Fetch_Results::SEQUENCE
</del><ins>+        if (is_resource($data)) {
+            rewind($data);
+            while (!feof($data)) {
+                if (fwrite($this->_stream, fread($data, 8192)) === false) {
+                    $write_error = true;
+                    break;
+                }
+            }
+        } elseif (fwrite($this->_stream, $data . (empty($opts['eol']) ? '' : "\r\n")) === false) {
+            $write_error = true;
+        }
+
+        if ($write_error) {
+            throw new Horde_Imap_Client_Exception(
+                Horde_Imap_Client_Translation::t("Server write error."),
+                Horde_Imap_Client_Exception::SERVER_WRITEERROR
</ins><span class="cx">             );
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        $ob = new Horde_Imap_Client_Interaction_Pipeline(
-            clone $this->_temp['fetchob']
-        );
</del><ins>+        if (!empty($opts['nodebug']) || !$this->_debug->debug) {
+            return;
+        }
</ins><span class="cx"> 
</span><del>-        if (!is_null($cmd)) {
-            $ob->add($cmd);
</del><ins>+        if (isset($opts['literal']) &&
+            empty($this->_params['debug_literal'])) {
+            $this->_debug->client('[' . (empty($opts['binary']) ? 'LITERAL' : 'BINARY') . ' DATA: ' . $opts['literal'] . ' bytes]');
+        } elseif (is_resource($data)) {
+            rewind($data);
+            while (!feof($data)) {
+                $this->_debug->raw(fread($data, 8192));
+            }
+        } else {
+            $this->_debug->raw($data . (empty($opts['eol']) ? '' : "\n"));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return $ob;
</del><ins>+        if (isset($opts['literal'])) {
+            $this->_debug->client('', false);
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><span class="cx">      * Gets data from the IMAP server stream and parses it.
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
-     *
</del><span class="cx">      * @return Horde_Imap_Client_Interaction_Server  Server object.
</span><span class="cx">      *
</span><span class="cx">      * @throws Horde_Imap_Client_Exception
</span><span class="cx">      */
</span><del>-    protected function _getLine(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline
-    )
</del><ins>+    protected function _getLine()
</ins><span class="cx">     {
</span><del>-        $server = Horde_Imap_Client_Interaction_Server::create(
-            $this->_connection->read()
-        );
</del><ins>+        $server = Horde_Imap_Client_Interaction_Server::create($this->_readStream());
</ins><span class="cx"> 
</span><span class="cx">         switch (get_class($server)) {
</span><span class="cx">         case 'Horde_Imap_Client_Interaction_Server_Continuation':
</span><del>-            $this->_responseCode($pipeline, $server);
</del><ins>+            $this->_responseCode($server);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'Horde_Imap_Client_Interaction_Server_Tagged':
</span><del>-            $pipeline->complete($server);
-            $this->_responseCode($pipeline, $server);
</del><ins>+            $this->_responseCode($server);
+
+            /* If any FLAGS responses contain MODSEQs but not UIDs, don't
+             * cache any data and immediately close the mailbox. */
+            foreach ($this->_temp['modseqs_nouid'] as $val) {
+                if (!$this->_fetch[$val]->getUid()) {
+                    $this->_debug->info('Server provided FLAGS MODSEQ without providing UID.');
+                    $data = clone $this->_fetch;
+                    $this->close();
+                    $this->_fetch = $data;
+                    break 2;
+                }
+            }
+
+            /* Update HIGHESTMODSEQ value. */
+            if (!empty($this->_temp['modseqs'])) {
+                $modseq = max($this->_temp['modseqs']);
+                $this->_mailboxOb()->setStatus(Horde_Imap_Client::STATUS_HIGHESTMODSEQ, $modseq);
+                $this->_updateModSeq($modseq);
+            }
+
+            /* Update cache items. */
+            $this->_updateCache($this->_fetch);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'Horde_Imap_Client_Interaction_Server_Untagged':
</span><span class="cx">             if (is_null($server->status)) {
</span><del>-                $this->_serverResponse($pipeline, $server);
</del><ins>+                $this->_serverResponse($server);
</ins><span class="cx">             } else {
</span><del>-                $this->_responseCode($pipeline, $server);
</del><ins>+                $this->_responseCode($server);
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -4113,13 +3900,18 @@
</span><span class="cx">         switch ($server->status) {
</span><span class="cx">         case $server::BAD:
</span><span class="cx">             /* A tagged BAD response indicates that the tagged command caused
</span><del>-             * the error. This information is unknown if untagged (RFC 3501
-             * [7.1.3]). */
</del><ins>+             * the error. This information is unknown if untagged. (RFC 3501
+             * [7.1.3]) */
+            $cmd = ($server instanceof Horde_Imap_Client_Interaction_Server_Tagged)
+                ? $this->_temp['lastcmd']->getCommand()
+                : null;
+
</ins><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("IMAP error reported by server."),
</span><span class="cx">                 0,
</span><del>-                $server,
-                $pipeline
</del><ins>+                $server->status,
+                strval($server->token),
+                $cmd
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case $server::BYE:
</span><span class="lines">@@ -4127,6 +3919,8 @@
</span><span class="cx">              * be treated like a regular command: a client MUST process the
</span><span class="cx">              * entire command until logging out (RFC 3501 [3.4; 7.1.5]). */
</span><span class="cx">             if (empty($this->_temp['logout'])) {
</span><ins>+                $this->_temp['logout'] = true;
+                $this->logout();
</ins><span class="cx">                 $e = new Horde_Imap_Client_Exception(
</span><span class="cx">                     Horde_Imap_Client_Translation::t("IMAP Server closed the connection."),
</span><span class="cx">                     Horde_Imap_Client_Exception::DISCONNECT
</span><span class="lines">@@ -4140,14 +3934,15 @@
</span><span class="cx">             /* An untagged NO response indicates a warning; ignore and assume
</span><span class="cx">              * that it also included response text code that is handled
</span><span class="cx">              * elsewhere. Throw exception if tagged; command handlers can
</span><del>-             * catch this if able to workaround this issue (RFC 3501
-             * [7.1.2]). */
</del><ins>+             * catch this if able to workaround this issue. (RFC 3501
+             * [7.1.2]) */
</ins><span class="cx">             if ($server instanceof Horde_Imap_Client_Interaction_Server_Tagged) {
</span><span class="cx">                 throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                     Horde_Imap_Client_Translation::t("IMAP error reported by server."),
</span><span class="cx">                     0,
</span><del>-                    $server,
-                    $pipeline
</del><ins>+                    $server->status,
+                    strval($server->token),
+                    $this->_temp['lastcmd']->getCommand()
</ins><span class="cx">                 );
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -4161,17 +3956,107 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     /**
</span><ins>+     * Read data from incoming IMAP stream.
+     *
+     * @return Horde_Imap_Client_Tokenize  The tokenized data.
+     *
+     * @throws Horde_Imap_Client_Exception
+     */
+    protected function _readStream()
+    {
+        $got_data = false;
+        $literal_len = null;
+        $token = new Horde_Imap_Client_Tokenize();
+
+        do {
+            if (feof($this->_stream)) {
+                $this->_temp['logout'] = true;
+                $this->logout();
+                $this->_debug->info("ERROR: Server closed the connection.");
+                throw new Horde_Imap_Client_Exception(
+                    Horde_Imap_Client_Translation::t("Mail server closed the connection unexpectedly."),
+                    Horde_Imap_Client_Exception::DISCONNECT
+                );
+            }
+
+            if (is_null($literal_len)) {
+                $this->_debug->server('', false);
+
+                while (($in = fgets($this->_stream)) !== false) {
+                    $got_data = true;
+
+                    if (substr($in, -1) == "\n") {
+                        $in = rtrim($in);
+                        $this->_debug->raw($in . "\n");
+                        $token->add($in);
+                        break;
+                    }
+
+                    $this->_debug->raw($in);
+                    $token->add($in);
+                }
+
+                /* Check for literal data. */
+                if (!is_null($len = $token->getLiteralLength())) {
+                    if ($len['length']) {
+                        $binary = $len['binary'];
+                        $literal_len = $len['length'];
+                    } else {
+                        // Skip 0-length literal data.
+                        $literal_len = null;
+                    }
+                    continue;
+                }
+                break;
+            }
+
+            $debug_literal = ($this->_debug->debug &&
+                              !empty($this->_params['debug_literal']));
+            $old_len = $literal_len;
+
+            $this->_debug->server('', false);
+
+            while ($literal_len && !feof($this->_stream)) {
+                $in = fread($this->_stream, min($literal_len, 8192));
+                $token->add($in);
+                if ($debug_literal) {
+                    $this->_debug->raw($in);
+                }
+
+                $got_data = true;
+
+                $in_len = strlen($in);
+                if ($in_len > $literal_len) {
+                    break;
+                }
+                $literal_len -= $in_len;
+            }
+
+            $literal_len = null;
+
+            if (!$debug_literal) {
+                $this->_debug->raw('[' . ($binary ? 'BINARY' : 'LITERAL') . ' DATA: ' . $old_len . ' bytes]' . "\n");
+            }
+        } while (true);
+
+        if (!$got_data) {
+            $this->_debug->info("ERROR: IMAP read/timeout error.");
+            $this->logout();
+            throw new Horde_Imap_Client_Exception(
+                Horde_Imap_Client_Translation::t("Error when communicating with the mail server."),
+                Horde_Imap_Client_Exception::SERVER_READERROR
+            );
+        }
+
+        return $token;
+    }
+
+    /**
</ins><span class="cx">      * Handle untagged server responses (see RFC 3501 [2.2.2]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
-     * @param Horde_Imap_Client_Interaction_Server $ob          Server
-     *                                                          response.
</del><ins>+     * @param Horde_Imap_Client_Interaction_Server $ob  Server response.
</ins><span class="cx">      */
</span><del>-    protected function _serverResponse(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Interaction_Server $ob
-    )
</del><ins>+    protected function _serverResponse(Horde_Imap_Client_Interaction_Server $ob)
</ins><span class="cx">     {
</span><span class="cx">         $token = $ob->token;
</span><span class="cx"> 
</span><span class="lines">@@ -4179,12 +4064,12 @@
</span><span class="cx">          * line. */
</span><span class="cx">         switch ($first = strtoupper($token->current())) {
</span><span class="cx">         case 'CAPABILITY':
</span><del>-            $this->_parseCapability($pipeline, $token->flushIterator());
</del><ins>+            $this->_parseCapability($token->flushIterator());
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'LIST':
</span><span class="cx">         case 'LSUB':
</span><del>-            $this->_parseList($pipeline, $token);
</del><ins>+            $this->_parseList($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'STATUS':
</span><span class="lines">@@ -4195,12 +4080,12 @@
</span><span class="cx">         case 'SEARCH':
</span><span class="cx">         case 'SORT':
</span><span class="cx">             // Parse a SEARCH/SORT response (RFC 3501 [7.2.5] & RFC 5256 [4]).
</span><del>-            $this->_parseSearch($pipeline, $token->flushIterator());
</del><ins>+            $this->_parseSearch($token->flushIterator());
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'ESEARCH':
</span><span class="cx">             // Parse an ESEARCH response (RFC 4466 [2.6.2]).
</span><del>-            $this->_parseEsearch($pipeline, $token);
</del><ins>+            $this->_parseEsearch($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'FLAGS':
</span><span class="lines">@@ -4209,7 +4094,7 @@
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'QUOTA':
</span><del>-            $this->_parseQuota($pipeline, $token);
</del><ins>+            $this->_parseQuota($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'QUOTAROOT':
</span><span class="lines">@@ -4218,28 +4103,28 @@
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'NAMESPACE':
</span><del>-            $this->_parseNamespace($pipeline, $token);
</del><ins>+            $this->_parseNamespace($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'THREAD':
</span><del>-            $this->_parseThread($pipeline, $token);
</del><ins>+            $this->_parseThread($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'ACL':
</span><del>-            $this->_parseACL($pipeline, $token);
</del><ins>+            $this->_parseACL($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'LISTRIGHTS':
</span><del>-            $this->_parseListRights($pipeline, $token);
</del><ins>+            $this->_parseListRights($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'MYRIGHTS':
</span><del>-            $this->_parseMyRights($pipeline, $token);
</del><ins>+            $this->_parseMyRights($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'ID':
</span><span class="cx">             // ID extension (RFC 2971)
</span><del>-            $this->_parseID($pipeline, $token);
</del><ins>+            $this->_parseID($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'ENABLED':
</span><span class="lines">@@ -4254,22 +4139,18 @@
</span><span class="cx"> 
</span><span class="cx">         case 'COMPARATOR':
</span><span class="cx">             // I18NLEVEL=2 extension (RFC 5255 [4.7])
</span><del>-            $this->_parseComparator($pipeline, $token);
</del><ins>+            $this->_parseComparator($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'VANISHED':
</span><span class="cx">             // QRESYNC extension (RFC 5162 [3.6])
</span><del>-            $this->_parseVanished($pipeline, $token);
</del><ins>+            $this->_parseVanished($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'ANNOTATION':
</span><del>-            // Parse an ANNOTATION response.
-            $this->_parseAnnotation($pipeline, $token);
-            break;
-
</del><span class="cx">         case 'METADATA':
</span><del>-            // Parse a METADATA response.
-            $this->_parseMetadata($pipeline, $token);
</del><ins>+            // Parse a ANNOTATEMORE/METADATA response.
+            $this->_parseMetadata($token);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         default:
</span><span class="lines">@@ -4295,16 +4176,13 @@
</span><span class="cx"> 
</span><span class="cx">             case 'EXPUNGE':
</span><span class="cx">                 // EXPUNGE response - RFC 3501 [7.4.1]
</span><del>-                $this->_deleteMsgs($this->_selected, $this->getIdsOb($first, true), array(
-                    'decrement' => true,
-                    'pipeline' => $pipeline
-                ));
-                $pipeline->data['expunge_seen'] = true;
</del><ins>+                $this->_deleteMsgs($this->_selected, $this->getIdsOb($first, true), true);
+                $this->_temp['expunge_seen'] = true;
</ins><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             case 'FETCH':
</span><span class="cx">                 // FETCH response - RFC 3501 [7.4.2]
</span><del>-                $this->_parseFetch($pipeline, $first, $token);
</del><ins>+                $this->_parseFetch($first, $token);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="lines">@@ -4314,16 +4192,11 @@
</span><span class="cx">     /**
</span><span class="cx">      * Handle status responses (see RFC 3501 [7.1]).
</span><span class="cx">      *
</span><del>-     * @param Horde_Imap_Client_Interaction_Pipeline $pipeline  Pipeline
-     *                                                          object.
-     * @param Horde_Imap_Client_Interaction_Server $ob          Server object.
</del><ins>+     * @param Horde_Imap_Client_Interaction_Server $ob  Server object.
</ins><span class="cx">      *
</span><span class="cx">      * @throws Horde_Imap_Client_Exception_ServerResponse
</span><span class="cx">      */
</span><del>-    protected function _responseCode(
-        Horde_Imap_Client_Interaction_Pipeline $pipeline,
-        Horde_Imap_Client_Interaction_Server $ob
-    )
</del><ins>+    protected function _responseCode(Horde_Imap_Client_Interaction_Server $ob)
</ins><span class="cx">     {
</span><span class="cx">         if (is_null($ob->responseCode)) {
</span><span class="cx">             return;
</span><span class="lines">@@ -4358,12 +4231,12 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("Charset used in search query is not supported on the mail server."),
</span><span class="cx">                 Horde_Imap_Client_Exception::BADCHARSET,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'CAPABILITY':
</span><del>-            $this->_parseCapability($pipeline, $rc->data);
</del><ins>+            $this->_parseCapability($rc->data);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'PARSE':
</span><span class="lines">@@ -4374,8 +4247,8 @@
</span><span class="cx">                 throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                     sprintf(Horde_Imap_Client_Translation::t("The mail server was unable to parse the contents of the mail message: %s"), strval($ob->token)),
</span><span class="cx">                     Horde_Imap_Client_Exception::PARSEERROR,
</span><del>-                    $ob,
-                    $pipeline
</del><ins>+                    $ob->status,
+                    strval($ob->token)
</ins><span class="cx">                 );
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="lines">@@ -4390,7 +4263,7 @@
</span><span class="cx"> 
</span><span class="cx">         case 'TRYCREATE':
</span><span class="cx">             // RFC 3501 [7.1]
</span><del>-            $pipeline->data['trycreate'] = true;
</del><ins>+            $this->_temp['trycreate'] = true;
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'PERMANENTFLAGS':
</span><span class="lines">@@ -4413,7 +4286,7 @@
</span><span class="cx"> 
</span><span class="cx">         case 'REFERRAL':
</span><span class="cx">             // Defined by RFC 2221
</span><del>-            $pipeline->data['referral'] = new Horde_Imap_Client_Url($rc->data[0]);
</del><ins>+            $this->_temp['referral'] = new Horde_Imap_Client_Url($rc->data[0]);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'UNKNOWN-CTE':
</span><span class="lines">@@ -4421,20 +4294,20 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("The mail server was unable to parse the contents of the mail message."),
</span><span class="cx">                 Horde_Imap_Client_Exception::UNKNOWNCTE,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'APPENDUID':
</span><span class="cx">             // Defined by RFC 4315
</span><span class="cx">             // APPENDUID: [0] = UIDVALIDITY, [1] = UID(s)
</span><del>-            $pipeline->data['appenduid'] = $this->getIdsOb($rc->data[1]);
</del><ins>+            $this->_temp['appenduid'] = $this->getIdsOb($rc->data[1]);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'COPYUID':
</span><span class="cx">             // Defined by RFC 4315
</span><span class="cx">             // COPYUID: [0] = UIDVALIDITY, [1] = UIDFROM, [2] = UIDTO
</span><del>-            $pipeline->data['copyuid'] = array_combine(
</del><ins>+            $this->_temp['copyuid'] = array_combine(
</ins><span class="cx">                 $this->getIdsOb($rc->data[1])->ids,
</span><span class="cx">                 $this->getIdsOb($rc->data[2])->ids
</span><span class="cx">             );
</span><span class="lines">@@ -4442,7 +4315,7 @@
</span><span class="cx">             /* Use UIDPLUS information to move cached data to new mailbox (see
</span><span class="cx">              * RFC 4549 [4.2.2.1]). Need to move now, because a MOVE might
</span><span class="cx">              * EXPUNGE immediately afterwards. */
</span><del>-            $this->_moveCache($pipeline->data['copydest'], $pipeline->data['copyuid'], $rc->data[0]);
</del><ins>+            $this->_moveCache($this->_temp['copydest'], $this->_temp['copyuid'], $rc->data[0]);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'UIDNOTSTICKY':
</span><span class="lines">@@ -4455,8 +4328,8 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("Could not save message on server."),
</span><span class="cx">                 Horde_Imap_Client_Exception::CATENATE_BADURL,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'TOOBIG':
</span><span class="lines">@@ -4464,44 +4337,44 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("Could not save message data because it is too large."),
</span><span class="cx">                 Horde_Imap_Client_Exception::CATENATE_TOOBIG,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'HIGHESTMODSEQ':
</span><span class="cx">             // Defined by RFC 4551 [3.1.1]
</span><del>-            $pipeline->data['modseqs'][] = $rc->data[0];
</del><ins>+            $this->_temp['modseqs'][] = $rc->data[0];
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'NOMODSEQ':
</span><span class="cx">             // Defined by RFC 4551 [3.1.2]
</span><del>-            $pipeline->data['modseqs'][] = 0;
</del><ins>+            $this->_temp['modseqs'][] = 0;
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'MODIFIED':
</span><span class="cx">             // Defined by RFC 4551 [3.2]
</span><del>-            $pipeline->data['modified']->add($rc->data[0]);
</del><ins>+            $this->_temp['modified']->add($rc->data[0]);
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'CLOSED':
</span><span class="cx">             // Defined by RFC 5162 [3.7]
</span><del>-            if (isset($pipeline->data['qresyncmbox'])) {
</del><ins>+            if (isset($this->_temp['qresyncmbox'])) {
</ins><span class="cx">                 /* If there is any pending FETCH cache entries, flush them
</span><span class="cx">                  * now before changing mailboxes. */
</span><del>-                $this->_updateCache($pipeline->fetch);
-                $pipeline->fetch->clear();
</del><ins>+                $this->_updateCache($this->_fetch);
+                $this->_fetch->clear();
</ins><span class="cx"> 
</span><span class="cx">                 $this->_changeSelected(
</span><del>-                    $pipeline->data['qresyncmbox'][0],
-                    $pipeline->data['qresyncmbox'][1]
</del><ins>+                    $this->_temp['qresyncmbox'][0],
+                    $this->_temp['qresyncmbox'][1]
</ins><span class="cx">                 );
</span><del>-                unset($pipeline->data['qresyncmbox']);
</del><ins>+                unset($this->_temp['qresyncmbox']);
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'NOTSAVED':
</span><span class="cx">             // Defined by RFC 5182 [2.5]
</span><del>-            $pipeline->data['searchnotsaved'] = true;
</del><ins>+            $this->_temp['searchnotsaved'] = true;
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'BADCOMPARATOR':
</span><span class="lines">@@ -4509,8 +4382,8 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("The comparison algorithm was not recognized by the server."),
</span><span class="cx">                 Horde_Imap_Client_Exception::BADCOMPARATOR,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'METADATA':
</span><span class="lines">@@ -4519,7 +4392,7 @@
</span><span class="cx">             switch ($md[0]) {
</span><span class="cx">             case 'LONGENTRIES':
</span><span class="cx">                 // Defined by RFC 5464 [4.2.1]
</span><del>-                $pipeline->data['metadata']['*longentries'] = intval($md[1]);
</del><ins>+                $this->_temp['metadata']['*longentries'] = intval($md[1]);
</ins><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             case 'MAXSIZE':
</span><span class="lines">@@ -4527,8 +4400,8 @@
</span><span class="cx">                 throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                     Horde_Imap_Client_Translation::t("The metadata item could not be saved because it is too large."),
</span><span class="cx">                     Horde_Imap_Client_Exception::METADATA_MAXSIZE,
</span><del>-                    $ob,
-                    $pipeline
</del><ins>+                    $ob->status,
+                    intval($md[1])
</ins><span class="cx">                 );
</span><span class="cx"> 
</span><span class="cx">             case 'NOPRIVATE':
</span><span class="lines">@@ -4536,8 +4409,8 @@
</span><span class="cx">                 throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                     Horde_Imap_Client_Translation::t("The metadata item could not be saved because the server does not support private annotations."),
</span><span class="cx">                     Horde_Imap_Client_Exception::METADATA_NOPRIVATE,
</span><del>-                    $ob,
-                    $pipeline
</del><ins>+                    $ob->status,
+                    strval($ob->token)
</ins><span class="cx">                 );
</span><span class="cx"> 
</span><span class="cx">             case 'TOOMANY':
</span><span class="lines">@@ -4545,15 +4418,15 @@
</span><span class="cx">                 throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                     Horde_Imap_Client_Translation::t("The metadata item could not be saved because the maximum number of annotations has been exceeded."),
</span><span class="cx">                     Horde_Imap_Client_Exception::METADATA_TOOMANY,
</span><del>-                    $ob,
-                    $pipeline
</del><ins>+                    $ob->status,
+                    strval($ob->token)
</ins><span class="cx">                 );
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'UNAVAILABLE':
</span><span class="cx">             // Defined by RFC 5530 [3]
</span><del>-            $pipeline->data['loginerr'] = new Horde_Imap_Client_Exception(
</del><ins>+            $this->_temp['loginerr'] = new Horde_Imap_Client_Exception(
</ins><span class="cx">                 Horde_Imap_Client_Translation::t("Remote server is temporarily unavailable."),
</span><span class="cx">                 Horde_Imap_Client_Exception::LOGIN_UNAVAILABLE
</span><span class="cx">             );
</span><span class="lines">@@ -4561,7 +4434,7 @@
</span><span class="cx"> 
</span><span class="cx">         case 'AUTHENTICATIONFAILED':
</span><span class="cx">             // Defined by RFC 5530 [3]
</span><del>-            $pipeline->data['loginerr'] = new Horde_Imap_Client_Exception(
</del><ins>+            $this->_temp['loginerr'] = new Horde_Imap_Client_Exception(
</ins><span class="cx">                 Horde_Imap_Client_Translation::t("Authentication failed."),
</span><span class="cx">                 Horde_Imap_Client_Exception::LOGIN_AUTHENTICATIONFAILED
</span><span class="cx">             );
</span><span class="lines">@@ -4569,7 +4442,7 @@
</span><span class="cx"> 
</span><span class="cx">         case 'AUTHORIZATIONFAILED':
</span><span class="cx">             // Defined by RFC 5530 [3]
</span><del>-            $pipeline->data['loginerr'] = new Horde_Imap_Client_Exception(
</del><ins>+            $this->_temp['loginerr'] = new Horde_Imap_Client_Exception(
</ins><span class="cx">                 Horde_Imap_Client_Translation::t("Authentication was successful, but authorization failed."),
</span><span class="cx">                 Horde_Imap_Client_Exception::LOGIN_AUTHORIZATIONFAILED
</span><span class="cx">             );
</span><span class="lines">@@ -4577,7 +4450,7 @@
</span><span class="cx"> 
</span><span class="cx">         case 'EXPIRED':
</span><span class="cx">             // Defined by RFC 5530 [3]
</span><del>-            $pipeline->data['loginerr'] = new Horde_Imap_Client_Exception(
</del><ins>+            $this->_temp['loginerr'] = new Horde_Imap_Client_Exception(
</ins><span class="cx">                 Horde_Imap_Client_Translation::t("Authentication credentials have expired."),
</span><span class="cx">                 Horde_Imap_Client_Exception::LOGIN_EXPIRED
</span><span class="cx">             );
</span><span class="lines">@@ -4585,7 +4458,7 @@
</span><span class="cx"> 
</span><span class="cx">         case 'PRIVACYREQUIRED':
</span><span class="cx">             // Defined by RFC 5530 [3]
</span><del>-            $pipeline->data['loginerr'] = new Horde_Imap_Client_Exception(
</del><ins>+            $this->_temp['loginerr'] = new Horde_Imap_Client_Exception(
</ins><span class="cx">                 Horde_Imap_Client_Translation::t("Operation failed due to a lack of a secure connection."),
</span><span class="cx">                 Horde_Imap_Client_Exception::LOGIN_PRIVACYREQUIRED
</span><span class="cx">             );
</span><span class="lines">@@ -4596,8 +4469,8 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("You do not have adequate permissions to carry out this operation."),
</span><span class="cx">                 Horde_Imap_Client_Exception::NOPERM,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'INUSE':
</span><span class="lines">@@ -4605,13 +4478,13 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("There was a temporary issue when attempting this operation. Please try again later."),
</span><span class="cx">                 Horde_Imap_Client_Exception::INUSE,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'EXPUNGEISSUED':
</span><span class="cx">             // Defined by RFC 5530 [3]
</span><del>-            $pipeline->data['expungeissued'] = true;
</del><ins>+            $this->_temp['expungeissued'] = true;
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case 'CORRUPTION':
</span><span class="lines">@@ -4619,8 +4492,8 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("The mail server is reporting corrupt data in your mailbox."),
</span><span class="cx">                 Horde_Imap_Client_Exception::CORRUPTION,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'SERVERBUG':
</span><span class="lines">@@ -4635,8 +4508,8 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("The mail server has denied the request."),
</span><span class="cx">                 Horde_Imap_Client_Exception::LIMIT,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'OVERQUOTA':
</span><span class="lines">@@ -4644,8 +4517,8 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("The operation failed because the quota has been exceeded on the mail server."),
</span><span class="cx">                 Horde_Imap_Client_Exception::OVERQUOTA,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'ALREADYEXISTS':
</span><span class="lines">@@ -4653,8 +4526,8 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("The object could not be created because it already exists."),
</span><span class="cx">                 Horde_Imap_Client_Exception::ALREADYEXISTS,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'NONEXISTENT':
</span><span class="lines">@@ -4662,8 +4535,8 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("The object could not be deleted because it does not exist."),
</span><span class="cx">                 Horde_Imap_Client_Exception::NONEXISTENT,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><span class="cx">         case 'USEATTR':
</span><span class="lines">@@ -4671,23 +4544,13 @@
</span><span class="cx">             throw new Horde_Imap_Client_Exception_ServerResponse(
</span><span class="cx">                 Horde_Imap_Client_Translation::t("The special-use attribute requested for the mailbox is not supported."),
</span><span class="cx">                 Horde_Imap_Client_Exception::USEATTR,
</span><del>-                $ob,
-                $pipeline
</del><ins>+                $ob->status,
+                strval($ob->token)
</ins><span class="cx">             );
</span><span class="cx"> 
</span><del>-        case 'DOWNGRADED':
-            // Defined by RFC 6858 [3]
-            $downgraded = $this->getIdsOb($rc->data[0]);
-            foreach ($pipeline->fetch as $val) {
-                if (in_array($val->getUid(), $downgraded)) {
-                    $val->setDowngraded(true);
-                }
-            }
-            break;
-
</del><span class="cx">         case 'XPROXYREUSE':
</span><span class="cx">             // The proxy connection was reused, so no need to do login tasks.
</span><del>-            $pipeline->data['proxyreuse'] = true;
</del><ins>+            $this->_temp['proxyreuse'] = true;
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         default:
</span></span></pre>
</div>
</div>

</body>
</html>