Exemple #1
0
 public function parsePgpDataProvider()
 {
     $data = file_get_contents(__DIR__ . '/fixtures/pgp_signed.txt');
     $stream = new Horde_Stream_Temp();
     $stream->add($data, true);
     return array(array($data), array($stream));
 }
Exemple #2
0
 public function escapeStream()
 {
     if (is_null($this->_data)) {
         $stream = new Horde_Stream_Temp();
         $stream->add('NIL', true);
         return $stream->stream;
     }
     return parent::escapeStream();
 }
Exemple #3
0
 /**
  * Return the escaped string as a stream.
  *
  * @return resource  The IMAP escaped stream.
  */
 public function escapeStream()
 {
     if ($this->literal()) {
         throw new Horde_Imap_Client_Data_Format_Exception('String requires literal to output.');
     }
     rewind($this->_data->stream);
     $stream = new Horde_Stream_Temp();
     $stream->add($this->_data, true);
     stream_filter_register('horde_imap_client_string_quote', 'Horde_Imap_Client_Data_Format_Filter_Quote');
     stream_filter_append($stream->stream, 'horde_imap_client_string_quote', STREAM_FILTER_READ);
     return $stream->stream;
 }
Exemple #4
0
 /**
  * @dataProvider parsePgpDataProvider
  */
 public function testParsePgpData($fixture, $expected, $headers)
 {
     $data = file_get_contents(__DIR__ . '/fixtures/' . $fixture);
     $stream = new Horde_Stream_Temp();
     $stream->add($data, true);
     $obs = array(new Horde_Pgp_Armor($data), new Horde_Pgp_Armor($stream));
     foreach ($obs as $ob) {
         $this->assertEquals(count($expected), count($ob));
         $i = 0;
         foreach ($ob as $val) {
             $this->assertEquals($expected[$i++], get_class($val));
             $this->assertEquals($headers, $val->headers);
         }
     }
 }
Exemple #5
0
 /**
  */
 protected function _read()
 {
     try {
         if (method_exists($this->_vfs, 'readStream')) {
             $stream = new Horde_Stream_Existing(array('stream' => $this->_vfs->readStream($this->_vfspath, $this->_id)));
             $stream->rewind();
         } else {
             $stream = new Horde_Stream_Temp();
             $stream->add($this->_vfs->read($this->_vfspath, $this->_id), true);
         }
         return $stream;
     } catch (Horde_Vfs_Exception $e) {
         throw new IMP_Compose_Exception($e);
     }
 }
Exemple #6
0
 /**
  */
 protected function _get($keys)
 {
     if (!$this->_stream) {
         return parent::_get($keys);
     }
     $out = array();
     foreach ($keys as $key) {
         try {
             if (method_exists($this->_vfs, 'readStream')) {
                 $data = new Horde_Stream_Existing(array('stream' => $this->_vfs->readStream($this->_params['vfspath'], $key)));
                 $data->rewind();
             } else {
                 $data = new Horde_Stream_Temp();
                 $data->add($this->_vfs->read($this->_params['vfspath'], $key), true);
             }
         } catch (Horde_Vfs_Exception $e) {
             $data = false;
         }
         $out[$key] = $data;
     }
     return $out;
 }
Exemple #7
0
 /**
  * Validate the body data to ensure consistent EOL and UTF8 data. Returns
  * body data in a stream object.
  *
  * @param array $data  The body data. @see self::_bodyPartText() for
  *                     structure.
  *
  * @return array  The validated body data array. @see self::_bodyPartText()
  */
 protected function _validateBodyData(&$data)
 {
     $stream = new Horde_Stream_Temp(array('max_memory' => 1048576));
     $filter_h = stream_filter_append($stream->stream, 'horde_eol', STREAM_FILTER_WRITE);
     $stream->add(Horde_ActiveSync_Utils::ensureUtf8($data['body'], $data['charset']), true);
     stream_filter_remove($filter_h);
     $data['body'] = $stream;
 }
