Added optional separate interface for out-of-office management (#1488266)

pull/181/head
Aleksander Machniak 10 years ago
parent 2f43fe94cb
commit 390eacc2af

@ -1,3 +1,5 @@
- Added optional separate interface for out-of-office management (#1488266)
* version 7.2 [2014-02-14]
-----------------------------------------------------------
- Nicely handle server-side modification of script names (#1489412)

@ -68,4 +68,10 @@ $config['managesieve_filename_exceptions'] = array();
// If not empty, user will need to select domain from a list
$config['managesieve_domains'] = array();
// Enables separate management interface for vacation responses (out-of-office)
// 0 - no separate section (default),
// 1 - add Vacation section,
// 2 - add Vacation section, but hide Filters section
$config['managesieve_vacation'] = 0;
?>

@ -24,21 +24,21 @@
class rcube_sieve_engine
{
private $rc;
private $sieve;
private $errors;
private $form;
private $tips = array();
private $script = array();
private $exts = array();
private $list;
private $active = array();
private $headers = array(
protected $rc;
protected $sieve;
protected $errors;
protected $form;
protected $tips = array();
protected $script = array();
protected $exts = array();
protected $list;
protected $active = array();
protected $headers = array(
'subject' => 'Subject',
'from' => 'From',
'to' => 'To',
);
private $addr_headers = array(
protected $addr_headers = array(
// Required
"from", "to", "cc", "bcc", "sender", "resent-from", "resent-to",
// Additional (RFC 822 / RFC 2822)
@ -53,7 +53,7 @@ class rcube_sieve_engine
"x-beenthere",
);
const VERSION = '7.2';
const VERSION = '8.0';
const PROGNAME = 'Roundcube (Managesieve)';
const PORT = 4190;
@ -70,7 +70,7 @@ class rcube_sieve_engine
/**
* Loads configuration, initializes plugin (including sieve connection)
*/
function start()
function start($mode = null)
{
// register UI objects
$this->rc->output->add_handlers(array(
@ -137,13 +137,16 @@ class rcube_sieve_engine
$this->rc->session->remove('managesieve_current');
}
if (!empty($_GET['_set']) || !empty($_POST['_set'])) {
$script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
}
else if (!empty($_SESSION['managesieve_current'])) {
$script_name = $_SESSION['managesieve_current'];
if ($mode != 'vacation') {
if (!empty($_GET['_set']) || !empty($_POST['_set'])) {
$script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true);
}
else if (!empty($_SESSION['managesieve_current'])) {
$script_name = $_SESSION['managesieve_current'];
}
}
else {
if ($script_name === null || $script_name === '') {
// get (first) active script
if (!empty($this->active[0])) {
$script_name = $this->active[0];
@ -911,9 +914,12 @@ class rcube_sieve_engine
break;
case 'vacation':
$reason = $this->strip_value($reasons[$idx]);
$interval_type = $interval_types[$idx] == 'seconds' ? 'seconds' : 'days';
console('---------------');
console($_POST);
console($reason);
$this->form['actions'][$i]['reason'] = str_replace("\r\n", "\n", $reason);
$this->form['actions'][$i]['subject'] = $subject[$idx];
$this->form['actions'][$i]['addresses'] = array_shift($addresses);
@ -980,7 +986,7 @@ class rcube_sieve_engine
}
if (!$this->errors && !$error) {
// zapis skryptu
// save the script
if (!isset($this->script[$fid])) {
$fid = $this->sieve->script->add_rule($this->form);
$new = true;
@ -1016,7 +1022,7 @@ class rcube_sieve_engine
$this->send();
}
private function send()
protected function send()
{
// Handle form action
if (isset($_GET['_framed']) || isset($_POST['_framed'])) {
@ -1026,7 +1032,8 @@ class rcube_sieve_engine
else {
$this->rc->output->send('managesieve.filteredit');
}
} else {
}
else {
$this->rc->output->set_pagetitle($this->plugin->gettext('filters'));
$this->rc->output->send('managesieve.managesieve');
}
@ -1809,12 +1816,12 @@ class rcube_sieve_engine
return $out;
}
private function genid()
protected function genid()
{
return preg_replace('/[^0-9]/', '', microtime(true));
}
private function strip_value($str, $allow_html = false, $trim = true)
protected function strip_value($str, $allow_html = false, $trim = true)
{
if (is_array($str)) {
foreach ($str as $idx => $val) {
@ -1835,7 +1842,7 @@ class rcube_sieve_engine
return $trim ? trim($str) : $str;
}
private function error_class($id, $type, $target, $elem_prefix='')
protected function error_class($id, $type, $target, $elem_prefix='')
{
// TODO: tooltips
if (($type == 'test' && ($str = $this->errors['tests'][$id][$target])) ||
@ -1848,7 +1855,7 @@ class rcube_sieve_engine
return '';
}
private function add_tip($id, $str, $error=false)
protected function add_tip($id, $str, $error=false)
{
if ($error)
$str = html::span('sieve error', $str);
@ -1856,7 +1863,7 @@ class rcube_sieve_engine
$this->tips[] = array($id, $str);
}
private function print_tips()
protected function print_tips()
{
if (empty($this->tips))
return;
@ -1865,7 +1872,7 @@ class rcube_sieve_engine
$this->rc->output->add_script($script, 'foot');
}
private function list_input($id, $name, $value, $enabled, $class, $size=null)
protected function list_input($id, $name, $value, $enabled, $class, $size=null)
{
$value = (array) $value;
$value = array_map(array('rcube', 'Q'), $value);
@ -1881,7 +1888,7 @@ class rcube_sieve_engine
/**
* Validate input for date part elements
*/
private function validate_date_part($type, $value)
protected function validate_date_part($type, $value)
{
// we do simple validation of date/part format
switch ($type) {
@ -1926,7 +1933,7 @@ class rcube_sieve_engine
*
* @return string Mailbox name
*/
private function mod_mailbox($mailbox, $mode = 'out')
protected function mod_mailbox($mailbox, $mode = 'out')
{
$delimiter = $_SESSION['imap_delimiter'];
$replace_delimiter = $this->rc->config->get('managesieve_replace_delimiter');
@ -2218,7 +2225,7 @@ class rcube_sieve_engine
/**
* Initializes internal script data
*/
private function init_script()
protected function init_script()
{
$this->script = $this->sieve->script->as_array();

@ -0,0 +1,303 @@
<?php
/**
* Managesieve Vacation Engine
*
* Engine part of Managesieve plugin implementing UI and backend access.
*
* Copyright (C) 2011-2014, Kolab Systems AG
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
class rcube_sieve_vacation extends rcube_sieve_engine
{
function actions()
{
$error = $this->start('vacation');
// find current vacation rule
if (!$error) {
$this->vacation_rule();
$this->vacation_post();
}
$this->plugin->add_label('vacation.saving');
$this->rc->output->add_handlers(array(
'vacationform' => array($this, 'vacation_form'),
));
$this->rc->output->set_pagetitle($this->plugin->gettext('vacation'));
$this->rc->output->send('managesieve.vacation');
}
private function vacation_rule()
{
$this->vacation = array();
if (empty($this->active)) {
return;
}
$list = array();
// find (first) vacation rule
foreach ($this->script as $idx => $rule) {
if (empty($this->vacation) && !empty($rule['actions']) && $rule['actions'][0]['type'] == 'vacation') {
$this->vacation = array_merge($rule['actions'][0], array(
'idx' => $idx,
'disabled' => $rule['disabled'],
'name' => $rule['name'],
'tests' => $rule['tests'],
));
}
else {
$list[$idx] = $rule['name'];
}
}
$this->vacation['list'] = $list;
}
private function vacation_post()
{
if (empty($_POST)) {
return;
}
$status = rcube_utils::get_input_value('vacation_status', rcube_utils::INPUT_POST);
$subject = rcube_utils::get_input_value('vacation_subject', rcube_utils::INPUT_POST, true);
$reason = rcube_utils::get_input_value('vacation_reason', rcube_utils::INPUT_POST, true);
$addresses = rcube_utils::get_input_value('vacation_addresses', rcube_utils::INPUT_POST, true);
$interval = rcube_utils::get_input_value('vacation_interval', rcube_utils::INPUT_POST);
$interval_type = rcube_utils::get_input_value('vacation_interval_type', rcube_utils::INPUT_POST);
$date_from = rcube_utils::get_input_value('vacation_datefrom', rcube_utils::INPUT_POST);
$date_to = rcube_utils::get_input_value('vacation_dateto', rcube_utils::INPUT_POST);
$after = rcube_utils::get_input_value('vacation_after', rcube_utils::INPUT_POST);
$interval_type = $interval_type == 'seconds' ? 'seconds' : 'days';
$vacation_action['type'] = 'vacation';
$vacation_action['reason'] = $this->strip_value(str_replace("\r\n", "\n", $reason));
$vacation_action['subject'] = $subject;
$vacation_action['addresses'] = $addresses;
$vacation_action[$interval_type] = $interval;
$vacation_tests = (array) $this->vacation['tests'];
foreach ((array) $vacation_action['addresses'] as $aidx => $address) {
$vacation_action['addresses'][$aidx] = $address = trim($address);
if (empty($address)) {
unset($vacation_action['addresses'][$aidx]);
}
else if (!rcube_utils::check_email($address)) {
$error = 'noemailwarning';
break;
}
}
if ($vacation_action['reason'] == '') {
$error = 'managesieve.cannotbeempty';
}
if ($vacation_action[$interval_type] && !preg_match('/^[0-9]+$/', $vacation_action[$interval_type])) {
$error = 'managesieve.forbiddenchars';
}
foreach (array('date_from', 'date_to') as $var) {
$date = $$var;
if ($date && ($dt = rcube_utils::anytodatetime($date))) {
$type = 'value-' . ($var == 'date_from' ? 'ge' : 'le');
$test = array(
'test' => 'currentdate',
'part' => 'date',
'type' => $type,
'arg' => $dt->format('Y-m-d'),
);
// find existing date rule
foreach ((array) $vacation_tests as $idx => $t) {
if ($t['test'] == 'currentdate' && $t['part'] == 'date' && $t['type'] == $type) {
$vacation_tests[$idx] = $test;
continue 2;
}
}
$vacation_tests[] = $test;
}
}
if (empty($vacation_tests)) {
$vacation_tests = $this->rc->config->get('managesieve_vacation_test', array(array('test' => 'true')));
}
// @TODO: handle situation when there's no active script
if (!$error) {
$rule = $this->vacation;
$rule['type'] = 'if';
$rule['name'] = $rule['name'] ?: $this->plugin->gettext('vacation');
$rule['disabled'] = $status == 'off';
$rule['actions'][0] = $vacation_action;
$rule['tests'] = $vacation_tests;
$rule['join'] = count($vacation_tests) > 1;
// reset original vacation rule
if (isset($this->vacation['idx'])) {
$this->script[$this->vacation['idx']] = null;
}
// re-order rules if needed
if (isset($after) && $after !== '') {
// add at target position
if ($after >= count($this->script) - 1) {
$this->script[] = $rule;
}
else {
$script = array();
foreach ($this->script as $idx => $r) {
if ($r) {
$script[] = $r;
}
if ($idx == $after) {
$script[] = $rule;
}
}
$this->script = $script;
}
}
else {
array_unshift($this->script, $rule);
}
$this->sieve->script->content = array_values(array_filter($this->script));
if ($this->save_script()) {
$this->rc->output->show_message('managesieve.vacationsaved', 'confirmation');
$this->rc->output->send();
}
}
$this->rc->output->show_message($error ? $error : 'managesieve.saveerror', 'error');
$this->rc->output->send();
}
/**
* Independent vacation form
*/
public function vacation_form($attrib)
{
// check supported extensions
$date_extension = in_array('date', $this->exts);
$seconds_extension = in_array('vacation-seconds', $this->exts);
// build FORM tag
$form_id = !empty($attrib['id']) ? $attrib['id'] : 'form';
$out = $this->rc->output->request_form(array(
'id' => $form_id,
'name' => $form_id,
'method' => 'post',
'task' => 'settings',
'action' => 'plugin.managesieve-vacation',
'noclose' => true
) + $attrib);
// form elements
$subject = new html_inputfield(array('name' => 'vacation_subject', 'size' => 50));
$reason = new html_textarea(array('name' => 'vacation_reason', 'cols' => 60, 'rows' => 8));
$interval = new html_inputfield(array('name' => 'vacation_interval', 'size' => 5));
$addresses = '<textarea name="vacation_addresses" data-type="list" data-size="30" style="display: none">'
. rcube::Q(implode("\n", (array) $this->vacation['addresses']), 'strict', false) . '</textarea>';
$status = new html_select(array('name' => 'vacation_status'));
$status->add($this->plugin->gettext('vacation.on'), 'on');
$status->add($this->plugin->gettext('vacation.off'), 'off');
if ($this->rc->config->get('managesieve_vacation') != 2 && count($this->vacation['list'])) {
$after = new html_select(array('name' => 'vacation_after'));
$after->add('', '');
foreach ($this->vacation['list'] as $idx => $rule) {
$after->add($rule, $idx);
}
}
$interval_txt = $interval->show(isset($this->vacation['seconds']) ? $this->vacation['seconds'] : $this->vacation['days']);
if ($seconds_extension) {
$interval_select = new html_select(array('name' => 'vacation_interval_type'));
$interval_select->add($this->plugin->gettext('days'), 'days');
$interval_select->add($this->plugin->gettext('seconds'), 'seconds');
$interval_txt .= '&nbsp;' . $interval_select->show(isset($this->vacation['seconds']) ? 'seconds' : 'days');
}
else {
$interval_txt .= '&nbsp;' . $this->plugin->gettext('days');
}
if ($date_extension) {
$date_from = new html_inputfield(array('name' => 'vacation_datefrom', 'class' => 'datepicker', 'size' => 12));
$date_to = new html_inputfield(array('name' => 'vacation_dateto', 'class' => 'datepicker', 'size' => 12));
$date_format = $this->rc->config->get('date_format', 'Y-m-d');
foreach ((array) $this->vacation['tests'] as $test) {
if ($test['test'] == 'currentdate' && $test['part'] == 'date') {
$date = $this->rc->format_date($test['arg'], $date_format, false);
$date_value[$test['type'] == 'value-ge' ? 'from' : 'to'] = $date;
}
}
}
// Message tab
$table = new html_table(array('cols' => 2));
$table->add('title', html::label('vacation_subject', $this->plugin->gettext('vacation.subject')));
$table->add(null, $subject->show($this->vacation['subject']));
$table->add('title', html::label('vacation_reason', $this->plugin->gettext('vacation.body')));
$table->add(null, $reason->show($this->vacation['reason']));
if ($date_extension) {
$table->add('title', html::label('vacation_datefrom', $this->plugin->gettext('vacation.dates')));
$table->add(null,
$this->plugin->gettext('vacation.from'). ' ' . $date_from->show($date_value['from'])
. ' ' . $this->plugin->gettext('vacation.to'). ' ' . $date_to->show($date_value['to'])
);
}
$table->add('title', html::label('vacation_status', $this->plugin->gettext('vacation.status')));
$table->add(null, $status->show($this->vacation['disabled'] ? 'off' : 'on'));
$out .= html::tag('fieldset', $class, html::tag('legend', null, $this->plugin->gettext('vacation.reply')) . $table->show($attrib));
// Advanced tab
$table = new html_table(array('cols' => 2));
$table->add('title', $this->plugin->gettext('vacation.addresses'));
$table->add(null, $addresses);
$table->add('title', $this->plugin->gettext('vacation.interval'));
$table->add(null, $interval_txt);
if ($after) {
$table->add('title', $this->plugin->gettext('vacation.after'));
$table->add(null, $after->show($this->vacation['idx'] - 1));
}
$out .= html::tag('fieldset', $class, html::tag('legend', null, $this->plugin->gettext('vacation.advanced')) . $table->show($attrib));
$out .= '</form>';
$this->rc->output->add_gui_object('sieveform', $form_id);
return $out;
}
}

@ -59,10 +59,10 @@ $labels['recipient'] = 'Recipient';
$labels['vacationaddr'] = 'My additional e-mail address(es):';
$labels['vacationdays'] = 'How often send messages (in days):';
$labels['vacationinterval'] = 'How often send messages:';
$labels['days'] = 'days';
$labels['seconds'] = 'seconds';
$labels['vacationreason'] = 'Message body (vacation reason):';
$labels['vacationsubject'] = 'Message subject:';
$labels['days'] = 'days';
$labels['seconds'] = 'seconds';
$labels['rulestop'] = 'Stop evaluating rules';
$labels['enable'] = 'Enable/Disable';
$labels['filterset'] = 'Filters set';
@ -159,6 +159,21 @@ $labels['asciicasemap'] = 'case insensitive (ascii-casemap)';
$labels['asciinumeric'] = 'numeric (ascii-numeric)';
$labels['index'] = 'index:';
$labels['indexlast'] = 'backwards';
$labels['vacation'] = 'Vacation';
$labels['vacation.reply'] = 'Reply message';
$labels['vacation.advanced'] = 'Advanced settings';
$labels['vacation.subject'] = 'Subject';
$labels['vacation.body'] = 'Body';
$labels['vacation.dates'] = 'Vacation time';
$labels['vacation.from'] = 'From:';
$labels['vacation.to'] = 'To:';
$labels['vacation.status'] = 'Status';
$labels['vacation.on'] = 'On';
$labels['vacation.off'] = 'Off';
$labels['vacation.addresses'] = 'My additional addresses';
$labels['vacation.interval'] = 'Reply interval';
$labels['vacation.after'] = 'Put vacation rule after';
$labels['vacation.saving'] = 'Saving data...';
$messages = array();
$messages['filterunknownerror'] = 'Unknown server error.';
@ -193,5 +208,7 @@ $messages['namereserved'] = 'Reserved name.';
$messages['setexist'] = 'Set already exists.';
$messages['nodata'] = 'At least one position must be selected!';
$messages['invaliddateformat'] = 'Invalid date or date part format';
$messages['saveerror'] = 'Unable to save data. Server error occurred.';
$messages['vacationsaved'] = 'Vacation data saved successfully.';
?>

@ -50,6 +50,18 @@ if (window.rcmail) {
$('textarea[data-type="list"]', rcmail.gui_objects.sieveform).each(function() {
smart_field_init(this);
});
// enable date pickers on date fields
if ($.datepicker && rcmail.env.date_format) {
$.datepicker.setDefaults({
dateFormat: rcmail.env.date_format,
changeMonth: true,
showOtherMonths: true,
selectOtherMonths: true,
onSelect: function(dateText) { $(this).focus().val(dateText) }
});
$('input.datepicker').datepicker();
}
}
else {
rcmail.enable_command('plugin.managesieve-add', 'plugin.managesieve-setadd', !rcmail.env.sieveconnerror);
@ -443,6 +455,12 @@ rcube_webmail.prototype.managesieve_unfocus_filter = function(row)
// Form submition
rcube_webmail.prototype.managesieve_save = function()
{
if (this.env.action == 'plugin.managesieve-vacation') {
var data = $(this.gui_objects.sieveform).serialize();
this.http_post('plugin.managesieve-vacation', data, this.display_message(this.get_label('managesieve.vacation.saving'), 'loading'));
return;
}
if (parent.rcmail && parent.rcmail.filters_list && this.gui_objects.sieveform.name != 'filtersetform') {
var id = parent.rcmail.filters_list.get_single_selection();
if (id != null)

@ -42,6 +42,7 @@ class managesieve extends rcube_plugin
// register actions
$this->register_action('plugin.managesieve', array($this, 'managesieve_actions'));
$this->register_action('plugin.managesieve-action', array($this, 'managesieve_actions'));
$this->register_action('plugin.managesieve-vacation', array($this, 'managesieve_actions'));
$this->register_action('plugin.managesieve-save', array($this, 'managesieve_save'));
if ($this->rc->task == 'settings') {
@ -69,8 +70,25 @@ class managesieve extends rcube_plugin
}
// load localization
$this->add_texts('localization/', array('filters','managefilters'));
$this->include_script('managesieve.js');
$this->add_texts('localization/');
if (strpos($this->rc->action, 'plugin.managesieve') === 0) {
$this->include_script('managesieve.js');
}
// include styles
$skin_path = $this->local_skin_path();
if ($this->rc->task == 'settings') {
if (is_file($this->home . "/$skin_path/managesieve.css")) {
$this->include_stylesheet("$skin_path/managesieve.css");
}
}
else {
if (is_file($this->home . "/$skin_path/managesieve_mail.css")) {
$this->include_stylesheet("$skin_path/managesieve_mail.css");
}
}
$this->ui_initialized = true;
}
@ -80,8 +98,30 @@ class managesieve extends rcube_plugin
*/
function settings_actions($args)
{
// register as settings action
$args['actions'][] = array('action' => 'plugin.managesieve', 'class' => 'filter', 'label' => 'filters', 'domain' => 'managesieve');
$this->load_config();
$vacation_mode = (int) $this->rc->config->get('managesieve_vacation');
// register Filters action
if ($vacation_mode != 2) {
$args['actions'][] = array(
'action' => 'plugin.managesieve',
'class' => 'filter',
'label' => 'filters',
'domain' => 'managesieve',
);
}
// register Vacation action
if ($vacation_mode > 0) {
$args['actions'][] = array(
'action' => 'plugin.managesieve-vacation',
'class' => 'vacation',
'label' => 'vacation',
'domain' => 'managesieve',
);
}
return $args;
}
@ -101,12 +141,6 @@ class managesieve extends rcube_plugin
// include js script and localization
$this->init_ui();
// include styles
$skin_path = $this->local_skin_path();
if (is_file($this->home . "/$skin_path/managesieve_mail.css")) {
$this->include_stylesheet("$skin_path/managesieve_mail.css");
}
// add 'Create filter' item to message menu
$this->api->add_content(html::tag('li', null,
$this->api->output->button(array(
@ -163,9 +197,11 @@ class managesieve extends rcube_plugin
$this->rc->output->send();
}
// handle other action
// handle other actions
$engine_type = $this->rc->action == 'plugin.managesieve-vacation' ? 'vacation' : '';
$engine = $this->get_engine($engine_type);
$this->init_ui();
$engine = $this->get_engine();
$engine->actions();
}
@ -189,7 +225,7 @@ class managesieve extends rcube_plugin
/**
* Initializes engine object
*/
private function get_engine()
private function get_engine($type = null)
{
if (!$this->engine) {
$this->load_config();
@ -199,7 +235,8 @@ class managesieve extends rcube_plugin
$include_path .= ini_get('include_path');
set_include_path($include_path);
$this->engine = new rcube_sieve_engine($this);
$class_name = 'rcube_sieve_' . ($type ? $type : 'engine');
$this->engine = new $class_name($this);
}
return $this->engine;

@ -115,7 +115,7 @@ body.iframe
padding: 20px 10px 10px 10px;
}
legend, label
#filter-form legend, #filter-form label
{
color: #666666;
}
@ -410,3 +410,20 @@ body.iframe.mail #filter-form
{
padding: 10px 5px 5px 5px;
}
#vacationform .listarea {
max-height: 83px;
}
#vacationform .listelement,
#vacationform .listelement .reset {
height: 20px;
}
#vacationform .listelement .reset {
background-position: -1px 2px;
}
#vacationform .listelement input {
vertical-align: top;
}

@ -3,7 +3,6 @@
<head>
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
<link rel="stylesheet" type="text/css" href="/this/managesieve.css" />
</head>
<body class="iframe<roundcube:exp expression="env:task != 'mail' ? '' : ' mail'" />">

@ -3,7 +3,6 @@
<head>
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
<link rel="stylesheet" type="text/css" href="/this/managesieve.css" />
<script type="text/javascript" src="/functions.js"></script>
<script type="text/javascript" src="/splitter.js"></script>

@ -3,7 +3,6 @@
<head>
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
<link rel="stylesheet" type="text/css" href="/this/managesieve.css" />
</head>
<body class="iframe">

@ -0,0 +1,31 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
<script type="text/javascript" src="/functions.js"></script>
</head>
<body>
<roundcube:include file="/includes/taskbar.html" />
<roundcube:include file="/includes/header.html" />
<roundcube:include file="/includes/settingstabs.html" />
<div id="mainscreen">
<div class="box" style="height: 100%; overflow: auto">
<div id="prefs-title" class="boxtitle"><roundcube:label name="managesieve.vacation" /></div>
<roundcube:object name="vacationform" id="vacationform" style="margin: 10px 10px 0 10px" />
<div id="formfooter" style="padding: 0 10px">
<div class="footerleft">
<roundcube:button command="save" type="input" class="button mainaction" label="save" />
</div>
</div>
</div>
</div>
<script type="text/javascript">
rcube_init_mail_ui();
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

@ -89,7 +89,7 @@ body.iframe
padding: 20px 10px 10px 10px;
}
legend, label
#filter-form legend, #filter-form label
{
color: #666666;
}
@ -124,7 +124,7 @@ div.rulerow table, div.actionrow table
min-width: 600px;
}
td
#filter-form td
{
vertical-align: top;
}
@ -414,3 +414,39 @@ body.iframe.mail #filter-form
{
padding: 10px 5px 5px 5px;
}
/* vacation form */
#settings-sections span.vacation a {
background: url(images/vacation_icons.png) no-repeat 7px 1px;
}
#settings-sections span.vacation.selected a {
background-position: 7px -23px;
}
#managesieve-vacation {
position: absolute;
top: 0;
left: 212px;
right: 0;
bottom: 0;
overflow: auto;
}
#vacationform .listarea {
max-height: 83px;
}
#vacationform .listelement,
#vacationform .listelement .reset {
height: 27px;
}
#vacationform .listelement .reset {
background-position: -1px 5px;
}
#vacationform .listelement input {
vertical-align: top;
}

@ -3,7 +3,6 @@
<head>
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
<link rel="stylesheet" type="text/css" href="/this/managesieve.css" />
</head>
<body class="iframe<roundcube:exp expression="env:task != 'mail' ? ' floatingbuttons' : ' mail'" />">

@ -3,7 +3,6 @@
<head>
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
<link rel="stylesheet" type="text/css" href="/this/managesieve.css" />
</head>
<body class="noscroll">

@ -3,7 +3,6 @@
<head>
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
<link rel="stylesheet" type="text/css" href="/this/managesieve.css" />
</head>
<body class="iframe floatingbuttons">

@ -0,0 +1,30 @@
<roundcube:object name="doctype" value="html5" />
<html>
<head>
<title><roundcube:object name="pagetitle" /></title>
<roundcube:include file="/includes/links.html" />
</head>
<body class="noscroll">
<roundcube:include file="/includes/header.html" />
<div id="mainscreen" class="offset">
<roundcube:include file="/includes/settingstabs.html" />
<div id="managesieve-vacation" class="uibox contentbox">
<div>
<h2 class="boxtitle"><roundcube:label name="managesieve.vacation" /></h2>
<roundcube:object name="vacationform" id="vacationform" class="propform boxcontent tabbed" />
</div>
<div class="footerleft formbuttons">
<roundcube:button command="plugin.managesieve-save" type="input" class="button mainaction" label="save" />
</div>
</div>
</div>
<roundcube:include file="/includes/footer.html" />
</body>
</html>
Loading…
Cancel
Save