* 'start' - (integer) If a portion of the full text is desired to be
* returned, the starting position is identified here.
* DEFAULT: The entire text is returned.
+ * 'stream' - (boolean) If true, returns a stream resource with the
+ * message data instead of a string.
* Return key: 'fullmsg'
- * Return format: (string) The full text of the entire message (or the
+ * Return format: (mixed) The full text of the entire message (or the
* portion of the text delineated by the 'start'/'length'
- * parameters).
+ * parameters). If the 'stream' parameter is set, returns
+ * a stream resource.
*
* Key: Horde_Imap_Client::FETCH_HEADERTEXT
* Desc: Returns the header text. Header text is defined only for the
* 'start' - (integer) If a portion of the full text is desired to be
* returned, the starting position is identified here.
* DEFAULT: The entire text is returned.
+ * 'stream' - (boolean) If true, returns a stream resource with the
+ * message data instead of a string.
* Return key: 'bodytext'
* Return format: (array) An array of body text entries. Keys are the
* the 'id', values are the message body text strings
* (or the portion of the text delineated by the
- * 'start'/'length' parameters).
+ * 'start'/'length' parameters). If the 'stream'
+ * parameter is set, returns a stream resource.
*
* Key: Horde_Imap_Client::FETCH_MIMEHEADER
* Desc: Returns the MIME header text. MIME header text is defined only
* 'start' - (integer) If a portion of the full data is desired to be
* returned, the starting position is identified here.
* DEFAULT: The entire data is returned.
+ * 'stream' - (boolean) If true, returns a stream resource with the
+ * message data instead of a string.
* Return key: 'bodypart' (and possibly 'bodypartdecode')
* Return format: (array) An array of body part data entries. Keys are
* the 'id', values are the body part data (or the
* portion of the data delineated by the 'start'/'length'
- * parameters).
+ * parameters). If the 'stream' parameter is set, returns
+ * a stream resource.
*
* Key: Horde_Imap_Client::FETCH_BODYPARTSIZE
* Desc: Returns the decoded body part size for a given MIME ID.
{
$t = &$this->_temp;
$t['fetchparams'] = array();
+ $t['literalstream'] = array();
$fp = &$t['fetchparams'];
$fetch = array();
break;
case Horde_Imap_Client::FETCH_FULLMSG:
+ if (!empty($c_val['stream'])) {
+ $this->_temp['literalstream'][] = 'BODY[]';
+ }
+
if (empty($c_val['peek'])) {
$this->openMailbox($this->_selected, Horde_Imap_Client::OPEN_READWRITE);
}
case Horde_Imap_Client::FETCH_BODYPART:
case Horde_Imap_Client::FETCH_HEADERS:
foreach ($c_val as $val) {
- $cmd = empty($val['id'])
+ $base_id = $cmd = empty($val['id'])
? ''
: $val['id'] . '.';
$main_cmd = 'BODY';
break;
case Horde_Imap_Client::FETCH_BODYTEXT:
+ if (!empty($val['stream'])) {
+ $this->_temp['literalstream'][] = $main_cmd . '[' . $base_id . 'TEXT]';
+ }
$cmd .= 'TEXT';
break;
if (empty($val['id'])) {
throw new Horde_Imap_Client_Exception('Need a non-zero MIME ID when retrieving a MIME body part.');
}
+
+ if (!empty($val['stream'])) {
+ $this->_temp['literalstream'][] = $main_cmd . '[' . $val['id'] . ']';
+ }
+
// Remove the last dot from the string.
$cmd = substr($cmd, 0, -1);
$this->_sendLine($cmd);
+ $t['literalstream'] = array();
+
return $t['fetchresp'][$use_seq ? 'seq' : 'uid'];
}
$tmp['fullmsg'] = $data[++$i];
} elseif (is_numeric(substr($tag, -1))) {
// BODY[MIMEID] request
- if (!isset($tmp['bodypart'])) {
- $tmp['bodypart'] = array();
- }
$tmp['bodypart'][$tag] = $data[++$i];
} else {
// BODY[HEADER|TEXT|MIME] request
do {
$literal_len = null;
- if (!$literal && (substr($line, -1) == '}')) {
- $pos = strrpos($line, '{');
- $literal_len = substr($line, $pos + 1, -1);
- if (is_numeric($literal_len)) {
- // Check for literal8 response
- if ($line[$pos - 1] == '~') {
- $binary = true;
- $line = substr($line, 0, $pos - 1);
- $this->_temp['literal8'][substr($line, strrpos($line, ' '))] = true;
+ if ($literal) {
+ $this->_temp['token']['ptr'][$this->_temp['token']['paren']][] = $line;
+ } else {
+ if (substr($line, -1) == '}') {
+ $pos = strrpos($line, '{');
+ $literal_len = substr($line, $pos + 1, -1);
+ if (is_numeric($literal_len)) {
+ // Check for literal8 response
+ if ($line[$pos - 1] == '~') {
+ $binary = true;
+ $line = substr($line, 0, $pos - 1);
+ $this->_temp['literal8'][substr($line, strrpos($line, ' '))] = true;
+ } else {
+ $line = substr($line, 0, $pos);
+ }
} else {
- $line = substr($line, 0, $pos);
+ $literal_len = null;
}
- } else {
- $literal_len = null;
}
- }
- if ($literal) {
- $this->_temp['token']['ptr'][$this->_temp['token']['paren']][] = $line;
- } else {
$this->_tokenizeData($line);
}
}
$data = '';
+ $got_data = $stream = false;
if (is_null($len)) {
do {
/* Can't do a straight fgets() because extremely large lines
* will result in read errors. */
- if ($tmp = fgets($this->_stream, 8192)) {
- $data .= $tmp;
- if (!isset($tmp[8190]) || ($tmp[8190] == "\n")) {
+ if ($in = fgets($this->_stream, 8192)) {
+ $data .= $in;
+ $got_data = true;
+ if (!isset($in[8190]) || ($in[8190] == "\n")) {
break;
}
}
- } while ($tmp !== false);
+ } while ($in !== false);
} else {
// Skip 0-length literal data
if (!$len) {
return $data;
}
+ // Add data to a stream, if desired.
+ if (!empty($this->_temp['literalstream']) &&
+ in_array(end($this->_temp['token']['ptr'][$this->_temp['token']['paren']]), $this->_temp['literalstream'])) {
+ $data = fopen('php://temp', 'r+');
+ $stream = true;
+ }
+
while ($len && ($in = fread($this->_stream, min($len, 8192)))) {
- $data .= $in;
+ if ($stream) {
+ fwrite($data, $in);
+ } else {
+ $data .= $in;
+ }
+
+ $got_data = true;
+
$in_len = strlen($in);
if ($in_len > $len) {
break;
}
}
- if (!strlen($data)) {
+ if (!$got_data) {
if ($this->_debug) {
fwrite($this->_debug, '[ERROR: IMAP read/timeout error.]' . "\n");
}
}
if ($this->_debug) {
- fwrite($this->_debug, 'S (' . microtime(true) . '): ' . ($binary ? '[BINARY DATA - ' . $len . ' bytes]' : $data));
+ if ($stream) {
+ rewind($data);
+ }
+
+ fwrite($this->_debug, 'S (' . microtime(true) . '): ' . ($binary ? '[BINARY DATA - ' . $len . ' bytes]' : ($stream ? stream_get_contents($data): $data)));
}
return is_null($len) ? rtrim($data) : $data;