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();"
+    >/&nbsp;[{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=""/>&nbsp;{$entry.name|escape}{if $entry.description}&nbsp;<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}
+  &nbsp;<input class="center" type="image" src="geticon.php?context=actions&amp;icon=submit&amp;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>/&nbsp;["._("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=""/>&nbsp;'.
-                        $this->escape($departmentInfo[$parent_base]['name']).
-                        (($departmentInfo[$parent_base]['description'] == '') ? '' : '&nbsp;<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=""/>&nbsp;'.
-                    $this->escape($departmentInfo[$base]['name']).
-                    (($departmentInfo[$base]['description'] == '') ? '' : '&nbsp;<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 .= "&nbsp;<input class='center' type='image' src='geticon.php?context=actions&amp;icon=submit&amp;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(' ', '&nbsp;', 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:&nbsp;".get_class($arg);
+          return 'CLASS:&nbsp;'.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&amp;icon=dialog-warning&amp;size=16" alt="" class="center"/>&nbsp;
               <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&amp;body=%BUGBODY%">
-                <img src="geticon.php?context=applications&amp;icon=internet-mail&amp;size=16" title="'._("Send bug report to the FusionDirectory Team").
-                '" class="center" alt="'.("Mail icon").'">&nbsp;'._("Send bugreport").'
+                <img src="geticon.php?context=applications&amp;icon=internet-mail&amp;size=16" title="'.htmlescape(_('Send bug report to the FusionDirectory Team')).
+                '" class="center" alt="'.htmlescape(_('Mail icon')).'">&nbsp;'.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 */