alecpl
2010-03-18 98c489e9f49de6a4442821614d5e69b36173eeab
- Managesieve: Added import from Horde-INGO
- Managesieve: Support for more than one match using if+stop instead of if+elsif structures (#1486078)
- Managesieve: Support for selectively disabling rules within a single sieve script (#1485882)
- Managesieve: Added vertical splitter


10 files modified
312 ■■■■■ changed files
CHANGELOG 3 ●●●●● patch | view | raw | blame | history
plugins/managesieve/Changelog 7 ●●●●● patch | view | raw | blame | history
plugins/managesieve/lib/rcube_sieve.php 173 ●●●●● patch | view | raw | blame | history
plugins/managesieve/localization/en_US.inc 1 ●●●● patch | view | raw | blame | history
plugins/managesieve/localization/pl_PL.inc 1 ●●●● patch | view | raw | blame | history
plugins/managesieve/managesieve.js 37 ●●●● patch | view | raw | blame | history
plugins/managesieve/managesieve.php 28 ●●●●● patch | view | raw | blame | history
plugins/managesieve/skins/default/managesieve.css 38 ●●●● patch | view | raw | blame | history
plugins/managesieve/skins/default/templates/filteredit.html 10 ●●●● patch | view | raw | blame | history
plugins/managesieve/skins/default/templates/managesieve.html 14 ●●●●● patch | view | raw | blame | history
CHANGELOG
@@ -1,6 +1,9 @@
CHANGELOG RoundCube Webmail
===========================
- Managesieve: import from Horde-INGO
- Managesieve: support for more than one match (#1486078)
- Managesieve: support for selectively disabling rules within a single sieve script (#1485882)
- Threaded message listing now available
- Added sorting by ARRIVAL and CC
- Message list columns configurable by the user
plugins/managesieve/Changelog
@@ -1,3 +1,10 @@
* 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)
plugins/managesieve/lib/rcube_sieve.php
@@ -58,6 +58,10 @@
        $this->disabled = $disabled;
    }
    public function __destruct() {
        $this->sieve->disconnect();
    }
    /**
    * Getter for error code
    */
@@ -221,13 +225,23 @@
    // try to parse from Roundcube format
        $this->script = new rcube_sieve_script($script, $this->disabled);
        // ... else try Squirrelmail format
        if (empty($this->script->content) && $name == 'phpscript') {
            $script = $this->sieve->getScript('phpscript');
            $script = $this->_convert_from_squirrel_rules($script);
        // ... else try to import from different formats
        if (empty($this->script->content)) {
            $script = $this->_import_rules($script);
            $this->script = new rcube_sieve_script($script, $this->disabled);
        }
        // replace all elsif with if+stop, we support only ifs
        foreach ($this->script->content as $idx => $rule) {
            if (!isset($this->script->content[$idx+1])
                || preg_match('/^else|elsif$/', $this->script->content[$idx+1]['type'])) {
                // 'stop' not found?
                if (!preg_match('/^(stop|vacation)$/', $rule['actions'][count($rule['actions'])-1]['type'])) {
                    $this->script->content[$idx]['actions'][] = array(
                        'type' => 'stop'
                    );
                }
            }
        }
        $this->current = $name;
@@ -254,13 +268,13 @@
    }
    private function _convert_from_squirrel_rules($script)
    private function _import_rules($script)
    {
        $i = 0;
        $name = array();
        // tokenize rules
        if ($tokens = preg_split('/(#START_SIEVE_RULE.*END_SIEVE_RULE)\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE))
        // Squirrelmail (Avelsieve)
        if ($tokens = preg_split('/(#START_SIEVE_RULE.*END_SIEVE_RULE)\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE)) {
            foreach($tokens as $token) {
            if (preg_match('/^#START_SIEVE_RULE.*/', $token, $matches)) {
                $name[$i] = "unnamed rule ".($i+1);
@@ -269,6 +283,21 @@
            elseif (isset($name[$i])) {
                $content .= "if $token\n";
            $i++;
                }
            }
        }
        // Horde (INGO)
        else if ($tokens = preg_split('/(# .+)\r?\n/i', $script, -1, PREG_SPLIT_DELIM_CAPTURE)) {
            foreach($tokens as $token) {
                if (preg_match('/^# (.+)/i', $token, $matches)) {
                    $name[$i] = $matches[1];
                    $content .= "# rule:[" . $name[$i] . "]\n";
                }
                elseif (isset($name[$i])) {
                    $token = str_replace(":comparator \"i;ascii-casemap\" ", "", $token);
                    $content .= $token . "\n";
                    $i++;
                }
                }
            }
@@ -330,14 +359,15 @@
      $result = false;
      
      // check existsing script rules names
      foreach ($this->content as $idx => $elem)
        foreach ($this->content as $idx => $elem) {
        $names[$elem['name']] = $idx;
        }
      
      foreach ($content as $elem)
        if (!isset($names[$elem['name']]))
      {
        foreach ($content as $elem) {
            if (!isset($names[$elem['name']])) {
            array_push($this->content, $elem);
        $result = true;
        }
      }
      return $result;
@@ -358,8 +388,7 @@
  public function delete_rule($index)
    {
      if(isset($this->content[$index]))
        {
        if(isset($this->content[$index])) {
          unset($this->content[$index]);
      return true;
    }
@@ -374,8 +403,7 @@
  public function update_rule($index, $content)
    {
      // TODO: check this->supported
      if ($this->content[$index])
        {
        if ($this->content[$index]) {
      $this->content[$index] = $content;
      return $index;
    }
@@ -392,8 +420,7 @@
      $idx = 0;
      
      // rules
      foreach ($this->content as $rule)
        {
        foreach ($this->content as $rule) {
      $extension = '';
      $tests = array();
      $i = 0;
@@ -402,11 +429,9 @@
      $script .= '# rule:[' . $rule['name'] . "]\n";
  
      // constraints expressions
      foreach ($rule['tests'] as $test)
        {
        foreach ($rule['tests'] as $test) {
          $tests[$i] = '';
          switch ($test['test'])
            {
            switch ($test['test']) {
          case 'size':
            $tests[$i] .= ($test['not'] ? 'not ' : '');
            $tests[$i] .= 'size :' . ($test['type']=='under' ? 'under ' : 'over ') . $test['arg'];
@@ -437,7 +462,10 @@
          $i++;
        }
  
      $script .= ($idx>0 ? 'els' : '').($rule['join'] ? 'if allof (' : 'if anyof (');
//            $script .= ($idx>0 ? 'els' : '').($rule['join'] ? 'if allof (' : 'if anyof (');
            // disabled rule: if false #....
            $script .= 'if' . ($rule['disabled'] ? ' false #' : '');
        $script .= $rule['join'] ? ' allof (' : ' anyof (';
      if (sizeof($tests) > 1)
        $script .= implode(",\n\t", $tests);
      elseif (sizeof($tests))
@@ -447,10 +475,8 @@
      $script .= ")\n{\n";
  
      // action(s)
      foreach ($rule['actions'] as $action)
          {
        switch ($action['type'])
        {
        foreach ($rule['actions'] as $action) {
            switch ($action['type']) {
          case 'fileinto':
            $extension = 'fileinto';
        $script .= "\tfileinto \"" . $this->_escape_string($action['target']) . "\";\n";
@@ -540,22 +566,19 @@
      $script = preg_replace('|/\*.*?\*/|sm', '', $script);
      // tokenize rules
      if ($tokens = preg_split('/(# rule:\[.*\])\r?\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE))
        foreach($tokens as $token)
      {
        if (preg_match('/^# rule:\[(.*)\]/', $token, $matches))
          {
        if ($tokens = preg_split('/(# rule:\[.*\])\r?\n/', $script, -1, PREG_SPLIT_DELIM_CAPTURE)) {
            foreach($tokens as $token) {
            if (preg_match('/^# rule:\[(.*)\]/', $token, $matches)) {
            $content[$i]['name'] = $matches[1];
          }
        elseif (isset($content[$i]['name']) && sizeof($content[$i]) == 1)
          {
            if ($rule = $this->_tokenize_rule($token))
          {
            elseif (isset($content[$i]['name']) && sizeof($content[$i]) == 1) {
                if ($rule = $this->_tokenize_rule($token)) {
                $content[$i] = array_merge($content[$i], $rule);
                $i++;
          }
        else // unknown rule format
            unset($content[$i]);
            }
          }
      }
@@ -571,16 +594,29 @@
    {
      $result = NULL;
    
      if (preg_match('/^(if|elsif|else)\s+((true|not\s+true|allof|anyof|exists|header|not|size)(.*))\s+\{(.*)\}$/sm', trim($content), $matches))
        {
      list($tests, $join) = $this->_parse_tests(trim($matches[2]));
        if (preg_match('/^(if|elsif|else)\s+((true|false|not\s+true|allof|anyof|exists|header|not|size)(.*))\s+\{(.*)\}$/sm',
            trim($content), $matches)) {
            $tests = trim($matches[2]);
            // disabled rule (false + comment): if false #.....
            if ($matches[3] == 'false') {
                $tests = preg_replace('/^false\s+#\s+/', '', $tests);
                $disabled = true;
            }
            else
                $disabled = false;
        list($tests, $join) = $this->_parse_tests($tests);
      $actions = $this->_parse_actions(trim($matches[5]));
      if ($tests && $actions)
        $result = array(
                    'type' => $matches[1],
            'tests' => $tests,
            'actions' => $actions,
            'join' => $join,
                    'disabled' => $disabled,
        );
    }
@@ -616,30 +652,23 @@
      $pattern = '/(' . implode('$)|(', $patterns) . '$)/ms';
      // parse actions body
      if (preg_match_all($pattern, $content, $mm, PREG_SET_ORDER))
      {
        foreach ($mm as $m)
    {
        if (preg_match_all($pattern, $content, $mm, PREG_SET_ORDER)) {
            foreach ($mm as $m) {
      $content = trim($m[0]);
      
          if(preg_match('/^(discard|keep|stop)/', $content, $matches))
            {
                if(preg_match('/^(discard|keep|stop)/', $content, $matches)) {
          $result[] = array('type' => $matches[1]);
        }
          elseif(preg_match('/^fileinto/', $content))
            {
                elseif(preg_match('/^fileinto/', $content)) {
          $result[] = array('type' => 'fileinto', 'target' => $this->_parse_string($m[sizeof($m)-1])); 
        }
          elseif(preg_match('/^redirect/', $content))
            {
                elseif(preg_match('/^redirect/', $content)) {
          $result[] = array('type' => 'redirect', 'target' => $this->_parse_string($m[sizeof($m)-1])); 
        }
          elseif(preg_match('/^(reject|ereject)\s+(.*);$/sm', $content, $matches))
            {
                elseif(preg_match('/^(reject|ereject)\s+(.*);$/sm', $content, $matches)) {
          $result[] = array('type' => $matches[1], 'target' => $this->_parse_string($matches[2])); 
        }
          elseif(preg_match('/^vacation\s+(.*);$/sm', $content, $matches))
            {
                elseif(preg_match('/^vacation\s+(.*);$/sm', $content, $matches)) {
          $vacation = array('type' => 'vacation');
              if (preg_match('/:(days)\s+([0-9]+)/', $content, $vm)) {
@@ -662,9 +691,11 @@
            $vacation['from'] = $vm[2];
        $content = preg_replace('/:(from)\s+(".*?[^\\\]")/', '', $content); 
          }
          $content = preg_replace('/^vacation/', '', $content);         
          $content = preg_replace('/;$/', '', $content);
          $content = trim($content);
              if (preg_match('/^:(mime)/', $content, $vm)) {
            $vacation['mime'] = true;
        $content = preg_replace('/^:mime/', '', $content); 
@@ -685,14 +716,12 @@
    *
    * @param    string    Text 
    */
  private function _parse_tests($content)
    {
      $result = NULL;
      // lists
      if (preg_match('/^(allof|anyof)\s+\((.*)\)$/sm', $content, $matches))
    {
        if (preg_match('/^(allof|anyof)\s+\((.*)\)$/sm', $content, $matches)) {
      $content = $matches[2];
      $join = $matches[1]=='allof' ? true : false;
    }
@@ -714,14 +743,11 @@
      $pattern = '/(' . implode(')|(', $patterns) . ')/';
      // ...and parse tests list
      if (preg_match_all($pattern, $content, $matches, PREG_SET_ORDER))
        {
      foreach ($matches as $match)
        {
        if (preg_match_all($pattern, $content, $matches, PREG_SET_ORDER)) {
        foreach ($matches as $match) {
          $size = sizeof($match);
          
          if (preg_match('/^(not\s+)?size/', $match[0]))
            {
            if (preg_match('/^(not\s+)?size/', $match[0])) {
          $result[] = array(
            'test'     => 'size',
            'not'     => $match[$size-4] ? true : false,
@@ -729,8 +755,7 @@
            'arg'    => $match[$size-1], // value
          );
        }
          elseif (preg_match('/^(not\s+)?header/', $match[0]))
            {
            elseif (preg_match('/^(not\s+)?header/', $match[0])) {
          $result[] = array(
            'test'    => 'header',
            'not'     => $match[$size-5] ? true : false,
@@ -739,16 +764,14 @@
            'arg2'    => $this->_parse_list($match[$size-1]), // string(s)
          );  
        }
          elseif (preg_match('/^(not\s+)?exists/', $match[0]))
        {
            elseif (preg_match('/^(not\s+)?exists/', $match[0])) {
          $result[] = array(
            'test'     => 'exists',
            'not'     => $match[$size-3] ? true : false,
            'arg'     => $this->_parse_list($match[$size-1]), // header(s)
          );
            }
          elseif (preg_match('/^(not\s+)?true/', $match[0]))
        {
            elseif (preg_match('/^(not\s+)?true/', $match[0])) {
          $result[] = array(
            'test'     => 'true',
            'not'     => $match[$size-2] ? true : false,
@@ -787,8 +810,7 @@
    {
      $replace['/"/'] = '\\"';
      
      if (is_array($content))
        {
        if (is_array($content)) {
      for ($x=0, $y=sizeof($content); $x<$y; $x++)
        $content[$x] = preg_replace(array_keys($replace), array_values($replace), $content[$x]);
        
@@ -807,16 +829,13 @@
    {
      $result = array();
      
      for ($x=0, $len=strlen($content); $x<$len; $x++)
        {
      switch ($content[$x])
        {
        for ($x=0, $len=strlen($content); $x<$len; $x++) {
        switch ($content[$x]) {
          case '\\':
            $str .= $content[++$x];
              break;
          case '"':
            if (isset($str))
              {
                if (isset($str)) {
            $result[] = $str;
            unset($str);
          }
plugins/managesieve/localization/en_US.inc
@@ -46,6 +46,7 @@
$labels['active'] = 'active';
$labels['copyfromset'] = 'Copy filters from set';
$labels['none'] = '- none -';
$labels['filterdisabled'] = 'Filter disabled';
$messages = array();
$messages['filterunknownerror'] = 'Unknown server error';
plugins/managesieve/localization/pl_PL.inc
@@ -47,6 +47,7 @@
$labels['active'] = 'aktywny';
$labels['copyfromset'] = 'Skopiuj filtry ze zbioru';
$labels['none'] = '- brak -';
$labels['filterdisabled'] = 'Filtr wyÅ‚Ä…czony';
$messages = array();
$messages['filterunknownerror'] = 'Nieznany bÅ‚Ä…d serwera';
plugins/managesieve/managesieve.js
@@ -26,8 +26,9 @@
    if (rcmail.env.action == 'plugin.managesieve')
      {
    if (rcmail.gui_objects.sieveform)
    if (rcmail.gui_objects.sieveform) {
      rcmail.enable_command('plugin.managesieve-save', true);
    }
    else {
      rcmail.enable_command('plugin.managesieve-del', 'plugin.managesieve-up',
        'plugin.managesieve-down', false);
@@ -47,6 +48,8 @@
            rcmail.filters_list.focus();
      }
      }
    if (rcmail.gui_objects.sieveform && rcmail.env.rule_disabled)
      $('#disabled').attr('checked', true);
  });
  /*********************************************************/
@@ -91,7 +94,7 @@
    return i;
    }
  rcube_webmail.prototype.managesieve_updatelist = function(action, name, id)
  rcube_webmail.prototype.managesieve_updatelist = function(action, name, id, disabled)
    {
    this.set_busy(true);
@@ -114,7 +117,7 @@
      case 'down':
        var rows = this.filters_list.rows;
    var from;
    var from, fromstatus, status;
    // we need only to replace filter names...
        for (var i=0; i<rows.length; i++)
@@ -122,11 +125,15 @@
      if (rows[i]==null) { // removed row
        continue;
          } else if (rows[i].uid == id) {
        from = rows[i].obj.cells[0];
        from = rows[i].obj;
            fromstatus = $(from).hasClass('disabled');
      } else if (rows[i].uid == id+1){
        name = rows[i].obj.cells[0].innerHTML;
        rows[i].obj.cells[0].innerHTML = from.innerHTML;
        from.innerHTML = name;
            status = $(rows[i].obj).hasClass('disabled');
        rows[i].obj.cells[0].innerHTML = from.cells[0].innerHTML;
        from.cells[0].innerHTML = name;
            $(from)[status?'addClass':'removeClass']('disabled');
            $(rows[i].obj)[fromstatus?'addClass':'removeClass']('disabled');
        this.filters_list.highlight_row(i);
        break;
      }
@@ -137,7 +144,7 @@
      case 'up':
        var rows = this.filters_list.rows;
    var from;
    var from, status, fromstatus;
    // we need only to replace filter names...
        for (var i=0; i<rows.length; i++)
@@ -145,12 +152,16 @@
      if (rows[i]==null) { // removed row
        continue;
          } else if (rows[i].uid == id-1) {
        from = rows[i].obj.cells[0];
        from = rows[i].obj;
            fromstatus = $(from).hasClass('disabled');
        this.filters_list.highlight_row(i);
      } else if (rows[i].uid == id) {
        name = rows[i].obj.cells[0].innerHTML;
        rows[i].obj.cells[0].innerHTML = from.innerHTML;
        from.innerHTML = name;
            status = $(rows[i].obj).hasClass('disabled');
        rows[i].obj.cells[0].innerHTML = from.cells[0].innerHTML;
        from.cells[0].innerHTML = name;
            $(from)[status?'addClass':'removeClass']('disabled');
            $(rows[i].obj)[fromstatus?'addClass':'removeClass']('disabled');
        break;
      }
    }
@@ -164,6 +175,10 @@
      if (rows[i] && rows[i].uid == id)
        {
        rows[i].obj.cells[0].innerHTML = name;
            if (disabled)
              $(rows[i].obj).addClass('disabled');
            else
              $(rows[i].obj).removeClass('disabled');
        break;
        }
        break;
@@ -186,6 +201,8 @@
            td = parent.document.createElement('td');
            new_row.appendChild(td);
        list.insert_row(new_row, false);
            if (disabled)
              $(new_row).addClass('disabled');
            if (row.cells[0].className)
              td.className = row.cells[0].className;
plugins/managesieve/managesieve.php
@@ -7,7 +7,7 @@
 * It's clickable interface which operates on text scripts and communicates
 * with server using managesieve protocol. Adds Filters tab in Settings.
 *
 * @version 2.2
 * @version 2.3
 * @author Aleksander 'A.L.E.C' Machniak <alec@alec.pl>
 *
 * Configuration (see config.inc.php.dist)
@@ -46,9 +46,7 @@
  
  function managesieve_start()
  {
    $rcmail = rcmail::get_instance();
    $this->rc = &$rcmail;
    $this->rc = rcmail::get_instance();
    $this->load_config();
    // register UI objects
@@ -302,6 +300,7 @@
      foreach ($sizeitems as $item)
    $items[] = $item;
      $this->form['disabled'] = $_POST['_disabled'] ? true : false;
      $this->form['join'] = $join=='allof' ? true : false;
      $this->form['name'] = $name;
      $this->form['tests'] = array();
@@ -486,8 +485,10 @@
    if ($save && $fid !== false)
    {
      $this->rc->output->show_message('managesieve.filtersaved', 'confirmation');
      $this->rc->output->add_script(sprintf("rcmail.managesieve_updatelist('%s', '%s', %d);",
        isset($new) ? 'add' : 'update', Q($this->form['name']), $fid), 'foot');
      $this->rc->output->add_script(
            sprintf("rcmail.managesieve_updatelist('%s', '%s', %d, %d);",
          isset($new) ? 'add' : 'update', Q($this->form['name']), $fid, $this->form['disabled']),
              'foot');
    }
    else
    {
@@ -504,10 +505,12 @@
  {
    // Handle form action 
    if (isset($_GET['_framed']) || isset($_POST['_framed'])) {
      if (isset($_GET['_newset']) || isset($_POST['_newset']))
      if (isset($_GET['_newset']) || isset($_POST['_newset'])) {
        $this->rc->output->send('managesieve.setedit');
      else
      }
      else {
        $this->rc->output->send('managesieve.filteredit');
      }
    } else {
      $this->rc->output->set_pagetitle($this->gettext('filters'));
      $this->rc->output->send('managesieve.managesieve');
@@ -525,7 +528,11 @@
    $a_show_cols = array('managesieve.filtername');
    foreach($this->script as $idx => $filter)
      $result[] = array('managesieve.filtername' => $filter['name'], 'id' => $idx);
      $result[] = array(
        'managesieve.filtername' => $filter['name'],
        'id' => $idx,
        'class' => $filter['disabled'] ? 'disabled' : '',
      );
    
    // create XHTML table
    $out = rcube_table_output($attrib, $result, $a_show_cols, 'id');
@@ -723,6 +730,9 @@
    $out .= "</fieldset>\n";
    if ($scr['disabled']) {
      $this->rc->output->set_env('rule_disabled', true);
    }
    $this->rc->output->add_label('managesieve.ruledeleteconfirm');
    $this->rc->output->add_label('managesieve.actiondeleteconfirm');
    $this->rc->output->add_gui_object('sieveform', 'filterform');
plugins/managesieve/skins/default/managesieve.css
@@ -5,7 +5,6 @@
{
  position: absolute;
  left: 20px;
  width: 220px;
  top: 120px;
  bottom: 30px;
  border: 1px solid #999999;
@@ -28,6 +27,11 @@
  cursor: pointer;
}
#filters-table tbody tr.disabled td
{
  color: #999999;
}
#filtersbuttons
{
  position: absolute;
@@ -38,7 +42,7 @@
#filtersetsbuttons
{
  position: absolute;
  left: 250px;
  left: 230px;
  top: 85px;
}
@@ -131,7 +135,7 @@
#filtersetselect
{
  position: absolute;
  left: 380px;
  left: 360px;
  top: 90px;
}
@@ -139,7 +143,6 @@
{
  position: absolute;
  top: 120px;
  left: 250px;
  right: 20px;
  bottom: 30px;
  border: 1px solid #999999;
@@ -168,12 +171,6 @@
  white-space: nowrap;
  background-color: #F9F9F9;
  padding: 20px 10px 10px 10px;
}
#filter-form input, select
{
  font-size: 10pt;
  font-family: inherit;
}
fieldset
@@ -248,3 +245,24 @@
  font-size: 10px;
  white-space: nowrap;
}
#footer
{
  padding-top: 5px;
  width: 100%;
}
#footer .footerleft
{
  padding-left: 2px;
  white-space: nowrap;
  float: left;
}
#footer .footerright
{
  padding-right: 2px;
  white-space: nowrap;
  text-align: right;
  float: right;
}
plugins/managesieve/skins/default/templates/filteredit.html
@@ -99,9 +99,15 @@
<div id="filter-form">
<roundcube:object name="filterform" />
<p>
<div id="footer">
<div class="footerleft">
<roundcube:button command="plugin.managesieve-save" type="input" class="button mainaction" label="save" />
</p>
</div>
<div class="footerright">
<label for="disabled"><roundcube:label name="managesieve.filterdisabled" /></label>
<input type="checkbox" id="disabled" name="_disabled" value="1" />
</div>
</div>
</form>
</div>
plugins/managesieve/skins/default/templates/managesieve.html
@@ -5,6 +5,15 @@
<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>
<style type="text/css">
#filterslist { width: <roundcube:exp expression="!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter-5 : 210" />px; }
#filter-box { left: <roundcube:exp expression="!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter+5 : 220" />px;
<roundcube:exp expression="browser:ie ? ('width:expression((parseInt(this.parentNode.offsetWidth)-'.(!empty(cookie:sieveviewsplitter) ? cookie:sieveviewsplitter+5 : 220).')+\\'px\\');') : ''" />
}
</style>
</head>
<body>
@@ -32,7 +41,10 @@
<div id="filterslist">
<roundcube:object name="filterslist" id="filters-table" class="records-table" cellspacing="0" summary="Filters list" />
</div>
<script type="text/javascript">
  var sieveviewsplit = new rcube_splitter({id:'sieveviewsplitter', p1: 'filterslist', p2: 'filter-box', orientation: 'v', relative: true, start: 215});
  rcmail.add_onload('sieveviewsplit.init()');
</script>
<div id="filter-box">
<roundcube:object name="filterframe" id="filter-frame" width="100%" height="100%" frameborder="0" src="/watermark.html" />
</div>