comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:1e000243b222
1 <?php
2
3 /**
4 +-------------------------------------------------------------------------+
5 | Mail_mime wrapper for the Enigma Plugin |
6 | |
7 | Copyright (C) 2010-2015 The Roundcube Dev Team |
8 | |
9 | Licensed under the GNU General Public License version 3 or |
10 | any later version with exceptions for skins & plugins. |
11 | See the README file for a full license statement. |
12 | |
13 +-------------------------------------------------------------------------+
14 | Author: Aleksander Machniak <alec@alec.pl> |
15 +-------------------------------------------------------------------------+
16 */
17
18 class enigma_mime_message extends Mail_mime
19 {
20 const PGP_SIGNED = 1;
21 const PGP_ENCRYPTED = 2;
22
23 protected $type;
24 protected $message;
25 protected $body;
26 protected $signature;
27 protected $encrypted;
28 protected $micalg;
29
30
31 /**
32 * Object constructor
33 *
34 * @param Mail_mime Original message
35 * @param int Output message type
36 */
37 function __construct($message, $type)
38 {
39 $this->message = $message;
40 $this->type = $type;
41
42 // clone parameters
43 foreach (array_keys($this->build_params) as $param) {
44 $this->build_params[$param] = $message->getParam($param);
45 }
46
47 // clone headers
48 $this->headers = $message->headers();
49
50 // \r\n is must-have here
51 $this->body = $message->get() . "\r\n";
52 }
53
54 /**
55 * Check if the message is multipart (requires PGP/MIME)
56 *
57 * @return bool True if it is multipart, otherwise False
58 */
59 public function isMultipart()
60 {
61 return $this->message instanceof enigma_mime_message
62 || $this->message->isMultipart() || $this->message->getHTMLBody();
63 }
64
65 /**
66 * Get e-mail address of message sender
67 *
68 * @return string Sender address
69 */
70 public function getFromAddress()
71 {
72 // get sender address
73 $headers = $this->message->headers();
74 $from = rcube_mime::decode_address_list($headers['From'], 1, false, null, true);
75 $from = $from[1];
76
77 return $from;
78 }
79
80 /**
81 * Get recipients' e-mail addresses
82 *
83 * @return array Recipients' addresses
84 */
85 public function getRecipients()
86 {
87 // get sender address
88 $headers = $this->message->headers();
89 $to = rcube_mime::decode_address_list($headers['To'], null, false, null, true);
90 $cc = rcube_mime::decode_address_list($headers['Cc'], null, false, null, true);
91 $bcc = rcube_mime::decode_address_list($headers['Bcc'], null, false, null, true);
92
93 $recipients = array_unique(array_merge($to, $cc, $bcc));
94 $recipients = array_diff($recipients, array('undisclosed-recipients:'));
95
96 return $recipients;
97 }
98
99 /**
100 * Get original message body, to be encrypted/signed
101 *
102 * @return string Message body
103 */
104 public function getOrigBody()
105 {
106 $_headers = $this->message->headers();
107 $headers = array();
108
109 if ($_headers['Content-Transfer-Encoding']
110 && stripos($_headers['Content-Type'], 'multipart') === false
111 ) {
112 $headers[] = 'Content-Transfer-Encoding: ' . $_headers['Content-Transfer-Encoding'];
113 }
114 $headers[] = 'Content-Type: ' . $_headers['Content-Type'];
115
116 return implode("\r\n", $headers) . "\r\n\r\n" . $this->body;
117 }
118
119 /**
120 * Register signature attachment
121 *
122 * @param string Signature body
123 * @param string Hash algorithm name
124 */
125 public function addPGPSignature($body, $algorithm = null)
126 {
127 $this->signature = $body;
128 $this->micalg = $algorithm;
129
130 // Reset Content-Type to be overwritten with valid boundary
131 unset($this->headers['Content-Type']);
132 unset($this->headers['Content-Transfer-Encoding']);
133 }
134
135 /**
136 * Register encrypted body
137 *
138 * @param string Encrypted body
139 */
140 public function setPGPEncryptedBody($body)
141 {
142 $this->encrypted = $body;
143
144 // Reset Content-Type to be overwritten with valid boundary
145 unset($this->headers['Content-Type']);
146 unset($this->headers['Content-Transfer-Encoding']);
147 }
148
149 /**
150 * Builds the multipart message.
151 *
152 * @param array $params Build parameters that change the way the email
153 * is built. Should be associative. See $_build_params.
154 * @param resource $filename Output file where to save the message instead of
155 * returning it
156 * @param boolean $skip_head True if you want to return/save only the message
157 * without headers
158 *
159 * @return mixed The MIME message content string, null or PEAR error object
160 */
161 public function get($params = null, $filename = null, $skip_head = false)
162 {
163 if (!empty($params)) {
164 foreach ($params as $key => $value) {
165 $this->build_params[$key] = $value;
166 }
167 }
168
169 $this->checkParams();
170
171 if ($this->type == self::PGP_SIGNED) {
172 $params = array(
173 'preamble' => "This is an OpenPGP/MIME signed message (RFC 4880 and 3156)",
174 'content_type' => "multipart/signed; protocol=\"application/pgp-signature\"",
175 'eol' => $this->build_params['eol'],
176 );
177
178 if ($this->micalg) {
179 $params['content_type'] .= "; micalg=pgp-" . $this->micalg;
180 }
181
182 $message = new Mail_mimePart('', $params);
183
184 if (!empty($this->body)) {
185 $headers = $this->message->headers();
186 $params = array('content_type' => $headers['Content-Type']);
187
188 if ($headers['Content-Transfer-Encoding']
189 && stripos($headers['Content-Type'], 'multipart') === false
190 ) {
191 $params['encoding'] = $headers['Content-Transfer-Encoding'];
192 }
193
194 $message->addSubpart($this->body, $params);
195 }
196
197 if (!empty($this->signature)) {
198 $message->addSubpart($this->signature, array(
199 'filename' => 'signature.asc',
200 'content_type' => 'application/pgp-signature',
201 'disposition' => 'attachment',
202 'description' => 'OpenPGP digital signature',
203 ));
204 }
205 }
206 else if ($this->type == self::PGP_ENCRYPTED) {
207 $params = array(
208 'preamble' => "This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156)",
209 'content_type' => "multipart/encrypted; protocol=\"application/pgp-encrypted\"",
210 'eol' => $this->build_params['eol'],
211 );
212
213 $message = new Mail_mimePart('', $params);
214
215 $message->addSubpart('Version: 1', array(
216 'content_type' => 'application/pgp-encrypted',
217 'description' => 'PGP/MIME version identification',
218 ));
219
220 $message->addSubpart($this->encrypted, array(
221 'content_type' => 'application/octet-stream',
222 'description' => 'PGP/MIME encrypted message',
223 'disposition' => 'inline',
224 'filename' => 'encrypted.asc',
225 ));
226 }
227
228 // Use saved boundary
229 if (!empty($this->build_params['boundary'])) {
230 $boundary = $this->build_params['boundary'];
231 }
232 else {
233 $boundary = null;
234 }
235
236 // Write output to file
237 if ($filename) {
238 // Append mimePart message headers and body into file
239 $headers = $message->encodeToFile($filename, $boundary, $skip_head);
240
241 if ($this->isError($headers)) {
242 return $headers;
243 }
244
245 $this->headers = array_merge($this->headers, $headers);
246
247 return;
248 }
249 else {
250 $output = $message->encode($boundary, $skip_head);
251
252 if ($this->isError($output)) {
253 return $output;
254 }
255
256 $this->headers = array_merge($this->headers, $output['headers']);
257
258 return $output['body'];
259 }
260 }
261
262 /**
263 * Get Content-Type and Content-Transfer-Encoding headers of the message
264 *
265 * @return array Headers array
266 */
267 protected function contentHeaders()
268 {
269 $this->checkParams();
270
271 $eol = $this->build_params['eol'] ?: "\r\n";
272
273 // multipart message: and boundary
274 if (!empty($this->build_params['boundary'])) {
275 $boundary = $this->build_params['boundary'];
276 }
277 else if (!empty($this->headers['Content-Type'])
278 && preg_match('/boundary="([^"]+)"/', $this->headers['Content-Type'], $m)
279 ) {
280 $boundary = $m[1];
281 }
282 else {
283 $boundary = '=_' . md5(rand() . microtime());
284 }
285
286 $this->build_params['boundary'] = $boundary;
287
288 if ($this->type == self::PGP_SIGNED) {
289 $headers['Content-Type'] = "multipart/signed;$eol"
290 ." protocol=\"application/pgp-signature\";$eol"
291 ." boundary=\"$boundary\"";
292
293 if ($this->micalg) {
294 $headers['Content-Type'] .= ";{$eol} micalg=pgp-" . $this->micalg;
295 }
296 }
297 else if ($this->type == self::PGP_ENCRYPTED) {
298 $headers['Content-Type'] = "multipart/encrypted;$eol"
299 ." protocol=\"application/pgp-encrypted\";$eol"
300 ." boundary=\"$boundary\"";
301 }
302
303 return $headers;
304 }
305 }