Page MenuHomePhorge

No OneTemporary

Size
70 KB
Referenced Files
None
Subscribers
None
diff --git a/plugins/managesieve/Changelog b/plugins/managesieve/Changelog
index 334699c34..01afe6906 100644
--- a/plugins/managesieve/Changelog
+++ b/plugins/managesieve/Changelog
@@ -1,313 +1,314 @@
- Fix missing css/js scripts in filter form in mail task
- Fix default vacation status (#1490019)
+- Make possible to set vacation start/end date and time
* version 8.0 [2014-07-16]
-----------------------------------------------------------
- Fix bug where non-existing (or unsubscribed) folder wasn't listed in folder selector (#1489956)
- Added optional separate interface for out-of-office management (#1488266)
- Fix disabled "create filter" action
- Fix enotify/notify extension handling
- Improved UI accessibility
- Added option to specify connection socket parameters - managesieve_conn_options
- Support vacation date rules without date extension (#1489978)
* version 7.2 [2014-02-14]
-----------------------------------------------------------
- Nicely handle server-side modification of script names (#1489412)
- Add Filters tab/section using plugin API hook
- Fix issue where folder selector wasn't visible on new filter form
- Fix issue where multi-select fields were not visible in new filter action rows (#1489600)
- Fix issue in displaying filter form when managesieve_kolab_master=true
and sieve variables extension is supported by the server (#1489599)
- Fix wrong action folder selection if managesieve_domains is not empty (#1489617)
- Fix filter creation from an email when preview frame is disabled (#1489647)
* version 7.1 [2013-11-22]
-----------------------------------------------------------
- lib/Net_Sieve.php moved to Roundcube /lib directory
- Added managesieve_domains option to limit redirect destinations
- Fix bug where at least one additional address of vacation message was required (#1489345)
- Fix so i;ascii-numeric comparator is not forced as default for :count and :value operators
- Fix date/currentdate related form issues and comparators handling (#1489346)
- Fix a bug where deleted filter was not removed from the list
* version 7.0 [2013-09-09]
-----------------------------------------------------------
- Add vacation-seconds extension support (RFC 6131)
- Several script parser code improvements
- Support string list arguments in filter form (#1489018)
- Support date, currendate and index tests - RFC5260 (#1488120)
- Split plugin file into two files
- Fix handling of &, <, > characters in scripts/filter names (#1489208)
- Support 'keep' action (#1489226)
- Add common headers to header selector (#1489271)
* version 6.2 [2013-02-17]
-----------------------------------------------------------
- Support tls:// prefix in managesieve_host option
- Removed depracated functions usage
- Don't trim whitespace in folder names (#1488955)
* version 6.1 [2012-12-21]
-----------------------------------------------------------
- Fixed filter activation/deactivation confirmation message (#1488765)
- Moved rcube_* classes to <plugin>/lib/Roundcube for compat. with Roundcube Framework autoloader
- Fixed filter selection after filter deletion (#1488832)
- Fixed compatibility with jQueryUI-1.9
- Don't force 'stop' action on last rule in a script
* version 6.0 [2012-10-03]
-----------------------------------------------------------
- Fixed issue with DBMail bug [http://pear.php.net/bugs/bug.php?id=19077] (#1488594)
- Added support for enotify/notify (RFC5435, RFC5436, draft-ietf-sieve-notify-00)
- Change default port to 4190 (IANA-allocated), add port auto-detection (#1488713)
- Added request size limits detection and script corruption prevention (#1488648)
- Fix so scripts listed in managesieve_filename_exceptions aren't displayed on the list (#1488724)
* version 5.2 [2012-07-24]
-----------------------------------------------------------
- Added GUI for variables setting - RFC5229 (patch from Paweł Słowik)
- Fixed scrollbars in Larry's iframes
- Fix performance issue in message_headers_output hook handling
* version 5.1 [2012-06-21]
-----------------------------------------------------------
- Fixed filter popup width (for non-english localizations)
- Fixed tokenizer infinite loop on invalid script content
- Larry skin support
- Fixed custom header name validity check, made RFC2822-compliant
* version 5.0 [2012-01-05]
-----------------------------------------------------------
- Fixed setting test type to :is when none is specified
- Fixed javascript error in IE8
- Fixed possible ID duplication when adding filter rules very fast (#1488288)
- Fixed bug where drag layer wasn't removed when dragging was ended over sets list
* version 5.0-rc1 [2011-11-17]
-----------------------------------------------------------
- Fixed sorting of scripts, scripts including aware of the sort order
- Fixed import of rules with unsupported tests
- Added 'address' and 'envelope' tests support
- Added 'body' extension support (RFC5173)
- Added 'subaddress' extension support (RFC5233)
- Added comparators support
- Changed Sender/Recipient labels to From/To
- Fixed importing rule names from Ingo
- Fixed handling of extensions disabled in config
* version 5.0-beta [2011-10-17]
-----------------------------------------------------------
- Added possibility to create a filter based on selected message "in-place"
- Fixed import from Horde-INGO (#1488064)
- Add managesieve_script_name option for default name of the script (#1487956)
- Fixed handling of enabled magic_quotes_gpc setting
- Fixed PHP warning on connection error when submitting filter form
- Fixed bug where new action row with flags wasn't handled properly
- Added managesieve_connect hook for plugins
- Fixed doubled Filter tab on page refresh
- Added filters set selector in filter form when invoked in mail task
- Improved script parser, added support for include and variables extensions
- Added Kolab's KEP:14 support (http://wiki.kolab.org/User:Greve/Drafts/KEP:14)
- Use smaller action/rule buttons
- UI redesign: added possibility to move filter to any place using drag&drop
(instead of up/down buttons), added filter sets list object, added more
'loading' messages
- Added option to hide some scripts (managesieve_filename_exceptions)
* version 4.3 [2011-07-28]
-----------------------------------------------------------
- Fixed handling of error in Net_Sieve::listScripts()
- Fixed handling of REFERRAL responses (http://pear.php.net/bugs/bug.php?id=17107)
- Fixed bug where wrong folders hierarchy was displayed on folders listing
* version 4.2 [2011-05-24]
-----------------------------------------------------------
- Moved elsif replacement code to handle only imports from other formats
- Fixed mod_mailbox() usage for newer Roundcube versions
- Fixed regex extension (error: regex require missing)
* version 4.1 [2011-03-07]
-----------------------------------------------------------
- Fix fileinto target is always INBOX (#1487776)
- Fix escaping of backslash character in quoted strings (#1487780)
- Fix handling of non-safe characters (double-quote, backslash)
or UTF-8 characters (dovecot's implementation bug workaround)
in script names
- Fix saving of a script using flags extension on servers with imap4flags support (#1487825)
* version 4.0 [2011-02-10]
-----------------------------------------------------------
- Fix STARTTLS for timsieved < 2.3.10
- Added :regex and :matches support (#1487746)
- Added setflag/addflag/removeflag support (#1487449)
- Added support for vacation :subject field (#1487120)
- rcube_sieve_script class moved to separate file
- Moved javascript code from skin templates into managesieve.js file
* version 3.0 [2011-02-01]
-----------------------------------------------------------
- Added support for SASL proxy authentication (#1486691)
- Fixed parsing of scripts with \r\n line separator
- Apply forgotten changes for form errors handling
- Fix multi-line strings parsing (#1487685)
- Added tests for script parser
- Rewritten script parser
- Fix double request when clicking on Filters tab using Firefox
* version 2.10 [2010-10-10]
-----------------------------------------------------------
- Fixed import from Avelsieve
- Use localized size units (#1486976)
- Added support for relational operators and i;ascii-numeric comparator
- Added popups with form errors
* version 2.9 [2010-08-02]
-----------------------------------------------------------
- Fixed vacation parameters parsing (#1486883)
* version 2.8 [2010-07-08]
-----------------------------------------------------------
- Added managesieve_auth_type option (#1486731)
* version 2.7 [2010-07-06]
-----------------------------------------------------------
- Update Net_Sieve to version 1.3.0 (fixes LOGIN athentication)
- Added support for copying and copy sending of messages (COPY extension)
* version 2.6 [2010-06-03]
-----------------------------------------------------------
- Support %n and %d variables in managesieve_host option
* version 2.5 [2010-05-04]
-----------------------------------------------------------
- Fix filters set label after activation
- Fix filters set activation, add possibility to deactivate sets (#1486699)
- Fix download button state when sets list is empty
- Fix errors when sets list is empty
* version 2.4 [2010-04-01]
-----------------------------------------------------------
- Fixed bug in DIGEST-MD5 authentication (http://pear.php.net/bugs/bug.php?id=17285)
- Fixed disabling rules with many tests
- Small css unification with core
- Scripts import/export
* version 2.3 [2010-03-18]
-----------------------------------------------------------
- Added import from Horde-INGO
- Support for more than one match using if+stop instead of if+elsif structures (#1486078)
- Support for selectively disabling rules within a single sieve script (#1485882)
- Added vertical splitter
* version 2.2 [2010-02-06]
-----------------------------------------------------------
- Fix handling of "<>" characters in filter names (#1486477)
* version 2.1 [2010-01-12]
-----------------------------------------------------------
- Fix "require" structure generation when many modules are used
- Fix problem with '<' and '>' characters in header tests
* version 2.0 [2009-11-02]
-----------------------------------------------------------
- Added 'managesieve_debug' option
- Added multi-script support
- Small css improvements + sprite image buttons
- PEAR::NetSieve 1.2.0b1
* version 1.7 [2009-09-20]
-----------------------------------------------------------
- Support multiple managesieve hosts using %h variable
in managesieve_host option
- Fix first rule deleting (#1486140)
* version 1.6 [2009-09-08]
-----------------------------------------------------------
- Fix warning when importing squirrelmail rules
- Fix handling of "true" as "anyof (true)" test
* version 1.5 [2009-09-04]
-----------------------------------------------------------
- Added es_ES, ua_UA localizations
- Added 'managesieve_mbox_encoding' option
* version 1.4 [2009-07-29]
-----------------------------------------------------------
- Updated PEAR::Net_Sieve to 1.1.7
* version 1.3 [2009-07-24]
-----------------------------------------------------------
- support more languages
- support config.inc.php file
* version 1.2 [2009-06-28]
-----------------------------------------------------------
- Support IMAP namespaces in fileinto (#1485943)
- Added it_IT localization
* version 1.1 [2009-05-27]
-----------------------------------------------------------
- Added new icons
- Added support for headers lists (coma-separated) in rules
- Added de_CH localization
* version 1.0 [2009-05-21]
-----------------------------------------------------------
- Rewritten using plugin API
- Added hu_HU localization (Tamas Tevesz)
* version beta7 (svn-r2300) [2009-03-01]
-----------------------------------------------------------
- Added SquirrelMail script auto-import (Jonathan Ernst)
- Added 'vacation' support (Jonathan Ernst & alec)
- Added 'stop' support (Jonathan Ernst)
- Added option for extensions disabling (Jonathan Ernst & alec)
- Added fi_FI, nl_NL, bg_BG localization
- Small style fixes
* version 0.2-stable1 (svn-r2205) [2009-01-03]
-----------------------------------------------------------
- Fix moving down filter row
- Fixes for compressed js files in stable release package
- Created patch for svn version r2205
* version 0.2-stable [2008-12-31]
-----------------------------------------------------------
- Added ru_RU, fr_FR, zh_CN translation
- Fixes for Roundcube 0.2-stable
* version 0.2-beta [2008-09-21]
-----------------------------------------------------------
- Small css fixes for IE
- Fixes for Roundcube 0.2-beta
* version beta6 [2008-08-08]
-----------------------------------------------------------
- Added de_DE translation
- Fix for Roundcube r1634
* version beta5 [2008-06-10]
-----------------------------------------------------------
- Fixed 'exists' operators
- Fixed 'not*' operators for custom headers
- Fixed filters deleting
* version beta4 [2008-06-09]
-----------------------------------------------------------
- Fix for Roundcube r1490
* version beta3 [2008-05-22]
-----------------------------------------------------------
- Fixed textarea error class setting
- Added pagetitle setting
- Added option 'managesieve_replace_delimiter'
- Fixed errors on IE (still need some css fixes)
* version beta2 [2008-05-20]
-----------------------------------------------------------
- Use 'if' only for first filter and 'elsif' for the rest
* version beta1 [2008-05-15]
-----------------------------------------------------------
- Initial version for Roundcube r1388.
diff --git a/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php b/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php
index 1c3181706..af028e0ae 100644
--- a/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php
+++ b/plugins/managesieve/lib/Roundcube/rcube_sieve_vacation.php
@@ -1,463 +1,504 @@
<?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') {
foreach ($rule['actions'] as $act) {
if ($act['type'] == 'discard' || $act['type'] == 'keep') {
$action = $act['type'];
}
else if ($act['type'] == 'redirect') {
$action = $act['copy'] ? 'copy' : 'redirect';
$target = $act['target'];
}
}
$this->vacation = array_merge($rule['actions'][0], array(
'idx' => $idx,
'disabled' => $rule['disabled'],
'name' => $rule['name'],
'tests' => $rule['tests'],
'action' => $action ?: 'keep',
'target' => $target,
));
}
else {
$list[$idx] = $rule['name'];
}
}
$this->vacation['list'] = $list;
}
private function vacation_post()
{
if (empty($_POST)) {
return;
}
$date_extension = in_array('date', $this->exts);
$regex_extension = in_array('regex', $this->exts);
+ // set user's timezone
+ try {
+ $timezone = new DateTimeZone($this->rc->config->get('timezone', 'GMT'));
+ }
+ catch (Exception $e) {
+ $timezone = new DateTimeZone('GMT');
+ }
+
$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);
+ $time_from = rcube_utils::get_input_value('vacation_timefrom', rcube_utils::INPUT_POST);
+ $time_to = rcube_utils::get_input_value('vacation_timeto', rcube_utils::INPUT_POST);
$after = rcube_utils::get_input_value('vacation_after', rcube_utils::INPUT_POST);
$action = rcube_utils::get_input_value('vacation_action', rcube_utils::INPUT_POST);
$target = rcube_utils::get_input_value('action_target', rcube_utils::INPUT_POST, true);
$target_domain = rcube_utils::get_input_value('action_domain', 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.emptyvacationbody';
}
if ($vacation_action[$interval_type] && !preg_match('/^[0-9]+$/', $vacation_action[$interval_type])) {
$error = 'managesieve.forbiddenchars';
}
// find and remove existing date/regex/true rules
foreach ((array) $vacation_tests as $idx => $t) {
- if (($t['test'] == 'currentdate' && $t['part'] == 'date' && $t['type'] == $type)
+ if ($t['test'] == 'currentdate' || $t['test'] == 'true'
|| ($t['test'] == 'header' && $t['type'] == 'regex' && $t['arg1'] == 'received')
- || ($t['test'] == 'true')
) {
unset($vacation_tests[$idx]);
}
}
if ($date_extension) {
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(
+ $time = ${str_replace('date', 'time', $var)};
+ $date = trim($$var . ' ' . $time);
+
+ if ($date && ($dt = rcube_utils::anytodatetime($date, $timezone))) {
+ $vacation_tests[] = array(
'test' => 'currentdate',
'part' => 'date',
- 'type' => $type,
+ 'type' => 'value-' . ($var == 'date_from' ? 'ge' : 'le'),
+ 'zone' => $dt->format('O'),
'arg' => $dt->format('Y-m-d'),
);
-
- $vacation_tests[] = $test;
+ if ($time) {
+ $vacation_tests[] = array(
+ 'test' => 'currentdate',
+ 'part' => 'time',
+ 'type' => 'value-' . ($var == 'date_from' ? 'ge' : 'le'),
+ 'zone' => $dt->format('O'),
+ 'arg' => $dt->format('H:i:s'),
+ );
+ }
}
}
}
else if ($regex_extension) {
// Add date range rules if range specified
if ($date_from && $date_to) {
if ($tests = self::build_regexp_tests($date_from, $date_to, $error)) {
$vacation_tests = array_merge($vacation_tests, $tests);
}
}
}
if ($action == 'redirect' || $action == 'copy') {
if ($target_domain) {
$target .= '@' . $target_domain;
}
if (empty($target) || !rcube_utils::check_email($target)) {
$error = 'noemailwarning';
}
}
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['tests'] = $vacation_tests;
$rule['join'] = $date_extension ? count($vacation_tests) > 1 : false;
$rule['actions'] = array($vacation_action);
if ($action && $action != 'keep') {
$rule['actions'][] = array(
'type' => $action == 'discard' ? 'discard' : 'redirect',
'copy' => $action == 'copy',
'target' => $action != 'discard' ? $target : '',
);
}
// 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);
$regex_extension = in_array('regex', $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', 'id' => 'vacation_subject', 'size' => 50));
$reason = new html_textarea(array('name' => 'vacation_reason', 'id' => 'vacation_reason', 'cols' => 60, 'rows' => 8));
$interval = new html_inputfield(array('name' => 'vacation_interval', 'id' => 'vacation_interval', 'size' => 5));
$addresses = '<textarea name="vacation_addresses" id="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', 'id' => 'vacation_status'));
$action = new html_select(array('name' => 'vacation_action', 'id' => 'vacation_action', 'onchange' => 'vacation_action_select()'));
$status->add($this->plugin->gettext('vacation.on'), 'on');
$status->add($this->plugin->gettext('vacation.off'), 'off');
$action->add($this->plugin->gettext('vacation.keep'), 'keep');
$action->add($this->plugin->gettext('vacation.discard'), 'discard');
$action->add($this->plugin->gettext('vacation.redirect'), 'redirect');
if (in_array('copy', $this->exts)) {
$action->add($this->plugin->gettext('vacation.copy'), 'copy');
}
if ($this->rc->config->get('managesieve_vacation') != 2 && count($this->vacation['list'])) {
$after = new html_select(array('name' => 'vacation_after', 'id' => '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 || $regex_extension) {
$date_from = new html_inputfield(array('name' => 'vacation_datefrom', 'id' => 'vacation_datefrom', 'class' => 'datepicker', 'size' => 12));
- $date_to = new html_inputfield(array('name' => 'vacation_dateto', 'class' => 'datepicker', 'size' => 12));
+ $date_to = new html_inputfield(array('name' => 'vacation_dateto', 'id' => 'vacation_dateto', 'class' => 'datepicker', 'size' => 12));
$date_format = $this->rc->config->get('date_format', 'Y-m-d');
}
if ($date_extension) {
+ $time_from = new html_inputfield(array('name' => 'vacation_timefrom', 'id' => 'vacation_timefrom', 'size' => 6));
+ $time_to = new html_inputfield(array('name' => 'vacation_timeto', 'id' => 'vacation_timeto', 'size' => 6));
+ $time_format = $this->rc->config->get('time_format', 'H:i');
+ $date_value = array();
+
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;
+ if ($test['test'] == 'currentdate' && ($test['part'] == 'date' || $test['part'] == 'time')) {
+ $idx = $test['type'] == 'value-ge' ? 'from' : 'to';
+ $date_value[$idx][$test['part']] = $test['arg'];
+ if ($test['zone']) {
+ $date_value[$idx]['zone'] = $test['zone'];
+ }
+ }
+ }
+
+ foreach ($date_value as $idx => $value) {
+ $date = $value['date'] . ' '
+ . ($value['time'] ? $value['time'] : ($idx == 'from' ? '00:00:00' : '23:59:59'))
+ . ($value['zone'] ? ' ' . $value['zone'] : '');
+
+ $date_value[$idx] = $this->rc->format_date($date, $date_format, !empty($value['time']) && !empty($value['zone']));
+
+ if (!empty($value['time'])) {
+ $date_value['time_' . $idx] = $this->rc->format_date($date, $time_format, !empty($value['zone']));
}
}
}
else if ($regex_extension) {
// Sieve 'date' extension not available, read start/end from RegEx based rules instead
if ($date_tests = self::parse_regexp_tests($this->vacation['tests'])) {
$date_value['from'] = $this->rc->format_date($date_tests['from'], $date_format, false);
$date_value['to'] = $this->rc->format_date($date_tests['to'], $date_format, false);
}
}
// force domain selection in redirect email input
$domains = (array) $this->rc->config->get('managesieve_domains');
$redirect = $this->vacation['action'] == 'redirect' || $this->vacation['action'] == 'copy';
if (!empty($domains)) {
sort($domains);
$domain_select = new html_select(array('name' => 'action_domain', 'id' => 'action_domain'));
$domain_select->add(array_combine($domains, $domains));
if ($redirect && $this->vacation['target']) {
$parts = explode('@', $this->vacation['target']);
if (!empty($parts)) {
$this->vacation['domain'] = array_pop($parts);
$this->vacation['target'] = implode('@', $parts);
}
}
}
// redirect target
$action_target = ' <span id="action_target_span" style="display:' . ($redirect ? 'inline' : 'none') . '">'
. '<input type="text" name="action_target" id="action_target"'
. ' value="' .($redirect ? rcube::Q($this->vacation['target'], 'strict', false) : '') . '"'
. (!empty($domains) ? ' size="20"' : ' size="35"') . '/>'
. (!empty($domains) ? ' @ ' . $domain_select->show($this->vacation['domain']) : '')
. '</span>';
// 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 || $regex_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_datefrom', $this->plugin->gettext('vacation.start')));
+ $table->add(null, $date_from->show($date_value['from']) . ($time_from ? ' ' . $time_from->show($date_value['time_from']) : ''));
+ $table->add('title', html::label('vacation_dateto', $this->plugin->gettext('vacation.end')));
+ $table->add(null, $date_to->show($date_value['to']) . ($time_to ? ' ' . $time_to->show($date_value['time_to']) : ''));
}
$table->add('title', html::label('vacation_status', $this->plugin->gettext('vacation.status')));
$table->add(null, $status->show(!isset($this->vacation['disabled']) || $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', html::label('vacation_addresses', $this->plugin->gettext('vacation.addresses')));
$table->add(null, $addresses);
$table->add('title', html::label('vacation_interval', $this->plugin->gettext('vacation.interval')));
$table->add(null, $interval_txt);
if ($after) {
$table->add('title', html::label('vacation_after', $this->plugin->gettext('vacation.after')));
$table->add(null, $after->show($this->vacation['idx'] - 1));
}
$table->add('title', html::label('vacation_action', $this->plugin->gettext('vacation.action')));
$table->add('vacation', $action->show($this->vacation['action']) . $action_target);
$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);
+ if ($time_format) {
+ $this->rc->output->set_env('time_format', $time_format);
+ }
+
return $out;
}
public static function build_regexp_tests($date_from, $date_to, &$error)
{
$tests = array();
$dt_from = rcube_utils::anytodatetime($date_from);
$dt_to = rcube_utils::anytodatetime($date_to);
$interval = $dt_from->diff($dt_to);
if ($interval->invert || $interval->days > 365) {
$error = 'managesieve.invaliddateformat';
return;
}
$dt_i = $dt_from;
$interval = new DateInterval('P1D');
$matchexp = '';
while (!$dt_i->diff($dt_to)->invert) {
$days = (int) $dt_i->format('d');
$matchexp .= $days < 10 ? "[ 0]$days" : $days;
if ($days == $dt_i->format('t') || $dt_i->diff($dt_to)->days == 0) {
$test = array(
'test' => 'header',
'type' => 'regex',
'arg1' => 'received',
'arg2' => '('.$matchexp.') '.$dt_i->format('M Y')
);
$tests[] = $test;
$matchexp = '';
}
else {
$matchexp .= '|';
}
$dt_i->add($interval);
}
return $tests;
}
public static function parse_regexp_tests($tests)
{
$rx_from = '/^\(([0-9]{2}).*\)\s([A-Za-z]+)\s([0-9]{4})/';
$rx_to = '/^\(.*([0-9]{2})\)\s([A-Za-z]+)\s([0-9]{4})/';
$result = array();
foreach ((array) $tests as $test) {
if ($test['test'] == 'header' && $test['type'] == 'regex' && $test['arg1'] == 'received') {
$textexp = preg_replace('/\[ ([^\]]*)\]/', '0', $test['arg2']);
if (!$result['from'] && preg_match($rx_from, $textexp, $matches)) {
$result['from'] = $matches[1]." ".$matches[2]." ".$matches[3];
}
if (preg_match($rx_to, $textexp, $matches)) {
$result['to'] = $matches[1]." ".$matches[2]." ".$matches[3];
}
}
}
return $result;
}
}
diff --git a/plugins/managesieve/managesieve.js b/plugins/managesieve/managesieve.js
index 5e14431fe..cd0d5f3ca 100644
--- a/plugins/managesieve/managesieve.js
+++ b/plugins/managesieve/managesieve.js
@@ -1,961 +1,1028 @@
/**
* (Manage)Sieve Filters plugin
*
* @licstart The following is the entire license notice for the
* JavaScript code in this file.
*
* Copyright (c) 2012-2014, The Roundcube Dev Team
*
* The JavaScript code in this page 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.
*
* @licend The above is the entire license notice
* for the JavaScript code in this file.
*/
if (window.rcmail) {
rcmail.addEventListener('init', function(evt) {
// add managesieve-create command to message_commands array,
// so it's state will be updated on message selection/unselection
if (rcmail.env.task == 'mail') {
if (rcmail.env.action != 'show')
rcmail.env.message_commands.push('managesieve-create');
else
rcmail.enable_command('managesieve-create', true);
}
if (rcmail.env.task == 'mail' || rcmail.env.action.startsWith('plugin.managesieve')) {
// Create layer for form tips
if (!rcmail.env.framed) {
rcmail.env.ms_tip_layer = $('<div id="managesieve-tip" class="popupmenu"></div>');
rcmail.env.ms_tip_layer.appendTo(document.body);
}
}
// register commands
rcmail.register_command('plugin.managesieve-save', function() { rcmail.managesieve_save() });
rcmail.register_command('plugin.managesieve-act', function() { rcmail.managesieve_act() });
rcmail.register_command('plugin.managesieve-add', function() { rcmail.managesieve_add() });
rcmail.register_command('plugin.managesieve-del', function() { rcmail.managesieve_del() });
rcmail.register_command('plugin.managesieve-move', function() { rcmail.managesieve_move() });
rcmail.register_command('plugin.managesieve-setadd', function() { rcmail.managesieve_setadd() });
rcmail.register_command('plugin.managesieve-setdel', function() { rcmail.managesieve_setdel() });
rcmail.register_command('plugin.managesieve-setact', function() { rcmail.managesieve_setact() });
rcmail.register_command('plugin.managesieve-setget', function() { rcmail.managesieve_setget() });
if (rcmail.env.action.startsWith('plugin.managesieve')) {
if (rcmail.gui_objects.sieveform) {
rcmail.enable_command('plugin.managesieve-save', true);
-
- // small resize for header element
- $('select[name="_header[]"]', rcmail.gui_objects.sieveform).each(function() {
- if (this.value == '...') this.style.width = '40px';
- });
-
- // resize dialog window
- if (rcmail.env.action == 'plugin.managesieve' && rcmail.env.task == 'mail') {
- parent.rcmail.managesieve_dialog_resize(rcmail.gui_objects.sieveform);
- }
-
- $('input[type="text"]:first', rcmail.gui_objects.sieveform).focus();
-
- // initialize smart list inputs
- $('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();
- }
+ sieve_form_init();
}
else {
rcmail.enable_command('plugin.managesieve-add', 'plugin.managesieve-setadd', !rcmail.env.sieveconnerror);
}
var setcnt, set = rcmail.env.currentset;
if (rcmail.gui_objects.filterslist) {
rcmail.filters_list = new rcube_list_widget(rcmail.gui_objects.filterslist,
{multiselect:false, draggable:true, keyboard:true});
rcmail.filters_list
.addEventListener('select', function(e) { rcmail.managesieve_select(e); })
.addEventListener('dragstart', function(e) { rcmail.managesieve_dragstart(e); })
.addEventListener('dragend', function(e) { rcmail.managesieve_dragend(e); })
.addEventListener('initrow', function(row) {
row.obj.onmouseover = function() { rcmail.managesieve_focus_filter(row); };
row.obj.onmouseout = function() { rcmail.managesieve_unfocus_filter(row); };
})
.init();
}
if (rcmail.gui_objects.filtersetslist) {
rcmail.filtersets_list = new rcube_list_widget(rcmail.gui_objects.filtersetslist,
{multiselect:false, draggable:false, keyboard:true});
rcmail.filtersets_list.init().focus();
if (set != null) {
set = rcmail.managesieve_setid(set);
rcmail.filtersets_list.select(set);
}
// attach select event after initial record was selected
rcmail.filtersets_list.addEventListener('select', function(e) { rcmail.managesieve_setselect(e); });
setcnt = rcmail.filtersets_list.rowcount;
rcmail.enable_command('plugin.managesieve-set', true);
rcmail.enable_command('plugin.managesieve-setact', 'plugin.managesieve-setget', setcnt);
rcmail.enable_command('plugin.managesieve-setdel', setcnt > 1);
// Fix dragging filters over sets list
$('tr', rcmail.gui_objects.filtersetslist).each(function (i, e) { rcmail.managesieve_fixdragend(e); });
}
}
if (rcmail.gui_objects.sieveform && rcmail.env.rule_disabled)
$('#disabled').attr('checked', true);
});
};
/*********************************************************/
/********* Managesieve UI methods *********/
/*********************************************************/
rcube_webmail.prototype.managesieve_add = function()
{
this.load_managesieveframe();
this.filters_list.clear_selection();
};
rcube_webmail.prototype.managesieve_del = function()
{
var id = this.filters_list.get_single_selection();
if (confirm(this.get_label('managesieve.filterdeleteconfirm'))) {
var lock = this.set_busy(true, 'loading');
this.http_post('plugin.managesieve-action',
'_act=delete&_fid='+this.filters_list.rows[id].uid, lock);
}
};
rcube_webmail.prototype.managesieve_act = function()
{
var id = this.filters_list.get_single_selection(),
lock = this.set_busy(true, 'loading');
this.http_post('plugin.managesieve-action',
'_act=act&_fid='+this.filters_list.rows[id].uid, lock);
};
// Filter selection
rcube_webmail.prototype.managesieve_select = function(list)
{
var id = list.get_single_selection();
if (id != null)
this.load_managesieveframe(list.rows[id].uid);
};
// Set selection
rcube_webmail.prototype.managesieve_setselect = function(list)
{
this.show_contentframe(false);
this.filters_list.clear(true);
this.enable_command('plugin.managesieve-setdel', list.rowcount > 1);
this.enable_command('plugin.managesieve-setact', 'plugin.managesieve-setget', true);
var id = list.get_single_selection();
if (id != null)
this.managesieve_list(this.env.filtersets[id]);
};
rcube_webmail.prototype.managesieve_rowid = function(id)
{
var i, rows = this.filters_list.rows;
for (i in rows)
if (rows[i] != null && rows[i].uid == id)
return i;
};
// Returns set's identifier
rcube_webmail.prototype.managesieve_setid = function(name)
{
for (var i in this.env.filtersets)
if (this.env.filtersets[i] == name)
return i;
};
// Filters listing request
rcube_webmail.prototype.managesieve_list = function(script)
{
var lock = this.set_busy(true, 'loading');
this.http_post('plugin.managesieve-action', '_act=list&_set='+urlencode(script), lock);
};
// Script download request
rcube_webmail.prototype.managesieve_setget = function()
{
var id = this.filtersets_list.get_single_selection(),
script = this.env.filtersets[id];
location.href = this.env.comm_path+'&_action=plugin.managesieve-action&_act=setget&_set='+urlencode(script);
};
// Set activate/deactivate request
rcube_webmail.prototype.managesieve_setact = function()
{
var id = this.filtersets_list.get_single_selection(),
lock = this.set_busy(true, 'loading'),
script = this.env.filtersets[id],
action = $('#rcmrow'+id).hasClass('disabled') ? 'setact' : 'deact';
this.http_post('plugin.managesieve-action', '_act='+action+'&_set='+urlencode(script), lock);
};
// Set delete request
rcube_webmail.prototype.managesieve_setdel = function()
{
if (!confirm(this.get_label('managesieve.setdeleteconfirm')))
return false;
var id = this.filtersets_list.get_single_selection(),
lock = this.set_busy(true, 'loading'),
script = this.env.filtersets[id];
this.http_post('plugin.managesieve-action', '_act=setdel&_set='+urlencode(script), lock);
};
// Set add request
rcube_webmail.prototype.managesieve_setadd = function()
{
this.filters_list.clear_selection();
this.enable_command('plugin.managesieve-act', 'plugin.managesieve-del', false);
if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) {
var lock = this.set_busy(true, 'loading');
target = window.frames[this.env.contentframe];
target.location.href = this.env.comm_path+'&_action=plugin.managesieve-action&_framed=1&_newset=1&_unlock='+lock;
}
};
rcube_webmail.prototype.managesieve_updatelist = function(action, o)
{
this.set_busy(true);
switch (action) {
// Delete filter row
case 'del':
var id = o.id, list = this.filters_list;
list.remove_row(this.managesieve_rowid(o.id));
list.clear_selection();
this.show_contentframe(false);
this.enable_command('plugin.managesieve-del', 'plugin.managesieve-act', false);
// filter identifiers changed, fix the list
$('tr', this.filters_list.list).each(function() {
// remove hidden (deleted) rows
if (this.style.display == 'none') {
$(this).detach();
return;
}
var rowid = this.id.substr(6);
// remove all attached events
$(this).unbind();
// update row id
if (rowid > id)
$(this).attr('id', 'rcmrow' + (rowid-1));
});
list.init();
break;
// Update filter row
case 'update':
var i, row = $('#rcmrow'+this.managesieve_rowid(o.id));
if (o.name)
$('td', row).text(o.name);
if (o.disabled)
row.addClass('disabled');
else
row.removeClass('disabled');
$('#disabled', $('iframe').contents()).prop('checked', o.disabled);
break;
// Add filter row to the list
case 'add':
var list = this.filters_list,
row = $('<tr><td class="name"></td></tr>');
$('td', row).text(o.name);
row.attr('id', 'rcmrow'+o.id);
if (o.disabled)
row.addClass('disabled');
list.insert_row(row.get(0));
list.highlight_row(o.id);
this.enable_command('plugin.managesieve-del', 'plugin.managesieve-act', true);
break;
// Filling rules list
case 'list':
var i, tr, td, el, list = this.filters_list;
if (o.clear)
list.clear();
for (i in o.list) {
el = o.list[i];
tr = document.createElement('TR');
td = document.createElement('TD');
$(td).text(el.name);
td.className = 'name';
tr.id = 'rcmrow' + el.id;
if (el['class'])
tr.className = el['class'];
tr.appendChild(td);
list.insert_row(tr);
}
if (o.set)
list.highlight_row(o.set);
else
this.enable_command('plugin.managesieve-del', 'plugin.managesieve-act', false);
break;
// Sactivate/deactivate set
case 'setact':
var id = this.managesieve_setid(o.name), row = $('#rcmrow' + id);
if (o.active) {
if (o.all)
$('tr', this.gui_objects.filtersetslist).addClass('disabled');
row.removeClass('disabled');
}
else
row.addClass('disabled');
break;
// Delete set row
case 'setdel':
var id = this.managesieve_setid(o.name);
this.filtersets_list.remove_row(id);
this.filters_list.clear();
this.show_contentframe(false);
this.enable_command('plugin.managesieve-setdel', 'plugin.managesieve-setact', 'plugin.managesieve-setget', false);
delete this.env.filtersets[id];
break;
// Create set row
case 'setadd':
var id = 'S' + new Date().getTime(),
list = this.filtersets_list,
row = $('<tr class="disabled"><td class="name"></td></tr>');
$('td', row).text(o.name);
row.attr('id', 'rcmrow'+id);
this.env.filtersets[id] = o.name;
list.insert_row(row.get(0));
// move row into its position on the list
if (o.index != list.rowcount-1) {
row.detach();
var elem = $('tr:visible', list.list).get(o.index);
row.insertBefore(elem);
}
list.select(id);
// Fix dragging filters over sets list
this.managesieve_fixdragend(row);
break;
}
this.set_busy(false);
};
// load filter frame
rcube_webmail.prototype.load_managesieveframe = function(id)
{
var has_id = typeof(id) != 'undefined' && id != null;
this.enable_command('plugin.managesieve-act', 'plugin.managesieve-del', has_id);
if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) {
target = window.frames[this.env.contentframe];
var msgid = this.set_busy(true, 'loading');
target.location.href = this.env.comm_path+'&_action=plugin.managesieve-action&_framed=1'
+(has_id ? '&_fid='+id : '')+'&_unlock='+msgid;
}
};
// load filter frame
rcube_webmail.prototype.managesieve_dragstart = function(list)
{
var id = this.filters_list.get_single_selection();
this.drag_active = true;
this.drag_filter = id;
};
rcube_webmail.prototype.managesieve_dragend = function(e)
{
if (this.drag_active) {
if (this.drag_filter_target) {
var lock = this.set_busy(true, 'loading');
this.show_contentframe(false);
this.http_post('plugin.managesieve-action', '_act=move&_fid='+this.drag_filter
+'&_to='+this.drag_filter_target, lock);
}
this.drag_active = false;
}
};
// Fixes filters dragging over sets list
// @TODO: to be removed after implementing copying filters
rcube_webmail.prototype.managesieve_fixdragend = function(elem)
{
var p = this;
$(elem).bind('mouseup' + ((bw.iphone || bw.ipad) ? ' touchend' : ''), function(e) {
if (p.drag_active)
p.filters_list.drag_mouse_up(e);
});
};
rcube_webmail.prototype.managesieve_focus_filter = function(row)
{
var id = row.id.replace(/^rcmrow/, '');
if (this.drag_active && id != this.drag_filter) {
this.drag_filter_target = id;
$(row.obj).addClass(id < this.drag_filter ? 'filtermoveup' : 'filtermovedown');
}
};
rcube_webmail.prototype.managesieve_unfocus_filter = function(row)
{
if (this.drag_active) {
$(row.obj).removeClass('filtermoveup filtermovedown');
this.drag_filter_target = null;
}
};
/*********************************************************/
/********* Filter Form methods *********/
/*********************************************************/
// 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)
this.gui_objects.sieveform.elements['_fid'].value = parent.rcmail.filters_list.rows[id].uid;
}
this.gui_objects.sieveform.submit();
};
// Operations on filters form
rcube_webmail.prototype.managesieve_ruleadd = function(id)
{
this.http_post('plugin.managesieve-action', '_act=ruleadd&_rid='+id);
};
rcube_webmail.prototype.managesieve_rulefill = function(content, id, after)
{
if (content != '') {
// create new element
var div = document.getElementById('rules'),
row = document.createElement('div');
this.managesieve_insertrow(div, row, after);
// fill row after inserting (for IE)
row.setAttribute('id', 'rulerow'+id);
row.className = 'rulerow';
row.innerHTML = content;
// initialize smart list inputs
$('textarea[data-type="list"]', row).each(function() {
smart_field_init(this);
});
this.managesieve_formbuttons(div);
}
};
rcube_webmail.prototype.managesieve_ruledel = function(id)
{
if ($('#ruledel'+id).hasClass('disabled'))
return;
if (confirm(this.get_label('managesieve.ruledeleteconfirm'))) {
var row = document.getElementById('rulerow'+id);
row.parentNode.removeChild(row);
this.managesieve_formbuttons(document.getElementById('rules'));
}
};
rcube_webmail.prototype.managesieve_actionadd = function(id)
{
this.http_post('plugin.managesieve-action', '_act=actionadd&_aid='+id);
};
rcube_webmail.prototype.managesieve_actionfill = function(content, id, after)
{
if (content != '') {
var div = document.getElementById('actions'),
row = document.createElement('div');
this.managesieve_insertrow(div, row, after);
// fill row after inserting (for IE)
row.className = 'actionrow';
row.setAttribute('id', 'actionrow'+id);
row.innerHTML = content;
// initialize smart list inputs
$('textarea[data-type="list"]', row).each(function() {
smart_field_init(this);
});
this.managesieve_formbuttons(div);
}
};
rcube_webmail.prototype.managesieve_actiondel = function(id)
{
if ($('#actiondel'+id).hasClass('disabled'))
return;
if (confirm(this.get_label('managesieve.actiondeleteconfirm'))) {
var row = document.getElementById('actionrow'+id);
row.parentNode.removeChild(row);
this.managesieve_formbuttons(document.getElementById('actions'));
}
};
// insert rule/action row in specified place on the list
rcube_webmail.prototype.managesieve_insertrow = function(div, row, after)
{
for (var i=0; i<div.childNodes.length; i++) {
if (div.childNodes[i].id == (div.id == 'rules' ? 'rulerow' : 'actionrow') + after)
break;
}
if (div.childNodes[i+1])
div.insertBefore(row, div.childNodes[i+1]);
else
div.appendChild(row);
};
// update Delete buttons status
rcube_webmail.prototype.managesieve_formbuttons = function(div)
{
var i, button, buttons = [];
// count and get buttons
for (i=0; i<div.childNodes.length; i++) {
if (div.id == 'rules' && div.childNodes[i].id) {
if (/rulerow/.test(div.childNodes[i].id))
buttons.push('ruledel' + div.childNodes[i].id.replace(/rulerow/, ''));
}
else if (div.childNodes[i].id) {
if (/actionrow/.test(div.childNodes[i].id))
buttons.push( 'actiondel' + div.childNodes[i].id.replace(/actionrow/, ''));
}
}
for (i=0; i<buttons.length; i++) {
button = document.getElementById(buttons[i]);
if (i>0 || buttons.length>1) {
$(button).removeClass('disabled');
}
else {
$(button).addClass('disabled');
}
}
};
function rule_header_select(id)
{
var obj = document.getElementById('header' + id),
size = document.getElementById('rule_size' + id),
op = document.getElementById('rule_op' + id),
header = document.getElementById('custom_header' + id + '_list'),
mod = document.getElementById('rule_mod' + id),
trans = document.getElementById('rule_trans' + id),
comp = document.getElementById('rule_comp' + id),
datepart = document.getElementById('rule_date_part' + id),
dateheader = document.getElementById('rule_date_header_div' + id),
h = obj.value;
if (h == 'size') {
size.style.display = 'inline';
$.each([op, header, mod, trans, comp], function() { this.style.display = 'none'; });
}
else {
header.style.display = h != '...' ? 'none' : 'inline-block';
size.style.display = 'none';
op.style.display = 'inline';
comp.style.display = '';
mod.style.display = h == 'body' || h == 'currentdate' || h == 'date' ? 'none' : 'block';
trans.style.display = h == 'body' ? 'block' : 'none';
}
if (datepart)
datepart.style.display = h == 'currentdate' || h == 'date' ? 'inline' : 'none';
if (dateheader)
dateheader.style.display = h == 'date' ? '' : 'none';
rule_op_select(op, id, h);
rule_mod_select(id, h);
obj.style.width = h == '...' ? '40px' : '';
};
function rule_op_select(obj, id, header)
{
var target = document.getElementById('rule_target' + id + '_list');
if (!header)
header = document.getElementById('header' + id).value;
target.style.display = obj.value == 'exists' || obj.value == 'notexists' || header == 'size' ? 'none' : 'inline-block';
};
function rule_trans_select(id)
{
var obj = document.getElementById('rule_trans_op' + id),
target = document.getElementById('rule_trans_type' + id);
target.style.display = obj.value != 'content' ? 'none' : 'inline';
};
function rule_mod_select(id, header)
{
var obj = document.getElementById('rule_mod_op' + id),
target = document.getElementById('rule_mod_type' + id),
index = document.getElementById('rule_index_div' + id);
if (!header)
header = document.getElementById('header' + id).value;
target.style.display = obj.value != 'address' && obj.value != 'envelope' ? 'none' : 'inline';
if (index)
index.style.display = header != 'body' && header != 'currentdate' && header != 'size' && obj.value != 'envelope' ? '' : 'none';
};
function rule_join_radio(value)
{
$('#rules').css('display', value == 'any' ? 'none' : 'block');
};
function rule_adv_switch(id, elem)
{
var elem = $(elem), enabled = elem.hasClass('hide'), adv = $('#rule_advanced'+id);
if (enabled) {
adv.hide();
elem.removeClass('hide').addClass('show');
}
else {
adv.show();
elem.removeClass('show').addClass('hide');
}
}
function action_type_select(id)
{
var obj = document.getElementById('action_type' + id),
v = obj.value, enabled = {},
elems = {
mailbox: document.getElementById('action_mailbox' + id),
target: document.getElementById('redirect_target' + id),
target_area: document.getElementById('action_target_area' + id),
flags: document.getElementById('action_flags' + id),
vacation: document.getElementById('action_vacation' + id),
set: document.getElementById('action_set' + id),
notify: document.getElementById('action_notify' + id)
};
if (v == 'fileinto' || v == 'fileinto_copy') {
enabled.mailbox = 1;
}
else if (v == 'redirect' || v == 'redirect_copy') {
enabled.target = 1;
}
else if (v.match(/^reject|ereject$/)) {
enabled.target_area = 1;
}
else if (v.match(/^(add|set|remove)flag$/)) {
enabled.flags = 1;
}
else if (v == 'vacation') {
enabled.vacation = 1;
}
else if (v == 'set') {
enabled.set = 1;
}
else if (v == 'notify') {
enabled.notify = 1;
}
for (var x in elems) {
elems[x].style.display = !enabled[x] ? 'none' : 'inline';
}
};
function vacation_action_select()
{
var selected = $('#vacation_action').val();
$('#action_target_span')[selected == 'discard' || selected == 'keep' ? 'hide' : 'show']();
};
// Inititalizes smart list input
function smart_field_init(field)
{
var id = field.id + '_list',
area = $('<span class="listarea"></span>'),
list = field.value ? field.value.split("\n") : [''];
if ($('#'+id).length)
return;
// add input rows
$.each(list, function(i, v) {
area.append(smart_field_row(v, field.name, i, $(field).data('size')));
});
area.attr('id', id);
field = $(field);
if (field.attr('disabled'))
area.hide();
field.after(area);
if (field.hasClass('error')) {
area.addClass('error');
rcmail.managesieve_tip_register([[id, field.data('tip')]]);
}
};
function smart_field_row(value, name, idx, size)
{
// build row element content
var input, content = '<span class="listelement">'
+ '<span class="reset"></span><input type="text"></span>',
elem = $(content),
attrs = {value: value, name: name + '[]'};
if (size)
attrs.size = size;
input = $('input', elem).attr(attrs).keydown(function(e) {
var input = $(this);
// element creation event (on Enter)
if (e.which == 13) {
var name = input.attr('name').replace(/\[\]$/, ''),
dt = (new Date()).getTime(),
elem = smart_field_row('', name, dt, size);
input.parent().after(elem);
$('input', elem).focus();
}
// backspace or delete: remove input, focus previous one
else if ((e.which == 8 || e.which == 46) && input.val() == '') {
var parent = input.parent(), siblings = parent.parent().children();
if (siblings.length > 1) {
if (parent.prev().length)
parent.prev().children('input').focus();
else
parent.next().children('input').focus();
parent.remove();
return false;
}
}
});
// element deletion event
$('span[class="reset"]', elem).click(function() {
var span = $(this.parentNode);
if (span.parent().children().length > 1)
span.remove();
else
$('input', span).val('').focus();
});
return elem;
}
// Register onmouse(leave/enter) events for tips on specified form element
rcube_webmail.prototype.managesieve_tip_register = function(tips)
{
var n, framed = parent.rcmail,
tip = framed ? parent.rcmail.env.ms_tip_layer : rcmail.env.ms_tip_layer;
for (var n in tips) {
$('#'+tips[n][0])
.data('tip', tips[n][1])
.bind('mouseenter', function(e) {
var elem = $(this),
offset = elem.offset(),
left = offset.left,
top = offset.top - 12,
minwidth = elem.width();
if (framed) {
offset = $((rcmail.env.task == 'mail' ? '#sievefilterform > iframe' : '#filter-box'), parent.document).offset();
top += offset.top;
left += offset.left;
}
tip.html(elem.data('tip'));
top -= tip.height();
tip.css({left: left, top: top, minWidth: (minwidth-2) + 'px'}).show();
})
.bind('mouseleave', function(e) { tip.hide(); });
}
};
+// format time string
+function sieve_formattime(hour, minutes)
+{
+ var i, c, h, time = '', format = rcmail.env.time_format || 'H:i';
+
+ for (i=0; i<format.length; i++) {
+ c = format.charAt(i);
+ switch (c) {
+ case 'a': time += hour > 12 ? 'am' : 'pm'; break;
+ case 'A': time += hour > 12 ? 'AM' : 'PM'; break;
+ case 'g':
+ case 'h':
+ h = hour == 0 ? 12 : hour > 12 ? hour - 12 : hour;
+ time += (c == 'h' && hour < 10 ? '0' : '') + hour;
+ break;
+ case 'G': time += hour; break;
+ case 'H': time += (hour < 10 ? '0' : '') + hour; break;
+ case 'i': time += (minutes < 10 ? '0' : '') + minutes; break;
+ case 's': time += '00';
+ default: time += c;
+ }
+ }
+
+ return time;
+}
+
+function sieve_form_init()
+{
+ // small resize for header element
+ $('select[name="_header[]"]', rcmail.gui_objects.sieveform).each(function() {
+ if (this.value == '...') this.style.width = '40px';
+ });
+
+ // resize dialog window
+ if (rcmail.env.action == 'plugin.managesieve' && rcmail.env.task == 'mail') {
+ parent.rcmail.managesieve_dialog_resize(rcmail.gui_objects.sieveform);
+ }
+
+ $('input[type="text"]:first', rcmail.gui_objects.sieveform).focus();
+
+ // initialize smart list inputs
+ $('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();
+ }
+
+ // configure drop-down menu on time input fields based on jquery UI autocomplete
+ $('#vacation_timefrom, #vacation_timeto')
+ .attr('autocomplete', "off")
+ .autocomplete({
+ delay: 100,
+ minLength: 1,
+ source: function(p, callback) {
+ var h, result = [];
+ for (h = 0; h < 24; h++)
+ result.push(sieve_formattime(h, 0));
+ result.push(sieve_formattime(23, 59));
+
+ return callback(result);
+ },
+ open: function(event, ui) {
+ // scroll to current time
+ var $this = $(this), val = $this.val(),
+ widget = $this.autocomplete('widget').css('width', '10em'),
+ menu = $this.data('ui-autocomplete').menu;
+
+ if (val && val.length)
+ widget.children().each(function() {
+ var li = $(this);
+ if (li.text().indexOf(val) == 0)
+ menu._scrollIntoView(li);
+ });
+ },
+ select: function(event, ui) {
+ $(this).val(ui.item.value);
+ return false;
+ }
+ })
+ .click(function() { // show drop-down upon clicks
+ $(this).autocomplete('search', $(this).val() || ' ');
+ })
+}
+
+
/*********************************************************/
/********* Mail UI methods *********/
/*********************************************************/
rcube_webmail.prototype.managesieve_create = function(force)
{
if (!force && this.env.action != 'show' && !$('#'+this.env.contentframe).is(':visible')) {
var uid = this.message_list.get_single_selection(),
lock = this.set_busy(true, 'loading');
this.http_post('plugin.managesieve-action', {_uid: uid}, lock);
return;
}
if (!this.env.sieve_headers || !this.env.sieve_headers.length)
return;
var i, html, buttons = {}, dialog = $("#sievefilterform");
// create dialog window
if (!dialog.length) {
dialog = $('<div id="sievefilterform"></div>');
$('body').append(dialog);
}
// build dialog window content
html = '<fieldset><legend>'+this.gettext('managesieve.usedata')+'</legend><ul>';
for (i in this.env.sieve_headers)
html += '<li><input type="checkbox" name="headers[]" id="sievehdr'+i+'" value="'+i+'" checked="checked" />'
+'<label for="sievehdr'+i+'">'+this.env.sieve_headers[i][0]+':</label> '+this.env.sieve_headers[i][1]+'</li>';
html += '</ul></fieldset>';
dialog.html(html);
// [Next Step] button action
buttons[this.gettext('managesieve.nextstep')] = function () {
// check if there's at least one checkbox checked
var hdrs = $('input[name="headers[]"]:checked', dialog);
if (!hdrs.length) {
alert(rcmail.gettext('managesieve.nodata'));
return;
}
// build frame URL
var url = rcmail.get_task_url('mail');
url = rcmail.add_url(url, '_action', 'plugin.managesieve');
url = rcmail.add_url(url, '_framed', 1);
hdrs.map(function() {
var val = rcmail.env.sieve_headers[this.value];
url = rcmail.add_url(url, 'r['+this.value+']', val[0]+':'+val[1]);
});
// load form in the iframe
var frame = $('<iframe>').attr({src: url, frameborder: 0})
dialog.empty().append(frame).dialog('widget').resize();
// Change [Next Step] button with [Save] button
buttons = {};
buttons[rcmail.gettext('save')] = function() {
var win = $('iframe', dialog).get(0).contentWindow;
win.rcmail.managesieve_save();
};
dialog.dialog('option', 'buttons', buttons);
};
// show dialog window
dialog.dialog({
modal: false,
resizable: true,
closeOnEscape: !bw.ie7, // disable for performance reasons
title: this.gettext('managesieve.newfilter'),
close: function() { rcmail.managesieve_dialog_close(); },
buttons: buttons,
minWidth: 600,
minHeight: 300,
height: 250
}).show();
this.env.managesieve_dialog = dialog;
}
rcube_webmail.prototype.managesieve_dialog_close = function()
{
var dialog = this.env.managesieve_dialog;
// BUG(?): if we don't remove the iframe first, it will be reloaded
dialog.html('');
dialog.dialog('destroy').hide();
}
rcube_webmail.prototype.managesieve_dialog_resize = function(o)
{
var dialog = this.env.managesieve_dialog,
win = $(window), form = $(o);
width = $('fieldset:first', o).width(), // fieldset width is more appropriate here
height = form.height(),
w = win.width(), h = win.height();
dialog.dialog('option', { height: Math.min(h-20, height+120), width: Math.min(w-20, width+65) })
.dialog('option', 'position', ['center', 'center']); // works in a separate call only (!?)
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Aug 18, 8:01 AM (16 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1260117
Default Alt Text
(70 KB)

Event Timeline