Mercurial > hg > rc1
diff plugins/enigma/lib/enigma_mime_message.php @ 0:1e000243b222
vanilla 1.3.3 distro, I hope
author | Charlie Root |
---|---|
date | Thu, 04 Jan 2018 15:50:29 -0500 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/enigma/lib/enigma_mime_message.php Thu Jan 04 15:50:29 2018 -0500 @@ -0,0 +1,305 @@ +<?php + +/** + +-------------------------------------------------------------------------+ + | Mail_mime wrapper for the Enigma Plugin | + | | + | Copyright (C) 2010-2015 The Roundcube Dev Team | + | | + | Licensed under the GNU General Public License version 3 or | + | any later version with exceptions for skins & plugins. | + | See the README file for a full license statement. | + | | + +-------------------------------------------------------------------------+ + | Author: Aleksander Machniak <alec@alec.pl> | + +-------------------------------------------------------------------------+ +*/ + +class enigma_mime_message extends Mail_mime +{ + const PGP_SIGNED = 1; + const PGP_ENCRYPTED = 2; + + protected $type; + protected $message; + protected $body; + protected $signature; + protected $encrypted; + protected $micalg; + + + /** + * Object constructor + * + * @param Mail_mime Original message + * @param int Output message type + */ + function __construct($message, $type) + { + $this->message = $message; + $this->type = $type; + + // clone parameters + foreach (array_keys($this->build_params) as $param) { + $this->build_params[$param] = $message->getParam($param); + } + + // clone headers + $this->headers = $message->headers(); + + // \r\n is must-have here + $this->body = $message->get() . "\r\n"; + } + + /** + * Check if the message is multipart (requires PGP/MIME) + * + * @return bool True if it is multipart, otherwise False + */ + public function isMultipart() + { + return $this->message instanceof enigma_mime_message + || $this->message->isMultipart() || $this->message->getHTMLBody(); + } + + /** + * Get e-mail address of message sender + * + * @return string Sender address + */ + public function getFromAddress() + { + // get sender address + $headers = $this->message->headers(); + $from = rcube_mime::decode_address_list($headers['From'], 1, false, null, true); + $from = $from[1]; + + return $from; + } + + /** + * Get recipients' e-mail addresses + * + * @return array Recipients' addresses + */ + public function getRecipients() + { + // get sender address + $headers = $this->message->headers(); + $to = rcube_mime::decode_address_list($headers['To'], null, false, null, true); + $cc = rcube_mime::decode_address_list($headers['Cc'], null, false, null, true); + $bcc = rcube_mime::decode_address_list($headers['Bcc'], null, false, null, true); + + $recipients = array_unique(array_merge($to, $cc, $bcc)); + $recipients = array_diff($recipients, array('undisclosed-recipients:')); + + return $recipients; + } + + /** + * Get original message body, to be encrypted/signed + * + * @return string Message body + */ + public function getOrigBody() + { + $_headers = $this->message->headers(); + $headers = array(); + + if ($_headers['Content-Transfer-Encoding'] + && stripos($_headers['Content-Type'], 'multipart') === false + ) { + $headers[] = 'Content-Transfer-Encoding: ' . $_headers['Content-Transfer-Encoding']; + } + $headers[] = 'Content-Type: ' . $_headers['Content-Type']; + + return implode("\r\n", $headers) . "\r\n\r\n" . $this->body; + } + + /** + * Register signature attachment + * + * @param string Signature body + * @param string Hash algorithm name + */ + public function addPGPSignature($body, $algorithm = null) + { + $this->signature = $body; + $this->micalg = $algorithm; + + // Reset Content-Type to be overwritten with valid boundary + unset($this->headers['Content-Type']); + unset($this->headers['Content-Transfer-Encoding']); + } + + /** + * Register encrypted body + * + * @param string Encrypted body + */ + public function setPGPEncryptedBody($body) + { + $this->encrypted = $body; + + // Reset Content-Type to be overwritten with valid boundary + unset($this->headers['Content-Type']); + unset($this->headers['Content-Transfer-Encoding']); + } + + /** + * Builds the multipart message. + * + * @param array $params Build parameters that change the way the email + * is built. Should be associative. See $_build_params. + * @param resource $filename Output file where to save the message instead of + * returning it + * @param boolean $skip_head True if you want to return/save only the message + * without headers + * + * @return mixed The MIME message content string, null or PEAR error object + */ + public function get($params = null, $filename = null, $skip_head = false) + { + if (!empty($params)) { + foreach ($params as $key => $value) { + $this->build_params[$key] = $value; + } + } + + $this->checkParams(); + + if ($this->type == self::PGP_SIGNED) { + $params = array( + 'preamble' => "This is an OpenPGP/MIME signed message (RFC 4880 and 3156)", + 'content_type' => "multipart/signed; protocol=\"application/pgp-signature\"", + 'eol' => $this->build_params['eol'], + ); + + if ($this->micalg) { + $params['content_type'] .= "; micalg=pgp-" . $this->micalg; + } + + $message = new Mail_mimePart('', $params); + + if (!empty($this->body)) { + $headers = $this->message->headers(); + $params = array('content_type' => $headers['Content-Type']); + + if ($headers['Content-Transfer-Encoding'] + && stripos($headers['Content-Type'], 'multipart') === false + ) { + $params['encoding'] = $headers['Content-Transfer-Encoding']; + } + + $message->addSubpart($this->body, $params); + } + + if (!empty($this->signature)) { + $message->addSubpart($this->signature, array( + 'filename' => 'signature.asc', + 'content_type' => 'application/pgp-signature', + 'disposition' => 'attachment', + 'description' => 'OpenPGP digital signature', + )); + } + } + else if ($this->type == self::PGP_ENCRYPTED) { + $params = array( + 'preamble' => "This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156)", + 'content_type' => "multipart/encrypted; protocol=\"application/pgp-encrypted\"", + 'eol' => $this->build_params['eol'], + ); + + $message = new Mail_mimePart('', $params); + + $message->addSubpart('Version: 1', array( + 'content_type' => 'application/pgp-encrypted', + 'description' => 'PGP/MIME version identification', + )); + + $message->addSubpart($this->encrypted, array( + 'content_type' => 'application/octet-stream', + 'description' => 'PGP/MIME encrypted message', + 'disposition' => 'inline', + 'filename' => 'encrypted.asc', + )); + } + + // Use saved boundary + if (!empty($this->build_params['boundary'])) { + $boundary = $this->build_params['boundary']; + } + else { + $boundary = null; + } + + // Write output to file + if ($filename) { + // Append mimePart message headers and body into file + $headers = $message->encodeToFile($filename, $boundary, $skip_head); + + if ($this->isError($headers)) { + return $headers; + } + + $this->headers = array_merge($this->headers, $headers); + + return; + } + else { + $output = $message->encode($boundary, $skip_head); + + if ($this->isError($output)) { + return $output; + } + + $this->headers = array_merge($this->headers, $output['headers']); + + return $output['body']; + } + } + + /** + * Get Content-Type and Content-Transfer-Encoding headers of the message + * + * @return array Headers array + */ + protected function contentHeaders() + { + $this->checkParams(); + + $eol = $this->build_params['eol'] ?: "\r\n"; + + // multipart message: and boundary + if (!empty($this->build_params['boundary'])) { + $boundary = $this->build_params['boundary']; + } + else if (!empty($this->headers['Content-Type']) + && preg_match('/boundary="([^"]+)"/', $this->headers['Content-Type'], $m) + ) { + $boundary = $m[1]; + } + else { + $boundary = '=_' . md5(rand() . microtime()); + } + + $this->build_params['boundary'] = $boundary; + + if ($this->type == self::PGP_SIGNED) { + $headers['Content-Type'] = "multipart/signed;$eol" + ." protocol=\"application/pgp-signature\";$eol" + ." boundary=\"$boundary\""; + + if ($this->micalg) { + $headers['Content-Type'] .= ";{$eol} micalg=pgp-" . $this->micalg; + } + } + else if ($this->type == self::PGP_ENCRYPTED) { + $headers['Content-Type'] = "multipart/encrypted;$eol" + ." protocol=\"application/pgp-encrypted\";$eol" + ." boundary=\"$boundary\""; + } + + return $headers; + } +}