Exemple #8
0
 /**
  * Prepares append message data for insertion into the IMAP command
  * string.
  *
  * @param mixed $data  Either a resource or a string.
  *
  * @param Horde_Stream  A stream containing the data.
  */
 protected function _appendData($data)
 {
     $stream = new Horde_Stream_Temp();
     stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol');
     $res = stream_filter_append($stream->stream, 'horde_eol', STREAM_FILTER_WRITE);
     if (is_resource($data)) {
         rewind($data);
     }
     $stream->add($data, true);
     $this->_temp['appendsize'] += $stream->length();
     stream_filter_remove($res);
     return $stream;
 }
Exemple #9
0
 /**
  */
 public function add($data, $reset = false)
 {
     if ($this->_string && is_string($data)) {
         if (strlen($data) + $this->_string->length() < $this->_params['max_memory']) {
             $this->_string->add($data, $reset);
             return;
         }
         parent::_init();
         parent::add(strval($this->_string));
         $this->seek($this->_string->pos(), false);
         unset($this->_string);
     }
     parent::add($data, $reset);
 }
Exemple #10
0
 /**
  * If this MIME part can contain embedded MIME part(s), and those part(s)
  * exist, return a representation of that data.
  *
  * @return mixed  A Horde_Mime_Part object representing the embedded data.
  *                Returns null if no embedded MIME part(s) exist.
  */
 protected function _getEmbeddedMimeParts()
 {
     if ($this->_mimepart->getType() != 'multipart/encrypted') {
         return null;
     }
     $imp_contents = $this->getConfigParam('imp_contents');
     $iterator = $this->_mimepart->partIterator();
     $iterator->rewind();
     $base_id = $iterator->current()->getMimeId();
     $iterator->next();
     $version_id = $iterator->current()->getMimeId();
     $id_ob = new Horde_Mime_Id($version_id);
     $data_id = $id_ob->idArithmetic($id_ob::ID_NEXT);
     $status = new IMP_Mime_Status($this->_mimepart);
     $status->icon('mime/encryption.png', 'PGP');
     $cache = $imp_contents->getViewCache();
     $cache->pgp[$base_id] = array('status' => array($status), 'other' => array($version_id => null, $data_id => null), 'wrap' => '');
     /* Is PGP active? */
     if (!IMP_Pgp::enabled()) {
         $status->addText(_("The data in this part has been encrypted via PGP, however, PGP support is disabled so the message cannot be decrypted."));
         return null;
     }
     /* PGP version information appears in the first MIME subpart. We
      * don't currently need to do anything with this information. The
      * encrypted data appears in the second MIME subpart. */
     if (!($encrypted_part = $imp_contents->getMimePart($data_id))) {
         return null;
     }
     $encrypted_data = $encrypted_part->getContents();
     $symmetric_pass = $personal_pass = null;
     /* Check if this a symmetrically encrypted message. */
     try {
         $imp_pgp = $GLOBALS['injector']->getInstance('IMP_Pgp');
         $symmetric = $imp_pgp->encryptedSymmetrically($encrypted_data);
         if ($symmetric) {
             $symmetric_id = $this->_getSymmetricID();
             $symmetric_pass = $imp_pgp->getPassphrase('symmetric', $symmetric_id);
             if (is_null($symmetric_pass)) {
                 $status->addText(_("The data in this part has been encrypted via PGP."));
                 /* Ask for the correct passphrase if this is encrypted
                  * symmetrically. */
                 $imple = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create('IMP_Ajax_Imple_PassphraseDialog', array('params' => array('symmetricid' => $symmetric_id), 'type' => 'pgpSymmetric'));
                 $status->addText(Horde::link('#', '', '', '', '', '', '', array('id' => $imple->getDomId())) . _("You must enter the passphrase used to encrypt this message to view it.") . '</a>');
                 return null;
             }
         }
     } catch (Horde_Exception $e) {
         Horde::log($e, 'INFO');
         return null;
     }
     /* Check if this is a literal compressed message. */
     try {
         $info = $imp_pgp->pgpPacketInformation($encrypted_data);
     } catch (Horde_Exception $e) {
         Horde::log($e, 'INFO');
         return null;
     }
     $literal = !empty($info['literal']);
     if ($literal) {
         $status->addText(_("The data in this part has been compressed via PGP."));
     } else {
         $status->addText(_("The data in this part has been encrypted via PGP."));
         if (!$symmetric) {
             if ($imp_pgp->getPersonalPrivateKey()) {
                 $personal_pass = $imp_pgp->getPassphrase('personal');
                 if (is_null($personal_pass)) {
                     /* Ask for the private key's passphrase if this is
                      * encrypted asymmetrically. */
                     $imple = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create('IMP_Ajax_Imple_PassphraseDialog', array('type' => 'pgpPersonal'));
                     $status->addText(Horde::link('#', '', '', '', '', '', '', array('id' => $imple->getDomId())) . _("You must enter the passphrase for your PGP private key to view this message.") . '</a>');
                     return null;
                 }
             } else {
                 /* Output if there is no personal private key to decrypt
                  * with. */
                 $status->addText(_("However, no personal private key exists so the message cannot be decrypted."));
                 return null;
             }
         }
     }
     try {
         if (!is_null($symmetric_pass)) {
             $decrypted_data = $imp_pgp->decryptMessage($encrypted_data, 'symmetric', array('passphrase' => $symmetric_pass, 'sender' => $this->_getSender()->bare_address));
         } elseif (!is_null($personal_pass)) {
             $decrypted_data = $imp_pgp->decryptMessage($encrypted_data, 'personal', array('passphrase' => $personal_pass, 'sender' => $this->_getSender()->bare_address));
         } else {
             $decrypted_data = $imp_pgp->decryptMessage($encrypted_data, 'literal');
         }
     } catch (Horde_Exception $e) {
         $status->addText(_("The data in this part does not appear to be a valid PGP encrypted message. Error: ") . $e->getMessage());
         if (!is_null($symmetric_pass)) {
             $imp_pgp->unsetPassphrase('symmetric', $this->_getSymmetricID());
             return $this->_getEmbeddedMimeParts();
         }
         return null;
     }
     $cache->pgp[$base_id]['wrap'] = 'mimePartWrapValid';
     /* Check for combined encryption/signature data. */
     if ($decrypted_data->result) {
         $sig_text = is_bool($decrypted_data->result) ? _("The data in this part has been digitally signed via PGP.") : $this->_textFilter($decrypted_data->result, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::NOHTML));
         $status2 = new IMP_Mime_Status($this->_mimepart, $sig_text);
         $status2->action(IMP_Mime_Status::SUCCESS);
         $cache->pgp[$base_id]['status'][] = $status2;
     }
     /* Force armor data as text/plain data. */
     if ($this->_mimepart->getMetadata(Horde_Crypt_Pgp_Parse::PGP_ARMOR)) {
         $decrypted_data->message = "Content-Type: text/plain\n\n" . $decrypted_data->message;
     }
     $new_part = Horde_Mime_Part::parseMessage($decrypted_data->message, array('forcemime' => true));
     if ($new_part->getType() == 'multipart/signed') {
         $data = new Horde_Stream_Temp();
         try {
             $data->add(Horde_Mime_Part::getRawPartText($decrypted_data->message, 'header', '1'));
             $data->add("\n\n");
             $data->add(Horde_Mime_Part::getRawPartText($decrypted_data->message, 'body', '1'));
         } catch (Horde_Mime_Exception $e) {
         }
         $new_part->setMetadata(self::PGP_SIGN_ENC, $data->stream);
         $new_part->setContents($decrypted_data->message, array('encoding' => 'binary'));
     }
     return $new_part;
 }
Exemple #11
0
 /**
  * Get the raw message suitable for saving to the sent email folder.
  *
  * @return stream  A stream contianing the raw message.
  */
 public function getSentMail()
 {
     if (!empty($this->_mailer)) {
         return $this->_mailer->getRaw();
     }
     $stream = new Horde_Stream_Temp(array('max_memory' => 262144));
     $stream->add($this->_headers->toString(array('charset' => 'UTF-8')) . $this->_raw->getMessage(), true);
     return $stream;
 }
Exemple #12
0
 /**
  * Parses a message into text and PGP components.
  *
  * @param mixed $text  Either the text to parse or a Horde_Stream object.
  *
  * @return array  An array with the parsed text, returned in blocks of
  *                text corresponding to their actual order. Keys:
  * <pre>
  *   - data: (array) The data for each section. Each line has been
  *           stripped of EOL characters.
  *   - type: (integer) The type of data contained in block. Valid types
  *           are the class ARMOR_* constants.
  * </pre>
  */
 public function parse($text)
 {
     $data = array();
     $temp = array('type' => self::ARMOR_TEXT);
     if ($text instanceof Horde_Stream) {
         $stream = $text;
         $stream->rewind();
     } else {
         $stream = new Horde_Stream_Temp();
         $stream->add($text, true);
     }
     while (!$stream->eof()) {
         $val = rtrim($stream->getToChar("\n", false), "\r");
         if (strpos($val, '-----') === 0 && preg_match('/^-----(BEGIN|END) PGP ([^-]+)-----\\s*$/', $val, $matches)) {
             if (isset($temp['data'])) {
                 $data[] = $temp;
             }
             $temp = array();
             if ($matches[1] == 'BEGIN') {
                 $temp['type'] = $this->_armor[$matches[2]];
                 $temp['data'][] = $val;
             } elseif ($matches[1] == 'END') {
                 $temp['type'] = self::ARMOR_TEXT;
                 $data[count($data) - 1]['data'][] = $val;
             }
         } else {
             $temp['data'][] = $val;
         }
     }
     if (isset($temp['data']) && (count($temp['data']) > 1 || !empty($temp['data'][0]))) {
         $data[] = $temp;
     }
     return $data;
 }
