/** * Return the rendered information about the Horde_Mime_Part object. * * URL parameters used by this function: * - tgz_contents: (integer) If set, show contents of ZIP file. * * @return array See Horde_Mime_Viewer_Driver::render(). */ protected function _renderInfo() { global $injector; $vars = $injector->getInstance('Horde_Variables'); if (!$this->getConfigParam('show_contents') && !isset($vars->tgz_contents)) { $status = new IMP_Mime_Status($this->_mimepart, _("This is a compressed file.")); $status->addMimeAction('tgzViewContents', _("Click to display the file contents.")); $status->icon('mime/compressed.png'); return array($this->_mimepart->getMimeId() => array('data' => '', 'status' => $status, 'type' => 'text/html; charset=UTF-8')); } $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/mime')); $view->addHelper('Text'); $view->downloadclass = 'tgzdownload'; $view->files = array(); $view->tableclass = 'tgzcontents'; $tgzInfo = $this->_getTgzInfo(); foreach ($tgzInfo as $key => $val) { if (!strlen($val['data'])) { continue; } $file = new stdClass(); $file->download = ''; $file->name = $val['name']; $file->size = IMP::sizeFormat($val['size']); if (!empty($val['size'])) { $file->download = $this->getConfigParam('imp_contents')->linkView($this->_mimepart, 'download_render', '', array('class' => 'iconImg downloadAtc', 'jstext' => _("Download"), 'params' => array('tgz_attachment' => $key))); } $view->files[] = $file; } return array($this->_mimepart->getMimeId() => array('data' => $view->render('compressed'), 'type' => 'text/html; charset=UTF-8')); }
/** * Return the rendered information about the Horde_Mime_Part object. * * URL parameters used by this function: * - zip_contents: (integer) If set, show contents of ZIP file. * * @return array See Horde_Mime_Viewer_Driver::render(). */ protected function _renderInfo() { global $injector; $vars = $injector->getInstance('Horde_Variables'); if (!$this->getConfigParam('show_contents') && !$vars->zip_contents) { $status = new IMP_Mime_Status($this->_mimepart, _("This is a compressed file.")); $status->addMimeAction('zipViewContents', _("Click to display the file contents.")); $status->icon('mime/compressed.png'); return array($this->_mimepart->getMimeId() => array('data' => '', 'status' => $status, 'type' => 'text/html; charset=UTF-8')); } $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/mime')); $view->addHelper('Text'); $view->downloadclass = 'zipdownload'; $view->files = array(); $view->tableclass = 'zipcontents'; $zlib = Horde_Util::extensionExists('zlib'); foreach ($this->_getZipInfo() as $key => $val) { $file = new stdClass(); $file->name = $val['name']; $file->size = IMP::sizeFormat($val['size']); /* TODO: Add ability to render in-browser for filetypes we can * handle. */ if (!empty($val['size']) && strstr($val['attr'], 'D') === false && ($zlib && $val['method'] == 0x8 || $val['method'] == 0x0)) { $file->download = $this->getConfigParam('imp_contents')->linkView($this->_mimepart, 'download_render', '', array('class' => 'iconImg downloadAtc', 'jstext' => _("Download"), 'params' => array('zip_attachment' => $key))); } else { $file->download = ''; } $view->files[] = $file; } return array($this->_mimepart->getMimeId() => array('data' => $view->render('compressed'), 'type' => 'text/html; charset=UTF-8')); }
/** * Render out the currently set contents. * * @param boolean $inline Are we viewing inline? * * @return array Two elements: html and status. */ protected function _IMPrender($inline) { global $injector, $registry; $data = $this->_mimepart->getContents(); $view = $registry->getView(); $contents = $this->getConfigParam('imp_contents'); $convert_text = $injector->getInstance('Horde_Variables')->convert_text; /* Don't do IMP DOM processing if converting to text. */ $this->_imptmp = array(); if ($inline && !$convert_text) { $this->_imptmp += array('cid' => null, 'cid_used' => array(), 'cssblock' => false, 'cssbroken' => false, 'imgblock' => false, 'imgbroken' => false, 'inline' => $inline, 'style' => array()); } /* Search for inlined data that we can display (multipart/related * parts) - see RFC 2392. */ if ($related_part = $contents->findMimeType($this->_mimepart->getMimeId(), 'multipart/related')) { $this->_imptmp['cid'] = $related_part->getMetadata('related_ob'); } /* Sanitize the HTML. */ $data = $this->_cleanHTML($data, array('noprefetch' => $inline, 'phishing' => $inline)); if (!empty($this->_imptmp['style'])) { $this->_processDomDocument($data->dom); } if ($inline) { $charset = 'UTF-8'; $data = $data->returnHtml(array('charset' => $charset, 'metacharset' => true)); } else { $charset = $this->_mimepart->getCharset(); $data = $data->returnHtml(); } $status = array(); if ($this->_phishWarn) { $tmp = new IMP_Mime_Status($this->_mimepart, array(_("This message may not be from whom it claims to be."), _("Beware of following any links in it or of providing the sender with any personal information."), _("The links that caused this warning have this background color:") . ' <span style="' . $this->_phishCss . '">' . _("EXAMPLE LINK") . '</span>')); $tmp->action($tmp::WARNING); $status[] = $tmp; } /* We are done processing if converting to text. */ if ($convert_text) { $data = $this->_textFilter($data, 'Html2text', array('wrap' => false)); // Filter bad language. return array('data' => IMP::filterText($data), 'type' => 'text/plain; charset=' . $charset); } if ($inline) { switch ($view) { case $registry::VIEW_SMARTMOBILE: if ($this->_imptmp['imgblock']) { $tmp_txt = _("Show images..."); } elseif ($this->_imptmp['cssblock']) { $tmp_txt = _("Load message styling..."); } else { $tmp_txt = null; } if (!is_null($tmp_txt)) { $tmp = new IMP_Mime_Status($this->_mimepart, array('<a href="#unblock-image" data-role="button" data-theme="e">' . $tmp_txt . '</a>')); $tmp->views = array($view); $status[] = $tmp; } break; default: $attr = array('muid' => strval($contents->getIndicesOb())); if (!$injector->getInstance('IMP_Prefs_Special_ImageReplacement')->canAddToSafeAddrList() || ($from = $contents->getHeader()->getHeader('from')) && $injector->getInstance('IMP_Identity')->hasAddress($from->getAddressList(true))) { $attr['noUnblockImageAdd'] = 1; } $link = $text = null; if ($this->_imptmp['imgblock']) { $text = _("Images have been blocked in this message part."); $link = _("Show Images?"); } elseif ($this->_imptmp['cssblock']) { $text = _("Message styling has been suppressed in this message part since the style data lives on a remote server."); $link = _("Load Styling?"); } if (!is_null($link)) { $tmp = new IMP_Mime_Status($this->_mimepart, $text); $tmp->addMimeAction('unblockImageLink', $link, $attr); $tmp->icon('mime/image.png'); $status[] = $tmp; } if ($this->_imptmp['cssbroken']) { $tmp = new IMP_Mime_Status_RenderIssue($this->_mimepart, array(_("This message contains corrupt styling data so the message contents may not appear correctly below."), $contents->linkViewJS($this->_mimepart, 'view_attach', _("Click to view HTML data in new window; it is possible this will allow you to view the message correctly.")))); $tmp->icon('mime/image.png'); $status[] = $tmp; } if ($this->_imptmp['imgbroken']) { $tmp = new IMP_Mime_Status_RenderIssue($this->_mimepart, array(_("This message contains images that cannot be loaded."))); $tmp->icon('mime/image.png'); $status[] = $tmp; } break; } } /* Add used CID information. */ if ($inline && !empty($this->_imptmp['cid'])) { $related_part->setMetadata('related_cids_used', $this->_imptmp['cid_used']); } return array('data' => $data, 'status' => $status, 'type' => 'text/html; charset=' . $charset); }
/** * 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; }
/** * 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; }