setDisposition() public method

Set the content-disposition of this part.
public setDisposition ( string $disposition = null )
$disposition string The content-disposition to set ('inline', 'attachment', or an empty value).
Example #1
0
 private function load()
 {
     $headers = [];
     $fetch_query = new \Horde_Imap_Client_Fetch_Query();
     $fetch_query->bodyPart($this->attachmentId);
     $fetch_query->mimeHeader($this->attachmentId);
     $headers = array_merge($headers, ['importance', 'list-post', 'x-priority']);
     $headers[] = 'content-type';
     $fetch_query->headers('imp', $headers, ['cache' => true]);
     // $list is an array of Horde_Imap_Client_Data_Fetch objects.
     $ids = new \Horde_Imap_Client_Ids($this->messageId);
     $headers = $this->conn->fetch($this->mailBox, $fetch_query, ['ids' => $ids]);
     /** @var $fetch Horde_Imap_Client_Data_Fetch */
     if (!isset($headers[$this->messageId])) {
         throw new DoesNotExistException('Unable to load the attachment.');
     }
     $fetch = $headers[$this->messageId];
     $mimeHeaders = $fetch->getMimeHeader($this->attachmentId, Horde_Imap_Client_Data_Fetch::HEADER_PARSE);
     $this->mimePart = new \Horde_Mime_Part();
     // To prevent potential problems with the SOP we serve all files with the
     // MIME type "application/octet-stream"
     $this->mimePart->setType('application/octet-stream');
     // Serve all files with a content-disposition of "attachment" to prevent Cross-Site Scripting
     $this->mimePart->setDisposition('attachment');
     // Extract headers from part
     $contentDisposition = $mimeHeaders->getValue('content-disposition', \Horde_Mime_Headers::VALUE_PARAMS);
     if (!is_null($contentDisposition)) {
         $vars = ['filename'];
         foreach ($contentDisposition as $key => $val) {
             if (in_array($key, $vars)) {
                 $this->mimePart->setDispositionParameter($key, $val);
             }
         }
     } else {
         $contentDisposition = $mimeHeaders->getValue('content-type', \Horde_Mime_Headers::VALUE_PARAMS);
         $vars = ['name'];
         foreach ($contentDisposition as $key => $val) {
             if (in_array($key, $vars)) {
                 $this->mimePart->setContentTypeParameter($key, $val);
             }
         }
     }
     /* Content transfer encoding. */
     if ($tmp = $mimeHeaders->getValue('content-transfer-encoding')) {
         $this->mimePart->setTransferEncoding($tmp);
     }
     $body = $fetch->getBodyPart($this->attachmentId);
     $this->mimePart->setContents($body);
 }
Example #2
0
File: Tnef.php Project: horde/horde
 /**
  * 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()
 {
     /* Get the data from the attachment. */
     try {
         if (!($tnef = $this->getConfigParam('tnef'))) {
             $tnef = Horde_Compress::factory('Tnef');
             $this->setConfigParam('tnef', $tnef);
         }
         $tnefData = $tnef->decompress($this->_mimepart->getContents());
     } catch (Horde_Compress_Exception $e) {
         $tnefData = array();
     }
     if (!count($tnefData)) {
         return null;
     }
     $mixed = new Horde_Mime_Part();
     $mixed->setType('multipart/mixed');
     reset($tnefData);
     while (list(, $data) = each($tnefData)) {
         $temp_part = new Horde_Mime_Part();
         $temp_part->setName($data['name']);
         $temp_part->setDescription($data['name']);
         $temp_part->setContents($data['stream']);
         $temp_part->setType($data['type'] . '/' . $data['subtype']);
         /* Short-circuit MIME-type guessing for winmail.dat parts;
          * we're showing enough entries for them already. */
         if (in_array($temp_part->getType(), array('application/octet-stream', 'application/base64'))) {
             $temp_part->setType(Horde_Mime_Magic::filenameToMIME($data['name']));
         }
         /* Set text parts to be displayed inline. */
         if ($temp_part->getPrimaryType() === 'text') {
             $temp_part->setDisposition('inline');
         }
         $mixed->addPart($temp_part);
     }
     return $mixed;
 }
Example #3
0
 /**
  * Recursively parse BODYSTRUCTURE data from a FETCH return (see
  * RFC 3501 [7.4.2]).
  *
  * @param Horde_Imap_Client_Tokenize $data  Data returned from the server.
  *
  * @return array  The array of bodystructure information.
  */
 protected function _parseBodystructure(Horde_Imap_Client_Tokenize $data)
 {
     $ob = new Horde_Mime_Part();
     // If index 0 is an array, this is a multipart part.
     if (is_object($entry = $data->rewind())) {
         // Keep going through array values until we find a non-array.
         do {
             $ob->addPart($this->_parseBodystructure($entry));
         } while (is_object($entry = $data->next()));
         // The first string entry after an array entry gives us the
         // subpart type.
         $ob->setType('multipart/' . $entry);
         // After the subtype is further extension information. This
         // information MAY not appear for BODYSTRUCTURE requests.
         // This is parameter information.
         if (is_object($tmp = $data->next())) {
             foreach ($this->_parseStructureParams($tmp, 'content-type') as $key => $val) {
                 $ob->setContentTypeParameter($key, $val);
             }
         }
     } else {
         $ob->setType($entry . '/' . $data->next());
         if (is_object($tmp = $data->next())) {
             foreach ($this->_parseStructureParams($tmp, 'content-type') as $key => $val) {
                 $ob->setContentTypeParameter($key, $val);
             }
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setContentId($tmp);
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setDescription(Horde_Mime::decode($tmp));
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setTransferEncoding($tmp);
         }
         $ob->setBytes($data->next());
         // If the type is 'message/rfc822' or 'text/*', several extra
         // fields are included
         switch ($ob->getPrimaryType()) {
             case 'message':
                 if ($ob->getSubType() == 'rfc822') {
                     $data->next();
                     // Ignore: envelope
                     $ob->addPart($this->_parseBodystructure($data->next()));
                     $data->next();
                     // Ignore: lines
                 }
                 break;
             case 'text':
                 $data->next();
                 // Ignore: lines
                 break;
         }
         // After the subtype is further extension information. This
         // information MAY appear for BODYSTRUCTURE requests.
         $data->next();
         // Ignore: MD5
     }
     // This is disposition information
     if (is_object($tmp = $data->next())) {
         $ob->setDisposition($tmp->rewind());
         foreach ($this->_parseStructureParams($tmp->next(), 'content-disposition') as $key => $val) {
             $ob->setDispositionParameter($key, $val);
         }
     }
     // This is language information. It is either a single value or a list
     // of values.
     if (($tmp = $data->next()) !== false) {
         $ob->setLanguage($tmp);
     }
     $data->next();
     // Ignore: location (RFC 2557)
     return $ob;
 }
Example #4
0
 /**
  * Returns a MIME part for an image to be embedded into a HTML document.
  *
  * @param string $file  An image file name.
  *
  * @return Horde_Mime_Part  A MIME part representing the image.
  */
 public static function getImagePart($file)
 {
     $background = Horde_Themes::img($file);
     $image = new Horde_Mime_Part();
     $image->setType('image/png');
     $image->setContents(file_get_contents($background->fs));
     $image->setContentId();
     $image->setDisposition('attachment');
     return $image;
 }
Example #5
0
File: Pgp.php Project: horde/horde
 /**
  * Encrypts a MIME part using PGP.
  *
  * @param Horde_Mime_Part $mime_part  The object to encrypt.
  * @param array $params               The parameters required for
  *                                    encryption
  *                                    ({@see _encryptMessage()}).
  *
  * @return mixed  A Horde_Mime_Part object that is encrypted according to
  *                RFC 3156.
  * @throws Horde_Crypt_Exception
  */
 public function encryptMIMEPart($mime_part, $params = array())
 {
     $params = array_merge($params, array('type' => 'message'));
     $signenc_body = $mime_part->toString(array('canonical' => true, 'headers' => true));
     $message_encrypt = $this->encrypt($signenc_body, $params);
     /* Set up MIME Structure according to RFC 3156. */
     $part = new Horde_Mime_Part();
     $part->setType('multipart/encrypted');
     $part->setHeaderCharset('UTF-8');
     $part->setContentTypeParameter('protocol', 'application/pgp-encrypted');
     $part->setDescription(Horde_Crypt_Translation::t("PGP Encrypted Data"));
     $part->setContents("This message is in MIME format and has been PGP encrypted.\n");
     $part1 = new Horde_Mime_Part();
     $part1->setType('application/pgp-encrypted');
     $part1->setCharset(null);
     $part1->setContents("Version: 1\n", array('encoding' => '7bit'));
     $part->addPart($part1);
     $part2 = new Horde_Mime_Part();
     $part2->setType('application/octet-stream');
     $part2->setCharset(null);
     $part2->setContents($message_encrypt, array('encoding' => '7bit'));
     $part2->setDisposition('inline');
     $part->addPart($part2);
     return $part;
 }
