diff --git a/ihtml/themes/breezy/baseselector.tpl b/ihtml/themes/breezy/baseselector.tpl new file mode 100644 index 0000000000000000000000000000000000000000..1e5a45caea7db924976699d10992e45c10954e20 --- /dev/null +++ b/ihtml/themes/breezy/baseselector.tpl @@ -0,0 +1,64 @@ +<input + class="base-selector" + type="text" + name="{$htmlid}" + id="{$htmlid}" + onkeydown="$('bs_{$pid}').hide()" + onfocus="$('bs_{$pid}').hide()" + onmouseover="Element.clonePosition($('bs_{$pid}'), '{$htmlid}', {literal}{{/literal}setHeight: false, setWidth: false, offsetTop:(Element.getHeight('{$htmlid}')){literal}}{/literal});$('bs_{$pid}').show();" + onmouseout="rtimer= Element.hide.delay(0.25, 'bs_{$pid}')" + value="{$currentValue|escape}"/> + +<div id="autocomplete_{$pid}" class="autocomplete"></div> +<script type="text/javascript"> + new Ajax.Autocompleter('{$htmlid}', 'autocomplete_{$pid}', 'autocomplete.php?type=base', { minChars: 3, frequency: 0.5 }); + {if $submitButton} + $('{$htmlid}').observe( + 'keypress', + function(event) { + if(event.keyCode == Event.KEY_RETURN) { + $('submit_base_{$pid}').click(); + } + } + ); + {/if} +</script> + +<div + class="treeList" + style="display:none;max-height:{$height}px" + id="bs_{$pid}" + onmouseover="window.clearTimeout(rtimer);" + onmouseout="rtimer= Element.hide.delay(0.25, 'bs_{$pid}')"> + <a + class="treeList{if $selected}Selected{/if}" + onclick="$('bs_rebase_{$pid}').value='{$rootBase|base64_encode}'; $('submit_tree_base_{$pid}').click();" + >/ [{t}Root{/t}]</a> + + {function tree} + <ul class="{$class}"> + {foreach from=$tree key="dn" item="entry"} + <li> + <a + {if $entry.selected}class="treeListSelected"{/if} + {if $entry.link}onclick="$('bs_rebase_{$pid}').value='{$dn|base64_encode}';$('submit_tree_base_{$pid}').click();"{/if} + title="{$dn|escape}"> + <img class="center" + src="{$entry.img|escape}" + alt=""/> {$entry.name|escape}{if $entry.description} <span class="informal">[{$entry.description|escape}]</span>{/if} + </a> + {tree tree=$entry.tree class=""} + </li> + {/foreach} + </ul> + {/function} + + {tree tree=$tree class="treeList"} +</div> + +{if $submitButton} + <input class="center" type="image" src="geticon.php?context=actions&icon=submit&size=16" title="{t}Submit{/t}" name="submit_base_{$pid}" id="submit_base_{$pid}" alt="{t}Submit{/t}"/> +{/if} +<input type="submit" formnovalidate="formnovalidate" style="display:none" name="submit_tree_base_{$pid}" id="submit_tree_base_{$pid}"/> +<input type="hidden" name="bs_rebase_{$pid}" id="bs_rebase_{$pid}"/> +<input type="hidden" name="BPID" id="BPID" value="{$pid}"/> diff --git a/include/class_baseSelector.inc b/include/class_baseSelector.inc index c80d81e490e4b1a03a277d5e1976f4ff36ac7bc0..c72940e4dfbc322a7e205dd77c6b3eba5fd924d8 100644 --- a/include/class_baseSelector.inc +++ b/include/class_baseSelector.inc @@ -190,105 +190,62 @@ class baseSelector protected function renderTree () { global $config; - $link = "onclick=\"\$('bs_rebase_".$this->pid."').value='".base64_encode($config->current['BASE'])."'; $('submit_tree_base_".$this->pid."').click();\""; - $this->tree = '<input class="base-selector" type="text" name="'.$this->getInputHtmlId().'"'. - ' id="'.$this->getInputHtmlId().'"'. - ' onkeydown="$(\'bs_'.$this->pid.'\').hide()"'. - ' onfocus="$(\'bs_'.$this->pid.'\').hide()"'. - ' onmouseover="Element.clonePosition($(\'bs_'.$this->pid.'\'), \''.$this->getInputHtmlId().'\', {setHeight: false, setWidth: false, offsetTop:(Element.getHeight(\''.$this->getInputHtmlId().'\'))});$(\'bs_'.$this->pid.'\').show();"'. - ' onmouseout="rtimer= Element.hide.delay(0.25, \'bs_'.$this->pid.'\')"'. - ' value="'.htmlescape($this->pathMapping[$this->base]).'"/>'; - - // Autocompleter - $this->tree .= "<div id='autocomplete_".$this->pid."' class='autocomplete'></div>". - "<script type='text/javascript'>". - "new Ajax.Autocompleter('".$this->getInputHtmlId()."', 'autocomplete_".$this->pid."', 'autocomplete.php?type=base', { minChars: 3, frequency: 0.5 });"; - if ($this->submitButton) { - $this->tree .= "$('".$this->getInputHtmlId()."').observe('keypress', function(event) { if(event.keyCode == Event.KEY_RETURN) { $('submit_base_".$this->pid."').click(); } });"; - } - $this->tree .= "</script>"; - - $selected = ($this->base == $config->current['BASE'] ? 'Selected' : ''); - $this->tree .= "<div class='treeList' style='display:none;max-height:".$this->height."px' id='bs_".$this->pid."' onmouseover=\"window.clearTimeout(rtimer);\" onmouseout=\"rtimer= Element.hide.delay(0.25, 'bs_".$this->pid."')\"><a class='treeList$selected' $link>/ ["._("Root")."]</a><ul class='treeList'>\n"; - $first = TRUE; - $last_indent = 2; - $last_base = ''; + /* Build tree */ $departmentInfo = $config->getDepartmentInfo(); - - foreach ($this->pathMapping as $base => $dummy) { - // Skip root for tree + $tree = []; + foreach (array_keys($this->pathMapping) as $base) { if ($base == $config->current['BASE']) { + /* Skip root */ continue; } - // Build path style display - $elements = explode(',', substr($base, 0, strlen($base) - strlen($config->current['BASE']))); - - $indent = count($elements); - if (!$first && ($indent == $last_indent)) { - $this->tree .= "</li>\n"; - } elseif ($indent > $last_indent) { - $parent_base = implode(',', array_slice($elements, 1)).$config->current['BASE']; - if (!$first && ($parent_base != $last_base)) { + $elements = explode(',', substr($base, 0, strlen($base) - strlen($config->current['BASE']))); + /* Remove last one */ + array_pop($elements); + /* Remove first one */ + array_shift($elements); + + $array =& $tree; + $elementBase = $config->current['BASE']; + foreach (array_reverse($elements) as $element) { + $elementBase = $element.','.$elementBase; + if (!isset($array[$elementBase])) { /* Our parent is missing, add it but without link */ - $this->tree .= "</li>\n"; - $this->tree .= '<li><a title="'.$parent_base.'">'. - '<img class="center" '. - 'src="'.htmlescape($departmentInfo[$parent_base]['img']).'" '. - 'alt=""/> '. - $this->escape($departmentInfo[$parent_base]['name']). - (($departmentInfo[$parent_base]['description'] == '') ? '' : ' <span class="informal">['.$this->escape($departmentInfo[$parent_base]['description']).']</span>'). - '</a>'; + $array[$elementBase] = [ + 'tree' => [], + 'selected' => FALSE, + 'link' => FALSE, + 'img' => $departmentInfo[$elementBase]['img'], + 'name' => $departmentInfo[$elementBase]['name'], + 'description' => $departmentInfo[$elementBase]['description'], + ]; } - $this->tree .= "<ul>\n"; - } elseif ($indent < $last_indent) { - for ($i = 0; $i < ($last_indent - $indent); $i++) { - $this->tree .= "</li></ul>\n"; - } - $this->tree .= "</li>\n"; - } - $selected = ($this->base == $base ? ' class="treeListSelected"' : ''); - $link = "onclick=\"\$('bs_rebase_".$this->pid."').value='".base64_encode($base)."';$('submit_tree_base_".$this->pid."').click();\""; - $this->tree .= '<li><a'.$selected.' '.$link.' title="'.$base.'">'. - '<img class="center" '. - 'src="'.htmlescape($departmentInfo[$base]['img']).'" '. - 'alt=""/> '. - $this->escape($departmentInfo[$base]['name']). - (($departmentInfo[$base]['description'] == '') ? '' : ' <span class="informal">['.$this->escape($departmentInfo[$base]['description']).']</span>'). - '</a>'; - - $last_indent = $indent; - $last_base = $base; - $first = FALSE; - } - - // Close tree - for ($i = 1; $i < $last_indent; $i++) { - if (($i > 1) || (!$first)) { - $this->tree .= "</li>"; + /* Go down one level */ + $array =& $array[$elementBase]['tree']; } - $this->tree .= "</ul>\n"; - } - $this->tree .= "</div>\n"; - // Draw submitter if required - if ($this->submitButton) { - $this->tree .= " <input class='center' type='image' src='geticon.php?context=actions&icon=submit&size=16' title='"._("Submit")."' name='submit_base_".$this->pid."' id='submit_base_".$this->pid."' alt='"._("Submit")."'>"; + $array[$base] = [ + 'tree' => [], + 'selected' => ($this->base == $base), + 'link' => TRUE, + 'img' => $departmentInfo[$base]['img'], + 'name' => $departmentInfo[$base]['name'], + 'description' => $departmentInfo[$base]['description'], + ]; } - $this->tree .= '<input type="submit" formnovalidate="formnovalidate" style="display:none" name="submit_tree_base_'.$this->pid.'" id="submit_tree_base_'.$this->pid.'"/>'; - $this->tree .= '<input type="hidden" name="bs_rebase_'.$this->pid.'" id="bs_rebase_'.$this->pid.'"/>'; - $this->tree .= '<input type="hidden" name="BPID" id="BPID" value="'.$this->pid.'"/>'; - } - /*! - * \brief Replace all space of the string by non-breaking space and escapes HTML - * - * \param String $string The string which his space will be replaced - */ - function escape (string $string): string - { - return str_replace(' ', ' ', htmlescape($string)); + $smarty = get_smarty(); + $smarty->assign('htmlid', $this->getInputHtmlId()); + $smarty->assign('pid', $this->pid); + $smarty->assign('currentValue', $this->pathMapping[$this->base]); + $smarty->assign('submitButton', $this->submitButton); + $smarty->assign('height', $this->height); + $smarty->assign('selected', ($this->base == $config->current['BASE'])); + $smarty->assign('rootBase', $config->current['BASE']); + $smarty->assign('tree', $tree); + + $this->tree = $smarty->fetch(get_template_path('baseselector.tpl')); } /*! diff --git a/include/functions.inc b/include/functions.inc index a756a6ff828970afa5aa78cffc1d3fa6a6c9331e..79117b01d958a2a98f27f112118c717b58c94f72 100644 --- a/include/functions.inc +++ b/include/functions.inc @@ -1722,22 +1722,6 @@ function send_binary_content ($data, $name, $type = "application/octet-stream") exit(); } -/*! - * \brief Escape string for HTML output - */ -function htmlescape (string $str): string -{ - return htmlentities($str, ENT_COMPAT | ENT_HTML5, 'UTF-8'); -} - -/*! - * \brief Unescape string for HTML output, reverse of htmlescape - */ -function htmlunescape (string $html): string -{ - return html_entity_decode($html, ENT_COMPAT | ENT_HTML5, 'UTF-8'); -} - /*! * \brief Encode special string characters * diff --git a/include/php_setup.inc b/include/php_setup.inc index 1d8ac98f4e40224a511e61be8274761b3faf8bb3..bb9193bdd07c88e028fe6b621720b5fdc74504fd 100644 --- a/include/php_setup.inc +++ b/include/php_setup.inc @@ -1,9 +1,8 @@ <?php - /* This code is part of FusionDirectory (http://www.fusiondirectory.org/) Copyright (C) 2003-2010 Cajus Pollmeier - Copyright (C) 2011-2016 FusionDirectory + Copyright (C) 2011-2020 FusionDirectory This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,9 +23,25 @@ * \file php_setup.inc * Source code for php_setup */ -require_once("variables.inc"); +require_once('variables.inc'); require_once('class_URL.inc'); +/*! + * \brief Escape string for HTML output + */ +function htmlescape (string $str): string +{ + return htmlentities($str, ENT_COMPAT | ENT_HTML5, 'UTF-8'); +} + +/*! + * \brief Unescape string for HTML output, reverse of htmlescape + */ +function htmlunescape (string $html): string +{ + return html_entity_decode($html, ENT_COMPAT | ENT_HTML5, 'UTF-8'); +} + function html_trace ($errstr = "") { static $hideArgs = [ @@ -51,7 +66,7 @@ function html_trace ($errstr = "") $return_html = '<table width="100%" style="background-color:#402005;color:white;border:2px solid red;border-spacing:0;border-collapse:collapse;">'. '<tr><td colspan="3">'. - '<h1 style="color:white">'._('PHP error').' "'.$errstr.'"'.$loc.'</h1>'. + '<h1 style="color:white">'.htmlescape(_('PHP error').' "'.$errstr.'"'.$loc).'</h1>'. '</td></tr>'; $return_mailto = rawurlencode('=== Trace ==='); /* Generate trace history */ @@ -60,7 +75,7 @@ function html_trace ($errstr = "") $loc = ''; $func = ''; if (isset($ct['class'])) { - $loc .= _("class")." ".$ct['class']; + $loc .= _('class').' '.$ct['class']; $func .= $ct['class']; if (isset($ct['function'])) { $loc .= ' / '; @@ -68,17 +83,17 @@ function html_trace ($errstr = "") } } if (isset($ct['function'])) { - $loc .= _("function")." ".$ct['function']; + $loc .= _('function').' '.$ct['function']; $func .= $ct['function']; } if (isset($ct['type'])) { switch ($ct['type']) { - case "::": - $type = _("static"); + case '::': + $type = _('static'); break; - case "->": - $type = _("method"); + case '->': + $type = _('method'); break; default: @@ -86,9 +101,9 @@ function html_trace ($errstr = "") break; } } else { - $type = "-"; + $type = '-'; } - $args = ""; + $args = ''; if (isset($ct['args'])) { if (isset($hideArgs[$func])) { $hideArgsIndexes = $hideArgs[$func]; @@ -105,38 +120,38 @@ function html_trace ($errstr = "") return '…'; } if (is_object($arg)) { - return "CLASS: ".get_class($arg); + return 'CLASS: '.get_class($arg); } elseif (is_array($arg)) { /* Avoid converting array to string errors */ $i++; - $ret = "array(".implode(',', array_map($f, array_keys($arg), $arg)).")"; + $ret = 'array('.implode(',', array_map($f, array_keys($arg), $arg)).')'; $i--; return $ret; } else { if (strlen("$arg") > 512) { $arg = substr("$arg", 0, 512)."…"; } - return '"'.htmlentities("$arg", ENT_COMPAT, 'UTF-8').'"'; + return '"'.htmlescape("$arg").'"'; } }; $args = implode(',', array_map($f, array_keys($ct['args']), $ct['args'])); } if (empty($args)) { - $args = "-"; + $args = '-'; } if (isset($ct['file'])) { $file = $ct['file']; } else { - $file = ""; + $file = ''; } if (isset($ct['line'])) { $line = $ct['line']; } else { - $line = ""; + $line = ''; } $color = ($index & 1) ? '#404040' : '606060'; - $return_html .= "<tr style='background-color:$color'><td style='padding-left:20px' width=\"30%\">"._("Trace")."[$index]: $loc</td>"; - $return_html .= "<td>"._("File").": $file ("._('Line')." $line)</td><td width=\"10%\">"._("Type").": $type</td></tr>"; - $return_html .= "<tr style='background-color:$color'><td colspan=3 style='padding-left:20px;'>"._("Arguments").": $args</td></tr>"; + $return_html .= "<tr style='background-color:$color'><td style='padding-left:20px' width=\"30%\">".htmlescape(_("Trace")."[$index]: $loc").'</td>'; + $return_html .= "<td>".htmlescape(_("File").": $file ("._('Line')." $line)").'</td><td width="10%">'.htmlescape(_("Type").": $type").'</td></tr>'; + $return_html .= "<tr style='background-color:$color'><td colspan=3 style='padding-left:20px;'>".htmlescape(_("Arguments").": $args").'</td></tr>'; /* Add trace part to mailto body */ $return_mailto .= rawurlencode( @@ -226,18 +241,18 @@ function gosaRaiseError ($errno, $errstr, $errfile, $errline) <td> <img src="geticon.php?context=status&icon=dialog-warning&size=16" alt="" class="center"/> <strong style="font-size:14px">'. - _("Generating this page caused the PHP interpreter to raise some errors!").' + htmlescape(_('Generating this page caused the PHP interpreter to raise some errors!')).' </strong> </td> <td align=right> <a href="mailto:bugs@fusiondirectory.org?subject=FusionDirectory%20bugreport&body=%BUGBODY%"> - <img src="geticon.php?context=applications&icon=internet-mail&size=16" title="'._("Send bug report to the FusionDirectory Team"). - '" class="center" alt="'.("Mail icon").'"> '._("Send bugreport").' + <img src="geticon.php?context=applications&icon=internet-mail&size=16" title="'.htmlescape(_('Send bug report to the FusionDirectory Team')). + '" class="center" alt="'.htmlescape(_('Mail icon')).'"> '.htmlescape(_('Send bugreport')).' </a> </td> <td align="right"> <button onClick="$(\'errorbox\').toggle();">'. - _("Toggle information").' + htmlescape(_('Toggle information')).' </button> </td> </tr> @@ -312,6 +327,8 @@ $smarty->caching = FALSE; $smarty->assign('css_files', []); $smarty->assign('js_files', []); +$smarty->registerPlugin('modifier', 'base64_encode', 'base64_encode'); + $smarty->php_handling = Smarty::PHP_REMOVE; /* Check for SSL connection */