Exemple #13
0
 /**
  * Converts and validates the message body data structure.
  *
  * @param array $data  Message body data structure.
  *
  * @return array  The message body data structure, with the [html][body] and
  *                [plain][body] data converted to UTF-8, EOL normalized and
  *                placed in a stream.
  */
 protected function _validateMessageBodyData($data)
 {
     //We will need the eol filter to work around PHP bug 65776.
     stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol');
     if (!empty($data['plain'])) {
         $stream = new Horde_Stream_Temp(array('max_memory' => 1048576));
         $filter_h = stream_filter_append($stream->stream, 'horde_eol', STREAM_FILTER_WRITE);
         $stream->add(Horde_ActiveSync_Utils::ensureUtf8($data['plain']['body'], $data['plain']['charset']), true);
         stream_filter_remove($filter_h);
         $data['plain']['body'] = $stream;
     }
     if (!empty($data['html'])) {
         $stream = new Horde_Stream_Temp(array('max_memory' => 1048576));
         $filter_h = stream_filter_append($stream->stream, 'horde_eol', STREAM_FILTER_WRITE);
         $stream->add(Horde_ActiveSync_Utils::ensureUtf8($data['html']['body'], $data['html']['charset']), true);
         stream_filter_remove($filter_h);
         $data['html']['body'] = $stream;
     }
     return $data;
 }
Exemple #14
0
 /**
  * Returns the raw message with the message headers stripped.
  *
  * @return Horde_Stream
  */
 public function getMessage()
 {
     // Position to after the headers.
     fseek($this->_stream->stream, $this->_hdr_pos + $this->_eol);
     $new_stream = new Horde_Stream_Temp(array('max_memory' => self::$memoryLimit));
     $new_stream->add($this->_stream, true);
     return $new_stream;
 }
Exemple #15
0
 /**
  * Split the sequence string at an approximate length.
  *
  * @since 2.7.0
  *
  * @param integer $length  Length to split.
  *
  * @return array  A list containing individual sequence strings.
  */
 public function split($length)
 {
     $id = new Horde_Stream_Temp();
     $id->add($this->tostring_sort, true);
     $out = array();
     do {
         $out[] = $id->substring(0, $length) . $id->getToChar(',');
     } while (!$id->eof());
     return $out;
 }
Exemple #16
0
 /**
  * Parse enveloped (encrypted) data.
  *
  * @return mixed  See self::_getEmbeddedMimeParts().
  */
 protected function _parseEnvelopedData()
 {
     $base_id = $this->_mimepart->getMimeId();
     /* Initialize inline data. */
     $status = new IMP_Mime_Status(_("The data in this part has been encrypted via S/MIME."));
     $status->icon('mime/encryption.png', 'S/MIME');
     $cache = $this->getConfigParam('imp_contents')->getViewCache();
     $cache->smime[$base_id] = array('status' => $status, 'wrap' => '');
     /* Is PGP active? */
     $this->_initSmime();
     if (empty($this->_impsmime)) {
         $status->addText(_("S/MIME support is not currently enabled so the data is unable to be decrypted."));
         return null;
     }
     if (!$this->_impsmime->getPersonalPrivateKey()) {
         $status->addText(_("No personal private key exists so the data is unable to be decrypted."));
         return null;
     }
     /* Make sure we have a passphrase. */
     $passphrase = $this->_impsmime->getPassphrase();
     if ($passphrase === false) {
         $imple = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create('IMP_Ajax_Imple_PassphraseDialog', array('type' => 'smimePersonal'));
         $status->addText(Horde::link('#', '', '', '', '', '', '', array('id' => $imple->getDomId())) . _("You must enter the passphrase for your S/MIME private key to view this data.") . '</a>');
         return null;
     }
     $raw_text = $this->_getPartStream($this->_mimepart->getMimeId());
     try {
         $decrypted_data = $this->_impsmime->decryptMessage($this->_mimepart->replaceEOL($raw_text, Horde_Mime_Part::RFC_EOL));
     } catch (Horde_Exception $e) {
         $status->addText($e->getMessage());
         return null;
     }
     $cache->smime[$base_id]['wrap'] = 'mimePartWrapValid';
     $new_part = Horde_Mime_Part::parseMessage($decrypted_data, array('forcemime' => true));
     switch ($new_part->getType()) {
         case 'application/pkcs7-mime':
         case 'application/x-pkcs7-mime':
             $signed_data = $this->_getSmimeType($new_part) === 'signed-data';
             break;
         case 'multipart/signed':
             $signed_data = true;
             break;
         default:
             $signed_data = false;
             break;
     }
     if ($signed_data) {
         $hdrs = $this->getConfigParam('imp_contents')->getHeader();
         $data = new Horde_Stream_Temp();
         $data->add('From:' . $hdrs->getValue('from') . "\n" . $decrypted_data);
         $new_part->setMetadata('imp-smime-decrypt', $data);
         $new_part->setContents($decrypted_data, array('encoding' => 'binary'));
     }
     return $new_part;
 }
