source: subversion/trunk/plugins/managesieve/managesieve.php @ 5187

Last change on this file since 5187 was 5187, checked in by alec, 22 months ago
  • Add managesieve_script_name option for default name of the script (#1487956)
  • Property svn:keywords set to Id
File size: 57.2 KB
Line 
1<?php
2
3/**
4 * Managesieve (Sieve Filters)
5 *
6 * Plugin that adds a possibility to manage Sieve filters in Thunderbird's style.
7 * It's clickable interface which operates on text scripts and communicates
8 * with server using managesieve protocol. Adds Filters tab in Settings.
9 *
10 * @version 4.3
11 * @author Aleksander Machniak <alec@alec.pl>
12 *
13 * Configuration (see config.inc.php.dist)
14 *
15 * Copyright (C) 2008-2011, The Roundcube Dev Team
16 * Copyright (C) 2011, Kolab Systems AG
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License version 2
20 * as published by the Free Software Foundation.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 *
31 * $Id$
32 */
33
34class managesieve extends rcube_plugin
35{
36    public $task = 'mail|settings';
37
38    private $rc;
39    private $sieve;
40    private $errors;
41    private $form;
42    private $tips = array();
43    private $script = array();
44    private $exts = array();
45    private $headers = array(
46        'subject'   => 'Subject',
47        'sender'    => 'From',
48        'recipient' => 'To',
49    );
50
51
52    function init()
53    {
54        $this->rc = rcmail::get_instance();
55
56        // register actions
57        $this->register_action('plugin.managesieve', array($this, 'managesieve_actions'));
58        $this->register_action('plugin.managesieve-save', array($this, 'managesieve_save'));
59
60        if ($this->rc->task == 'settings') {
61            // load localization
62            $this->add_texts('localization/', array('filters','managefilters'));
63
64            $this->include_script('managesieve.js');
65        }
66        else if ($this->rc->task == 'mail') {
67            // register message hook
68            $this->add_hook('message_headers_output', array($this, 'mail_headers'));
69
70            // inject Create Filter popup stuff
71            if (empty($this->rc->action) || $this->rc->action == 'show') {
72                $this->mail_task_handler();
73            }
74        }
75    }
76
77    /**
78     * Add UI elements to the 'mailbox view' and 'show message' UI.
79     */
80    function mail_task_handler()
81    {
82        // load localization
83        $this->add_texts('localization/');
84
85        // use jQuery for popup window
86        $this->require_plugin('jqueryui'); 
87
88        // include main js script
89        $this->include_script('managesieve.js');
90
91        // include styles
92        $skin = $this->rc->config->get('skin');
93        if (!file_exists($this->home."/skins/$skin/managesieve_mail.css"))
94            $skin = 'default';
95        $this->include_stylesheet("skins/$skin/managesieve_mail.css");
96
97        // add 'Create filter' item to message menu
98        $this->api->add_content(html::tag('li', null, 
99            $this->api->output->button(array(
100                'command'  => 'managesieve-create',
101                'label'    => 'managesieve.filtercreate',
102                'type'     => 'link',
103                'classact' => 'filterlink active',
104                'class'    => 'filterlink',
105            ))), 'messagemenu');
106
107        // register some labels/messages
108        $this->rc->output->add_label('managesieve.newfilter', 'managesieve.usedata',
109            'managesieve.nodata', 'managesieve.nextstep', 'save');
110
111        $this->rc->session->remove('managesieve_current');
112    }
113
114    /**
115     * Get message headers for popup window
116     */
117    function mail_headers($args)
118    {
119        $headers = $args['headers'];
120        $ret     = array();
121
122        if ($headers->subject)
123            $ret[] = array('Subject', $this->rc->imap->decode_header($headers->subject));
124
125        // @TODO: List-Id, others?
126        foreach (array('From', 'To') as $h) {
127            $hl = strtolower($h);
128            if ($headers->$hl) {
129                $list = $this->rc->imap->decode_address_list($headers->$hl);
130                foreach ($list as $item) {
131                    if ($item['mailto']) {
132                        $ret[] = array($h, $item['mailto']);
133                    }
134                }
135            }
136        }
137
138        if ($this->rc->action == 'preview')
139            $this->rc->output->command('parent.set_env', array('sieve_headers' => $ret));
140        else
141            $this->rc->output->set_env('sieve_headers', $ret);
142
143
144        return $args;
145    }
146
147    /**
148     * Loads configuration, initializes plugin (including sieve connection)
149     */
150    function managesieve_start()
151    {
152        $this->load_config();
153
154        // register UI objects
155        $this->rc->output->add_handlers(array(
156            'filterslist'    => array($this, 'filters_list'),
157            'filtersetslist' => array($this, 'filtersets_list'),
158            'filterframe'    => array($this, 'filter_frame'),
159            'filterform'     => array($this, 'filter_form'),
160            'filtersetform'  => array($this, 'filterset_form'),
161        ));
162
163        // Add include path for internal classes
164        $include_path = $this->home . '/lib' . PATH_SEPARATOR;
165        $include_path .= ini_get('include_path');
166        set_include_path($include_path);
167
168        $host = rcube_parse_host($this->rc->config->get('managesieve_host', 'localhost'));
169        $port = $this->rc->config->get('managesieve_port', 2000);
170
171        $host = rcube_idn_to_ascii($host);
172
173        // try to connect to managesieve server and to fetch the script
174        $this->sieve = new rcube_sieve($_SESSION['username'],
175            $this->rc->decrypt($_SESSION['password']), $host, $port,
176            $this->rc->config->get('managesieve_auth_type'),
177            $this->rc->config->get('managesieve_usetls', false),
178            $this->rc->config->get('managesieve_disabled_extensions'),
179            $this->rc->config->get('managesieve_debug', false),
180            $this->rc->config->get('managesieve_auth_cid'), 
181            $this->rc->config->get('managesieve_auth_pw')
182        );
183
184        if (!($error = $this->sieve->error())) {
185
186            $list = $this->sieve->get_scripts();
187            $active = $this->sieve->get_active();
188            $_SESSION['managesieve_active'] = $active;
189
190            if (!empty($_GET['_set'])) {
191                $script_name = get_input_value('_set', RCUBE_INPUT_GET);
192            }
193            else if (!empty($_SESSION['managesieve_current'])) {
194                $script_name = $_SESSION['managesieve_current'];
195            }
196            else {
197                // get active script
198                if ($active) {
199                    $script_name = $active;
200                }
201                else if ($list) {
202                    $script_name = $list[0];
203                }
204                // create a new (initial) script
205                else {
206                    // if script not exists build default script contents
207                    $script_file = $this->rc->config->get('managesieve_default');
208                    $script_name = $this->rc->config->get('managesieve_script_name');
209
210                    if (empty($script_name))
211                        $script_name = 'roundcube';
212
213                    if ($script_file && is_readable($script_file))
214                        $content = file_get_contents($script_file);
215
216                    // add script and set it active
217                    if ($this->sieve->save_script($script_name, $content))
218                        if ($this->sieve->activate($script_name))
219                            $_SESSION['managesieve_active'] = $script_name;
220                }
221            }
222
223            if ($script_name)
224                $this->sieve->load($script_name);
225
226            $error = $this->sieve->error();
227        }
228
229        // finally set script objects
230        if ($error) {
231            switch ($error) {
232                case SIEVE_ERROR_CONNECTION:
233                case SIEVE_ERROR_LOGIN:
234                    $this->rc->output->show_message('managesieve.filterconnerror', 'error');
235                    break;
236                default:
237                    $this->rc->output->show_message('managesieve.filterunknownerror', 'error');
238                    break;
239            }
240
241            raise_error(array('code' => 403, 'type' => 'php',
242                'file' => __FILE__, 'line' => __LINE__,
243                'message' => "Unable to connect to managesieve on $host:$port"), true, false);
244
245            // to disable 'Add filter' button set env variable
246            $this->rc->output->set_env('filterconnerror', true);
247            $this->script = array();
248        }
249        else {
250            $this->script = $this->sieve->script->as_array();
251            $this->exts = $this->sieve->get_extensions();
252            $this->rc->output->set_env('active_set', $_SESSION['managesieve_active']);
253            $_SESSION['managesieve_current'] = $this->sieve->current;
254        }
255
256        return $error;
257    }
258
259    function managesieve_actions()
260    {
261        // load localization
262        $this->add_texts('localization/', array('filters','managefilters'));
263
264        // include main js script
265        if ($this->api->output->type == 'html') {
266            $this->include_script('managesieve.js');
267        }
268
269        // Init plugin and handle managesieve connection
270        $error = $this->managesieve_start();
271
272        // Handle user requests
273        if ($action = get_input_value('_act', RCUBE_INPUT_GPC)) {
274            $fid = (int) get_input_value('_fid', RCUBE_INPUT_GET);
275
276            if ($action == 'up' && !$error) {
277                if ($fid && isset($this->script[$fid]) && isset($this->script[$fid-1])) {
278                    if ($this->sieve->script->update_rule($fid, $this->script[$fid-1]) !== false
279                        && $this->sieve->script->update_rule($fid-1, $this->script[$fid]) !== false) {
280                        $result = $this->sieve->save();
281                    }
282
283                    if ($result) {
284//                      $this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
285                        $this->rc->output->command('managesieve_updatelist', 'up', '', $fid);
286                    } else
287                        $this->rc->output->show_message('managesieve.filtersaveerror', 'error');
288                }
289            }
290            else if ($action == 'down' && !$error) {
291                if (isset($this->script[$fid]) && isset($this->script[$fid+1])) {
292                    if ($this->sieve->script->update_rule($fid, $this->script[$fid+1]) !== false
293                        && $this->sieve->script->update_rule($fid+1, $this->script[$fid]) !== false) {
294                        $result = $this->sieve->save();
295                    }
296
297                    if ($result === true) {
298//                      $this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
299                        $this->rc->output->command('managesieve_updatelist', 'down', '', $fid);
300                    } else {
301                        $this->rc->output->show_message('managesieve.filtersaveerror', 'error');
302                    }
303                }
304            }
305            else if ($action == 'delete' && !$error) {
306                if (isset($this->script[$fid])) {
307                    if ($this->sieve->script->delete_rule($fid))
308                        $result = $this->sieve->save();
309
310                    if ($result === true) {
311                        $this->rc->output->show_message('managesieve.filterdeleted', 'confirmation');
312                        $this->rc->output->command('managesieve_updatelist', 'delete', '', $fid);
313                    } else {
314                        $this->rc->output->show_message('managesieve.filterdeleteerror', 'error');
315                    }
316                }
317            }
318            else if ($action == 'setact' && !$error) {
319                $script_name = get_input_value('_set', RCUBE_INPUT_GPC);
320                $result = $this->sieve->activate($script_name);
321
322                if ($result === true) {
323                    $this->rc->output->set_env('active_set', $script_name);
324                    $this->rc->output->show_message('managesieve.setactivated', 'confirmation');
325                    $this->rc->output->command('managesieve_reset');
326                    $_SESSION['managesieve_active'] = $script_name;
327                } else {
328                    $this->rc->output->show_message('managesieve.setactivateerror', 'error');
329                }
330            }
331            else if ($action == 'deact' && !$error) {
332                $result = $this->sieve->deactivate();
333
334                if ($result === true) {
335                    $this->rc->output->set_env('active_set', '');
336                    $this->rc->output->show_message('managesieve.setdeactivated', 'confirmation');
337                    $this->rc->output->command('managesieve_reset');
338                    $_SESSION['managesieve_active'] = '';
339                } else {
340                    $this->rc->output->show_message('managesieve.setdeactivateerror', 'error');
341                }
342            }
343            else if ($action == 'setdel' && !$error) {
344                $script_name = get_input_value('_set', RCUBE_INPUT_GPC);
345                $result = $this->sieve->remove($script_name);
346
347                if ($result === true) {
348                    $this->rc->output->show_message('managesieve.setdeleted', 'confirmation');
349                    $this->rc->output->command('managesieve_reload');
350                    $this->rc->session->remove('managesieve_current');
351                } else {
352                    $this->rc->output->show_message('managesieve.setdeleteerror', 'error');
353                }
354            }
355            else if ($action == 'setget') {
356                $script_name = get_input_value('_set', RCUBE_INPUT_GPC);
357                $script = $this->sieve->get_script($script_name);
358
359                if (PEAR::isError($script))
360                    exit;
361
362                $browser = new rcube_browser;
363
364                // send download headers
365                header("Content-Type: application/octet-stream");
366                header("Content-Length: ".strlen($script));
367
368                if ($browser->ie)
369                    header("Content-Type: application/force-download");
370                if ($browser->ie && $browser->ver < 7)
371                    $filename = rawurlencode(abbreviate_string($script_name, 55));
372                else if ($browser->ie)
373                    $filename = rawurlencode($script_name);
374                else
375                    $filename = addcslashes($script_name, '\\"');
376
377                header("Content-Disposition: attachment; filename=\"$filename.txt\"");
378                echo $script;
379                exit;
380            }
381            elseif ($action == 'ruleadd') {
382                $rid = get_input_value('_rid', RCUBE_INPUT_GPC);
383                $id = $this->genid();
384                $content = $this->rule_div($fid, $id, false);
385
386                $this->rc->output->command('managesieve_rulefill', $content, $id, $rid);
387            }
388            elseif ($action == 'actionadd') {
389                $aid = get_input_value('_aid', RCUBE_INPUT_GPC);
390                $id = $this->genid();
391                $content = $this->action_div($fid, $id, false);
392
393                $this->rc->output->command('managesieve_actionfill', $content, $id, $aid);
394            }
395
396            $this->rc->output->send();
397        }
398        else if ($this->rc->task == 'mail') {
399            // Initialize the form
400            $rules = get_input_value('r', RCUBE_INPUT_GET);
401            if (!empty($rules)) {
402                $i = 0;
403                foreach ($rules as $rule) {
404                    list($header, $value) = explode(':', $rule, 2);
405                    $tests[$i] = array(
406                        'type' => 'contains',
407                        'test' => 'header',
408                        'arg1' => $header,
409                        'arg2' => $value,
410                    );
411                    $i++;
412                }
413
414                $this->form = array(
415                    'join'  => count($tests) > 1 ? 'allof' : 'anyof',
416                    'name'  => '',
417                    'tests' => $tests,
418                    'actions' => array(
419                        0 => array('type' => 'fileinto'),
420                        1 => array('type' => 'stop'),
421                    ),
422                );
423            }
424        }
425
426        $this->managesieve_send();
427    }
428
429    function managesieve_save()
430    {
431        // load localization
432        $this->add_texts('localization/', array('filters','managefilters'));
433
434        // include main js script
435        if ($this->api->output->type == 'html') {
436            $this->include_script('managesieve.js');
437        }
438
439        // Init plugin and handle managesieve connection
440        $error = $this->managesieve_start();
441
442        // filters set add action
443        if (!empty($_POST['_newset'])) {
444            $name = get_input_value('_name', RCUBE_INPUT_POST);
445            $copy = get_input_value('_copy', RCUBE_INPUT_POST);
446            $from = get_input_value('_from', RCUBE_INPUT_POST);
447
448            if (!$name)
449                $error = 'managesieve.emptyname';
450            else if (mb_strlen($name)>128)
451                $error = 'managesieve.nametoolong';
452            else if ($from == 'file') {
453                // from file
454                if (is_uploaded_file($_FILES['_file']['tmp_name'])) {
455                    $file = file_get_contents($_FILES['_file']['tmp_name']);
456                    $file = preg_replace('/\r/', '', $file);
457                    // for security don't save script directly
458                    // check syntax before, like this...
459                    $this->sieve->load_script($file);
460                    if (!$this->sieve->save($name)) {
461                        $error = 'managesieve.setcreateerror';
462                    }
463                }
464                else {  // upload failed
465                    $err = $_FILES['_file']['error'];
466                    $error = true;
467
468                    if ($err == UPLOAD_ERR_INI_SIZE || $err == UPLOAD_ERR_FORM_SIZE) {
469                        $msg = rcube_label(array('name' => 'filesizeerror',
470                            'vars' => array('size' =>
471                                show_bytes(parse_bytes(ini_get('upload_max_filesize'))))));
472                    }
473                    else {
474                        $error = 'fileuploaderror';
475                    }
476                }
477            }
478            else if (!$this->sieve->copy($name, $from == 'set' ? $copy : '')) {
479                $error = 'managesieve.setcreateerror';
480            }
481
482            if (!$error) {
483                $this->rc->output->show_message('managesieve.setcreated', 'confirmation');
484                $this->rc->output->command('parent.managesieve_reload', $name);
485            } else if ($msg) {
486                $this->rc->output->command('display_message', $msg, 'error');
487            } else {
488                $this->rc->output->show_message($error, 'error');
489            }
490        }
491        // filter add/edit action
492        else if (isset($_POST['_name'])) {
493            $name = trim(get_input_value('_name', RCUBE_INPUT_POST, true));
494            $fid  = trim(get_input_value('_fid', RCUBE_INPUT_POST));
495            $join = trim(get_input_value('_join', RCUBE_INPUT_POST));
496
497            // and arrays
498            $headers = $_POST['_header'];
499            $cust_headers = $_POST['_custom_header'];
500            $ops = $_POST['_rule_op'];
501            $sizeops = $_POST['_rule_size_op'];
502            $sizeitems = $_POST['_rule_size_item'];
503            $sizetargets = $_POST['_rule_size_target'];
504            $targets = $_POST['_rule_target'];
505            $act_types = $_POST['_action_type'];
506            $mailboxes = $_POST['_action_mailbox'];
507            $act_targets = $_POST['_action_target'];
508            $area_targets = $_POST['_action_target_area'];
509            $reasons = $_POST['_action_reason'];
510            $addresses = $_POST['_action_addresses'];
511            $days = $_POST['_action_days'];
512            $subject = $_POST['_action_subject'];
513            $flags = $_POST['_action_flags'];
514
515            // we need a "hack" for radiobuttons
516            foreach ($sizeitems as $item)
517                $items[] = $item;
518
519            $this->form['disabled'] = $_POST['_disabled'] ? true : false;
520            $this->form['join']     = $join=='allof' ? true : false;
521            $this->form['name']     = $name;
522            $this->form['tests']    = array();
523            $this->form['actions']  = array();
524
525            if ($name == '')
526                $this->errors['name'] = $this->gettext('cannotbeempty');
527            else {
528                foreach($this->script as $idx => $rule)
529                    if($rule['name'] == $name && $idx != $fid) {
530                        $this->errors['name'] = $this->gettext('ruleexist');
531                        break;
532                    }
533            }
534
535            $i = 0;
536            // rules
537            if ($join == 'any') {
538                $this->form['tests'][0]['test'] = 'true';
539            }
540            else {
541                foreach ($headers as $idx => $header) {
542                    $header = $this->strip_value($header);
543                    $target = $this->strip_value($targets[$idx], true);
544                    $op     = $this->strip_value($ops[$idx]);
545
546                    // normal header
547                    if (in_array($header, $this->headers)) {
548                        if (preg_match('/^not/', $op))
549                            $this->form['tests'][$i]['not'] = true;
550                        $type = preg_replace('/^not/', '', $op);
551
552                        if ($type == 'exists') {
553                            $this->form['tests'][$i]['test'] = 'exists';
554                            $this->form['tests'][$i]['arg'] = $header;
555                        }
556                        else {
557                            $this->form['tests'][$i]['type'] = $type;
558                            $this->form['tests'][$i]['test'] = 'header';
559                            $this->form['tests'][$i]['arg1'] = $header;
560                            $this->form['tests'][$i]['arg2'] = $target;
561
562                            if ($target == '')
563                                $this->errors['tests'][$i]['target'] = $this->gettext('cannotbeempty');
564                            else if (preg_match('/^(value|count)-/', $type) && !preg_match('/[0-9]+/', $target))
565                                $this->errors['tests'][$i]['target'] = $this->gettext('forbiddenchars');
566                        }
567                    }
568                    else
569                        switch ($header) {
570                        case 'size':
571                            $sizeop     = $this->strip_value($sizeops[$idx]);
572                            $sizeitem   = $this->strip_value($items[$idx]);
573                            $sizetarget = $this->strip_value($sizetargets[$idx]);
574
575                            $this->form['tests'][$i]['test'] = 'size';
576                            $this->form['tests'][$i]['type'] = $sizeop;
577                            $this->form['tests'][$i]['arg']  = $sizetarget.$sizeitem;
578
579                            if ($sizetarget == '')
580                                $this->errors['tests'][$i]['sizetarget'] = $this->gettext('cannotbeempty');
581                            else if (!preg_match('/^[0-9]+(K|M|G)*$/i', $sizetarget))
582                                $this->errors['tests'][$i]['sizetarget'] = $this->gettext('forbiddenchars');
583                            break;
584                        case '...':
585                            $cust_header = $headers = $this->strip_value($cust_headers[$idx]);
586
587                            if (preg_match('/^not/', $op))
588                                $this->form['tests'][$i]['not'] = true;
589                            $type = preg_replace('/^not/', '', $op);
590
591                            if ($cust_header == '')
592                                $this->errors['tests'][$i]['header'] = $this->gettext('cannotbeempty');
593                            else {
594                                $headers = preg_split('/[\s,]+/', $cust_header, -1, PREG_SPLIT_NO_EMPTY);
595
596                                if (!count($headers))
597                                    $this->errors['tests'][$i]['header'] = $this->gettext('cannotbeempty');
598                                else {
599                                    foreach ($headers as $hr)
600                                        if (!preg_match('/^[a-z0-9-]+$/i', $hr))
601                                            $this->errors['tests'][$i]['header'] = $this->gettext('forbiddenchars');
602                                }
603                            }
604
605                            if (empty($this->errors['tests'][$i]['header']))
606                                $cust_header = (is_array($headers) && count($headers) == 1) ? $headers[0] : $headers;
607
608                            if ($type == 'exists') {
609                                $this->form['tests'][$i]['test'] = 'exists';
610                                $this->form['tests'][$i]['arg']  = $cust_header;
611                            }
612                            else {
613                                $this->form['tests'][$i]['test'] = 'header';
614                                $this->form['tests'][$i]['type'] = $type;
615                                $this->form['tests'][$i]['arg1'] = $cust_header;
616                                $this->form['tests'][$i]['arg2'] = $target;
617
618                                if ($target == '')
619                                    $this->errors['tests'][$i]['target'] = $this->gettext('cannotbeempty');
620                                else if (preg_match('/^(value|count)-/', $type) && !preg_match('/[0-9]+/', $target))
621                                    $this->errors['tests'][$i]['target'] = $this->gettext('forbiddenchars');
622                            }
623                            break;
624                        }
625                    $i++;
626                }
627            }
628
629            $i = 0;
630            // actions
631            foreach($act_types as $idx => $type) {
632                $type   = $this->strip_value($type);
633                $target = $this->strip_value($act_targets[$idx]);
634
635                switch ($type) {
636
637                case 'fileinto':
638                case 'fileinto_copy':
639                    $mailbox = $this->strip_value($mailboxes[$idx]);
640                    $this->form['actions'][$i]['target'] = $this->mod_mailbox($mailbox, 'in');
641                    if ($type == 'fileinto_copy') {
642                        $type = 'fileinto';
643                        $this->form['actions'][$i]['copy'] = true;
644                    }
645                    break;
646
647                case 'reject':
648                case 'ereject':
649                    $target = $this->strip_value($area_targets[$idx]);
650                    $this->form['actions'][$i]['target'] = str_replace("\r\n", "\n", $target);
651
652 //                 if ($target == '')
653//                      $this->errors['actions'][$i]['targetarea'] = $this->gettext('cannotbeempty');
654                    break;
655
656                case 'redirect':
657                case 'redirect_copy':
658                    $this->form['actions'][$i]['target'] = $target;
659
660                    if ($this->form['actions'][$i]['target'] == '')
661                        $this->errors['actions'][$i]['target'] = $this->gettext('cannotbeempty');
662                    else if (!check_email($this->form['actions'][$i]['target']))
663                        $this->errors['actions'][$i]['target'] = $this->gettext('noemailwarning');
664
665                    if ($type == 'redirect_copy') {
666                        $type = 'redirect';
667                        $this->form['actions'][$i]['copy'] = true;
668                    }
669                    break;
670
671                case 'addflag':
672                case 'setflag':
673                case 'removeflag':
674                    $_target = array();
675                    if (empty($flags[$idx])) {
676                        $this->errors['actions'][$i]['target'] = $this->gettext('noflagset');
677                    }
678                    else {
679                        foreach ($flags[$idx] as $flag) {
680                            $_target[] = $this->strip_value($flag);
681                        }
682                    }
683                    $this->form['actions'][$i]['target'] = $_target;
684                    break;
685
686                case 'vacation':
687                    $reason = $this->strip_value($reasons[$idx]);
688                    $this->form['actions'][$i]['reason']    = str_replace("\r\n", "\n", $reason);
689                    $this->form['actions'][$i]['days']      = $days[$idx];
690                    $this->form['actions'][$i]['subject']   = $subject[$idx];
691                    $this->form['actions'][$i]['addresses'] = explode(',', $addresses[$idx]);
692// @TODO: vacation :mime, :from, :handle
693
694                    if ($this->form['actions'][$i]['addresses']) {
695                        foreach($this->form['actions'][$i]['addresses'] as $aidx => $address) {
696                            $address = trim($address);
697                            if (!$address)
698                                unset($this->form['actions'][$i]['addresses'][$aidx]);
699                            else if(!check_email($address)) {
700                                $this->errors['actions'][$i]['addresses'] = $this->gettext('noemailwarning');
701                                break;
702                            } else
703                                $this->form['actions'][$i]['addresses'][$aidx] = $address;
704                        }
705                    }
706
707                    if ($this->form['actions'][$i]['reason'] == '')
708                        $this->errors['actions'][$i]['reason'] = $this->gettext('cannotbeempty');
709                    if ($this->form['actions'][$i]['days'] && !preg_match('/^[0-9]+$/', $this->form['actions'][$i]['days']))
710                        $this->errors['actions'][$i]['days'] = $this->gettext('forbiddenchars');
711                    break;
712                }
713
714                $this->form['actions'][$i]['type'] = $type;
715                $i++;
716            }
717
718            if (!$this->errors) {
719                // zapis skryptu
720                if (!isset($this->script[$fid])) {
721                    $fid = $this->sieve->script->add_rule($this->form);
722                    $new = true;
723                } else
724                    $fid = $this->sieve->script->update_rule($fid, $this->form);
725
726                if ($fid !== false)
727                    $save = $this->sieve->save();
728
729                if ($save && $fid !== false) {
730                    $this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
731                    if ($this->rc->task != 'mail') {
732                        $this->rc->output->add_script(
733                            sprintf("rcmail.managesieve_updatelist('%s', '%s', %d, %d);",
734                                isset($new) ? 'add' : 'update', Q($this->form['name']),
735                                $fid, $this->form['disabled']),
736                            'foot');
737                    }
738                    else {
739                        $this->rc->output->command('managesieve_dialog_close');
740                        $this->rc->output->send('iframe');
741                    }
742                }
743                else {
744                    $this->rc->output->show_message('managesieve.filtersaveerror', 'error');
745//                  $this->rc->output->send();
746                }
747            }
748        }
749
750        $this->managesieve_send();
751    }
752
753    private function managesieve_send()
754    {
755        // Handle form action
756        if (isset($_GET['_framed']) || isset($_POST['_framed'])) {
757            if (isset($_GET['_newset']) || isset($_POST['_newset'])) {
758                $this->rc->output->send('managesieve.setedit');
759            }
760            else {
761                $this->rc->output->send('managesieve.filteredit');
762            }
763        } else {
764            $this->rc->output->set_pagetitle($this->gettext('filters'));
765            $this->rc->output->send('managesieve.managesieve');
766        }
767    }
768
769    // return the filters list as HTML table
770    function filters_list($attrib)
771    {
772        // add id to message list table if not specified
773        if (!strlen($attrib['id']))
774            $attrib['id'] = 'rcmfilterslist';
775
776        // define list of cols to be displayed
777        $a_show_cols = array('managesieve.filtername');
778
779        foreach($this->script as $idx => $filter)
780            $result[] = array(
781                'managesieve.filtername' => $filter['name'],
782                'id' => $idx,
783                'class' => $filter['disabled'] ? 'disabled' : '',
784            );
785
786        // create XHTML table
787        $out = rcube_table_output($attrib, $result, $a_show_cols, 'id');
788
789        // set client env
790        $this->rc->output->add_gui_object('filterslist', $attrib['id']);
791        $this->rc->output->include_script('list.js');
792
793        // add some labels to client
794        $this->rc->output->add_label('managesieve.filterdeleteconfirm');
795
796        return $out;
797    }
798
799    // return the filters list as <SELECT>
800    function filtersets_list($attrib)
801    {
802        // add id to message list table if not specified
803        if (!strlen($attrib['id']))
804            $attrib['id'] = 'rcmfiltersetslist';
805
806        $list = $this->sieve->get_scripts();
807        $active = $this->sieve->get_active();
808
809        $select = new html_select(array('name' => '_set', 'id' => $attrib['id'],
810            'onchange' => 'rcmail.managesieve_set()'));
811
812        if ($list) {
813            asort($list, SORT_LOCALE_STRING);
814
815            foreach ($list as $set)
816                $select->add($set . ($set == $active ? ' ('.$this->gettext('active').')' : ''), $set);
817        }
818
819        $out = $select->show($this->sieve->current);
820
821        // set client env
822        $this->rc->output->add_gui_object('filtersetslist', $attrib['id']);
823        $this->rc->output->add_label(
824            'managesieve.setdeleteconfirm',
825            'managesieve.active',
826            'managesieve.filtersetact',
827            'managesieve.filtersetdeact'
828        );
829
830        return $out;
831    }
832
833    function filter_frame($attrib)
834    {
835        if (!$attrib['id'])
836            $attrib['id'] = 'rcmfilterframe';
837
838        $attrib['name'] = $attrib['id'];
839
840        $this->rc->output->set_env('contentframe', $attrib['name']);
841        $this->rc->output->set_env('blankpage', $attrib['src'] ?
842        $this->rc->output->abs_url($attrib['src']) : 'program/blank.gif');
843
844        return html::tag('iframe', $attrib);
845    }
846
847    function filterset_form($attrib)
848    {
849        if (!$attrib['id'])
850            $attrib['id'] = 'rcmfiltersetform';
851
852        $out = '<form name="filtersetform" action="./" method="post" enctype="multipart/form-data">'."\n";
853
854        $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $this->rc->task));
855        $hiddenfields->add(array('name' => '_action', 'value' => 'plugin.managesieve-save'));
856        $hiddenfields->add(array('name' => '_framed', 'value' => ($_POST['_framed'] || $_GET['_framed'] ? 1 : 0)));
857        $hiddenfields->add(array('name' => '_newset', 'value' => 1));
858
859        $out .= $hiddenfields->show();
860
861        $name     = get_input_value('_name', RCUBE_INPUT_POST);
862        $copy     = get_input_value('_copy', RCUBE_INPUT_POST);
863        $selected = get_input_value('_from', RCUBE_INPUT_POST);
864
865        // filter set name input
866        $input_name = new html_inputfield(array('name' => '_name', 'id' => '_name', 'size' => 30,
867            'class' => ($this->errors['name'] ? 'error' : '')));
868
869        $out .= sprintf('<label for="%s"><b>%s:</b></label> %s<br /><br />',
870            '_name', Q($this->gettext('filtersetname')), $input_name->show($name));
871
872        $out .="\n<fieldset class=\"itemlist\"><legend>" . $this->gettext('filters') . ":</legend>\n";
873        $out .= '<input type="radio" id="from_none" name="_from" value="none"'
874            .(!$selected || $selected=='none' ? ' checked="checked"' : '').'></input>';
875        $out .= sprintf('<label for="%s">%s</label> ', 'from_none', Q($this->gettext('none')));
876
877        // filters set list
878        $list   = $this->sieve->get_scripts();
879        $active = $this->sieve->get_active();
880
881        $select = new html_select(array('name' => '_copy', 'id' => '_copy'));
882
883        if (is_array($list)) {
884            asort($list, SORT_LOCALE_STRING);
885
886            foreach ($list as $set)
887                $select->add($set . ($set == $active ? ' ('.$this->gettext('active').')' : ''), $set);
888
889            $out .= '<br /><input type="radio" id="from_set" name="_from" value="set"'
890                .($selected=='set' ? ' checked="checked"' : '').'></input>';
891            $out .= sprintf('<label for="%s">%s:</label> ', 'from_set', Q($this->gettext('fromset')));
892            $out .= $select->show($copy);
893        }
894
895        // script upload box
896        $upload = new html_inputfield(array('name' => '_file', 'id' => '_file', 'size' => 30,
897            'type' => 'file', 'class' => ($this->errors['name'] ? 'error' : '')));
898
899        $out .= '<br /><input type="radio" id="from_file" name="_from" value="file"'
900            .($selected=='file' ? ' checked="checked"' : '').'></input>';
901        $out .= sprintf('<label for="%s">%s:</label> ', 'from_file', Q($this->gettext('fromfile')));
902        $out .= $upload->show();
903        $out .= '</fieldset>';
904
905        $this->rc->output->add_gui_object('sieveform', 'filtersetform');
906
907        return $out;
908    }
909
910
911    function filter_form($attrib)
912    {
913        if (!$attrib['id'])
914            $attrib['id'] = 'rcmfilterform';
915
916        $fid = get_input_value('_fid', RCUBE_INPUT_GPC);
917        $scr = isset($this->form) ? $this->form : $this->script[$fid];
918
919        $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $this->rc->task));
920        $hiddenfields->add(array('name' => '_action', 'value' => 'plugin.managesieve-save'));
921        $hiddenfields->add(array('name' => '_framed', 'value' => ($_POST['_framed'] || $_GET['_framed'] ? 1 : 0)));
922        $hiddenfields->add(array('name' => '_fid', 'value' => $fid));
923
924        $out = '<form name="filterform" action="./" method="post">'."\n";
925        $out .= $hiddenfields->show();
926
927        // 'any' flag
928        if (sizeof($scr['tests']) == 1 && $scr['tests'][0]['test'] == 'true' && !$scr['tests'][0]['not'])
929            $any = true;
930
931        // filter name input
932        $field_id = '_name';
933        $input_name = new html_inputfield(array('name' => '_name', 'id' => $field_id, 'size' => 30,
934            'class' => ($this->errors['name'] ? 'error' : '')));
935
936        if ($this->errors['name'])
937            $this->add_tip($field_id, $this->errors['name'], true);
938
939        if (isset($scr))
940            $input_name = $input_name->show($scr['name']);
941        else
942            $input_name = $input_name->show();
943
944        $out .= sprintf("\n<label for=\"%s\"><b>%s:</b></label> %s<br /><br />\n",
945            $field_id, Q($this->gettext('filtername')), $input_name);
946
947        $out .= '<fieldset><legend>' . Q($this->gettext('messagesrules')) . "</legend>\n";
948
949        // any, allof, anyof radio buttons
950        $field_id = '_allof';
951        $input_join = new html_radiobutton(array('name' => '_join', 'id' => $field_id, 'value' => 'allof',
952            'onclick' => 'rule_join_radio(\'allof\')', 'class' => 'radio'));
953
954        if (isset($scr) && !$any)
955            $input_join = $input_join->show($scr['join'] ? 'allof' : '');
956        else
957            $input_join = $input_join->show();
958
959        $out .= sprintf("%s<label for=\"%s\">%s</label>&nbsp;\n",
960            $input_join, $field_id, Q($this->gettext('filterallof')));
961
962        $field_id = '_anyof';
963        $input_join = new html_radiobutton(array('name' => '_join', 'id' => $field_id, 'value' => 'anyof',
964            'onclick' => 'rule_join_radio(\'anyof\')', 'class' => 'radio'));
965
966        if (isset($scr) && !$any)
967            $input_join = $input_join->show($scr['join'] ? '' : 'anyof');
968        else
969            $input_join = $input_join->show('anyof'); // default
970
971        $out .= sprintf("%s<label for=\"%s\">%s</label>\n",
972            $input_join, $field_id, Q($this->gettext('filteranyof')));
973
974        $field_id = '_any';
975        $input_join = new html_radiobutton(array('name' => '_join', 'id' => $field_id, 'value' => 'any',
976            'onclick' => 'rule_join_radio(\'any\')', 'class' => 'radio'));
977
978        $input_join = $input_join->show($any ? 'any' : '');
979
980        $out .= sprintf("%s<label for=\"%s\">%s</label>\n",
981            $input_join, $field_id, Q($this->gettext('filterany')));
982
983        $rows_num = isset($scr) ? sizeof($scr['tests']) : 1;
984
985        $out .= '<div id="rules"'.($any ? ' style="display: none"' : '').'>';
986        for ($x=0; $x<$rows_num; $x++)
987            $out .= $this->rule_div($fid, $x);
988        $out .= "</div>\n";
989
990        $out .= "</fieldset>\n";
991
992        // actions
993        $out .= '<fieldset><legend>' . Q($this->gettext('messagesactions')) . "</legend>\n";
994
995        $rows_num = isset($scr) ? sizeof($scr['actions']) : 1;
996
997        $out .= '<div id="actions">';
998        for ($x=0; $x<$rows_num; $x++)
999            $out .= $this->action_div($fid, $x);
1000        $out .= "</div>\n";
1001
1002        $out .= "</fieldset>\n";
1003
1004        $this->print_tips();
1005
1006        if ($scr['disabled']) {
1007            $this->rc->output->set_env('rule_disabled', true);
1008        }
1009        $this->rc->output->add_label(
1010            'managesieve.ruledeleteconfirm',
1011            'managesieve.actiondeleteconfirm'
1012        );
1013        $this->rc->output->add_gui_object('sieveform', 'filterform');
1014
1015        return $out;
1016    }
1017
1018    function rule_div($fid, $id, $div=true)
1019    {
1020        $rule     = isset($this->form) ? $this->form['tests'][$id] : $this->script[$fid]['tests'][$id];
1021        $rows_num = isset($this->form) ? sizeof($this->form['tests']) : sizeof($this->script[$fid]['tests']);
1022
1023        $out = $div ? '<div class="rulerow" id="rulerow' .$id .'">'."\n" : '';
1024
1025        $out .= '<table><tr><td class="rowactions">';
1026
1027        // headers select
1028        $select_header = new html_select(array('name' => "_header[]", 'id' => 'header'.$id,
1029            'onchange' => 'rule_header_select(' .$id .')'));
1030        foreach($this->headers as $name => $val)
1031            $select_header->add(Q($this->gettext($name)), Q($val));
1032        $select_header->add(Q($this->gettext('size')), 'size');
1033        $select_header->add(Q($this->gettext('...')), '...');
1034
1035        // TODO: list arguments
1036
1037        if ((isset($rule['test']) && $rule['test'] == 'header')
1038            && !is_array($rule['arg1']) && in_array($rule['arg1'], $this->headers))
1039            $out .= $select_header->show($rule['arg1']);
1040        else if ((isset($rule['test']) && $rule['test'] == 'exists')
1041            && !is_array($rule['arg']) && in_array($rule['arg'], $this->headers))
1042            $out .= $select_header->show($rule['arg']);
1043        else if (isset($rule['test']) && $rule['test'] == 'size')
1044            $out .= $select_header->show('size');
1045        else if (isset($rule['test']) && $rule['test'] != 'true')
1046            $out .= $select_header->show('...');
1047        else
1048            $out .= $select_header->show();
1049
1050        $out .= '</td><td class="rowtargets">';
1051
1052        if ((isset($rule['test']) && $rule['test'] == 'header')
1053            && (is_array($rule['arg1']) || !in_array($rule['arg1'], $this->headers)))
1054            $custom = is_array($rule['arg1']) ? implode(', ', $rule['arg1']) : $rule['arg1'];
1055        else if ((isset($rule['test']) && $rule['test'] == 'exists')
1056            && (is_array($rule['arg']) || !in_array($rule['arg'], $this->headers)))
1057            $custom = is_array($rule['arg']) ? implode(', ', $rule['arg']) : $rule['arg'];
1058
1059        $out .= '<div id="custom_header' .$id. '" style="display:' .(isset($custom) ? 'inline' : 'none'). '">
1060            <input type="text" name="_custom_header[]" id="custom_header_i'.$id.'" '
1061            . $this->error_class($id, 'test', 'header', 'custom_header_i')
1062            .' value="' .Q($custom). '" size="20" />&nbsp;</div>' . "\n";
1063
1064        // matching type select (operator)
1065        $select_op = new html_select(array('name' => "_rule_op[]", 'id' => 'rule_op'.$id,
1066            'style' => 'display:' .($rule['test']!='size' ? 'inline' : 'none'),
1067            'onchange' => 'rule_op_select('.$id.')'));
1068        $select_op->add(Q($this->gettext('filtercontains')), 'contains');
1069        $select_op->add(Q($this->gettext('filternotcontains')), 'notcontains');
1070        $select_op->add(Q($this->gettext('filteris')), 'is');
1071        $select_op->add(Q($this->gettext('filterisnot')), 'notis');
1072        $select_op->add(Q($this->gettext('filterexists')), 'exists');
1073        $select_op->add(Q($this->gettext('filternotexists')), 'notexists');
1074        $select_op->add(Q($this->gettext('filtermatches')), 'matches');
1075        $select_op->add(Q($this->gettext('filternotmatches')), 'notmatches');
1076                if (in_array('regex', $this->exts)) {
1077            $select_op->add(Q($this->gettext('filterregex')), 'regex');
1078            $select_op->add(Q($this->gettext('filternotregex')), 'notregex');
1079        }
1080                if (in_array('relational', $this->exts)) {
1081                        $select_op->add(Q($this->gettext('countisgreaterthan')), 'count-gt');
1082                        $select_op->add(Q($this->gettext('countisgreaterthanequal')), 'count-ge');
1083                        $select_op->add(Q($this->gettext('countislessthan')), 'count-lt');
1084                        $select_op->add(Q($this->gettext('countislessthanequal')), 'count-le');
1085                        $select_op->add(Q($this->gettext('countequals')), 'count-eq');
1086                        $select_op->add(Q($this->gettext('countnotequals')), 'count-ne');
1087                        $select_op->add(Q($this->gettext('valueisgreaterthan')), 'value-gt');
1088                        $select_op->add(Q($this->gettext('valueisgreaterthanequal')), 'value-ge');
1089                        $select_op->add(Q($this->gettext('valueislessthan')), 'value-lt');
1090                        $select_op->add(Q($this->gettext('valueislessthanequal')), 'value-le');
1091                        $select_op->add(Q($this->gettext('valueequals')), 'value-eq');
1092                        $select_op->add(Q($this->gettext('valuenotequals')), 'value-ne');
1093                }
1094
1095        // target input (TODO: lists)
1096
1097        if ($rule['test'] == 'header') {
1098            $out .= $select_op->show(($rule['not'] ? 'not' : '').$rule['type']);
1099            $target = $rule['arg2'];
1100        }
1101        else if ($rule['test'] == 'size') {
1102            $out .= $select_op->show();
1103            if (preg_match('/^([0-9]+)(K|M|G)*$/', $rule['arg'], $matches)) {
1104                $sizetarget = $matches[1];
1105                $sizeitem = $matches[2];
1106            }
1107        }
1108        else {
1109            $out .= $select_op->show(($rule['not'] ? 'not' : '').$rule['test']);
1110            $target = '';
1111        }
1112
1113        $out .= '<input type="text" name="_rule_target[]" id="rule_target' .$id. '"
1114            value="' .Q($target). '" size="20" ' . $this->error_class($id, 'test', 'target', 'rule_target')
1115            . ' style="display:' . ($rule['test']!='size' && $rule['test'] != 'exists' ? 'inline' : 'none') . '" />'."\n";
1116
1117        $select_size_op = new html_select(array('name' => "_rule_size_op[]", 'id' => 'rule_size_op'.$id));
1118        $select_size_op->add(Q($this->gettext('filterunder')), 'under');
1119        $select_size_op->add(Q($this->gettext('filterover')), 'over');
1120
1121        $out .= '<div id="rule_size' .$id. '" style="display:' . ($rule['test']=='size' ? 'inline' : 'none') .'">';
1122        $out .= $select_size_op->show($rule['test']=='size' ? $rule['type'] : '');
1123        $out .= '<input type="text" name="_rule_size_target[]" id="rule_size_i'.$id.'" value="'.$sizetarget.'" size="10" ' 
1124            . $this->error_class($id, 'test', 'sizetarget', 'rule_size_i') .' />
1125            <input type="radio" name="_rule_size_item['.$id.']" value=""'
1126                . (!$sizeitem ? ' checked="checked"' : '') .' class="radio" />'.rcube_label('B').'
1127            <input type="radio" name="_rule_size_item['.$id.']" value="K"'
1128                . ($sizeitem=='K' ? ' checked="checked"' : '') .' class="radio" />'.rcube_label('KB').'
1129            <input type="radio" name="_rule_size_item['.$id.']" value="M"'
1130                . ($sizeitem=='M' ? ' checked="checked"' : '') .' class="radio" />'.rcube_label('MB').'
1131            <input type="radio" name="_rule_size_item['.$id.']" value="G"'
1132                . ($sizeitem=='G' ? ' checked="checked"' : '') .' class="radio" />'.rcube_label('GB');
1133        $out .= '</div>';
1134        $out .= '</td>';
1135
1136        // add/del buttons
1137        $out .= '<td class="rowbuttons">';
1138        $out .= '<input type="button" id="ruleadd' . $id .'" value="'. Q($this->gettext('add')). '"
1139            onclick="rcmail.managesieve_ruleadd(' . $id .')" class="button" /> ';
1140        $out .= '<input type="button" id="ruledel' . $id .'" value="'. Q($this->gettext('del')). '"
1141            onclick="rcmail.managesieve_ruledel(' . $id .')" class="button' . ($rows_num<2 ? ' disabled' : '') .'"'
1142            . ($rows_num<2 ? ' disabled="disabled"' : '') .' />';
1143        $out .= '</td></tr></table>';
1144
1145        $out .= $div ? "</div>\n" : '';
1146
1147        return $out;
1148    }
1149
1150    function action_div($fid, $id, $div=true)
1151    {
1152        $action   = isset($this->form) ? $this->form['actions'][$id] : $this->script[$fid]['actions'][$id];
1153        $rows_num = isset($this->form) ? sizeof($this->form['actions']) : sizeof($this->script[$fid]['actions']);
1154
1155        $out = $div ? '<div class="actionrow" id="actionrow' .$id .'">'."\n" : '';
1156
1157        $out .= '<table><tr><td class="rowactions">';
1158
1159        // action select
1160        $select_action = new html_select(array('name' => "_action_type[]", 'id' => 'action_type'.$id,
1161            'onchange' => 'action_type_select(' .$id .')'));
1162        if (in_array('fileinto', $this->exts))
1163            $select_action->add(Q($this->gettext('messagemoveto')), 'fileinto');
1164        if (in_array('fileinto', $this->exts) && in_array('copy', $this->exts))
1165            $select_action->add(Q($this->gettext('messagecopyto')), 'fileinto_copy');
1166        $select_action->add(Q($this->gettext('messageredirect')), 'redirect');
1167        if (in_array('copy', $this->exts))
1168            $select_action->add(Q($this->gettext('messagesendcopy')), 'redirect_copy');
1169        if (in_array('reject', $this->exts))
1170            $select_action->add(Q($this->gettext('messagediscard')), 'reject');
1171        else if (in_array('ereject', $this->exts))
1172            $select_action->add(Q($this->gettext('messagediscard')), 'ereject');
1173        if (in_array('vacation', $this->exts))
1174            $select_action->add(Q($this->gettext('messagereply')), 'vacation');
1175        $select_action->add(Q($this->gettext('messagedelete')), 'discard');
1176        if (in_array('imapflags', $this->exts) || in_array('imap4flags', $this->exts)) {
1177            $select_action->add(Q($this->gettext('setflags')), 'setflag');
1178            $select_action->add(Q($this->gettext('addflags')), 'addflag');
1179            $select_action->add(Q($this->gettext('removeflags')), 'removeflag');
1180        }
1181        $select_action->add(Q($this->gettext('rulestop')), 'stop');
1182
1183        $select_type = $action['type'];
1184        if (in_array($action['type'], array('fileinto', 'redirect')) && $action['copy']) {
1185            $select_type .= '_copy';
1186        }
1187
1188        $out .= $select_action->show($select_type);
1189        $out .= '</td>';
1190
1191        // actions target inputs
1192        $out .= '<td class="rowtargets">';
1193        // shared targets
1194        $out .= '<input type="text" name="_action_target[]" id="action_target' .$id. '" '
1195            .'value="' .($action['type']=='redirect' ? Q($action['target'], 'strict', false) : ''). '" size="40" '
1196            .'style="display:' .($action['type']=='redirect' ? 'inline' : 'none') .'" '
1197            . $this->error_class($id, 'action', 'target', 'action_target') .' />';
1198        $out .= '<textarea name="_action_target_area[]" id="action_target_area' .$id. '" '
1199            .'rows="3" cols="40" '. $this->error_class($id, 'action', 'targetarea', 'action_target_area')
1200            .'style="display:' .(in_array($action['type'], array('reject', 'ereject')) ? 'inline' : 'none') .'">'
1201            . (in_array($action['type'], array('reject', 'ereject')) ? Q($action['target'], 'strict', false) : '')
1202            . "</textarea>\n";
1203
1204        // vacation
1205        $out .= '<div id="action_vacation' .$id.'" style="display:' .($action['type']=='vacation' ? 'inline' : 'none') .'">';
1206        $out .= '<span class="label">'. Q($this->gettext('vacationreason')) .'</span><br />'
1207            .'<textarea name="_action_reason[]" id="action_reason' .$id. '" '
1208            .'rows="3" cols="45" '. $this->error_class($id, 'action', 'reason', 'action_reason') . '>'
1209            . Q($action['reason'], 'strict', false) . "</textarea>\n";
1210        $out .= '<br /><span class="label">' .Q($this->gettext('vacationsubject')) . '</span><br />'
1211            .'<input type="text" name="_action_subject[]" id="action_subject'.$id.'" '
1212            .'value="' . (is_array($action['subject']) ? Q(implode(', ', $action['subject']), 'strict', false) : $action['subject']) . '" size="50" '
1213            . $this->error_class($id, 'action', 'subject', 'action_subject') .' />';
1214        $out .= '<br /><span class="label">' .Q($this->gettext('vacationaddresses')) . '</span><br />'
1215            .'<input type="text" name="_action_addresses[]" id="action_addr'.$id.'" '
1216            .'value="' . (is_array($action['addresses']) ? Q(implode(', ', $action['addresses']), 'strict', false) : $action['addresses']) . '" size="50" '
1217            . $this->error_class($id, 'action', 'addresses', 'action_addr') .' />';
1218        $out .= '<br /><span class="label">' . Q($this->gettext('vacationdays')) . '</span><br />'
1219            .'<input type="text" name="_action_days[]" id="action_days'.$id.'" '
1220            .'value="' .Q($action['days'], 'strict', false) . '" size="2" '
1221            . $this->error_class($id, 'action', 'days', 'action_days') .' />';
1222        $out .= '</div>';
1223
1224        // flags
1225        $flags = array(
1226            'read'      => '\\Seen',
1227            'answered'  => '\\Answered',
1228            'flagged'   => '\\Flagged',
1229            'deleted'   => '\\Deleted',
1230            'draft'     => '\\Draft',
1231        );
1232        $flags_target = (array)$action['target'];
1233
1234        $out .= '<div id="action_flags' .$id.'" style="display:' 
1235            . (preg_match('/^(set|add|remove)flag$/', $action['type']) ? 'inline' : 'none') . '"'
1236            . $this->error_class($id, 'action', 'flags', 'action_flags') . '>';
1237        foreach ($flags as $fidx => $flag) {
1238            $out .= '<input type="checkbox" name="_action_flags[' .$id .'][]" value="' . $flag . '"'
1239                . (in_array_nocase($flag, $flags_target) ? 'checked="checked"' : '') . ' />'
1240                . Q($this->gettext('flag'.$fidx)) .'<br>';
1241        }
1242        $out .= '</div>';
1243
1244        // mailbox select
1245        if ($action['type'] == 'fileinto')
1246            $mailbox = $this->mod_mailbox($action['target'], 'out');
1247        else
1248            $mailbox = '';
1249
1250        $this->rc->imap_connect();
1251        $select = rcmail_mailbox_select(array(
1252                'realnames' => false,
1253                'maxlength' => 100,
1254                'id' => 'action_mailbox' . $id,
1255                'name' => '_action_mailbox[]',
1256                'style' => 'display:'.(!isset($action) || $action['type']=='fileinto' ? 'inline' : 'none')
1257            ));
1258        $out .= $select->show($mailbox);
1259        $out .= '</td>';
1260
1261        // add/del buttons
1262        $out .= '<td class="rowbuttons">';
1263        $out .= '<input type="button" id="actionadd' . $id .'" value="'. Q($this->gettext('add')). '"
1264            onclick="rcmail.managesieve_actionadd(' . $id .')" class="button" /> ';
1265        $out .= '<input type="button" id="actiondel' . $id .'" value="'. Q($this->gettext('del')). '"
1266            onclick="rcmail.managesieve_actiondel(' . $id .')" class="button' . ($rows_num<2 ? ' disabled' : '') .'"'
1267            . ($rows_num<2 ? ' disabled="disabled"' : '') .' />';
1268        $out .= '</td>';
1269
1270        $out .= '</tr></table>';
1271
1272        $out .= $div ? "</div>\n" : '';
1273
1274        return $out;
1275    }
1276
1277    private function genid()
1278    {
1279        $result = intval(rcube_timer());
1280        return $result;
1281    }
1282
1283    private function strip_value($str, $allow_html=false)
1284    {
1285        if (!$allow_html)
1286            $str = strip_tags($str);
1287
1288        return trim($str);
1289    }
1290
1291    private function error_class($id, $type, $target, $elem_prefix='')
1292    {
1293        // TODO: tooltips
1294        if (($type == 'test' && ($str = $this->errors['tests'][$id][$target])) ||
1295            ($type == 'action' && ($str = $this->errors['actions'][$id][$target]))
1296        ) {
1297            $this->add_tip($elem_prefix.$id, $str, true);
1298            return ' class="error"';
1299        }
1300
1301        return '';
1302    }
1303
1304    private function add_tip($id, $str, $error=false)
1305    {
1306        if ($error)
1307            $str = html::span('sieve error', $str);
1308
1309        $this->tips[] = array($id, $str);
1310    }
1311
1312    private function print_tips()
1313    {
1314        if (empty($this->tips))
1315            return;
1316
1317        $script = JS_OBJECT_NAME.'.managesieve_tip_register('.json_encode($this->tips).');';
1318        $this->rc->output->add_script($script, 'foot');
1319    }
1320
1321    /**
1322     * Converts mailbox name from/to UTF7-IMAP from/to internal Sieve encoding
1323     * with delimiter replacement.
1324     *
1325     * @param string $mailbox Mailbox name
1326     * @param string $mode    Conversion direction ('in'|'out')
1327     *
1328     * @return string Mailbox name
1329     */
1330    private function mod_mailbox($mailbox, $mode = 'out')
1331    {
1332        $delimiter         = $_SESSION['imap_delimiter'];
1333        $replace_delimiter = $this->rc->config->get('managesieve_replace_delimiter');
1334        $mbox_encoding     = $this->rc->config->get('managesieve_mbox_encoding', 'UTF7-IMAP');
1335
1336        if ($mode == 'out') {
1337            $mailbox = rcube_charset_convert($mailbox, $mbox_encoding, 'UTF7-IMAP');
1338            if ($replace_delimiter && $replace_delimiter != $delimiter)
1339                $mailbox = str_replace($replace_delimiter, $delimiter, $mailbox);
1340        }
1341        else {
1342            $mailbox = rcube_charset_convert($mailbox, 'UTF7-IMAP', $mbox_encoding);
1343            if ($replace_delimiter && $replace_delimiter != $delimiter)
1344                $mailbox = str_replace($delimiter, $replace_delimiter, $mailbox);
1345        }
1346
1347        return $mailbox;
1348    }
1349}
Note: See TracBrowser for help on using the repository browser.