# HG changeset patch
# User Charlie Root
# Date 1759850440 14400
# Node ID b631c1c7a3ce5041b3c41923a16a83ce76a5c154
# Parent dd5ed6ef69c9d0def47c152d6c10608c3f3e7254
More cleaning up more php8 Warnings/deprecations,
including _many_ ediff-based fixes on rcmail_output_html.php
diff -r dd5ed6ef69c9 -r b631c1c7a3ce program/include/rcmail_output_html.php
--- a/program/include/rcmail_output_html.php Mon Oct 06 12:20:32 2025 -0400
+++ b/program/include/rcmail_output_html.php Tue Oct 07 11:20:40 2025 -0400
@@ -70,7 +70,7 @@
$this->set_env('task', $task);
$this->set_env('x_frame_options', $this->config->get('x_frame_options', 'sameorigin'));
$this->set_env('standard_windows', (bool) $this->config->get('standard_windows'));
- $this->set_env('locale', $_SESSION['language']);
+ $this->set_env('locale', !empty($_SESSION['language']) ? $_SESSION['language'] : 'en_US');
$this->set_env('devel_mode', $this->devel_mode);
// add cookie info
@@ -85,10 +85,13 @@
$this->set_assets_path($this->config->get('assets_path'), $this->config->get('assets_dir'));
- if (!empty($_REQUEST['_extwin']))
+ if (!empty($_REQUEST['_extwin'])) {
$this->set_env('extwin', 1);
- if ($this->framed || $framed)
+ }
+
+ if ($this->framed || $framed) {
$this->set_env('framed', 1);
+ }
$lic = <<pagetitle)) {
$title = $this->pagetitle;
}
- else if ($this->env['task'] == 'login') {
- $title = $this->app->gettext(array(
- 'name' => 'welcome',
- 'vars' => array('product' => $this->config->get('product_name')
- )));
+ else if (isset($this->env['task'])) {
+ if ($this->env['task'] == 'login') {
+ $title = $this->app->gettext([
+ 'name' => 'welcome',
+ 'vars' => ['product' => $this->config->get('product_name')]
+ ]);
+ }
+ else {
+ $title = ucfirst($this->env['task']);
+ }
}
else {
- $title = ucfirst($this->env['task']);
+ $title = '';
}
return $title;
@@ -285,13 +293,13 @@
$path_elements = explode('/', $skin_path);
$skin_id = end($path_elements);
- if (!$meta['name']) {
+ if (empty($meta['name'])) {
$meta['name'] = $skin_id;
}
$this->skins[$skin_id] = $meta;
- if ($meta['extends']) {
+ if (!empty($meta['extends'])) {
$path = RCUBE_INSTALL_PATH . 'skins/';
if (is_dir($path . $meta['extends']) && is_readable($path . $meta['extends'])) {
$this->load_skin('skins/' . $meta['extends']);
@@ -310,8 +318,9 @@
{
foreach ($this->skin_paths as $skin_path) {
$filename = RCUBE_INSTALL_PATH . $skin_path . '/templates/' . $name . '.html';
- if ((is_file($filename) && is_readable($filename))
- || ($this->deprecated_templates[$name] && $this->template_exists($this->deprecated_templates[$name]))
+ if (
+ (is_file($filename) && is_readable($filename))
+ || (!empty($this->deprecated_templates[$name]) && $this->template_exists($this->deprecated_templates[$name]))
) {
return true;
}
@@ -416,8 +425,9 @@
$vars = array_map(array('rcube','Q'), $vars);
$msgtext = $this->app->gettext(array('name' => $message, 'vars' => $vars));
}
- else
+ else {
$msgtext = $message;
+ }
$this->message = $message;
$this->command('display_message', $msgtext, $type, $timeout * 1000);
@@ -462,7 +472,7 @@
*/
public function redirect($p = array(), $delay = 1, $secure = false)
{
- if ($this->env['extwin'])
+ if (!empty($this->env['extwin']))
$p['extwin'] = 1;
$location = $this->app->url($p, false, false, $secure);
header('Location: ' . $location);
@@ -525,10 +535,12 @@
}
// write all javascript commands
- $this->add_script($commands, 'head_top');
+ if (!empty($commands)) {
+ $this->add_script($commands, 'head_top');
+ }
// allow (legal) iframe content to be loaded
- $iframe = $this->framed || $this->env['framed'];
+ $iframe = $this->framed || !empty($this->env['framed']);
if (!headers_sent() && $iframe && ($xopt = $this->app->config->get('x_frame_options', 'sameorigin'))) {
if (strtolower($xopt) != 'sameorigin') {
header('X-Frame-Options: sameorigin', true);
@@ -583,8 +595,9 @@
$path = RCUBE_INSTALL_PATH . "$skin_path/templates/$name.html";
// fallback to deprecated template names
- if (!is_readable($path) && ($dname = $this->deprecated_templates[$realname])) {
- $path = RCUBE_INSTALL_PATH . "$skin_path/templates/$dname.html";
+ if (!is_readable($path) && !empty($this->deprecated_templates[$realname])) {
+ $dname = $this->deprecated_templates[$realname];
+ $path = RCUBE_INSTALL_PATH . "$skin_path/templates/$dname.html";
if (is_readable($path)) {
rcube::raise_error(array(
@@ -631,7 +644,7 @@
);
}
- // parse for specialtags
+ // parse for special tags
$output = $this->parse_conditions($templ);
$output = $this->parse_xml($output);
#rcube::write_log('mail',"px: ".strlen($output));
@@ -664,6 +677,7 @@
{
$out = '';
$parent_commands = 0;
+ $parent_prefix = '';
$top_commands = array();
// these should be always on top,
@@ -676,7 +690,7 @@
}
// unlock interface after iframe load
- $unlock = preg_replace('/[^a-z0-9]/i', '', $_REQUEST['_unlock']);
+ $unlock = isset($_REQUEST['_unlock']) ? preg_replace('/[^a-z0-9]/i', '', $_REQUEST['_unlock']) : 0;
if ($this->framed) {
$top_commands[] = array('iframe_loaded', $unlock);
}
@@ -729,7 +743,7 @@
*/
public function abs_url($str, $search_path = false)
{
- if ($str[0] == '/') {
+ if (isset($str[0]) && $str[0] == '/') {
if ($search_path && ($file_url = $this->get_skin_file($str, $skin_path))) {
return $file_url;
}
@@ -877,7 +891,7 @@
}
/**
- * Public wrapper to dipp into template parsing.
+ * Public wrapper to dip into template parsing.
*
* @param string $input Template content
*
@@ -957,7 +971,7 @@
$out = $matches[0];
$attrib = html::parse_attrib_string($matches[1]);
- if (strtolower($attrib['method']) == 'post') {
+ if (!empty($attrib['method']) && strtolower($attrib['method']) == 'post') {
$hidden = new html_hiddenfield(array('name' => '_token', 'value' => $this->app->get_request_token()));
$out .= "\n" . $hidden->show();
}
@@ -987,10 +1001,10 @@
array(
"\$_SESSION['\\1']",
"\$this->app->config->get('\\1',rcube_utils::get_boolean('\\3'))",
- "\$this->env['\\1']",
+ "(\$this->env['\\1'] ?? null)",
"rcube_utils::get_input_value('\\1', rcube_utils::INPUT_GPC)",
- "\$_COOKIE['\\1']",
- "\$this->browser->{'\\1'}",
+ "(\$_COOKIE['\\1'] ?? null)",
+ "(\$this->browser->{'\\1'} ?? null)",
"'{$this->template_name}'",
),
$expression
@@ -1046,7 +1060,7 @@
switch ($command) {
// return a button
case 'button':
- if ($attrib['name'] || $attrib['command']) {
+ if (!empty($attrib['name']) || !empty($attrib['command'])) {
#rcube::write_log('lab',"button in: ".print_r($attrib,true));
$but = $this->button($attrib);
#rcube::write_log('lab',"button out:\n$but");
@@ -1062,18 +1076,26 @@
// show a label
case 'label':
- if ($attrib['expression'])
+ if (!empty($attrib['expression'])) {
$attrib['name'] = $this->eval_expression($attrib['expression']);
+ }
- if ($attrib['name'] || $attrib['command']) {
- $vars = $attrib + array('product' => $this->config->get('product_name'));
+ if (!empty($attrib['name']) || !empty($attrib['command'])) {
+ $vars = $attrib + ['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']) : (rcube_utils::get_boolean((string)$attrib['html']) ? 'no' : '');
+ $label = $this->app->gettext($attrib + ['vars' => $vars]);
+ $quoting = null;
+
+ if (!empty($attrib['quoting'])) {
+ $quoting = strtolower($attrib['quoting']);
+ }
+ else if (isset($attrib['html'])) {
+ $quoting = rcube_utils::get_boolean((string) $attrib['html']) ? 'no' : '';
+ }
// 'noshow' can be used in skins to define new labels
- if ($attrib['noshow']) {
+ if (!empty($attrib['noshow'])) {
return '';
}
@@ -1101,8 +1123,13 @@
// include a file
case 'include':
$old_base_path = $this->base_path;
- if (!empty($attrib['skin_path'])) $attrib['skinpath'] = $attrib['skin_path'];
- if ($path = $this->get_skin_file($attrib['file'], $skin_path, $attrib['skinpath'])) {
+ $attr_skin_path = !empty($attrib['skinpath']) ? $attrib['skinpath'] : null;
+
+ if (!empty($attrib['skin_path'])) {
+ $attr_skin_path = $attrib['skin_path'];
+ }
+
+ if ($path = $this->get_skin_file($attrib['file'], $skin_path, $attr_skin_path)) {
// set base_path to core skin directory (not plugin's skin)
$this->base_path = preg_replace('!plugins/\w+/!', '', $skin_path);
$path = realpath(RCUBE_INSTALL_PATH . $path);
@@ -1129,7 +1156,7 @@
// define a container block
case 'container':
- if ($attrib['name'] && $attrib['id']) {
+ if (!empty($attrib['name']) && !empty($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);
@@ -1141,20 +1168,19 @@
case 'object':
$object = strtolower($attrib['name']);
$content = '';
+ $handler = null;
- // we are calling a class/method
- if (($handler = $this->object_handlers[$object]) && is_array($handler)) {
- if (is_callable($handler)) {
- // We assume that objects with src attribute are internal (in most
- // cases this is a watermark frame). We need this to make sure assets_path
- // is added to the internal assets paths
- $external = empty($attrib['src']);
- $content = call_user_func($handler, $attrib);
- }
+ if (!empty($this->object_handlers[$object])) {
+ $handler = $this->object_handlers[$object];
}
// execute object handler function
- else if (function_exists($handler)) {
- $content = call_user_func($handler, $attrib);
+ if (is_callable($handler)) {
+
+ // We assume that objects with src attribute are internal (in most
+ // cases this is a watermark frame). We need this to make sure assets_path
+ // is added to the internal assets paths
+ $external = empty($attrib['src']);
+ $content = call_user_func($handler, $attrib);
}
else if ($object == 'doctype') {
$content = html::doctype($attrib['value']);
@@ -1185,11 +1211,11 @@
else if ($object == 'version') {
$ver = (string)RCMAIL_VERSION;
if (is_file(RCUBE_INSTALL_PATH . '.svn/entries')) {
- if (preg_match('/Revision:\s(\d+)/', @shell_exec('svn info'), $regs))
+ if (preg_match('/Revision:\s(\d+)/', (string) @shell_exec('svn info'), $regs))
$ver .= ' [SVN r'.$regs[1].']';
}
else if (is_file(RCUBE_INSTALL_PATH . '.git/index')) {
- if (preg_match('/Date:\s+([^\n]+)/', @shell_exec('git log -1'), $regs)) {
+ if (preg_match('/Date:\s+([^\n]+)/', (string) @shell_exec('git log -1'), $regs)) {
if ($date = date('Ymd.Hi', strtotime($regs[1]))) {
$ver .= ' [GIT '.$date.']';
}
@@ -1212,7 +1238,7 @@
}
// exec plugin hooks for this template object
- $hook = $this->app->plugins->exec_hook("template_object_$object", $attrib + array('content' => $content));
+ $hook = $this->app->plugins->exec_hook("template_object_$object", $attrib + array('content' => (string) $content));
if (strlen($hook['content']) && !empty($external)) {
$object_id = uniqid('TEMPLOBJECT:', true);
@@ -1234,11 +1260,11 @@
switch ($var[0]) {
case 'env':
- $value = $this->env[$name];
+ $value = $this->env[$name] ?? null;
break;
case 'config':
$value = $this->config->get($name);
- if (is_array($value) && $value[$_SESSION['storage_host']]) {
+ if (is_array($value) && !empty($value[$_SESSION['storage_host']])) {
$value = $value[$_SESSION['storage_host']];
}
break;
@@ -1246,13 +1272,13 @@
$value = rcube_utils::get_input_value($name, rcube_utils::INPUT_GPC);
break;
case 'session':
- $value = $_SESSION[$name];
+ $value = $_SESSION[$name] ?? '';
break;
case 'cookie':
$value = htmlspecialchars($_COOKIE[$name]);
break;
case 'browser':
- $value = $this->browser->{$name};
+ $value = $this->browser->{$name} ?? '';
break;
}
@@ -1292,7 +1318,7 @@
{
// insert objects' contents
foreach ($this->objects as $key => $val) {
- $output = str_replace($key, $val, $output, $count);
+ $output = str_replace($key, (string) $val, $output, $count);
if ($count) {
$this->objects[$key] = null;
}
@@ -1321,12 +1347,12 @@
// these commands can be called directly via url
$a_static_commands = array('compose', 'list', 'preferences', 'folders', 'identities');
- if (!($attrib['command'] || $attrib['name'] || $attrib['href'])) {
+ if (empty($attrib['command']) && empty($attrib['name']) && empty($attrib['href'])) {
return '';
}
// try to find out the button type
- if ($attrib['type']) {
+ if (!empty($attrib['type'])) {
$attrib['type'] = strtolower($attrib['type']);
if ($pos = strpos($attrib['type'], '-menuitem')) {
$attrib['type'] = substr($attrib['type'], 0, -9);
@@ -1334,16 +1360,16 @@
}
}
else {
- $attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link';
+ $attrib['type'] = (!empty($attrib['image']) || !empty($attrib['imagepas']) || !empty($attrib['imageact'])) ? 'image' : 'link';
}
- $command = $attrib['command'];
+ $command = $attrib['command']??'';
- if ($attrib['task']) {
+ if (!empty($attrib['task'])) {
$element = $command = $attrib['task'] . '.' . $command;
}
else {
- $element = ($this->env['task'] ? $this->env['task'] . '.' : '') . $command;
+ $element = (!empty($this->env['task']) ? $this->env['task'] . '.' : '') . $command;
}
if ($disabled_actions === null) {
@@ -1355,37 +1381,44 @@
return '';
}
- if (!$attrib['image']) {
- $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact'];
+ if (empty($attrib['image'])) {
+ if (!empty($attrib['imagepas'])) {
+ $attrib['image'] = $attrib['imagepas'];
+ }
+ else if (!empty($attrib['imageact'])) {
+ $attrib['image'] = $attrib['imageact'];
+ }
}
- if (!$attrib['id']) {
+ if (empty($attrib['id'])) {
$attrib['id'] = sprintf('rcmbtn%d', $s_button_count++);
}
// get localized text for labels and titles
- if ($attrib['title']) {
- $attrib['title'] = html::quote($this->app->gettext($attrib['title'], $attrib['domain']));
+ $domain = !empty($attrib['domain']) ? $attrib['domain'] : null;
+ if (!empty($attrib['title'])) {
+ $attrib['title'] = html::quote($this->app->gettext($attrib['title'], $domain));
}
- if ($attrib['label']) {
- $attrib['label'] = html::quote($this->app->gettext($attrib['label'], $attrib['domain']));
+ if (!empty($attrib['label'])) {
+ $attrib['label'] = html::quote($this->app->gettext($attrib['label'], $domain));
}
- if ($attrib['alt']) {
- $attrib['alt'] = html::quote($this->app->gettext($attrib['alt'], $attrib['domain']));
+ if (!empty($attrib['alt'])) {
+ $attrib['alt'] = html::quote($this->app->gettext($attrib['alt'], $domain));
}
// set accessibility attributes
- if (!$attrib['role']) {
+ if (empty($attrib['role'])) {
$attrib['role'] = 'button';
}
if (!empty($attrib['class']) && !empty($attrib['classact']) || !empty($attrib['imagepas']) && !empty($attrib['imageact'])) {
- if (array_key_exists('tabindex', $attrib))
+ if (array_key_exists('tabindex', $attrib)) {
$attrib['data-tabindex'] = $attrib['tabindex'];
- $attrib['tabindex'] = '-1'; // disable button by default
+ }
+ $attrib['tabindex'] = '-1'; // disable button by default
$attrib['aria-disabled'] = 'true';
}
// set title to alt attribute for IE browsers
- if ($this->browser->ie && !$attrib['title'] && $attrib['alt']) {
+ if ($this->browser->ie && empty($attrib['title']) && !empty($attrib['alt'])) {
$attrib['title'] = $attrib['alt'];
}
@@ -1395,16 +1428,16 @@
}
// register button in the system
- if ($attrib['command']) {
+ if (!empty($attrib['command'])) {
$this->add_script(sprintf(
"%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');",
self::JS_OBJECT_NAME,
$command,
$attrib['id'],
$attrib['type'],
- $attrib['imageact'] ? $this->abs_url($attrib['imageact']) : $attrib['classact'],
- $attrib['imagesel'] ? $this->abs_url($attrib['imagesel']) : $attrib['classsel'],
- $attrib['imageover'] ? $this->abs_url($attrib['imageover']) : ''
+ !empty($attrib['imageact']) ? $this->abs_url($attrib['imageact']) : (!empty($attrib['classact']) ? $attrib['classact'] : ''),
+ !empty($attrib['imagesel']) ? $this->abs_url($attrib['imagesel']) : (!empty($attrib['classsel']) ? $attrib['classsel'] : ''),
+ !empty($attrib['imageover']) ? $this->abs_url($attrib['imageover']) : ''
));
// make valid href to specific buttons
@@ -1412,8 +1445,8 @@
$attrib['href'] = $this->app->url(array('task' => $attrib['command']));
$attrib['onclick'] = sprintf("return %s.command('switch-task','%s',this,event)", self::JS_OBJECT_NAME, $attrib['command']);
}
- else if ($attrib['task'] && in_array($attrib['task'], rcmail::$main_tasks)) {
- $attrib['href'] = $this->app->url(array('action' => $attrib['command'], 'task' => $attrib['task']));
+ else if (!empty($attrib['task']) && in_array($attrib['task'], rcmail::$main_tasks)) {
+ $attrib['href'] = $this->app->url(['action' => $attrib['command'], 'task' => $attrib['task']]);
}
else if (in_array($attrib['command'], $a_static_commands)) {
$attrib['href'] = $this->app->url(array('action' => $attrib['command']));
@@ -1424,23 +1457,27 @@
}
// overwrite attributes
- if (!$attrib['href']) {
+ if (empty($attrib['href'])) {
$attrib['href'] = '#';
}
- if ($attrib['task']) {
- if ($attrib['classact'])
+
+ if (!empty($attrib['task'])) {
+ if (!empty($attrib['classact'])) {
$attrib['class'] = $attrib['classact'];
+ }
}
- else if ($command && !$attrib['onclick']) {
+ else if ($command && empty($attrib['onclick'])) {
$attrib['onclick'] = sprintf(
"return %s.command('%s','%s',this,event)",
self::JS_OBJECT_NAME,
$command,
- $attrib['prop']
+ !empty($attrib['prop']) ? $attrib['prop'] : ''
);
}
- $out = '';
+ $out = '';
+ $btn_content = null;
+ $link_attrib = [];
// generate image tag
if ($attrib['type'] == 'image') {
@@ -1452,28 +1489,40 @@
)
);
$btn_content = sprintf('
', $this->abs_url($attrib['image']), $attrib_str);
- if ($attrib['label']) {
+ if (!empty($attrib['label'])) {
$btn_content .= ' '.$attrib['label'];
}
$link_attrib = array('href', 'onclick', 'onmouseover', 'onmouseout', 'onmousedown', 'onmouseup', 'target');
}
else if ($attrib['type'] == 'link') {
- $btn_content = isset($attrib['content']) ? $attrib['content'] : ($attrib['label'] ? $attrib['label'] : $attrib['command']);
- $link_attrib = array_merge(html::$common_attrib, array('href', 'onclick', 'tabindex', 'target'));
- if ($attrib['innerclass'])
+ $btn_content = $attrib['content'] ?? (!empty($attrib['label']) ? $attrib['label'] : $attrib['command']);
+ $link_attrib = array_merge(html::$common_attrib, ['href', 'onclick', 'tabindex', 'target', 'rel']);
+ if (!empty($attrib['innerclass'])) {
$btn_content = html::span($attrib['innerclass'], $btn_content);
+ }
}
else if ($attrib['type'] == 'input') {
$attrib['type'] = 'button';
- if ($attrib['label']) {
+ if (!empty($attrib['label'])) {
$attrib['value'] = $attrib['label'];
}
- if ($attrib['command']) {
- $attrib['disabled'] = 'disabled';
+ if (!empty($attrib['command'])) {
+ $attrib['disabled'] = 'disabled';
}
- $out = html::tag('input', $attrib, null, array('type', 'value', 'onclick', 'id', 'class', 'style', 'tabindex', 'disabled'));
+ $out = html::tag('input', $attrib, null, ['type', 'value', 'onclick', 'id', 'class', 'style', 'tabindex', 'disabled']);
+ }
+ else {
+ if (!empty($attrib['label'])) {
+ $attrib['value'] = $attrib['label'];
+ }
+ if (!empty($attrib['command'])) {
+ $attrib['disabled'] = 'disabled';
+ }
+
+ $content = $attrib['content'] ?? $attrib['label'];
+ $out = html::tag('button', $attrib, $content, ['type', 'value', 'onclick', 'id', 'class', 'style', 'tabindex', 'disabled']);
}
// generate html code for button
@@ -1482,12 +1531,12 @@
$out = sprintf('%s', $attrib_str, $btn_content);
}
- if ($attrib['wrapper']) {
+ if (!empty($attrib['wrapper'])) {
$out = html::tag($attrib['wrapper'], null, $out);
}
- if ($menuitem) {
- $class = $attrib['menuitem-class'] ? ' class="' . $attrib['menuitem-class'] . '"' : '';
+ if (!empty($menuitem)) {
+ $class = !empty($attrib['menuitem-class']) ? ' class="' . $attrib['menuitem-class'] . '"' : '';
$out = '' . $out . '';
}
@@ -1506,7 +1555,7 @@
$file = $this->file_mod($this->scripts_path . $file);
}
- if (!is_array($this->script_files[$position])) {
+ if (!isset($this->script_files[$position]) || !is_array($this->script_files[$position])) {
$this->script_files[$position] = array();
}
@@ -1553,7 +1602,7 @@
/**
* Add HTML code to the page footer
- * To be added right befor
+ * To be added right before
*
* @param string $str HTML code
*/
@@ -1627,7 +1676,7 @@
$this->add_script('$(document).ready(function(){ ' . $this->scripts['docready'] . "\n});", 'foot');
}
- if (is_array($this->script_files['foot'])) {
+ if (!empty($this->script_files['foot'])) {
foreach ($this->script_files['foot'] as $file) {
$page_footer .= html::script($file);
}
@@ -1658,7 +1707,7 @@
$page_header = "
\n$page_header\n\n";
}
- // add page hader
+ // add page header
if ($hpos) {
$output = substr_replace($output, $page_header, $hpos, 0);
}
@@ -1675,7 +1724,7 @@
}
// add css files in head, before scripts, for speed up with parallel downloads
- if (!empty($this->css_files) && !$is_empty
+ if (!empty($this->css_files) && empty($is_empty)
&& (($pos = stripos($output, '