From e8d5bdc84ecfdf6fe5008655215a258bbdf0c521 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Thu, 03 Feb 2011 08:58:07 -0500
Subject: [PATCH] - Fix IDNA support when IDN/INTL modules are in use (#1487742)
---
program/include/rcube_template.php | 247 ++++++++++++++++++++++++++++++------------------
1 files changed, 153 insertions(+), 94 deletions(-)
diff --git a/program/include/rcube_template.php b/program/include/rcube_template.php
index c622380..2102aaa 100755
--- a/program/include/rcube_template.php
+++ b/program/include/rcube_template.php
@@ -4,8 +4,8 @@
+-----------------------------------------------------------------------+
| program/include/rcube_template.php |
| |
- | This file is part of the RoundCube Webmail client |
- | Copyright (C) 2006-2009, RoundCube Dev. - Switzerland |
+ | This file is part of the Roundcube Webmail client |
+ | Copyright (C) 2006-2010, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
@@ -30,18 +30,29 @@
*/
class rcube_template extends rcube_html_page
{
- var $app;
- var $config;
- var $framed = false;
- var $pagetitle = '';
- var $message = null;
- var $env = array();
- var $js_env = array();
- var $js_commands = array();
- var $object_handlers = array();
+ private $app;
+ private $config;
+ private $pagetitle = '';
+ private $message = null;
+ private $js_env = array();
+ private $js_commands = array();
+ private $object_handlers = array();
+ private $plugin_skin_path;
+ public $browser;
+ public $framed = false;
+ public $env = array();
public $type = 'html';
public $ajax_call = false;
+
+ // deprecated names of templates used before 0.5
+ private $deprecated_templates = array(
+ 'contact' => 'showcontact',
+ 'contactadd' => 'addcontact',
+ 'contactedit' => 'editcontact',
+ 'identityedit' => 'editidentity',
+ 'messageprint' => 'printmessage',
+ );
/**
* Constructor
@@ -56,7 +67,7 @@
$this->app = rcmail::get_instance();
$this->config = $this->app->config->all();
$this->browser = new rcube_browser();
-
+
//$this->framed = $framed;
$this->set_env('task', $task);
$this->set_env('request_token', $this->app->get_request_token());
@@ -128,7 +139,7 @@
else {
$title = ucfirst($this->env['task']);
}
-
+
return $title;
}
@@ -138,13 +149,21 @@
*/
public function set_skin($skin)
{
- if (!empty($skin) && is_dir('skins/'.$skin) && is_readable('skins/'.$skin))
+ $valid = false;
+
+ if (!empty($skin) && is_dir('skins/'.$skin) && is_readable('skins/'.$skin)) {
$skin_path = 'skins/'.$skin;
- else
+ $valid = true;
+ }
+ else {
$skin_path = $this->config['skin_path'] ? $this->config['skin_path'] : 'skins/default';
+ $valid = !$skin;
+ }
$this->app->config->set('skin_path', $skin_path);
$this->config['skin_path'] = $skin_path;
+
+ return $valid;
}
/**
@@ -156,8 +175,7 @@
public function template_exists($name)
{
$filename = $this->config['skin_path'] . '/templates/' . $name . '.html';
-
- return (is_file($filename) && is_readable($filename));
+ return (is_file($filename) && is_readable($filename)) || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name]));
}
/**
@@ -217,7 +235,7 @@
$args = func_get_args();
if (count($args) == 1 && is_array($args[0]))
$args = $args[0];
-
+
foreach ($args as $name) {
$this->command('add_label', $name, rcube_label($name));
}
@@ -306,7 +324,7 @@
// set output asap
ob_flush();
flush();
-
+
if ($exit) {
exit;
}
@@ -322,14 +340,18 @@
public function write($template = '')
{
// unlock interface after iframe load
+ $unlock = preg_replace('/[^a-z0-9]/i', '', $_GET['_unlock']);
if ($this->framed) {
- array_unshift($this->js_commands, array('set_busy', false));
+ array_unshift($this->js_commands, array('set_busy', false, null, $unlock));
+ }
+ else if ($unlock) {
+ array_unshift($this->js_commands, array('hide_message', $unlock));
}
// write all env variables to client
$js = $this->framed ? "if(window.parent) {\n" : '';
$js .= $this->get_js_commands() . ($this->framed ? ' }' : '');
$this->add_script($js, 'head_top');
-
+
// make sure all <form> tags have a valid request token
$template = preg_replace_callback('/<form\s+([^>]+)>/Ui', array($this, 'alter_form_tag'), $template);
$this->footer = preg_replace_callback('/<form\s+([^>]+)>/Ui', array($this, 'alter_form_tag'), $this->footer);
@@ -352,20 +374,30 @@
{
$skin_path = $this->config['skin_path'];
$plugin = false;
-
+ $this->plugin_skin_path = null;
+
$temp = explode(".", $name, 2);
if (count($temp) > 1) {
$plugin = $temp[0];
$name = $temp[1];
$skin_dir = $plugin . '/skins/' . $this->config['skin'];
- $skin_path = $this->app->plugins->dir . $skin_dir;
+ $skin_path = $this->plugin_skin_path = $this->app->plugins->dir . $skin_dir;
if (!is_dir($skin_path)) { // fallback to default skin
$skin_dir = $plugin . '/skins/default';
- $skin_path = $this->app->plugins->dir . $skin_dir;
+ $skin_path = $this->plugin_skin_path = $this->app->plugins->dir . $skin_dir;
}
}
-
+
$path = "$skin_path/templates/$name.html";
+
+ if (!is_readable($path) && $this->deprecated_templates[$name]) {
+ $path = "$skin_path/templates/".$this->deprecated_templates[$name].".html";
+ if (is_readable($path))
+ raise_error(array('code' => 502, 'type' => 'php',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Using deprecated template '".$this->deprecated_templates[$name]."' in ".$this->config['skin_path']."/templates. Please rename to '".$name."'"),
+ true, false);
+ }
// read template file
if (($templ = @file_get_contents($path)) === false) {
@@ -378,7 +410,7 @@
), true, true);
return false;
}
-
+
// replace all path references to plugins/... with the configured plugins dir
// and /this/ to the current plugin skin directory
if ($plugin) {
@@ -388,7 +420,7 @@
// parse for specialtags
$output = $this->parse_conditions($templ);
$output = $this->parse_xml($output);
-
+
// trigger generic hook where plugins can put additional content to the page
$hook = $this->app->plugins->exec_hook("render_page", array('template' => $name, 'content' => $output));
@@ -399,7 +431,7 @@
<textarea name="console" id="dbgconsole" rows="20" cols="40" wrap="off" style="display:none;width:400px;border:none;font-size:10px" spellcheck="false"></textarea></div>'
);
}
-
+
$output = $this->parse_with_globals($hook['content']);
$this->write(trim($output));
if ($exit) {
@@ -432,7 +464,7 @@
implode(',', $args)
);
}
-
+
return $out;
}
@@ -444,7 +476,10 @@
*/
public function abs_url($str)
{
- return preg_replace('/^\//', $this->config['skin_path'].'/', $str);
+ if ($str[0] == '/')
+ return $this->config['skin_path'] . $str;
+ else
+ return $str;
}
@@ -491,7 +526,7 @@
*/
private function parse_conditions($input)
{
- $matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE);
+ $matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>\n?/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE);
if ($matches && count($matches) == 4) {
if (preg_match('/^(else|endif)$/i', $matches[1])) {
return $matches[0] . $this->parse_conditions($matches[3]);
@@ -499,10 +534,10 @@
$attrib = parse_attrib_string($matches[2]);
if (isset($attrib['condition'])) {
$condmet = $this->check_condition($attrib['condition']);
- $submatches = preg_split('/<roundcube:(elseif|else|endif)\s+([^>]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE);
+ $submatches = preg_split('/<roundcube:(elseif|else|endif)\s+([^>]+)>\n?/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE);
if ($condmet) {
$result = $submatches[0];
- $result.= ($submatches[1] != 'endif' ? preg_replace('/.*<roundcube:endif\s+[^>]+>/Uis', '', $submatches[3], 1) : $submatches[3]);
+ $result.= ($submatches[1] != 'endif' ? preg_replace('/.*<roundcube:endif\s+[^>]+>\n?/Uis', '', $submatches[3], 1) : $submatches[3]);
}
else {
$result = "<roundcube:$submatches[1] $submatches[2]>" . $submatches[3];
@@ -533,21 +568,21 @@
{
return eval("return (".$this->parse_expression($condition).");");
}
-
-
+
+
/**
- *
+ * Inserts hidden field with CSRF-prevention-token into POST forms
*/
private function alter_form_tag($matches)
{
$out = $matches[0];
$attrib = parse_attrib_string($matches[1]);
-
+
if (strtolower($attrib['method']) == 'post') {
$hidden = new html_hiddenfield(array('name' => '_token', 'value' => $this->app->get_request_token()));
$out .= "\n" . $hidden->show();
}
-
+
return $out;
}
@@ -631,7 +666,9 @@
// include a file
case 'include':
- $path = realpath($this->config['skin_path'].$attrib['file']);
+ 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['skin_path']).$attrib['file']);
+
if (is_readable($path)) {
if ($this->config['skin_include_php']) {
$incl = $this->include_php($path);
@@ -648,7 +685,7 @@
$hook = $this->app->plugins->exec_hook("template_plugin_include", $attrib);
return $hook['content'];
break;
-
+
// define a container block
case 'container':
if ($attrib['name'] && $attrib['id']) {
@@ -675,7 +712,7 @@
$content = call_user_func($handler, $attrib);
}
else if ($object == 'productname') {
- $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'RoundCube Webmail';
+ $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'Roundcube Webmail';
$content = Q($name);
}
else if ($object == 'version') {
@@ -694,7 +731,7 @@
$title .= $this->get_pagetitle();
$content = Q($title);
}
-
+
// exec plugin hooks for this template object
$hook = $this->app->plugins->exec_hook("template_object_$object", $attrib + array('content' => $content));
return $hook['content'];
@@ -703,7 +740,7 @@
case 'exp':
$value = $this->parse_expression($attrib['expression']);
return eval("return Q($value);");
-
+
// return variable
case 'var':
$var = explode(':', $attrib['name']);
@@ -770,7 +807,6 @@
*/
public function button($attrib)
{
- static $sa_buttons = array();
static $s_button_count = 100;
// these commands can be called directly via url
@@ -787,25 +823,14 @@
else {
$attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link';
}
+
$command = $attrib['command'];
- // take the button from the stack
- if ($attrib['name'] && $sa_buttons[$attrib['name']]) {
- $attrib = $sa_buttons[$attrib['name']];
- }
- else if($attrib['image'] || $attrib['imageact'] || $attrib['imagepas'] || $attrib['class']) {
- // add button to button stack
- if (!$attrib['name']) {
- $attrib['name'] = $command;
- }
- if (!$attrib['image']) {
- $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact'];
- }
- $sa_buttons[$attrib['name']] = $attrib;
- }
- else if ($command && $sa_buttons[$command]) {
- // get saved button for this command/name
- $attrib = $sa_buttons[$command];
+ if ($attrib['task'])
+ $command = $attrib['task'] . '.' . $command;
+
+ if (!$attrib['image']) {
+ $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact'];
}
if (!$attrib['id']) {
@@ -849,6 +874,9 @@
if (in_array($attrib['command'], rcmail::$main_tasks)) {
$attrib['href'] = rcmail_url(null, null, $attrib['command']);
}
+ else if ($attrib['task'] && in_array($attrib['task'], rcmail::$main_tasks)) {
+ $attrib['href'] = rcmail_url($attrib['command'], null, $attrib['task']);
+ }
else if (in_array($attrib['command'], $a_static_commands)) {
$attrib['href'] = rcmail_url($attrib['command']);
}
@@ -861,7 +889,11 @@
if (!$attrib['href']) {
$attrib['href'] = '#';
}
- if ($command && !$attrib['onclick']) {
+ if ($attrib['task']) {
+ if ($attrib['classact'])
+ $attrib['class'] = $attrib['classact'];
+ }
+ else if ($command && !$attrib['onclick']) {
$attrib['onclick'] = sprintf(
"return %s.command('%s','%s',this)",
JS_OBJECT_NAME,
@@ -932,17 +964,17 @@
$hiddenfield = new html_hiddenfield(array('name' => '_framed', 'value' => '1'));
$hidden = $hiddenfield->show();
}
-
+
if (!$content)
$attrib['noclose'] = true;
-
+
return html::tag('form',
$attrib + array('action' => "./", 'method' => "get"),
$hidden . $content,
array('id','class','style','name','method','action','enctype','onsubmit'));
}
-
-
+
+
/**
* Build a form tag with a unique request token
*
@@ -959,13 +991,16 @@
if ($attrib['action']) {
$hidden->add(array('name' => '_action', 'value' => $attrib['action']));
}
-
+
unset($attrib['task'], $attrib['request']);
$attrib['action'] = './';
-
+
// we already have a <form> tag
- if ($attrib['form'])
+ if ($attrib['form']) {
+ if ($this->framed || !empty($_REQUEST['_framed']))
+ $hidden->add(array('name' => '_framed', 'value' => '1'));
return $hidden->show() . $content;
+ }
else
return $this->form_tag($attrib, $hidden->show() . $content);
}
@@ -987,15 +1022,19 @@
return $username;
}
+ // Current username is an e-mail address
+ if (strpos($_SESSION['username'], '@')) {
+ $username = $_SESSION['username'];
+ }
// get e-mail address from default identity
- if ($sql_arr = $this->app->user->get_identity()) {
+ else if ($sql_arr = $this->app->user->get_identity()) {
$username = $sql_arr['email'];
}
else {
$username = $this->app->user->get_username();
}
- return $username;
+ return rcube_idn_to_utf8($username);
}
@@ -1009,22 +1048,31 @@
private function login_form($attrib)
{
$default_host = $this->config['default_host'];
+ $autocomplete = (int) $this->config['login_autocomplete'];
$_SESSION['temp'] = true;
-
+
// save original url
$url = get_input_value('_url', RCUBE_INPUT_POST);
if (empty($url) && !preg_match('/_(task|action)=logout/', $_SERVER['QUERY_STRING']))
$url = $_SERVER['QUERY_STRING'];
- $input_user = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser') + $attrib);
- $input_pass = new html_passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd') + $attrib);
+ // set atocomplete attribute
+ $user_attrib = $autocomplete > 0 ? array() : array('autocomplete' => 'off');
+ $host_attrib = $autocomplete > 0 ? array() : array('autocomplete' => 'off');
+ $pass_attrib = $autocomplete > 1 ? array() : array('autocomplete' => 'off');
+
+ $input_task = new html_hiddenfield(array('name' => '_task', 'value' => 'login'));
$input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login'));
$input_tzone = new html_hiddenfield(array('name' => '_timezone', 'id' => 'rcmlogintz', 'value' => '_default_'));
$input_url = new html_hiddenfield(array('name' => '_url', 'id' => 'rcmloginurl', 'value' => $url));
+ $input_user = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser')
+ + $attrib + $user_attrib);
+ $input_pass = new html_passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd')
+ + $attrib + $pass_attrib);
$input_host = null;
- if (is_array($default_host)) {
+ if (is_array($default_host) && count($default_host) > 1) {
$input_host = new html_select(array('name' => '_host', 'id' => 'rcmloginhost'));
foreach ($default_host as $key => $value) {
@@ -1037,8 +1085,14 @@
}
}
}
+ else if (is_array($default_host) && ($host = array_pop($default_host))) {
+ $hide_host = true;
+ $input_host = new html_hiddenfield(array(
+ 'name' => '_host', 'id' => 'rcmloginhost', 'value' => $host) + $attrib);
+ }
else if (empty($default_host)) {
- $input_host = new html_inputfield(array('name' => '_host', 'id' => 'rcmloginhost') + $attrib);
+ $input_host = new html_inputfield(array('name' => '_host', 'id' => 'rcmloginhost')
+ + $attrib + $host_attrib);
}
$form_name = !empty($attrib['form']) ? $attrib['form'] : 'form';
@@ -1048,25 +1102,30 @@
$table = new html_table(array('cols' => 2));
$table->add('title', html::label('rcmloginuser', Q(rcube_label('username'))));
- $table->add(null, $input_user->show(get_input_value('_user', RCUBE_INPUT_POST)));
+ $table->add(null, $input_user->show(get_input_value('_user', RCUBE_INPUT_GPC)));
$table->add('title', html::label('rcmloginpwd', Q(rcube_label('password'))));
$table->add(null, $input_pass->show());
// add host selection row
- if (is_object($input_host)) {
+ if (is_object($input_host) && !$hide_host) {
$table->add('title', html::label('rcmloginhost', Q(rcube_label('server'))));
- $table->add(null, $input_host->show(get_input_value('_host', RCUBE_INPUT_POST)));
+ $table->add(null, $input_host->show(get_input_value('_host', RCUBE_INPUT_GPC)));
}
- $out = $input_action->show();
+ $out = $input_task->show();
+ $out .= $input_action->show();
$out .= $input_tzone->show();
$out .= $input_url->show();
$out .= $table->show();
+ if ($hide_host) {
+ $out .= $input_host->show();
+ }
+
// surround html output with a form tag
if (empty($attrib['form'])) {
- $out = $this->form_tag(array('name' => $form_name, 'method' => "post"), $out);
+ $out = $this->form_tag(array('name' => $form_name, 'method' => 'post'), $out);
}
return $out;
@@ -1115,9 +1174,9 @@
$attrib['id'] = 'rcmqsearchbox';
}
if ($attrib['type'] == 'search' && !$this->browser->khtml) {
- unset($attrib['type'], $attrib['results']);
+ unset($attrib['type'], $attrib['results']);
}
-
+
$input_q = new html_inputfield($attrib);
$out = $input_q->show();
@@ -1129,7 +1188,7 @@
'name' => "rcmqsearchform",
'onsubmit' => JS_OBJECT_NAME . ".command('search');return false;",
'style' => "display:inline"),
- $out);
+ $out);
}
return $out;
@@ -1173,8 +1232,8 @@
'UTF-8' => 'UTF-8 ('.rcube_label('unicode').')',
'US-ASCII' => 'ASCII ('.rcube_label('english').')',
'ISO-8859-1' => 'ISO-8859-1 ('.rcube_label('westerneuropean').')',
- 'ISO-8859-2' => 'ISO-8895-2 ('.rcube_label('easterneuropean').')',
- 'ISO-8859-4' => 'ISO-8895-4 ('.rcube_label('baltic').')',
+ 'ISO-8859-2' => 'ISO-8859-2 ('.rcube_label('easterneuropean').')',
+ 'ISO-8859-4' => 'ISO-8859-4 ('.rcube_label('baltic').')',
'ISO-8859-5' => 'ISO-8859-5 ('.rcube_label('cyrillic').')',
'ISO-8859-6' => 'ISO-8859-6 ('.rcube_label('arabic').')',
'ISO-8859-7' => 'ISO-8859-7 ('.rcube_label('greek').')',
@@ -1206,15 +1265,15 @@
);
if (!empty($_POST['_charset']))
- $set = $_POST['_charset'];
- else if (!empty($attrib['selected']))
- $set = $attrib['selected'];
- else
- $set = $this->get_charset();
+ $set = $_POST['_charset'];
+ else if (!empty($attrib['selected']))
+ $set = $attrib['selected'];
+ else
+ $set = $this->get_charset();
- $set = strtoupper($set);
- if (!isset($charsets[$set]))
- $charsets[$set] = $set;
+ $set = strtoupper($set);
+ if (!isset($charsets[$set]))
+ $charsets[$set] = $set;
$select = new html_select($field_attrib);
$select->add(array_values($charsets), array_keys($charsets));
--
Gitblit v1.9.1