Skip to content

Commit

Permalink
Merge branch 'master' into bytestream-patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
bytestream authored Sep 11, 2023
2 parents 21413e1 + fed98c8 commit e764898
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 25 deletions.
5 changes: 4 additions & 1 deletion lib/Horde/Imap/Client/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ abstract class Horde_Imap_Client_Base
* DEFAULT: false
* - timeout: (integer) Connection timeout, in seconds.
* DEFAULT: 30 seconds
* - read_timeout: (integer) Read timeout, in seconds.
* DEFAULT: 120 seconds
* - username: (string) [REQUIRED] The username.
* - authusername (string) The username used for SASL authentication.
* If specified this is the user name whose password is used
Expand All @@ -251,7 +253,8 @@ public function __construct(array $params = array())
'context' => array(),
'hostspec' => 'localhost',
'secure' => false,
'timeout' => 30
'timeout' => 30,
'read_timeout' => 120,
), array_filter($params));

if (!isset($params['port']) && strpos($params['hostspec'], 'unix://') !== 0) {
Expand Down
5 changes: 5 additions & 0 deletions lib/Horde/Imap/Client/Exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ class Horde_Imap_Client_Exception extends Horde_Exception_Wrapped
*/
const SERVER_READERROR = 12;

/**
* Thrown if read timeout occurs.
*/
const SERVER_READTIMEOUT = 28;

/**
* Thrown if write error in server interaction.
*/
Expand Down
33 changes: 26 additions & 7 deletions lib/Horde/Imap/Client/Socket.php
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,9 @@ protected function _connect()
$this->getParam('context'),
array(
'debug' => $this->_debug,
'debugliteral' => $this->getParam('debug_literal')
'debugliteral' => $this->getParam('debug_literal'),
'timeout' => $this->getParam('timeout'),
'read_timeout' => $this->getParam('read_timeout'),
)
);
} catch (Horde\Socket\Client\Exception $e) {
Expand Down Expand Up @@ -4310,17 +4312,34 @@ protected function _sendCmdChunk($pipeline, $chunk)

while ($cmd_count) {
try {
if (! isset($read_start)) {
$read_start = microtime(true);
}

if ($this->_getLine($pipeline) instanceof Horde_Imap_Client_Interaction_Server_Tagged) {
--$cmd_count;
}

$read_start = null;
} catch (Horde_Imap_Client_Exception $e) {
switch ($e->getCode()) {
case $e::DISCONNECT:
/* Guaranteed to have no more data incoming, so we can
* immediately logout. */
$this->_temp['logout'] = true;
$this->logout();
throw $e;
case $e::DISCONNECT:
/* Guaranteed to have no more data incoming, so we can
* immediately logout. */
$this->_temp['logout'] = true;
$this->logout();
throw $e;

case $e::SERVER_READTIMEOUT:
$read_now = microtime(true);
$t_read = $read_now - $read_start;
if ($t_read <= $this->_params['read_timeout']) {
break;
}

$this->_temp['logout'] = true;
$this->logout();
throw $e;
}

/* For all other issues, catch and store exception; don't
Expand Down
60 changes: 44 additions & 16 deletions lib/Horde/Imap/Client/Socket/Connection/Socket.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,22 +183,50 @@ public function read($size = null)

$old_len = $literal_len;

while (($literal_len > 0) && !feof($this->_stream)) {
$in = fread($this->_stream, min($literal_len, 8192));
/* Only store in stream if this is something more than a
* nominal number of bytes. */
if ($old_len > 256) {
$token->addLiteralStream($in);
} else {
$token->add($in);
}
try {
stream_set_blocking($this->_stream, false);

if (!empty($this->_params['debugliteral'])) {
$this->_params['debug']->raw($in);
}
while (($literal_len > 0) && !feof($this->_stream)) {
$in = fread($this->_stream, min($literal_len, 8192));

if (empty($in)) {
if (! isset($read_start)) {
$read_start = microtime(true);
}

$read_now = microtime(true);
$t_read = $read_now - $read_start;
if ($t_read > $this->_params['timeout']) {
$this->_params['debug']->info(sprintf('ERROR: read timeout. No data received for %d seconds.', $this->_params['read_timeout']));

throw new Horde_Imap_Client_Exception(
Horde_Imap_Client_Translation::r("Read timeout."),
Horde_Imap_Client_Exception::SERVER_READTIMEOUT
);
}

continue;
}

$got_data = true;
$literal_len -= strlen($in);
$read_start = null;

/* Only store in stream if this is something more than a
* nominal number of bytes. */
if ($old_len > 256) {
$token->addLiteralStream($in);
} else {
$token->add($in);
}

if (!empty($this->_params['debugliteral'])) {
$this->_params['debug']->raw($in);
}

$got_data = true;
$literal_len -= strlen($in);
}
} finally {
stream_set_blocking($this->_stream, true);
}

$literal_len = null;
Expand All @@ -209,10 +237,10 @@ public function read($size = null)
} while (true);

if (!$got_data) {
$this->_params['debug']->info('ERROR: read/timeout error.');
$this->_params['debug']->info('ERROR: read timeout error.');
throw new Horde_Imap_Client_Exception(
Horde_Imap_Client_Translation::r("Error when communicating with the mail server."),
Horde_Imap_Client_Exception::SERVER_READERROR
Horde_Imap_Client_Exception::SERVER_READTIMEOUT
);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Horde/Imap/Client/Socket/Pop3.php
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ protected function _fetchCmd(Horde_Imap_Client_Fetch_Results $results,
case Horde_Imap_Client::FETCH_IMAPDATE:
foreach ($seq_ids as $id) {
$tmp = $this->_pop3Cache('hdrob', $id);
$results->get($lookup[$id])->setImapDate($tmp['Date']);
$results->get($lookup[$id])->setImapDate((string) $tmp['Date']);
}
break;

Expand Down

0 comments on commit e764898

Please sign in to comment.