Example #6
0
 /**
  * Create the base Horde_Mime_Part for sending.
  *
  * @param Horde_Mail_Rfc822_List $to  The recipient list.
  * @param string $body                Message body.
  * @param array $options              Additional options:
  *   - encrypt: (integer) The encryption flag.
  *   - from: (Horde_Mail_Rfc822_Address) The outgoing from address (only
  *           needed for multiple PGP encryption).
  *   - html: (boolean) Is this a HTML message?
  *   - identity: (IMP_Prefs_Identity) Identity of the sender.
  *   - nofinal: (boolean) This is not a message which will be sent out.
  *   - noattach: (boolean) Don't add attachment information.
  *   - pgp_attach_pubkey: (boolean) Attach the user's PGP public key?
  *   - signature: (IMP_Prefs_Identity|string) If set, add the signature to
  *                the message.
  *   - vcard_attach: (string) If set, attach user's vcard to message.
  *
  * @return Horde_Mime_Part  The MIME message to send.
  *
  * @throws Horde_Exception
  * @throws IMP_Compose_Exception
  */
 protected function _createMimeMessage(Horde_Mail_Rfc822_List $to, $body, array $options = array())
 {
     global $conf, $injector, $prefs, $registry;
     /* Get body text. */
     if (empty($options['html'])) {
         $body_html = null;
     } else {
         $tfilter = $injector->getInstance('Horde_Core_Factory_TextFilter');
         $body_html = $tfilter->filter($body, 'Xss', array('return_dom' => true, 'strip_style_attributes' => false));
         $body_html_body = $body_html->getBody();
         $body = $tfilter->filter($body_html->returnHtml(), 'Html2text', array('wrap' => false));
     }
     $hooks = $injector->getInstance('Horde_Core_Hooks');
     /* We need to do the attachment check before any of the body text
      * has been altered. */
     if (!count($this) && !$this->getMetadata('attach_body_check')) {
         $this->_setMetadata('attach_body_check', true);
         try {
             $check = $hooks->callHook('attach_body_check', 'imp', array($body));
         } catch (Horde_Exception_HookNotSet $e) {
             $check = array();
         }
         if (!empty($check) && preg_match('/\\b(' . implode('|', array_map('preg_quote', $check)) . ')\\b/i', $body, $matches)) {
             throw IMP_Compose_Exception::createAndLog('DEBUG', sprintf(_("Found the word %s in the message text although there are no files attached to the message. Did you forget to attach a file? (This check will not be performed again for this message.)"), $matches[0]));
         }
     }
     /* Add signature data. */
     if (!empty($options['signature'])) {
         if (is_string($options['signature'])) {
             if (empty($options['html'])) {
                 $body .= "\n\n" . trim($options['signature']);
             } else {
                 $html_sig = trim($options['signature']);
                 $body .= "\n" . $tfilter->filter($html_sig, 'Html2text');
             }
         } else {
             $sig = $options['signature']->getSignature('text');
             $body .= $sig;
             if (!empty($options['html'])) {
                 $html_sig = $options['signature']->getSignature('html');
                 if (!strlen($html_sig) && strlen($sig)) {
                     $html_sig = $this->text2html($sig);
                 }
             }
         }
         if (!empty($options['html'])) {
             try {
                 $sig_ob = new IMP_Compose_HtmlSignature($html_sig);
             } catch (IMP_Exception $e) {
                 throw new IMP_Compose_Exception($e);
             }
             foreach ($sig_ob->dom->getBody()->childNodes as $child) {
                 $body_html_body->appendChild($body_html->dom->importNode($child, true));
             }
         }
     }
     /* Add linked attachments. */
     if (empty($options['nofinal'])) {
         $this->_linkAttachments($body, $body_html);
     }
     /* Get trailer text (if any). */
     if (empty($options['nofinal'])) {
         try {
             $trailer = $hooks->callHook('trailer', 'imp', array(false, $options['identity'], $to));
             $html_trailer = $hooks->callHook('trailer', 'imp', array(true, $options['identity'], $to));
         } catch (Horde_Exception_HookNotSet $e) {
             $trailer = $html_trailer = null;
         }
         $body .= strval($trailer);
         if (!empty($options['html'])) {
             if (is_null($html_trailer) && strlen($trailer)) {
                 $html_trailer = $this->text2html($trailer);
             }
             if (strlen($html_trailer)) {
                 $t_dom = new Horde_Domhtml($html_trailer, 'UTF-8');
                 foreach ($t_dom->getBody()->childNodes as $child) {
                     $body_html_body->appendChild($body_html->dom->importNode($child, true));
                 }
             }
         }
     }
     /* Convert text to sending charset. HTML text will be converted
      * via Horde_Domhtml. */
     $body = Horde_String::convertCharset($body, 'UTF-8', $this->charset);
     /* Set up the body part now. */
     $textBody = new Horde_Mime_Part();
     $textBody->setType('text/plain');
     $textBody->setCharset($this->charset);
     $textBody->setDisposition('inline');
     /* Send in flowed format. */
     $flowed = new Horde_Text_Flowed($body, $this->charset);
     $flowed->setDelSp(true);
     $textBody->setContentTypeParameter('format', 'flowed');
     $textBody->setContentTypeParameter('DelSp', 'Yes');
     $text_contents = $flowed->toFlowed();
     $textBody->setContents($text_contents);
     /* Determine whether or not to send a multipart/alternative
      * message with an HTML part. */
     if (!empty($options['html'])) {
         $htmlBody = new Horde_Mime_Part();
         $htmlBody->setType('text/html');
         $htmlBody->setCharset($this->charset);
         $htmlBody->setDisposition('inline');
         $htmlBody->setDescription(Horde_String::convertCharset(_("HTML Message"), 'UTF-8', $this->charset));
         /* Add default font CSS information here. */
         $styles = array();
         if ($font_family = $prefs->getValue('compose_html_font_family')) {
             $styles[] = 'font-family:' . $font_family;
         }
         if ($font_size = intval($prefs->getValue('compose_html_font_size'))) {
             $styles[] = 'font-size:' . $font_size . 'px';
         }
         if (!empty($styles)) {
             $body_html_body->setAttribute('style', implode(';', $styles));
         }
         if (empty($options['nofinal'])) {
             $this->_cleanHtmlOutput($body_html);
         }
         $to_add = $this->_convertToRelated($body_html, $htmlBody);
         /* Now, all parts referred to in the HTML data have been added
          * to the attachment list. Convert to multipart/related if
          * this is the case. Exception: if text representation is empty,
          * just send HTML part. */
         if (strlen(trim($text_contents))) {
             $textpart = new Horde_Mime_Part();
             $textpart->setType('multipart/alternative');
             $textpart->addPart($textBody);
             $textpart->addPart($to_add);
             $textpart->setHeaderCharset($this->charset);
             $textBody->setDescription(Horde_String::convertCharset(_("Plaintext Message"), 'UTF-8', $this->charset));
         } else {
             $textpart = $to_add;
         }
         $htmlBody->setContents($tfilter->filter($body_html->returnHtml(array('charset' => $this->charset, 'metacharset' => true)), 'Cleanhtml', array('charset' => $this->charset)));
     } else {
         $textpart = $textBody;
     }
     /* Add attachments. */
     $base = $textpart;
     if (empty($options['noattach'])) {
         $parts = array();
         foreach ($this as $val) {
             if (!$val->related && !$val->linked) {
                 $parts[] = $val->getPart(true);
             }
         }
         if (!empty($options['pgp_attach_pubkey'])) {
             $parts[] = $injector->getInstance('IMP_Crypt_Pgp')->publicKeyMIMEPart();
         }
         if (!empty($options['vcard_attach'])) {
             try {
                 $vpart = new Horde_Mime_Part();
                 $vpart->setType('text/x-vcard');
                 $vpart->setCharset('UTF-8');
                 $vpart->setContents($registry->call('contacts/ownVCard'));
                 $vpart->setName($options['vcard_attach']);
                 $parts[] = $vpart;
             } catch (Horde_Exception $e) {
                 throw new IMP_Compose_Exception(sprintf(_("Can't attach contact information: %s"), $e->getMessage()));
             }
         }
         if (!empty($parts)) {
             $base = new Horde_Mime_Part();
             $base->setType('multipart/mixed');
             $base->addPart($textpart);
             foreach ($parts as $val) {
                 $base->addPart($val);
             }
         }
     }
     /* Set up the base message now. */
     $encrypt = empty($options['encrypt']) ? IMP::ENCRYPT_NONE : $options['encrypt'];
     if ($prefs->getValue('use_pgp') && !empty($conf['gnupg']['path']) && in_array($encrypt, array(IMP_Crypt_Pgp::ENCRYPT, IMP_Crypt_Pgp::SIGN, IMP_Crypt_Pgp::SIGNENC, IMP_Crypt_Pgp::SYM_ENCRYPT, IMP_Crypt_Pgp::SYM_SIGNENC))) {
         $imp_pgp = $injector->getInstance('IMP_Crypt_Pgp');
         $symmetric_passphrase = null;
         switch ($encrypt) {
             case IMP_Crypt_Pgp::SIGN:
             case IMP_Crypt_Pgp::SIGNENC:
             case IMP_Crypt_Pgp::SYM_SIGNENC:
                 /* Check to see if we have the user's passphrase yet. */
                 $passphrase = $imp_pgp->getPassphrase('personal');
                 if (empty($passphrase)) {
                     $e = new IMP_Compose_Exception(_("PGP: Need passphrase for personal private key."));
                     $e->encrypt = 'pgp_passphrase_dialog';
                     throw $e;
                 }
                 break;
             case IMP_Crypt_Pgp::SYM_ENCRYPT:
             case IMP_Crypt_Pgp::SYM_SIGNENC:
                 /* Check to see if we have the user's symmetric passphrase
                  * yet. */
                 $symmetric_passphrase = $imp_pgp->getPassphrase('symmetric', 'imp_compose_' . $this->_cacheid);
                 if (empty($symmetric_passphrase)) {
                     $e = new IMP_Compose_Exception(_("PGP: Need passphrase to encrypt your message with."));
                     $e->encrypt = 'pgp_symmetric_passphrase_dialog';
                     throw $e;
                 }
                 break;
         }
         /* Do the encryption/signing requested. */
         try {
             switch ($encrypt) {
                 case IMP_Crypt_Pgp::SIGN:
                     $base = $imp_pgp->impSignMimePart($base);
                     $this->_setMetadata('encrypt_sign', true);
                     break;
                 case IMP_Crypt_Pgp::ENCRYPT:
                 case IMP_Crypt_Pgp::SYM_ENCRYPT:
                     $to_list = clone $to;
                     if (count($options['from'])) {
                         $to_list->add($options['from']);
                     }
                     $base = $imp_pgp->IMPencryptMIMEPart($base, $to_list, $encrypt == IMP_Crypt_Pgp::SYM_ENCRYPT ? $symmetric_passphrase : null);
                     break;
                 case IMP_Crypt_Pgp::SIGNENC:
                 case IMP_Crypt_Pgp::SYM_SIGNENC:
                     $to_list = clone $to;
                     if (count($options['from'])) {
                         $to_list->add($options['from']);
                     }
                     $base = $imp_pgp->IMPsignAndEncryptMIMEPart($base, $to_list, $encrypt == IMP_Crypt_Pgp::SYM_SIGNENC ? $symmetric_passphrase : null);
                     break;
             }
         } catch (Horde_Exception $e) {
             throw new IMP_Compose_Exception(_("PGP Error: ") . $e->getMessage(), $e->getCode());
         }
     } elseif ($prefs->getValue('use_smime') && in_array($encrypt, array(IMP_Crypt_Smime::ENCRYPT, IMP_Crypt_Smime::SIGN, IMP_Crypt_Smime::SIGNENC))) {
         $imp_smime = $injector->getInstance('IMP_Crypt_Smime');
         /* Check to see if we have the user's passphrase yet. */
         if (in_array($encrypt, array(IMP_Crypt_Smime::SIGN, IMP_Crypt_Smime::SIGNENC))) {
             $passphrase = $imp_smime->getPassphrase();
             if ($passphrase === false) {
                 $e = new IMP_Compose_Exception(_("S/MIME Error: Need passphrase for personal private key."));
                 $e->encrypt = 'smime_passphrase_dialog';
                 throw $e;
             }
         }
         /* Do the encryption/signing requested. */
         try {
             switch ($encrypt) {
                 case IMP_Crypt_Smime::SIGN:
                     $base = $imp_smime->IMPsignMIMEPart($base);
                     $this->_setMetadata('encrypt_sign', true);
                     break;
                 case IMP_Crypt_Smime::ENCRYPT:
                     $base = $imp_smime->IMPencryptMIMEPart($base, $to[0]);
                     break;
                 case IMP_Crypt_Smime::SIGNENC:
                     $base = $imp_smime->IMPsignAndEncryptMIMEPart($base, $to[0]);
                     break;
             }
         } catch (Horde_Exception $e) {
             throw new IMP_Compose_Exception(_("S/MIME Error: ") . $e->getMessage(), $e->getCode());
         }
     }
     /* Flag this as the base part and rebuild MIME IDs. */
     $base->isBasePart(true);
     $base->buildMimeIds();
     return $base;
 }
