Mercurial > hg > rc1
comparison plugins/enigma/lib/enigma_ui.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 | User Interface 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_ui | |
19 { | |
20 private $rc; | |
21 private $enigma; | |
22 private $home; | |
23 private $css_loaded; | |
24 private $js_loaded; | |
25 private $data; | |
26 private $keys_parts = array(); | |
27 private $keys_bodies = array(); | |
28 | |
29 | |
30 function __construct($enigma_plugin, $home='') | |
31 { | |
32 $this->enigma = $enigma_plugin; | |
33 $this->rc = $enigma_plugin->rc; | |
34 $this->home = $home; // we cannot use $enigma_plugin->home here | |
35 } | |
36 | |
37 /** | |
38 * UI initialization and requests handlers. | |
39 * | |
40 * @param string Preferences section | |
41 */ | |
42 function init() | |
43 { | |
44 $this->add_js(); | |
45 | |
46 $action = rcube_utils::get_input_value('_a', rcube_utils::INPUT_GPC); | |
47 | |
48 if ($this->rc->action == 'plugin.enigmakeys') { | |
49 switch ($action) { | |
50 case 'delete': | |
51 $this->key_delete(); | |
52 break; | |
53 /* | |
54 case 'edit': | |
55 $this->key_edit(); | |
56 break; | |
57 */ | |
58 case 'import': | |
59 $this->key_import(); | |
60 break; | |
61 | |
62 case 'export': | |
63 $this->key_export(); | |
64 break; | |
65 | |
66 case 'generate': | |
67 $this->key_generate(); | |
68 break; | |
69 | |
70 case 'create': | |
71 $this->key_create(); | |
72 break; | |
73 | |
74 case 'search': | |
75 case 'list': | |
76 $this->key_list(); | |
77 break; | |
78 | |
79 case 'info': | |
80 $this->key_info(); | |
81 break; | |
82 } | |
83 | |
84 $this->rc->output->add_handlers(array( | |
85 'keyslist' => array($this, 'tpl_keys_list'), | |
86 'keyframe' => array($this, 'tpl_key_frame'), | |
87 'countdisplay' => array($this, 'tpl_keys_rowcount'), | |
88 'searchform' => array($this->rc->output, 'search_form'), | |
89 )); | |
90 | |
91 $this->rc->output->set_pagetitle($this->enigma->gettext('enigmakeys')); | |
92 $this->rc->output->send('enigma.keys'); | |
93 } | |
94 /* | |
95 // Preferences UI | |
96 else if ($this->rc->action == 'plugin.enigmacerts') { | |
97 $this->rc->output->add_handlers(array( | |
98 'keyslist' => array($this, 'tpl_certs_list'), | |
99 'keyframe' => array($this, 'tpl_cert_frame'), | |
100 'countdisplay' => array($this, 'tpl_certs_rowcount'), | |
101 'searchform' => array($this->rc->output, 'search_form'), | |
102 )); | |
103 | |
104 $this->rc->output->set_pagetitle($this->enigma->gettext('enigmacerts')); | |
105 $this->rc->output->send('enigma.certs'); | |
106 } | |
107 */ | |
108 // Message composing UI | |
109 else if ($this->rc->action == 'compose') { | |
110 $this->compose_ui(); | |
111 } | |
112 } | |
113 | |
114 /** | |
115 * Adds CSS style file to the page header. | |
116 */ | |
117 function add_css() | |
118 { | |
119 if ($this->css_loaded) { | |
120 return; | |
121 } | |
122 | |
123 $skin_path = $this->enigma->local_skin_path(); | |
124 $this->enigma->include_stylesheet("$skin_path/enigma.css"); | |
125 $this->css_loaded = true; | |
126 } | |
127 | |
128 /** | |
129 * Adds javascript file to the page header. | |
130 */ | |
131 function add_js() | |
132 { | |
133 if ($this->js_loaded) { | |
134 return; | |
135 } | |
136 | |
137 $this->enigma->include_script('enigma.js'); | |
138 | |
139 $this->js_loaded = true; | |
140 } | |
141 | |
142 /** | |
143 * Initializes key password prompt | |
144 * | |
145 * @param enigma_error $status Error object with key info | |
146 * @param array $params Optional prompt parameters | |
147 */ | |
148 function password_prompt($status, $params = array()) | |
149 { | |
150 $data = $status->getData('missing'); | |
151 | |
152 if (empty($data)) { | |
153 $data = $status->getData('bad'); | |
154 } | |
155 | |
156 $keyid = key($data); | |
157 $data = array( | |
158 'keyid' => $params['keyid'] ?: $keyid, | |
159 'user' => $data[$keyid] | |
160 ); | |
161 | |
162 // With GnuPG 2.1 user name may not be specified (e.g. on private | |
163 // key export), we'll get the key information and set the name appropriately | |
164 if ($keyid && $params['keyid'] && strpos($data['user'], $keyid) !== false) { | |
165 $key = $this->enigma->engine->get_key($params['keyid']); | |
166 if ($key && $key->name) { | |
167 $data['user'] = $key->name; | |
168 } | |
169 } | |
170 | |
171 if (!empty($params)) { | |
172 $data = array_merge($params, $data); | |
173 } | |
174 | |
175 if (preg_match('/^(send|plugin.enigmaimport|plugin.enigmakeys)$/', $this->rc->action)) { | |
176 $this->rc->output->command('enigma_password_request', $data); | |
177 } | |
178 else { | |
179 $this->rc->output->set_env('enigma_password_request', $data); | |
180 } | |
181 | |
182 // add some labels to client | |
183 $this->rc->output->add_label('enigma.enterkeypasstitle', 'enigma.enterkeypass', | |
184 'save', 'cancel'); | |
185 | |
186 $this->add_css(); | |
187 $this->add_js(); | |
188 } | |
189 | |
190 /** | |
191 * Template object for key info/edit frame. | |
192 * | |
193 * @param array Object attributes | |
194 * | |
195 * @return string HTML output | |
196 */ | |
197 function tpl_key_frame($attrib) | |
198 { | |
199 return $this->rc->output->frame($attrib, true); | |
200 } | |
201 | |
202 /** | |
203 * Template object for list of keys. | |
204 * | |
205 * @param array Object attributes | |
206 * | |
207 * @return string HTML content | |
208 */ | |
209 function tpl_keys_list($attrib) | |
210 { | |
211 // add id to message list table if not specified | |
212 if (!strlen($attrib['id'])) { | |
213 $attrib['id'] = 'rcmenigmakeyslist'; | |
214 } | |
215 | |
216 // define list of cols to be displayed | |
217 $a_show_cols = array('name'); | |
218 | |
219 // create XHTML table | |
220 $out = $this->rc->table_output($attrib, array(), $a_show_cols, 'id'); | |
221 | |
222 // set client env | |
223 $this->rc->output->add_gui_object('keyslist', $attrib['id']); | |
224 $this->rc->output->include_script('list.js'); | |
225 | |
226 // add some labels to client | |
227 $this->rc->output->add_label('enigma.keyremoveconfirm', 'enigma.keyremoving', | |
228 'enigma.keyexportprompt', 'enigma.withprivkeys', 'enigma.onlypubkeys', 'enigma.exportkeys' | |
229 ); | |
230 | |
231 return $out; | |
232 } | |
233 | |
234 /** | |
235 * Key listing (and searching) request handler | |
236 */ | |
237 private function key_list() | |
238 { | |
239 $this->enigma->load_engine(); | |
240 | |
241 $pagesize = $this->rc->config->get('pagesize', 100); | |
242 $page = max(intval(rcube_utils::get_input_value('_p', rcube_utils::INPUT_GPC)), 1); | |
243 $search = rcube_utils::get_input_value('_q', rcube_utils::INPUT_GPC); | |
244 | |
245 // Get the list | |
246 $list = $this->enigma->engine->list_keys($search); | |
247 | |
248 if ($list && ($list instanceof enigma_error)) | |
249 $this->rc->output->show_message('enigma.keylisterror', 'error'); | |
250 else if (empty($list)) | |
251 $this->rc->output->show_message('enigma.nokeysfound', 'notice'); | |
252 else if (is_array($list)) { | |
253 // Save the size | |
254 $listsize = count($list); | |
255 | |
256 // Sort the list by key (user) name | |
257 usort($list, array('enigma_key', 'cmp')); | |
258 | |
259 // Slice current page | |
260 $list = array_slice($list, ($page - 1) * $pagesize, $pagesize); | |
261 $size = count($list); | |
262 | |
263 // Add rows | |
264 foreach ($list as $key) { | |
265 $this->rc->output->command('enigma_add_list_row', array( | |
266 'name' => rcube::Q($key->name), | |
267 'id' => $key->id, | |
268 'flags' => $key->is_private() ? 'p' : '' | |
269 )); | |
270 } | |
271 } | |
272 | |
273 $this->rc->output->set_env('rowcount', $size); | |
274 $this->rc->output->set_env('search_request', $search); | |
275 $this->rc->output->set_env('pagecount', ceil($listsize/$pagesize)); | |
276 $this->rc->output->set_env('current_page', $page); | |
277 $this->rc->output->command('set_rowcount', | |
278 $this->get_rowcount_text($listsize, $size, $page)); | |
279 | |
280 $this->rc->output->send(); | |
281 } | |
282 | |
283 /** | |
284 * Template object for list records counter. | |
285 * | |
286 * @param array Object attributes | |
287 * | |
288 * @return string HTML output | |
289 */ | |
290 function tpl_keys_rowcount($attrib) | |
291 { | |
292 if (!$attrib['id']) | |
293 $attrib['id'] = 'rcmcountdisplay'; | |
294 | |
295 $this->rc->output->add_gui_object('countdisplay', $attrib['id']); | |
296 | |
297 return html::span($attrib, $this->get_rowcount_text()); | |
298 } | |
299 | |
300 /** | |
301 * Returns text representation of list records counter | |
302 */ | |
303 private function get_rowcount_text($all=0, $curr_count=0, $page=1) | |
304 { | |
305 if (!$curr_count) { | |
306 $out = $this->enigma->gettext('nokeysfound'); | |
307 } | |
308 else { | |
309 $pagesize = $this->rc->config->get('pagesize', 100); | |
310 $first = ($page - 1) * $pagesize; | |
311 | |
312 $out = $this->enigma->gettext(array( | |
313 'name' => 'keysfromto', | |
314 'vars' => array( | |
315 'from' => $first + 1, | |
316 'to' => $first + $curr_count, | |
317 'count' => $all) | |
318 )); | |
319 } | |
320 | |
321 return $out; | |
322 } | |
323 | |
324 /** | |
325 * Key information page handler | |
326 */ | |
327 private function key_info() | |
328 { | |
329 $this->enigma->load_engine(); | |
330 | |
331 $id = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GET); | |
332 $res = $this->enigma->engine->get_key($id); | |
333 | |
334 if ($res instanceof enigma_key) { | |
335 $this->data = $res; | |
336 } | |
337 else { // error | |
338 $this->rc->output->show_message('enigma.keyopenerror', 'error'); | |
339 $this->rc->output->command('parent.enigma_loadframe'); | |
340 $this->rc->output->send('iframe'); | |
341 } | |
342 | |
343 $this->rc->output->add_handlers(array( | |
344 'keyname' => array($this, 'tpl_key_name'), | |
345 'keydata' => array($this, 'tpl_key_data'), | |
346 )); | |
347 | |
348 $this->rc->output->set_pagetitle($this->enigma->gettext('keyinfo')); | |
349 $this->rc->output->send('enigma.keyinfo'); | |
350 } | |
351 | |
352 /** | |
353 * Template object for key name | |
354 */ | |
355 function tpl_key_name($attrib) | |
356 { | |
357 return rcube::Q($this->data->name); | |
358 } | |
359 | |
360 /** | |
361 * Template object for key information page content | |
362 */ | |
363 function tpl_key_data($attrib) | |
364 { | |
365 $out = ''; | |
366 $table = new html_table(array('cols' => 2)); | |
367 | |
368 // Key user ID | |
369 $table->add('title', $this->enigma->gettext('keyuserid')); | |
370 $table->add(null, rcube::Q($this->data->name)); | |
371 | |
372 // Key ID | |
373 $table->add('title', $this->enigma->gettext('keyid')); | |
374 $table->add(null, $this->data->subkeys[0]->get_short_id()); | |
375 | |
376 // Key type | |
377 $keytype = $this->data->get_type(); | |
378 if ($keytype == enigma_key::TYPE_KEYPAIR) { | |
379 $type = $this->enigma->gettext('typekeypair'); | |
380 } | |
381 else if ($keytype == enigma_key::TYPE_PUBLIC) { | |
382 $type = $this->enigma->gettext('typepublickey'); | |
383 } | |
384 $table->add('title', $this->enigma->gettext('keytype')); | |
385 $table->add(null, $type); | |
386 | |
387 // Key fingerprint | |
388 $table->add('title', $this->enigma->gettext('fingerprint')); | |
389 $table->add(null, $this->data->subkeys[0]->get_fingerprint()); | |
390 | |
391 $out .= html::tag('fieldset', null, | |
392 html::tag('legend', null, | |
393 $this->enigma->gettext('basicinfo')) . $table->show($attrib)); | |
394 | |
395 // Subkeys | |
396 $table = new html_table(array('cols' => 5, 'id' => 'enigmasubkeytable', 'class' => 'records-table')); | |
397 | |
398 $table->add_header('id', $this->enigma->gettext('subkeyid')); | |
399 $table->add_header('algo', $this->enigma->gettext('subkeyalgo')); | |
400 $table->add_header('created', $this->enigma->gettext('subkeycreated')); | |
401 $table->add_header('expires', $this->enigma->gettext('subkeyexpires')); | |
402 $table->add_header('usage', $this->enigma->gettext('subkeyusage')); | |
403 | |
404 $now = time(); | |
405 $date_format = $this->rc->config->get('date_format', 'Y-m-d'); | |
406 $usage_map = array( | |
407 enigma_key::CAN_ENCRYPT => $this->enigma->gettext('typeencrypt'), | |
408 enigma_key::CAN_SIGN => $this->enigma->gettext('typesign'), | |
409 enigma_key::CAN_CERTIFY => $this->enigma->gettext('typecert'), | |
410 enigma_key::CAN_AUTHENTICATE => $this->enigma->gettext('typeauth'), | |
411 ); | |
412 | |
413 foreach ($this->data->subkeys as $subkey) { | |
414 $algo = $subkey->get_algorithm(); | |
415 if ($algo && $subkey->length) { | |
416 $algo .= ' (' . $subkey->length . ')'; | |
417 } | |
418 | |
419 $usage = array(); | |
420 foreach ($usage_map as $key => $text) { | |
421 if ($subkey->usage & $key) { | |
422 $usage[] = $text; | |
423 } | |
424 } | |
425 | |
426 $table->add('id', $subkey->get_short_id()); | |
427 $table->add('algo', $algo); | |
428 $table->add('created', $subkey->created ? $this->rc->format_date($subkey->created, $date_format, false) : ''); | |
429 $table->add('expires', $subkey->expires ? $this->rc->format_date($subkey->expires, $date_format, false) : $this->enigma->gettext('expiresnever')); | |
430 $table->add('usage', implode(',', $usage)); | |
431 $table->set_row_attribs($subkey->revoked || ($subkey->expires && $subkey->expires < $now) ? 'deleted' : ''); | |
432 } | |
433 | |
434 $out .= html::tag('fieldset', null, | |
435 html::tag('legend', null, | |
436 $this->enigma->gettext('subkeys')) . $table->show()); | |
437 | |
438 // Additional user IDs | |
439 $table = new html_table(array('cols' => 2, 'id' => 'enigmausertable', 'class' => 'records-table')); | |
440 | |
441 $table->add_header('id', $this->enigma->gettext('userid')); | |
442 $table->add_header('valid', $this->enigma->gettext('uservalid')); | |
443 | |
444 foreach ($this->data->users as $user) { | |
445 $username = $user->name; | |
446 if ($user->comment) { | |
447 $username .= ' (' . $user->comment . ')'; | |
448 } | |
449 $username .= ' <' . $user->email . '>'; | |
450 | |
451 $table->add('id', rcube::Q(trim($username))); | |
452 $table->add('valid', $this->enigma->gettext($user->valid ? 'valid' : 'unknown')); | |
453 $table->set_row_attribs($user->revoked || !$user->valid ? 'deleted' : ''); | |
454 } | |
455 | |
456 $out .= html::tag('fieldset', null, | |
457 html::tag('legend', null, | |
458 $this->enigma->gettext('userids')) . $table->show()); | |
459 | |
460 return $out; | |
461 } | |
462 | |
463 /** | |
464 * Key(s) export handler | |
465 */ | |
466 private function key_export() | |
467 { | |
468 $keys = rcube_utils::get_input_value('_keys', rcube_utils::INPUT_POST); | |
469 $priv = rcube_utils::get_input_value('_priv', rcube_utils::INPUT_POST); | |
470 $engine = $this->enigma->load_engine(); | |
471 $list = $keys == '*' ? $engine->list_keys() : explode(',', $keys); | |
472 | |
473 if (is_array($list) && ($fp = fopen('php://memory', 'rw'))) { | |
474 $filename = 'export.pgp'; | |
475 if (count($list) == 1) { | |
476 $filename = (is_object($list[0]) ? $list[0]->id : $list[0]) . '.pgp'; | |
477 } | |
478 | |
479 $status = null; | |
480 foreach ($list as $key) { | |
481 $keyid = is_object($key) ? $key->id : $key; | |
482 $status = $engine->export_key($keyid, $fp, (bool) $priv); | |
483 | |
484 if ($status instanceof enigma_error) { | |
485 $code = $status->getCode(); | |
486 | |
487 if ($code == enigma_error::BADPASS) { | |
488 $this->password_prompt($status, array( | |
489 'input_keys' => $keys, | |
490 'input_priv' => 1, | |
491 'input_task' => 'settings', | |
492 'input_action' => 'plugin.enigmakeys', | |
493 'input_a' => 'export', | |
494 'action' => '?', | |
495 'iframe' => true, | |
496 'nolock' => true, | |
497 'keyid' => $keyid, | |
498 )); | |
499 fclose($fp); | |
500 $this->rc->output->send('iframe'); | |
501 } | |
502 } | |
503 } | |
504 | |
505 // send downlaod headers | |
506 header('Content-Type: application/pgp-keys'); | |
507 header('Content-Disposition: attachment; filename="' . $filename . '"'); | |
508 | |
509 rewind($fp); | |
510 while (!feof($fp)) { | |
511 echo fread($fp, 1024 * 1024); | |
512 } | |
513 fclose($fp); | |
514 } | |
515 | |
516 exit; | |
517 } | |
518 | |
519 /** | |
520 * Key import (page) handler | |
521 */ | |
522 private function key_import() | |
523 { | |
524 // Import process | |
525 if ($data = rcube_utils::get_input_value('_keys', rcube_utils::INPUT_POST)) { | |
526 $this->enigma->load_engine(); | |
527 $this->enigma->engine->password_handler(); | |
528 | |
529 $result = $this->enigma->engine->import_key($data); | |
530 | |
531 if (is_array($result)) { | |
532 if (rcube_utils::get_input_value('_generated', rcube_utils::INPUT_POST)) { | |
533 $this->rc->output->command('enigma_key_create_success'); | |
534 $this->rc->output->show_message('enigma.keygeneratesuccess', 'confirmation'); | |
535 } | |
536 else { | |
537 $this->rc->output->show_message('enigma.keysimportsuccess', 'confirmation', | |
538 array('new' => $result['imported'], 'old' => $result['unchanged'])); | |
539 | |
540 if ($result['imported'] && !empty($_POST['_refresh'])) { | |
541 $this->rc->output->command('enigma_list', 1, false); | |
542 } | |
543 } | |
544 } | |
545 else { | |
546 $this->rc->output->show_message('enigma.keysimportfailed', 'error'); | |
547 } | |
548 | |
549 $this->rc->output->send(); | |
550 } | |
551 else if ($_FILES['_file']['tmp_name'] && is_uploaded_file($_FILES['_file']['tmp_name'])) { | |
552 $this->enigma->load_engine(); | |
553 $result = $this->enigma->engine->import_key($_FILES['_file']['tmp_name'], true); | |
554 | |
555 if (is_array($result)) { | |
556 // reload list if any keys has been added | |
557 if ($result['imported']) { | |
558 $this->rc->output->command('parent.enigma_list', 1); | |
559 } | |
560 else { | |
561 $this->rc->output->command('parent.enigma_loadframe'); | |
562 } | |
563 | |
564 $this->rc->output->show_message('enigma.keysimportsuccess', 'confirmation', | |
565 array('new' => $result['imported'], 'old' => $result['unchanged'])); | |
566 } | |
567 else if ($result instanceof enigma_error && $result->getCode() == enigma_error::BADPASS) { | |
568 $this->password_prompt($result); | |
569 } | |
570 else { | |
571 $this->rc->output->show_message('enigma.keysimportfailed', 'error'); | |
572 } | |
573 | |
574 $this->rc->output->send('iframe'); | |
575 } | |
576 else if ($err = $_FILES['_file']['error']) { | |
577 if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) { | |
578 $this->rc->output->show_message('filesizeerror', 'error', | |
579 array('size' => $this->rc->show_bytes(rcube_utils::max_upload_size()))); | |
580 } else { | |
581 $this->rc->output->show_message('fileuploaderror', 'error'); | |
582 } | |
583 | |
584 $this->rc->output->send('iframe'); | |
585 } | |
586 | |
587 $this->rc->output->add_handlers(array( | |
588 'importform' => array($this, 'tpl_key_import_form'), | |
589 )); | |
590 | |
591 $this->rc->output->set_pagetitle($this->enigma->gettext('keyimport')); | |
592 $this->rc->output->send('enigma.keyimport'); | |
593 } | |
594 | |
595 /** | |
596 * Template object for key import (upload) form | |
597 */ | |
598 function tpl_key_import_form($attrib) | |
599 { | |
600 $attrib += array('id' => 'rcmKeyImportForm'); | |
601 | |
602 $upload = new html_inputfield(array('type' => 'file', 'name' => '_file', | |
603 'id' => 'rcmimportfile', 'size' => 30)); | |
604 $search = new html_inputfield(array('type' => 'text', 'name' => '_search', | |
605 'id' => 'rcmimportsearch', 'size' => 30)); | |
606 | |
607 $upload_button = new html_inputfield(array( | |
608 'type' => 'button', | |
609 'value' => $this->rc->gettext('import'), | |
610 'class' => 'button', | |
611 'onclick' => "return rcmail.command('plugin.enigma-import','',this,event)", | |
612 )); | |
613 | |
614 $search_button = new html_inputfield(array( | |
615 'type' => 'button', | |
616 'value' => $this->rc->gettext('search'), | |
617 'class' => 'button', | |
618 'onclick' => "return rcmail.command('plugin.enigma-import-search','',this,event)", | |
619 )); | |
620 | |
621 $upload_form = html::div(null, | |
622 rcube::Q($this->enigma->gettext('keyimporttext'), 'show') | |
623 . html::br() . html::br() . $upload->show() | |
624 . html::br() . html::br() . $upload_button->show() | |
625 ); | |
626 | |
627 $search_form = html::div(null, | |
628 rcube::Q($this->enigma->gettext('keyimportsearchtext'), 'show') | |
629 . html::br() . html::br() . $search->show() | |
630 . html::br() . html::br() . $search_button->show() | |
631 ); | |
632 | |
633 $form = html::tag('fieldset', '', html::tag('legend', null, $this->enigma->gettext('keyimportlabel')) . $upload_form) | |
634 . html::tag('fieldset', '', html::tag('legend', null, $this->enigma->gettext('keyimportsearchlabel')) . $search_form); | |
635 | |
636 $this->rc->output->add_label('selectimportfile', 'importwait', 'nopubkeyfor', 'nopubkeyforsender', | |
637 'encryptnoattachments','encryptedsendialog','searchpubkeyservers', 'importpubkeys', | |
638 'encryptpubkeysfound', 'search', 'close', 'import', 'keyid', 'keylength', 'keyexpired', | |
639 'keyrevoked', 'keyimportsuccess', 'keyservererror'); | |
640 $this->rc->output->add_gui_object('importform', $attrib['id']); | |
641 $this->rc->output->include_script('publickey.js'); | |
642 | |
643 $out = $this->rc->output->form_tag(array( | |
644 'action' => $this->rc->url(array('action' => $this->rc->action, 'a' => 'import')), | |
645 'method' => 'post', | |
646 'enctype' => 'multipart/form-data') + $attrib, | |
647 $form | |
648 ); | |
649 | |
650 return $out; | |
651 } | |
652 | |
653 /** | |
654 * Server-side key pair generation handler | |
655 */ | |
656 private function key_generate() | |
657 { | |
658 // Crypt_GPG does not support key generation for multiple identities | |
659 // It is also very slow (which is problematic because it may exceed | |
660 // request time limit) and requires entropy generator | |
661 // That's why we use only OpenPGP.js method of key generation | |
662 return; | |
663 | |
664 $user = rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST, true); | |
665 $pass = rcube_utils::get_input_value('_password', rcube_utils::INPUT_POST, true); | |
666 $size = (int) rcube_utils::get_input_value('_size', rcube_utils::INPUT_POST); | |
667 | |
668 if ($size > 4096) { | |
669 $size = 4096; | |
670 } | |
671 | |
672 $ident = rcube_mime::decode_address_list($user, 1, false); | |
673 | |
674 if (empty($ident)) { | |
675 $this->rc->output->show_message('enigma.keygenerateerror', 'error'); | |
676 $this->rc->output->send(); | |
677 } | |
678 | |
679 $this->enigma->load_engine(); | |
680 $result = $this->enigma->engine->generate_key(array( | |
681 'user' => $ident[1]['name'], | |
682 'email' => $ident[1]['mailto'], | |
683 'password' => $pass, | |
684 'size' => $size, | |
685 )); | |
686 | |
687 if ($result instanceof enigma_key) { | |
688 $this->rc->output->command('enigma_key_create_success'); | |
689 $this->rc->output->show_message('enigma.keygeneratesuccess', 'confirmation'); | |
690 } | |
691 else { | |
692 $this->rc->output->show_message('enigma.keygenerateerror', 'error'); | |
693 } | |
694 | |
695 $this->rc->output->send(); | |
696 } | |
697 | |
698 /** | |
699 * Key generation page handler | |
700 */ | |
701 private function key_create() | |
702 { | |
703 $this->enigma->include_script('openpgp.min.js'); | |
704 | |
705 $this->rc->output->add_handlers(array( | |
706 'keyform' => array($this, 'tpl_key_create_form'), | |
707 )); | |
708 | |
709 $this->rc->output->set_pagetitle($this->enigma->gettext('keygenerate')); | |
710 $this->rc->output->send('enigma.keycreate'); | |
711 } | |
712 | |
713 /** | |
714 * Template object for key generation form | |
715 */ | |
716 function tpl_key_create_form($attrib) | |
717 { | |
718 $attrib += array('id' => 'rcmKeyCreateForm'); | |
719 $table = new html_table(array('cols' => 2)); | |
720 | |
721 // get user's identities | |
722 $identities = $this->rc->user->list_identities(null, true); | |
723 $checkbox = new html_checkbox(array('name' => 'identity[]')); | |
724 foreach ((array) $identities as $idx => $ident) { | |
725 $name = empty($ident['name']) ? ($ident['email']) : $ident['ident']; | |
726 $identities[$idx] = html::label(null, $checkbox->show($name, array('value' => $name)) . rcube::Q($name)); | |
727 } | |
728 | |
729 $table->add('title', html::label('key-name', rcube::Q($this->enigma->gettext('newkeyident')))); | |
730 $table->add(null, implode($identities, "\n")); | |
731 | |
732 // Key size | |
733 $select = new html_select(array('name' => 'size', 'id' => 'key-size')); | |
734 $select->add($this->enigma->gettext('key2048'), '2048'); | |
735 $select->add($this->enigma->gettext('key4096'), '4096'); | |
736 | |
737 $table->add('title', html::label('key-size', rcube::Q($this->enigma->gettext('newkeysize')))); | |
738 $table->add(null, $select->show()); | |
739 | |
740 // Password and confirm password | |
741 $table->add('title', html::label('key-pass', rcube::Q($this->enigma->gettext('newkeypass')))); | |
742 $table->add(null, rcube_output::get_edit_field('password', '', | |
743 array('id' => 'key-pass', 'size' => $attrib['size'], 'required' => true), 'password')); | |
744 | |
745 $table->add('title', html::label('key-pass-confirm', rcube::Q($this->enigma->gettext('newkeypassconfirm')))); | |
746 $table->add(null, rcube_output::get_edit_field('password-confirm', '', | |
747 array('id' => 'key-pass-confirm', 'size' => $attrib['size'], 'required' => true), 'password')); | |
748 | |
749 $this->rc->output->add_gui_object('keyform', $attrib['id']); | |
750 $this->rc->output->add_label('enigma.keygenerating', 'enigma.formerror', | |
751 'enigma.passwordsdiffer', 'enigma.keygenerateerror', 'enigma.noidentselected', | |
752 'enigma.keygennosupport'); | |
753 | |
754 return $this->rc->output->form_tag(array(), $table->show($attrib)); | |
755 } | |
756 | |
757 /** | |
758 * Key deleting | |
759 */ | |
760 private function key_delete() | |
761 { | |
762 $keys = rcube_utils::get_input_value('_keys', rcube_utils::INPUT_POST); | |
763 $engine = $this->enigma->load_engine(); | |
764 | |
765 foreach ((array)$keys as $key) { | |
766 $res = $engine->delete_key($key); | |
767 | |
768 if ($res !== true) { | |
769 $this->rc->output->show_message('enigma.keyremoveerror', 'error'); | |
770 $this->rc->output->command('enigma_list'); | |
771 $this->rc->output->send(); | |
772 } | |
773 } | |
774 | |
775 $this->rc->output->command('enigma_list'); | |
776 $this->rc->output->show_message('enigma.keyremovesuccess', 'confirmation'); | |
777 $this->rc->output->send(); | |
778 } | |
779 | |
780 /** | |
781 * Init compose UI (add task button and the menu) | |
782 */ | |
783 private function compose_ui() | |
784 { | |
785 $this->add_css(); | |
786 | |
787 // Options menu button | |
788 $this->enigma->add_button(array( | |
789 'type' => 'link', | |
790 'command' => 'plugin.enigma', | |
791 'onclick' => "rcmail.command('menu-open', 'enigmamenu', event.target, event)", | |
792 'class' => 'button enigma', | |
793 'title' => 'encryptionoptions', | |
794 'label' => 'encryption', | |
795 'domain' => $this->enigma->ID, | |
796 'width' => 32, | |
797 'height' => 32, | |
798 'aria-owns' => 'enigmamenu', | |
799 'aria-haspopup' => 'true', | |
800 'aria-expanded' => 'false', | |
801 ), 'toolbar'); | |
802 | |
803 $locks = (array) $this->rc->config->get('enigma_options_lock'); | |
804 $menu = new html_table(array('cols' => 2)); | |
805 $chbox = new html_checkbox(array('value' => 1)); | |
806 | |
807 $menu->add(null, html::label(array('for' => 'enigmasignopt'), | |
808 rcube::Q($this->enigma->gettext('signmsg')))); | |
809 $menu->add(null, $chbox->show($this->rc->config->get('enigma_sign_all') ? 1 : 0, | |
810 array( | |
811 'name' => '_enigma_sign', | |
812 'id' => 'enigmasignopt', | |
813 'disabled' => in_array('sign', $locks), | |
814 ))); | |
815 | |
816 $menu->add(null, html::label(array('for' => 'enigmaencryptopt'), | |
817 rcube::Q($this->enigma->gettext('encryptmsg')))); | |
818 $menu->add(null, $chbox->show($this->rc->config->get('enigma_encrypt_all') ? 1 : 0, | |
819 array( | |
820 'name' => '_enigma_encrypt', | |
821 'id' => 'enigmaencryptopt', | |
822 'disabled' => in_array('encrypt', $locks), | |
823 ))); | |
824 | |
825 $menu->add(null, html::label(array('for' => 'enigmaattachpubkeyopt'), | |
826 rcube::Q($this->enigma->gettext('attachpubkeymsg')))); | |
827 $menu->add(null, $chbox->show($this->rc->config->get('enigma_attach_pubkey') ? 1 : 0, | |
828 array( | |
829 'name' => '_enigma_attachpubkey', | |
830 'id' => 'enigmaattachpubkeyopt', | |
831 'disabled' => in_array('pubkey', $locks), | |
832 ))); | |
833 | |
834 $menu = html::div(array('id' => 'enigmamenu', 'class' => 'popupmenu'), $menu->show()); | |
835 | |
836 // Options menu contents | |
837 $this->rc->output->add_footer($menu); | |
838 } | |
839 | |
840 /** | |
841 * Handler for message_body_prefix hook. | |
842 * Called for every displayed (content) part of the message. | |
843 * Adds infobox about signature verification and/or decryption | |
844 * status above the body. | |
845 * | |
846 * @param array Original parameters | |
847 * | |
848 * @return array Modified parameters | |
849 */ | |
850 function status_message($p) | |
851 { | |
852 // skip: not a message part | |
853 if ($p['part'] instanceof rcube_message) { | |
854 return $p; | |
855 } | |
856 | |
857 // skip: message has no signed/encoded content | |
858 if (!$this->enigma->engine) { | |
859 return $p; | |
860 } | |
861 | |
862 $engine = $this->enigma->engine; | |
863 $part_id = $p['part']->mime_id; | |
864 $messages = array(); | |
865 | |
866 // Decryption status | |
867 if (($found = $this->find_part_id($part_id, $engine->decryptions)) !== null | |
868 && ($status = $engine->decryptions[$found]) | |
869 ) { | |
870 $attach_scripts = true; | |
871 | |
872 // show the message only once | |
873 unset($engine->decryptions[$found]); | |
874 | |
875 // display status info | |
876 $attrib['id'] = 'enigma-message'; | |
877 | |
878 if ($status instanceof enigma_error) { | |
879 $attrib['class'] = 'enigmaerror'; | |
880 $code = $status->getCode(); | |
881 | |
882 if ($code == enigma_error::KEYNOTFOUND) { | |
883 $msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($status->getData('id')), | |
884 $this->enigma->gettext('decryptnokey'))); | |
885 } | |
886 else if ($code == enigma_error::BADPASS) { | |
887 $missing = $status->getData('missing'); | |
888 $label = 'decrypt' . (!empty($missing) ? 'no' : 'bad') . 'pass'; | |
889 $msg = rcube::Q($this->enigma->gettext($label)); | |
890 $this->password_prompt($status); | |
891 } | |
892 else { | |
893 $msg = rcube::Q($this->enigma->gettext('decrypterror')); | |
894 } | |
895 } | |
896 else if ($status === enigma_engine::ENCRYPTED_PARTIALLY) { | |
897 $attrib['class'] = 'enigmawarning'; | |
898 $msg = rcube::Q($this->enigma->gettext('decryptpartial')); | |
899 } | |
900 else { | |
901 $attrib['class'] = 'enigmanotice'; | |
902 $msg = rcube::Q($this->enigma->gettext('decryptok')); | |
903 } | |
904 | |
905 $attrib['msg'] = $msg; | |
906 $messages[] = $attrib; | |
907 } | |
908 | |
909 // Signature verification status | |
910 if (($found = $this->find_part_id($part_id, $engine->signatures)) !== null | |
911 && ($sig = $engine->signatures[$found]) | |
912 ) { | |
913 $attach_scripts = true; | |
914 | |
915 // show the message only once | |
916 unset($engine->signatures[$found]); | |
917 | |
918 // display status info | |
919 $attrib['id'] = 'enigma-message'; | |
920 | |
921 if ($sig instanceof enigma_signature) { | |
922 $sender = $sig->name ?: ''; | |
923 if ($sig->email) { | |
924 $sender .= ' <' . $sig->email . '>'; | |
925 } | |
926 | |
927 if ($sig->valid === enigma_error::UNVERIFIED) { | |
928 $attrib['class'] = 'enigmawarning'; | |
929 $msg = str_replace('$sender', $sender, $this->enigma->gettext('sigunverified')); | |
930 $msg = str_replace('$keyid', $sig->id, $msg); | |
931 $msg = rcube::Q($msg); | |
932 } | |
933 else if ($sig->valid) { | |
934 $attrib['class'] = $sig->partial ? 'enigmawarning' : 'enigmanotice'; | |
935 $label = 'sigvalid' . ($sig->partial ? 'partial' : ''); | |
936 $msg = rcube::Q(str_replace('$sender', $sender, $this->enigma->gettext($label))); | |
937 } | |
938 else { | |
939 $attrib['class'] = 'enigmawarning'; | |
940 if ($sender) { | |
941 $msg = rcube::Q(str_replace('$sender', $sender, $this->enigma->gettext('siginvalid'))); | |
942 } | |
943 else { | |
944 $msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($sig->id), | |
945 $this->enigma->gettext('signokey'))); | |
946 } | |
947 } | |
948 } | |
949 else if ($sig && $sig->getCode() == enigma_error::KEYNOTFOUND) { | |
950 $attrib['class'] = 'enigmawarning'; | |
951 $msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($sig->getData('id')), | |
952 $this->enigma->gettext('signokey'))); | |
953 } | |
954 else { | |
955 $attrib['class'] = 'enigmaerror'; | |
956 $msg = rcube::Q($this->enigma->gettext('sigerror')); | |
957 } | |
958 /* | |
959 $msg .= ' ' . html::a(array('href' => "#sigdetails", | |
960 'onclick' => rcmail_output::JS_OBJECT_NAME.".command('enigma-sig-details')"), | |
961 rcube::Q($this->enigma->gettext('showdetails'))); | |
962 */ | |
963 // test | |
964 // $msg .= '<br /><pre>'.$sig->body.'</pre>'; | |
965 | |
966 $attrib['msg'] = $msg; | |
967 $messages[] = $attrib; | |
968 } | |
969 | |
970 if ($count = count($messages)) { | |
971 if ($count == 2 && $messages[0]['class'] == $messages[1]['class']) { | |
972 $p['prefix'] .= html::div($messages[0], $messages[0]['msg'] . ' ' . $messages[1]['msg']); | |
973 } | |
974 else { | |
975 foreach ($messages as $msg) { | |
976 $p['prefix'] .= html::div($msg, $msg['msg']); | |
977 } | |
978 } | |
979 } | |
980 | |
981 if ($attach_scripts) { | |
982 // add css and js script | |
983 $this->add_css(); | |
984 $this->add_js(); | |
985 } | |
986 | |
987 return $p; | |
988 } | |
989 | |
990 /** | |
991 * Handler for message_load hook. | |
992 * Check message bodies and attachments for keys/certs. | |
993 */ | |
994 function message_load($p) | |
995 { | |
996 $engine = $this->enigma->load_engine(); | |
997 | |
998 // handle keys/certs in attachments | |
999 foreach ((array) $p['object']->attachments as $attachment) { | |
1000 if ($engine->is_keys_part($attachment)) { | |
1001 $this->keys_parts[] = $attachment->mime_id; | |
1002 } | |
1003 } | |
1004 | |
1005 // the same with message bodies | |
1006 foreach ((array) $p['object']->parts as $part) { | |
1007 if ($engine->is_keys_part($part)) { | |
1008 $this->keys_parts[] = $part->mime_id; | |
1009 $this->keys_bodies[] = $part->mime_id; | |
1010 } | |
1011 } | |
1012 | |
1013 // @TODO: inline PGP keys | |
1014 | |
1015 if ($this->keys_parts) { | |
1016 $this->enigma->add_texts('localization'); | |
1017 } | |
1018 | |
1019 return $p; | |
1020 } | |
1021 | |
1022 /** | |
1023 * Handler for template_object_messagebody hook. | |
1024 * This callback function adds a box below the message content | |
1025 * if there is a key/cert attachment available | |
1026 */ | |
1027 function message_output($p) | |
1028 { | |
1029 foreach ($this->keys_parts as $part) { | |
1030 // remove part's body | |
1031 if (in_array($part, $this->keys_bodies)) { | |
1032 $p['content'] = ''; | |
1033 } | |
1034 | |
1035 // add box below message body | |
1036 $p['content'] .= html::p(array('class' => 'enigmaattachment'), | |
1037 html::a(array( | |
1038 'href' => "#", | |
1039 'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".enigma_import_attachment('".rcube::JQ($part)."')", | |
1040 'title' => $this->enigma->gettext('keyattimport')), | |
1041 html::span(null, $this->enigma->gettext('keyattfound')))); | |
1042 | |
1043 $attach_scripts = true; | |
1044 } | |
1045 | |
1046 if ($attach_scripts) { | |
1047 // add css and js script | |
1048 $this->add_css(); | |
1049 $this->add_js(); | |
1050 } | |
1051 | |
1052 return $p; | |
1053 } | |
1054 | |
1055 /** | |
1056 * Handle message_ready hook (encryption/signing/attach public key) | |
1057 */ | |
1058 function message_ready($p) | |
1059 { | |
1060 $savedraft = !empty($_POST['_draft']) && empty($_GET['_saveonly']); | |
1061 $sign_enable = (bool) rcube_utils::get_input_value('_enigma_sign', rcube_utils::INPUT_POST); | |
1062 $encrypt_enable = (bool) rcube_utils::get_input_value('_enigma_encrypt', rcube_utils::INPUT_POST); | |
1063 $pubkey_enable = (bool) rcube_utils::get_input_value('_enigma_attachpubkey', rcube_utils::INPUT_POST); | |
1064 $locks = (array) $this->rc->config->get('enigma_options_lock'); | |
1065 | |
1066 if (in_array('sign', $locks)) { | |
1067 $sign_enable = (bool) $this->rc->config->get('enigma_sign_all'); | |
1068 } | |
1069 if (in_array('encrypt', $locks)) { | |
1070 $encrypt_enable = (bool) $this->rc->config->get('enigma_encrypt_all'); | |
1071 } | |
1072 if (in_array('pubkey', $locks)) { | |
1073 $pubkey_enable = (bool) $this->rc->config->get('enigma_attach_pubkey'); | |
1074 } | |
1075 | |
1076 if (!$savedraft && $pubkey_enable) { | |
1077 $engine = $this->enigma->load_engine(); | |
1078 $engine->attach_public_key($p['message']); | |
1079 } | |
1080 | |
1081 if ($encrypt_enable) { | |
1082 $engine = $this->enigma->load_engine(); | |
1083 $mode = !$savedraft && $sign_enable ? enigma_engine::ENCRYPT_MODE_SIGN : null; | |
1084 $status = $engine->encrypt_message($p['message'], $mode, $savedraft); | |
1085 $mode = 'encrypt'; | |
1086 } | |
1087 else if (!$savedraft && $sign_enable) { | |
1088 $engine = $this->enigma->load_engine(); | |
1089 $status = $engine->sign_message($p['message'], enigma_engine::SIGN_MODE_MIME); | |
1090 $mode = 'sign'; | |
1091 } | |
1092 | |
1093 if ($mode && ($status instanceof enigma_error)) { | |
1094 $code = $status->getCode(); | |
1095 | |
1096 if ($code == enigma_error::KEYNOTFOUND) { | |
1097 $vars = array('email' => $status->getData('missing')); | |
1098 $msg = 'enigma.' . $mode . 'nokey'; | |
1099 } | |
1100 else if ($code == enigma_error::BADPASS) { | |
1101 $this->password_prompt($status); | |
1102 } | |
1103 else { | |
1104 $msg = 'enigma.' . $mode . 'error'; | |
1105 } | |
1106 | |
1107 if ($msg) { | |
1108 if ($vars && $vars['email']) { | |
1109 $this->rc->output->command('enigma_key_not_found', array( | |
1110 'email' => $vars['email'], | |
1111 'text' => $this->rc->gettext(array('name' => $msg, 'vars' => $vars)), | |
1112 'title' => $this->enigma->gettext('keynotfound'), | |
1113 'button' => $this->enigma->gettext('findkey'), | |
1114 )); | |
1115 } | |
1116 else { | |
1117 $this->rc->output->show_message($msg, 'error', $vars); | |
1118 } | |
1119 } | |
1120 | |
1121 $this->rc->output->send('iframe'); | |
1122 } | |
1123 | |
1124 return $p; | |
1125 } | |
1126 | |
1127 /** | |
1128 * Handler for message_compose_body hook | |
1129 * Display error when the message cannot be encrypted | |
1130 * and provide a way to try again with a password. | |
1131 */ | |
1132 function message_compose($p) | |
1133 { | |
1134 $engine = $this->enigma->load_engine(); | |
1135 | |
1136 // skip: message has no signed/encoded content | |
1137 if (!$this->enigma->engine) { | |
1138 return $p; | |
1139 } | |
1140 | |
1141 $engine = $this->enigma->engine; | |
1142 $locks = (array) $this->rc->config->get('enigma_options_lock'); | |
1143 | |
1144 // Decryption status | |
1145 foreach ($engine->decryptions as $status) { | |
1146 if ($status instanceof enigma_error) { | |
1147 $code = $status->getCode(); | |
1148 | |
1149 if ($code == enigma_error::KEYNOTFOUND) { | |
1150 $msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($status->getData('id')), | |
1151 $this->enigma->gettext('decryptnokey'))); | |
1152 } | |
1153 else if ($code == enigma_error::BADPASS) { | |
1154 $this->password_prompt($status, array('compose-init' => true)); | |
1155 return $p; | |
1156 } | |
1157 else { | |
1158 $msg = rcube::Q($this->enigma->gettext('decrypterror')); | |
1159 } | |
1160 } | |
1161 } | |
1162 | |
1163 if ($msg) { | |
1164 $this->rc->output->show_message($msg, 'error'); | |
1165 } | |
1166 | |
1167 // Check sign/ecrypt options for signed/encrypted drafts | |
1168 if (!in_array('encrypt', $locks)) { | |
1169 $this->rc->output->set_env('enigma_force_encrypt', !empty($engine->decryptions)); | |
1170 } | |
1171 if (!in_array('sign', $locks)) { | |
1172 $this->rc->output->set_env('enigma_force_sign', !empty($engine->signatures)); | |
1173 } | |
1174 | |
1175 return $p; | |
1176 } | |
1177 | |
1178 /** | |
1179 * Handler for keys/certs import request action | |
1180 */ | |
1181 function import_file() | |
1182 { | |
1183 $uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST); | |
1184 $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST); | |
1185 $mime_id = rcube_utils::get_input_value('_part', rcube_utils::INPUT_POST); | |
1186 $storage = $this->rc->get_storage(); | |
1187 $engine = $this->enigma->load_engine(); | |
1188 | |
1189 if ($uid && $mime_id) { | |
1190 // Note: we get the attachment body via rcube_message class | |
1191 // to support keys inside encrypted messages (#5285) | |
1192 $message = new rcube_message($uid, $mbox); | |
1193 | |
1194 // Check if we don't need to ask for password again | |
1195 foreach ($engine->decryptions as $status) { | |
1196 if ($status instanceof enigma_error) { | |
1197 if ($status->getCode() == enigma_error::BADPASS) { | |
1198 $this->password_prompt($status, array( | |
1199 'input_uid' => $uid, | |
1200 'input_mbox' => $mbox, | |
1201 'input_part' => $mime_id, | |
1202 'input_task' => 'mail', | |
1203 'input_action' => 'plugin.enigmaimport', | |
1204 'action' => '?', | |
1205 'iframe' => true, | |
1206 )); | |
1207 $this->rc->output->send($this->rc->output->type == 'html' ? 'iframe' : null); | |
1208 return; | |
1209 } | |
1210 } | |
1211 } | |
1212 | |
1213 if ($engine->is_keys_part($message->mime_parts[$mime_id])) { | |
1214 $part = $message->get_part_body($mime_id); | |
1215 } | |
1216 } | |
1217 | |
1218 if ($part && is_array($result = $engine->import_key($part))) { | |
1219 $this->rc->output->show_message('enigma.keysimportsuccess', 'confirmation', | |
1220 array('new' => $result['imported'], 'old' => $result['unchanged'])); | |
1221 } | |
1222 else { | |
1223 $this->rc->output->show_message('enigma.keysimportfailed', 'error'); | |
1224 } | |
1225 | |
1226 $this->rc->output->send($this->rc->output->type == 'html' ? 'iframe' : null); | |
1227 } | |
1228 | |
1229 /** | |
1230 * Check if the part or its parent exists in the array | |
1231 * of decryptions/signatures. Returns found ID. | |
1232 */ | |
1233 private function find_part_id($part_id, $data) | |
1234 { | |
1235 $ids = explode('.', $part_id); | |
1236 $i = 0; | |
1237 $count = count($ids); | |
1238 | |
1239 while ($i < $count && strlen($part = implode('.', array_slice($ids, 0, ++$i)))) { | |
1240 if (array_key_exists($part, $data)) { | |
1241 return $part; | |
1242 } | |
1243 } | |
1244 } | |
1245 } |