Exemple #17
0
 /**
  * @return mixed  Either a string, boolean (true for open paren, false for
  *                close paren/EOS), Horde_Stream object, or null.
  */
 public function next()
 {
     $level = isset($this->_nextModify['level']) ? $this->_nextModify['level'] : null;
     /* Directly access stream here to drastically reduce the number of
      * getChar() calls we would have to make. */
     $stream = $this->_stream->stream;
     do {
         $check_len = true;
         $in_quote = $text = $binary = false;
         while (($c = fgetc($stream)) !== false) {
             switch ($c) {
                 case '\\':
                     $text .= $in_quote ? fgetc($stream) : $c;
                     break;
                 case '"':
                     if ($in_quote) {
                         $check_len = false;
                         break 2;
                     }
                     $in_quote = true;
                     /* Set $text to non-false (could be empty string). */
                     $text = '';
                     break;
                 default:
                     if ($in_quote) {
                         $text .= $c;
                         break;
                     }
                     switch ($c) {
                         case '(':
                             ++$this->_level;
                             $check_len = false;
                             $text = true;
                             break 3;
                         case ')':
                             if ($text === false) {
                                 --$this->_level;
                                 $check_len = $text = false;
                             } else {
                                 $this->_stream->seek(-1);
                             }
                             break 3;
                         case '~':
                             // Ignore binary string identifier. PHP strings are
                             // binary-safe. But keep it if it is not used as string
                             // identifier.
                             $binary = true;
                             $text .= $c;
                             continue;
                         case '{':
                             if ($binary) {
                                 $text = substr($text, 0, -1);
                             }
                             $literal_len = intval($this->_stream->getToChar('}'));
                             $pos = $this->_stream->pos();
                             if (isset($this->_literals[$pos])) {
                                 $text = $this->_literals[$pos];
                                 if (!$this->_literalStream) {
                                     $text = strval($text);
                                 }
                             } elseif ($this->_literalStream) {
                                 $text = new Horde_Stream_Temp();
                                 while ($literal_len > 0 && !feof($stream)) {
                                     $part = $this->_stream->substring(0, min($literal_len, 8192));
                                     $text->add($part);
                                     $literal_len -= strlen($part);
                                 }
                             } else {
                                 $text = $this->_stream->substring(0, $literal_len);
                             }
                             $check_len = false;
                             break 3;
                         case ' ':
                             if ($text !== false) {
                                 break 3;
                             }
                             break;
                         default:
                             $text .= $c;
                             break;
                     }
                     break;
             }
             $binary = false;
         }
         if ($check_len) {
             switch (strlen($text)) {
                 case 0:
                     $text = false;
                     break;
                 case 3:
                     if (strcasecmp($text, 'NIL') === 0) {
                         $text = null;
                     }
                     break;
             }
         }
         if ($text === false && feof($stream)) {
             $this->_key = $this->_level = false;
             break;
         }
         ++$this->_key;
         if (is_null($level) || $level > $this->_level) {
             break;
         }
         if ($level === $this->_level && !is_bool($text)) {
             $this->_nextModify['out'][] = $text;
         }
     } while (true);
     $this->_current = $text;
     return $text;
 }
Exemple #18
0
 /**
  * Builds a Horde_Mime_Headers object from header text.
  *
  * @param mixed $text  A text string (or, as of 2.3.0, a Horde_Stream
  *                     object or stream resource) containing the headers.
  *
  * @return Horde_Mime_Headers  A new Horde_Mime_Headers object.
  */
 public static function parseHeaders($text)
 {
     $currheader = $currtext = null;
     $mime = self::mimeParamFields();
     $to_process = array();
     if ($text instanceof Horde_Stream) {
         $stream = $text;
         $stream->rewind();
     } else {
         $stream = new Horde_Stream_Temp();
         $stream->add($text, true);
     }
     while (!$stream->eof()) {
         if (!($val = rtrim($stream->getToChar("\n", false), "\r"))) {
             break;
         }
         if ($val[0] == ' ' || $val[0] == "\t") {
             $currtext .= ' ' . ltrim($val);
         } else {
             if (!is_null($currheader)) {
                 $to_process[] = array($currheader, rtrim($currtext));
             }
             $pos = strpos($val, ':');
             $currheader = substr($val, 0, $pos);
             $currtext = ltrim(substr($val, $pos + 1));
         }
     }
     if (!is_null($currheader)) {
         $to_process[] = array($currheader, $currtext);
     }
     $headers = new Horde_Mime_Headers();
     reset($to_process);
     while (list(, $val) = each($to_process)) {
         /* Ignore empty headers. */
         if (!strlen($val[1])) {
             continue;
         }
         if (in_array(Horde_String::lower($val[0]), $mime)) {
             $res = Horde_Mime::decodeParam($val[0], $val[1]);
             $headers->addHeader($val[0], $res['val'], array('params' => $res['params'], 'sanity_check' => true));
         } else {
             $headers->addHeader($val[0], $val[1], array('sanity_check' => true));
         }
     }
     return $headers;
 }
