/** * Return the rendered information about the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInfo() { $mdn_id = $this->_mimepart->getMimeId(); $parts = array_keys($this->_mimepart->contentTypeMap()); $status = new IMP_Mime_Status(_("A message you have sent has resulted in a return notification from the recipient.")); $status->icon('info_icon.png', _("Info")); /* RFC 3798 [3]: There are three parts to a delivery status * multipart/report message: * (1) Human readable message * (2) Machine parsable body part (message/disposition-notification) * (3) Original message (optional) */ /* Get the human readable message. */ reset($parts); $part1_id = next($parts); /* Display a link to more detailed message. */ $part2_id = Horde_Mime::mimeIdArithmetic($part1_id, 'next'); $part = $this->getConfigParam('imp_contents')->getMIMEPart($part2_id); if ($part) { $status->addText(sprintf(_("Technical details can be viewed %s."), $this->getConfigParam('imp_contents')->linkViewJS($part, 'view_attach', _("HERE"), array('jstext' => _("Technical details"), 'params' => array('ctype' => 'text/plain', 'mode' => IMP_Contents::RENDER_FULL))))); } $ret[$part2_id] = null; /* Display a link to the sent message. */ $part3_id = Horde_Mime::mimeIdArithmetic($part2_id, 'next'); $part = $this->getConfigParam('imp_contents')->getMIMEPart($part3_id); if ($part) { $status->addText(sprintf(_("The text of the sent message can be viewed %s."), $this->getConfigParam('imp_contents')->linkViewJS($part, 'view_attach', _("HERE"), array('jstext' => _("The text of the sent message"), 'params' => array('ctype' => 'message/rfc822', 'mode' => IMP_Contents::RENDER_FULL))))); foreach (array_keys($part->contentTypeMap()) as $key) { $ret[$key] = null; } } $ret[$mdn_id] = array('data' => '', 'status' => $status, 'type' => 'text/html; charset=' . $this->getConfigParam('charset'), 'wrap' => 'mimePartWrap'); return $ret; }
/** * Return the rendered information about the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInfo() { /* Check to see if convert utility is available. */ if (!$this->_getHordeImageOb(false)) { return array(); } $status = new IMP_Mime_Status(_("This is a thumbnail of a PDF file attachment.")); $status->icon('mime/image.png'); switch ($GLOBALS['registry']->getView()) { case Horde_Registry::VIEW_MINIMAL: $status->addText(Horde::link($this->getConfigParam('imp_contents')->urlView($this->_mimepart, 'view_attach')) . $this->_outputImgTag() . '</a>'); break; default: $status->addText($this->getConfigParam('imp_contents')->linkViewJS($this->_mimepart, 'view_attach', $this->_outputImgTag(), null, null, null)); break; } return array($this->_mimepart->getMimeId() => array('data' => '', 'status' => $status, 'type' => 'text/html; charset=' . $this->getConfigParam('charset'))); }
/** * Return the rendered information about the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInfo() { /* Check to see if convert utility is available. */ if (!$this->_getHordeImageOb(false)) { return array(); } $status = new IMP_Mime_Status($this->_mimepart, _("This is a thumbnail of a PDF file attachment.")); $status->icon('mime/image.png'); $status->addText($this->getConfigParam('imp_contents')->linkViewJS($this->_mimepart, 'view_attach', $this->_outputImgTag(), null, null, null)); return array($this->_mimepart->getMimeId() => array('data' => '', 'status' => $status, 'type' => 'text/html; charset=' . $this->getConfigParam('charset'))); }
/** * Render a MIME Part. * * @param string $mime_id The MIME ID to render. * @param integer $mode One of the RENDER_ constants. * @param array $options Additional options: * - autodetect: (boolean) Attempt to auto-detect MIME type? * - mime_part: (Horde_Mime_Part) The MIME part to render. * - type: (string) Use this MIME type instead of the MIME type * identified in the MIME part. * * @return array See Horde_Mime_Viewer_Base::render(). The following * fields may also be present in addition to the fields * defined in Horde_Mime_Viewer_Base: * - attach: (boolean) Force display of this part as an attachment. * - js: (array) A list of javascript commands to run after the content * is displayed on screen. * - name: (string) Contains the MIME name information. * - wrap: (string) If present, indicates that this part, and all child * parts, will be wrapped in a DIV with the given class name. */ public function renderMIMEPart($mime_id, $mode, array $options = array()) { $this->_buildMessage(); $mime_part = empty($options['mime_part']) ? $this->getMimePart($mime_id) : $options['mime_part']; if (!$mime_part) { return array($mime_id => null); } if (!empty($options['autodetect']) && ($tempfile = Horde::getTempFile()) && ($fp = fopen($tempfile, 'w')) && !is_null($contents = $mime_part->getContents(array('stream' => true)))) { rewind($contents); while (!feof($contents)) { fwrite($fp, fread($contents, 65536)); } fclose($fp); $options['type'] = Horde_Mime_Magic::analyzeFile($tempfile, empty($GLOBALS['conf']['mime']['magic_db']) ? null : $GLOBALS['conf']['mime']['magic_db']); } $type = empty($options['type']) ? null : $options['type']; $viewer = $GLOBALS['injector']->getInstance('IMP_Factory_MimeViewer')->create($mime_part, array('contents' => $this, 'type' => $type)); switch ($mode) { case self::RENDER_INLINE: case self::RENDER_INLINE_AUTO: case self::RENDER_INLINE_DISP_NO: $textmode = 'inline'; $limit = $viewer->getConfigParam('limit_inline_size'); if ($limit && $mime_part->getBytes() > $limit) { $data = ''; $status = new IMP_Mime_Status($mime_part, array(_("This message part cannot be viewed because it is too large."), $this->linkView($mime_part, 'download_attach', _("Click to download the data.")))); $status->icon('alerts/warning.png', _("Warning")); if (method_exists($viewer, 'overLimitText')) { $data = $viewer->overLimitText(); $status->addText(_("The initial portion of this text part is displayed below.")); } return array($mime_id => array('data' => $data, 'name' => '', 'status' => $status, 'type' => 'text/html; charset=' . 'UTF-8')); } break; case self::RENDER_INFO: $textmode = 'info'; break; case self::RENDER_RAW: $textmode = 'raw'; break; case self::RENDER_RAW_FALLBACK: $textmode = $viewer->canRender('raw') ? 'raw' : 'full'; break; case self::RENDER_FULL: default: $textmode = 'full'; break; } $ret = $viewer->render($textmode); if (empty($ret)) { return $mode == self::RENDER_INLINE_AUTO ? $this->renderMIMEPart($mime_id, self::RENDER_INFO, $options) : array(); } if (!empty($ret[$mime_id]) && !isset($ret[$mime_id]['name'])) { $ret[$mime_id]['name'] = $mime_part->getName(true); } /* Don't show empty parts. */ if ($textmode == 'inline' && !is_null($ret[$mime_id]['data']) && !strlen($ret[$mime_id]['data']) && !isset($ret[$mime_id]['status'])) { $ret[$mime_id] = null; } return $ret; }
/** * Return the rendered information about the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInfo() { $parts = array_keys($this->_mimepart->contentTypeMap()); /* RFC 3464 [2]: There are three parts to a delivery status * multipart/report message: * (1) Human readable message * (2) Machine parsable body part (message/delivery-status) * (3) Returned message (optional) * * Information on the message status is found in the 'Action' field * located in part #2 (RFC 3464 [2.3.3]). It can be either 'failed', * 'delayed', 'delivered', 'relayed', or 'expanded'. */ if (count($parts) < 2) { return array(); } reset($parts); $part1_id = next($parts); $part2_id = Horde_Mime::mimeIdArithmetic($part1_id, 'next'); $part3_id = Horde_Mime::mimeIdArithmetic($part2_id, 'next'); /* Get the action first - it appears in the second part. */ $action = null; $part2 = $this->getConfigParam('imp_contents')->getMIMEPart($part2_id); foreach (explode("\n", $part2->getContents()) as $line) { if (stristr($line, 'Action:') !== false) { $action = strtolower(trim(substr($line, strpos($line, ':') + 1))); if (strpos($action, ' ') !== false) { $action = substr($action, 0, strpos($action, ' ')); } break; } } if (is_null($action)) { return array(); } /* Get the correct text strings for the action type. */ switch ($action) { case 'failed': case 'delayed': $status = new IMP_Mime_Status(array(_("ERROR: Your message could not be delivered."), sprintf(_("Technical error details can be viewed %s."), $this->getConfigParam('imp_contents')->linkViewJS($part2, 'view_attach', _("HERE"), array('jstext' => _("Technical details"), 'params' => array('ctype' => 'text/plain', 'mode' => IMP_Contents::RENDER_FULL)))))); $status->action(IMP_Mime_Status::ERROR); $msg_link = _("The text of the returned message can be viewed %s."); $msg_link_status = _("The text of the returned message"); break; case 'delivered': case 'expanded': case 'relayed': $status = new IMP_Mime_Status(array(_("Your message was successfully delivered."), sprintf(_("Technical message details can be viewed %s."), $this->getConfigParam('imp_contents')->linkViewJS($part2, 'view_attach', _("HERE"), array('jstext' => _("Technical details"), 'params' => array('ctype' => 'text/x-simple', 'mode' => IMP_Contents::RENDER_FULL)))))); $status->action(IMP_Mime_Status::SUCCESS); $msg_link = _("The text of the message can be viewed %s."); $msg_link_status = _("The text of the message"); break; default: return array(); } /* Display a link to the returned message, if it exists. */ $part3 = $this->getConfigParam('imp_contents')->getMIMEPart($part3_id); if ($part3) { $status->addText(sprintf($msg_link, $this->getConfigParam('imp_contents')->linkViewJS($part3, 'view_attach', _("HERE"), array('jstext' => $msg_link_status, 'params' => array('ctype' => 'message/rfc822'))))); } $ret = array_fill_keys(array_diff($parts, array($part1_id)), null); $ret[$this->_mimepart->getMimeId()] = array('data' => '', 'status' => $status, 'type' => 'text/html; charset=' . $this->getConfigParam('charset'), 'wrap' => 'mimePartWrap'); return $ret; }
/** * Generates HTML output for 'multipart/signed' MIME parts. * * @return string The HTML output. */ protected function _outputPGPSigned() { global $injector, $prefs, $session; $iterator = $this->_mimepart->partIterator(); $iterator->rewind(); $base_id = $iterator->current()->getMimeId(); $iterator->next(); $signed_id = $iterator->current()->getMimeId(); $id_ob = new Horde_Mime_Id($signed_id); $sig_id = $id_ob->idArithmetic($id_ob::ID_NEXT); if (!IMP_Pgp::enabled()) { return array($sig_id => null); } $status = new IMP_Mime_Status($this->_mimepart); $status->addText(_("The data in this part has been digitally signed via PGP.")); $status->icon('mime/encryption.png', 'PGP'); $ret = array($base_id => array('data' => '', 'nosummary' => true, 'status' => array($status), 'type' => 'text/html; charset=' . $this->getConfigParam('charset'), 'wrap' => 'mimePartWrap'), $sig_id => null); if ($prefs->getValue('pgp_verify') || $injector->getInstance('Horde_Variables')->pgp_verify_msg) { $imp_contents = $this->getConfigParam('imp_contents'); $sig_part = $imp_contents->getMimePart($sig_id); $status2 = new IMP_Mime_Status($this->_mimepart); if (!$sig_part) { $status2->action(IMP_Mime_Status::ERROR); $sig_text = _("This digitally signed message is broken."); $ret[$base_id]['wrap'] = 'mimePartWrapInvalid'; } else { /* Close session, since this may be a long-running * operation. */ $session->close(); try { $imp_pgp = $injector->getInstance('IMP_Pgp'); if ($sig_raw = $sig_part->getMetadata(Horde_Crypt_Pgp_Parse::SIG_RAW)) { $sig_result = $imp_pgp->verifySignature($sig_raw, $this->_getSender()->bare_address, null, $sig_part->getMetadata(Horde_Crypt_Pgp_Parse::SIG_CHARSET)); } else { $stream = $imp_contents->isEmbedded($signed_id) ? $this->_mimepart->getMetadata(self::PGP_SIGN_ENC) : $imp_contents->getBodyPart($signed_id, array('mimeheaders' => true, 'stream' => true))->data; rewind($stream); stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol'); $filter = stream_filter_append($stream, 'horde_eol', STREAM_FILTER_READ, array('eol' => Horde_Mime_Part::RFC_EOL)); $sig_result = $imp_pgp->verifySignature(stream_get_contents($stream), $this->_getSender()->bare_address, $sig_part->getContents()); stream_filter_remove($filter); } $status2->action(IMP_Mime_Status::SUCCESS); $sig_text = $sig_result->message; $ret[$base_id]['wrap'] = 'mimePartWrapValid'; } catch (Horde_Exception $e) { $status2->action(IMP_Mime_Status::ERROR); $sig_text = $e->getMessage(); $ret[$base_id]['wrap'] = 'mimePartWrapInvalid'; } } $status2->addText($this->_textFilter($sig_text, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::NOHTML))); $ret[$base_id]['status'][] = $status2; } else { $status->addMimeAction('pgpVerifyMsg', _("Click to verify the message.")); } return $ret; }
/** * Generates HTML output for 'multipart/signed' MIME parts. * * @return string The HTML output. */ protected function _outputPGPSigned() { global $conf, $injector, $prefs, $registry, $session; $partlist = array_keys($this->_mimepart->contentTypeMap()); $base_id = reset($partlist); $signed_id = next($partlist); $sig_id = Horde_Mime::mimeIdArithmetic($signed_id, 'next'); if (!$prefs->getValue('use_pgp') || empty($conf['gnupg']['path'])) { return array($sig_id => null); } $status = new IMP_Mime_Status(); $status->addText(_("The data in this part has been digitally signed via PGP.")); $status->icon('mime/encryption.png', 'PGP'); $ret = array($base_id => array('data' => '', 'nosummary' => true, 'status' => array($status), 'type' => 'text/html; charset=' . $this->getConfigParam('charset'), 'wrap' => 'mimePartWrap'), $sig_id => null); if ($prefs->getValue('pgp_verify') || $injector->getInstance('Horde_Variables')->pgp_verify_msg) { $imp_contents = $this->getConfigParam('imp_contents'); $sig_part = $imp_contents->getMIMEPart($sig_id); $status2 = new IMP_Mime_Status(); if (!$sig_part) { $status2->action(IMP_Mime_Status::ERROR); $sig_text = _("This digitally signed message is broken."); $ret[$base_id]['wrap'] = 'mimePartWrapInvalid'; } else { /* Close session, since this may be a long-running * operation. */ $session->close(); try { $imp_pgp = $injector->getInstance('IMP_Crypt_Pgp'); if ($sig_raw = $sig_part->getMetadata(Horde_Crypt_Pgp_Parse::SIG_RAW)) { $sig_result = $imp_pgp->verifySignature($sig_raw, $this->_getSender()->bare_address, null, $sig_part->getMetadata(Horde_Crypt_Pgp_Parse::SIG_CHARSET)); } else { $stream = $imp_contents->isEmbedded($signed_id) ? $this->_mimepart->getMetadata(self::PGP_SIGN_ENC) : $imp_contents->getBodyPart($signed_id, array('mimeheaders' => true, 'stream' => true))->data; rewind($stream); stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol'); stream_filter_append($stream, 'horde_eol', STREAM_FILTER_READ, array('eol' => Horde_Mime_Part::RFC_EOL)); $sig_result = $imp_pgp->verifySignature(stream_get_contents($stream), $this->_getSender()->bare_address, $sig_part->getContents()); } $status2->action(IMP_Mime_Status::SUCCESS); $sig_text = $sig_result->message; $ret[$base_id]['wrap'] = 'mimePartWrapValid'; } catch (Horde_Exception $e) { $status2->action(IMP_Mime_Status::ERROR); $sig_text = $e->getMessage(); $ret[$base_id]['wrap'] = 'mimePartWrapInvalid'; } } $status2->addText($this->_textFilter($sig_text, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::NOHTML))); $ret[$base_id]['status'][] = $status2; } else { switch ($registry->getView()) { case Horde_Registry::VIEW_BASIC: $status->addText(Horde::link(Horde::selfUrlParams()->add(array('pgp_verify_msg' => 1))) . _("Click HERE to verify the message.") . '</a>'); break; case Horde_Registry::VIEW_DYNAMIC: $status->addText(Horde::link('#', '', 'pgpVerifyMsg') . _("Click HERE to verify the message.") . '</a>'); break; } } return $ret; }
/** * Return the rendered information about the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInfo() { $imp_contents = $this->getConfigParam('imp_contents'); $machine = $original = null; $ret = array(); switch ($this->_mimepart->getType()) { case 'message/disposition-notification': /* Outlook can send a disposition-notification without the * RFC-required multipart/report wrapper. */ $machine = $imp_contents->getMimePart($this->_mimepart->getMimeId()); break; case 'multipart/report': /* RFC 3798 [3]: There are three parts to a delivery status * multipart/report message: * (1) Human readable message * (2) Machine parsable body part * [message/disposition-notification] * (3) Original message (optional) */ $iterator = $this->_mimepart->partIterator(false); $iterator->rewind(); if (!($curr = $iterator->current())) { break; } $part1_id = $curr->getMimeId(); $id_ob = new Horde_Mime_Id($part1_id); /* Technical details. */ $id_ob->id = $id_ob->idArithmetic($id_ob::ID_NEXT); $ret[$id_ob->id] = null; $machine = $imp_contents->getMimePart($id_ob->id); /* Original sent message. */ $original = $imp_contents->getMimePart($id_ob->idArithmetic($id_ob::ID_NEXT)); if ($original) { foreach ($this->_mimepart->partIterator() as $val) { $ret[$val->getMimeId()] = null; } /* Allow the human readable part to be displayed * separately. */ unset($ret[$part1_id]); } break; default: return array($this->_mimepart->getMimeId() => null); } $mdn_status = array(_("A message you have sent has resulted in a return notification from the recipient.")); if ($machine) { $parse = Horde_Mime_Headers::parseHeaders(preg_replace('/\\n{2,}/', "\n", strtr($machine->getContents(), "\r", "\n"))); if (isset($parse['Final-Recipient'])) { list(, $recip) = explode(';', $parse['Final-Recipient']->value_single); if ($recip) { $mdn_status[] = sprintf(_("Recipient: %s"), trim($recip)); } } if (isset($parse['Disposition'])) { list($modes, $type) = explode(';', $parse['Disposition']->value_single); list($action, $sent) = explode('/', $modes); switch (trim(Horde_String::lower($type))) { case 'displayed': $mdn_status[] = _("The message has been displayed to the recipient."); break; case 'deleted': $mdn_status[] = _("The message has been deleted by the recipient; it is unknown whether they viewed the message."); break; } switch (trim(Horde_String::lower($action))) { case 'manual-action': // NOOP break; case 'automatic-action': // NOOP break; } switch (trim(Horde_String::lower($sent))) { case 'mdn-sent-manually': $mdn_status[] = _("This notification was explicitly sent by the recipient."); break; case 'mdn-sent-automatically': // NOOP break; } } } $status = new IMP_Mime_Status($this->_mimepart, $mdn_status); $status->icon('info_icon.png', _("Info")); if ($original) { $status->addText($imp_contents->linkViewJS($original, 'view_attach', _("View the text of the original sent message."), array('params' => array('ctype' => 'message/rfc822', 'mode' => IMP_Contents::RENDER_FULL)))); } $ret[$this->_mimepart->getMimeId()] = array('data' => '', 'status' => $status, 'type' => 'text/html; charset=' . $this->getConfigParam('charset'), 'wrap' => 'mimePartWrap'); return $ret; }
/** * Parse signed data. * * @param boolean $sig_only Only do signature checking? * * @return mixed See self::_getEmbeddedMimeParts(). */ protected function _parseSignedData($sig_only = false) { $partlist = array_keys($this->_mimepart->contentTypeMap()); $base_id = reset($partlist); $data_id = next($partlist); $sig_id = Horde_Mime::mimeIdArithmetic($data_id, 'next'); /* Initialize inline data. */ $status = new IMP_Mime_Status(_("The data in this part has been digitally signed via S/MIME.")); $status->icon('mime/encryption.png', 'S/MIME'); $cache = $this->getConfigParam('imp_contents')->getViewCache(); $cache->smime[$base_id] = array('sig' => $sig_id, 'status' => $status, 'wrap' => 'mimePartWrap'); if (!$GLOBALS['prefs']->getValue('use_smime')) { $status->addText(_("S/MIME support is not enabled so the digital signature is unable to be verified.")); return null; } /* Sanity checking to make sure MIME structure is correct. */ if (!in_array($sig_id, $partlist)) { $status->action(IMP_Mime_Status::ERROR); $cache->smime[$base_id]['wrap'] = 'mimePartWrapInvalid'; $status->addText(_("Invalid S/MIME data.")); /* This will suppress displaying the invalid part. */ $cache->smime[$base_id]['sig'] = $data_id; return null; } $imp_contents = $this->getConfigParam('imp_contents'); $stream = $imp_contents->isEmbedded($base_id) ? $this->_mimepart->getMetadata('imp-smime-decrypt')->stream : $this->_getPartStream($base_id); $raw_text = $this->_mimepart->replaceEOL($stream, Horde_Mime_Part::RFC_EOL); $this->_initSmime(); $sig_result = null; if ($GLOBALS['prefs']->getValue('smime_verify') || $GLOBALS['injector']->getInstance('Horde_Variables')->smime_verify_msg) { try { $sig_result = $this->_impsmime->verifySignature($raw_text); if ($sig_result->verify) { $status->action(IMP_Mime_Status::SUCCESS); } else { $status->action(IMP_Mime_Status::WARNING); } $cache->smime[$base_id]['wrap'] = 'mimePartWrapValid'; $email = is_array($sig_result->email) ? implode(', ', $sig_result->email) : $sig_result->email; $status->addText($sig_result->msg); if (!empty($sig_result->cert)) { $cert = $this->_impsmime->parseCert($sig_result->cert); if (isset($cert['certificate']['subject']['CommonName']) && strcasecmp($email, $cert['certificate']['subject']['CommonName']) !== 0) { $email = $cert['certificate']['subject']['CommonName'] . ' (' . trim($email) . ')'; } } if (!empty($sig_result->cert) && isset($sig_result->email) && $GLOBALS['registry']->hasMethod('contacts/addField') && $GLOBALS['prefs']->getValue('add_source')) { $status->addText(sprintf(_("Sender: %s"), $imp_contents->linkViewJS($this->_mimepart, 'view_attach', htmlspecialchars(strlen($email) ? $email : $sig_result->email), array('jstext' => _("View certificate details"), 'params' => array('mode' => IMP_Contents::RENDER_INLINE, 'view_smime_key' => 1))))); try { $this->_impsmime->getPublicKey($sig_result->email); } catch (Horde_Exception $e) { $imple = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create('IMP_Ajax_Imple_ImportEncryptKey', array('mime_id' => $base_id, 'muid' => strval($imp_contents->getIndicesOb()), 'type' => 'smime')); $status->addText(Horde::link('#', '', '', '', '', '', '', array('id' => $imple->getDomId())) . _("Save the certificate to your Address Book.") . '</a>'); } } elseif (strlen($email)) { $status->addText(sprintf(_("Sender: %s"), htmlspecialchars($email))); } } catch (Horde_Exception $e) { $status->action(IMP_Mime_Status::ERROR); $cache->smime[$base_id]['wrap'] = 'mimePartWrapInvalid'; $status->addText($e->getMessage()); } } else { switch ($GLOBALS['registry']->getView()) { case Horde_Registry::VIEW_BASIC: $status->addText(Horde::link(Horde::selfUrlParams()->add('smime_verify_msg', 1)) . _("Click HERE to verify the data.") . '</a>'); break; case Horde_Registry::VIEW_DYNAMIC: $status->addText(Horde::link('#', '', 'smimeVerifyMsg') . _("Click HERE to verify the data.") . '</a>'); break; } } if ($sig_only) { return; } $subpart = $imp_contents->getMIMEPart($sig_id); if (empty($subpart)) { try { $msg_data = $this->_impsmime->extractSignedContents($raw_text); $subpart = Horde_Mime_Part::parseMessage($msg_data, array('forcemime' => true)); } catch (Horde_Exception $e) { $status->addText($e->getMessage()); return null; } } return $subpart; }
/** * Parse signed data. * * @param boolean $sig_only Only do signature checking? * * @return mixed See self::_getEmbeddedMimeParts(). */ protected function _parseSignedData($sig_only = false) { $iterator = $this->_mimepart->partIterator(); $iterator->rewind(); if (!($curr = $iterator->current())) { return null; } $base_id = $curr->getMimeId(); $iterator->next(); if (!($curr = $iterator->current())) { // application/pkcs-7-mime might be the base part. // See RFC 5751 3.4.2 $data_id = $base_id; } else { $data_id = $curr->getMimeId(); } $id_ob = new Horde_Mime_Id($data_id); $sig_id = $id_ob->idArithmetic($id_ob::ID_NEXT); /* Initialize inline data. */ $status = new IMP_Mime_Status($this->_mimepart, _("The data in this part has been digitally signed via S/MIME.")); $status->icon('mime/encryption.png', 'S/MIME'); $cache = $this->getConfigParam('imp_contents')->getViewCache(); $cache->smime[$base_id] = array('sig' => $sig_id, 'status' => $status, 'wrap' => 'mimePartWrap'); if (!IMP_Smime::enabled()) { $status->addText(_("S/MIME support is not enabled so the digital signature is unable to be verified.")); return null; } $imp_contents = $this->getConfigParam('imp_contents'); $stream = $imp_contents->isEmbedded($base_id) ? $this->_mimepart->getMetadata('imp-smime-decrypt')->stream : $this->_getPartStream($base_id); $raw_text = $this->_mimepart->replaceEOL($stream, Horde_Mime_Part::RFC_EOL); $this->_initSmime(); $sig_result = null; if ($GLOBALS['prefs']->getValue('smime_verify') || $GLOBALS['injector']->getInstance('Horde_Variables')->smime_verify_msg) { try { $sig_result = $this->_impsmime->verifySignature($raw_text); if ($sig_result->verify) { $status->action(IMP_Mime_Status::SUCCESS); } else { $status->action(IMP_Mime_Status::WARNING); } if (!is_array($sig_result->email)) { $sig_result->email = array($sig_result->email); } $email = implode(', ', $sig_result->email); $cache->smime[$base_id]['wrap'] = 'mimePartWrapValid'; $status->addText($sig_result->msg); if (!empty($sig_result->cert)) { $cert = $this->_impsmime->parseCert($sig_result->cert); if (isset($cert['certificate']['subject']['CommonName']) && strcasecmp($email, $cert['certificate']['subject']['CommonName']) !== 0) { $email = $cert['certificate']['subject']['CommonName'] . ' (' . trim($email) . ')'; } } if (!empty($sig_result->cert) && isset($sig_result->email) && $GLOBALS['registry']->hasMethod('contacts/addField') && $GLOBALS['prefs']->getValue('add_source')) { $status->addText(sprintf(_("Sender: %s"), $imp_contents->linkViewJS($this->_mimepart, 'view_attach', htmlspecialchars($email), array('jstext' => _("View certificate details"), 'params' => array('mode' => IMP_Contents::RENDER_INLINE, 'view_smime_key' => 1))))); foreach ($sig_result->email as $single_email) { try { $this->_impsmime->getPublicKey($single_email); } catch (Horde_Exception $e) { $imple = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create('IMP_Ajax_Imple_ImportEncryptKey', array('mime_id' => $base_id, 'muid' => strval($imp_contents->getIndicesOb()), 'type' => 'smime')); $status->addText(Horde::link('#', '', '', '', '', '', '', array('id' => $imple->getDomId())) . _("Save the certificate to your Address Book.") . '</a>'); break; } } } elseif (strlen($email)) { $status->addText(sprintf(_("Sender: %s"), htmlspecialchars($email))); } } catch (Horde_Exception $e) { $status->action(IMP_Mime_Status::ERROR); $cache->smime[$base_id]['wrap'] = 'mimePartWrapInvalid'; $status->addText($e->getMessage()); } } else { $status->addMimeAction('smimeVerifyMsg', _("Click to verify the data.")); } if ($sig_only) { return; } if (!($subpart = $imp_contents->getMimePart($sig_id))) { try { $msg_data = $this->_impsmime->extractSignedContents($raw_text); $subpart = Horde_Mime_Part::parseMessage($msg_data, array('forcemime' => true)); } catch (Horde_Exception $e) { $status->addText($e->getMessage()); return null; } } return $subpart; }
/** * Return the rendered information about the Horde_Mime_Part object. * * @return array See parent::render(). */ protected function _renderInfo() { $imp_contents = $this->getConfigParam('imp_contents'); $machine = $original = $status = null; $mime_id = $this->_mimepart->getMimeId(); $ret = array(); switch ($this->_mimepart->getType()) { case 'message/delivery-status': $machine = $imp_contents->getMimePart($mime_id); break; case 'multipart/report': /* RFC 3464 [2]: There are three parts to a delivery status * multipart/report message: * (1) Human readable message * (2) Machine parsable body part (message/delivery-status) * (3) Returned message (optional) */ $iterator = $this->_mimepart->partIterator(false); $iterator->rewind(); if (!($curr = $iterator->current())) { break; } $part1_id = $curr->getMimeId(); $id_ob = new Horde_Mime_Id($part1_id); /* Technical details. */ $id_ob->id = $id_ob->idArithmetic($id_ob::ID_NEXT); $ret[$id_ob->id] = null; $machine = $imp_contents->getMimePart($id_ob->id); /* Returned message. */ $original = $imp_contents->getMimePart($id_ob->idArithmetic($id_ob::ID_NEXT)); if ($original) { foreach ($this->_mimepart->partIterator() as $val) { $ret[$val->getMimeId()] = null; } /* Allow the human readable part to be displayed * separately. */ unset($ret[$part1_id]); } break; } if (!$machine) { return array($mime_id => null); } $parse = Horde_Mime_Headers::parseHeaders(preg_replace('/\\n{2,}/', "\n", strtr($machine->getContents(), "\r", "\n"))); /* Information on the message status is found in the 'Action' * field located in part #2 (RFC 3464 [2.3.3]). */ if (isset($parse['Action'])) { switch (trim($parse['Action']->value_single)) { case 'failed': case 'delayed': $msg_link = _("View details of the returned message."); $status_action = IMP_Mime_Status::ERROR; $status_msg = _("ERROR: Your message could not be delivered."); break; case 'delivered': case 'expanded': case 'relayed': $msg_link = _("View details of the delivered message."); $status_action = IMP_Mime_Status::SUCCESS; $status_msg = _("Your message was successfully delivered."); break; } if (isset($msg_link)) { $status = new IMP_Mime_Status($this->_mimepart, $status_msg); $status->action($status_action); if (isset($parse['Final-Recipient'])) { list(, $recip) = explode(';', $parse['Final-Recipient']->value_single); $recip_ob = new Horde_Mail_Rfc822_List($recip); if (count($recip_ob)) { $status->addText(sprintf(_("Recipient: %s"), $recip_ob[0])); } } /* Display a link to the returned message, if it exists. */ if ($original) { $status->addText($imp_contents->linkViewJS($original, 'view_attach', $msg_link, array('params' => array('ctype' => 'message/rfc822')))); } } } $ret[$mime_id] = array_filter(array('data' => '', 'status' => $status ?: null, 'type' => 'text/html; charset=' . $this->getConfigParam('charset'), 'wrap' => 'mimePartWrap')); return $ret; }