Example #7
0
 /**
  * Strips one or all MIME parts out of a message.
  *
  * @param string $partid  The MIME ID of the part to strip. All parts are
  *                        stripped if null.
  *
  * @return IMP_Indices  Returns the new indices object.
  * @throws IMP_Exception
  */
 public function stripPart($partid = null)
 {
     global $injector;
     list($mbox, $uid) = $this->getSingle();
     if (!$uid) {
         return;
     }
     if ($mbox->readonly) {
         throw new IMP_Exception(_("Cannot strip the part as the mailbox is read-only."));
     }
     $uidvalidity = $mbox->uidvalid;
     $contents = $injector->getInstance('IMP_Factory_Contents')->create($this);
     $message = $contents->getMIMEMessage();
     $boundary = trim($message->getContentTypeParameter('boundary'), '"');
     $url = new Horde_Imap_Client_Url();
     $url->mailbox = $mbox;
     $url->uid = $uid;
     $url->uidvalidity = $uidvalidity;
     $imp_imap = $mbox->imp_imap;
     /* Always add the header to output. */
     $url->section = 'HEADER';
     $parts = array(array('t' => 'url', 'v' => strval($url)));
     for ($id = 1;; ++$id) {
         if (!($part = $message[$id])) {
             break;
         }
         $parts[] = array('t' => 'text', 'v' => "\r\n--" . $boundary . "\r\n");
         if ($id != 1 && is_null($partid) || $id == $partid) {
             $newPart = new Horde_Mime_Part();
             $newPart->setType('text/plain');
             /* Need to make sure all text is in the correct charset. */
             $newPart->setCharset('UTF-8');
             $newPart->setContents(sprintf(_("[Part stripped: Original part type: %s, name: %s]"), $part->getType(), $contents->getPartName($part)));
             $newPart->setDisposition('attachment');
             $parts[] = array('t' => 'text', 'v' => $newPart->toString(array('canonical' => true, 'headers' => true, 'stream' => true)));
         } else {
             $url->section = $id . '.MIME';
             $parts[] = array('t' => 'url', 'v' => strval($url));
             $url->section = $id;
             $parts[] = array('t' => 'url', 'v' => strval($url));
         }
     }
     $parts[] = array('t' => 'text', 'v' => "\r\n--" . $boundary . "--\r\n");
     /* Get the headers for the message. */
     $query = new Horde_Imap_Client_Fetch_Query();
     $query->imapDate();
     $query->flags();
     try {
         $res = $imp_imap->fetch($mbox, $query, array('ids' => $imp_imap->getIdsOb($uid)))->first();
         if (is_null($res)) {
             throw new IMP_Imap_Exception();
         }
         $flags = $res->getFlags();
         /* If in Virtual Inbox, we need to reset flag to unseen so that it
          * appears again in the mailbox list. */
         if ($mbox->vinbox) {
             $flags = array_values(array_diff($flags, array(Horde_Imap_Client::FLAG_SEEN)));
         }
         $new_uid = $imp_imap->append($mbox, array(array('data' => $parts, 'flags' => $flags, 'internaldate' => $res->getImapDate())))->ids;
         $new_uid = reset($new_uid);
     } catch (IMP_Imap_Exception $e) {
         throw new IMP_Exception(_("An error occured while attempting to strip the part."));
     }
     $this->delete(array('keeplog' => true, 'nuke' => true));
     $indices_ob = $mbox->getIndicesOb($new_uid);
     /* We need to replace the old UID(s) in the URL params. */
     $vars = $injector->getInstance('Horde_Variables');
     if (isset($vars->buid)) {
         list(, $vars->buid) = $mbox->toBuids($indices_ob)->getSingle();
     }
     if (isset($vars->uid)) {
         $vars->uid = $new_uid;
     }
     return $indices_ob;
 }