Exemple #19
0
 public function testParsePGPData()
 {
     $data = file_get_contents(__DIR__ . '/fixtures/pgp_signed.txt');
     $this->_testParsePGPData($data);
     $stream = new Horde_Stream_Temp();
     $stream->add($data, true);
     $this->_testParsePGPData($stream);
 }
Exemple #20
0
 /**
  */
 protected function _append(Horde_Imap_Client_Mailbox $mailbox, $data, $options)
 {
     // Check for MULTIAPPEND extension (RFC 3502)
     if (count($data) > 1 && !$this->queryCapability('MULTIAPPEND')) {
         $result = $this->getIdsOb();
         foreach (array_keys($data) as $key) {
             $res = $this->_append($mailbox, array($data[$key]), $options);
             if ($res === true || $result === true) {
                 $result = true;
             } else {
                 $result->add($res);
             }
         }
         return $result;
     }
     // Check for CATENATE extension (RFC 4469)
     $catenate = $this->queryCapability('CATENATE');
     $asize = 0;
     $cmd = $this->_command('APPEND')->add(new Horde_Imap_Client_Data_Format_Mailbox($mailbox));
     $cmd->literal8 = true;
     foreach (array_keys($data) as $key) {
         if (!empty($data[$key]['flags'])) {
             $tmp = new Horde_Imap_Client_Data_Format_List();
             foreach ($data[$key]['flags'] as $val) {
                 /* Ignore recent flag. RFC 3501 [9]: flag definition */
                 if (strcasecmp($val, Horde_Imap_Client::FLAG_RECENT) !== 0) {
                     $tmp->add($val);
                 }
             }
             $cmd->add($tmp);
         }
         if (!empty($data[$key]['internaldate'])) {
             $cmd->add(new Horde_Imap_Client_Data_Format_DateTime($data[$key]['internaldate']));
         }
         if (is_array($data[$key]['data'])) {
             if ($catenate) {
                 $cmd->add('CATENATE');
                 $tmp = new Horde_Imap_Client_Data_Format_List();
             } else {
                 $data_stream = new Horde_Stream_Temp();
             }
             reset($data[$key]['data']);
             while (list(, $v) = each($data[$key]['data'])) {
                 switch ($v['t']) {
                     case 'text':
                         if ($catenate) {
                             $tmp->add(array('TEXT', $this->_appendData($v['v'], $asize)));
                         } else {
                             if (is_resource($v['v'])) {
                                 rewind($v['v']);
                             }
                             $data_stream->add($v['v']);
                         }
                         break;
                     case 'url':
                         if ($catenate) {
                             $tmp->add(array('URL', new Horde_Imap_Client_Data_Format_Astring($v['v'])));
                         } else {
                             $data_stream->add($this->_convertCatenateUrl($v['v']));
                         }
                         break;
                 }
             }
             if ($catenate) {
                 $cmd->add($tmp);
             } else {
                 $cmd->add($this->_appendData($data_stream->stream, $asize));
             }
         } else {
             $cmd->add($this->_appendData($data[$key]['data'], $asize));
         }
     }
     /* Although it is normally more efficient to use LITERAL+, disable if
      * payload is over 0.5 MB because it allows the server to throw error
      * before we potentially push a lot of data to server that would
      * otherwise be ignored (see RFC 4549 [4.2.2.3]).
      * Additionally, if using BINARY, since so many IMAP servers have
      * issues with APPEND + BINARY, don't use LITERAL+ since servers may
      * send BAD after initial command. */
     $cmd->literalplus = $asize < 524288 && !$this->queryCapability('BINARY');
     // If the mailbox is currently selected read-only, we need to close
     // because some IMAP implementations won't allow an append. And some
     // implementations don't support append on ANY open mailbox. Be safe
     // and always make sure we are in a non-selected state.
     $this->close();
     try {
         $resp = $this->_sendCmd($cmd);
     } catch (Horde_Imap_Client_Exception $e) {
         switch ($e->getCode()) {
             case $e::CATENATE_BADURL:
             case $e::CATENATE_TOOBIG:
                 /* Cyrus 2.4 (at least as of .14) has a broken CATENATE (see
                  * Bug #11111). Regardless, if CATENATE is broken, we can try
                  * to fallback to APPEND. */
                 $this->_unsetCapability('CATENATE');
                 return $this->_append($mailbox, $data, $options);
             case $e::DISCONNECT:
                 /* Workaround broken literal8 on Cyrus. */
                 if ($this->queryCapability('BINARY')) {
                     // Need to re-login first before removing capability.
                     $this->login();
                     $this->_unsetCapability('BINARY');
                     return $this->_append($mailbox, $data, $options);
                 }
                 break;
         }
         if (!empty($options['create']) && !empty($e->resp_data['trycreate'])) {
             $this->createMailbox($mailbox);
             unset($options['create']);
             return $this->_append($mailbox, $data, $options);
         }
         /* RFC 3516/4466 says we should be able to append binary data
          * using literal8 "~{#} format", but it doesn't seem to work on
          * all servers tried (UW-IMAP/Cyrus). Do a last-ditch check for
          * broken BINARY and attempt to fix here. */
         if ($this->queryCapability('BINARY') && $e instanceof Horde_Imap_Client_Exception_ServerResponse) {
             switch ($e->status) {
                 case Horde_Imap_Client_Interaction_Server::BAD:
                 case Horde_Imap_Client_Interaction_Server::NO:
                     $this->_unsetCapability('BINARY');
                     return $this->_append($mailbox, $data, $options);
             }
         }
         throw $e;
     }
     /* If we reach this point and have data in 'appenduid', UIDPLUS (RFC
      * 4315) has done the dirty work for us. */
     return isset($resp->data['appenduid']) ? $resp->data['appenduid'] : true;
 }
