/**
  * Callback function for parsing an xml command tag
  * and turn it into real html content
  *
  * @param  array Matches array of preg_replace_callback
  * @return string Tag/Object content
  */
 protected function xml_command($matches)
 {
     $command = strtolower($matches[1]);
     $attrib = html::parse_attrib_string($matches[2]);
     // empty output if required condition is not met
     if (!empty($attrib['condition']) && !$this->check_condition($attrib['condition'])) {
         return '';
     }
     // execute command
     switch ($command) {
         // return a button
         case 'button':
             if ($attrib['name'] || $attrib['command']) {
                 return $this->button($attrib);
             }
             break;
             // show a label
         // show a label
         case 'label':
             if ($attrib['name'] || $attrib['command']) {
                 // @FIXME: 'noshow' is useless, remove?
                 if ($attrib['noshow']) {
                     return '';
                 }
                 $vars = $attrib + array('product' => $this->config->get('product_name'));
                 unset($vars['name'], $vars['command']);
                 $label = $this->app->gettext($attrib + array('vars' => $vars));
                 $quoting = !empty($attrib['quoting']) ? strtolower($attrib['quoting']) : (get_boolean((string) $attrib['html']) ? 'no' : '');
                 switch ($quoting) {
                     case 'no':
                     case 'raw':
                         break;
                     case 'javascript':
                     case 'js':
                         $label = rcmail::JQ($label);
                         break;
                     default:
                         $label = html::quote($label);
                         break;
                 }
                 return $label;
             }
             break;
             // include a file
         // include a file
         case 'include':
             if (!$this->plugin_skin_path || !is_file($path = realpath($this->plugin_skin_path . $attrib['file']))) {
                 $path = realpath(($attrib['skin_path'] ? $attrib['skin_path'] : $this->config->get('skin_path')) . $attrib['file']);
             }
             if (is_readable($path)) {
                 if ($this->config->get('skin_include_php')) {
                     $incl = $this->include_php($path);
                 } else {
                     $incl = file_get_contents($path);
                 }
                 $incl = $this->parse_conditions($incl);
                 return $this->parse_xml($incl);
             }
             break;
         case 'plugin.include':
             $hook = $this->app->plugins->exec_hook("template_plugin_include", $attrib);
             return $hook['content'];
             break;
             // define a container block
         // define a container block
         case 'container':
             if ($attrib['name'] && $attrib['id']) {
                 $this->command('gui_container', $attrib['name'], $attrib['id']);
                 // let plugins insert some content here
                 $hook = $this->app->plugins->exec_hook("template_container", $attrib);
                 return $hook['content'];
             }
             break;
             // return code for a specific application object
         // return code for a specific application object
         case 'object':
             $object = strtolower($attrib['name']);
             $content = '';
             // we are calling a class/method
             if (($handler = $this->object_handlers[$object]) && is_array($handler)) {
                 if (is_object($handler[0]) && method_exists($handler[0], $handler[1]) || is_string($handler[0]) && class_exists($handler[0])) {
                     $content = call_user_func($handler, $attrib);
                 }
             } else {
                 if (function_exists($handler)) {
                     $content = call_user_func($handler, $attrib);
                 } else {
                     if ($object == 'doctype') {
                         $content = html::doctype($attrib['value']);
                     } else {
                         if ($object == 'logo') {
                             $attrib += array('alt' => $this->xml_command(array('', 'object', 'name="productname"')));
                             if ($logo = $this->config->get('skin_logo')) {
                                 $attrib['src'] = $logo;
                             }
                             $content = html::img($attrib);
                         } else {
                             if ($object == 'productname') {
                                 $name = $this->config->get('product_name', 'Roundcube Webmail');
                                 $content = html::quote($name);
                             } else {
                                 if ($object == 'version') {
                                     $ver = (string) RCMAIL_VERSION;
                                     if (is_file(INSTALL_PATH . '.svn/entries')) {
                                         if (preg_match('/Revision:\\s(\\d+)/', @shell_exec('svn info'), $regs)) {
                                             $ver .= ' [SVN r' . $regs[1] . ']';
                                         }
                                     } else {
                                         if (is_file(INSTALL_PATH . '.git/index')) {
                                             if (preg_match('/Date:\\s+([^\\n]+)/', @shell_exec('git log -1'), $regs)) {
                                                 if ($date = date('Ymd.Hi', strtotime($regs[1]))) {
                                                     $ver .= ' [GIT ' . $date . ']';
                                                 }
                                             }
                                         }
                                     }
                                     $content = html::quote($ver);
                                 } else {
                                     if ($object == 'steptitle') {
                                         $content = html::quote($this->get_pagetitle());
                                     } else {
                                         if ($object == 'pagetitle') {
                                             if ($this->config->get('devel_mode') && !empty($_SESSION['username'])) {
                                                 $title = $_SESSION['username'] . ' :: ';
                                             } else {
                                                 if ($prod_name = $this->config->get('product_name')) {
                                                     $title = $prod_name . ' :: ';
                                                 } else {
                                                     $title = '';
                                                 }
                                             }
                                             $title .= $this->get_pagetitle();
                                             $content = html::quote($title);
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
             // exec plugin hooks for this template object
             $hook = $this->app->plugins->exec_hook("template_object_{$object}", $attrib + array('content' => $content));
             return $hook['content'];
             // return code for a specified eval expression
         // return code for a specified eval expression
         case 'exp':
             $value = $this->parse_expression($attrib['expression']);
             return eval("return html::quote({$value});");
             // return variable
         // return variable
         case 'var':
             $var = explode(':', $attrib['name']);
             $name = $var[1];
             $value = '';
             switch ($var[0]) {
                 case 'env':
                     $value = $this->env[$name];
                     break;
                 case 'config':
                     $value = $this->config->get($name);
                     if (is_array($value) && $value[$_SESSION['storage_host']]) {
                         $value = $value[$_SESSION['storage_host']];
                     }
                     break;
                 case 'request':
                     $value = rcube_utils::get_input_value($name, rcube_utils::INPUT_GPC);
                     break;
                 case 'session':
                     $value = $_SESSION[$name];
                     break;
                 case 'cookie':
                     $value = htmlspecialchars($_COOKIE[$name]);
                     break;
                 case 'browser':
                     $value = $this->browser->{$name};
                     break;
             }
             if (is_array($value)) {
                 $value = implode(', ', $value);
             }
             return html::quote($value);
             break;
     }
     return '';
 }
 function gen_js_list()
 {
     // create JS version of rule list for updating UI via AJAX
     $this->_startup();
     if (sizeof($this->script) == 0) {
         // no rules exist, clear rule list
         $this->api->output->command('sieverules_update_list', 'add-first', -1, rcube_utils::rep_specialchars_output($this->gettext('nosieverules')));
     } else {
         foreach ($this->script as $idx => $filter) {
             $args = rcube::get_instance()->plugins->exec_hook('sieverules_list_rules', array('idx' => $idx, 'name' => $filter['name']));
             // skip the vacation and aborted rules
             if ($args['abort'] || $this->vacation_ui && $idx == $this->vacation_rule_position && $filter['name'] == $this->vacation_rule_name) {
                 $this->api->output->command('sieverules_update_list', $idx == 0 ? 'add-first' : 'add', 'rcmrow' . $idx, '', '', true);
             } else {
                 $parts = $this->_rule_list_parts($idx, $filter);
                 $parts['control'] = str_replace("'", "\\'", $parts['control']);
                 // send rule to UI
                 $this->api->output->command('sieverules_update_list', $idx == 0 ? 'add-first' : 'add', 'rcmrow' . $idx, rcmail::JQ($parts['name']), $parts['control'], $args['abort']);
             }
         }
     }
     $this->api->output->send();
 }
 /**
  * Callback function used to build mailto: links around e-mail strings
  *
  * @param array Matches result from preg_replace_callback
  * @return int Index of saved string value
  */
 public function mailto_callback($matches)
 {
     $href = $matches[1];
     $suffix = $this->parse_url_brackets($href);
     $i = $this->add(html::a(array('href' => 'mailto:' . $href, 'onclick' => "return " . rcmail::JS_OBJECT_NAME . ".command('compose','" . rcmail::JQ($href) . "',this)"), rcmail::Q($href)) . $suffix);
     return $i >= 0 ? $this->get_replacement($i) : '';
 }
 function gen_js_list()
 {
     // create JS version of rule list for updating UI via AJAX
     $this->_startup();
     if (sizeof($this->script) == 0) {
         // no rules exist, clear rule list
         $this->api->output->command('sieverules_update_list', 'add-first', -1, rcube_utils::rep_specialchars_output($this->gettext('nosieverules')));
     } else {
         foreach ($this->script as $idx => $filter) {
             $parts = $this->_rule_list_parts($idx, $filter);
             $parts['control'] = str_replace("'", "\\'", $parts['control']);
             // send rule to UI
             $this->api->output->command('sieverules_update_list', $idx == 0 ? 'add-first' : 'add', 'rcmrow' . $idx, rcmail::JQ($parts['name']), $parts['control']);
         }
     }
     $this->api->output->send();
 }
 function gen_js_list()
 {
     $this->_startup();
     if (sizeof($this->script) == 0) {
         $this->api->output->command('sieverules_update_list', 'add-first', -1, rcube_utils::rep_specialchars_output($this->gettext('nosieverules')));
     } else {
         foreach ($this->script as $idx => $filter) {
             if ($filter['disabled'] == 1) {
                 $filter_name = $filter['name'] . ' (' . $this->gettext('disabled') . ')';
             } else {
                 $filter_name = $filter['name'];
             }
             $tmp_output = new rcube_output_html('settings');
             $dst = $idx - 1;
             $up_link = $tmp_output->button(array('command' => 'plugin.sieverules.move', 'prop' => $dst, 'type' => 'link', 'class' => 'up_arrow', 'title' => 'sieverules.moveup', 'content' => ' '));
             $up_link = str_replace("'", "\\'", $up_link);
             $dst = $idx + 2;
             $down_link = $tmp_output->button(array('command' => 'plugin.sieverules.move', 'prop' => $dst, 'type' => 'link', 'class' => 'down_arrow', 'title' => 'sieverules.movedown', 'content' => ' '));
             $down_link = str_replace("'", "\\'", $down_link);
             $this->api->output->command('sieverules_update_list', $idx == 0 ? 'add-first' : 'add', 'rcmrow' . $idx, rcmail::JQ($filter_name), $down_link, $up_link);
         }
     }
     $this->api->output->send();
 }