Example #8
0
 /**
  * Save an object in this folder.
  *
  * @param array  $object       The array that holds the data of the object.
  * @param int    $data_version The format handler version.
  * @param string $object_type  The type of the kolab object.
  * @param string $id           The IMAP id of the old object if it
  *                             existed before
  * @param array  $old_object   The array that holds the current data of the
  *                             object.
  *
  * @return boolean True on success.
  */
 public function saveObject(&$object, $data_version, $object_type, $id = null, &$old_object = null)
 {
     // Select folder
     $this->_driver->select($this->_path);
     $new_headers = new Horde_Mime_Headers();
     $new_headers->setEOL("\r\n");
     $formats = $this->getFormats();
     $handlers = array();
     foreach ($formats as $type) {
         $handlers[$type] =& Horde_Kolab_Format::factory($type, $object_type, $data_version);
         if (is_a($handlers[$type], 'PEAR_Error')) {
             if ($type == 'XML') {
                 return $handlers[$type];
             }
             Horde::log(sprintf('Loading format handler "%s" failed: %s', $type, $handlers[$type]->getMessage()), 'ERR');
             continue;
         }
     }
     if ($id != null) {
         /** Update an existing kolab object */
         if (!in_array($id, $this->_driver->getUids($this->_path))) {
             return PEAR::raiseError(sprintf(Horde_Kolab_Storage_Translation::t("The message with ID %s does not exist. This probably means that the Kolab object has been modified by somebody else while you were editing it. Your edits have been lost."), $id));
         }
         /** Parse email and load Kolab format structure */
         $result = $this->parseMessage($id, $handlers['XML']->getMimeType(), true, $formats);
         if (is_a($result, 'PEAR_Error')) {
             return $result;
         }
         list($old_message, $part_ids, $mime_message, $mime_headers) = $result;
         if (is_a($old_message, 'PEAR_Error')) {
             return $old_message;
         }
         if (isset($object['_attachments']) && isset($old_object['_attachments'])) {
             $attachments = array_keys($object['_attachments']);
             foreach (array_keys($old_object['_attachments']) as $attachment) {
                 if (!in_array($attachment, $attachments)) {
                     foreach ($mime_message->getParts() as $part) {
                         if ($part->getName() === $attachment) {
                             foreach (array_keys($mime_message->_parts) as $key) {
                                 if ($mime_message->_parts[$key]->getMimeId() == $part->getMimeId()) {
                                     unset($mime_message->_parts[$key]);
                                     break;
                                 }
                             }
                             $mime_message->_generateIdMap($mime_message->_parts);
                         }
                     }
                 }
             }
         }
         $object = array_merge($old_object, $object);
         if (isset($attachments)) {
             foreach ($mime_message->getParts() as $part) {
                 $name = $part->getName();
                 foreach ($attachments as $attachment) {
                     if ($name === $attachment) {
                         $object['_attachments'][$attachment]['id'] = $part->getMimeId();
                     }
                 }
             }
         }
         /** Copy email header */
         if (!empty($mime_headers) && !$mime_headers === false) {
             foreach ($mime_headers as $header => $value) {
                 $new_headers->addheader($header, $value);
             }
         }
     } else {
         $mime_message = $this->_prepareNewMessage($new_headers);
         $mime_part_id = false;
     }
     if (isset($object['_attachments'])) {
         $attachments = array_keys($object['_attachments']);
         foreach ($attachments as $attachment) {
             $data = $object['_attachments'][$attachment];
             if (!isset($data['content']) && !isset($data['path'])) {
                 /**
                  * There no new content and no new path. Do not rewrite the
                  * attachment.
                  */
                 continue;
             }
             $part = new Horde_Mime_Part();
             $part->setType(isset($data['type']) ? $data['type'] : null);
             $part->setContents(isset($data['content']) ? $data['content'] : file_get_contents($data['path']));
             $part->setCharset('UTF-8');
             $part->setTransferEncoding('quoted-printable');
             $part->setDisposition('attachment');
             $part->setName($attachment);
             if (!isset($data['id'])) {
                 $mime_message->addPart($part);
             } else {
                 $mime_message->alterPart($data['id'], $part);
             }
         }
     }
     foreach ($formats as $type) {
         $new_content = $handlers[$type]->save($object);
         if (is_a($new_content, 'PEAR_Error')) {
             return $new_content;
         }
         /** Update mime part */
         $part = new Horde_Mime_Part();
         $part->setType($handlers[$type]->getMimeType());
         $part->setContents($new_content);
         $part->setCharset('UTF-8');
         $part->setTransferEncoding('quoted-printable');
         $part->setDisposition($handlers[$type]->getDisposition());
         $part->setDispositionParameter('x-kolab-type', $type);
         $part->setName($handlers[$type]->getName());
         if (!isset($part_ids) || $part_ids[$type] === false) {
             $mime_message->addPart($part);
         } else {
             $mime_message->alterPart($part_ids[$type], $part);
         }
     }
     // Update email headers
     $new_headers->addHeader('From', $this->_driver->getAuth());
     $new_headers->addHeader('To', $this->_driver->getAuth());
     $new_headers->addHeader('Date', date('r'));
     $new_headers->addHeader('X-Kolab-Type', $handlers['XML']->getMimeType());
     $new_headers->addHeader('Subject', $object['uid']);
     $new_headers->addHeader('User-Agent', 'Horde::Kolab::Storage v0.2');
     $new_headers->addHeader('MIME-Version', '1.0');
     $mime_message->addMimeHeaders(array('headers' => $new_headers));
     $msg = $new_headers->toString() . $mime_message->toString(array('canonical' => true, 'headers' => false));
     // delete old email?
     if ($id != null) {
         $this->_driver->deleteMessages($this->_path, $id);
     }
     // store new email
     try {
         $result = $this->_driver->appendMessage($this->_path, $msg);
     } catch (Horde_Kolab_Storage_Exception $e) {
         if ($id != null) {
             $this->_driver->undeleteMessages($id);
         }
     }
     // remove deleted object
     if ($id != null) {
         $this->_driver->expunge($this->_path);
     }
 }
Example #9
0
 /**
  * Embed the Kolab content into a new MIME Part.
  *
  * @param resource $content The Kolab content.
  *
  * @return Horde_Mime_Part The MIME part that encapsules the Kolab content.
  */
 protected function createFreshKolabPart($content)
 {
     $part = new Horde_Mime_Part();
     $part->setCharset('utf-8');
     $part->setDisposition('inline');
     $part->setDispositionParameter('x-kolab-type', 'xml');
     $part->setName('kolab.xml');
     $part->setType(Horde_Kolab_Storage_Object_MimeType::getMimeTypeFromObjectType($this->getType()));
     $part->setContents($content, array('encoding' => 'quoted-printable'));
     return $part;
 }
Example #10
0
 /**
  * Encrypt a MIME part using S/MIME. This produces S/MIME Version 3.2
  * compatible data (see RFC 5751 [3.3]).
  *
  * @param Horde_Mime_Part $mime_part  The object to encrypt.
  * @param array $params               The parameters required for
  *                                    encryption.
  *
  * @return Horde_Mime_Part  An encrypted MIME part object.
  * @throws Horde_Crypt_Exception
  */
 public function encryptMIMEPart($mime_part, $params = array())
 {
     /* Sign the part as a message */
     $message = $this->encrypt($mime_part->toString(array('headers' => true, 'canonical' => true)), $params);
     $msg = new Horde_Mime_Part();
     $msg->setCharset($this->_params['email_charset']);
     $msg->setHeaderCharset('UTF-8');
     $msg->setDescription(Horde_Crypt_Translation::t("S/MIME Encrypted Message"));
     $msg->setDisposition('inline');
     $msg->setType('application/pkcs7-mime');
     $msg->setContentTypeParameter('smime-type', 'enveloped-data');
     $msg->setContents(substr($message, strpos($message, "\n\n") + 2), array('encoding' => 'base64'));
     return $msg;
 }
