<!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>[2317] 2013/codebykat/post-by-email/trunk/include/Horde: Upgraded to horde_imap_client-2.15.2</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/2317">2317</a></dd>
<dt>Author</dt> <dd>codebykat</dd>
<dt>Date</dt> <dd>2013-09-16 02:11:45 +0000 (Mon, 16 Sep 2013)</dd>
</dl>
<h3>Log Message</h3>
<pre>Upgraded to horde_imap_client-2.15.2</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientBaseConnectionphp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base/Connection.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientBasephp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientCacheBackendDbphp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Cache/Backend/Db.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientDataFetchphp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Data/Fetch.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientInteractionCommandContinuationphp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Interaction/Command/Continuation.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientMailboxListphp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Mailbox/List.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientMailboxphp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Mailbox.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientSocketConnectionPop3php">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection/Pop3.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientSocketConnectionSocketphp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection/Socket.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientSocketConnectionphp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection.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>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientphp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeMailRfc822Addressphp">2013/codebykat/post-by-email/trunk/include/Horde/Mail/Rfc822/Address.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeMailRfc822Listphp">2013/codebykat/post-by-email/trunk/include/Horde/Mail/Rfc822/List.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeMimeHeadersphp">2013/codebykat/post-by-email/trunk/include/Horde/Mime/Headers.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeMimePartphp">2013/codebykat/post-by-email/trunk/include/Horde/Mime/Part.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeStreamFilterEolphp">2013/codebykat/post-by-email/trunk/include/Horde/Stream/Filter/Eol.php</a></li>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeSupportStubphp">2013/codebykat/post-by-email/trunk/include/Horde/Support/Stub.php</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#2013codebykatpostbyemailtrunkincludeHordeImapClientBasePasswordphp">2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base/Password.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientBaseConnectionphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base/Connection.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base/Connection.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base/Connection.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -61,8 +61,13 @@
</span><span class="cx"> */
</span><span class="cx"> public function __construct(Horde_Imap_Client_Base $base, $debug)
</span><span class="cx"> {
</span><del>- if ($base->getParam('secure') && !extension_loaded('openssl')) {
- throw new InvalidArgumentException('Secure connections require the PHP openssl extension.');
</del><ins>+ if (($secure = $base->getParam('secure')) &&
+ !extension_loaded('openssl')) {
+ if ($secure !== true) {
+ throw new InvalidArgumentException('Secure connections require the PHP openssl extension.');
+ }
+
+ $base->setParam('secure', false);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> $this->_debug = $debug;
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientBasePasswordphp"></a>
<div class="addfile"><h4>Added: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base/Password.php (0 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base/Password.php (rev 0)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base/Password.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -0,0 +1,33 @@
</span><ins>+<?php
+/**
+ * Copyright 2013 Horde LLC (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.horde.org/licenses/lgpl21.
+ *
+ * @category Horde
+ * @copyright 2013 Horde LLC
+ * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
+ * @package Imap_Client
+ */
+
+/**
+ * Interface to allow dynamic generation of server password.
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @copyright 2013 Horde LLC
+ * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
+ * @package Imap_Client
+ * @since 2.14.0
+ */
+interface Horde_Imap_Client_Base_Password
+{
+ /**
+ * Return the password to use for the server connection.
+ *
+ * @return string The password.
+ */
+ public function getPassword();
+
+}
</ins></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientBasephp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base.php (2316 => 2317)</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:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Base.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -57,6 +57,19 @@
</span><span class="cx"> public $changed = false;
</span><span class="cx">
</span><span class="cx"> /**
</span><ins>+ * 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;
+
+ /**
</ins><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">@@ -78,6 +91,14 @@
</span><span class="cx"> protected $_debug = null;
</span><span class="cx">
</span><span class="cx"> /**
</span><ins>+ * The default ports to use for a connection.
+ * First element is non-secure, second is SSL.
+ *
+ * @var array
+ */
+ protected $_defaultPorts = array();
+
+ /**
</ins><span class="cx"> * The fetch data object type to return.
</span><span class="cx"> *
</span><span class="cx"> * @var string
</span><span class="lines">@@ -136,7 +157,9 @@
</span><span class="cx"> * <ul>
</span><span class="cx"> * <li>REQUIRED Parameters
</span><span class="cx"> * <ul>
</span><del>- * <li>password: (string) The IMAP user password.</li>
</del><ins>+ * <li>password: (mixed) The IMAP user password. Either a string or
+ * a Horde_Imap_Client_Base_Password object (since
+ * 2.14.0).</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">@@ -153,10 +176,6 @@
</span><span class="cx"> * Backend cache driver (as of 2.9.0).
</span><span class="cx"> * </li>
</span><span class="cx"> * <li>
</span><del>- * cacheob: [REQUIRED (or backend)] (Horde_Cache) The cache object to
- * use (DEPRECATED).
- * </li>
- * <li>
</del><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">@@ -205,12 +224,6 @@
</span><span class="cx"> * DEFAULT: No debug output
</span><span class="cx"> * </li>
</span><span class="cx"> * <li>
</span><del>- * 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>
</del><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">@@ -234,13 +247,14 @@
</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</li>
</del><ins>+ * <li>false (No encryption)</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'</li>
</del><ins>+ * <li>'tls' (TLS)</li>
+ * <li>true (TLS if available/necessary) [since 2.15.0]</li>
</ins><span class="cx"> * </ul>
</span><del>- * DEFAULT: No encryption</li>
</del><ins>+ * DEFAULT: false</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">@@ -266,14 +280,10 @@
</span><span class="cx"> 'timeout' => 30
</span><span class="cx"> ), array_filter($params));
</span><span class="cx">
</span><del>- if ($params['secure'] === true) {
- $params['secure'] = 'tls';
- }
-
</del><span class="cx"> if (!isset($params['port'])) {
</span><del>- $params['port'] = (isset($params['secure']) && in_array($params['secure'], array('ssl', 'sslv2', 'sslv3')))
- ? 993
- : 143;
</del><ins>+ $params['port'] = (!empty($params['secure']) && in_array($params['secure'], array('ssl', 'sslv2', 'sslv3'), true))
+ ? $this->_defaultPorts[1]
+ : $this->_defaultPorts[0];
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (empty($params['cache'])) {
</span><span class="lines">@@ -298,6 +308,8 @@
</span><span class="cx"> /**
</span><span class="cx"> * Get encryption key.
</span><span class="cx"> *
</span><ins>+ * @deprecated Pass callable into 'password' parameter instead.
+ *
</ins><span class="cx"> * @return string The encryption key.
</span><span class="cx"> */
</span><span class="cx"> protected function _getEncryptKey()
</span><span class="lines">@@ -498,13 +510,22 @@
</span><span class="cx"> public function getParam($key)
</span><span class="cx"> {
</span><span class="cx"> /* Passwords may be stored encrypted. */
</span><del>- 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;
</del><ins>+ switch ($key) {
+ case 'password':
+ if ($this->_params[$key] instanceof Horde_Imap_Client_Base_Password) {
+ return $this->_params[$key]->getPassword();
</ins><span class="cx"> }
</span><ins>+
+ // 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;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> return isset($this->_params[$key])
</span><span class="lines">@@ -522,7 +543,11 @@
</span><span class="cx"> {
</span><span class="cx"> switch ($key) {
</span><span class="cx"> case 'password':
</span><del>- // Encrypt password.
</del><ins>+ if ($val instanceof Horde_Imap_Client_Base_Password) {
+ break;
+ }
+
+ // DEPRECATED: 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">@@ -530,9 +555,7 @@
</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) {
- $this->_params['_passencrypt'] = false;
- }
</del><ins>+ } catch (Exception $e) {}
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -693,7 +716,7 @@
</span><span class="cx"> if (!empty($to_process)) {
</span><span class="cx"> foreach ($this->listMailboxes($to_process, Horde_Imap_Client::MBOX_ALL, array('delimiter' => true)) as $val) {
</span><span class="cx"> $ns[$val] = array(
</span><del>- 'delimiter' => $first['delimiter'],
</del><ins>+ 'delimiter' => $val['delimiter'],
</ins><span class="cx"> 'hidden' => true,
</span><span class="cx"> 'name' => $val,
</span><span class="cx"> 'translation' => '',
</span><span class="lines">@@ -829,8 +852,7 @@
</span><span class="cx"> throw new Horde_Imap_Client_Exception_NoSupportExtension('ID');
</span><span class="cx"> }
</span><span class="cx">
</span><del>- /* Modified for WordPress inclusion: The shorthand ternary operator ?: was introduced in PHP 5.3. */
- $this->_sendID(is_null($info) ? ($this->getParam('id') ? $this->getParam('id') : array()) : $info);
</del><ins>+ $this->_sendID(is_null($info) ? ($this->getParam('id') ?: array()) : $info);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> /**
</span><span class="lines">@@ -1358,8 +1380,7 @@
</span><span class="cx">
</span><span class="cx"> if (!empty($options['status']) &&
</span><span class="cx"> !$this->queryCapability('LIST-STATUS')) {
</span><del>- $status = $this->statusMultiple($this->_selected, $options['status']);
- foreach ($status as $key => $val) {
</del><ins>+ foreach ($this->status(array_keys($ret), $options['status']) as $key => $val) {
</ins><span class="cx"> $ret[$key]['status'] = $val;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -1605,6 +1626,19 @@
</span><span class="cx"> * </ul>
</span><span class="cx"> * </li>
</span><span class="cx"> * <li>
</span><ins>+ * 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>
</ins><span class="cx"> * Horde_Imap_Client::STATUS_ALL (DEFAULT)
</span><span class="cx"> * <ul>
</span><span class="cx"> * <li>
</span><span class="lines">@@ -1659,6 +1693,10 @@
</span><span class="cx"> 'unseen' => Horde_Imap_Client::STATUS_UNSEEN
</span><span class="cx"> );
</span><span class="cx">
</span><ins>+ if (!$this->statuscache) {
+ $flags |= Horde_Imap_Client::STATUS_FORCE_REFRESH;
+ }
+
</ins><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="lines">@@ -1689,19 +1727,26 @@
</span><span class="cx"> $name = strval($val);
</span><span class="cx"> $tmp_flags = $flags;
</span><span class="cx">
</span><del>- /* 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) ||
</del><ins>+ if ($val->equals($this->_selected)) {
</ins><span class="cx"> /* Check if already in mailbox. */
</span><del>- $val->equals($this->_selected) ||
- /* 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);
</del><ins>+ $opened = true;
</ins><span class="cx">
</span><ins>+ 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);
+ }
+
</ins><span class="cx"> $ret[$name] = $master;
</span><span class="cx"> $ptr = &$ret[$name];
</span><span class="cx">
</span><span class="lines">@@ -2200,6 +2245,8 @@
</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><ins>+ } elseif (!in_array(Horde_Imap_Client::SEARCH_RESULTS_COUNT, $options['results'])) {
+ $options['results'][] = Horde_Imap_Client::SEARCH_RESULTS_COUNT;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Default to an ALL search.
</span><span class="lines">@@ -2318,12 +2365,14 @@
</span><span class="cx">
</span><span class="cx"> $ret = $this->_search($query, $options);
</span><span class="cx"> } else {
</span><del>- $ret = array(
- 'count' => 0
- );
</del><ins>+ $ret = array();
</ins><span class="cx">
</span><span class="cx"> foreach ($options['results'] as $val) {
</span><span class="cx"> switch ($val) {
</span><ins>+ case Horde_Imap_Client::SEARCH_RESULTS_COUNT:
+ $ret['count'] = 0;
+ break;
+
</ins><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">@@ -3567,7 +3616,9 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> $convert = 2;
</span><del>- } elseif (!$convert || (!$ids->sequence && ($convert == 1))) {
</del><ins>+ } elseif (!$convert ||
+ (!$ids->sequence && ($convert == 1)) ||
+ $ids->isEmpty()) {
</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">@@ -3601,7 +3652,7 @@
</span><span class="cx"> return $res['match'];
</span><span class="cx"> }
</span><span class="cx">
</span><del>- $map->update(array_combine($ids->ids, $res['match']->ids));
</del><ins>+ $map->update(array_combine(array_slice($ids->ids, 0, count($res['match'])), $res['match']->ids));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> return $res['match'];
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientCacheBackendDbphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Cache/Backend/Db.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Cache/Backend/Db.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Cache/Backend/Db.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -89,9 +89,9 @@
</span><span class="cx"> $columns = $this->_db->columns(self::MSG_TABLE);
</span><span class="cx"> $res = $this->_db->select($query[0], $query[1]);
</span><span class="cx">
</span><del>- while (($row = $res->fetchObject()) !== false) {
- $out[$row->msguid] = @unserialize($compress->decompress(
- $columns['data']->binaryToString($row->data)
</del><ins>+ foreach ($res as $row) {
+ $out[$row['msguid']] = @unserialize($compress->decompress(
+ $columns['data']->binaryToString($row['data'])
</ins><span class="cx"> ));
</span><span class="cx"> }
</span><span class="cx"> } catch (Horde_Db_Exception $e) {}
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientDataFetchphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Data/Fetch.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Data/Fetch.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Data/Fetch.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -564,4 +564,5 @@
</span><span class="cx"> : $this->_msgText(false, $this->_data[$key][$id]);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> }
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientInteractionCommandContinuationphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Interaction/Command/Continuation.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Interaction/Command/Continuation.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Interaction/Command/Continuation.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -25,6 +25,14 @@
</span><span class="cx"> class Horde_Imap_Client_Interaction_Command_Continuation
</span><span class="cx"> {
</span><span class="cx"> /**
</span><ins>+ * Is this an optional continuation request?
+ *
+ * @since 2.13.0
+ * @var boolean
+ */
+ public $optional = false;
+
+ /**
</ins><span class="cx"> * Closure function to run after continuation response.
</span><span class="cx"> *
</span><span class="cx"> * @var Closure
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientMailboxListphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Mailbox/List.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Mailbox/List.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Mailbox/List.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -98,9 +98,9 @@
</span><span class="cx"> {
</span><span class="cx"> /* Always return INBOX as "smaller". */
</span><span class="cx"> if ($this->_sortinbox) {
</span><del>- if (strcasecmp($a, 'INBOX') == 0) {
</del><ins>+ if (strcasecmp($a, 'INBOX') === 0) {
</ins><span class="cx"> return -1;
</span><del>- } elseif (strcasecmp($b, 'INBOX') == 0) {
</del><ins>+ } elseif (strcasecmp($b, 'INBOX') === 0) {
</ins><span class="cx"> return 1;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -116,8 +116,8 @@
</span><span class="cx"> /* If only one of the folders is under INBOX, return it as
</span><span class="cx"> * "smaller". */
</span><span class="cx"> if ($this->_sortinbox && ($i == 0)) {
</span><del>- $a_base = (strcasecmp($a_parts[0], 'INBOX') == 0);
- $b_base = (strcasecmp($b_parts[0], 'INBOX') == 0);
</del><ins>+ $a_base = (strcasecmp($a_parts[0], 'INBOX') === 0);
+ $b_base = (strcasecmp($b_parts[0], 'INBOX') === 0);
</ins><span class="cx"> if ($a_base && !$b_base) {
</span><span class="cx"> return -1;
</span><span class="cx"> } elseif (!$a_base && $b_base) {
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientMailboxphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Mailbox.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Mailbox.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Mailbox.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -68,6 +68,10 @@
</span><span class="cx"> */
</span><span class="cx"> public function __construct($mbox, $utf7imap = false)
</span><span class="cx"> {
</span><ins>+ if (strcasecmp($mbox, 'INBOX') === 0) {
+ $mbox = 'INBOX';
+ }
+
</ins><span class="cx"> if ($utf7imap) {
</span><span class="cx"> $this->_utf7imap = $mbox;
</span><span class="cx"> } else {
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientSocketConnectionPop3php"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection/Pop3.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection/Pop3.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection/Pop3.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -60,13 +60,13 @@
</span><span class="cx"> $this->close();
</span><span class="cx"> $this->_debug->info("ERROR: Server closed the connection.");
</span><span class="cx"> throw new Horde_Imap_Client_Exception(
</span><del>- Horde_Imap_Client_Translation::t("POP3 Server closed the connection unexpectedly."),
</del><ins>+ Horde_Imap_Client_Translation::t("Server closed the connection unexpectedly."),
</ins><span class="cx"> Horde_Imap_Client_Exception::DISCONNECT
</span><span class="cx"> );
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (($read = fgets($this->_stream)) === false) {
</span><del>- $this->_debug->info("ERROR: IMAP read/timeout error.");
</del><ins>+ $this->_debug->info("ERROR: read/timeout error.");
</ins><span class="cx"> throw new Horde_Imap_Client_Exception(
</span><span class="cx"> Horde_Imap_Client_Translation::t("Error when communicating with the mail server."),
</span><span class="cx"> Horde_Imap_Client_Exception::SERVER_READERROR
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientSocketConnectionSocketphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection/Socket.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection/Socket.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection/Socket.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -197,7 +197,7 @@
</span><span class="cx"> } while (true);
</span><span class="cx">
</span><span class="cx"> if (!$got_data) {
</span><del>- $this->_debug->info("ERROR: IMAP read/timeout error.");
</del><ins>+ $this->_debug->info("ERROR: read/timeout error.");
</ins><span class="cx"> throw new Horde_Imap_Client_Exception(
</span><span class="cx"> Horde_Imap_Client_Translation::t("Error when communicating with the mail server."),
</span><span class="cx"> Horde_Imap_Client_Exception::SERVER_READERROR
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientSocketConnectionphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Connection.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -54,7 +54,7 @@
</span><span class="cx"> {
</span><span class="cx"> parent::__construct($base, $debug);
</span><span class="cx">
</span><del>- switch ($secure = $base->getParam('secure')) {
</del><ins>+ switch (strval($secure = $base->getParam('secure'))) {
</ins><span class="cx"> case 'ssl':
</span><span class="cx"> case 'sslv2':
</span><span class="cx"> case 'sslv3':
</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 (2316 => 2317)</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:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket/Pop3.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -61,7 +61,8 @@
</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 1734/5034: POP3 SASL
</del><ins>+ * - RFC 4616: AUTH=PLAIN
+ * - RFC 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">@@ -74,6 +75,13 @@
</span><span class="cx"> class Horde_Imap_Client_Socket_Pop3 extends Horde_Imap_Client_Base
</span><span class="cx"> {
</span><span class="cx"> /**
</span><ins>+ * The default ports to use for a connection.
+ *
+ * @var array
+ */
+ protected $_defaultPorts = array(110, 995);
+
+ /**
</ins><span class="cx"> * The list of deleted messages.
</span><span class="cx"> *
</span><span class="cx"> * @var array
</span><span class="lines">@@ -89,17 +97,6 @@
</span><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> */
</span><del>- public function __construct(array $params = array())
- {
- parent::__construct($params);
-
- if (empty($params['port'])) {
- $this->setParam('port', in_array($this->getParam('secure'), array('ssl', 'sslv2', 'sslv3')) ? 995 : 110);
- }
- }
-
- /**
- */
</del><span class="cx"> protected function _initCache($current = false)
</span><span class="cx"> {
</span><span class="cx"> return parent::_initCache($current) &&
</span><span class="lines">@@ -133,23 +130,25 @@
</span><span class="cx"> : true;
</span><span class="cx"> }
</span><span class="cx"> } catch (Horde_Imap_Client_Exception $e) {
</span><ins>+ $this->_temp['no_capa'] = true;
+
</ins><span class="cx"> /* Need to probe for capabilities if CAPA command is not
</span><span class="cx"> * available. */
</span><del>- $capability = array('USER', 'SASL');
</del><ins>+ $capability = array('USER' => true);
</ins><span class="cx">
</span><del>- try {
- $this->_sendLine('UIDL', array(
- 'multiline' => 'none'
- ));
- $capability[] = 'UIDL';
- } catch (Horde_Imap_Client_Exception $e) {}
</del><ins>+ /* 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;
+ }
</ins><span class="cx">
</span><del>- try {
- $this->_sendLine('TOP 1 0', array(
- 'multiline' => 'none'
- ));
- $capability[] = 'TOP';
- } catch (Horde_Imap_Client_Exception $e) {}
</del><ins>+ $this->_pop3Cache('top', 1);
+ if (empty($this->_temp['no_top'])) {
+ $capability['TOP'] = true;
+ }
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> $this->_setInit('capability', $capability);
</span><span class="lines">@@ -183,25 +182,33 @@
</span><span class="cx"> {
</span><span class="cx"> $this->_connect();
</span><span class="cx">
</span><ins>+ $secure = $this->getParam('secure');
+
</ins><span class="cx"> // Switch to secure channel if using TLS.
</span><span class="cx"> if (!$this->isSecureConnection() &&
</span><del>- ($this->getParam('secure') == 'tls')) {
</del><ins>+ (($secure === 'tls') || $secure === true)) {
</ins><span class="cx"> // Switch over to a TLS connection.
</span><span class="cx"> if (!$this->queryCapability('STLS')) {
</span><del>- 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
- );
- }
</del><ins>+ 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');
</ins><span class="cx">
</span><del>- $this->_sendLine('STLS');
</del><ins>+ $this->setParam('secure', 'tls');
</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>+ 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
+ );
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Expire cached CAPABILITY information
</span><span class="lines">@@ -226,6 +233,12 @@
</span><span class="cx"> try {
</span><span class="cx"> $this->_tryLogin($method);
</span><span class="cx"> $this->_setInit('authmethod', $method);
</span><ins>+
+ if (!empty($this->_temp['no_capa']) ||
+ !$this->queryCapability('UIDL')) {
+ $this->_capability();
+ }
+
</ins><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">@@ -312,7 +325,7 @@
</span><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case 'LOGIN':
</span><del>- // RFC 5034
</del><ins>+ // RFC 4616 (AUTH=PLAIN) & 5034 (POP3 SASL)
</ins><span class="cx"> $this->_sendLine('AUTH LOGIN');
</span><span class="cx"> $this->_sendLine(base64_encode($username), array(
</span><span class="cx"> 'debug' => sprintf('[AUTH LOGIN Command - username: %s]', $username)
</span><span class="lines">@@ -324,7 +337,11 @@
</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, $this->getParam('password')))), array(
</del><ins>+ $this->_sendLine('AUTH PLAIN ' . base64_encode(implode("\0", array(
+ $username,
+ $username,
+ $password
+ ))), array(
</ins><span class="cx"> 'debug' => sprintf('[AUTH PLAIN Command - username: %s]', $username)
</span><span class="cx"> ));
</span><span class="cx"> break;
</span><span class="lines">@@ -400,7 +417,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 (strcasecmp($mailbox, 'INBOX') !== 0) {
</del><ins>+ if ($mailbox != 'INBOX') {
</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">@@ -465,8 +482,7 @@
</span><span class="cx"> */
</span><span class="cx"> protected function _status($mboxes, $flags)
</span><span class="cx"> {
</span><del>- if ((count($mboxes) > 1) ||
- (strcasecmp(reset($mboxes), 'INBOX') !== 0)) {
</del><ins>+ if ((count($mboxes) > 1) || (reset($mboxes) != 'INBOX')) {
</ins><span class="cx"> throw new Horde_Imap_Client_Exception_NoSupportPop3('Mailboxes other than INBOX');
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -805,7 +821,7 @@
</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>- * or 'uidl'.
</del><ins>+ * 'top', 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">@@ -825,8 +841,9 @@
</span><span class="cx">
</span><span class="cx"> switch ($type) {
</span><span class="cx"> case 'hdr':
</span><ins>+ case 'top':
</ins><span class="cx"> $data = null;
</span><del>- if ($this->queryCapability('TOP')) {
</del><ins>+ if ($this->queryCapability('TOP') || ($type == 'top')) {
</ins><span class="cx"> try {
</span><span class="cx"> $res = $this->_sendLine('TOP ' . $index . ' 0', array(
</span><span class="cx"> 'multiline' => 'stream'
</span><span class="lines">@@ -834,7 +851,12 @@
</span><span class="cx"> rewind($res['data']);
</span><span class="cx"> $data = stream_get_contents($res['data']);
</span><span class="cx"> fclose($res['data']);
</span><del>- } catch (Horde_Imap_Client_Exception $e) {}
</del><ins>+ } catch (Horde_Imap_Client_Exception $e) {
+ $this->_temp['no_top'] = true;
+ if ($type == 'top') {
+ return null;
+ }
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (is_null($data)) {
</span><span class="lines">@@ -865,7 +887,11 @@
</span><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) {}
</del><ins>+ } catch (Horde_Imap_Client_Exception $e) {
+ if ($type == 'uidl') {
+ $this->_temp['no_uidl'] = true;
+ }
+ }
</ins><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case 'stat':
</span><span class="lines">@@ -1048,6 +1074,25 @@
</span><span class="cx"> return null;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ /**
+ */
+ 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)
+ );
+ }
+
</ins><span class="cx"> /* Internal functions. */
</span><span class="cx">
</span><span class="cx"> /**
</span><span class="lines">@@ -1105,7 +1150,7 @@
</span><span class="cx"> $ob = array('resp' => '');
</span><span class="cx">
</span><span class="cx"> $read = explode(' ', rtrim($this->_connection->read(), "\r\n"), 2);
</span><del>- if (!in_array($read[0], array('+OK', '-ERR'))) {
</del><ins>+ if (!in_array($read[0], array('+OK', '-ERR', '+'))) {
</ins><span class="cx"> $this->_debug->info("ERROR: IMAP read/timeout error.");
</span><span class="cx"> throw new Horde_Imap_Client_Exception(
</span><span class="cx"> Horde_Imap_Client_Translation::t("Error when communicating with the mail server."),
</span><span class="lines">@@ -1122,6 +1167,7 @@
</span><span class="cx">
</span><span class="cx"> switch ($read[0]) {
</span><span class="cx"> case '+OK':
</span><ins>+ case '+':
</ins><span class="cx"> if ($respcode) {
</span><span class="cx"> $ob['resp'] = $respcode->text;
</span><span class="cx"> } elseif (isset($read[1])) {
</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 (2316 => 2317)</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:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client/Socket.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -76,6 +76,11 @@
</span><span class="cx"> * </li>
</span><span class="cx"> * </ul>
</span><span class="cx"> * </li>
</span><ins>+ * <li>AUTH=XOAUTH2
+ * <ul>
+ * <li>https://developers.google.com/gmail/xoauth2_protocol</li>
+ * </ul>
+ * </li>
</ins><span class="cx"> * </ul>
</span><span class="cx"> *
</span><span class="cx"> * TODO (or not necessary?):
</span><span class="lines">@@ -125,6 +130,13 @@
</span><span class="cx"> protected $_cmdQueue = array();
</span><span class="cx">
</span><span class="cx"> /**
</span><ins>+ * The default ports to use for a connection.
+ *
+ * @var array
+ */
+ protected $_defaultPorts = array(143, 993);
+
+ /**
</ins><span class="cx"> * Mapping of status fields to IMAP names.
</span><span class="cx"> *
</span><span class="cx"> * @var array
</span><span class="lines">@@ -161,6 +173,11 @@
</span><span class="cx"> * - envelope_string: (integer) The maximum length of string fields
</span><span class="cx"> * returned by the FETCH ENVELOPE command.
</span><span class="cx"> * DEFAULT: 2048
</span><ins>+ * - 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).
</ins><span class="cx"> */
</span><span class="cx"> public function __construct(array $params = array())
</span><span class="cx"> {
</span><span class="lines">@@ -173,6 +190,21 @@
</span><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> */
</span><ins>+ public function getParam($key)
+ {
+ switch ($key) {
+ case 'xoauth2_token':
+ if ($this->_params[$key] instanceof Horde_Imap_Client_Base_Password) {
+ return $this->_params[$key]->getPassword();
+ }
+ break;
+ }
+
+ return parent::getParam($key);
+ }
+
+ /**
+ */
</ins><span class="cx"> protected function _capability()
</span><span class="cx"> {
</span><span class="cx"> // Need to use connect call here or else we run into loop issues
</span><span class="lines">@@ -202,12 +234,9 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- /* Assume capabilities are additive. */
- $c = empty($this->_init['capability'])
- ? array()
- : $this->_init['capability'];
</del><ins>+ $pipeline->data['capability_set'] = true;
</ins><span class="cx">
</span><del>- $pipeline->data['capabilties_set'] = true;
</del><ins>+ $c = array();
</ins><span class="cx">
</span><span class="cx"> foreach ($data as $val) {
</span><span class="cx"> $cap_list = explode('=', $val);
</span><span class="lines">@@ -338,13 +367,15 @@
</span><span class="cx"> $this->_connect();
</span><span class="cx">
</span><span class="cx"> $first_login = empty($this->_init['authmethod']);
</span><ins>+ $secure = $this->getParam('secure');
</ins><span class="cx">
</span><span class="cx"> // Switch to secure channel if using TLS.
</span><span class="cx"> if (!$this->isSecureConnection() &&
</span><del>- ($this->getParam('secure') == 'tls')) {
</del><ins>+ (($secure === 'tls') ||
+ (($secure === true) && $this->queryCapability('LOGINDISABLED')))) {
</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">@@ -353,7 +384,7 @@
</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->_sendCmd($this->_command('STARTTLS'));
</ins><span class="cx">
</span><span class="cx"> if (!$this->_connection->startTls()) {
</span><span class="cx"> $this->logout();
</span><span class="lines">@@ -363,6 +394,8 @@
</span><span class="cx"> );
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ $this->setParam('secure', 'tls');
+
</ins><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">@@ -378,45 +411,54 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ($first_login) {
</span><del>- $imap_auth_mech = array();
</del><ins>+ // Add authentication methods.
+ $auth_mech = array();
</ins><span class="cx">
</span><del>- $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);
</del><ins>+ $auth = ($auth = $this->queryCapability('AUTH'))
+ ? array_flip($auth)
+ : array();
</ins><span class="cx">
</span><del>- // Next, try 'PLAIN' authentication.
- if (in_array('PLAIN', $auth_methods)) {
- $imap_auth_mech[] = 'PLAIN';
- }
</del><ins>+ // XOAUTH2
+ if (isset($auth['XOAUTH2']) && $this->getParam('xoauth2_token')) {
+ $auth_mech[] = 'XOAUTH2';
+ unset($auth['XOAUTH2']);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+ // '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']);
+
</ins><span class="cx"> // Fall back to 'LOGIN' if available.
</span><ins>+ $auth_mech = array_merge($auth_mech, array_keys($auth));
</ins><span class="cx"> if (!$this->queryCapability('LOGINDISABLED')) {
</span><del>- $imap_auth_mech[] = 'LOGIN';
</del><ins>+ $auth_mech[] = 'LOGIN';
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- if (empty($imap_auth_mech)) {
</del><ins>+ if (empty($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><del>-
- /* Use MD5 authentication first, if available. But no need to use
- * special authentication if we are already using an encrypted
- * connection. */
- if ($this->isSecureConnection()) {
- $imap_auth_mech = array_reverse($imap_auth_mech);
- }
</del><span class="cx"> } else {
</span><del>- $imap_auth_mech = array($this->_init['authmethod']);
</del><ins>+ $auth_mech = array($this->_init['authmethod']);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> $login_err = null;
</span><span class="cx">
</span><del>- foreach ($imap_auth_mech as $method) {
</del><ins>+ foreach ($auth_mech as $method) {
</ins><span class="cx"> try {
</span><span class="cx"> $resp = $this->_tryLogin($method);
</span><span class="cx"> $data = $resp->data;
</span><span class="lines">@@ -505,8 +547,7 @@
</span><span class="cx"> $this->_temp['no_cap'] = true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- /* Get greeting information. This is untagged so we need to specially
- * deal with it here. */
</del><ins>+ /* Get greeting information (untagged response). */
</ins><span class="cx"> try {
</span><span class="cx"> $this->_getLine($this->_pipeline());
</span><span class="cx"> } catch (Horde_Imap_Client_Exception_ServerResponse $e) {
</span><span class="lines">@@ -556,6 +597,8 @@
</span><span class="cx"> $username = $this->getParam('username');
</span><span class="cx"> $password = $this->getParam('password');
</span><span class="cx">
</span><ins>+ $authenticate_cmd = false;
+
</ins><span class="cx"> switch ($method) {
</span><span class="cx"> case 'CRAM-MD5':
</span><span class="cx"> case 'CRAM-SHA1':
</span><span class="lines">@@ -635,38 +678,46 @@
</span><span class="cx"> $username,
</span><span class="cx"> $password
</span><span class="cx"> )));
</span><del>- $cmd = $this->_command('AUTHENTICATE')->add('PLAIN');
</del><ins>+ $authenticate_cmd = true;
+ break;
</ins><span class="cx">
</span><ins>+ case 'XOAUTH2':
+ // Google XOAUTH2
+ $auth = $this->getParam('xoauth2_token');
+ $authenticate_cmd = true;
+ break;
+
+ default:
+ throw new Horde_Imap_Client_Exception(
+ sprintf(Horde_Imap_Client_Translation::t("Unknown authentication method: %s"), $method),
+ Horde_Imap_Client_Exception::SERVER_CONNECT
+ );
+ }
+
+ if ($authenticate_cmd) {
+ $cmd = $this->_command('AUTHENTICATE')->add($method);
+
</ins><span class="cx"> if ($this->queryCapability('SASL-IR')) {
</span><span class="cx"> // IMAP Extension for SASL Initial Client Response (RFC 4959)
</span><span class="cx"> $cmd->add($auth);
</span><del>- $cmd->debug = sprintf('[SASL-IR AUTHENTICATE Command - username: %s]', $username);
</del><ins>+ $cmd->debug = sprintf('[SASL-IR AUTHENTICATE Command - method: %s, username: %s]', $method, $username);
</ins><span class="cx"> } else {
</span><span class="cx"> $cmd->add(new Horde_Imap_Client_Interaction_Command_Continuation(function($ob) use ($auth) {
</span><span class="cx"> return new Horde_Imap_Client_Data_Format_List($auth);
</span><span class="cx"> }));
</span><del>- $cmd->debug = sprintf('[AUTHENTICATE Command - username: %s]', $username);
</del><ins>+ $cmd->debug = sprintf('[AUTHENTICATE Command - method: %s, username: %s]', $method, $username);
</ins><span class="cx"> }
</span><del>- break;
</del><span class="cx">
</span><del>- default:
- throw new Horde_Imap_Client_Exception(
- sprintf(Horde_Imap_Client_Translation::t("Unknown authentication method: %s"), $method),
- Horde_Imap_Client_Exception::SERVER_CONNECT
- );
</del><ins>+ /* 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);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- $pipeline = $this->_pipeline($cmd);
-
- /* 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). */
- $pipeline->data['in_login'] = true;
-
- return $this->_sendCmd($pipeline);
</del><ins>+ return $this->_sendCmd($this->_pipeline($cmd));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> /**
</span><span class="lines">@@ -675,7 +726,7 @@
</span><span class="cx"> * @param boolean $firstlogin Is this the first login?
</span><span class="cx"> * @param array $resp The data response from the login command.
</span><span class="cx"> * May include:
</span><del>- * - logincapset: (boolean) True if CAPABILITY sent after login.
</del><ins>+ * - capability_set: (boolean) True if CAPABILITY was set after login.
</ins><span class="cx"> * - proxyreuse: (boolean) True if re-used connection via imapproxy.
</span><span class="cx"> *
</span><span class="cx"> * @return boolean True if global login tasks should be performed.
</span><span class="lines">@@ -700,7 +751,7 @@
</span><span class="cx">
</span><span class="cx"> /* If we logged in for first time, and server did not return
</span><span class="cx"> * capability information, we need to mark for retrieval. */
</span><del>- if ($firstlogin && empty($resp['capabilities_set'])) {
</del><ins>+ if ($firstlogin && empty($resp['capability_set'])) {
</ins><span class="cx"> $this->_setInit('capability');
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1745,11 +1796,17 @@
</span><span class="cx"> // RFC 3691 defines 'UNSELECT' for precisely this purpose
</span><span class="cx"> $this->_sendCmd($this->_command('UNSELECT'));
</span><span class="cx"> } else {
</span><del>- // RFC 3501 [6.4.2]: to close a mailbox without expunge,
- // select a non-existent mailbox. Selecting a null mailbox
- // should do the trick.
</del><ins>+ /* RFC 3501 [6.4.2]: to close a mailbox without expunge,
+ * select a non-existent mailbox. */
</ins><span class="cx"> try {
</span><del>- $this->_sendCmd($this->_command('SELECT')->add(''));
</del><ins>+ $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'));
</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">@@ -1778,7 +1835,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">@@ -3628,7 +3685,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> /**
</span><del>- * Parse a METADATA response (RFC 5464 [4.4]).
</del><ins>+ * Parse an ANNOTATION response (ANNOTATEMORE/ANNOTATEMORE2).
</ins><span class="cx"> *
</span><span class="cx"> * @param Horde_Imap_Client_Interaction_Pipeline $pipeline Pipeline
</span><span class="cx"> * object.
</span><span class="lines">@@ -3636,52 +3693,61 @@
</span><span class="cx"> *
</span><span class="cx"> * @throws Horde_Imap_Client_Exception
</span><span class="cx"> */
</span><del>- protected function _parseMetadata(
</del><ins>+ protected function _parseAnnotation(
</ins><span class="cx"> Horde_Imap_Client_Interaction_Pipeline $pipeline,
</span><span class="cx"> Horde_Imap_Client_Tokenize $data
</span><span class="cx"> )
</span><span class="cx"> {
</span><del>- switch ($data->current()) {
- case 'ANNOTATION':
- $mbox = $data->next();
- $entry = $data->next();
</del><ins>+ // Mailbox name is in UTF7-IMAP.
+ $mbox = Horde_Imap_Client_Mailbox::get($data->next(), true);
+ $entry = $data->next();
</ins><span class="cx">
</span><del>- // Ignore unsolicited responses.
- if ($data->next() !== true) {
</del><ins>+ // 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();
</ins><span class="cx"> break;
</span><del>- }
</del><span class="cx">
</span><del>- while (($type = $data->next()) !== false) {
- switch ($type) {
- case 'value.priv':
- $pipeline->data['metadata'][$mbox]['/private' . $entry] = $data->next();
- break;
</del><ins>+ case 'value.shared':
+ $pipeline->data['metadata'][strval($mbox)]['/shared' . $entry] = $data->next();
+ break;
</ins><span class="cx">
</span><del>- case 'value.shared':
- $pipeline->data['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
- );
- }
</del><ins>+ 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>- break;
</del><ins>+ }
+ }
</ins><span class="cx">
</span><del>- case 'METADATA':
- $mbox = $data->next();
</del><ins>+ /**
+ * 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);
</ins><span class="cx">
</span><del>- // Ignore unsolicited responses.
- if ($data->next() !== true) {
- break;
- }
-
</del><ins>+ // Ignore unsolicited responses.
+ if ($data->next() === true) {
</ins><span class="cx"> while (($entry = $data->next()) !== false) {
</span><del>- $pipeline->data['metadata'][$mbox][$entry] = $data->next();
</del><ins>+ $pipeline->data['metadata'][strval($mbox)][$entry] = $data->next();
</ins><span class="cx"> }
</span><del>- break;
</del><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -3803,8 +3869,11 @@
</span><span class="cx"> $this->_debug->raw($val->tag . ' ' . $val->debug . "\n");
</span><span class="cx"> $this->_debug->debug = false;
</span><span class="cx"> }
</span><del>- $this->_processCmd($pipeline, $val, $val);
- $this->_connection->write('', true);
</del><ins>+ if ($this->_processCmd($pipeline, $val, $val)) {
+ $this->_connection->write('', true);
+ } else {
+ $cmd_count = 0;
+ }
</ins><span class="cx"> $this->_debug->debug = $old_debug;
</span><span class="cx"> } catch (Horde_Imap_Client_Exception $e) {
</span><span class="cx"> $this->_debug->debug = $old_debug;
</span><span class="lines">@@ -3862,6 +3931,7 @@
</span><span class="cx"> * @param Horde_Imap_Client_Interaction_Command $cmd The master command.
</span><span class="cx"> * @param Horde_Imap_Client_Data_Format_List $data Commands to send.
</span><span class="cx"> *
</span><ins>+ * @return boolean True if EOL needed to finish command.
</ins><span class="cx"> * @throws Horde_Imap_Client_Exception
</span><span class="cx"> * @throws Horde_Imap_Client_Exception_NoSupport
</span><span class="cx"> */
</span><span class="lines">@@ -3871,10 +3941,16 @@
</span><span class="cx"> if ($val instanceof Horde_Imap_Client_Interaction_Command_Continuation) {
</span><span class="cx"> $this->_connection->write('', true);
</span><span class="cx">
</span><ins>+ /* Check for optional continuation responses when the command
+ * has already finished. */
+ if (!$cmd_continuation = $this->_processCmdContinuation($pipeline, $val->optional)) {
+ return false;
+ }
+
</ins><span class="cx"> $this->_processCmd(
</span><span class="cx"> $pipeline,
</span><span class="cx"> $cmd,
</span><del>- $val->getCommands($this->_processCmdContinuation($pipeline))
</del><ins>+ $val->getCommands($cmd_continuation)
</ins><span class="cx"> );
</span><span class="cx"> continue;
</span><span class="cx"> }
</span><span class="lines">@@ -3916,24 +3992,35 @@
</span><span class="cx"> $this->_connection->write($val->escape());
</span><span class="cx"> }
</span><span class="cx"> }
</span><ins>+
+ return true;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> * Process a command continuation response.
</span><span class="cx"> *
</span><del>- * @param Horde_Imap_Client_Interaction_Pipeline $pipeline The pipeline
- * object.
</del><ins>+ * @param Horde_Imap_Client_Interaction_Pipeline $pipeline The pipeline
+ * object.
+ * @param boolean $noexception Don't throw
+ * exception if
+ * continuation
+ * does not occur.
</ins><span class="cx"> *
</span><del>- * @return Horde_Imap_Client_Interaction_Server_Continuation Continuation
- * object.
</del><ins>+ * @return mixed A Horde_Imap_Client_Interaction_Server_Continuation
+ * object or false.
</ins><span class="cx"> *
</span><span class="cx"> * @throws Horde_Imap_Client_Exception
</span><span class="cx"> */
</span><del>- protected function _processCmdContinuation($pipeline)
</del><ins>+ protected function _processCmdContinuation($pipeline, $noexception = false)
</ins><span class="cx"> {
</span><del>- $ob = $this->_getLine($pipeline);
</del><ins>+ do {
+ $ob = $this->_getLine($pipeline);
+ } while ($ob instanceof Horde_Imap_Client_Interaction_Server_Untagged);
+
</ins><span class="cx"> if ($ob instanceof Horde_Imap_Client_Interaction_Server_Continuation) {
</span><span class="cx"> return $ob;
</span><ins>+ } elseif ($noexception) {
+ return false;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> $this->_debug->info("ERROR: Unexpected response from server while waiting for a continuation request.");
</span><span class="lines">@@ -4176,8 +4263,12 @@
</span><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case 'ANNOTATION':
</span><ins>+ // Parse an ANNOTATION response.
+ $this->_parseAnnotation($pipeline, $token);
+ break;
+
</ins><span class="cx"> case 'METADATA':
</span><del>- // Parse a ANNOTATEMORE/METADATA response.
</del><ins>+ // Parse a METADATA response.
</ins><span class="cx"> $this->_parseMetadata($pipeline, $token);
</span><span class="cx"> break;
</span><span class="cx">
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeImapClientphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Imap/Client.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -52,6 +52,8 @@
</span><span class="cx"> const STATUS_SYNCVANISHED = 16384;
</span><span class="cx"> /* @since 2.12.0 */
</span><span class="cx"> const STATUS_RECENT_TOTAL = 32768;
</span><ins>+ /* @since 2.14.0 */
+ const STATUS_FORCE_REFRESH = 65536;
</ins><span class="cx">
</span><span class="cx"> /* Constants for search() */
</span><span class="cx"> const SORT_ARRIVAL = 1;
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeMailRfc822Addressphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Mail/Rfc822/Address.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Mail/Rfc822/Address.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Mail/Rfc822/Address.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -21,6 +21,8 @@
</span><span class="cx"> * @package Mail
</span><span class="cx"> *
</span><span class="cx"> * @property-read string $bare_address The bare mailbox@host address.
</span><ins>+ * @property-read string $bare_address_idn The bare mailbox@host address (IDN
+ * encoded). (@since 2.1.0)
</ins><span class="cx"> * @property-read string $encoded The full MIME/IDN encoded address (UTF-8).
</span><span class="cx"> * @property string $host Returns the host part (UTF-8).
</span><span class="cx"> * @property-read string $host_idn Returns the IDN encoded host part.
</span><span class="lines">@@ -111,6 +113,13 @@
</span><span class="cx"> ? $this->mailbox
</span><span class="cx"> : $this->mailbox . '@' . $this->host;
</span><span class="cx">
</span><ins>+ case 'bare_address_idn':
+ $personal = $this->_personal;
+ $this->_personal = null;
+ $res = $this->encoded;
+ $this->_personal = $personal;
+ return $res;
+
</ins><span class="cx"> case 'encoded':
</span><span class="cx"> return $this->writeAddress(true);
</span><span class="cx">
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeMailRfc822Listphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Mail/Rfc822/List.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Mail/Rfc822/List.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Mail/Rfc822/List.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -23,6 +23,9 @@
</span><span class="cx"> * @property-read array $addresses The list of all addresses (address
</span><span class="cx"> * w/personal parts).
</span><span class="cx"> * @property-read array $bare_addresses The list of all addresses (mail@host).
</span><ins>+ * @property-read array $bare_addresses_idn The list of all addresses
+ * (mail@host; IDN encoded).
+ * (@since 2.1.0)
</ins><span class="cx"> * @property-read array $base_addresses The list of ONLY base addresses
</span><span class="cx"> * (Address objects).
</span><span class="cx"> * @property-read array $raw_addresses The list of all addresses (Address
</span><span class="lines">@@ -74,6 +77,7 @@
</span><span class="cx"> switch ($name) {
</span><span class="cx"> case 'addresses':
</span><span class="cx"> case 'bare_addresses':
</span><ins>+ case 'bare_addresses_idn':
</ins><span class="cx"> case 'base_addresses':
</span><span class="cx"> case 'raw_addresses':
</span><span class="cx"> $old = $this->_filter;
</span><span class="lines">@@ -93,6 +97,10 @@
</span><span class="cx"> $out[] = $val->bare_address;
</span><span class="cx"> break;
</span><span class="cx">
</span><ins>+ case 'bare_addresses_idn':
+ $out[] = $val->bare_address_idn;
+ break;
+
</ins><span class="cx"> case 'base_addresses':
</span><span class="cx"> case 'raw_addresses':
</span><span class="cx"> $out[] = clone $val;
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeMimeHeadersphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Mime/Headers.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Mime/Headers.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Mime/Headers.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -302,7 +302,7 @@
</span><span class="cx"> public function getUserAgent()
</span><span class="cx"> {
</span><span class="cx"> if (is_null($this->_agent)) {
</span><del>- $this->_agent = 'Horde Application Framework 4';
</del><ins>+ $this->_agent = 'Horde Application Framework 5';
</ins><span class="cx"> }
</span><span class="cx"> return $this->_agent;
</span><span class="cx"> }
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeMimePartphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Mime/Part.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Mime/Part.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Mime/Part.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -535,11 +535,10 @@
</span><span class="cx"> *
</span><span class="cx"> * @param resource $fp A stream containing the data to encode.
</span><span class="cx"> * @param string $encoding The encoding to use.
</span><del>- * @param string $eol EOL string.
</del><span class="cx"> *
</span><span class="cx"> * @return resource A new file resource with the encoded data.
</span><span class="cx"> */
</span><del>- protected function _transferEncode($fp, $encoding, $eol)
</del><ins>+ protected function _transferEncode($fp, $encoding)
</ins><span class="cx"> {
</span><span class="cx"> $this->_temp['transferEncodeClose'] = true;
</span><span class="cx">
</span><span class="lines">@@ -549,20 +548,24 @@
</span><span class="cx"> return $this->_writeStream($fp, array(
</span><span class="cx"> 'filter' => array(
</span><span class="cx"> 'convert.base64-encode' => array(
</span><del>- 'line-break-chars' => $eol,
</del><ins>+ 'line-break-chars' => $this->getEOL(),
</ins><span class="cx"> 'line-length' => 76
</span><span class="cx"> )
</span><span class="cx"> )
</span><span class="cx"> ));
</span><span class="cx">
</span><span class="cx"> case 'quoted-printable':
</span><ins>+ $stream = new Horde_Stream_Existing(array(
+ 'stream' => $fp
+ ));
+
</ins><span class="cx"> /* Quoted-Printable Encoding: See RFC 2045, section 6.7 */
</span><span class="cx"> return $this->_writeStream($fp, array(
</span><span class="cx"> 'filter' => array(
</span><del>- 'convert.quoted-printable-encode' => array(
- 'line-break-chars' => $eol,
</del><ins>+ 'convert.quoted-printable-encode' => array_filter(array(
+ 'line-break-chars' => $stream->getEOL(),
</ins><span class="cx"> 'line-length' => 76
</span><del>- )
</del><ins>+ ))
</ins><span class="cx"> )
</span><span class="cx"> ));
</span><span class="cx">
</span><span class="lines">@@ -1222,11 +1225,7 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- $parts[] = $this->_transferEncode(
- $this->_contents,
- $encoding,
- (empty($options['canonical']) ? $this->getEOL() : self::RFC_EOL)
- );
</del><ins>+ $parts[] = $this->_transferEncode($this->_contents, $encoding);
</ins><span class="cx">
</span><span class="cx"> /* If not using $this->_contents, we can close the stream
</span><span class="cx"> * when finished. */
</span><span class="lines">@@ -1410,10 +1409,12 @@
</span><span class="cx"> $eol = $this->getEOL();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- $fp = $this->_writeStream($text);
-
</del><span class="cx"> stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol');
</span><del>- stream_filter_append($fp, 'horde_eol', STREAM_FILTER_READ, array('eol' => $eol));
</del><ins>+ $fp = $this->_writeStream($text, array(
+ 'filter' => array(
+ 'horde_eol' => array('eol' => $eol)
+ )
+ ));
</ins><span class="cx">
</span><span class="cx"> return $stream ? $fp : $this->_readStream($fp, true);
</span><span class="cx"> }
</span><span class="lines">@@ -1559,7 +1560,8 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ($rfc822) {
</span><del>- if (empty($this->_parts)) {
</del><ins>+ if (empty($this->_parts) &&
+ ($this->getPrimaryType() != 'multipart')) {
</ins><span class="cx"> $this->setMimeId($id . '1');
</span><span class="cx"> } else {
</span><span class="cx"> if (empty($id) && ($this->getType() == 'message/rfc822')) {
</span><span class="lines">@@ -1689,10 +1691,10 @@
</span><span class="cx"> $old_basepart = $this->_basepart;
</span><span class="cx"> $this->_basepart = true;
</span><span class="cx">
</span><del>- /* Does the SMTP backend support 8BITMIME (RFC 1652) or
- * BINARYMIME (RFC 3030) extensions? Requires Net_SMTP version
- * 1.3+. */
</del><ins>+ /* Does the SMTP backend support 8BITMIME (RFC 1652)? */
+ $canonical = true;
</ins><span class="cx"> $encode = self::ENCODE_7BIT;
</span><ins>+
</ins><span class="cx"> if (isset($opts['encode'])) {
</span><span class="cx"> /* Always allow 7bit encoding. */
</span><span class="cx"> $encode |= $opts['encode'];
</span><span class="lines">@@ -1702,34 +1704,24 @@
</span><span class="cx"> if (isset($smtp_ext['8BITMIME'])) {
</span><span class="cx"> $encode |= self::ENCODE_8BIT;
</span><span class="cx"> }
</span><del>- if (isset($smtp_ext['BINARYMIME'])) {
- $encode |= self::ENCODE_BINARY;
</del><ins>+ } catch (Horde_Mail_Exception $e) {}
+ $canonical = false;
+ } elseif ($mailer instanceof Horde_Mail_Transport_Smtphorde) {
+ try {
+ if ($mailer->getSMTPObject()->data_8bit) {
+ $encode |= self::ENCODE_8BIT;
</ins><span class="cx"> }
</span><span class="cx"> } catch (Horde_Mail_Exception $e) {}
</span><ins>+ $canonical = false;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> $msg = $this->toString(array(
</span><del>- 'canonical' => true,
</del><ins>+ 'canonical' => $canonical,
</ins><span class="cx"> 'encode' => $encode,
</span><span class="cx"> 'headers' => false,
</span><span class="cx"> 'stream' => true
</span><span class="cx"> ));
</span><span class="cx">
</span><del>- /* Make sure the message has a trailing newline. */
- fseek($msg, -1, SEEK_END);
- switch (fgetc($msg)) {
- case "\r":
- if (fgetc($msg) != "\n") {
- fputs($msg, "\n");
- }
- break;
-
- default:
- fputs($msg, "\r\n");
- break;
- }
- rewind($msg);
-
</del><span class="cx"> /* Add MIME Headers if they don't already exist. */
</span><span class="cx"> if (!$headers->getValue('MIME-Version')) {
</span><span class="cx"> $headers = $this->addMimeHeaders(array('encode' => $encode, 'headers' => $headers));
</span><span class="lines">@@ -1738,12 +1730,12 @@
</span><span class="cx"> if (!empty($this->_temp['toString'])) {
</span><span class="cx"> $headers->replaceHeader('Content-Transfer-Encoding', $this->_temp['toString']);
</span><span class="cx"> switch ($this->_temp['toString']) {
</span><del>- case 'binary':
- $mailer->addServiceExtensionParameter('BODY', 'BINARYMIME');
- break;
-
</del><span class="cx"> case '8bit':
</span><del>- $mailer->addServiceExtensionParameter('BODY', '8BITMIME');
</del><ins>+ if ($mailer instanceof Horde_Mail_Transport_Smtp) {
+ $mailer->addServiceExtensionParameter('BODY', '8BITMIME');
+ } elseif ($mailer instanceof Horde_Mail_Transport_Smtphorde) {
+ $mailer->send8bit = true;
+ }
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -1755,7 +1747,7 @@
</span><span class="cx"> 'encode' => $this->getHeaderCharset(),
</span><span class="cx"> 'idn' => true
</span><span class="cx"> )), $headers->toArray(array(
</span><del>- 'canonical' => true,
</del><ins>+ 'canonical' => $canonical,
</ins><span class="cx"> 'charset' => $this->getHeaderCharset()
</span><span class="cx"> )), $msg);
</span><span class="cx"> } catch (Horde_Mail_Exception $e) {
</span><span class="lines">@@ -2083,6 +2075,9 @@
</span><span class="cx"> $boundary = $ob->getContentTypeParameter('boundary');
</span><span class="cx"> if (!is_null($boundary)) {
</span><span class="cx"> foreach (self::_findBoundary($body, 0, $boundary) as $val) {
</span><ins>+ if (!isset($val['length'])) {
+ break;
+ }
</ins><span class="cx"> $subpart = substr($body, $val['start'], $val['length']);
</span><span class="cx"> list($hdr_pos, $eol) = self::_findHeader($subpart);
</span><span class="cx"> $ob->addPart(self::_getStructure(substr($subpart, 0, $hdr_pos), substr($subpart, $hdr_pos + $eol), array(
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeStreamFilterEolphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Stream/Filter/Eol.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Stream/Filter/Eol.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Stream/Filter/Eol.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -33,25 +33,34 @@
</span><span class="cx"> class Horde_Stream_Filter_Eol extends php_user_filter
</span><span class="cx"> {
</span><span class="cx"> /**
</span><ins>+ * Replacement data
+ *
+ * @var mixed
+ */
+ protected $_replace;
+
+ /**
</ins><span class="cx"> * Search array.
</span><span class="cx"> *
</span><del>- * @param mixed
</del><ins>+ * @var mixed
</ins><span class="cx"> */
</span><span class="cx"> protected $_search;
</span><span class="cx">
</span><span class="cx"> /**
</span><del>- * Replacement data
</del><ins>+ * First character of a multi-character EOL.
</ins><span class="cx"> *
</span><del>- * @param mixed
</del><ins>+ * @var string
</ins><span class="cx"> */
</span><del>- protected $_replace;
</del><ins>+ protected $_split = null;
</ins><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> * @see stream_filter_register()
</span><span class="cx"> */
</span><span class="cx"> public function onCreate()
</span><span class="cx"> {
</span><del>- $eol = isset($this->params['eol']) ? $this->params['eol'] : "\r\n";
</del><ins>+ $eol = isset($this->params['eol'])
+ ? $this->params['eol']
+ : "\r\n";
</ins><span class="cx">
</span><span class="cx"> if (!strlen($eol)) {
</span><span class="cx"> $this->_search = array("\r", "\n");
</span><span class="lines">@@ -62,6 +71,9 @@
</span><span class="cx"> } else {
</span><span class="cx"> $this->_search = array("\r\n", "\r", "\n");
</span><span class="cx"> $this->_replace = array("\n", "\n", $eol);
</span><ins>+ if (strlen($eol) > 1) {
+ $this->_split = $eol[0];
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> return true;
</span><span class="lines">@@ -73,6 +85,11 @@
</span><span class="cx"> public function filter($in, $out, &$consumed, $closing)
</span><span class="cx"> {
</span><span class="cx"> while ($bucket = stream_bucket_make_writeable($in)) {
</span><ins>+ if (!is_null($this->_split) &&
+ ($bucket->data[$bucket->datalen - 1] == $this->_split)) {
+ $bucket->data = substr($bucket->data, 0, -1);
+ }
+
</ins><span class="cx"> $bucket->data = str_replace($this->_search, $this->_replace, $bucket->data);
</span><span class="cx"> $consumed += $bucket->datalen;
</span><span class="cx"> stream_bucket_append($out, $bucket);
</span></span></pre></div>
<a id="2013codebykatpostbyemailtrunkincludeHordeSupportStubphp"></a>
<div class="modfile"><h4>Modified: 2013/codebykat/post-by-email/trunk/include/Horde/Support/Stub.php (2316 => 2317)</h4>
<pre class="diff"><span>
<span class="info">--- 2013/codebykat/post-by-email/trunk/include/Horde/Support/Stub.php 2013-09-16 02:11:18 UTC (rev 2316)
+++ 2013/codebykat/post-by-email/trunk/include/Horde/Support/Stub.php 2013-09-16 02:11:45 UTC (rev 2317)
</span><span class="lines">@@ -16,7 +16,7 @@
</span><span class="cx"> * @license http://www.horde.org/licenses/bsd BSD
</span><span class="cx"> * @package Support
</span><span class="cx"> */
</span><del>-class Horde_Support_Stub
</del><ins>+class Horde_Support_Stub implements ArrayAccess, Countable, IteratorAggregate
</ins><span class="cx"> {
</span><span class="cx"> /**
</span><span class="cx"> * Cooerce to an empty string.
</span><span class="lines">@@ -91,4 +91,50 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ /* ArrayAccess methods. */
+
+ /**
+ */
+ public function offsetGet($offset)
+ {
+ return null;
+ }
+
+ /**
+ */
+ public function offsetSet($offset, $value)
+ {
+ }
+
+ /**
+ */
+ public function offsetExists($offset)
+ {
+ return false;
+ }
+
+ /**
+ */
+ public function offsetUnset($offset)
+ {
+ }
+
+ /* Countable methods. */
+
+ /**
+ */
+ public function count()
+ {
+ return 0;
+ }
+
+ /* IteratorAggregate method. */
+
+ /**
+ */
+ public function getIterator()
+ {
+ return new ArrayIterator(array());
+ }
+
</ins><span class="cx"> }
</span></span></pre>
</div>
</div>
</body>
</html>