comparison program/include/rcmail_output_html.php @ 18:b631c1c7a3ce

More cleaning up more php8 Warnings/deprecations, including _many_ ediff-based fixes on rcmail_output_html.php
author Charlie Root
date Tue, 07 Oct 2025 11:20:40 -0400
parents 3a5f959af5ae
children 303b85d5b561
comparison
equal deleted inserted replaced
17:dd5ed6ef69c9 18:b631c1c7a3ce
68 $this->devel_mode = $this->config->get('devel_mode'); 68 $this->devel_mode = $this->config->get('devel_mode');
69 69
70 $this->set_env('task', $task); 70 $this->set_env('task', $task);
71 $this->set_env('x_frame_options', $this->config->get('x_frame_options', 'sameorigin')); 71 $this->set_env('x_frame_options', $this->config->get('x_frame_options', 'sameorigin'));
72 $this->set_env('standard_windows', (bool) $this->config->get('standard_windows')); 72 $this->set_env('standard_windows', (bool) $this->config->get('standard_windows'));
73 $this->set_env('locale', $_SESSION['language']); 73 $this->set_env('locale', !empty($_SESSION['language']) ? $_SESSION['language'] : 'en_US');
74 $this->set_env('devel_mode', $this->devel_mode); 74 $this->set_env('devel_mode', $this->devel_mode);
75 75
76 // add cookie info 76 // add cookie info
77 $this->set_env('cookie_domain', ini_get('session.cookie_domain')); 77 $this->set_env('cookie_domain', ini_get('session.cookie_domain'));
78 $this->set_env('cookie_path', ini_get('session.cookie_path')); 78 $this->set_env('cookie_path', ini_get('session.cookie_path'));
83 $this->set_skin($skin); 83 $this->set_skin($skin);
84 $this->set_env('skin', $skin); 84 $this->set_env('skin', $skin);
85 85
86 $this->set_assets_path($this->config->get('assets_path'), $this->config->get('assets_dir')); 86 $this->set_assets_path($this->config->get('assets_path'), $this->config->get('assets_dir'));
87 87
88 if (!empty($_REQUEST['_extwin'])) 88 if (!empty($_REQUEST['_extwin'])) {
89 $this->set_env('extwin', 1); 89 $this->set_env('extwin', 1);
90 if ($this->framed || $framed) 90 }
91
92 if ($this->framed || $framed) {
91 $this->set_env('framed', 1); 93 $this->set_env('framed', 1);
94 }
92 95
93 $lic = <<<EOF 96 $lic = <<<EOF
94 /* 97 /*
95 @licstart The following is the entire license notice for the 98 @licstart The following is the entire license notice for the
96 JavaScript code in this page. 99 JavaScript code in this page.
208 protected function get_pagetitle() 211 protected function get_pagetitle()
209 { 212 {
210 if (!empty($this->pagetitle)) { 213 if (!empty($this->pagetitle)) {
211 $title = $this->pagetitle; 214 $title = $this->pagetitle;
212 } 215 }
213 else if ($this->env['task'] == 'login') { 216 else if (isset($this->env['task'])) {
214 $title = $this->app->gettext(array( 217 if ($this->env['task'] == 'login') {
215 'name' => 'welcome', 218 $title = $this->app->gettext([
216 'vars' => array('product' => $this->config->get('product_name') 219 'name' => 'welcome',
217 ))); 220 'vars' => ['product' => $this->config->get('product_name')]
221 ]);
222 }
223 else {
224 $title = ucfirst($this->env['task']);
225 }
218 } 226 }
219 else { 227 else {
220 $title = ucfirst($this->env['task']); 228 $title = '';
221 } 229 }
222 230
223 return $title; 231 return $title;
224 } 232 }
225 233
283 291
284 $meta['path'] = $skin_path; 292 $meta['path'] = $skin_path;
285 $path_elements = explode('/', $skin_path); 293 $path_elements = explode('/', $skin_path);
286 $skin_id = end($path_elements); 294 $skin_id = end($path_elements);
287 295
288 if (!$meta['name']) { 296 if (empty($meta['name'])) {
289 $meta['name'] = $skin_id; 297 $meta['name'] = $skin_id;
290 } 298 }
291 299
292 $this->skins[$skin_id] = $meta; 300 $this->skins[$skin_id] = $meta;
293 301
294 if ($meta['extends']) { 302 if (!empty($meta['extends'])) {
295 $path = RCUBE_INSTALL_PATH . 'skins/'; 303 $path = RCUBE_INSTALL_PATH . 'skins/';
296 if (is_dir($path . $meta['extends']) && is_readable($path . $meta['extends'])) { 304 if (is_dir($path . $meta['extends']) && is_readable($path . $meta['extends'])) {
297 $this->load_skin('skins/' . $meta['extends']); 305 $this->load_skin('skins/' . $meta['extends']);
298 } 306 }
299 } 307 }
308 */ 316 */
309 public function template_exists($name) 317 public function template_exists($name)
310 { 318 {
311 foreach ($this->skin_paths as $skin_path) { 319 foreach ($this->skin_paths as $skin_path) {
312 $filename = RCUBE_INSTALL_PATH . $skin_path . '/templates/' . $name . '.html'; 320 $filename = RCUBE_INSTALL_PATH . $skin_path . '/templates/' . $name . '.html';
313 if ((is_file($filename) && is_readable($filename)) 321 if (
314 || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name])) 322 (is_file($filename) && is_readable($filename))
323 || (!empty($this->deprecated_templates[$name]) && $this->template_exists($this->deprecated_templates[$name]))
315 ) { 324 ) {
316 return true; 325 return true;
317 } 326 }
318 } 327 }
319 328
414 if ($this->app->text_exists($message)) { 423 if ($this->app->text_exists($message)) {
415 if (!empty($vars)) 424 if (!empty($vars))
416 $vars = array_map(array('rcube','Q'), $vars); 425 $vars = array_map(array('rcube','Q'), $vars);
417 $msgtext = $this->app->gettext(array('name' => $message, 'vars' => $vars)); 426 $msgtext = $this->app->gettext(array('name' => $message, 'vars' => $vars));
418 } 427 }
419 else 428 else {
420 $msgtext = $message; 429 $msgtext = $message;
430 }
421 431
422 $this->message = $message; 432 $this->message = $message;
423 $this->command('display_message', $msgtext, $type, $timeout * 1000); 433 $this->command('display_message', $msgtext, $type, $timeout * 1000);
424 } 434 }
425 } 435 }
460 * @param int $delay Delay in seconds 470 * @param int $delay Delay in seconds
461 * @param bool $secure Redirect to secure location (see rcmail::url()) 471 * @param bool $secure Redirect to secure location (see rcmail::url())
462 */ 472 */
463 public function redirect($p = array(), $delay = 1, $secure = false) 473 public function redirect($p = array(), $delay = 1, $secure = false)
464 { 474 {
465 if ($this->env['extwin']) 475 if (!empty($this->env['extwin']))
466 $p['extwin'] = 1; 476 $p['extwin'] = 1;
467 $location = $this->app->url($p, false, false, $secure); 477 $location = $this->app->url($p, false, false, $secure);
468 header('Location: ' . $location); 478 header('Location: ' . $location);
469 exit; 479 exit;
470 } 480 }
523 $this->header = ''; 533 $this->header = '';
524 $this->footer = ''; 534 $this->footer = '';
525 } 535 }
526 536
527 // write all javascript commands 537 // write all javascript commands
528 $this->add_script($commands, 'head_top'); 538 if (!empty($commands)) {
539 $this->add_script($commands, 'head_top');
540 }
529 541
530 // allow (legal) iframe content to be loaded 542 // allow (legal) iframe content to be loaded
531 $iframe = $this->framed || $this->env['framed']; 543 $iframe = $this->framed || !empty($this->env['framed']);
532 if (!headers_sent() && $iframe && ($xopt = $this->app->config->get('x_frame_options', 'sameorigin'))) { 544 if (!headers_sent() && $iframe && ($xopt = $this->app->config->get('x_frame_options', 'sameorigin'))) {
533 if (strtolower($xopt) != 'sameorigin') { 545 if (strtolower($xopt) != 'sameorigin') {
534 header('X-Frame-Options: sameorigin', true); 546 header('X-Frame-Options: sameorigin', true);
535 } 547 }
536 } 548 }
581 $path = false; 593 $path = false;
582 foreach ($this->skin_paths as $skin_path) { 594 foreach ($this->skin_paths as $skin_path) {
583 $path = RCUBE_INSTALL_PATH . "$skin_path/templates/$name.html"; 595 $path = RCUBE_INSTALL_PATH . "$skin_path/templates/$name.html";
584 596
585 // fallback to deprecated template names 597 // fallback to deprecated template names
586 if (!is_readable($path) && ($dname = $this->deprecated_templates[$realname])) { 598 if (!is_readable($path) && !empty($this->deprecated_templates[$realname])) {
587 $path = RCUBE_INSTALL_PATH . "$skin_path/templates/$dname.html"; 599 $dname = $this->deprecated_templates[$realname];
600 $path = RCUBE_INSTALL_PATH . "$skin_path/templates/$dname.html";
588 601
589 if (is_readable($path)) { 602 if (is_readable($path)) {
590 rcube::raise_error(array( 603 rcube::raise_error(array(
591 'code' => 502, 'file' => __FILE__, 'line' => __LINE__, 604 'code' => 502, 'file' => __FILE__, 'line' => __LINE__,
592 'message' => "Using deprecated template '$dname' in $skin_path/templates. Please rename to '$realname'" 605 'message' => "Using deprecated template '$dname' in $skin_path/templates. Please rename to '$realname'"
629 array($this->app->plugins->url, '\\1'.$this->app->plugins->url.$skin_dir.'/'), 642 array($this->app->plugins->url, '\\1'.$this->app->plugins->url.$skin_dir.'/'),
630 $templ 643 $templ
631 ); 644 );
632 } 645 }
633 646
634 // parse for specialtags 647 // parse for special tags
635 $output = $this->parse_conditions($templ); 648 $output = $this->parse_conditions($templ);
636 $output = $this->parse_xml($output); 649 $output = $this->parse_xml($output);
637 #rcube::write_log('mail',"px: ".strlen($output)); 650 #rcube::write_log('mail',"px: ".strlen($output));
638 651
639 // trigger generic hook where plugins can put additional content to the page 652 // trigger generic hook where plugins can put additional content to the page
662 */ 675 */
663 protected function get_js_commands(&$framed = null) 676 protected function get_js_commands(&$framed = null)
664 { 677 {
665 $out = ''; 678 $out = '';
666 $parent_commands = 0; 679 $parent_commands = 0;
680 $parent_prefix = '';
667 $top_commands = array(); 681 $top_commands = array();
668 682
669 // these should be always on top, 683 // these should be always on top,
670 // e.g. hide_message() below depends on env.framed 684 // e.g. hide_message() below depends on env.framed
671 if (!$this->framed && !empty($this->js_env)) { 685 if (!$this->framed && !empty($this->js_env)) {
674 if (!empty($this->js_labels)) { 688 if (!empty($this->js_labels)) {
675 $top_commands[] = array('add_label', $this->js_labels); 689 $top_commands[] = array('add_label', $this->js_labels);
676 } 690 }
677 691
678 // unlock interface after iframe load 692 // unlock interface after iframe load
679 $unlock = preg_replace('/[^a-z0-9]/i', '', $_REQUEST['_unlock']); 693 $unlock = isset($_REQUEST['_unlock']) ? preg_replace('/[^a-z0-9]/i', '', $_REQUEST['_unlock']) : 0;
680 if ($this->framed) { 694 if ($this->framed) {
681 $top_commands[] = array('iframe_loaded', $unlock); 695 $top_commands[] = array('iframe_loaded', $unlock);
682 } 696 }
683 else if ($unlock) { 697 else if ($unlock) {
684 $top_commands[] = array('hide_message', $unlock); 698 $top_commands[] = array('hide_message', $unlock);
727 * 741 *
728 * @return string URL 742 * @return string URL
729 */ 743 */
730 public function abs_url($str, $search_path = false) 744 public function abs_url($str, $search_path = false)
731 { 745 {
732 if ($str[0] == '/') { 746 if (isset($str[0]) && $str[0] == '/') {
733 if ($search_path && ($file_url = $this->get_skin_file($str, $skin_path))) { 747 if ($search_path && ($file_url = $this->get_skin_file($str, $skin_path))) {
734 return $file_url; 748 return $file_url;
735 } 749 }
736 750
737 return $this->base_path . $str; 751 return $this->base_path . $str;
875 889
876 return $file; 890 return $file;
877 } 891 }
878 892
879 /** 893 /**
880 * Public wrapper to dipp into template parsing. 894 * Public wrapper to dip into template parsing.
881 * 895 *
882 * @param string $input Template content 896 * @param string $input Template content
883 * 897 *
884 * @return string 898 * @return string
885 * @uses rcmail_output_html::parse_xml() 899 * @uses rcmail_output_html::parse_xml()
955 protected function alter_form_tag($matches) 969 protected function alter_form_tag($matches)
956 { 970 {
957 $out = $matches[0]; 971 $out = $matches[0];
958 $attrib = html::parse_attrib_string($matches[1]); 972 $attrib = html::parse_attrib_string($matches[1]);
959 973
960 if (strtolower($attrib['method']) == 'post') { 974 if (!empty($attrib['method']) && strtolower($attrib['method']) == 'post') {
961 $hidden = new html_hiddenfield(array('name' => '_token', 'value' => $this->app->get_request_token())); 975 $hidden = new html_hiddenfield(array('name' => '_token', 'value' => $this->app->get_request_token()));
962 $out .= "\n" . $hidden->show(); 976 $out .= "\n" . $hidden->show();
963 } 977 }
964 978
965 return $out; 979 return $out;
985 '/template:name/i', 999 '/template:name/i',
986 ), 1000 ),
987 array( 1001 array(
988 "\$_SESSION['\\1']", 1002 "\$_SESSION['\\1']",
989 "\$this->app->config->get('\\1',rcube_utils::get_boolean('\\3'))", 1003 "\$this->app->config->get('\\1',rcube_utils::get_boolean('\\3'))",
990 "\$this->env['\\1']", 1004 "(\$this->env['\\1'] ?? null)",
991 "rcube_utils::get_input_value('\\1', rcube_utils::INPUT_GPC)", 1005 "rcube_utils::get_input_value('\\1', rcube_utils::INPUT_GPC)",
992 "\$_COOKIE['\\1']", 1006 "(\$_COOKIE['\\1'] ?? null)",
993 "\$this->browser->{'\\1'}", 1007 "(\$this->browser->{'\\1'} ?? null)",
994 "'{$this->template_name}'", 1008 "'{$this->template_name}'",
995 ), 1009 ),
996 $expression 1010 $expression
997 ); 1011 );
998 1012
1044 1058
1045 // execute command 1059 // execute command
1046 switch ($command) { 1060 switch ($command) {
1047 // return a button 1061 // return a button
1048 case 'button': 1062 case 'button':
1049 if ($attrib['name'] || $attrib['command']) { 1063 if (!empty($attrib['name']) || !empty($attrib['command'])) {
1050 #rcube::write_log('lab',"button in: ".print_r($attrib,true)); 1064 #rcube::write_log('lab',"button in: ".print_r($attrib,true));
1051 $but = $this->button($attrib); 1065 $but = $this->button($attrib);
1052 #rcube::write_log('lab',"button out:\n$but"); 1066 #rcube::write_log('lab',"button out:\n$but");
1053 return $but; 1067 return $but;
1054 1068
1060 return $this->frame($attrib); 1074 return $this->frame($attrib);
1061 break; 1075 break;
1062 1076
1063 // show a label 1077 // show a label
1064 case 'label': 1078 case 'label':
1065 if ($attrib['expression']) 1079 if (!empty($attrib['expression'])) {
1066 $attrib['name'] = $this->eval_expression($attrib['expression']); 1080 $attrib['name'] = $this->eval_expression($attrib['expression']);
1067 1081 }
1068 if ($attrib['name'] || $attrib['command']) { 1082
1069 $vars = $attrib + array('product' => $this->config->get('product_name')); 1083 if (!empty($attrib['name']) || !empty($attrib['command'])) {
1084 $vars = $attrib + ['product' => $this->config->get('product_name')];
1070 unset($vars['name'], $vars['command']); 1085 unset($vars['name'], $vars['command']);
1071 1086
1072 $label = $this->app->gettext($attrib + array('vars' => $vars)); 1087 $label = $this->app->gettext($attrib + ['vars' => $vars]);
1073 $quoting = !empty($attrib['quoting']) ? strtolower($attrib['quoting']) : (rcube_utils::get_boolean((string)$attrib['html']) ? 'no' : ''); 1088 $quoting = null;
1089
1090 if (!empty($attrib['quoting'])) {
1091 $quoting = strtolower($attrib['quoting']);
1092 }
1093 else if (isset($attrib['html'])) {
1094 $quoting = rcube_utils::get_boolean((string) $attrib['html']) ? 'no' : '';
1095 }
1074 1096
1075 // 'noshow' can be used in skins to define new labels 1097 // 'noshow' can be used in skins to define new labels
1076 if ($attrib['noshow']) { 1098 if (!empty($attrib['noshow'])) {
1077 return ''; 1099 return '';
1078 } 1100 }
1079 1101
1080 switch ($quoting) { 1102 switch ($quoting) {
1081 case 'no': 1103 case 'no':
1099 break; 1121 break;
1100 1122
1101 // include a file 1123 // include a file
1102 case 'include': 1124 case 'include':
1103 $old_base_path = $this->base_path; 1125 $old_base_path = $this->base_path;
1104 if (!empty($attrib['skin_path'])) $attrib['skinpath'] = $attrib['skin_path']; 1126 $attr_skin_path = !empty($attrib['skinpath']) ? $attrib['skinpath'] : null;
1105 if ($path = $this->get_skin_file($attrib['file'], $skin_path, $attrib['skinpath'])) { 1127
1128 if (!empty($attrib['skin_path'])) {
1129 $attr_skin_path = $attrib['skin_path'];
1130 }
1131
1132 if ($path = $this->get_skin_file($attrib['file'], $skin_path, $attr_skin_path)) {
1106 // set base_path to core skin directory (not plugin's skin) 1133 // set base_path to core skin directory (not plugin's skin)
1107 $this->base_path = preg_replace('!plugins/\w+/!', '', $skin_path); 1134 $this->base_path = preg_replace('!plugins/\w+/!', '', $skin_path);
1108 $path = realpath(RCUBE_INSTALL_PATH . $path); 1135 $path = realpath(RCUBE_INSTALL_PATH . $path);
1109 } 1136 }
1110 1137
1127 $hook = $this->app->plugins->exec_hook("template_plugin_include", $attrib); 1154 $hook = $this->app->plugins->exec_hook("template_plugin_include", $attrib);
1128 return $hook['content']; 1155 return $hook['content'];
1129 1156
1130 // define a container block 1157 // define a container block
1131 case 'container': 1158 case 'container':
1132 if ($attrib['name'] && $attrib['id']) { 1159 if (!empty($attrib['name']) && !empty($attrib['id'])) {
1133 $this->command('gui_container', $attrib['name'], $attrib['id']); 1160 $this->command('gui_container', $attrib['name'], $attrib['id']);
1134 // let plugins insert some content here 1161 // let plugins insert some content here
1135 $hook = $this->app->plugins->exec_hook("template_container", $attrib); 1162 $hook = $this->app->plugins->exec_hook("template_container", $attrib);
1136 return $hook['content']; 1163 return $hook['content'];
1137 } 1164 }
1139 1166
1140 // return code for a specific application object 1167 // return code for a specific application object
1141 case 'object': 1168 case 'object':
1142 $object = strtolower($attrib['name']); 1169 $object = strtolower($attrib['name']);
1143 $content = ''; 1170 $content = '';
1144 1171 $handler = null;
1145 // we are calling a class/method 1172
1146 if (($handler = $this->object_handlers[$object]) && is_array($handler)) { 1173 if (!empty($this->object_handlers[$object])) {
1147 if (is_callable($handler)) { 1174 $handler = $this->object_handlers[$object];
1148 // We assume that objects with src attribute are internal (in most
1149 // cases this is a watermark frame). We need this to make sure assets_path
1150 // is added to the internal assets paths
1151 $external = empty($attrib['src']);
1152 $content = call_user_func($handler, $attrib);
1153 }
1154 } 1175 }
1155 // execute object handler function 1176 // execute object handler function
1156 else if (function_exists($handler)) { 1177 if (is_callable($handler)) {
1157 $content = call_user_func($handler, $attrib); 1178
1179 // We assume that objects with src attribute are internal (in most
1180 // cases this is a watermark frame). We need this to make sure assets_path
1181 // is added to the internal assets paths
1182 $external = empty($attrib['src']);
1183 $content = call_user_func($handler, $attrib);
1158 } 1184 }
1159 else if ($object == 'doctype') { 1185 else if ($object == 'doctype') {
1160 $content = html::doctype($attrib['value']); 1186 $content = html::doctype($attrib['value']);
1161 } 1187 }
1162 else if ($object == 'logo') { 1188 else if ($object == 'logo') {
1183 $content = html::quote($name); 1209 $content = html::quote($name);
1184 } 1210 }
1185 else if ($object == 'version') { 1211 else if ($object == 'version') {
1186 $ver = (string)RCMAIL_VERSION; 1212 $ver = (string)RCMAIL_VERSION;
1187 if (is_file(RCUBE_INSTALL_PATH . '.svn/entries')) { 1213 if (is_file(RCUBE_INSTALL_PATH . '.svn/entries')) {
1188 if (preg_match('/Revision:\s(\d+)/', @shell_exec('svn info'), $regs)) 1214 if (preg_match('/Revision:\s(\d+)/', (string) @shell_exec('svn info'), $regs))
1189 $ver .= ' [SVN r'.$regs[1].']'; 1215 $ver .= ' [SVN r'.$regs[1].']';
1190 } 1216 }
1191 else if (is_file(RCUBE_INSTALL_PATH . '.git/index')) { 1217 else if (is_file(RCUBE_INSTALL_PATH . '.git/index')) {
1192 if (preg_match('/Date:\s+([^\n]+)/', @shell_exec('git log -1'), $regs)) { 1218 if (preg_match('/Date:\s+([^\n]+)/', (string) @shell_exec('git log -1'), $regs)) {
1193 if ($date = date('Ymd.Hi', strtotime($regs[1]))) { 1219 if ($date = date('Ymd.Hi', strtotime($regs[1]))) {
1194 $ver .= ' [GIT '.$date.']'; 1220 $ver .= ' [GIT '.$date.']';
1195 } 1221 }
1196 } 1222 }
1197 } 1223 }
1210 $title .= $this->get_pagetitle(); 1236 $title .= $this->get_pagetitle();
1211 $content = html::quote($title); 1237 $content = html::quote($title);
1212 } 1238 }
1213 1239
1214 // exec plugin hooks for this template object 1240 // exec plugin hooks for this template object
1215 $hook = $this->app->plugins->exec_hook("template_object_$object", $attrib + array('content' => $content)); 1241 $hook = $this->app->plugins->exec_hook("template_object_$object", $attrib + array('content' => (string) $content));
1216 1242
1217 if (strlen($hook['content']) && !empty($external)) { 1243 if (strlen($hook['content']) && !empty($external)) {
1218 $object_id = uniqid('TEMPLOBJECT:', true); 1244 $object_id = uniqid('TEMPLOBJECT:', true);
1219 $this->objects[$object_id] = $hook['content']; 1245 $this->objects[$object_id] = $hook['content'];
1220 $hook['content'] = $object_id; 1246 $hook['content'] = $object_id;
1232 $name = $var[1]; 1258 $name = $var[1];
1233 $value = ''; 1259 $value = '';
1234 1260
1235 switch ($var[0]) { 1261 switch ($var[0]) {
1236 case 'env': 1262 case 'env':
1237 $value = $this->env[$name]; 1263 $value = $this->env[$name] ?? null;
1238 break; 1264 break;
1239 case 'config': 1265 case 'config':
1240 $value = $this->config->get($name); 1266 $value = $this->config->get($name);
1241 if (is_array($value) && $value[$_SESSION['storage_host']]) { 1267 if (is_array($value) && !empty($value[$_SESSION['storage_host']])) {
1242 $value = $value[$_SESSION['storage_host']]; 1268 $value = $value[$_SESSION['storage_host']];
1243 } 1269 }
1244 break; 1270 break;
1245 case 'request': 1271 case 'request':
1246 $value = rcube_utils::get_input_value($name, rcube_utils::INPUT_GPC); 1272 $value = rcube_utils::get_input_value($name, rcube_utils::INPUT_GPC);
1247 break; 1273 break;
1248 case 'session': 1274 case 'session':
1249 $value = $_SESSION[$name]; 1275 $value = $_SESSION[$name] ?? '';
1250 break; 1276 break;
1251 case 'cookie': 1277 case 'cookie':
1252 $value = htmlspecialchars($_COOKIE[$name]); 1278 $value = htmlspecialchars($_COOKIE[$name]);
1253 break; 1279 break;
1254 case 'browser': 1280 case 'browser':
1255 $value = $this->browser->{$name}; 1281 $value = $this->browser->{$name} ?? '';
1256 break; 1282 break;
1257 } 1283 }
1258 1284
1259 if (is_array($value)) { 1285 if (is_array($value)) {
1260 $value = implode(', ', $value); 1286 $value = implode(', ', $value);
1290 */ 1316 */
1291 protected function postrender($output) 1317 protected function postrender($output)
1292 { 1318 {
1293 // insert objects' contents 1319 // insert objects' contents
1294 foreach ($this->objects as $key => $val) { 1320 foreach ($this->objects as $key => $val) {
1295 $output = str_replace($key, $val, $output, $count); 1321 $output = str_replace($key, (string) $val, $output, $count);
1296 if ($count) { 1322 if ($count) {
1297 $this->objects[$key] = null; 1323 $this->objects[$key] = null;
1298 } 1324 }
1299 } 1325 }
1300 1326
1319 static $disabled_actions = null; 1345 static $disabled_actions = null;
1320 1346
1321 // these commands can be called directly via url 1347 // these commands can be called directly via url
1322 $a_static_commands = array('compose', 'list', 'preferences', 'folders', 'identities'); 1348 $a_static_commands = array('compose', 'list', 'preferences', 'folders', 'identities');
1323 1349
1324 if (!($attrib['command'] || $attrib['name'] || $attrib['href'])) { 1350 if (empty($attrib['command']) && empty($attrib['name']) && empty($attrib['href'])) {
1325 return ''; 1351 return '';
1326 } 1352 }
1327 1353
1328 // try to find out the button type 1354 // try to find out the button type
1329 if ($attrib['type']) { 1355 if (!empty($attrib['type'])) {
1330 $attrib['type'] = strtolower($attrib['type']); 1356 $attrib['type'] = strtolower($attrib['type']);
1331 if ($pos = strpos($attrib['type'], '-menuitem')) { 1357 if ($pos = strpos($attrib['type'], '-menuitem')) {
1332 $attrib['type'] = substr($attrib['type'], 0, -9); 1358 $attrib['type'] = substr($attrib['type'], 0, -9);
1333 $menuitem = true; 1359 $menuitem = true;
1334 } 1360 }
1335 } 1361 }
1336 else { 1362 else {
1337 $attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link'; 1363 $attrib['type'] = (!empty($attrib['image']) || !empty($attrib['imagepas']) || !empty($attrib['imageact'])) ? 'image' : 'link';
1338 } 1364 }
1339 1365
1340 $command = $attrib['command']; 1366 $command = $attrib['command']??'';
1341 1367
1342 if ($attrib['task']) { 1368 if (!empty($attrib['task'])) {
1343 $element = $command = $attrib['task'] . '.' . $command; 1369 $element = $command = $attrib['task'] . '.' . $command;
1344 } 1370 }
1345 else { 1371 else {
1346 $element = ($this->env['task'] ? $this->env['task'] . '.' : '') . $command; 1372 $element = (!empty($this->env['task']) ? $this->env['task'] . '.' : '') . $command;
1347 } 1373 }
1348 1374
1349 if ($disabled_actions === null) { 1375 if ($disabled_actions === null) {
1350 $disabled_actions = (array) $this->config->get('disabled_actions'); 1376 $disabled_actions = (array) $this->config->get('disabled_actions');
1351 } 1377 }
1353 // remove buttons for disabled actions 1379 // remove buttons for disabled actions
1354 if (in_array($element, $disabled_actions)) { 1380 if (in_array($element, $disabled_actions)) {
1355 return ''; 1381 return '';
1356 } 1382 }
1357 1383
1358 if (!$attrib['image']) { 1384 if (empty($attrib['image'])) {
1359 $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact']; 1385 if (!empty($attrib['imagepas'])) {
1360 } 1386 $attrib['image'] = $attrib['imagepas'];
1361 1387 }
1362 if (!$attrib['id']) { 1388 else if (!empty($attrib['imageact'])) {
1389 $attrib['image'] = $attrib['imageact'];
1390 }
1391 }
1392
1393 if (empty($attrib['id'])) {
1363 $attrib['id'] = sprintf('rcmbtn%d', $s_button_count++); 1394 $attrib['id'] = sprintf('rcmbtn%d', $s_button_count++);
1364 } 1395 }
1365 // get localized text for labels and titles 1396 // get localized text for labels and titles
1366 if ($attrib['title']) { 1397 $domain = !empty($attrib['domain']) ? $attrib['domain'] : null;
1367 $attrib['title'] = html::quote($this->app->gettext($attrib['title'], $attrib['domain'])); 1398 if (!empty($attrib['title'])) {
1368 } 1399 $attrib['title'] = html::quote($this->app->gettext($attrib['title'], $domain));
1369 if ($attrib['label']) { 1400 }
1370 $attrib['label'] = html::quote($this->app->gettext($attrib['label'], $attrib['domain'])); 1401 if (!empty($attrib['label'])) {
1371 } 1402 $attrib['label'] = html::quote($this->app->gettext($attrib['label'], $domain));
1372 if ($attrib['alt']) { 1403 }
1373 $attrib['alt'] = html::quote($this->app->gettext($attrib['alt'], $attrib['domain'])); 1404 if (!empty($attrib['alt'])) {
1405 $attrib['alt'] = html::quote($this->app->gettext($attrib['alt'], $domain));
1374 } 1406 }
1375 1407
1376 // set accessibility attributes 1408 // set accessibility attributes
1377 if (!$attrib['role']) { 1409 if (empty($attrib['role'])) {
1378 $attrib['role'] = 'button'; 1410 $attrib['role'] = 'button';
1379 } 1411 }
1380 if (!empty($attrib['class']) && !empty($attrib['classact']) || !empty($attrib['imagepas']) && !empty($attrib['imageact'])) { 1412 if (!empty($attrib['class']) && !empty($attrib['classact']) || !empty($attrib['imagepas']) && !empty($attrib['imageact'])) {
1381 if (array_key_exists('tabindex', $attrib)) 1413 if (array_key_exists('tabindex', $attrib)) {
1382 $attrib['data-tabindex'] = $attrib['tabindex']; 1414 $attrib['data-tabindex'] = $attrib['tabindex'];
1383 $attrib['tabindex'] = '-1'; // disable button by default 1415 }
1416 $attrib['tabindex'] = '-1'; // disable button by default
1384 $attrib['aria-disabled'] = 'true'; 1417 $attrib['aria-disabled'] = 'true';
1385 } 1418 }
1386 1419
1387 // set title to alt attribute for IE browsers 1420 // set title to alt attribute for IE browsers
1388 if ($this->browser->ie && !$attrib['title'] && $attrib['alt']) { 1421 if ($this->browser->ie && empty($attrib['title']) && !empty($attrib['alt'])) {
1389 $attrib['title'] = $attrib['alt']; 1422 $attrib['title'] = $attrib['alt'];
1390 } 1423 }
1391 1424
1392 // add empty alt attribute for XHTML compatibility 1425 // add empty alt attribute for XHTML compatibility
1393 if (!isset($attrib['alt'])) { 1426 if (!isset($attrib['alt'])) {
1394 $attrib['alt'] = ''; 1427 $attrib['alt'] = '';
1395 } 1428 }
1396 1429
1397 // register button in the system 1430 // register button in the system
1398 if ($attrib['command']) { 1431 if (!empty($attrib['command'])) {
1399 $this->add_script(sprintf( 1432 $this->add_script(sprintf(
1400 "%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');", 1433 "%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');",
1401 self::JS_OBJECT_NAME, 1434 self::JS_OBJECT_NAME,
1402 $command, 1435 $command,
1403 $attrib['id'], 1436 $attrib['id'],
1404 $attrib['type'], 1437 $attrib['type'],
1405 $attrib['imageact'] ? $this->abs_url($attrib['imageact']) : $attrib['classact'], 1438 !empty($attrib['imageact']) ? $this->abs_url($attrib['imageact']) : (!empty($attrib['classact']) ? $attrib['classact'] : ''),
1406 $attrib['imagesel'] ? $this->abs_url($attrib['imagesel']) : $attrib['classsel'], 1439 !empty($attrib['imagesel']) ? $this->abs_url($attrib['imagesel']) : (!empty($attrib['classsel']) ? $attrib['classsel'] : ''),
1407 $attrib['imageover'] ? $this->abs_url($attrib['imageover']) : '' 1440 !empty($attrib['imageover']) ? $this->abs_url($attrib['imageover']) : ''
1408 )); 1441 ));
1409 1442
1410 // make valid href to specific buttons 1443 // make valid href to specific buttons
1411 if (in_array($attrib['command'], rcmail::$main_tasks)) { 1444 if (in_array($attrib['command'], rcmail::$main_tasks)) {
1412 $attrib['href'] = $this->app->url(array('task' => $attrib['command'])); 1445 $attrib['href'] = $this->app->url(array('task' => $attrib['command']));
1413 $attrib['onclick'] = sprintf("return %s.command('switch-task','%s',this,event)", self::JS_OBJECT_NAME, $attrib['command']); 1446 $attrib['onclick'] = sprintf("return %s.command('switch-task','%s',this,event)", self::JS_OBJECT_NAME, $attrib['command']);
1414 } 1447 }
1415 else if ($attrib['task'] && in_array($attrib['task'], rcmail::$main_tasks)) { 1448 else if (!empty($attrib['task']) && in_array($attrib['task'], rcmail::$main_tasks)) {
1416 $attrib['href'] = $this->app->url(array('action' => $attrib['command'], 'task' => $attrib['task'])); 1449 $attrib['href'] = $this->app->url(['action' => $attrib['command'], 'task' => $attrib['task']]);
1417 } 1450 }
1418 else if (in_array($attrib['command'], $a_static_commands)) { 1451 else if (in_array($attrib['command'], $a_static_commands)) {
1419 $attrib['href'] = $this->app->url(array('action' => $attrib['command'])); 1452 $attrib['href'] = $this->app->url(array('action' => $attrib['command']));
1420 } 1453 }
1421 else if (($attrib['command'] == 'permaurl' || $attrib['command'] == 'extwin') && !empty($this->env['permaurl'])) { 1454 else if (($attrib['command'] == 'permaurl' || $attrib['command'] == 'extwin') && !empty($this->env['permaurl'])) {
1422 $attrib['href'] = $this->env['permaurl']; 1455 $attrib['href'] = $this->env['permaurl'];
1423 } 1456 }
1424 } 1457 }
1425 1458
1426 // overwrite attributes 1459 // overwrite attributes
1427 if (!$attrib['href']) { 1460 if (empty($attrib['href'])) {
1428 $attrib['href'] = '#'; 1461 $attrib['href'] = '#';
1429 } 1462 }
1430 if ($attrib['task']) { 1463
1431 if ($attrib['classact']) 1464 if (!empty($attrib['task'])) {
1465 if (!empty($attrib['classact'])) {
1432 $attrib['class'] = $attrib['classact']; 1466 $attrib['class'] = $attrib['classact'];
1433 } 1467 }
1434 else if ($command && !$attrib['onclick']) { 1468 }
1469 else if ($command && empty($attrib['onclick'])) {
1435 $attrib['onclick'] = sprintf( 1470 $attrib['onclick'] = sprintf(
1436 "return %s.command('%s','%s',this,event)", 1471 "return %s.command('%s','%s',this,event)",
1437 self::JS_OBJECT_NAME, 1472 self::JS_OBJECT_NAME,
1438 $command, 1473 $command,
1439 $attrib['prop'] 1474 !empty($attrib['prop']) ? $attrib['prop'] : ''
1440 ); 1475 );
1441 } 1476 }
1442 1477
1443 $out = ''; 1478 $out = '';
1479 $btn_content = null;
1480 $link_attrib = [];
1444 1481
1445 // generate image tag 1482 // generate image tag
1446 if ($attrib['type'] == 'image') { 1483 if ($attrib['type'] == 'image') {
1447 $attrib_str = html::attrib_string( 1484 $attrib_str = html::attrib_string(
1448 $attrib, 1485 $attrib,
1450 'style', 'class', 'id', 'width', 'height', 'border', 'hspace', 1487 'style', 'class', 'id', 'width', 'height', 'border', 'hspace',
1451 'vspace', 'align', 'alt', 'tabindex', 'title' 1488 'vspace', 'align', 'alt', 'tabindex', 'title'
1452 ) 1489 )
1453 ); 1490 );
1454 $btn_content = sprintf('<img src="%s"%s />', $this->abs_url($attrib['image']), $attrib_str); 1491 $btn_content = sprintf('<img src="%s"%s />', $this->abs_url($attrib['image']), $attrib_str);
1455 if ($attrib['label']) { 1492 if (!empty($attrib['label'])) {
1456 $btn_content .= ' '.$attrib['label']; 1493 $btn_content .= ' '.$attrib['label'];
1457 } 1494 }
1458 $link_attrib = array('href', 'onclick', 'onmouseover', 'onmouseout', 'onmousedown', 'onmouseup', 'target'); 1495 $link_attrib = array('href', 'onclick', 'onmouseover', 'onmouseout', 'onmousedown', 'onmouseup', 'target');
1459 } 1496 }
1460 else if ($attrib['type'] == 'link') { 1497 else if ($attrib['type'] == 'link') {
1461 $btn_content = isset($attrib['content']) ? $attrib['content'] : ($attrib['label'] ? $attrib['label'] : $attrib['command']); 1498 $btn_content = $attrib['content'] ?? (!empty($attrib['label']) ? $attrib['label'] : $attrib['command']);
1462 $link_attrib = array_merge(html::$common_attrib, array('href', 'onclick', 'tabindex', 'target')); 1499 $link_attrib = array_merge(html::$common_attrib, ['href', 'onclick', 'tabindex', 'target', 'rel']);
1463 if ($attrib['innerclass']) 1500 if (!empty($attrib['innerclass'])) {
1464 $btn_content = html::span($attrib['innerclass'], $btn_content); 1501 $btn_content = html::span($attrib['innerclass'], $btn_content);
1502 }
1465 } 1503 }
1466 else if ($attrib['type'] == 'input') { 1504 else if ($attrib['type'] == 'input') {
1467 $attrib['type'] = 'button'; 1505 $attrib['type'] = 'button';
1468 1506
1469 if ($attrib['label']) { 1507 if (!empty($attrib['label'])) {
1470 $attrib['value'] = $attrib['label']; 1508 $attrib['value'] = $attrib['label'];
1471 } 1509 }
1472 if ($attrib['command']) { 1510 if (!empty($attrib['command'])) {
1473 $attrib['disabled'] = 'disabled'; 1511 $attrib['disabled'] = 'disabled';
1474 } 1512 }
1475 1513
1476 $out = html::tag('input', $attrib, null, array('type', 'value', 'onclick', 'id', 'class', 'style', 'tabindex', 'disabled')); 1514 $out = html::tag('input', $attrib, null, ['type', 'value', 'onclick', 'id', 'class', 'style', 'tabindex', 'disabled']);
1515 }
1516 else {
1517 if (!empty($attrib['label'])) {
1518 $attrib['value'] = $attrib['label'];
1519 }
1520 if (!empty($attrib['command'])) {
1521 $attrib['disabled'] = 'disabled';
1522 }
1523
1524 $content = $attrib['content'] ?? $attrib['label'];
1525 $out = html::tag('button', $attrib, $content, ['type', 'value', 'onclick', 'id', 'class', 'style', 'tabindex', 'disabled']);
1477 } 1526 }
1478 1527
1479 // generate html code for button 1528 // generate html code for button
1480 if ($btn_content) { 1529 if ($btn_content) {
1481 $attrib_str = html::attrib_string($attrib, $link_attrib); 1530 $attrib_str = html::attrib_string($attrib, $link_attrib);
1482 $out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content); 1531 $out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content);
1483 } 1532 }
1484 1533
1485 if ($attrib['wrapper']) { 1534 if (!empty($attrib['wrapper'])) {
1486 $out = html::tag($attrib['wrapper'], null, $out); 1535 $out = html::tag($attrib['wrapper'], null, $out);
1487 } 1536 }
1488 1537
1489 if ($menuitem) { 1538 if (!empty($menuitem)) {
1490 $class = $attrib['menuitem-class'] ? ' class="' . $attrib['menuitem-class'] . '"' : ''; 1539 $class = !empty($attrib['menuitem-class']) ? ' class="' . $attrib['menuitem-class'] . '"' : '';
1491 $out = '<li role="menuitem"' . $class . '>' . $out . '</li>'; 1540 $out = '<li role="menuitem"' . $class . '>' . $out . '</li>';
1492 } 1541 }
1493 1542
1494 return $out; 1543 return $out;
1495 } 1544 }
1504 { 1553 {
1505 if (!preg_match('|^https?://|i', $file) && $file[0] != '/') { 1554 if (!preg_match('|^https?://|i', $file) && $file[0] != '/') {
1506 $file = $this->file_mod($this->scripts_path . $file); 1555 $file = $this->file_mod($this->scripts_path . $file);
1507 } 1556 }
1508 1557
1509 if (!is_array($this->script_files[$position])) { 1558 if (!isset($this->script_files[$position]) || !is_array($this->script_files[$position])) {
1510 $this->script_files[$position] = array(); 1559 $this->script_files[$position] = array();
1511 } 1560 }
1512 1561
1513 if (!in_array($file, $this->script_files[$position])) { 1562 if (!in_array($file, $this->script_files[$position])) {
1514 $this->script_files[$position][] = $file; 1563 $this->script_files[$position][] = $file;
1551 $this->header .= "\n" . $str; 1600 $this->header .= "\n" . $str;
1552 } 1601 }
1553 1602
1554 /** 1603 /**
1555 * Add HTML code to the page footer 1604 * Add HTML code to the page footer
1556 * To be added right befor </body> 1605 * To be added right before </body>
1557 * 1606 *
1558 * @param string $str HTML code 1607 * @param string $str HTML code
1559 */ 1608 */
1560 public function add_footer($str) 1609 public function add_footer($str)
1561 { 1610 {
1625 // put docready commands into page footer 1674 // put docready commands into page footer
1626 if (!empty($this->scripts['docready'])) { 1675 if (!empty($this->scripts['docready'])) {
1627 $this->add_script('$(document).ready(function(){ ' . $this->scripts['docready'] . "\n});", 'foot'); 1676 $this->add_script('$(document).ready(function(){ ' . $this->scripts['docready'] . "\n});", 'foot');
1628 } 1677 }
1629 1678
1630 if (is_array($this->script_files['foot'])) { 1679 if (!empty($this->script_files['foot'])) {
1631 foreach ($this->script_files['foot'] as $file) { 1680 foreach ($this->script_files['foot'] as $file) {
1632 $page_footer .= html::script($file); 1681 $page_footer .= html::script($file);
1633 } 1682 }
1634 } 1683 }
1635 1684
1656 $hpos++; 1705 $hpos++;
1657 } 1706 }
1658 $page_header = "<head>\n<title>$page_title</title>\n$page_header\n</head>\n"; 1707 $page_header = "<head>\n<title>$page_title</title>\n$page_header\n</head>\n";
1659 } 1708 }
1660 1709
1661 // add page hader 1710 // add page header
1662 if ($hpos) { 1711 if ($hpos) {
1663 $output = substr_replace($output, $page_header, $hpos, 0); 1712 $output = substr_replace($output, $page_header, $hpos, 0);
1664 } 1713 }
1665 else { 1714 else {
1666 $output = $page_header . $output; 1715 $output = $page_header . $output;
1673 else { 1722 else {
1674 $output .= "\n".$page_footer; 1723 $output .= "\n".$page_footer;
1675 } 1724 }
1676 1725
1677 // add css files in head, before scripts, for speed up with parallel downloads 1726 // add css files in head, before scripts, for speed up with parallel downloads
1678 if (!empty($this->css_files) && !$is_empty 1727 if (!empty($this->css_files) && empty($is_empty)
1679 && (($pos = stripos($output, '<script ')) || ($pos = stripos($output, '</head>'))) 1728 && (($pos = stripos($output, '<script ')) || ($pos = stripos($output, '</head>')))
1680 ) { 1729 ) {
1681 $css = ''; 1730 $css = '';
1682 foreach ($this->css_files as $file) { 1731 foreach ($this->css_files as $file) {
1683 $css .= html::tag('link', array('rel' => 'stylesheet', 1732 $css .= html::tag('link', array('rel' => 'stylesheet',
1716 */ 1765 */
1717 public function frame($attrib, $is_contentframe = false) 1766 public function frame($attrib, $is_contentframe = false)
1718 { 1767 {
1719 static $idcount = 0; 1768 static $idcount = 0;
1720 1769
1721 if (!$attrib['id']) { 1770 if (empty($attrib['id'])) {
1722 $attrib['id'] = 'rcmframe' . ++$idcount; 1771 $attrib['id'] = 'rcmframe' . ++$idcount;
1723 } 1772 }
1724 1773
1725 $attrib['name'] = $attrib['id']; 1774 $attrib['name'] = $attrib['id'];
1726 $attrib['src'] = $attrib['src'] ? $this->abs_url($attrib['src'], true) : 'program/resources/blank.gif'; 1775 $attrib['src'] = !empty($attrib['src']) ? $this->abs_url($attrib['src'], true) : 'program/resources/blank.gif';
1727 1776
1728 // register as 'contentframe' object 1777 // register as 'contentframe' object
1729 if ($is_contentframe || $attrib['contentframe']) { 1778 if ($is_contentframe || !empty($attrib['contentframe'])) {
1730 $this->set_env('contentframe', $attrib['contentframe'] ? $attrib['contentframe'] : $attrib['name']); 1779 $this->set_env('contentframe', !empty($attrib['contentframe']) ? $attrib['contentframe'] : $attrib['name']);
1731 $this->set_env('blankpage', $this->asset_url($attrib['src'])); 1780 $this->set_env('blankpage', $this->asset_url($attrib['src']));
1732 } 1781 }
1733 1782
1734 return html::iframe($attrib); 1783 return html::iframe($attrib);
1735 } 1784 }
1745 * 1794 *
1746 * @return string HTML code for the form 1795 * @return string HTML code for the form
1747 */ 1796 */
1748 public function form_tag($attrib, $content = null) 1797 public function form_tag($attrib, $content = null)
1749 { 1798 {
1750 if ($this->env['extwin']) { 1799 $hidden = '';
1751 $hiddenfield = new html_hiddenfield(array('name' => '_extwin', 'value' => '1')); 1800
1801 if (!empty($this->env['extwin'])) {
1802 $hiddenfield = new html_hiddenfield(['name' => '_extwin', 'value' => '1']);
1752 $hidden = $hiddenfield->show(); 1803 $hidden = $hiddenfield->show();
1753 } 1804 }
1754 else if ($this->framed || $this->env['framed']) { 1805 else if ($this->framed || !empty($this->env['framed'])) {
1755 $hiddenfield = new html_hiddenfield(array('name' => '_framed', 'value' => '1')); 1806 $hiddenfield = new html_hiddenfield(['name' => '_framed', 'value' => '1']);
1756 $hidden = $hiddenfield->show(); 1807 $hidden = $hiddenfield->show();
1757 } 1808 }
1758 1809
1759 if (!$content) { 1810 if (!$content) {
1760 $attrib['noclose'] = true; 1811 $attrib['noclose'] = true;
1777 * @return string HTML code for the form 1828 * @return string HTML code for the form
1778 */ 1829 */
1779 public function request_form($attrib, $content = '') 1830 public function request_form($attrib, $content = '')
1780 { 1831 {
1781 $hidden = new html_hiddenfield(); 1832 $hidden = new html_hiddenfield();
1782 if ($attrib['task']) { 1833
1783 $hidden->add(array('name' => '_task', 'value' => $attrib['task'])); 1834 if (!empty($attrib['task'])) {
1784 } 1835 $hidden->add(['name' => '_task', 'value' => $attrib['task']]);
1785 if ($attrib['action']) { 1836 }
1786 $hidden->add(array('name' => '_action', 'value' => $attrib['action'])); 1837
1838 if (!empty($attrib['action'])) {
1839 $hidden->add(['name' => '_action', 'value' => $attrib['action']]);
1787 } 1840 }
1788 1841
1789 // we already have a <form> tag 1842 // we already have a <form> tag
1790 if ($attrib['form']) { 1843 if (!empty($attrib['form'])) {
1791 if ($this->framed || $this->env['framed']) { 1844 if ($this->framed || !empty($this->env['framed'])) {
1792 $hidden->add(array('name' => '_framed', 'value' => '1')); 1845 $hidden->add(['name' => '_framed', 'value' => '1']);
1793 } 1846 }
1794 1847
1795 return $hidden->show() . $content; 1848 return $hidden->show() . $content;
1796 } 1849 }
1797 1850
1811 */ 1864 */
1812 public function current_username($attrib) 1865 public function current_username($attrib)
1813 { 1866 {
1814 static $username; 1867 static $username;
1815 1868
1816 // alread fetched 1869 // already fetched
1817 if (!empty($username)) { 1870 if (!empty($username)) {
1818 return $username; 1871 return $username;
1819 } 1872 }
1820 1873
1821 // Current username is an e-mail address 1874 // Current username is an e-mail address
1822 if (strpos($_SESSION['username'], '@')) { 1875 if (isset($_SESSION['username']) && strpos($_SESSION['username'], '@')) {
1823 $username = $_SESSION['username']; 1876 $username = $_SESSION['username'];
1824 } 1877 }
1825 // get e-mail address from default identity 1878 // get e-mail address from default identity
1826 else if ($sql_arr = $this->app->user->get_identity()) { 1879 else if ($sql_arr = $this->app->user->get_identity()) {
1827 $username = $sql_arr['email']; 1880 $username = $sql_arr['email'];
1828 } 1881 }
1829 else { 1882 else {
1830 $username = $this->app->user->get_username(); 1883 $username = $this->app->user->get_username();
1831 } 1884 }
1832 1885
1833 return rcube_utils::idn_to_utf8($username); 1886 $username = rcube_utils::idn_to_utf8($username);
1887
1888 return html::quote($username);
1834 } 1889 }
1835 1890
1836 /** 1891 /**
1837 * GUI object 'loginform' 1892 * GUI object 'loginform'
1838 * Returns code for the webmail login form 1893 * Returns code for the webmail login form
1848 1903
1849 $_SESSION['temp'] = true; 1904 $_SESSION['temp'] = true;
1850 1905
1851 // save original url 1906 // save original url
1852 $url = rcube_utils::get_input_value('_url', rcube_utils::INPUT_POST); 1907 $url = rcube_utils::get_input_value('_url', rcube_utils::INPUT_POST);
1853 if (empty($url) && !preg_match('/_(task|action)=logout/', $_SERVER['QUERY_STRING'])) 1908 if (empty($url)
1854 $url = $_SERVER['QUERY_STRING']; 1909 && !empty($_SERVER['QUERY_STRING'])
1910 && !preg_match('/_(task|action)=logout/', $_SERVER['QUERY_STRING'])
1911 ) {
1912 $url = $_SERVER['QUERY_STRING'];
1913 }
1855 1914
1856 // Disable autocapitalization on iPad/iPhone (#1488609) 1915 // Disable autocapitalization on iPad/iPhone (#1488609)
1857 $attrib['autocapitalize'] = 'off'; 1916 $attrib['autocapitalize'] = 'off';
1858 1917
1859 $form_name = !empty($attrib['form']) ? $attrib['form'] : 'form'; 1918 $form_name = !empty($attrib['form']) ? $attrib['form'] : 'form';
1951 { 2010 {
1952 $images = preg_split('/[\s\t\n,]+/', $attrib['images'], -1, PREG_SPLIT_NO_EMPTY); 2011 $images = preg_split('/[\s\t\n,]+/', $attrib['images'], -1, PREG_SPLIT_NO_EMPTY);
1953 $images = array_map(array($this, 'abs_url'), $images); 2012 $images = array_map(array($this, 'abs_url'), $images);
1954 $images = array_map(array($this, 'asset_url'), $images); 2013 $images = array_map(array($this, 'asset_url'), $images);
1955 2014
1956 if (empty($images) || $_REQUEST['_task'] == 'logout') { 2015 if (empty($images) || (isset($_REQUEST['_task']) && $_REQUEST['_task'] == 'logout')) {
1957 return; 2016 return;
1958 } 2017 }
1959 2018
1960 $this->add_script('var images = ' . self::json_serialize($images, $this->devel_mode) .'; 2019 $this->add_script('var images = ' . self::json_serialize($images, $this->devel_mode) .';
1961 for (var i=0; i<images.length; i++) { 2020 for (var i=0; i<images.length; i++) {
1980 $attrib['name'] = '_q'; 2039 $attrib['name'] = '_q';
1981 2040
1982 if (empty($attrib['id'])) { 2041 if (empty($attrib['id'])) {
1983 $attrib['id'] = 'rcmqsearchbox'; 2042 $attrib['id'] = 'rcmqsearchbox';
1984 } 2043 }
1985 if ($attrib['type'] == 'search' && !$this->browser->khtml) { 2044 if (isset($attrib['type']) && $attrib['type'] == 'search' && !$this->browser->khtml) {
1986 unset($attrib['type'], $attrib['results']); 2045 unset($attrib['type'], $attrib['results']);
1987 } 2046 }
1988 2047
1989 $input_q = new html_inputfield($attrib); 2048 $input_q = new html_inputfield($attrib);
1990 $out = $input_q->show(); 2049 $out = $input_q->show();
2004 } 2063 }
2005 2064
2006 /** 2065 /**
2007 * Builder for GUI object 'message' 2066 * Builder for GUI object 'message'
2008 * 2067 *
2009 * @param array Named tag parameters 2068 * @param array $attrib Named tag parameters
2010 * @return string HTML code for the gui object 2069 * @return string HTML code for the gui object
2011 */ 2070 */
2012 protected function message_container($attrib) 2071 protected function message_container($attrib)
2013 { 2072 {
2014 if (isset($attrib['id']) === false) { 2073 if (isset($attrib['id']) === false) {