Example #11
0
 public function testNullCharactersNotAllowedInMimeHeaderData()
 {
     $part = new Horde_Mime_Part();
     $part->setType("text/plain");
     $this->assertEquals('text/plain', $part->getType());
     $part->setDisposition("inline");
     $this->assertEquals('inline', $part->getDisposition());
     $part->setDispositionParameter('size', '123' . "" . '456');
     $this->assertEquals(123456, $part->getDispositionParameter('size'));
     $part->setDispositionParameter('foo', "foobar");
     $this->assertEquals('foobar', $part->getDispositionParameter('foo'));
     $part->setCharset("utf-8");
     $this->assertEquals('utf-8', $part->getCharset());
     $part->setName("foobar");
     $this->assertEquals('foobar', $part->getName());
     $this->assertEquals('foobar', $part->getDispositionParameter('filename'));
     $this->assertEquals('foobar', $part->getContentTypeParameter('name'));
     $part->setLanguage("en");
     $this->assertEquals(array('en'), $part->getLanguage());
     $part->setLanguage(array("en", "de"));
     $this->assertEquals(array('en', 'de'), $part->getLanguage());
     $part->setDuration('123' . "" . '456');
     $this->assertEquals(123456, $part->getDuration());
     $part->setBytes('123' . "" . '456');
     $this->assertEquals(123456, $part->getBytes());
     $part->setDescription("foobar");
     $this->assertEquals('foobar', $part->getDescription());
     $part->setContentTypeParameter('foo', "foobar");
     $this->assertEquals('foobar', $part->getContentTypeParameter('foo'));
     $part->setContentId("foobar");
     $this->assertEquals('foobar', $part->getContentId());
 }
Example #12
0
 /**
  * Creates a structure object from the text of one part of a MIME message.
  *
  * @param string $header      The header text.
  * @param string $body        The body text.
  * @param string $ctype       The default content-type.
  * @param boolean $forcemime  If true, the message data is assumed to be
  *                            MIME data. If not, a MIME-Version header
  *                            must exist to be parsed as a MIME message.
  *
  * @return Horde_Mime_Part  TODO
  */
 protected static function _getStructure($header, $body, $ctype = 'application/octet-stream', $forcemime = false)
 {
     /* Parse headers text into a Horde_Mime_Headers object. */
     $hdrs = Horde_Mime_Headers::parseHeaders($header);
     $ob = new Horde_Mime_Part();
     /* This is not a MIME message. */
     if (!$forcemime && !$hdrs->getValue('mime-version')) {
         $ob->setType('text/plain');
         if (!empty($body)) {
             $ob->setContents($body);
             $ob->setBytes(strlen(str_replace(array("\r\n", "\n"), array("\n", "\r\n"), $body)));
         }
         return $ob;
     }
     /* Content type. */
     if ($tmp = $hdrs->getValue('content-type', Horde_Mime_Headers::VALUE_BASE)) {
         $ob->setType($tmp);
         $ctype_params = $hdrs->getValue('content-type', Horde_Mime_Headers::VALUE_PARAMS);
         foreach ($ctype_params as $key => $val) {
             $ob->setContentTypeParameter($key, $val);
         }
     } else {
         $ob->setType($ctype);
         $ctype_params = array();
     }
     /* Content transfer encoding. */
     if ($tmp = $hdrs->getValue('content-transfer-encoding')) {
         $ob->setTransferEncoding($tmp);
     }
     /* Content-Description. */
     if ($tmp = $hdrs->getValue('content-description')) {
         $ob->setDescription($tmp);
     }
     /* Content-Disposition. */
     if ($tmp = $hdrs->getValue('content-disposition', Horde_Mime_Headers::VALUE_BASE)) {
         $ob->setDisposition($tmp);
         foreach ($hdrs->getValue('content-disposition', Horde_Mime_Headers::VALUE_PARAMS) as $key => $val) {
             $ob->setDispositionParameter($key, $val);
         }
     }
     /* Content-Duration */
     if ($tmp = $hdrs->getValue('content-duration')) {
         $ob->setDuration($tmp);
     }
     /* Content-ID. */
     if ($tmp = $hdrs->getValue('content-id')) {
         $ob->setContentId($tmp);
     }
     /* Get file size (if 'body' text is set). */
     if (!empty($body) && $ob->getPrimaryType() != 'multipart') {
         $ob->setContents($body);
         if ($ob->getType() != '/message/rfc822') {
             $ob->setBytes(strlen(str_replace(array("\r\n", "\n"), array("\n", "\r\n"), $body)));
         }
     }
     /* Process subparts. */
     switch ($ob->getPrimaryType()) {
         case 'message':
             if ($ob->getSubType() == 'rfc822') {
                 $ob->addPart(self::parseMessage($body, array('forcemime' => true)));
             }
             break;
         case 'multipart':
             if (isset($ctype_params['boundary'])) {
                 $b_find = self::_findBoundary($body, 0, $ctype_params['boundary']);
                 foreach ($b_find as $val) {
                     $subpart = substr($body, $val['start'], $val['length']);
                     list($hdr_pos, $eol) = self::_findHeader($subpart);
                     $ob->addPart(self::_getStructure(substr($subpart, 0, $hdr_pos), substr($subpart, $hdr_pos + $eol), $ob->getSubType() == 'digest' ? 'message/rfc822' : 'text/plain', true));
                 }
             }
             break;
     }
     return $ob;
 }
Example #13
0
<?php

