]> git.donarmstrong.com Git - roundcube.git/blob - plugins/enigma/lib/enigma_ui.php
Imported Upstream version 0.7
[roundcube.git] / plugins / enigma / lib / enigma_ui.php
1 <?php
2 /*
3  +-------------------------------------------------------------------------+
4  | User Interface for the Enigma Plugin                                    |
5  |                                                                         |
6  | This program is free software; you can redistribute it and/or modify    |
7  | it under the terms of the GNU General Public License version 2          |
8  | as published by the Free Software Foundation.                           |
9  |                                                                         |
10  | This program is distributed in the hope that it will be useful,         |
11  | but WITHOUT ANY WARRANTY; without even the implied warranty of          |
12  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           |
13  | GNU General Public License for more details.                            |
14  |                                                                         |
15  | You should have received a copy of the GNU General Public License along |
16  | with this program; if not, write to the Free Software Foundation, Inc., |
17  | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.             |
18  |                                                                         |
19  +-------------------------------------------------------------------------+
20  | Author: Aleksander Machniak <alec@alec.pl>                              |
21  +-------------------------------------------------------------------------+
22 */
23
24 class enigma_ui
25 {
26     private $rc;
27     private $enigma;
28     private $home;
29     private $css_added;
30     private $data;
31
32
33     function __construct($enigma_plugin, $home='')
34     {
35         $this->enigma = $enigma_plugin;
36         $this->rc = $enigma_plugin->rc;
37         // we cannot use $enigma_plugin->home here
38         $this->home = $home;
39     }
40
41     /**
42      * UI initialization and requests handlers.
43      *
44      * @param string Preferences section
45      */
46     function init($section='')
47     {
48         $this->enigma->include_script('enigma.js');
49
50         // Enigma actions
51         if ($this->rc->action == 'plugin.enigma') {
52             $action = get_input_value('_a', RCUBE_INPUT_GPC);
53
54             switch ($action) {
55                 case 'keyedit':
56                     $this->key_edit();
57                     break;
58                 case 'keyimport':
59                     $this->key_import();
60                     break;
61                 case 'keysearch':
62                 case 'keylist':
63                     $this->key_list();
64                     break;
65                 case 'keyinfo':
66                 default:
67                     $this->key_info();
68             }
69         }
70         // Message composing UI
71         else if ($this->rc->action == 'compose') {
72             $this->compose_ui();
73         }
74         // Preferences UI
75         else { // if ($this->rc->action == 'edit-prefs') {
76             if ($section == 'enigmacerts') {
77                 $this->rc->output->add_handlers(array(
78                     'keyslist' => array($this, 'tpl_certs_list'),
79                     'keyframe' => array($this, 'tpl_cert_frame'),
80                     'countdisplay' => array($this, 'tpl_certs_rowcount'),
81                     'searchform' => array($this->rc->output, 'search_form'),
82                 ));
83                 $this->rc->output->set_pagetitle($this->enigma->gettext('enigmacerts'));
84                 $this->rc->output->send('enigma.certs'); 
85             }
86             else {
87                 $this->rc->output->add_handlers(array(
88                     'keyslist' => array($this, 'tpl_keys_list'),
89                     'keyframe' => array($this, 'tpl_key_frame'),
90                     'countdisplay' => array($this, 'tpl_keys_rowcount'),
91                     'searchform' => array($this->rc->output, 'search_form'),
92                 ));
93                 $this->rc->output->set_pagetitle($this->enigma->gettext('enigmakeys'));
94                 $this->rc->output->send('enigma.keys'); 
95             }
96         }
97     }
98
99    /**
100      * Adds CSS style file to the page header.
101      */
102     function add_css()
103     {
104         if ($this->css_loaded)
105             return;
106
107         $skin = $this->rc->config->get('skin');
108         if (!file_exists($this->home . "/skins/$skin/enigma.css"))
109             $skin = 'default';
110
111         $this->enigma->include_stylesheet("skins/$skin/enigma.css");
112         $this->css_added = true;
113     }
114
115     /**
116      * Template object for key info/edit frame.
117      *
118      * @param array Object attributes
119      *
120      * @return string HTML output
121      */
122     function tpl_key_frame($attrib)
123     {
124         if (!$attrib['id']) {
125             $attrib['id'] = 'rcmkeysframe';
126         }
127
128         $attrib['name'] = $attrib['id'];
129
130         $this->rc->output->set_env('contentframe', $attrib['name']);
131         $this->rc->output->set_env('blankpage', $attrib['src'] ? 
132             $this->rc->output->abs_url($attrib['src']) : 'program/blank.gif');
133
134         return html::tag('iframe', $attrib);
135     }
136
137     /**
138      * Template object for list of keys.
139      *
140      * @param array Object attributes
141      *
142      * @return string HTML content
143      */
144     function tpl_keys_list($attrib)
145     {
146         // add id to message list table if not specified
147         if (!strlen($attrib['id'])) {
148             $attrib['id'] = 'rcmenigmakeyslist';
149         }
150
151         // define list of cols to be displayed
152         $a_show_cols = array('name');
153
154         // create XHTML table
155         $out = rcube_table_output($attrib, array(), $a_show_cols, 'id');
156
157         // set client env
158         $this->rc->output->add_gui_object('keyslist', $attrib['id']);
159         $this->rc->output->include_script('list.js');
160
161         // add some labels to client
162         $this->rc->output->add_label('enigma.keyconfirmdelete');
163
164         return $out;
165     }
166
167     /**
168      * Key listing (and searching) request handler
169      */
170     private function key_list()
171     {
172         $this->enigma->load_engine();
173
174         $pagesize = $this->rc->config->get('pagesize', 100);
175         $page     = max(intval(get_input_value('_p', RCUBE_INPUT_GPC)), 1);
176         $search   = get_input_value('_q', RCUBE_INPUT_GPC);
177
178         // define list of cols to be displayed
179         $a_show_cols = array('name');
180         $result = array();
181
182         // Get the list
183         $list = $this->enigma->engine->list_keys($search);
184
185         if ($list && ($list instanceof enigma_error))
186             $this->rc->output->show_message('enigma.keylisterror', 'error');
187         else if (empty($list))
188             $this->rc->output->show_message('enigma.nokeysfound', 'notice');
189         else {
190             if (is_array($list)) {
191                 // Save the size
192                 $listsize = count($list);
193
194                 // Sort the list by key (user) name
195                 usort($list, array('enigma_key', 'cmp'));
196
197                 // Slice current page
198                 $list = array_slice($list, ($page - 1) * $pagesize, $pagesize);
199
200                 $size = count($list);
201
202                 // Add rows
203                 foreach($list as $idx => $key) {
204                     $this->rc->output->command('enigma_add_list_row',
205                         array('name' => Q($key->name), 'id' => $key->id));
206                 }
207             }
208         }
209
210         $this->rc->output->set_env('search_request', $search);
211         $this->rc->output->set_env('pagecount', ceil($listsize/$pagesize));
212         $this->rc->output->set_env('current_page', $page);
213         $this->rc->output->command('set_rowcount',
214             $this->get_rowcount_text($listsize, $size, $page));
215
216         $this->rc->output->send();
217     }
218
219     /**
220      * Template object for list records counter.
221      *
222      * @param array Object attributes
223      *
224      * @return string HTML output
225      */
226     function tpl_keys_rowcount($attrib)
227     {
228         if (!$attrib['id'])
229             $attrib['id'] = 'rcmcountdisplay';
230
231         $this->rc->output->add_gui_object('countdisplay', $attrib['id']);
232
233         return html::span($attrib, $this->get_rowcount_text());
234     }
235
236     /**
237      * Returns text representation of list records counter
238      */
239     private function get_rowcount_text($all=0, $curr_count=0, $page=1)
240     {
241         if (!$curr_count)
242             $out = $this->enigma->gettext('nokeysfound');
243         else {
244             $pagesize = $this->rc->config->get('pagesize', 100);
245             $first = ($page - 1) * $pagesize;
246
247             $out = $this->enigma->gettext(array(
248                 'name' => 'keysfromto',
249                 'vars' => array(
250                     'from'  => $first + 1,
251                     'to'    => $first + $curr_count,
252                     'count' => $all)
253             ));
254         }
255
256         return $out;
257     }
258
259     /**
260      * Key information page handler
261      */
262     private function key_info()
263     {
264         $id = get_input_value('_id', RCUBE_INPUT_GET);
265
266         $this->enigma->load_engine();
267         $res = $this->enigma->engine->get_key($id);
268
269         if ($res instanceof enigma_key)
270             $this->data = $res;
271         else { // error
272             $this->rc->output->show_message('enigma.keyopenerror', 'error');
273             $this->rc->output->command('parent.enigma_loadframe');
274             $this->rc->output->send('iframe');
275         }
276
277         $this->rc->output->add_handlers(array(
278             'keyname' => array($this, 'tpl_key_name'),
279             'keydata' => array($this, 'tpl_key_data'),
280         ));
281
282         $this->rc->output->set_pagetitle($this->enigma->gettext('keyinfo'));
283         $this->rc->output->send('enigma.keyinfo');
284     }
285
286     /**
287      * Template object for key name
288      */
289     function tpl_key_name($attrib)
290     {
291         return Q($this->data->name);
292     }
293
294     /**
295      * Template object for key information page content
296      */
297     function tpl_key_data($attrib)
298     {
299         $out = '';
300         $table = new html_table(array('cols' => 2)); 
301
302         // Key user ID
303         $table->add('title', $this->enigma->gettext('keyuserid'));
304         $table->add(null, Q($this->data->name));
305         // Key ID
306         $table->add('title', $this->enigma->gettext('keyid'));
307         $table->add(null, $this->data->subkeys[0]->get_short_id());
308         // Key type
309         $keytype = $this->data->get_type();
310         if ($keytype == enigma_key::TYPE_KEYPAIR)
311             $type = $this->enigma->gettext('typekeypair');
312         else if ($keytype == enigma_key::TYPE_PUBLIC)
313             $type = $this->enigma->gettext('typepublickey');
314         $table->add('title', $this->enigma->gettext('keytype'));
315         $table->add(null, $type);
316         // Key fingerprint
317         $table->add('title', $this->enigma->gettext('fingerprint'));
318         $table->add(null, $this->data->subkeys[0]->get_fingerprint());
319
320         $out .= html::tag('fieldset', null,
321             html::tag('legend', null,
322                 $this->enigma->gettext('basicinfo')) . $table->show($attrib));
323
324         // Subkeys
325         $table = new html_table(array('cols' => 6)); 
326         // Columns: Type, ID, Algorithm, Size, Created, Expires
327
328         $out .= html::tag('fieldset', null,
329             html::tag('legend', null, 
330                 $this->enigma->gettext('subkeys')) . $table->show($attrib));
331
332         // Additional user IDs
333         $table = new html_table(array('cols' => 2));
334         // Columns: User ID, Validity
335
336         $out .= html::tag('fieldset', null,
337             html::tag('legend', null, 
338                 $this->enigma->gettext('userids')) . $table->show($attrib));
339
340         return $out;
341     }
342
343     /**
344      * Key import page handler
345      */
346     private function key_import()
347     {
348         // Import process
349         if ($_FILES['_file']['tmp_name'] && is_uploaded_file($_FILES['_file']['tmp_name'])) {
350             $this->enigma->load_engine();
351             $result = $this->enigma->engine->import_key($_FILES['_file']['tmp_name'], true);
352
353             if (is_array($result)) {
354                 // reload list if any keys has been added
355                 if ($result['imported']) {
356                     $this->rc->output->command('parent.enigma_list', 1);
357                 }
358                 else
359                     $this->rc->output->command('parent.enigma_loadframe');
360
361                 $this->rc->output->show_message('enigma.keysimportsuccess', 'confirmation',
362                     array('new' => $result['imported'], 'old' => $result['unchanged']));
363
364                 $this->rc->output->send('iframe');
365             }
366             else
367                 $this->rc->output->show_message('enigma.keysimportfailed', 'error');
368         }
369         else if ($err = $_FILES['_file']['error']) {
370             if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
371                 $this->rc->output->show_message('filesizeerror', 'error',
372                     array('size' => show_bytes(parse_bytes(ini_get('upload_max_filesize')))));
373             } else {
374                 $this->rc->output->show_message('fileuploaderror', 'error');
375             }
376         }
377
378         $this->rc->output->add_handlers(array(
379             'importform' => array($this, 'tpl_key_import_form'),
380         ));
381
382         $this->rc->output->set_pagetitle($this->enigma->gettext('keyimport'));
383         $this->rc->output->send('enigma.keyimport');
384     }
385
386     /**
387      * Template object for key import (upload) form
388      */
389     function tpl_key_import_form($attrib)
390     {
391         $attrib += array('id' => 'rcmKeyImportForm');
392
393         $upload = new html_inputfield(array('type' => 'file', 'name' => '_file',
394             'id' => 'rcmimportfile', 'size' => 30));
395
396         $form = html::p(null,
397             Q($this->enigma->gettext('keyimporttext'), 'show')
398             . html::br() . html::br() . $upload->show()
399         );
400
401         $this->rc->output->add_label('selectimportfile', 'importwait');
402         $this->rc->output->add_gui_object('importform', $attrib['id']);
403
404         $out = $this->rc->output->form_tag(array(
405             'action' => $this->rc->url(array('action' => 'plugin.enigma', 'a' => 'keyimport')),
406             'method' => 'post',
407             'enctype' => 'multipart/form-data') + $attrib,
408             $form);
409
410         return $out;
411     }
412
413     private function compose_ui()
414     {
415         // Options menu button
416         // @TODO: make this work with non-default skins
417         $this->enigma->add_button(array(
418             'name' => 'enigmamenu',
419             'imagepas' => 'skins/default/enigma.png',
420             'imageact' => 'skins/default/enigma.png',
421             'onclick' => "rcmail_ui.show_popup('enigmamenu', true); return false",
422             'title' => 'securityoptions',
423             'domain' => 'enigma',
424             ), 'toolbar');
425
426         // Options menu contents
427         $this->enigma->add_hook('render_page', array($this, 'compose_menu'));
428     }
429
430     function compose_menu($p)
431     {
432         $menu = new html_table(array('cols' => 2));
433         $chbox = new html_checkbox(array('value' => 1));
434
435         $menu->add(null, html::label(array('for' => 'enigmadefaultopt'),
436             Q($this->enigma->gettext('identdefault'))));
437         $menu->add(null, $chbox->show(1, array('name' => '_enigma_default', 'id' => 'enigmadefaultopt')));
438
439         $menu->add(null, html::label(array('for' => 'enigmasignopt'),
440             Q($this->enigma->gettext('signmsg'))));
441         $menu->add(null, $chbox->show(1, array('name' => '_enigma_sign', 'id' => 'enigmasignopt')));
442
443         $menu->add(null, html::label(array('for' => 'enigmacryptopt'),
444             Q($this->enigma->gettext('encryptmsg'))));
445         $menu->add(null, $chbox->show(1, array('name' => '_enigma_crypt', 'id' => 'enigmacryptopt')));
446
447         $menu = html::div(array('id' => 'enigmamenu', 'class' => 'popupmenu'),
448             $menu->show());
449
450         $p['content'] = preg_replace('/(<form name="form"[^>]+>)/i', '\\1'."\n$menu", $p['content']);
451
452         return $p;
453
454     }
455
456 }