Exemple #21
0
 /**
  */
 public function getStream()
 {
     $stream = new Horde_Stream_Temp();
     $stream->add($this->_mailbox->utf7imap);
     return $stream;
 }
Exemple #22
0
 /**
  */
 public function getStream()
 {
     $stream = new Horde_Stream_Temp();
     $stream->add($this->_mailbox->{$this->_encoding});
     return $stream;
 }
Exemple #23
0
 /**
  * Builds a Horde_Mime_Headers object from header text.
  *
  * @param mixed $text  A text string (or, as of 2.3.0, a Horde_Stream
  *                     object or stream resource) containing the headers.
  *
  * @return Horde_Mime_Headers  A new Horde_Mime_Headers object.
  */
 public static function parseHeaders($text)
 {
     $curr = null;
     $headers = new Horde_Mime_Headers();
     $hdr_list = array();
     if ($text instanceof Horde_Stream) {
         $stream = $text;
         $stream->rewind();
     } else {
         $stream = new Horde_Stream_Temp();
         $stream->add($text, true);
     }
     while (!$stream->eof()) {
         if (!($val = rtrim($stream->getToChar("\n", false), "\r"))) {
             break;
         }
         if ($curr && ($val[0] == ' ' || $val[0] == "\t")) {
             $curr->text .= ' ' . ltrim($val);
         } else {
             $pos = strpos($val, ':');
             $curr = new stdClass();
             $curr->header = substr($val, 0, $pos);
             $curr->text = ltrim(substr($val, $pos + 1));
             $hdr_list[] = $curr;
         }
     }
     foreach ($hdr_list as $val) {
         /* When parsing, only keep the FIRST header seen for single value
          * text-only headers, since newer headers generally are appended
          * to the top of the message. */
         if (!($ob = $headers[$val->header]) || !$ob instanceof Horde_Mime_Headers_Element_Single || $ob instanceof Horde_Mime_Headers_Addresses) {
             $headers->addHeader($val->header, rtrim($val->text));
         }
     }
     if (!$text instanceof Horde_Stream) {
         $stream->close();
     }
     return $headers;
 }