$part1 = new Horde_Mime_Part();
$part1->setType('text/plain');
$part1->setTransferEncoding('quoted-printable');
$part1->setCharset('UTF-8');
$part1->setDisposition('inline');
$part1->setBytes(249);
$part2 = new Horde_Mime_Part();
$part2->setType('application/x-vnd.kolab.note');
$part2->setTransferEncoding('quoted-printable');
$part2->setName('kolab.xml');
$part2->setDisposition('attachment');
$part2->setBytes(704);
$message = new Horde_Mime_Part();
$message->setType('multipart/mixed');
$message->addPart($part1);
$message->addPart($part2);
$message->buildMimeIds(0);
return $message;
Example #14
0
 /**
  * Create the base Horde_Mime_Part for sending.
  *
  * @param string $body                Message body.
  * @param array $options              Additional options:
  *   - html: (boolean) Is this a HTML message?
  *   - identity: (IMP_Prefs_Identity) Identity of the sender.
  *   - nofinal: (boolean) This is not a message which will be sent out.
  *   - noattach: (boolean) Don't add attachment information.
  *   - pgp_attach_pubkey: (boolean) Attach the user's PGP public key?
  *   - recip: (Horde_Mail_Rfc822_List) The recipient list.
  *   - signature: (IMP_Prefs_Identity|string) If set, add the signature to
  *                the message.
  *   - vcard_attach: (string) If set, attach user's vcard to message.
  *
  * @return Horde_Mime_Part  The base MIME part.
  *
  * @throws Horde_Exception
  * @throws IMP_Compose_Exception
  */
 protected function _createMimeMessage($body, array $options = array())
 {
     global $injector, $prefs, $registry;
     /* Get body text. */
     if (empty($options['html'])) {
         $body_html = null;
     } else {
         $tfilter = $injector->getInstance('Horde_Core_Factory_TextFilter');
         $body_html = $tfilter->filter($body, 'Xss', array('return_dom' => true, 'strip_style_attributes' => false));
         $body_html_body = $body_html->getBody();
         $body = $tfilter->filter($body_html->returnHtml(), 'Html2text', array('wrap' => false));
     }
     $hooks = $injector->getInstance('Horde_Core_Hooks');
     /* We need to do the attachment check before any of the body text
      * has been altered. */
     if (!count($this) && !$this->getMetadata('attach_body_check')) {
         $this->_setMetadata('attach_body_check', true);
         try {
             $check = $hooks->callHook('attach_body_check', 'imp', array($body));
         } catch (Horde_Exception_HookNotSet $e) {
             $check = array();
         }
         if (!empty($check) && preg_match('/\\b(' . implode('|', array_map('preg_quote', $check, array_fill(0, count($check), '/'))) . ')\\b/i', $body, $matches)) {
             throw IMP_Compose_Exception::createAndLog('DEBUG', sprintf(_("Found the word %s in the message text although there are no files attached to the message. Did you forget to attach a file? (This check will not be performed again for this message.)"), $matches[0]));
         }
     }
     /* Add signature data. */
     if (!empty($options['signature'])) {
         if (is_string($options['signature'])) {
             if (empty($options['html'])) {
                 $body .= "\n\n" . trim($options['signature']);
             } else {
                 $html_sig = trim($options['signature']);
                 $body .= "\n" . $tfilter->filter($html_sig, 'Html2text');
             }
         } else {
             $sig = $options['signature']->getSignature('text');
             $body .= $sig;
             if (!empty($options['html'])) {
                 $html_sig = $options['signature']->getSignature('html');
                 if (!strlen($html_sig) && strlen($sig)) {
                     $html_sig = $this->text2html($sig);
                 }
             }
         }
         if (!empty($options['html'])) {
             try {
                 $sig_ob = new IMP_Compose_HtmlSignature($html_sig);
             } catch (IMP_Exception $e) {
                 throw new IMP_Compose_Exception($e);
             }
             foreach ($sig_ob->dom->getBody()->childNodes as $child) {
                 $body_html_body->appendChild($body_html->dom->importNode($child, true));
             }
         }
     }
     /* Add linked attachments. */
     if (empty($options['nofinal'])) {
         $this->_linkAttachments($body, $body_html);
     }
     /* Get trailer text (if any). */
     if (empty($options['nofinal']) && !empty($options['recip'])) {
         try {
             $trailer = $hooks->callHook('trailer', 'imp', array(false, $options['identity'], $options['recip']));
             $html_trailer = $hooks->callHook('trailer', 'imp', array(true, $options['identity'], $options['recip']));
         } catch (Horde_Exception_HookNotSet $e) {
             $trailer = $html_trailer = null;
         }
         $body .= strval($trailer);
         if (!empty($options['html'])) {
             if (is_null($html_trailer) && strlen($trailer)) {
                 $html_trailer = $this->text2html($trailer);
             }
             if (strlen($html_trailer)) {
                 $t_dom = new Horde_Domhtml($html_trailer, 'UTF-8');
                 foreach ($t_dom->getBody()->childNodes as $child) {
                     $body_html_body->appendChild($body_html->dom->importNode($child, true));
                 }
             }
         }
     }
     /* Convert text to sending charset. HTML text will be converted
      * via Horde_Domhtml. */
     $body = Horde_String::convertCharset($body, 'UTF-8', $this->charset);
     /* Set up the body part now. */
     $textBody = new Horde_Mime_Part();
     $textBody->setType('text/plain');
     $textBody->setCharset($this->charset);
     $textBody->setDisposition('inline');
     /* Send in flowed format. */
     $flowed = new Horde_Text_Flowed($body, $this->charset);
     $flowed->setDelSp(true);
     $textBody->setContentTypeParameter('format', 'flowed');
     $textBody->setContentTypeParameter('DelSp', 'Yes');
     $text_contents = $flowed->toFlowed();
     $textBody->setContents($text_contents);
     /* Determine whether or not to send a multipart/alternative
      * message with an HTML part. */
     if (!empty($options['html'])) {
         $htmlBody = new Horde_Mime_Part();
         $htmlBody->setType('text/html');
         $htmlBody->setCharset($this->charset);
         $htmlBody->setDisposition('inline');
         $htmlBody->setDescription(Horde_String::convertCharset(_("HTML Message"), 'UTF-8', $this->charset));
         /* Add default font CSS information here. */
         $styles = array();
         if ($font_family = $prefs->getValue('compose_html_font_family')) {
             $styles[] = 'font-family:' . $font_family;
         }
         if ($font_size = intval($prefs->getValue('compose_html_font_size'))) {
             $styles[] = 'font-size:' . $font_size . 'px';
         }
         if (!empty($styles)) {
             $body_html_body->setAttribute('style', implode(';', $styles));
         }
         if (empty($options['nofinal'])) {
             $this->_cleanHtmlOutput($body_html);
         }
         $to_add = $this->_convertToRelated($body_html, $htmlBody);
         /* Now, all parts referred to in the HTML data have been added
          * to the attachment list. Convert to multipart/related if
          * this is the case. Exception: if text representation is empty,
          * just send HTML part. */
         if (strlen(trim($text_contents))) {
             $textpart = new Horde_Mime_Part();
             $textpart->setType('multipart/alternative');
             $textpart[] = $textBody;
             $textpart[] = $to_add;
             $textpart->setHeaderCharset($this->charset);
             $textBody->setDescription(Horde_String::convertCharset(_("Plaintext Message"), 'UTF-8', $this->charset));
         } else {
             $textpart = $to_add;
         }
         $htmlBody->setContents($tfilter->filter($body_html->returnHtml(array('charset' => $this->charset, 'metacharset' => true)), 'Cleanhtml', array('charset' => $this->charset)));
         $base = $textpart;
     } else {
         $base = $textpart = strlen(trim($text_contents)) ? $textBody : null;
     }
     /* Add attachments. */
     if (empty($options['noattach'])) {
         $parts = array();
         foreach ($this as $val) {
             if (!$val->related && !$val->linked) {
                 $parts[] = $val->getPart(true);
             }
         }
         if (!empty($options['pgp_attach_pubkey'])) {
             $parts[] = $injector->getInstance('IMP_Crypt_Pgp')->publicKeyMIMEPart();
         }
         if (!empty($options['vcard_attach'])) {
             try {
                 $vpart = new Horde_Mime_Part();
                 $vpart->setType('text/x-vcard');
                 $vpart->setCharset('UTF-8');
                 $vpart->setContents($registry->call('contacts/ownVCard'));
                 $vpart->setName($options['vcard_attach']);
                 $parts[] = $vpart;
             } catch (Horde_Exception $e) {
                 throw new IMP_Compose_Exception(sprintf(_("Can't attach contact information: %s"), $e->getMessage()));
             }
         }
         if (!empty($parts)) {
             if (is_null($base) && count($parts) === 1) {
                 /* If this is a single attachment with no text, the
                  * attachment IS the message. */
                 $base = reset($parts);
             } else {
                 $base = new Horde_Mime_Part();
                 $base->setType('multipart/mixed');
                 if (!is_null($textpart)) {
                     $base[] = $textpart;
                 }
                 foreach ($parts as $val) {
                     $base[] = $val;
                 }
             }
         }
     }
     /* If we reach this far with no base, we are sending a blank message.
      * Assume this is what the user wants. */
     if (is_null($base)) {
         $base = $textBody;
     }
     /* Flag this as the base part and rebuild MIME IDs. */
     $base->isBasePart(true);
     $base->buildMimeIds();
     return $base;
 }
Example #15
0
 /**
  * Parse the output from imap_fetchstructure() into a MIME Part object.
  *
  * @param object $data  Data from imap_fetchstructure().
  *
  * @return Horde_Mime_Part  A MIME Part object.
  */
 protected function _parseStructure($data)
 {
     $ob = new Horde_Mime_Part();
     $ob->setType(Horde_String::lower($data->type) . '/' . Horde_String::lower($data->subType));
     // Optional for multipart-parts, required for all others
     if (isset($data->parameters)) {
         $params = array();
         foreach ($data->parameters as $key => $value) {
             $params[Horde_String::lower($key)] = $value;
         }
         $params = Horde_Mime::decodeParam('content-type', $params);
         foreach ($params['params'] as $key => $value) {
             $ob->setContentTypeParameter($key, $value);
         }
     }
     // Optional entries. 'location' and 'language' not supported
     if (isset($data->disposition)) {
         $ob->setDisposition($data->disposition);
         if (isset($data->dparameters)) {
             $dparams = array();
             foreach ($data->dparameters as $key => $value) {
                 $dparams[Horde_String::lower($key)] = $value;
             }
             $dparams = Horde_Mime::decodeParam('content-disposition', $dparams);
             foreach ($dparams['params'] as $key => $value) {
                 $ob->setDispositionParameter($key, $value);
             }
         }
     }
     if ($ob->getPrimaryType() == 'multipart') {
         // multipart/* specific entries
         foreach ($data->subParts as $val) {
             $ob->addPart($this->_parseStructure($val));
         }
     } else {
         // Required options
         if (isset($data->partID)) {
             $ob->setContentId($data->partID);
         }
         $ob->setTransferEncoding(Horde_String::lower($data->encoding));
         $ob->setBytes($data->bytes);
         if ($ob->getType() == 'message/rfc822') {
             $ob->addPart($this->_parseStructure(reset($data->subParts)));
         }
     }
     return $ob;
 }
