[ Index ] |
|
Code source de IMP H3 (4.1.5) |
1 <?php 2 3 require_once IMP_BASE . '/lib/Crypt/SMIME.php'; 4 require_once 'Horde/MIME/Structure.php'; 5 6 /** 7 * The IMP_MIME_Viewer_pkcs7 class allows viewing/decrypting of S/MIME 8 * messages. 9 * This class implements parts of RFC 2630, RFC 2632, and RFC 2633. 10 * 11 * This class handles the following MIME types: 12 * application/pkcs7-mime 13 * application/pkcs7-signature 14 * application/x-pkcs7-mime 15 * application/x-pkcs7-signature 16 * 17 * $Horde: imp/lib/MIME/Viewer/pkcs7.php,v 1.68.2.20 2007/01/02 13:55:00 jan Exp $ 18 * 19 * Copyright 2002-2007 Mike Cochrane <mike@graftonhall.co.nz> 20 * Copyright 2004-2007 Michael Slusarz <slusarz@curecanti.org> 21 * 22 * See the enclosed file COPYING for license information (GPL). If you 23 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. 24 * 25 * @author Mike Cochrane <mike@graftonhall.co.nz> 26 * @author Michael Slusarz <slusarz@curecanti.org> 27 * @since IMP 4.0 28 * @package Horde_MIME_Viewer 29 */ 30 class IMP_MIME_Viewer_pkcs7 extends MIME_Viewer { 31 32 /** 33 * IMP_SMIME object. 34 * 35 * @var IMP_SMIME 36 */ 37 var $_impSmime; 38 39 /** 40 * Classwide cache for icons for status messages. 41 * 42 * @var string 43 */ 44 var $_icon = null; 45 46 /** 47 * Pointer to the MIME_Contents item. 48 * 49 * @var MIME_Contents 50 */ 51 var $_contents = null; 52 53 /** 54 * Classwide cache for status messages. 55 * 56 * @var array 57 */ 58 var $_status = array(); 59 60 /** 61 * The IMP_Headers object for the message data. 62 * 63 * @var IMP_Headers 64 */ 65 var $_headers; 66 67 /** 68 * Some mailers set S/MIME messages to always be attachments. However, 69 * most of the time S/MIME is used to secure the contents of the message, 70 * so displaying as an attachment makes no sense. Therefore, force 71 * viewing inline (or at least let MIME_Viewer/MIME_Contents make the 72 * determination on whether the data can be viewed inline or not). 73 * 74 * @var boolean 75 */ 76 var $_forceinline = true; 77 78 /** 79 * Render out the currently set contents. 80 * 81 * @param array $params An array with a reference to a MIME_Contents 82 * object. 83 * 84 * @return string The rendered text in HTML. 85 */ 86 function render($params) 87 { 88 /* Set the MIME_Contents class variable. */ 89 $this->_contents = &$params[0]; 90 91 $msg = ''; 92 93 if (empty($this->_impSmime)) { 94 $this->_impSmime = &new IMP_SMIME(); 95 } 96 97 /* Check to see if S/MIME support is available. */ 98 $openssl_check = $this->_impSmime->checkForOpenSSL(); 99 if ($GLOBALS['prefs']->getValue('use_smime') && 100 !is_a($openssl_check, 'PEAR_Error')) { 101 /* We need to insert JavaScript code now if S/MIME support is 102 active. */ 103 $msg = Util::bufferOutput(array('Horde', 'addScriptFile'), 'popup.js'); 104 } 105 106 /* Get the type of message now. */ 107 $type = $this->_getSMIMEType(); 108 switch ($type) { 109 case 'signed': 110 $msg .= $this->_outputSMIMESigned(); 111 break; 112 113 case 'encrypted': 114 $msg .= $this->_outputSMIMEEncrypted(); 115 break; 116 } 117 118 return $msg; 119 } 120 121 /** 122 * Generates HTML output for the S/MIME key in 123 * 'application/pkcs7-signature' MIME_Parts. 124 * 125 * @access private 126 * 127 * @return string The HTML output. 128 */ 129 function _outputSMIMEKey() 130 { 131 if (!$GLOBALS['prefs']->getValue('use_smime')) { 132 return _("S/MIME support is not enabled."); 133 } else { 134 $mime = &$this->mime_part; 135 $signenc = $mime->getInformation('smime_signenc'); 136 $raw_text = $this->_getRawSMIMEText(); 137 if ($signenc && $mime->getInformation('smime_from')) { 138 $smime_from = $mime->getInformation('smime_from'); 139 $raw_text = "From: $smime_from\n" . $raw_text; 140 } 141 $sig_result = $this->_impSmime->verifySignature($raw_text); 142 return $this->_impSmime->certToHTML($sig_result->cert); 143 } 144 } 145 146 /** 147 * Generates HTML output for 'multipart/signed', 148 * 'application/pkcs7-signature' and 149 * 'application/x-pkcs7-signature' MIME_Parts. 150 * 151 * @access private 152 * 153 * @return string The HTML output. 154 */ 155 function _outputSMIMESigned() 156 { 157 if (Util::getFormData('viewkey')) { 158 return $this->_outputSMIMEKey(); 159 } 160 161 $cert = $text = ''; 162 $mime = &$this->mime_part; 163 $mimetype = $mime->getType(); 164 $active = $GLOBALS['prefs']->getValue('use_smime'); 165 166 $signenc = $mime->getInformation('smime_signenc'); 167 if ($signenc) { 168 $this->_status[] = _("This message has been encrypted via S/MIME."); 169 } 170 171 $this->_initStatus($this->getIcon($mimetype), _("S/MIME")); 172 $this->_status[] = _("This message has been digitally signed via S/MIME."); 173 174 if (!$active) { 175 $this->_status[] = _("S/MIME support is not enabled so the digital signature is unable to be verified."); 176 } 177 178 /* Store S/MIME results in $sig_result. */ 179 $sig_result = null; 180 if ($mimetype == 'multipart/signed') { 181 if (!$signenc) { 182 if (($mimeID = $mime->getMIMEId())) { 183 $mime->setContents($this->_contents->getBodyPart($mimeID)); 184 } else { 185 $mime->setContents($this->_contents->getBody()); 186 } 187 $mime->splitContents(); 188 } 189 190 /* Data that is signed appears in the first MIME subpart. */ 191 $signed_part = $mime->getPart($mime->getRelativeMIMEId(1)); 192 $signed_data = rtrim($signed_part->getCanonicalContents(), "\r"); 193 $mime_message = &MIME_Structure::parseTextMIMEMessage($signed_data); 194 195 /* The S/MIME signature appears in the second MIME subpart. */ 196 $subpart = $mime->getPart($mime->getRelativeMIMEId(2)); 197 if (!$subpart || 198 !in_array($subpart->getType(), array('application/pkcs7-signature', 'application/x-pkcs7-signature'))) { 199 $this->_status[] = _("This message does not appear to be in the correct S/MIME format."); 200 } 201 } elseif (!$active) { 202 $this->_status[] = _("S/MIME support is not enabled so the contents of this signed message cannot be displayed."); 203 } 204 205 if ($active) { 206 $raw_text = $this->_getRawSMIMEText(); 207 if ($signenc && $mime->getInformation('smime_from')) { 208 $smime_from = $mime->getInformation('smime_from'); 209 $raw_text = "From: $smime_from\n" . $raw_text; 210 } 211 $sig_result = $this->_impSmime->verifySignature($raw_text); 212 if (!isset($subpart)) { 213 $msg_data = $this->_impSmime->extractSignedContents($raw_text); 214 if (is_a($msg_data, 'PEAR_Error')) { 215 $this->_status[] = $msg_data->getMessage(); 216 $mime_message = $mime; 217 } else { 218 $mime_message = &MIME_Structure::parseTextMIMEMessage($msg_data); 219 } 220 } 221 222 $text = $this->_outputStatus(); 223 $text .= $this->_outputSMIMESignatureTest($sig_result->result, $sig_result->email); 224 if (!empty($sig_result->cert)) { 225 if (!isset($smime_from) && isset($this->_headers['from'])) { 226 $smime_from = $this->_headers['from']; 227 } 228 if (isset($smime_from) && 229 $GLOBALS['registry']->hasMethod('contacts/addField') && 230 $GLOBALS['prefs']->getValue('add_source')) { 231 $this->_status[] = sprintf(_("The S/MIME certificate of %s: "), @htmlspecialchars($smime_from, ENT_COMPAT, NLS::getCharset())) . 232 $this->_contents->linkViewJS($subpart, 'view_attach', _("View"), '', null, array('viewkey' => 1)) . '/' . 233 Horde::link('#', '', null, null, $this->_impSmime->savePublicKeyURL($sig_result->cert, $smime_from) . ' return false;') . _("Save in your Address Book") . '</a>'; 234 $text .= $this->_outputStatus(); 235 } 236 } 237 } 238 239 if (isset($mime_message)) { 240 /* We need to stick the output into a MIME_Contents object. */ 241 $mc = &new MIME_Contents($mime_message, array('download' => 'download_attach', 'view' => 'view_attach'), array(&$this->_contents)); 242 $mc->buildMessage(); 243 244 $text .= '<table cellpadding="0" cellspacing="0">' . $mc->getMessage(true) . '</table>'; 245 } else { 246 $text = $this->_outputStatus(); 247 } 248 249 return $text; 250 } 251 252 /** 253 * Generates HTML output for 'multipart/encrypted', 254 * 'application/pkcs7-mime' and 255 * 'application/x-pkcs7-mime' MIME_Parts. 256 * 257 * @access private 258 * 259 * @return string The HTML output. 260 */ 261 function _outputSMIMEEncrypted() 262 { 263 $active = $GLOBALS['prefs']->getValue('use_smime'); 264 $mime = &$this->mime_part; 265 $mimetype = $mime->getType(); 266 $msg = ''; 267 268 $this->_initStatus($this->getIcon($mime->getType()), _("S/MIME")); 269 $this->_status[] = _("This message has been encrypted via S/MIME."); 270 271 if (!$active) { 272 $this->_status[] = _("S/MIME support is not currently enabled so the message is unable to be decrypted."); 273 return $this->_outputStatus(); 274 } 275 276 if (!$this->_impSmime->getPersonalPrivateKey()) { 277 $this->_status[] = _("No personal private key exists so the message is unable to be decrypted."); 278 return $this->_outputStatus(); 279 } 280 281 /* Make sure we have a passphrase. */ 282 $passphrase = $this->_impSmime->getPassphrase(); 283 if ($passphrase === false) { 284 $url = $this->_impSmime->getJSOpenWinCode('open_passphrase_dialog'); 285 $this->_status[] = Horde::link('#', _("You must enter the passphrase for your S/MIME private key to view this message"), null, null, $url . ' return false;') . '<em>' . _("You must enter the passphrase for your S/MIME private key to view this message") . '</em></a>.'; 286 $msg .= $this->_outputStatus() . 287 '<script type="text/javascript">' . $url . ';</script>'; 288 return $msg; 289 } 290 291 $raw_text = $this->_getRawSMIMEText(); 292 $decrypted_data = $this->_impSmime->decryptMessage($raw_text); 293 294 if (is_a($decrypted_data, 'PEAR_Error')) { 295 $this->_status[] = $decrypted_data->getMessage(); 296 return $this->_outputStatus(); 297 } 298 299 /* We need to check if this is a signed/encrypted message. */ 300 $mime_message = &MIME_Structure::parseTextMIMEMessage($decrypted_data); 301 if ($mime_message) { 302 /* Check for signed and encoded data. */ 303 if (in_array($mime_message->getType(), array('multipart/signed', 'application/pkcs7-mime', 'application/x-pkcs7-mime'))) { 304 $mime_message->setContents($decrypted_data); 305 $mime_message->splitContents(); 306 $mime_message->setInformation('smime_signenc', true); 307 if (isset($this->_headers['from'])) { 308 $mime_message->setInformation('smime_from', $this->_headers['from']); 309 } 310 } else { 311 $msg .= $this->_outputStatus(); 312 } 313 314 /* We need to stick the output into a MIME_Contents object. */ 315 $mc = &new MIME_Contents($mime_message, array('download' => 'download_attach', 'view' => 'view_attach'), array(&$this->_contents)); 316 $mc->buildMessage(); 317 $msg .= '<table cellpadding="0" cellspacing="0">' . $mc->getMessage(true) . '</table>'; 318 } else { 319 require_once 'Horde/Text/Filter.php'; 320 $msg .= $this->_outputStatus() . 321 '<span class="fixed">' . Text_Filter::filter($decrypted_data, 'text2html', array('parselevel' => TEXT_HTML_SYNTAX)) . '</span>'; 322 } 323 324 return $msg; 325 } 326 327 /** 328 * Return text/html as the content-type. 329 * 330 * @return string "text/html" constant. 331 */ 332 function getType() 333 { 334 return 'text/html; charset=' . NLS::getCharset(); 335 } 336 337 /** 338 * Get the headers of the S/MIME message. 339 * 340 * @access private 341 */ 342 function _getRawSMIMEText() 343 { 344 $mime = &$this->mime_part; 345 346 $mime->setContents($this->_contents->getBody()); 347 if (is_a($this->_contents, 'IMP_Contents') && 348 (($mime->getMIMEId() == 0) || 349 ($mime->splitContents() == false))) { 350 $imp_headers = &$this->_contents->getHeaderOb(); 351 $this->_headers = MIME_Structure::parseMIMEHeaders($imp_headers->getHeaderText(), true, true); 352 return $this->_contents->fullMessageText(); 353 } else { 354 require_once IMP_BASE . '/lib/MIME/Headers.php'; 355 $header_text = $mime->getCanonicalContents(); 356 $header_text = substr($header_text, 0, strpos($header_text, "\r\n\r\n")); 357 $this->_headers = MIME_Structure::parseMIMEHeaders($header_text, true, true); 358 359 $imp_headers = new IMP_Headers(); 360 if (isset($this->_headers['content-type'])) { 361 $imp_headers->addHeader('Content-Type', $this->_headers['content-type']); 362 } 363 if (isset($this->_headers['from'])) { 364 $imp_headers->addHeader('From', $this->_headers['from']); 365 } 366 if (isset($this->_headers['to'])) { 367 $imp_headers->addHeader('To', $this->_headers['to']); 368 } 369 370 return $imp_headers->toString() . $mime->toCanonicalString(); 371 } 372 } 373 374 /* Various formatting helper functions. */ 375 function _initStatus($src, $alt = '') 376 { 377 if (is_null($this->_icon)) { 378 $this->_icon = Horde::img($src, $alt, 'height="16" width="16"', '') . ' '; 379 } 380 } 381 382 function _outputStatus() 383 { 384 $output = ''; 385 if (!empty($this->_status)) { 386 $output = $this->_contents->formatStatusMsg($this->_status, $this->_icon); 387 } 388 $this->_icon = null; 389 $this->_status = array(); 390 return $output; 391 } 392 393 /** 394 * Generates HTML output for the S/MIME signature test. 395 * 396 * @access private 397 * 398 * @param string $result Result string of the S/MIME output concerning 399 * the signature test. 400 * @param string $email The email of the sender. 401 * 402 * @return string The HTML output. 403 */ 404 function _outputSMIMESignatureTest($result, $email) 405 { 406 $text = ''; 407 408 if (is_a($result, 'PEAR_Error')) { 409 if ($result->getCode() == 'horde.warning') { 410 $this->_initStatus($GLOBALS['registry']->getImageDir('horde') . '/alerts/warning.png', _("Warning")); 411 } else { 412 $this->_initStatus($GLOBALS['registry']->getImageDir('horde') . '/alerts/error.png', _("Error")); 413 } 414 $result = $result->getMessage(); 415 } else { 416 $this->_initStatus($GLOBALS['registry']->getImageDir('horde') . '/alerts/success.png', _("Success")); 417 /* This message has been verified but there was no output 418 from the PGP program. */ 419 if (empty($result) || ($result === true)) { 420 $email = (is_array($email)) ? implode(', ', $email): $email; 421 $result = sprintf(_("The message has been verified. Sender: %s."), htmlspecialchars($email)); 422 } 423 } 424 425 require_once 'Horde/Text/Filter.php'; 426 427 $this->_status[] = Text_Filter::filter($result, 'text2html', array('parselevel' => TEXT_HTML_NOHTML)); 428 429 return $this->_outputStatus(); 430 } 431 432 /** 433 * Render out attachment information. 434 * 435 * @param array $params An array with a reference to a MIME_Contents 436 * object. 437 * 438 * @return string The rendered text in HTML. 439 */ 440 function renderAttachmentInfo($params) 441 { 442 $this->_contents = &$params[0]; 443 444 $type = $this->_getSMIMEType(); 445 switch ($type) { 446 case 'signed': 447 $this->_status[] = _("This message contains an attachment that has been digitally signed via S/MIME."); 448 break; 449 450 case 'encrypted': 451 $this->_status[] = _("This message contains an attachment that has been encrypted via S/MIME."); 452 break; 453 } 454 455 $this->_status[] = sprintf(_("Click %s to view the attachment in a separate window."), $this->_contents->linkViewJS($this->mime_part, 'view_attach', _("HERE"), _("View attachment in a separate window"))); 456 $this->_initStatus($this->getIcon($this->mime_part->getType()), _("S/MIME")); 457 return $this->_outputStatus(); 458 } 459 460 /** 461 * Deterimne the S/MIME type of the message. 462 * 463 * @access private 464 * 465 * @return string Either 'encrypted' or 'signed'. 466 */ 467 function _getSMIMEType() 468 { 469 $type = $this->mime_part->getType(); 470 if (in_array($type, array('application/pkcs7-mime', 'application/x-pkcs7-mime'))) { 471 $smime_type = $this->mime_part->getContentTypeParameter('smime-type'); 472 if ($smime_type == 'signed-data') { 473 return 'signed'; 474 } elseif (!$smime_type || ($smime_type == 'enveloped-data')) { 475 return 'encrypted'; 476 } 477 } 478 479 switch ($type) { 480 case 'multipart/signed': 481 case 'application/pkcs7-signature': 482 case 'application/x-pkcs7-signature': 483 return 'signed'; 484 } 485 } 486 487 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Nov 29 12:30:07 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |