commit | author | age
|
48e9c1
|
1 |
<?php |
58c279
|
2 |
|
AM |
3 |
/** |
48e9c1
|
4 |
+-------------------------------------------------------------------------+ |
T |
5 |
| User Interface for the Enigma Plugin | |
|
6 |
| | |
a99c34
|
7 |
| Copyright (C) 2010-2015 The Roundcube Dev Team | |
48e9c1
|
8 |
| | |
a99c34
|
9 |
| Licensed under the GNU General Public License version 3 or | |
AM |
10 |
| any later version with exceptions for skins & plugins. | |
|
11 |
| See the README file for a full license statement. | |
48e9c1
|
12 |
| | |
T |
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; |
0878c8
|
23 |
private $css_loaded; |
AM |
24 |
private $js_loaded; |
48e9c1
|
25 |
private $data; |
0878c8
|
26 |
private $keys_parts = array(); |
AM |
27 |
private $keys_bodies = array(); |
48e9c1
|
28 |
|
T |
29 |
|
|
30 |
function __construct($enigma_plugin, $home='') |
|
31 |
{ |
|
32 |
$this->enigma = $enigma_plugin; |
0878c8
|
33 |
$this->rc = $enigma_plugin->rc; |
AM |
34 |
$this->home = $home; // we cannot use $enigma_plugin->home here |
48e9c1
|
35 |
} |
T |
36 |
|
|
37 |
/** |
|
38 |
* UI initialization and requests handlers. |
|
39 |
* |
|
40 |
* @param string Preferences section |
|
41 |
*/ |
a99c34
|
42 |
function init() |
48e9c1
|
43 |
{ |
0878c8
|
44 |
$this->add_js(); |
48e9c1
|
45 |
|
0878c8
|
46 |
$action = rcube_utils::get_input_value('_a', rcube_utils::INPUT_GPC); |
48e9c1
|
47 |
|
0878c8
|
48 |
if ($this->rc->action == 'plugin.enigmakeys') { |
48e9c1
|
49 |
switch ($action) { |
0878c8
|
50 |
case 'delete': |
AM |
51 |
$this->key_delete(); |
|
52 |
break; |
|
53 |
/* |
|
54 |
case 'edit': |
48e9c1
|
55 |
$this->key_edit(); |
T |
56 |
break; |
0878c8
|
57 |
*/ |
AM |
58 |
case 'import': |
48e9c1
|
59 |
$this->key_import(); |
T |
60 |
break; |
0878c8
|
61 |
|
211929
|
62 |
case 'export': |
AM |
63 |
$this->key_export(); |
|
64 |
break; |
|
65 |
|
a0dfcb
|
66 |
case 'generate': |
AM |
67 |
$this->key_generate(); |
|
68 |
break; |
|
69 |
|
d5501a
|
70 |
case 'create': |
AM |
71 |
$this->key_create(); |
|
72 |
break; |
|
73 |
|
0878c8
|
74 |
case 'search': |
AM |
75 |
case 'list': |
48e9c1
|
76 |
$this->key_list(); |
T |
77 |
break; |
0878c8
|
78 |
|
AM |
79 |
case 'info': |
48e9c1
|
80 |
$this->key_info(); |
0878c8
|
81 |
break; |
48e9c1
|
82 |
} |
0878c8
|
83 |
|
AM |
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'); |
48e9c1
|
93 |
} |
0878c8
|
94 |
/* |
AM |
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 |
*/ |
48e9c1
|
108 |
// Message composing UI |
T |
109 |
else if ($this->rc->action == 'compose') { |
|
110 |
$this->compose_ui(); |
|
111 |
} |
|
112 |
} |
|
113 |
|
0878c8
|
114 |
/** |
48e9c1
|
115 |
* Adds CSS style file to the page header. |
T |
116 |
*/ |
|
117 |
function add_css() |
|
118 |
{ |
|
119 |
if ($this->css_loaded) |
|
120 |
return; |
|
121 |
|
30ceb6
|
122 |
$skin_path = $this->enigma->local_skin_path(); |
14ace8
|
123 |
if (is_file($this->home . "/$skin_path/enigma.css")) { |
AM |
124 |
$this->enigma->include_stylesheet("$skin_path/enigma.css"); |
|
125 |
} |
48e9c1
|
126 |
|
0878c8
|
127 |
$this->css_loaded = true; |
AM |
128 |
} |
|
129 |
|
|
130 |
/** |
|
131 |
* Adds javascript file to the page header. |
|
132 |
*/ |
|
133 |
function add_js() |
|
134 |
{ |
|
135 |
if ($this->js_loaded) { |
|
136 |
return; |
|
137 |
} |
|
138 |
|
|
139 |
$this->enigma->include_script('enigma.js'); |
|
140 |
|
|
141 |
$this->js_loaded = true; |
|
142 |
} |
|
143 |
|
|
144 |
/** |
|
145 |
* Initializes key password prompt |
|
146 |
* |
58c279
|
147 |
* @param enigma_error $status Error object with key info |
AM |
148 |
* @param array $params Optional prompt parameters |
0878c8
|
149 |
*/ |
58c279
|
150 |
function password_prompt($status, $params = array()) |
0878c8
|
151 |
{ |
AM |
152 |
$data = $status->getData('missing'); |
|
153 |
|
|
154 |
if (empty($data)) { |
|
155 |
$data = $status->getData('bad'); |
|
156 |
} |
|
157 |
|
|
158 |
$data = array('keyid' => key($data), 'user' => $data[key($data)]); |
58c279
|
159 |
|
AM |
160 |
if (!empty($params)) { |
|
161 |
$data = array_merge($params, $data); |
|
162 |
} |
0878c8
|
163 |
|
a99c34
|
164 |
if ($this->rc->action == 'send') { |
AM |
165 |
$this->rc->output->command('enigma_password_request', $data); |
|
166 |
} |
|
167 |
else { |
|
168 |
$this->rc->output->set_env('enigma_password_request', $data); |
|
169 |
} |
0878c8
|
170 |
|
AM |
171 |
// add some labels to client |
|
172 |
$this->rc->output->add_label('enigma.enterkeypasstitle', 'enigma.enterkeypass', |
|
173 |
'save', 'cancel'); |
|
174 |
|
|
175 |
$this->add_css(); |
|
176 |
$this->add_js(); |
48e9c1
|
177 |
} |
T |
178 |
|
|
179 |
/** |
|
180 |
* Template object for key info/edit frame. |
|
181 |
* |
|
182 |
* @param array Object attributes |
|
183 |
* |
|
184 |
* @return string HTML output |
|
185 |
*/ |
|
186 |
function tpl_key_frame($attrib) |
|
187 |
{ |
|
188 |
if (!$attrib['id']) { |
|
189 |
$attrib['id'] = 'rcmkeysframe'; |
|
190 |
} |
|
191 |
|
|
192 |
$attrib['name'] = $attrib['id']; |
|
193 |
|
|
194 |
$this->rc->output->set_env('contentframe', $attrib['name']); |
a99c34
|
195 |
$this->rc->output->set_env('blankpage', $attrib['src'] ? |
cfc27c
|
196 |
$this->rc->output->abs_url($attrib['src']) : 'program/resources/blank.gif'); |
48e9c1
|
197 |
|
789baa
|
198 |
return $this->rc->output->frame($attrib); |
48e9c1
|
199 |
} |
T |
200 |
|
|
201 |
/** |
|
202 |
* Template object for list of keys. |
|
203 |
* |
|
204 |
* @param array Object attributes |
|
205 |
* |
|
206 |
* @return string HTML content |
|
207 |
*/ |
|
208 |
function tpl_keys_list($attrib) |
|
209 |
{ |
|
210 |
// add id to message list table if not specified |
|
211 |
if (!strlen($attrib['id'])) { |
|
212 |
$attrib['id'] = 'rcmenigmakeyslist'; |
|
213 |
} |
|
214 |
|
|
215 |
// define list of cols to be displayed |
|
216 |
$a_show_cols = array('name'); |
|
217 |
|
|
218 |
// create XHTML table |
61be82
|
219 |
$out = $this->rc->table_output($attrib, array(), $a_show_cols, 'id'); |
48e9c1
|
220 |
|
T |
221 |
// set client env |
|
222 |
$this->rc->output->add_gui_object('keyslist', $attrib['id']); |
|
223 |
$this->rc->output->include_script('list.js'); |
|
224 |
|
|
225 |
// add some labels to client |
0878c8
|
226 |
$this->rc->output->add_label('enigma.keyremoveconfirm', 'enigma.keyremoving'); |
48e9c1
|
227 |
|
T |
228 |
return $out; |
|
229 |
} |
|
230 |
|
|
231 |
/** |
|
232 |
* Key listing (and searching) request handler |
|
233 |
*/ |
|
234 |
private function key_list() |
|
235 |
{ |
|
236 |
$this->enigma->load_engine(); |
|
237 |
|
|
238 |
$pagesize = $this->rc->config->get('pagesize', 100); |
61be82
|
239 |
$page = max(intval(rcube_utils::get_input_value('_p', rcube_utils::INPUT_GPC)), 1); |
AM |
240 |
$search = rcube_utils::get_input_value('_q', rcube_utils::INPUT_GPC); |
48e9c1
|
241 |
|
T |
242 |
// Get the list |
|
243 |
$list = $this->enigma->engine->list_keys($search); |
|
244 |
|
|
245 |
if ($list && ($list instanceof enigma_error)) |
|
246 |
$this->rc->output->show_message('enigma.keylisterror', 'error'); |
|
247 |
else if (empty($list)) |
|
248 |
$this->rc->output->show_message('enigma.nokeysfound', 'notice'); |
a99c34
|
249 |
else if (is_array($list)) { |
AM |
250 |
// Save the size |
|
251 |
$listsize = count($list); |
48e9c1
|
252 |
|
a99c34
|
253 |
// Sort the list by key (user) name |
AM |
254 |
usort($list, array('enigma_key', 'cmp')); |
48e9c1
|
255 |
|
a99c34
|
256 |
// Slice current page |
AM |
257 |
$list = array_slice($list, ($page - 1) * $pagesize, $pagesize); |
|
258 |
$size = count($list); |
48e9c1
|
259 |
|
a99c34
|
260 |
// Add rows |
AM |
261 |
foreach ($list as $key) { |
|
262 |
$this->rc->output->command('enigma_add_list_row', |
|
263 |
array('name' => rcube::Q($key->name), 'id' => $key->id)); |
48e9c1
|
264 |
} |
T |
265 |
} |
|
266 |
|
211929
|
267 |
$this->rc->output->set_env('rowcount', $size); |
48e9c1
|
268 |
$this->rc->output->set_env('search_request', $search); |
T |
269 |
$this->rc->output->set_env('pagecount', ceil($listsize/$pagesize)); |
|
270 |
$this->rc->output->set_env('current_page', $page); |
|
271 |
$this->rc->output->command('set_rowcount', |
|
272 |
$this->get_rowcount_text($listsize, $size, $page)); |
|
273 |
|
|
274 |
$this->rc->output->send(); |
|
275 |
} |
|
276 |
|
|
277 |
/** |
|
278 |
* Template object for list records counter. |
|
279 |
* |
|
280 |
* @param array Object attributes |
|
281 |
* |
|
282 |
* @return string HTML output |
|
283 |
*/ |
|
284 |
function tpl_keys_rowcount($attrib) |
|
285 |
{ |
|
286 |
if (!$attrib['id']) |
|
287 |
$attrib['id'] = 'rcmcountdisplay'; |
|
288 |
|
|
289 |
$this->rc->output->add_gui_object('countdisplay', $attrib['id']); |
|
290 |
|
|
291 |
return html::span($attrib, $this->get_rowcount_text()); |
|
292 |
} |
|
293 |
|
|
294 |
/** |
|
295 |
* Returns text representation of list records counter |
|
296 |
*/ |
|
297 |
private function get_rowcount_text($all=0, $curr_count=0, $page=1) |
|
298 |
{ |
a99c34
|
299 |
if (!$curr_count) { |
48e9c1
|
300 |
$out = $this->enigma->gettext('nokeysfound'); |
a99c34
|
301 |
} |
48e9c1
|
302 |
else { |
T |
303 |
$pagesize = $this->rc->config->get('pagesize', 100); |
a99c34
|
304 |
$first = ($page - 1) * $pagesize; |
48e9c1
|
305 |
|
T |
306 |
$out = $this->enigma->gettext(array( |
|
307 |
'name' => 'keysfromto', |
|
308 |
'vars' => array( |
|
309 |
'from' => $first + 1, |
|
310 |
'to' => $first + $curr_count, |
|
311 |
'count' => $all) |
|
312 |
)); |
|
313 |
} |
|
314 |
|
|
315 |
return $out; |
|
316 |
} |
|
317 |
|
|
318 |
/** |
|
319 |
* Key information page handler |
|
320 |
*/ |
|
321 |
private function key_info() |
|
322 |
{ |
|
323 |
$this->enigma->load_engine(); |
0878c8
|
324 |
|
AM |
325 |
$id = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GET); |
48e9c1
|
326 |
$res = $this->enigma->engine->get_key($id); |
T |
327 |
|
0878c8
|
328 |
if ($res instanceof enigma_key) { |
48e9c1
|
329 |
$this->data = $res; |
0878c8
|
330 |
} |
48e9c1
|
331 |
else { // error |
T |
332 |
$this->rc->output->show_message('enigma.keyopenerror', 'error'); |
|
333 |
$this->rc->output->command('parent.enigma_loadframe'); |
|
334 |
$this->rc->output->send('iframe'); |
|
335 |
} |
|
336 |
|
|
337 |
$this->rc->output->add_handlers(array( |
|
338 |
'keyname' => array($this, 'tpl_key_name'), |
|
339 |
'keydata' => array($this, 'tpl_key_data'), |
|
340 |
)); |
|
341 |
|
|
342 |
$this->rc->output->set_pagetitle($this->enigma->gettext('keyinfo')); |
|
343 |
$this->rc->output->send('enigma.keyinfo'); |
|
344 |
} |
|
345 |
|
|
346 |
/** |
|
347 |
* Template object for key name |
|
348 |
*/ |
|
349 |
function tpl_key_name($attrib) |
|
350 |
{ |
61be82
|
351 |
return rcube::Q($this->data->name); |
48e9c1
|
352 |
} |
T |
353 |
|
|
354 |
/** |
|
355 |
* Template object for key information page content |
|
356 |
*/ |
|
357 |
function tpl_key_data($attrib) |
|
358 |
{ |
58c279
|
359 |
$out = ''; |
13eb9b
|
360 |
$table = new html_table(array('cols' => 2)); |
48e9c1
|
361 |
|
T |
362 |
// Key user ID |
|
363 |
$table->add('title', $this->enigma->gettext('keyuserid')); |
61be82
|
364 |
$table->add(null, rcube::Q($this->data->name)); |
58c279
|
365 |
|
48e9c1
|
366 |
// Key ID |
T |
367 |
$table->add('title', $this->enigma->gettext('keyid')); |
|
368 |
$table->add(null, $this->data->subkeys[0]->get_short_id()); |
58c279
|
369 |
|
48e9c1
|
370 |
// Key type |
T |
371 |
$keytype = $this->data->get_type(); |
58c279
|
372 |
if ($keytype == enigma_key::TYPE_KEYPAIR) { |
48e9c1
|
373 |
$type = $this->enigma->gettext('typekeypair'); |
58c279
|
374 |
} |
AM |
375 |
else if ($keytype == enigma_key::TYPE_PUBLIC) { |
48e9c1
|
376 |
$type = $this->enigma->gettext('typepublickey'); |
58c279
|
377 |
} |
48e9c1
|
378 |
$table->add('title', $this->enigma->gettext('keytype')); |
T |
379 |
$table->add(null, $type); |
58c279
|
380 |
|
48e9c1
|
381 |
// Key fingerprint |
T |
382 |
$table->add('title', $this->enigma->gettext('fingerprint')); |
|
383 |
$table->add(null, $this->data->subkeys[0]->get_fingerprint()); |
|
384 |
|
|
385 |
$out .= html::tag('fieldset', null, |
|
386 |
html::tag('legend', null, |
|
387 |
$this->enigma->gettext('basicinfo')) . $table->show($attrib)); |
13eb9b
|
388 |
|
48e9c1
|
389 |
// Subkeys |
13eb9b
|
390 |
$table = new html_table(array('cols' => 5, 'id' => 'enigmasubkeytable', 'class' => 'records-table')); |
AM |
391 |
|
|
392 |
$table->add_header('id', $this->enigma->gettext('subkeyid')); |
|
393 |
$table->add_header('algo', $this->enigma->gettext('subkeyalgo')); |
|
394 |
$table->add_header('created', $this->enigma->gettext('subkeycreated')); |
|
395 |
$table->add_header('expires', $this->enigma->gettext('subkeyexpires')); |
|
396 |
$table->add_header('usage', $this->enigma->gettext('subkeyusage')); |
|
397 |
|
|
398 |
$now = time(); |
|
399 |
$date_format = $this->rc->config->get('date_format', 'Y-m-d'); |
|
400 |
$usage_map = array( |
c85242
|
401 |
enigma_key::CAN_ENCRYPT => $this->enigma->gettext('typeencrypt'), |
AM |
402 |
enigma_key::CAN_SIGN => $this->enigma->gettext('typesign'), |
|
403 |
enigma_key::CAN_CERTIFY => $this->enigma->gettext('typecert'), |
|
404 |
enigma_key::CAN_AUTHENTICATE => $this->enigma->gettext('typeauth'), |
13eb9b
|
405 |
); |
AM |
406 |
|
|
407 |
foreach ($this->data->subkeys as $subkey) { |
|
408 |
$algo = $subkey->get_algorithm(); |
|
409 |
if ($algo && $subkey->length) { |
|
410 |
$algo .= ' (' . $subkey->length . ')'; |
|
411 |
} |
|
412 |
|
|
413 |
$usage = array(); |
|
414 |
foreach ($usage_map as $key => $text) { |
|
415 |
if ($subkey->usage & $key) { |
|
416 |
$usage[] = $text; |
|
417 |
} |
|
418 |
} |
|
419 |
|
|
420 |
$table->add('id', $subkey->get_short_id()); |
|
421 |
$table->add('algo', $algo); |
|
422 |
$table->add('created', $subkey->created ? $this->rc->format_date($subkey->created, $date_format, false) : ''); |
|
423 |
$table->add('expires', $subkey->expires ? $this->rc->format_date($subkey->expires, $date_format, false) : $this->enigma->gettext('expiresnever')); |
|
424 |
$table->add('usage', implode(',', $usage)); |
|
425 |
$table->set_row_attribs($subkey->revoked || ($subkey->expires && $subkey->expires < $now) ? 'deleted' : ''); |
|
426 |
} |
48e9c1
|
427 |
|
T |
428 |
$out .= html::tag('fieldset', null, |
13eb9b
|
429 |
html::tag('legend', null, |
AM |
430 |
$this->enigma->gettext('subkeys')) . $table->show()); |
48e9c1
|
431 |
|
T |
432 |
// Additional user IDs |
13eb9b
|
433 |
$table = new html_table(array('cols' => 2, 'id' => 'enigmausertable', 'class' => 'records-table')); |
AM |
434 |
|
|
435 |
$table->add_header('id', $this->enigma->gettext('userid')); |
|
436 |
$table->add_header('valid', $this->enigma->gettext('uservalid')); |
|
437 |
|
|
438 |
foreach ($this->data->users as $user) { |
|
439 |
$username = $user->name; |
|
440 |
if ($user->comment) { |
|
441 |
$username .= ' (' . $user->comment . ')'; |
|
442 |
} |
|
443 |
$username .= ' <' . $user->email . '>'; |
|
444 |
|
|
445 |
$table->add('id', rcube::Q(trim($username))); |
|
446 |
$table->add('valid', $this->enigma->gettext($user->valid ? 'valid' : 'unknown')); |
|
447 |
$table->set_row_attribs($user->revoked || !$user->valid ? 'deleted' : ''); |
|
448 |
} |
48e9c1
|
449 |
|
T |
450 |
$out .= html::tag('fieldset', null, |
13eb9b
|
451 |
html::tag('legend', null, |
AM |
452 |
$this->enigma->gettext('userids')) . $table->show()); |
|
453 |
|
48e9c1
|
454 |
return $out; |
211929
|
455 |
} |
AM |
456 |
|
|
457 |
/** |
|
458 |
* Key(s) export handler |
|
459 |
*/ |
|
460 |
private function key_export() |
|
461 |
{ |
|
462 |
$keys = rcube_utils::get_input_value('_keys', rcube_utils::INPUT_GPC); |
|
463 |
$engine = $this->enigma->load_engine(); |
|
464 |
$list = $keys == '*' ? $engine->list_keys() : explode(',', $keys); |
|
465 |
|
|
466 |
if (is_array($list)) { |
|
467 |
$filename = 'export.pgp'; |
|
468 |
if (count($list) == 1) { |
|
469 |
$filename = (is_object($list[0]) ? $list[0]->id : $list[0]) . '.pgp'; |
|
470 |
} |
|
471 |
|
|
472 |
// send downlaod headers |
|
473 |
header('Content-Type: application/pgp-keys'); |
|
474 |
header('Content-Disposition: attachment; filename="' . $filename . '"'); |
|
475 |
|
|
476 |
if ($fp = fopen('php://output', 'w')) { |
|
477 |
foreach ($list as $key) { |
|
478 |
$engine->export_key(is_object($key) ? $key->id : $key, $fp); |
|
479 |
} |
|
480 |
} |
|
481 |
} |
|
482 |
|
|
483 |
exit; |
48e9c1
|
484 |
} |
T |
485 |
|
|
486 |
/** |
d5501a
|
487 |
* Key import (page) handler |
48e9c1
|
488 |
*/ |
T |
489 |
private function key_import() |
|
490 |
{ |
|
491 |
// Import process |
d5501a
|
492 |
if ($data = rcube_utils::get_input_value('_keys', rcube_utils::INPUT_POST)) { |
AM |
493 |
// Import from generation form (ajax request) |
|
494 |
$this->enigma->load_engine(); |
|
495 |
$result = $this->enigma->engine->import_key($data); |
|
496 |
|
|
497 |
if (is_array($result)) { |
|
498 |
$this->rc->output->command('enigma_key_create_success'); |
|
499 |
$this->rc->output->show_message('enigma.keygeneratesuccess', 'confirmation'); |
|
500 |
} |
|
501 |
else { |
|
502 |
$this->rc->output->show_message('enigma.keysimportfailed', 'error'); |
|
503 |
} |
|
504 |
|
|
505 |
$this->rc->output->send(); |
|
506 |
} |
|
507 |
else if ($_FILES['_file']['tmp_name'] && is_uploaded_file($_FILES['_file']['tmp_name'])) { |
48e9c1
|
508 |
$this->enigma->load_engine(); |
T |
509 |
$result = $this->enigma->engine->import_key($_FILES['_file']['tmp_name'], true); |
|
510 |
|
|
511 |
if (is_array($result)) { |
|
512 |
// reload list if any keys has been added |
|
513 |
if ($result['imported']) { |
|
514 |
$this->rc->output->command('parent.enigma_list', 1); |
|
515 |
} |
d5501a
|
516 |
else { |
48e9c1
|
517 |
$this->rc->output->command('parent.enigma_loadframe'); |
d5501a
|
518 |
} |
48e9c1
|
519 |
|
T |
520 |
$this->rc->output->show_message('enigma.keysimportsuccess', 'confirmation', |
|
521 |
array('new' => $result['imported'], 'old' => $result['unchanged'])); |
|
522 |
|
|
523 |
$this->rc->output->send('iframe'); |
|
524 |
} |
0878c8
|
525 |
else { |
48e9c1
|
526 |
$this->rc->output->show_message('enigma.keysimportfailed', 'error'); |
0878c8
|
527 |
} |
48e9c1
|
528 |
} |
T |
529 |
else if ($err = $_FILES['_file']['error']) { |
|
530 |
if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) { |
|
531 |
$this->rc->output->show_message('filesizeerror', 'error', |
61be82
|
532 |
array('size' => $this->rc->show_bytes(parse_bytes(ini_get('upload_max_filesize'))))); |
48e9c1
|
533 |
} else { |
T |
534 |
$this->rc->output->show_message('fileuploaderror', 'error'); |
|
535 |
} |
|
536 |
} |
|
537 |
|
|
538 |
$this->rc->output->add_handlers(array( |
|
539 |
'importform' => array($this, 'tpl_key_import_form'), |
|
540 |
)); |
|
541 |
|
|
542 |
$this->rc->output->set_pagetitle($this->enigma->gettext('keyimport')); |
|
543 |
$this->rc->output->send('enigma.keyimport'); |
|
544 |
} |
|
545 |
|
|
546 |
/** |
|
547 |
* Template object for key import (upload) form |
|
548 |
*/ |
|
549 |
function tpl_key_import_form($attrib) |
|
550 |
{ |
|
551 |
$attrib += array('id' => 'rcmKeyImportForm'); |
|
552 |
|
|
553 |
$upload = new html_inputfield(array('type' => 'file', 'name' => '_file', |
|
554 |
'id' => 'rcmimportfile', 'size' => 30)); |
|
555 |
|
|
556 |
$form = html::p(null, |
61be82
|
557 |
rcube::Q($this->enigma->gettext('keyimporttext'), 'show') |
48e9c1
|
558 |
. html::br() . html::br() . $upload->show() |
T |
559 |
); |
|
560 |
|
|
561 |
$this->rc->output->add_label('selectimportfile', 'importwait'); |
|
562 |
$this->rc->output->add_gui_object('importform', $attrib['id']); |
|
563 |
|
|
564 |
$out = $this->rc->output->form_tag(array( |
0878c8
|
565 |
'action' => $this->rc->url(array('action' => $this->rc->action, 'a' => 'import')), |
48e9c1
|
566 |
'method' => 'post', |
T |
567 |
'enctype' => 'multipart/form-data') + $attrib, |
|
568 |
$form); |
|
569 |
|
|
570 |
return $out; |
|
571 |
} |
|
572 |
|
0878c8
|
573 |
/** |
a0dfcb
|
574 |
* Server-side key pair generation handler |
AM |
575 |
*/ |
|
576 |
private function key_generate() |
|
577 |
{ |
|
578 |
$user = rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST, true); |
|
579 |
$pass = rcube_utils::get_input_value('_password', rcube_utils::INPUT_POST, true); |
|
580 |
$size = (int) rcube_utils::get_input_value('_size', rcube_utils::INPUT_POST); |
|
581 |
|
|
582 |
if ($size > 4096) { |
|
583 |
$size = 4096; |
|
584 |
} |
|
585 |
|
|
586 |
$ident = rcube_mime::decode_address_list($user, 1, false); |
|
587 |
|
|
588 |
if (empty($ident)) { |
|
589 |
$this->rc->output->show_message('enigma.keygenerateerror', 'error'); |
|
590 |
$this->rc->output->send(); |
|
591 |
} |
|
592 |
|
|
593 |
$this->enigma->load_engine(); |
|
594 |
$result = $this->enigma->engine->generate_key(array( |
|
595 |
'user' => $ident[1]['name'], |
|
596 |
'email' => $ident[1]['mailto'], |
|
597 |
'password' => $pass, |
|
598 |
'size' => $size, |
|
599 |
)); |
|
600 |
|
|
601 |
if ($result instanceof enigma_key) { |
|
602 |
$this->rc->output->command('enigma_key_create_success'); |
|
603 |
$this->rc->output->show_message('enigma.keygeneratesuccess', 'confirmation'); |
|
604 |
} |
|
605 |
else { |
|
606 |
$this->rc->output->show_message('enigma.keygenerateerror', 'error'); |
|
607 |
} |
|
608 |
|
|
609 |
$this->rc->output->send(); |
|
610 |
} |
|
611 |
|
|
612 |
/** |
d5501a
|
613 |
* Key generation page handler |
AM |
614 |
*/ |
|
615 |
private function key_create() |
|
616 |
{ |
|
617 |
$this->enigma->include_script('openpgp.min.js'); |
|
618 |
|
|
619 |
$this->rc->output->add_handlers(array( |
|
620 |
'keyform' => array($this, 'tpl_key_create_form'), |
|
621 |
)); |
a0dfcb
|
622 |
|
AM |
623 |
$this->rc->output->set_env('enigma_keygen_server', $this->rc->config->get('enigma_keygen_server')); |
d5501a
|
624 |
|
AM |
625 |
$this->rc->output->set_pagetitle($this->enigma->gettext('keygenerate')); |
|
626 |
$this->rc->output->send('enigma.keycreate'); |
|
627 |
} |
|
628 |
|
|
629 |
/** |
|
630 |
* Template object for key generation form |
|
631 |
*/ |
|
632 |
function tpl_key_create_form($attrib) |
|
633 |
{ |
|
634 |
$attrib += array('id' => 'rcmKeyCreateForm'); |
|
635 |
$table = new html_table(array('cols' => 2)); |
|
636 |
|
|
637 |
// get user's identities |
|
638 |
$identities = $this->rc->user->list_identities(null, true); |
|
639 |
|
|
640 |
// Identity |
|
641 |
$select = new html_select(array('name' => 'identity', 'id' => 'key-ident')); |
|
642 |
foreach ((array) $identities as $idx => $ident) { |
|
643 |
$name = empty($ident['name']) ? ('<' . $ident['email'] . '>') : $ident['ident']; |
|
644 |
$select->add($name, $idx); |
|
645 |
} |
|
646 |
|
|
647 |
$table->add('title', html::label('key-name', rcube::Q($this->enigma->gettext('newkeyident')))); |
|
648 |
$table->add(null, $select->show(0)); |
|
649 |
|
|
650 |
// Key size |
|
651 |
$select = new html_select(array('name' => 'size', 'id' => 'key-size')); |
|
652 |
$select->add($this->enigma->gettext('key2048'), '2048'); |
|
653 |
$select->add($this->enigma->gettext('key4096'), '4096'); |
|
654 |
|
|
655 |
$table->add('title', html::label('key-size', rcube::Q($this->enigma->gettext('newkeysize')))); |
|
656 |
$table->add(null, $select->show()); |
|
657 |
|
|
658 |
// Password and confirm password |
|
659 |
$table->add('title', html::label('key-pass', rcube::Q($this->enigma->gettext('newkeypass')))); |
|
660 |
$table->add(null, rcube_output::get_edit_field('password', '', |
|
661 |
array('id' => 'key-pass', 'size' => $attrib['size'], 'required' => true), 'password')); |
|
662 |
|
|
663 |
$table->add('title', html::label('key-pass-confirm', rcube::Q($this->enigma->gettext('newkeypassconfirm')))); |
|
664 |
$table->add(null, rcube_output::get_edit_field('password-confirm', '', |
|
665 |
array('id' => 'key-pass-confirm', 'size' => $attrib['size'], 'required' => true), 'password')); |
|
666 |
|
|
667 |
$this->rc->output->add_gui_object('keyform', $attrib['id']); |
|
668 |
$this->rc->output->add_label('enigma.keygenerating', 'enigma.formerror', |
a0dfcb
|
669 |
'enigma.passwordsdiffer', 'enigma.keygenerateerror', 'enigma.nonameident', |
AM |
670 |
'enigma.keygennosupport'); |
d5501a
|
671 |
|
AM |
672 |
return $this->rc->output->form_tag(array(), $table->show($attrib)); |
|
673 |
} |
|
674 |
|
|
675 |
/** |
0878c8
|
676 |
* Key deleting |
AM |
677 |
*/ |
|
678 |
private function key_delete() |
|
679 |
{ |
211929
|
680 |
$keys = rcube_utils::get_input_value('_keys', rcube_utils::INPUT_POST); |
AM |
681 |
$engine = $this->enigma->load_engine(); |
0878c8
|
682 |
|
AM |
683 |
foreach ((array)$keys as $key) { |
211929
|
684 |
$res = $engine->delete_key($key); |
0878c8
|
685 |
|
AM |
686 |
if ($res !== true) { |
|
687 |
$this->rc->output->show_message('enigma.keyremoveerror', 'error'); |
|
688 |
$this->rc->output->command('enigma_list'); |
|
689 |
$this->rc->output->send(); |
|
690 |
} |
|
691 |
} |
|
692 |
|
|
693 |
$this->rc->output->command('enigma_list'); |
|
694 |
$this->rc->output->show_message('enigma.keyremovesuccess', 'confirmation'); |
|
695 |
$this->rc->output->send(); |
|
696 |
} |
|
697 |
|
58c279
|
698 |
/** |
AM |
699 |
* Init compose UI (add task button and the menu) |
|
700 |
*/ |
48e9c1
|
701 |
private function compose_ui() |
T |
702 |
{ |
0878c8
|
703 |
$this->add_css(); |
AM |
704 |
|
48e9c1
|
705 |
// Options menu button |
T |
706 |
$this->enigma->add_button(array( |
0878c8
|
707 |
'type' => 'link', |
AM |
708 |
'command' => 'plugin.enigma', |
|
709 |
'onclick' => "rcmail.command('menu-open', 'enigmamenu', event.target, event)", |
|
710 |
'class' => 'button enigma', |
a99c34
|
711 |
'title' => 'encryptionoptions', |
AM |
712 |
'label' => 'encryption', |
0878c8
|
713 |
'domain' => $this->enigma->ID, |
AM |
714 |
'width' => 32, |
|
715 |
'height' => 32 |
48e9c1
|
716 |
), 'toolbar'); |
T |
717 |
|
a99c34
|
718 |
$menu = new html_table(array('cols' => 2)); |
48e9c1
|
719 |
$chbox = new html_checkbox(array('value' => 1)); |
T |
720 |
|
|
721 |
$menu->add(null, html::label(array('for' => 'enigmasignopt'), |
61be82
|
722 |
rcube::Q($this->enigma->gettext('signmsg')))); |
a99c34
|
723 |
$menu->add(null, $chbox->show($this->rc->config->get('enigma_sign_all') ? 1 : 0, |
AM |
724 |
array('name' => '_enigma_sign', 'id' => 'enigmasignopt'))); |
48e9c1
|
725 |
|
a99c34
|
726 |
$menu->add(null, html::label(array('for' => 'enigmaencryptopt'), |
61be82
|
727 |
rcube::Q($this->enigma->gettext('encryptmsg')))); |
a99c34
|
728 |
$menu->add(null, $chbox->show($this->rc->config->get('enigma_encrypt_all') ? 1 : 0, |
AM |
729 |
array('name' => '_enigma_encrypt', 'id' => 'enigmaencryptopt'))); |
48e9c1
|
730 |
|
58c279
|
731 |
$menu = html::div(array('id' => 'enigmamenu', 'class' => 'popupmenu'), $menu->show()); |
48e9c1
|
732 |
|
58c279
|
733 |
// Options menu contents |
AM |
734 |
$this->rc->output->add_footer($menu); |
0878c8
|
735 |
} |
48e9c1
|
736 |
|
0878c8
|
737 |
/** |
AM |
738 |
* Handler for message_body_prefix hook. |
|
739 |
* Called for every displayed (content) part of the message. |
|
740 |
* Adds infobox about signature verification and/or decryption |
|
741 |
* status above the body. |
|
742 |
* |
|
743 |
* @param array Original parameters |
|
744 |
* |
|
745 |
* @return array Modified parameters |
|
746 |
*/ |
|
747 |
function status_message($p) |
|
748 |
{ |
|
749 |
// skip: not a message part |
|
750 |
if ($p['part'] instanceof rcube_message) { |
|
751 |
return $p; |
|
752 |
} |
|
753 |
|
|
754 |
// skip: message has no signed/encoded content |
|
755 |
if (!$this->enigma->engine) { |
|
756 |
return $p; |
|
757 |
} |
|
758 |
|
c1a518
|
759 |
$engine = $this->enigma->engine; |
AM |
760 |
$part_id = $p['part']->mime_id; |
0878c8
|
761 |
|
AM |
762 |
// Decryption status |
c1a518
|
763 |
if (($found = $this->find_part_id($part_id, $engine->decryptions)) !== null |
AM |
764 |
&& ($status = $engine->decryptions[$found]) |
c9e2ab
|
765 |
) { |
0878c8
|
766 |
$attach_scripts = true; |
AM |
767 |
|
c9e2ab
|
768 |
// show the message only once |
c1a518
|
769 |
unset($engine->decryptions[$found]); |
0878c8
|
770 |
|
AM |
771 |
// display status info |
|
772 |
$attrib['id'] = 'enigma-message'; |
|
773 |
|
|
774 |
if ($status instanceof enigma_error) { |
|
775 |
$attrib['class'] = 'enigmaerror'; |
|
776 |
$code = $status->getCode(); |
|
777 |
|
cffe97
|
778 |
if ($code == enigma_error::KEYNOTFOUND) { |
0878c8
|
779 |
$msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($status->getData('id')), |
AM |
780 |
$this->enigma->gettext('decryptnokey'))); |
|
781 |
} |
cffe97
|
782 |
else if ($code == enigma_error::BADPASS) { |
0878c8
|
783 |
$msg = rcube::Q($this->enigma->gettext('decryptbadpass')); |
AM |
784 |
$this->password_prompt($status); |
|
785 |
} |
|
786 |
else { |
|
787 |
$msg = rcube::Q($this->enigma->gettext('decrypterror')); |
|
788 |
} |
|
789 |
} |
|
790 |
else { |
|
791 |
$attrib['class'] = 'enigmanotice'; |
|
792 |
$msg = rcube::Q($this->enigma->gettext('decryptok')); |
|
793 |
} |
|
794 |
|
|
795 |
$p['prefix'] .= html::div($attrib, $msg); |
|
796 |
} |
|
797 |
|
|
798 |
// Signature verification status |
c1a518
|
799 |
if (($found = $this->find_part_id($part_id, $engine->signed_parts)) !== null |
AM |
800 |
&& ($sig = $engine->signatures[$engine->signed_parts[$found]]) |
0878c8
|
801 |
) { |
AM |
802 |
$attach_scripts = true; |
c1a518
|
803 |
|
AM |
804 |
// show the message only once |
|
805 |
unset($engine->signatures[$engine->signed_parts[$part_id]]); |
0878c8
|
806 |
|
AM |
807 |
// display status info |
|
808 |
$attrib['id'] = 'enigma-message'; |
|
809 |
|
|
810 |
if ($sig instanceof enigma_signature) { |
|
811 |
$sender = ($sig->name ? $sig->name . ' ' : '') . '<' . $sig->email . '>'; |
|
812 |
|
cffe97
|
813 |
if ($sig->valid === enigma_error::UNVERIFIED) { |
0878c8
|
814 |
$attrib['class'] = 'enigmawarning'; |
AM |
815 |
$msg = str_replace('$sender', $sender, $this->enigma->gettext('sigunverified')); |
|
816 |
$msg = str_replace('$keyid', $sig->id, $msg); |
|
817 |
$msg = rcube::Q($msg); |
|
818 |
} |
|
819 |
else if ($sig->valid) { |
|
820 |
$attrib['class'] = 'enigmanotice'; |
|
821 |
$msg = rcube::Q(str_replace('$sender', $sender, $this->enigma->gettext('sigvalid'))); |
|
822 |
} |
|
823 |
else { |
|
824 |
$attrib['class'] = 'enigmawarning'; |
|
825 |
$msg = rcube::Q(str_replace('$sender', $sender, $this->enigma->gettext('siginvalid'))); |
|
826 |
} |
|
827 |
} |
cffe97
|
828 |
else if ($sig && $sig->getCode() == enigma_error::KEYNOTFOUND) { |
0878c8
|
829 |
$attrib['class'] = 'enigmawarning'; |
AM |
830 |
$msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($sig->getData('id')), |
|
831 |
$this->enigma->gettext('signokey'))); |
|
832 |
} |
|
833 |
else { |
|
834 |
$attrib['class'] = 'enigmaerror'; |
|
835 |
$msg = rcube::Q($this->enigma->gettext('sigerror')); |
|
836 |
} |
|
837 |
/* |
|
838 |
$msg .= ' ' . html::a(array('href' => "#sigdetails", |
|
839 |
'onclick' => rcmail_output::JS_OBJECT_NAME.".command('enigma-sig-details')"), |
|
840 |
rcube::Q($this->enigma->gettext('showdetails'))); |
|
841 |
*/ |
|
842 |
// test |
|
843 |
// $msg .= '<br /><pre>'.$sig->body.'</pre>'; |
|
844 |
|
|
845 |
$p['prefix'] .= html::div($attrib, $msg); |
|
846 |
} |
|
847 |
|
|
848 |
if ($attach_scripts) { |
|
849 |
// add css and js script |
|
850 |
$this->add_css(); |
|
851 |
$this->add_js(); |
|
852 |
} |
|
853 |
|
|
854 |
return $p; |
|
855 |
} |
|
856 |
|
|
857 |
/** |
|
858 |
* Handler for message_load hook. |
|
859 |
* Check message bodies and attachments for keys/certs. |
|
860 |
*/ |
|
861 |
function message_load($p) |
|
862 |
{ |
|
863 |
$engine = $this->enigma->load_engine(); |
|
864 |
|
58c279
|
865 |
// handle keys/certs in attachments |
0878c8
|
866 |
foreach ((array) $p['object']->attachments as $attachment) { |
AM |
867 |
if ($engine->is_keys_part($attachment)) { |
|
868 |
$this->keys_parts[] = $attachment->mime_id; |
|
869 |
} |
|
870 |
} |
|
871 |
|
|
872 |
// the same with message bodies |
|
873 |
foreach ((array) $p['object']->parts as $part) { |
|
874 |
if ($engine->is_keys_part($part)) { |
|
875 |
$this->keys_parts[] = $part->mime_id; |
|
876 |
$this->keys_bodies[] = $part->mime_id; |
|
877 |
} |
|
878 |
} |
|
879 |
|
|
880 |
// @TODO: inline PGP keys |
|
881 |
|
|
882 |
if ($this->keys_parts) { |
|
883 |
$this->enigma->add_texts('localization'); |
|
884 |
} |
|
885 |
|
|
886 |
return $p; |
|
887 |
} |
|
888 |
|
|
889 |
/** |
|
890 |
* Handler for template_object_messagebody hook. |
|
891 |
* This callback function adds a box below the message content |
|
892 |
* if there is a key/cert attachment available |
|
893 |
*/ |
|
894 |
function message_output($p) |
|
895 |
{ |
|
896 |
foreach ($this->keys_parts as $part) { |
|
897 |
// remove part's body |
|
898 |
if (in_array($part, $this->keys_bodies)) { |
|
899 |
$p['content'] = ''; |
|
900 |
} |
|
901 |
|
|
902 |
// add box below message body |
|
903 |
$p['content'] .= html::p(array('class' => 'enigmaattachment'), |
|
904 |
html::a(array( |
|
905 |
'href' => "#", |
|
906 |
'onclick' => "return ".rcmail_output::JS_OBJECT_NAME.".enigma_import_attachment('".rcube::JQ($part)."')", |
|
907 |
'title' => $this->enigma->gettext('keyattimport')), |
|
908 |
html::span(null, $this->enigma->gettext('keyattfound')))); |
|
909 |
|
|
910 |
$attach_scripts = true; |
|
911 |
} |
|
912 |
|
|
913 |
if ($attach_scripts) { |
|
914 |
// add css and js script |
|
915 |
$this->add_css(); |
|
916 |
$this->add_js(); |
|
917 |
} |
|
918 |
|
|
919 |
return $p; |
48e9c1
|
920 |
} |
T |
921 |
|
a99c34
|
922 |
/** |
AM |
923 |
* Handle message_ready hook (encryption/signing) |
|
924 |
*/ |
|
925 |
function message_ready($p) |
|
926 |
{ |
|
927 |
$savedraft = !empty($_POST['_draft']) && empty($_GET['_saveonly']); |
|
928 |
|
|
929 |
if (!$savedraft && rcube_utils::get_input_value('_enigma_sign', rcube_utils::INPUT_POST)) { |
|
930 |
$this->enigma->load_engine(); |
|
931 |
$status = $this->enigma->engine->sign_message($p['message']); |
|
932 |
$mode = 'sign'; |
|
933 |
} |
|
934 |
|
|
935 |
if ((!$status instanceof enigma_error) && rcube_utils::get_input_value('_enigma_encrypt', rcube_utils::INPUT_POST)) { |
|
936 |
$this->enigma->load_engine(); |
|
937 |
$status = $this->enigma->engine->encrypt_message($p['message'], null, $savedraft); |
|
938 |
$mode = 'encrypt'; |
|
939 |
} |
|
940 |
|
|
941 |
if ($mode && ($status instanceof enigma_error)) { |
|
942 |
$code = $status->getCode(); |
|
943 |
|
cffe97
|
944 |
if ($code == enigma_error::KEYNOTFOUND) { |
a99c34
|
945 |
$vars = array('email' => $status->getData('missing')); |
AM |
946 |
$msg = 'enigma.' . $mode . 'nokey'; |
|
947 |
} |
cffe97
|
948 |
else if ($code == enigma_error::BADPASS) { |
a99c34
|
949 |
$msg = 'enigma.' . $mode . 'badpass'; |
AM |
950 |
$type = 'warning'; |
|
951 |
|
|
952 |
$this->password_prompt($status); |
|
953 |
} |
|
954 |
else { |
|
955 |
$msg = 'enigma.' . $mode . 'error'; |
|
956 |
} |
|
957 |
|
|
958 |
$this->rc->output->show_message($msg, $type ?: 'error', $vars); |
|
959 |
$this->rc->output->send('iframe'); |
|
960 |
} |
|
961 |
|
|
962 |
return $p; |
|
963 |
} |
|
964 |
|
58c279
|
965 |
/** |
AM |
966 |
* Handler for message_compose_body hook |
|
967 |
* Display error when the message cannot be encrypted |
|
968 |
* and provide a way to try again with a password. |
|
969 |
*/ |
|
970 |
function message_compose($p) |
|
971 |
{ |
|
972 |
$engine = $this->enigma->load_engine(); |
|
973 |
|
|
974 |
// skip: message has no signed/encoded content |
|
975 |
if (!$this->enigma->engine) { |
|
976 |
return $p; |
|
977 |
} |
|
978 |
|
|
979 |
$engine = $this->enigma->engine; |
|
980 |
|
|
981 |
// Decryption status |
|
982 |
foreach ($engine->decryptions as $status) { |
|
983 |
if ($status instanceof enigma_error) { |
|
984 |
$code = $status->getCode(); |
|
985 |
|
cffe97
|
986 |
if ($code == enigma_error::KEYNOTFOUND) { |
58c279
|
987 |
$msg = rcube::Q(str_replace('$keyid', enigma_key::format_id($status->getData('id')), |
AM |
988 |
$this->enigma->gettext('decryptnokey'))); |
|
989 |
} |
cffe97
|
990 |
else if ($code == enigma_error::BADPASS) { |
58c279
|
991 |
$this->password_prompt($status, array('compose-init' => true)); |
AM |
992 |
return $p; |
|
993 |
} |
|
994 |
else { |
|
995 |
$msg = rcube::Q($this->enigma->gettext('decrypterror')); |
|
996 |
} |
|
997 |
} |
|
998 |
} |
|
999 |
|
|
1000 |
if ($msg) { |
|
1001 |
$this->rc->output->show_message($msg, 'error'); |
|
1002 |
} |
|
1003 |
|
f04b56
|
1004 |
// Check sign/ecrypt options for signed/encrypted drafts |
AM |
1005 |
$this->rc->output->set_env('enigma_force_encrypt', !empty($engine->decryptions)); |
|
1006 |
$this->rc->output->set_env('enigma_force_sign', !empty($engine->signatures)); |
|
1007 |
|
58c279
|
1008 |
return $p; |
AM |
1009 |
} |
c1a518
|
1010 |
|
AM |
1011 |
/** |
|
1012 |
* Check if the part or its parent exists in the array |
|
1013 |
* of decryptions/signatures. Returns found ID. |
|
1014 |
*/ |
|
1015 |
private function find_part_id($part_id, $data) |
|
1016 |
{ |
|
1017 |
$ids = explode('.', $part_id); |
|
1018 |
$i = 0; |
|
1019 |
$count = count($ids); |
|
1020 |
|
|
1021 |
while ($i < $count && strlen($part = implode('.', array_slice($ids, 0, ++$i)))) { |
|
1022 |
if (array_key_exists($part, $data)) { |
|
1023 |
return $part; |
|
1024 |
} |
|
1025 |
} |
|
1026 |
} |
48e9c1
|
1027 |
} |