Example #16
0
 /**
  * Creates a MIME object from the text of one part of a MIME message.
  *
  * @param string $header  The header text.
  * @param string $body    The body text.
  * @param array $opts     Additional options:
  * <pre>
  *   - ctype: (string) The default content-type.
  *   - forcemime: (boolean) If true, the message data is assumed to be
  *                MIME data. If not, a MIME-Version header must exist to
  *                be parsed as a MIME message.
  *   - level: (integer) Current nesting level.
  *   - no_body: (boolean) If true, don't set body contents of parts.
  * </pre>
  *
  * @return Horde_Mime_Part  The MIME part object.
  */
 protected static function _getStructure($header, $body, array $opts = array())
 {
     $opts = array_merge(array('ctype' => 'text/plain', 'forcemime' => false, 'level' => 0, 'no_body' => false), $opts);
     /* Parse headers text into a Horde_Mime_Headers object. */
     $hdrs = Horde_Mime_Headers::parseHeaders($header);
     $ob = new Horde_Mime_Part();
     /* This is not a MIME message. */
     if (!$opts['forcemime'] && !isset($hdrs['MIME-Version'])) {
         $ob->setType('text/plain');
         if ($len = strlen($body)) {
             if ($opts['no_body']) {
                 $ob->setBytes($len);
             } else {
                 $ob->setContents($body);
             }
         }
         return $ob;
     }
     /* Content type. */
     if ($tmp = $hdrs['Content-Type']) {
         $ob->setType($tmp->value);
         foreach ($tmp->params as $key => $val) {
             $ob->setContentTypeParameter($key, $val);
         }
     } else {
         $ob->setType($opts['ctype']);
     }
     /* Content transfer encoding. */
     if ($tmp = $hdrs['Content-Transfer-Encoding']) {
         $ob->setTransferEncoding(strval($tmp));
     }
     /* Content-Description. */
     if ($tmp = $hdrs['Content-Description']) {
         $ob->setDescription(strval($tmp));
     }
     /* Content-Disposition. */
     if ($tmp = $hdrs['Content-Disposition']) {
         $ob->setDisposition($tmp->value);
         foreach ($tmp->params as $key => $val) {
             $ob->setDispositionParameter($key, $val);
         }
     }
     /* Content-Duration */
     if ($tmp = $hdrs['Content-Duration']) {
         $ob->setDuration(strval($tmp));
     }
     /* Content-ID. */
     if ($tmp = $hdrs['Content-Id']) {
         $ob->setContentId(strval($tmp));
     }
     if (($len = strlen($body)) && $ob->getPrimaryType() != 'multipart') {
         if ($opts['no_body']) {
             $ob->setBytes($len);
         } else {
             $ob->setContents($body);
         }
     }
     if (++$opts['level'] >= self::NESTING_LIMIT) {
         return $ob;
     }
     /* Process subparts. */
     switch ($ob->getPrimaryType()) {
         case 'message':
             if ($ob->getSubType() == 'rfc822') {
                 $ob[] = self::parseMessage($body, array('forcemime' => true, 'no_body' => $opts['no_body']));
             }
             break;
         case 'multipart':
             $boundary = $ob->getContentTypeParameter('boundary');
             if (!is_null($boundary)) {
                 foreach (self::_findBoundary($body, 0, $boundary) as $val) {
                     if (!isset($val['length'])) {
                         break;
                     }
                     $subpart = substr($body, $val['start'], $val['length']);
                     $hdr_pos = self::_findHeader($subpart, self::EOL);
                     $ob[] = self::_getStructure(substr($subpart, 0, $hdr_pos), substr($subpart, $hdr_pos + 2), array('ctype' => $ob->getSubType() == 'digest' ? 'message/rfc822' : 'text/plain', 'forcemime' => true, 'level' => $opts['level'], 'no_body' => $opts['no_body']));
                 }
             }
             break;
     }
     return $ob;
 }
Example #17
0
 /**
  * Recursively parse BODYSTRUCTURE data from a FETCH return (see
  * RFC 3501 [7.4.2]).
  *
  * @param array $data  The tokenized information from the server.
  *
  * @return array  The array of bodystructure information.
  */
 protected function _parseStructure($data)
 {
     $ob = new Horde_Mime_Part();
     // If index 0 is an array, this is a multipart part.
     if (is_array($data[0])) {
         // Keep going through array values until we find a non-array.
         for ($i = 0, $cnt = count($data); $i < $cnt; ++$i) {
             if (!is_array($data[$i])) {
                 break;
             }
             $ob->addPart($this->_parseStructure($data[$i]));
         }
         // The first string entry after an array entry gives us the
         // subpart type.
         $ob->setType('multipart/' . $data[$i]);
         // After the subtype is further extension information. This
         // information MAY not appear for BODYSTRUCTURE requests.
         // This is parameter information.
         if (isset($data[++$i]) && is_array($data[$i])) {
             foreach ($this->_parseStructureParams($data[$i], 'content-type') as $key => $val) {
                 $ob->setContentTypeParameter($key, $val);
             }
         }
         // This is disposition information.
         if (isset($data[++$i]) && is_array($data[$i])) {
             $ob->setDisposition($data[$i][0]);
             foreach ($this->_parseStructureParams($data[$i][1], 'content-disposition') as $key => $val) {
                 $ob->setDispositionParameter($key, $val);
             }
         }
         // This is language information. It is either a single value or
         // a list of values.
         if (isset($data[++$i])) {
             $ob->setLanguage($data[$i]);
         }
         // Ignore: location (RFC 2557)
         // There can be further information returned in the future, but
         // for now we are done.
     } else {
         $ob->setType($data[0] . '/' . $data[1]);
         foreach ($this->_parseStructureParams($data[2], 'content-type') as $key => $val) {
             $ob->setContentTypeParameter($key, $val);
         }
         if ($data[3] !== null) {
             $ob->setContentId($data[3]);
         }
         if ($data[4] !== null) {
             $ob->setDescription(Horde_Mime::decode($data[4]));
         }
         if ($data[5] !== null) {
             $ob->setTransferEncoding($data[5]);
         }
         if ($data[6] !== null) {
             $ob->setBytes($data[6]);
         }
         // If the type is 'message/rfc822' or 'text/*', several extra
         // fields are included
         switch ($ob->getPrimaryType()) {
             case 'message':
                 if ($ob->getSubType() == 'rfc822') {
                     // Ignore: envelope
                     $ob->addPart($this->_parseStructure($data[8]));
                     // Ignore: lines
                     $i = 10;
                 } else {
                     $i = 7;
                 }
                 break;
             case 'text':
                 // Ignore: lines
                 $i = 8;
                 break;
             default:
                 $i = 7;
                 break;
         }
         // After the subtype is further extension information. This
         // information MAY appear for BODYSTRUCTURE requests.
         // Ignore: MD5
         // This is disposition information
         if (isset($data[++$i]) && is_array($data[$i])) {
             $ob->setDisposition($data[$i][0]);
             foreach ($this->_parseStructureParams($data[$i][1], 'content-disposition') as $key => $val) {
                 $ob->setDispositionParameter($key, $val);
             }
         }
         // This is language information. It is either a single value or
         // a list of values.
         if (isset($data[++$i])) {
             $ob->setLanguage($data[$i]);
         }
         // Ignore: location (RFC 2557)
     }
     return $ob;
 }
Example #18
0
 /**
  * Parses an armored message into a Horde_Mime_Part object.
  *
  * @param mixed $text  Either the text to parse or a Horde_Stream object.
  *
  * @return mixed  Either null if no PGP data was found, or a
  *                Horde_Mime_Part object. For detached signature data:
  *                the full contents of the armored text (data + sig) is
  *                contained in the SIG_RAW metadata, and the charset is
  *                contained in the SIG_CHARSET metadata, within the
  *                application/pgp-signature part.
  */
 public function parseToPart($text, $charset = 'UTF-8')
 {
     $parts = $this->parse($text);
     if (empty($parts) || count($parts) == 1 && $parts[0]['type'] == self::ARMOR_TEXT) {
         return null;
     }
     $new_part = new Horde_Mime_Part();
     $new_part->setType('multipart/mixed');
     foreach ($parts as $val) {
         switch ($val['type']) {
             case self::ARMOR_TEXT:
                 $part = new Horde_Mime_Part();
                 $part->setType('text/plain');
                 $part->setCharset($charset);
                 $part->setContents(implode("\n", $val['data']));
                 $new_part->addPart($part);
                 break;
             case self::ARMOR_PUBLIC_KEY:
                 $part = new Horde_Mime_Part();
                 $part->setType('application/pgp-keys');
                 $part->setContents(implode("\n", $val['data']));
                 $new_part->addPart($part);
                 break;
             case self::ARMOR_MESSAGE:
                 $part = new Horde_Mime_Part();
                 $part->setType('multipart/encrypted');
                 $part->setMetadata(self::PGP_ARMOR, true);
                 $part->setContentTypeParameter('protocol', 'application/pgp-encrypted');
                 $part1 = new Horde_Mime_Part();
                 $part1->setType('application/pgp-encrypted');
                 $part1->setContents("Version: 1\n");
                 $part2 = new Horde_Mime_Part();
                 $part2->setType('application/octet-stream');
                 $part2->setContents(implode("\n", $val['data']));
                 $part2->setDisposition('inline');
                 $part->addPart($part1);
                 $part->addPart($part2);
                 $new_part->addPart($part);
                 break;
             case self::ARMOR_SIGNED_MESSAGE:
                 if (($sig = current($parts)) && $sig['type'] == self::ARMOR_SIGNATURE) {
                     $part = new Horde_Mime_Part();
                     $part->setType('multipart/signed');
                     // TODO: add micalg parameter
                     $part->setContentTypeParameter('protocol', 'application/pgp-signature');
                     $part1 = new Horde_Mime_Part();
                     $part1->setType('text/plain');
                     $part1->setCharset($charset);
                     $part1_data = implode("\n", $val['data']);
                     $part1->setContents(substr($part1_data, strpos($part1_data, "\n\n") + 2));
                     $part2 = new Horde_Mime_Part();
                     $part2->setType('application/pgp-signature');
                     $part2->setContents(implode("\n", $sig['data']));
                     $part2->setMetadata(self::SIG_CHARSET, $charset);
                     $part2->setMetadata(self::SIG_RAW, implode("\n", $val['data']) . "\n" . implode("\n", $sig['data']));
                     $part->addPart($part1);
                     $part->addPart($part2);
                     $new_part->addPart($part);
                     next($parts);
                 }
         }
     }
     return $new_part;
 }
Example #19
0
File: Mime.php Project: horde/horde
 /**
  * Create the base MIME part used for encryption (RFC 3156 [4]).
  *
  * @param Horde_Pgp_Element_Message $encrypted  Encrypted data.
  *
  * @return Horde_Mime_Part  Base encrypted MIME part.
  */
 protected function _encryptBase($encrypted)
 {
     $base = new Horde_Mime_Part();
     $base->setType('multipart/encrypted');
     $base->setHeaderCharset('UTF-8');
     $base->setContentTypeParameter('protocol', 'application/pgp-encrypted');
     $part1 = new Horde_Mime_Part();
     $part1->setType('application/pgp-encrypted');
     $part1->setCharset(null);
     $part1->setContents("Version: 1\n", array('encoding' => '7bit'));
     $base[] = $part1;
     $part2 = new Horde_Mime_Part();
     $part2->setType('application/octet-stream');
     $part2->setCharset(null);
     $part2->setContents(strval($encrypted), array('encoding' => '7bit'));
     $part2->setDisposition('inline');
     $base[] = $part2;
     return $base;
 }
Example #20
0
 /**
  * Adds a message part.
  *
  * @param string $mime_type    The content type of the part.
  * @param string $content      The content of the part.
  * @param string $charset      The character set of the part.
  * @param string $disposition  The content disposition of the part.
  *
  * @return integer  The part number.
  */
 public function addPart($mime_type, $content, $charset = 'us-ascii', $disposition = null)
 {
     $part = new Horde_Mime_Part();
     $part->setType($mime_type);
     $part->setCharset($charset);
     $part->setDisposition($disposition);
     $part->setContents($content);
     return $this->addMimePart($part);
 }
Example #21
0
 /**
  * Recursively parse BODYSTRUCTURE data from a FETCH return (see
  * RFC 3501 [7.4.2]).
  *
  * @param Horde_Imap_Client_Tokenize $data  Data returned from the server.
  *
  * @return Horde_Mime_Part  Mime part object.
  */
 protected function _parseBodystructure(Horde_Imap_Client_Tokenize $data)
 {
     $ob = new Horde_Mime_Part();
     // If index 0 is an array, this is a multipart part.
     if (($entry = $data->next()) === true) {
         do {
             $ob->addPart($this->_parseBodystructure($data));
         } while (($entry = $data->next()) === true);
         // The subpart type.
         $ob->setType('multipart/' . $entry);
         // After the subtype is further extension information. This
         // information MAY appear for BODYSTRUCTURE requests.
         // This is parameter information.
         if (($tmp = $data->next()) === false) {
             return $ob;
         } elseif ($tmp === true) {
             foreach ($this->_parseStructureParams($data, 'content-type') as $key => $val) {
                 $ob->setContentTypeParameter($key, $val);
             }
         }
     } else {
         $ob->setType($entry . '/' . $data->next());
         if ($data->next() === true) {
             foreach ($this->_parseStructureParams($data, 'content-type') as $key => $val) {
                 $ob->setContentTypeParameter($key, $val);
             }
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setContentId($tmp);
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setDescription(Horde_Mime::decode($tmp));
         }
         if (!is_null($tmp = $data->next())) {
             $ob->setTransferEncoding($tmp);
         }
         $ob->setBytes($data->next());
         // If the type is 'message/rfc822' or 'text/*', several extra
         // fields are included
         switch ($ob->getPrimaryType()) {
             case 'message':
                 if ($ob->getSubType() == 'rfc822') {
                     if ($data->next() === true) {
                         // Ignore: envelope
                         $data->flushIterator(false);
                     }
                     if ($data->next() === true) {
                         $ob->addPart($this->_parseBodystructure($data));
                     }
                     $data->next();
                     // Ignore: lines
                 }
                 break;
             case 'text':
                 $data->next();
                 // Ignore: lines
                 break;
         }
         // After the subtype is further extension information. This
         // information MAY appear for BODYSTRUCTURE requests.
         // Ignore: MD5
         if ($data->next() === false) {
             return $ob;
         }
     }
     // This is disposition information
     if (($tmp = $data->next()) === false) {
         return $ob;
     } elseif ($tmp === true) {
         $ob->setDisposition($data->next());
         if ($data->next() === true) {
             foreach ($this->_parseStructureParams($data, 'content-disposition') as $key => $val) {
                 $ob->setDispositionParameter($key, $val);
             }
         }
         $data->next();
     }
     // This is language information. It is either a single value or a list
     // of values.
     if (($tmp = $data->next()) === false) {
         return $ob;
     } elseif (!is_null($tmp)) {
         $ob->setLanguage($tmp === true ? $data->flushIterator() : $tmp);
     }
     // Ignore location (RFC 2557) and consume closing paren.
     $data->flushIterator(false);
     return $ob;
 }
Example #22
0
 /**
  * Parse the output from imap_fetchstructure() into a MIME Part object.
  *
  * @param object $data  Data from imap_fetchstructure().
  *
  * @return Horde_Mime_Part  A MIME Part object.
  */
 protected function _parseStructure($data)
 {
     $ob = new Horde_Mime_Part();
     $ob->setType($this->_mimeTypes[$data->type] . '/' . ($data->ifsubtype ? strtolower($data->subtype) : Horde_Mime_Part::UNKNOWN));
     // Optional for multipart-parts, required for all others
     if ($data->ifparameters) {
         $params = array();
         foreach ($data->parameters as $val) {
             $params[$val->attribute] = $val->value;
         }
         $params = Horde_Mime::decodeParam('content-type', $params);
         foreach ($params['params'] as $key => $val) {
             $ob->setContentTypeParameter($key, $val);
         }
     }
     // Optional entries. 'location' and 'language' not supported
     if ($data->ifdisposition) {
         $ob->setDisposition($data->disposition);
         if ($data->ifdparameters) {
             $dparams = array();
             foreach ($data->dparameters as $val) {
                 $dparams[$val->attribute] = $val->value;
             }
             $dparams = Horde_Mime::decodeParam('content-disposition', $dparams);
             foreach ($dparams['params'] as $key => $val) {
                 $ob->setDispositionParameter($key, $val);
             }
         }
     }
     if ($ob->getPrimaryType() == 'multipart') {
         // multipart/* specific entries
         foreach ($data->parts as $val) {
             $ob->addPart($this->_parseStructure($val));
         }
     } else {
         // Required options
         if ($data->ifid) {
             $ob->setContentId($data->id);
         }
         if ($data->ifdescription) {
             $ob->setDescription(Horde_Mime::decode($data->description));
         }
         $ob->setTransferEncoding($this->_mimeEncodings[$data->encoding]);
         $ob->setBytes($data->bytes);
         if ($ob->getType() == 'message/rfc822') {
             $ob->addPart($this->_parseStructure(reset($data->parts)));
         }
     }
     return $ob;
 }