diff -pruN 3.0.2-2/ADDITIONS/convert-passwd-to-postfixadmin.pl 3.2-2/ADDITIONS/convert-passwd-to-postfixadmin.pl
--- 3.0.2-2/ADDITIONS/convert-passwd-to-postfixadmin.pl	2013-11-10 15:57:32.000000000 +0000
+++ 3.2-2/ADDITIONS/convert-passwd-to-postfixadmin.pl	2018-05-02 20:37:27.000000000 +0000
@@ -8,7 +8,7 @@
 # 
 # Further details on the project are available at http://postfixadmin.sf.net 
 # 
-# @version $Id: convert-passwd-to-postfixadmin.pl 1558 2013-11-10 15:57:32Z christian_boltz $ 
+# @version $Id$ 
 # @license GNU GPL v2 or later. 
 #
 #
diff -pruN 3.0.2-2/ADDITIONS/mailbox_remover.pl 3.2-2/ADDITIONS/mailbox_remover.pl
--- 3.0.2-2/ADDITIONS/mailbox_remover.pl	2007-11-11 23:36:46.000000000 +0000
+++ 3.2-2/ADDITIONS/mailbox_remover.pl	2018-05-02 20:37:27.000000000 +0000
@@ -6,7 +6,7 @@
 #
 # Added subdir support and pause --- Alan Batie 2007
 # Lists directories to be deleted then pauses for 5 seconds for chance to abort
-# $Id: mailbox_remover.pl 211 2007-11-11 23:36:46Z christian_boltz $
+# $Id$
 #
 # All your maildirs or other directories could be accidentally removed.
 # Use it at own risk. No warranties!
diff -pruN 3.0.2-2/ADDITIONS/squirrelmail-plugin/common.php 3.2-2/ADDITIONS/squirrelmail-plugin/common.php
--- 3.0.2-2/ADDITIONS/squirrelmail-plugin/common.php	2014-02-19 11:53:43.000000000 +0000
+++ 3.2-2/ADDITIONS/squirrelmail-plugin/common.php	2018-05-02 20:37:27.000000000 +0000
@@ -3,35 +3,30 @@
 ini_set('include_path', get_include_path() . ':' . dirname(__FILE__));
 
 @include_once('Zend/Version.php');
-if(!class_exists('Zend_Version', false)) {
-	die("Zend Framework not found. Please check the INSTALL File.");
+if (!class_exists('Zend_Version', false)) {
+    die("Zend Framework not found. Please check the INSTALL File.");
 }
 chdir("..");
 
 
-if (!defined('SM_PATH')) 
-{
-    define('SM_PATH','../');
+if (!defined('SM_PATH')) {
+    define('SM_PATH', '../');
 }
 include_once(dirname(__FILE__)  . '/config.php');
 include_once(dirname(__FILE__) . '/functions.inc.php');
 include_if_exists(dirname(__FILE__) . '/../include/validate.php');
-if (file_exists(dirname(__FILE__) . '/../include/validate.php')) 
-{
+if (file_exists(dirname(__FILE__) . '/../include/validate.php')) {
     include_once(dirname(__FILE__) . '/include/validate.php');
-}
-else { 
+} else {
     include_if_exists(SM_PATH . 'src/validate.php');
 }
 include_once(SM_PATH . 'functions/page_header.php');
 include_once(SM_PATH . 'functions/display_messages.php');
 include_once(SM_PATH . 'functions/imap.php');
 include_if_exists(SM_PATH . 'functions/array.php');
-if (file_exists(SM_PATH . 'src/load_prefs.php'))
-{
+if (file_exists(SM_PATH . 'src/load_prefs.php')) {
     include_once(SM_PATH . 'src/load_prefs.php');
-}
-else {
+} else {
     include_if_exists(SM_PATH . 'include/load_prefs.php');
 }
 // overwrite squirrelmail's content type to utf8...
@@ -41,4 +36,3 @@ header("Content-Type: text/html; charset
 //global $VACCONFMESSAGE;
 bindtextdomain('postfixadmin', dirname(__FILE__) . '/postfixadmin/locale');
 textdomain('postfixadmin');
-
diff -pruN 3.0.2-2/ADDITIONS/squirrelmail-plugin/functions.inc.php 3.2-2/ADDITIONS/squirrelmail-plugin/functions.inc.php
--- 3.0.2-2/ADDITIONS/squirrelmail-plugin/functions.inc.php	2014-02-19 11:53:09.000000000 +0000
+++ 3.2-2/ADDITIONS/squirrelmail-plugin/functions.inc.php	2018-05-02 20:37:27.000000000 +0000
@@ -22,7 +22,7 @@ function _display_password_form() {
     echo _('The PostfixAdmin plugin needs your current mailbox password');
     echo "<form action='' method='post'>";
     echo _('Password for');
-    echo " " . $_SESSION['username'] . " :"; 
+    echo " " . $_SESSION['username'] . " :";
     echo "<input type='password' name='password' value=''>";
     echo "<input type='submit' value='" . _('Submit') . "'></form>";
     do_footer();
@@ -40,37 +40,33 @@ function get_xmlrpc() {
 
     $login_object = $client->getProxy('login');
 
-    if(empty($_SESSION['password'])) {
-        if(empty($_POST['password'])) {
+    if (empty($_SESSION['password'])) {
+        if (empty($_POST['password'])) {
             _display_password_form();
             exit(0);
-        }
-        else {
+        } else {
             try {
                 $success = $login_object->login($_SESSION['username'], $_POST['password']);
-            }
-            catch(Exception $e) {
+            } catch (Exception $e) {
                 //var_dump($client->getHttpClient()->getLastResponse()->getBody());
                 error_log("Failed to login to xmlrpc instance - " . $e->getMessage());
                 die('Failed to login to xmlrpc instance');
             }
-            if($success) {
+            if ($success) {
                 $_SESSION['password'] = $_POST['password'];
                 // reload the current page as a GET request.
                 header("Location: {$_SERVER['REQUEST_URI']}");
                 exit(0);
-            }
-            else {
+            } else {
                 _display_password_form();
                 exit(0);
             }
         }
-    }
-    else {
+    } else {
         $success = $login_object->login($_SESSION['username'], $_SESSION['password']);
     }
 
-    if(!$success) {
+    if (!$success) {
         unset($_SESSION['password']);
         die("Invalid details cached... refresh this page and re-enter your mailbox password");
     }
@@ -78,7 +74,7 @@ function get_xmlrpc() {
 }
 
 function include_if_exists($filename) {
-    if(file_exists($filename)) {
+    if (file_exists($filename)) {
         include_once($filename);
     }
     return;
@@ -93,10 +89,8 @@ $optmode = 'display';
 //
 function check_email($email) {
     $return = filter_var($email, FILTER_VALIDATE_EMAIL);
-    if($return === false) {
+    if ($return === false) {
         return false;
     }
     return true;
 }
-
-
diff -pruN 3.0.2-2/ADDITIONS/squirrelmail-plugin/index.php 3.2-2/ADDITIONS/squirrelmail-plugin/index.php
--- 3.0.2-2/ADDITIONS/squirrelmail-plugin/index.php	2010-02-10 22:49:21.000000000 +0000
+++ 3.2-2/ADDITIONS/squirrelmail-plugin/index.php	2018-05-02 20:37:27.000000000 +0000
@@ -23,5 +23,3 @@
 ****************************************************************************************/
 
 header("Location: ../../index.php");
-
-?>
\ No newline at end of file
diff -pruN 3.0.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_changepass.php 3.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_changepass.php
--- 3.0.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_changepass.php	2010-02-10 22:49:21.000000000 +0000
+++ 3.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_changepass.php	2018-05-02 20:37:27.000000000 +0000
@@ -9,7 +9,7 @@ global $username;
 do_header();
 
 $USERID_USERNAME = $username;
-$tmp = preg_split ('/@/', $USERID_USERNAME);
+$tmp = preg_split('/@/', $USERID_USERNAME);
 $USERID_DOMAIN = $tmp[1];
 
 
@@ -20,15 +20,14 @@ $pPassword_password_current_text = '';
 $pPassword_password_text = '';
 $error = 0;
 
-if ($_SERVER['REQUEST_METHOD'] == "POST")
-{
+if ($_SERVER['REQUEST_METHOD'] == "POST") {
     //$pPassword_password_text = _("pPassword_password_text");
     $fPassword_current = $_POST['fPassword_current'];
     $fPassword = $_POST['fPassword'];
     $fPassword2 = $_POST['fPassword2'];
     $username = $USERID_USERNAME;
 
-    if(!$user->login($_SESSION['username'], $_POST['fPassword_current'])) {
+    if (!$user->login($_SESSION['username'], $_POST['fPassword_current'])) {
         $error = 1;
         bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
         textdomain('postfixadmin');
@@ -37,20 +36,20 @@ if ($_SERVER['REQUEST_METHOD'] == "POST"
         textdomain('squirrelmail');
     }
     $min_length = 0;
-    if(isset($CONF['min_password_length'])) {
+    if (isset($CONF['min_password_length'])) {
         $min_length = $CONF['min_password_length'];
     }
-    if (empty ($fPassword) or ($fPassword != $fPassword2) or ($min_length > 0 && strlen($fPassword) < $min_length)) {
+    if (empty($fPassword) or ($fPassword != $fPassword2) or ($min_length > 0 && strlen($fPassword) < $min_length)) {
         $error = 1;
         bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
         textdomain('postfixadmin');
-        if(empty($fPassword)) {
+        if (empty($fPassword)) {
             $pPassword_password_text .= _("The passwords that you supplied are empty!");
         }
-        if($fPassword != $fPassword2) {
+        if ($fPassword != $fPassword2) {
             $pPassword_password_text .= _("The passwords that you supplied don't match!");
         }
-        if($min_length > 0 && strlen($fPassword) < $min_length) {
+        if ($min_length > 0 && strlen($fPassword) < $min_length) {
             $pPassword_password_text .= _("The password you supplied is too short!");
         }
         bindtextdomain('squirrelmail', SM_PATH . 'locale');
@@ -67,8 +66,7 @@ if ($_SERVER['REQUEST_METHOD'] == "POST"
             $stMessage = _("Please sign out and log back again with your new password!");
             bindtextdomain('squirrelmail', SM_PATH . 'locale');
             textdomain('squirrelmail');
-        }
-        else {
+        } else {
             bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
             textdomain('postfixadmin');
             $tMessage = _("Unable to change your password!");
@@ -125,4 +123,3 @@ echo "<table bgcolor=\"$color[0]\" align
     </tr></table></td></tr></table>";
 bindtextdomain('squirrelmail', SM_PATH . 'locale');
 textdomain('squirrelmail');
-?>
diff -pruN 3.0.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_forward.php 3.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_forward.php
--- 3.0.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_forward.php	2014-02-19 11:57:47.000000000 +0000
+++ 3.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_forward.php	2018-05-02 20:37:27.000000000 +0000
@@ -5,7 +5,7 @@ require_once(dirname(__FILE__) . '/commo
 
 
 $USERID_USERNAME = $username;
-$tmp = preg_split ('/@/', $USERID_USERNAME);
+$tmp = preg_split('/@/', $USERID_USERNAME);
 $USERID_LOCALPART = $tmp[0];
 $USERID_DOMAIN = $tmp[1];
 
@@ -13,10 +13,9 @@ $xmlrpc = get_xmlrpc();
 $alias = $xmlrpc->getProxy('alias');
 do_header();
 // Normal page request (GET)
-if ($_SERVER['REQUEST_METHOD'] == "GET")
-{
+if ($_SERVER['REQUEST_METHOD'] == "GET") {
     $row = $alias->get();
-    if($row === false) {
+    if ($row === false) {
         bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
         textdomain('postfixadmin');
         $tMessage = _("Unable to locate alias!");
@@ -26,29 +25,25 @@ if ($_SERVER['REQUEST_METHOD'] == "GET")
     }
 }
 
-if ($_SERVER['REQUEST_METHOD'] == "POST")
-{
+if ($_SERVER['REQUEST_METHOD'] == "POST") {
     $pEdit_alias_goto = _("To");
 
     $fGoto = $_POST['fGoto'];
 
     // reform string into a list...
-    $goto = preg_replace ('/\r\n/', ',', $fGoto);
-    $goto = preg_replace ('/[\s]+/i', '', $goto);
-    $goto = preg_replace ('/\,*$/', '', $goto);
-    $array = preg_split ('/,/', $goto);
+    $goto = preg_replace('/\r\n/', ',', $fGoto);
+    $goto = preg_replace('/[\s]+/i', '', $goto);
+    $goto = preg_replace('/\,*$/', '', $goto);
+    $array = preg_split('/,/', $goto);
     $error = 0;
     // check that we have valid addresses in the list
 
-    foreach($array as $key => $email_address) 
-    {
-        if (empty($email_address))
-        {
-            unset($array[$key]);	
+    foreach ($array as $key => $email_address) {
+        if (empty($email_address)) {
+            unset($array[$key]);
             continue;
         }
-        if (!check_email($email_address)) 
-        {
+        if (!check_email($email_address)) {
             $error = 1;
             $tGoto = $goto;
             bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
@@ -61,15 +56,13 @@ if ($_SERVER['REQUEST_METHOD'] == "POST"
     if ($error != 1) {
         $flag = 'forward_and_store'; // goto = $USERID_USERNAME;
         $success = $alias->update($array, $flag);
-        if(!$success) {
+        if (!$success) {
             bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
             textdomain('postfixadmin');
             $tMessage = _("Unable to modify the alias!");
             bindtextdomain('squirrelmail', SM_PATH . 'locale');
             textdomain('squirrelmail');
-        }
-        else {
-
+        } else {
             bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
             textdomain('postfixadmin');
             echo "<p align=center><b>". _("Alias successfully changed!"). "\n</b></p>";
@@ -83,7 +76,7 @@ if ($_SERVER['REQUEST_METHOD'] == "POST"
 bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
 textdomain('postfixadmin');
 
-if(!isset($tMessage)) {
+if (!isset($tMessage)) {
     $tMessage = '';
 }
 echo "<table bgcolor=\"$color[0]\" align=\"center\" width=\"95%\" cellpadding=\"1\" cellspacing=\"0\" border=\"0\">
@@ -129,8 +122,10 @@ echo "<table bgcolor=\"$color[0]\" align
 bindtextdomain('squirrelmail', SM_PATH . 'locale');
 textdomain('squirrelmail');
 $aliases = $alias->get();
-foreach($aliases as $address) {
-    if ($address == "" || $address == NULL) { continue; }
+foreach ($aliases as $address) {
+    if ($address == "" || $address == null) {
+        continue;
+    }
     print "$address\n";
 }
 bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
@@ -162,4 +157,3 @@ echo "
 ";
 bindtextdomain('squirrelmail', SM_PATH . 'locale');
 textdomain('squirrelmail');
-?>
diff -pruN 3.0.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_vacation.php 3.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_vacation.php
--- 3.0.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_vacation.php	2010-02-10 22:49:21.000000000 +0000
+++ 3.2-2/ADDITIONS/squirrelmail-plugin/postfixadmin_vacation.php	2018-05-02 20:37:27.000000000 +0000
@@ -15,14 +15,12 @@ EOM;
 do_header();
 
 $USERID_USERNAME = $username;
-$tmp = preg_split ('/@/', $USERID_USERNAME);
+$tmp = preg_split('/@/', $USERID_USERNAME);
 $USERID_DOMAIN = $tmp[1];
 
-if ($_SERVER['REQUEST_METHOD'] == "GET")
-{
+if ($_SERVER['REQUEST_METHOD'] == "GET") {
     $details = $vacation->getDetails();
-    if($vacation->checkVacation()) {
-
+    if ($vacation->checkVacation()) {
         bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
         textdomain('postfixadmin');
         $tMessage = _("You already have an auto response configured!");
@@ -54,9 +52,7 @@ if ($_SERVER['REQUEST_METHOD'] == "GET")
             </tr></table><BR></td></tr></table></td></tr></table>";
         bindtextdomain('squirrelmail', SM_PATH . 'locale');
         textdomain('squirrelmail');
-    }
-    else
-    {
+    } else {
         $tSubject = "Out of Office";
         $tSubject = $details['subject'];
         $VACCONF = $details['body'];
@@ -94,64 +90,52 @@ if ($_SERVER['REQUEST_METHOD'] == "GET")
     }
 }
 
-if ($_SERVER['REQUEST_METHOD'] == "POST")
-{
+if ($_SERVER['REQUEST_METHOD'] == "POST") {
     $fBack = null;
     $fAway = null;
-    foreach(array('fBack', 'fAway', 'fSubject', 'fBody') as $key) {
+    foreach (array('fBack', 'fAway', 'fSubject', 'fBody') as $key) {
         $$key = null;
-        if(isset($_POST[$key])) {
+        if (isset($_POST[$key])) {
             $$key = $_POST[$key];
         }
     }
     
-    if (!empty($fBack))
-    {
+    if (!empty($fBack)) {
         $success = $vacation->remove();
 
-        if(!$success)
-        {
+        if (!$success) {
             bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
             textdomain('postfixadmin');
             $tMessage = _("Unable to update your auto response settings!");
             echo "<p>This may signify an error; please contact support (1)</p>";
             bindtextdomain('squirrelmail', SM_PATH . 'locale');
             textdomain('squirrelmail');
-        }
-        else
-        {
+        } else {
             bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
             textdomain('postfixadmin');
             echo "<p align=center><b>". _("Your auto response has been removed!") ."</b></p>";
             bindtextdomain('squirrelmail', SM_PATH . 'locale');
             textdomain('squirrelmail');
-
         }
     }
 
-    if (!empty ($fAway))
-    {
+    if (!empty($fAway)) {
         // add record into vacation
         $success = $vacation->setAway($fSubject, $fBody);
 
-        if(!$success) {
+        if (!$success) {
             $error = 1;
             bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
             textdomain('postfixadmin');
             $tMessage = _("Unable to update your auto response settings!");
             bindtextdomain('squirrelmail', SM_PATH . 'locale');
             textdomain('squirrelmail');
-        }
-        else
-        {
+        } else {
             bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
             textdomain('postfixadmin');
             echo "<p align=center><b>". _("Your auto response has been set!") ."</b></p>";
             bindtextdomain('squirrelmail', SM_PATH . 'locale');
             textdomain('squirrelmail');
-
         }
     }
 }
-
-?>
diff -pruN 3.0.2-2/ADDITIONS/squirrelmail-plugin/README 3.2-2/ADDITIONS/squirrelmail-plugin/README
--- 3.0.2-2/ADDITIONS/squirrelmail-plugin/README	2010-02-10 22:49:21.000000000 +0000
+++ 3.2-2/ADDITIONS/squirrelmail-plugin/README	1970-01-01 00:00:00.000000000 +0000
@@ -1,70 +0,0 @@
-Squirrelmail Plugin Postfixadmin
-********************************
-
-The Postfixadmin SquirrelMail plugin let users change their virtual alias,
-vacation status/message and password if you are using the great postfixadmin
-tool from http://high5.net/postfixadmin
-
-Version 0.4.3   2007/08/14
-
-Postfixadmin - Postfixadmin+MySQL/PgSQL plugin for Squirrelmail
-
-
-Author: Florian Kimmerl <info@spacekoeln.de>
-Author: Sam Brookes <sam at pale purple.co.uk>
-    - Initial conversion to MDB2
-    - Fix SQL Injections etc
-Author: David Goodwin <david at pale purple.co.uk>
-    - Subsequent tidyup + testing etc
-Author: Krzysztof 'Mad Max' Laska - <madmax at riders.pl>
-    - Polish Translation.
-
-
-
-The Initial Developer of the Original postfixadmin Code is Mischa Peters.
-Portions created by Mischa Peters are Copyright (c) 2002, 2003, 2004.
-All Rights Reserved.
-
-REQUIREMENTS
-
-o SquirrelMail 1.4x
-
-o A working Mail-System "Virtual Domains and Users with postfix+Courier-IMAP+MySQL" (or PostgreSQL) See http://high5.net/howto/
-
-o POSTFIXADMIN version 2.2.0 or higher. See http://sf.net/projects/postfixadmin
-
-o This plugin only uses the postfixadmin database
-
-o Pear MDB2 database abstraction layer - see http://pear.php.net 
-
-o PHP installation with register globals TURNED OFF (huraren on IRC reports that the MDB2 driver isn't happy with it turned on)
-
-INSTALLATION
-
-See the included file INSTALL
-
-BUGS
-
-o Probably vulnerable to cross site scripting, certainly when setting the vacation message.
-
-o There may be some remaining SQL injection holes.
-
-TODO
-
--Code Cleanup
--Tranlation
-
-
-TRANSLATIONS
-
-Translations are welcome! Send the *.po-File to: david@NO.codepoets.SPAM.co.uk
-
-
-ACKNOWLEDGMENTS
-
-Thanks to the SquirrelMail team for building such a great app and
-for all the work they do to keep it running.
-
-Thanks to high5.net for writing the great Postfixadmin tool
-
-
diff -pruN 3.0.2-2/ADDITIONS/squirrelmail-plugin/README.md 3.2-2/ADDITIONS/squirrelmail-plugin/README.md
--- 3.0.2-2/ADDITIONS/squirrelmail-plugin/README.md	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/ADDITIONS/squirrelmail-plugin/README.md	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,31 @@
+# Squirrelmail Plugin Postfixadmin 
+
+The Postfixadmin SquirrelMail plugin let users change their virtual alias,
+vacation status/message and password 
+
+Your users can therefore use this plugin within Squirrelmail to :
+
+ * Turn vacation on/off
+ * Change their email password
+ * Setup forwarding rules
+
+
+Note, this plugin does not require access to the Postfixadmin database. It communicates with Postfixadmin using the XMLRPC protocol. 
+
+## Notes
+
+ * We now depend upon the Zend Framework (preferably v1.9.x at the time of writing) (Download from http://framework.zend.com/download/latest - the minimal one should be sufficient)
+ * Traffic to the XmlRpc interface needs encrypting (e.g. https) - this is something _you_ need to do
+ * When trying to use the plugin, the user will be prompted to enter their mailbox password - this is necessary to authenticate with the remote XmlRpc? interface 
+
+
+## REQUIREMENTS 
+
+ * SquirrelMail 1.4x
+ * PostfixAdmin version 3 or higher. 
+ * PHP 5.4+ with XMLRPC support
+
+
+
+
+
diff -pruN 3.0.2-2/ADDITIONS/squirrelmail-plugin/setup.php 3.2-2/ADDITIONS/squirrelmail-plugin/setup.php
--- 3.0.2-2/ADDITIONS/squirrelmail-plugin/setup.php	2014-02-19 11:52:36.000000000 +0000
+++ 3.2-2/ADDITIONS/squirrelmail-plugin/setup.php	2018-05-02 20:37:27.000000000 +0000
@@ -7,14 +7,13 @@ function squirrelmail_plugin_init_postfi
     global $squirrelmail_plugin_hooks;
 
     $squirrelmail_plugin_hooks['optpage_register_block']['postfixadmin'] = 'postfixadmin_optpage_register_block';
-
 }
 
-function postfixadmin_version(){
+function postfixadmin_version() {
     return '2.3.0';
 }
 
-function postfixadmin_optpage_register_block () {
+function postfixadmin_optpage_register_block() {
     // Gets added to the user's OPTIONS page.
     global $optpage_blocks;
     global $AllowVacation;
@@ -24,18 +23,18 @@ function postfixadmin_optpage_register_b
 
     bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
     textdomain('postfixadmin');
-    $optpage_blocks[] = array (
+    $optpage_blocks[] = array(
         'name' => _("Forwarding"),
         'url'  => '../plugins/postfixadmin/postfixadmin_forward.php',
         'desc' => _("Here you can create and edit E-Mail forwards."),
-        'js'   => FALSE
+        'js'   => false
     );
     bindtextdomain('squirrelmail', SM_PATH . 'locale');
     textdomain('squirrelmail');
 
     bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
     textdomain('postfixadmin');
-    if($AllowVacation) {
+    if ($AllowVacation) {
         $optpage_blocks[] = array(
             'name' => _("Auto Response"),
             'url'  => '../plugins/postfixadmin/postfixadmin_vacation.php',
@@ -47,7 +46,7 @@ function postfixadmin_optpage_register_b
     }
     bindtextdomain('postfixadmin', SM_PATH . 'plugins/postfixadmin/locale');
     textdomain('postfixadmin');
-    if($AllowChangePass) {
+    if ($AllowChangePass) {
         $optpage_blocks[] = array(
             'name' => _("Change Password"),
             'url'  => '../plugins/postfixadmin/postfixadmin_changepass.php',
@@ -58,4 +57,3 @@ function postfixadmin_optpage_register_b
         textdomain('squirrelmail');
     }
 }
-?>
diff -pruN 3.0.2-2/ADDITIONS/virtualmaildel.php 3.2-2/ADDITIONS/virtualmaildel.php
--- 3.0.2-2/ADDITIONS/virtualmaildel.php	2007-11-11 23:36:46.000000000 +0000
+++ 3.2-2/ADDITIONS/virtualmaildel.php	2018-05-02 20:37:27.000000000 +0000
@@ -1,185 +1,193 @@
 <?php
+/*
+ Virtual Mail Delete
+ by George Vieira <george at citadelcomputer dot com dot au>
+
+ You can run this from your crontab with something like
+
+ 0 4 * * * *    vmail    php -q virtualmaildel.php >/dev/null
+
+ Changes:
+    2017.08.31 updated to use PHP mysqli extension.
+    2018.02.23 removing Sieve filters if exists.
+        Tadas UstinaviÄius <tadas at ring dot lt> ( https://github.com/postfixadmin/postfixadmin/pull/70 )
+
+*/
+
+$CONF = [];
+
+// Either, uncomment this (and change to work)
+//require_once('/path/to/postfixadmin/config.inc.php');
+
+// OR uncomment this.
+/*
+$CONF = [
+    'database_host' => 'localhost',
+    'database_user' => 'someone',
+    'database_password' => 'something',
+    'database_name' => 'mydb'
+];
+ */
+
+
+$MAKE_CHANGES = false; // change to true when you're happy this isn't going to trash your server.
+
+if (empty($CONF)) {
+    die("\nPlease configure me\n\n");
+}
+
+// Where's the homedir accounts stored. (GET THIS RIGHT OTHERWISE IT THINK NONE EXIST AND DELETES ALL)
+$homedir    = '/home/virtual';
+
+if (! is_dir($homedir)) {
+    die("Cannot find home directory for virtual mailboxes in $homedir\n");
+}
+
 //
-// Virtual Mail Delete
-// by George Vieira <george at citadelcomputer dot com dot au>
+// Recursive Delete Function
+//
+function deldir($dir) {
+    $current_dir = opendir($dir);
+    while ($entryname = readdir($current_dir)) {
+        if (is_dir("$dir/$entryname") and ($entryname != "." and $entryname!="..")) {
+            deldir("${dir}/${entryname}");
+        } elseif ($entryname != "." and $entryname!="..") {
+            unlink("${dir}/${entryname}");
+        }
+    }
+    closedir($current_dir);
+    @rmdir(${dir});
+}
+
+// --- Main Start ---
+
+$dir = [];
+
 //
-// You can run this from your crontab with something like
+// Get list of directories
 //
-// 0 4 * * * *    vmail    php -q virtualmaildel.php >/dev/null
+$fr = opendir($homedir);
 
-	//
-	// Setup location of postfixadmin config files. Needed to login to mysql
-	//
-	$conf		= '/home/httpd/mail/admin/config.inc.php';
-
-	//
-	// Where's the homedir accounts stored. (GET THIS RIGHT OTHERWISE IT THINK NONE EXIST AND DELETES ALL)
-	//
-	$homedir	= '/home/virtual';
-
-	//
-	// Make sure everything is everything before continuing
-	//
-	if ( ! file_exists( $conf ) )
-		die( "Cannot find config file $conf\n" );
-
-	if ( ! is_dir( $homedir ) )
-		die( "Cannot find home directory for virtual mailboxes in $homedir\n" );
-
-	//
-	// Load mysql authentication from postfixadmin
-	//
-	include( $conf );
-
-	//
-	// Recursive Delete Function
-	//
-	function deldir($dir)
-	{
-		$current_dir = opendir($dir);
-		while($entryname = readdir($current_dir))
-		{
-			if(is_dir("$dir/$entryname") and ($entryname != "." and $entryname!=".."))
-			{
-				deldir("${dir}/${entryname}");
-			}
-			elseif($entryname != "." and $entryname!="..")
-			{
-				unlink("${dir}/${entryname}");
-			}
-		}
-		closedir($current_dir);
-		@rmdir(${dir});
-	}
+// TODO: Would glob($homedir . '/**/*/new') be somewhat quicker/shorter/less effort?
 
-// --- Main Start ---
+while (($domain = readdir($fr)) !== false) {
+    //
+    // Check if it's a dir
+    //
+    if ($domain == "." || $domain == ".." || filetype($homedir .'/'. $domain) != "dir") {
+        continue;
+    }
+    //
+    // Open the (assumed) DOMAIN directory
+    //
+    $ff = opendir($homedir .'/'. $domain);
+    while (($user = readdir($ff)) !== false) {
+        //
+        // Check for directories assuming it's a user account
+        //
+        if ($user == "." || $user == ".." || filetype($homedir .'/'. $domain .'/'. $user) != "dir") {
+            continue;
+        }
+
+        //
+        // if the dir 'new' exists inside then it's an account
+        //
+        if (file_exists($homedir .'/'. $domain .'/'. $user .'/'. "new")) {
+            $dir[$domain][$user] = "";
+        } else {
+            //
+            // Alert that the dir doesn't have a 'new' dir, possibly not an account. Leave it.
+            //
+            echo "UNKNOWN  : " . $homedir ."/". $domain ."/". $user ."/new NOT FOUND. Possibly not an account. Leaving untouched\n";
+        }
+    }
+}
+//
+// OK, got an array of accounts from the dir, Now connect to the DB and check them
+//
+$conx = mysqli_connect($CONF['database_host'], $CONF['database_user'], $CONF['database_password'], $CONF['database_name']);
+//
+// Is there a problem connecting?
+//
+if (! $conx || mysqli_connect_errno()) {
+    var_dump("DB connection failed." . mysqli_connect_error());
+    die("Problem connecting to the database. ");
+}
+
+//
+// Select all mailboxes to verify against dirs listed in array
+//
+$query = "SELECT * FROM mailbox";
+$result = mysqli_query($conx, $query);
+
+//
+// Query the mailbox table
+//
+if (! $result) {
+    die("Failed to query mailbox table.");
+}
+
+//
+// Fetch the list of results
+//
+while ($row = mysqli_fetch_assoc($result)) {
+    //
+    // Pull apart the maildir field, needed to figure out the directory structure to compare
+    //
+    $strip = explode("/", $row['maildir']);
+    //
+    // Unset the array if it exists. This stops it being erased later.
+    //
+    unset($dir[ $strip[0] ][ $strip[1] ]);
+}
+//
+// If there are results. unset the domain too.
+//
+if (count($dir[$strip[0]])==0 and mysqli_num_rows($result)>0) {
+    unset($dir[$strip[0]]);
+}
+
+//
+// OK, time to clean up. All known users/domains have been removed from the list.
+//
+
+//
+// If the array still exists (incase nothing there)
+//
+if (is_array($dir)) {
+    //
+    // Go through each dir
+    //
+    foreach ($dir as $key => $value) {
+        //
+        // Is this a user array?
+        //
+        if (!is_array($value)) {
+            continue;
+        }
+
+        //
+        // Go through and nuke the folders
+        //
+        foreach ($value as $user => $value2) {
+            // Nuke.. need any more explanations?
+            $path = $homedir . '/' . $key . '/' . $user;
+            $sieve_path = $homedir . '/.sieve/' . $key . '/' . $user;
+            $sieve_exists = file_exists($sieve_path);
+            // check if user has Sieve filters created
+            if ($MAKE_CHANGES) {
+                deldir($path);
+                if ($sieve_exists) {
+                    deldir($sieve_path);
+                }
+            } else {
+                echo " - Would recursively delete : $path \n";
+                if ($sieve_exists) {
+                    echo " - Would recursively delete Sieve filters : $sieve_path \n";
+                }
+            }
+        }
+    }
+}
 
-	//
-	// Get list of directories
-	//
-	$fr = opendir( $homedir );
-	while ( ($domain = readdir($fr)) !== false)
-	{
-		//
-		// Check if it's a dir
-		//
-		if ( $domain != "." and $domain != ".." and filetype($homedir .'/'. $domain) == "dir" )
-		{
-			//
-			// Open the (assumed) DOMAIN directory
-			//
-			$ff = opendir( $homedir .'/'. $domain );
-			while ( ($user = readdir($ff)) !== false)
-			{
-				//
-				// Check for directories assuming it's a user account
-				//
-				if ( $user!="." and $user!=".." and filetype($homedir .'/'. $domain .'/'. $user) == "dir" )
-				{
-					//
-					// if the dir 'new' exists inside then it's an account
-					//
-					if ( file_exists($homedir .'/'. $domain .'/'. $user .'/'. "new") )
-					{
-						$dir[$domain][$user] = "";
-					}
-					else
-					{
-						//
-						// Alert that the dir doesn't have a 'new' dir, possibly not an account. Leave it.
-						//
-						echo "UNKNOWN  : " . $homedir ."/". $domain ."/". $user ."/new NOT FOUND. Possibly not an account. Leaving untouched\n";
-					}
-				}
-			} 
-		}
-	} 
-	//
-	// OK, got an array of accounts from the dir, Now connect to the DB and check them
-	//
-	$conx = mysql_connect( $CONF['database_host'],$CONF['database_user'],$CONF['database_password'] );
-	//
-	// Is there a problem connecting?
-	//
-	if ( $conx != false )
-	{
-		//
-		// Select the database
-		//
-		mysql_select_db( $CONF['database_name'] , $conx) or die ("Can't access database postfix : " . mysql_error()); 
-
-		//
-		// Select all mailboxes to verify against dirs listed in array
-		//
-		$query = "SELECT * FROM mailbox";
-		$result = mysql_query( $query );
-
-		//
-		// Query the mailbox table
-		//
-		if ( $result != false )
-		{
-			//
-			// Fetch the list of results
-			//
-			while ( $row = mysql_fetch_assoc( $result ) )
-			{
-				//
-				// Pull apart the maildir field, needed to figure out the directory structure to compare
-				//
-				$strip = explode("/",$row['maildir']);
-				//
-				// Unset the array if it exists. This stops it being erased later.
-				//
-				unset( $dir[ $strip[0] ][ $strip[1] ] );
-			}
-			//
-			// If there are results. unset the domain too.
-			//
-			if ( count($dir[$strip[0]])==0 and mysql_num_rows($result)>0 )
-				unset( $dir[$strip[0]] );
-		}
-		else
-			die( "Failed SELECT in mailboxes\n" );
-	}
-	else
-		die( 'Cannot connect to the database!\n' );
-
-	//
-	// OK, time to clean up. All known users/domains have been removed from the list.
-	//
-
-	//
-	// If the array still exists (incase nothing there)
-	//
-	if ( is_array($dir) )
-	{
-		//
-		// Go through each dir
-		//
-		foreach ( $dir as $key => $value )
-		{
-			//
-			// Is this a user array?
-			//
-			if ( is_array( $value) )
-			{
-				//
-				// Go through and nuke the folders
-				//
-				foreach ( $value as $user => $value2 )
-				{
-					//
-					// Nuke.. need any more explanations?
-					//
-					echo "REMOVING : " . $homedir."/".$key."/".$user."\n" ;
-					deldir( $homedir."/".$key."/".$user ) ;
-				}
-			}
-		}
-	}
-	//
-	// And we are outta here....
-	//
-	echo "Cleanup process completed\n";
-?>
+echo "Cleanup process completed\n";
diff -pruN 3.0.2-2/backup.php 3.2-2/backup.php
--- 3.0.2-2/backup.php	2013-11-16 00:00:53.000000000 +0000
+++ 3.2-2/backup.php	1970-01-01 00:00:00.000000000 +0000
@@ -1,140 +0,0 @@
-<?php
-/** 
- * Postfix Admin 
- * 
- * LICENSE 
- * This source file is subject to the GPL license that is bundled with  
- * this package in the file LICENSE.TXT. 
- * 
- * Further details on the project are available at http://postfixadmin.sf.net 
- * 
- * @version $Id: backup.php 1582 2013-11-16 00:00:53Z christian_boltz $ 
- * @license GNU GPL v2 or later. 
- * 
- * File: backup.php
- * Used to save all settings - but only works for MySQL databases.
- * Template File: -none-
- *
- * Template Variables: -none-
- *
- * Form POST \ GET Variables: -none-
- */
-
-require_once('common.php');
-
-authentication_require_role('global-admin');
-
-(($CONF['backup'] == 'NO') ? header("Location: main.php") && exit : '1');
-
-// TODO: make backup supported for postgres
-if (db_pgsql()) {
-	flash_error('Sorry: Backup is currently not supported for your DBMS ('.$CONF['database_type'].').');
-	$smarty->assign ('smarty_template', 'message');
-	$smarty->display ('index.tpl');
-   die;
-}
-
-if (safeget('download') == "") {
-	$smarty->assign ('smarty_template', 'backupwarning');
-	$smarty->display ('index.tpl');
-   die;
-}
-
-# Still here? Then let's create the database dump...
-
-/*
-	SELECT attnum,attname,typname,atttypmod-4,attnotnull,atthasdef,adsrc
-	AS def FROM pg_attribute,pg_class,pg_type,pg_attrdef
-	WHERE pg_class.oid=attrelid AND pg_type.oid=atttypid
-	AND attnum>0 AND pg_class.oid=adrelid AND adnum=attnum AND atthasdef='t' AND lower(relname)='admin'
-	UNION SELECT attnum,attname,typname,atttypmod-4,attnotnull,atthasdef,''
-	AS def FROM pg_attribute,pg_class,pg_type
-	WHERE pg_class.oid=attrelid
-	AND pg_type.oid=atttypid
-	AND attnum>0
-	AND atthasdef='f'
-	AND lower(relname)='admin'
-$db = $_GET['db'];
-$cmd = "pg_dump -c -D -f /tix/miner/miner.sql -F p -N -U postgres $db";
-$res = `$cmd`;
-// Alternate: $res = shell_exec($cmd);
-echo $res; 
-*/
-
-if ($_SERVER['REQUEST_METHOD'] == "GET")
-{
-   umask (077);
-   $path = (ini_get('upload_tmp_dir') != '') ? ini_get('upload_tmp_dir') : '/tmp';
-   date_default_timezone_set(@date_default_timezone_get()); # Suppress date.timezone warnings
-   $filename = "postfixadmin-" . date ("Ymd") . "-" . getmypid() . ".sql";
-   $backup = $path . DIRECTORY_SEPARATOR . $filename;
-
-   $header = "#\n# Postfix Admin $version\n# Date: " . date ("D M j G:i:s T Y") . "\n#\n";
-
-   if (!$fh = fopen ($backup, 'w'))
-   {
-      flash_error("<div class=\"error_msg\">Cannot open file ($backup)</div>");
-		$smarty->assign ('smarty_template', 'message');
-		$smarty->display ('index.tpl');
-   } 
-   else
-   {
-      fwrite ($fh, $header);
-      
-      $tables = array(
-         'admin',
-         'alias',
-         'alias_domain',
-         'config',
-         'domain',
-         'domain_admins',
-         'fetchmail',
-         'log',
-         'mailbox',
-		 'quota',
-		 'quota2',
-         'vacation',
-         'vacation_notification'
-      );
-
-      for ($i = 0 ; $i < sizeof ($tables) ; ++$i)
-      {
-         $result = db_query ("SHOW CREATE TABLE " . table_by_key($tables[$i]));
-         if ($result['rows'] > 0)
-         {
-            while ($row = db_array ($result['result']))
-            {
-               fwrite ($fh, "$row[1];\n\n");
-            }
-         }
-      }   
-
-      for ($i = 0 ; $i < sizeof ($tables) ; ++$i)
-      {
-         $result = db_query ("SELECT * FROM " . table_by_key($tables[$i]));
-         if ($result['rows'] > 0)
-         {
-            while ($row = db_assoc ($result['result']))
-            {
-                $fields = array_keys($row);
-                $values = array_values($row);
-                $values = array_map('escape_string', $values);
-
-               fwrite ($fh, "INSERT INTO ". $tables[$i] . " (". implode (',',$fields) . ") VALUES ('" . implode ('\',\'',$values) . "');\n");
-               $fields = "";
-               $values = "";
-            }
-         }
-      }
-   }
-   header ("Content-Type: text/plain");
-   header ("Content-Disposition: attachment; filename=\"$filename\"");
-   header ("Content-Transfer-Encoding: binary");
-   header ("Content-Length: " . filesize("$backup"));
-   header ("Content-Description: Postfix Admin");
-   $download_backup = fopen ("$backup", "r");
-   unlink ("$backup");
-   fpassthru ($download_backup);
-}
-/* vim: set expandtab softtabstop=3 tabstop=3 shiftwidth=3: */
-?>
diff -pruN 3.0.2-2/broadcast-message.php 3.2-2/broadcast-message.php
--- 3.0.2-2/broadcast-message.php	2016-05-20 20:42:04.000000000 +0000
+++ 3.2-2/broadcast-message.php	1970-01-01 00:00:00.000000000 +0000
@@ -1,104 +0,0 @@
-<?php
-/** 
- * Postfix Admin 
- * 
- * LICENSE 
- * This source file is subject to the GPL license that is bundled with  
- * this package in the file LICENSE.TXT. 
- * 
- * Further details on the project are available at http://postfixadmin.sf.net 
- * 
- * @version $Id: broadcast-message.php 1842 2016-05-20 20:42:04Z christian_boltz $ 
- * @license GNU GPL v2 or later. 
- * 
- * File: broadcast-message.php
- * Used to send a message to _ALL_ users with mailboxes on this server.
- *
- * Template File: broadcast-message.tpl
- *
- * Template Variables: -none-
- *
- * Form POST \ GET Variables:
- *
- * name
- * subject
- * message
- */
-
-require_once('common.php');
-
-authentication_require_role('global-admin');
-
-if ($CONF['sendmail'] != 'YES') {
-   header("Location: main.php");
-   exit;
-}
-
-$smtp_from_email = smtp_get_admin_email();
-
-if ($_SERVER['REQUEST_METHOD'] == "POST")
-{
-   if (safepost('token') != $_SESSION['PFA_token']) die('Invalid token!');
-
-   if (empty($_POST['subject']) || empty($_POST['message']) || empty($_POST['name']))
-   {
-      $error = 1;
-      flash_error($PALANG['pBroadcast_error_empty']);
-   }
-   else
-   {
-      $table_mailbox = table_by_key('mailbox');
-	  $table_alias = table_by_key('alias');
-      
-	  $q = "select username from $table_mailbox union select goto from $table_alias " .
-		   "where goto not in (select username from $table_mailbox)";
-
-      $result = db_query ($q);
-      if ($result['rows'] > 0)
-      {
-         mb_internal_encoding("UTF-8");
-         $b_name = mb_encode_mimeheader( $_POST['name'], 'UTF-8', 'Q');
-         $b_subject = mb_encode_mimeheader( $_POST['subject'], 'UTF-8', 'Q');
-         $b_message = base64_encode($_POST['message']);
-
-         $i = 0;
-         while ($row = db_array ($result['result'])) {
-            $fTo = $row[0];
-            $fHeaders  = 'To: ' . $fTo . "\n";
-            $fHeaders .= 'From: ' . $b_name . ' <' . $smtp_from_email . ">\n";
-            $fHeaders .= 'Subject: ' . $b_subject . "\n";
-            $fHeaders .= 'MIME-Version: 1.0' . "\n";
-            $fHeaders .= 'Content-Type: text/plain; charset=UTF-8' . "\n";
-            $fHeaders .= 'Content-Transfer-Encoding: base64' . "\n";
-
-            $fHeaders .= $b_message;
-
-            if (!smtp_mail ($fTo, $smtp_from_email, $fHeaders))
-            {
-               flash_error(Config::lang_f('pSendmail_result_error', $fTo));
-            }
-            else
-            {
-               flash_info(Config::lang_f('pSendmail_result_success', $fTo));
-            }
-         }
-      }
-		flash_info($PALANG['pBroadcast_success']);
-		$smarty->assign ('smarty_template', 'message');
-		$smarty->display ('index.tpl');
-//		echo '<p>'.$PALANG['pBroadcast_success'].'</p>';
-   }
-}
-
-if ($_SERVER['REQUEST_METHOD'] == "GET" || $error == 1)
-{
-	$smarty->assign ('smtp_from_email', $smtp_from_email);
-	$smarty->assign ('error', $error);
-	$smarty->assign ('smarty_template', 'broadcast-message');
-	$smarty->display ('index.tpl');
-
-//   include ("templates/broadcast-message.tpl");
-}
-
-/* vim: set expandtab softtabstop=3 tabstop=3 shiftwidth=3: */
-?>
diff -pruN 3.0.2-2/calendar.js 3.2-2/calendar.js
--- 3.0.2-2/calendar.js	2009-11-05 14:55:39.000000000 +0000
+++ 3.2-2/calendar.js	1970-01-01 00:00:00.000000000 +0000
@@ -1,336 +0,0 @@
-// Tigra Calendar v4.0.2 (12-01-2009) European (dd.mm.yyyy)
-// http://www.softcomplex.com/products/tigra_calendar/
-// Public Domain Software... You're welcome.
-
-// default settins
-var A_TCALDEF = {
-	'months' : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
-	'weekdays' : ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
-	'yearscroll': true, // show year scroller
-	'weekstart': 1, // first day of week: 0-Su or 1-Mo
-	'centyear'  : 70, // 2 digit years less than 'centyear' are in 20xx, othewise in 19xx.
-	'imgpath' : 'images/calendar/' // directory with calendar images
-}
-// date parsing function
-function f_tcalParseDate (s_date) {
-
-	var re_date = /^\s*(\d{1,2})\.(\d{1,2})\.(\d{2,4})\s*$/;
-	if (!re_date.exec(s_date))
-		return alert ("Invalid date: '" + s_date + "'.\nAccepted format is dd.mm.yyyy.")
-	var n_day = Number(RegExp.$1),
-		n_month = Number(RegExp.$2),
-		n_year = Number(RegExp.$3);
-
-	if (n_year < 100)
-		n_year += (n_year < this.a_tpl.centyear ? 2000 : 1900);
-	if (n_month < 1 || n_month > 12)
-		return alert ("Invalid month value: '" + n_month + "'.\nAllowed range is 01-12.");
-	var d_numdays = new Date(n_year, n_month, 0);
-	if (n_day > d_numdays.getDate())
-		return alert("Invalid day of month value: '" + n_day + "'.\nAllowed range for selected month is 01 - " + d_numdays.getDate() + ".");
-
-	return new Date (n_year, n_month - 1, n_day);
-}
-// date generating function
-function f_tcalGenerDate (d_date) {
-	return (
-		(d_date.getDate() < 10 ? '0' : '') + d_date.getDate() + "."
-		+ (d_date.getMonth() < 9 ? '0' : '') + (d_date.getMonth() + 1) + "."
-		+ d_date.getFullYear()
-	);
-}
-
-// implementation
-function tcal (a_cfg, a_tpl) {
-
-	// apply default template if not specified
-	if (!a_tpl)
-		a_tpl = A_TCALDEF;
-
-	// register in global collections
-	if (!window.A_TCALS)
-		window.A_TCALS = [];
-	if (!window.A_TCALSIDX)
-		window.A_TCALSIDX = [];
-	
-	this.s_id = a_cfg.id ? a_cfg.id : A_TCALS.length;
-	window.A_TCALS[this.s_id] = this;
-	window.A_TCALSIDX[window.A_TCALSIDX.length] = this;
-	
-	// assign methods
-	this.f_show = f_tcalShow;
-	this.f_hide = f_tcalHide;
-	this.f_toggle = f_tcalToggle;
-	this.f_update = f_tcalUpdate;
-	this.f_relDate = f_tcalRelDate;
-	this.f_parseDate = f_tcalParseDate;
-	this.f_generDate = f_tcalGenerDate;
-	
-	// create calendar icon
-	this.s_iconId = 'tcalico_' + this.s_id;
-	this.e_icon = f_getElement(this.s_iconId);
-	if (!this.e_icon) {
-		document.write('<img src="' + a_tpl.imgpath + 'cal.gif" id="' + this.s_iconId + '" onclick="A_TCALS[\'' + this.s_id + '\'].f_toggle()" class="tcalIcon" alt="Open Calendar" />');
-		this.e_icon = f_getElement(this.s_iconId);
-	}
-	// save received parameters
-	this.a_cfg = a_cfg;
-	this.a_tpl = a_tpl;
-}
-
-function f_tcalShow (d_date) {
-
-	// find input field
-	if (!this.a_cfg.controlname)
-		throw("TC: control name is not specified");
-	if (this.a_cfg.formname) {
-		var e_form = document.forms[this.a_cfg.formname];
-		if (!e_form)
-			throw("TC: form '" + this.a_cfg.formname + "' can not be found");
-		this.e_input = e_form.elements[this.a_cfg.controlname];
-	}
-	else
-		this.e_input = f_getElement(this.a_cfg.controlname);
-
-	if (!this.e_input || !this.e_input.tagName || this.e_input.tagName != 'INPUT')
-		throw("TC: element '" + this.a_cfg.controlname + "' does not exist in "
-			+ (this.a_cfg.formname ? "form '" + this.a_cfg.controlname + "'" : 'this document'));
-
-	// dynamically create HTML elements if needed
-	this.e_div = f_getElement('tcal');
-	if (!this.e_div) {
-		this.e_div = document.createElement("DIV");
-		this.e_div.id = 'tcal';
-		document.body.appendChild(this.e_div);
-	}
-	this.e_shade = f_getElement('tcalShade');
-	if (!this.e_shade) {
-		this.e_shade = document.createElement("DIV");
-		this.e_shade.id = 'tcalShade';
-		document.body.appendChild(this.e_shade);
-	}
-	this.e_iframe =  f_getElement('tcalIF')
-	if (b_ieFix && !this.e_iframe) {
-		this.e_iframe = document.createElement("IFRAME");
-		this.e_iframe.style.filter = 'alpha(opacity=0)';
-		this.e_iframe.id = 'tcalIF';
-		this.e_iframe.src = this.a_tpl.imgpath + 'pixel.gif';
-		document.body.appendChild(this.e_iframe);
-	}
-	
-	// hide all calendars
-	f_tcalHideAll();
-
-	// generate HTML and show calendar
-	this.e_icon = f_getElement(this.s_iconId);
-	if (!this.f_update())
-		return;
-
-	this.e_div.style.visibility = 'visible';
-	this.e_shade.style.visibility = 'visible';
-	if (this.e_iframe)
-		this.e_iframe.style.visibility = 'visible';
-
-	// change icon and status
-	this.e_icon.src = this.a_tpl.imgpath + 'no_cal.gif';
-	this.e_icon.title = 'Close Calendar';
-	this.b_visible = true;
-}
-
-function f_tcalHide (n_date) {
-	if (n_date)
-		this.e_input.value = this.f_generDate(new Date(n_date));
-
-	// no action if not visible
-	if (!this.b_visible)
-		return;
-
-	// hide elements
-	if (this.e_iframe)
-		this.e_iframe.style.visibility = 'hidden';
-	if (this.e_shade)
-		this.e_shade.style.visibility = 'hidden';
-	this.e_div.style.visibility = 'hidden';
-	
-	// change icon and status
-	this.e_icon = f_getElement(this.s_iconId);
-	this.e_icon.src = this.a_tpl.imgpath + 'cal.gif';
-	this.e_icon.title = 'Open Calendar';
-	this.b_visible = false;
-}
-
-function f_tcalToggle () {
-	return this.b_visible ? this.f_hide() : this.f_show();
-}
-
-function f_tcalUpdate (d_date) {
-
-	var d_today = this.a_cfg.today ? this.f_parseDate(this.a_cfg.today) : f_tcalResetTime(new Date());
-	var d_selected = this.e_input.value == ''
-		? (this.a_cfg.selected ? this.f_parseDate(this.a_cfg.selected) : d_today)
-		: this.f_parseDate(this.e_input.value);
-
-	// figure out date to display
-	if (!d_date)
-		// selected by default
-		d_date = d_selected;
-	else if (typeof(d_date) == 'number')
-		// get from number
-		d_date = f_tcalResetTime(new Date(d_date));
-	else if (typeof(d_date) == 'string')
-		// parse from string
-		this.f_parseDate(d_date);
-		
-	if (!d_date) return false;
-
-	// first date to display
-	var d_firstday = new Date(d_date);
-	d_firstday.setDate(1);
-	d_firstday.setDate(1 - (7 + d_firstday.getDay() - this.a_tpl.weekstart) % 7);
-	
-	var a_class, s_html = '<table class="ctrl"><tbody><tr>'
-		+ (this.a_tpl.yearscroll ? '<td' + this.f_relDate(d_date, -1, 'y') + ' title="Previous Year"><img src="' + this.a_tpl.imgpath + 'prev_year.gif" /></td>' : '')
-		+ '<td' + this.f_relDate(d_date, -1) + ' title="Previous Month"><img src="' + this.a_tpl.imgpath + 'prev_mon.gif" /></td><th>'
-		+ this.a_tpl.months[d_date.getMonth()] + ' ' + d_date.getFullYear()
-			+ '</th><td' + this.f_relDate(d_date, 1) + ' title="Next Month"><img src="' + this.a_tpl.imgpath + 'next_mon.gif" /></td>'
-		+ (this.a_tpl.yearscroll ? '<td' + this.f_relDate(d_date, 1, 'y') + ' title="Next Year"><img src="' + this.a_tpl.imgpath + 'next_year.gif" /></td></td>' : '')
-		+ '</tr></tbody></table><table><tbody><tr class="wd">';
-
-	// print weekdays titles
-	for (var i = 0; i < 7; i++)
-		s_html += '<th>' + this.a_tpl.weekdays[(this.a_tpl.weekstart + i) % 7] + '</th>';
-	s_html += '</tr>' ;
-
-	// print calendar table
-	var n_date, n_month, d_current = new Date(d_firstday);
-	while (d_current.getMonth() == d_date.getMonth() ||
-		d_current.getMonth() == d_firstday.getMonth()) {
-	
-		// print row heder
-		s_html +='<tr>';
-		for (var n_wday = 0; n_wday < 7; n_wday++) {
-
-			a_class = [];
-			n_date = d_current.getDate();
-			n_month = d_current.getMonth();
-
-			// other month
-			if (d_current.getMonth() != d_date.getMonth())
-				a_class[a_class.length] = 'othermonth';
-			// weekend
-			if (d_current.getDay() == 0 || d_current.getDay() == 6)
-				a_class[a_class.length] = 'weekend';
-			// today
-			if (d_current.valueOf() == d_today.valueOf())
-				a_class[a_class.length] = 'today';
-			// selected
-			if (d_current.valueOf() == d_selected.valueOf())
-				a_class[a_class.length] = 'selected';
-
-			s_html += '<td onclick="A_TCALS[\'' + this.s_id + '\'].f_hide(' + d_current.valueOf() + ')"' + (a_class.length ? ' class="' + a_class.join(' ') + '">' : '>') + n_date + '</td>'
-
-			d_current.setDate(++n_date);
-			while (d_current.getDate() != n_date && d_current.getMonth() == n_month) {
-				alert(n_date + "\n" + d_current + "\n" + new Date());
-				d_current.setHours(d_current.getHours + 1);
-				d_current = f_tcalResetTime(d_current);
-			}
-		}
-		// print row footer
-		s_html +='</tr>';
-	}
-	s_html +='</tbody></table>';
-	
-	// update HTML, positions and sizes
-	this.e_div.innerHTML = s_html;
-
-	var n_width  = this.e_div.offsetWidth;
-	var n_height = this.e_div.offsetHeight;
-	var n_top  = f_getPosition (this.e_icon, 'Top') + this.e_icon.offsetHeight;
-	var n_left = f_getPosition (this.e_icon, 'Left') - n_width + this.e_icon.offsetWidth;
-	if (n_left < 0) n_left = 0;
-	
-	this.e_div.style.left = n_left + 'px';
-	this.e_div.style.top  = n_top + 'px';
-
-	this.e_shade.style.width = (n_width + 8) + 'px';
-	this.e_shade.style.left = (n_left - 1) + 'px';
-	this.e_shade.style.top = (n_top - 1) + 'px';
-	this.e_shade.innerHTML = b_ieFix
-		? '<table><tbody><tr><td rowspan="2" colspan="2" width="6"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td width="7" height="7" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.a_tpl.imgpath + 'shade_tr.png\', sizingMethod=\'scale\');"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td></tr><tr><td height="' + (n_height - 7) + '" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.a_tpl.imgpath + 'shade_mr.png\', sizingMethod=\'scale\');"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td></tr><tr><td width="7" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.a_tpl.imgpath + 'shade_bl.png\', sizingMethod=\'scale\');"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.a_tpl.imgpath + 'shade_bm.png\', sizingMethod=\'scale\');" height="7" align="left"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.a_tpl.imgpath + 'shade_br.png\', sizingMethod=\'scale\');"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td></tr><tbody></table>'
-		: '<table><tbody><tr><td rowspan="2" width="6"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td rowspan="2"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td width="7" height="7"><img src="' + this.a_tpl.imgpath + 'shade_tr.png"></td></tr><tr><td background="' + this.a_tpl.imgpath + 'shade_mr.png" height="' + (n_height - 7) + '"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td></tr><tr><td><img src="' + this.a_tpl.imgpath + 'shade_bl.png"></td><td background="' + this.a_tpl.imgpath + 'shade_bm.png" height="7" align="left"><img src="' + this.a_tpl.imgpath + 'pixel.gif"></td><td><img src="' + this.a_tpl.imgpath + 'shade_br.png"></td></tr><tbody></table>';
-	
-	if (this.e_iframe) {
-		this.e_iframe.style.left = n_left + 'px';
-		this.e_iframe.style.top  = n_top + 'px';
-		this.e_iframe.style.width = (n_width + 6) + 'px';
-		this.e_iframe.style.height = (n_height + 6) +'px';
-	}
-	return true;
-}
-
-function f_getPosition (e_elemRef, s_coord) {
-	var n_pos = 0, n_offset,
-		e_elem = e_elemRef;
-
-	while (e_elem) {
-		n_offset = e_elem["offset" + s_coord];
-		n_pos += n_offset;
-		e_elem = e_elem.offsetParent;
-	}
-	// margin correction in some browsers
-	if (b_ieMac)
-		n_pos += parseInt(document.body[s_coord.toLowerCase() + 'Margin']);
-	else if (b_safari)
-		n_pos -= n_offset;
-	
-	e_elem = e_elemRef;
-	while (e_elem != document.body) {
-		n_offset = e_elem["scroll" + s_coord];
-		if (n_offset && e_elem.style.overflow == 'scroll')
-			n_pos -= n_offset;
-		e_elem = e_elem.parentNode;
-	}
-	return n_pos;
-}
-
-function f_tcalRelDate (d_date, d_diff, s_units) {
-	var s_units = (s_units == 'y' ? 'FullYear' : 'Month');
-	var d_result = new Date(d_date);
-	d_result['set' + s_units](d_date['get' + s_units]() + d_diff);
-	if (d_result.getDate() != d_date.getDate())
-		d_result.setDate(0);
-	return ' onclick="A_TCALS[\'' + this.s_id + '\'].f_update(' + d_result.valueOf() + ')"';
-}
-
-function f_tcalHideAll () {
-	for (var i = 0; i < window.A_TCALSIDX.length; i++)
-		window.A_TCALSIDX[i].f_hide();
-}	
-
-function f_tcalResetTime (d_date) {
-	d_date.setHours(0);
-	d_date.setMinutes(0);
-	d_date.setSeconds(0);
-	d_date.setMilliseconds(0);
-	return d_date;
-}
-
-f_getElement = document.all ?
-	function (s_id) { return document.all[s_id] } :
-	function (s_id) { return document.getElementById(s_id) };
-
-if (document.addEventListener)
-	window.addEventListener('scroll', f_tcalHideAll, false);
-if (window.attachEvent)
-	window.attachEvent('onscroll', f_tcalHideAll);
-	
-// global variables
-var s_userAgent = navigator.userAgent.toLowerCase(),
-	re_webkit = /WebKit\/(\d+)/i;
-var b_mac = s_userAgent.indexOf('mac') != -1,
-	b_ie5 = s_userAgent.indexOf('msie 5') != -1,
-	b_ie6 = s_userAgent.indexOf('msie 6') != -1 && s_userAgent.indexOf('opera') == -1;
-var b_ieFix = b_ie5 || b_ie6,
-	b_ieMac  = b_mac && b_ie5,
-	b_safari = b_mac && re_webkit.exec(s_userAgent) && Number(RegExp.$1) < 500;
diff -pruN 3.0.2-2/CHANGELOG.TXT 3.2-2/CHANGELOG.TXT
--- 3.0.2-2/CHANGELOG.TXT	2017-02-08 20:46:10.000000000 +0000
+++ 3.2-2/CHANGELOG.TXT	2018-05-02 20:37:27.000000000 +0000
@@ -5,9 +5,60 @@
 # this package in the file LICENSE.TXT.
 #
 # Further details on the project are available at http://postfixadmin.sf.net
-#
-# Last update:
-# $Id: CHANGELOG.TXT 1895 2017-02-08 20:46:10Z christian_boltz $
+
+Version 3.2 - 2018/05/02
+-------------------------------------------------
+
+  - move public facing stuff into public/, this allows us to stop exposing
+    templates_c/ etc. to the world (but also means you'll need to adjust your
+    webserver config)
+  - enable users to reset their passwords by mail or SMS
+    ($CONF['forgotten_user_password_reset'],
+    $CONF['forgotten_admin_password_reset'], $CONF['sms_send_function'])
+  - allow local alias targets (without @domain) - see #134
+  - add $CONF['edit_alias'] to disable "edit_alias" function for users
+  - add php_crypt $CONF["encrypt"] option (see #170 for examples)
+  - add random_compat phar (see: https://github.com/paragonie/random_compat) to
+    support random_int()/random_string() in older PHP versions.
+  - add support for MySQL connections over SSL
+  - language updates: sk, ja, nl, bg, fr, cz
+  - update bundled smarty library (lib/smarty to 3.1.32; includes security fixes)
+  - split up pacrypt() into different functions; add some minimal test coverage
+  - add id autoincrement field to log table (#89)
+  - add token to login.php to prevent CSRF
+  - lots of bugfixes and code cleanup
+  - drop unused code in postfixadmin-cli
+  - introduce PHP-CS-Fixer to enforce code style
+  - vacation.pl:
+    - avoid answering to more known autoresponders
+    - add $no_vacation_pattern to avoid sending autoresponders based on the To:
+      address
+    - replace Deprecated Mail::Sender by Email::Sender
+    - use MIME:EncWords
+    - remove unused MIME::Base64
+  - add docker repo, see https://github.com/postfixadmin/docker
+
+Version 3.1 - 2017/06/25
+-------------------------------------------------
+
+  - broadcast improvements:
+    - allow to send to mailboxes only
+    - allow to send to only some domains
+    - allow domain admins to send to their domains - new config option
+      $CONF['sendmail_all_admins']
+    - don't send to inactive mailboxes or aliases
+  - update squirrelmail plugin
+  - better static DB connection cache to avoid hundreds of mysqli connection
+    when doing lots of escape_string() calls
+  - use $CONF[page_size] in viewlog.php
+  - fix problems with utf8mb4 as default charset in setup.php/upgrade.php
+  - fix default for $CONF[create_mailbox_subdirs_hostoptions]
+  - get rid of variables.inc.php (and initialize variables where needed)
+  - add favicon to fix session handling in chrome (#44)
+  - add check to ensure templates_c/ exists and is writeable
+  - recommend usage of config.local.php in setup.php
+  - remove php4 constructor from cNav_bar (page browser)
+  - update fr.lang
 
 Version 3.0.2 - 2017/02/08 - SVN r1895
 -------------------------------------------------
diff -pruN 3.0.2-2/common.php 3.2-2/common.php
--- 3.0.2-2/common.php	2016-05-22 16:57:09.000000000 +0000
+++ 3.2-2/common.php	2018-05-02 20:37:27.000000000 +0000
@@ -1,37 +1,31 @@
 <?php
-/** 
- * Postfix Admin 
- * 
- * LICENSE 
- * This source file is subject to the GPL license that is bundled with  
- * this package in the file LICENSE.TXT. 
- * 
- * Further details on the project are available at http://postfixadmin.sf.net 
- * 
- * @version $Id: common.php 1846 2016-05-22 16:57:09Z christian_boltz $ 
- * @license GNU GPL v2 or later. 
- * 
+/**
+ * Postfix Admin
+ *
+ * LICENSE
+ * This source file is subject to the GPL license that is bundled with
+ * this package in the file LICENSE.TXT.
+ *
+ * Further details on the project are available at http://postfixadmin.sf.net
+ *
+ * @version $Id$
+ * @license GNU GPL v2 or later.
+ *
  * File: common.php
  * All pages should include this file - which itself sets up the necessary
  * environment and ensures other functions are loaded.
  */
 
-if(!defined('POSTFIXADMIN')) { # already defined if called from setup.php
+if (!defined('POSTFIXADMIN')) { # already defined if called from setup.php
     define('POSTFIXADMIN', 1); # checked in included files
 
     if (!defined('POSTFIXADMIN_CLI')) {
         // this is the default; see also https://sourceforge.net/p/postfixadmin/bugs/347/
-        session_cache_limiter('nocache'); 
+        session_cache_limiter('nocache');
         session_name('postfixadmin_session');
         session_start();
 
-        if (defined('POSTFIXADMIN_LOGOUT')) {
-            session_unset();
-            session_destroy();
-            session_start();
-        }
-
-        if(empty($_SESSION['flash'])) {
+        if (empty($_SESSION['flash'])) {
             $_SESSION['flash'] = array();
         }
     }
@@ -41,7 +35,7 @@ $incpath = dirname(__FILE__);
 (ini_get('magic_quotes_gpc') ? ini_set('magic_quotes_runtime', '0') : '1');
 (ini_get('magic_quotes_gpc') ? ini_set('magic_quotes_sybase', '0') : '1');
 
-if(ini_get('register_globals') == 'on') {
+if (ini_get('register_globals') == 'on') {
     die("Please turn off register_globals; edit your php.ini");
 }
 
@@ -52,7 +46,7 @@ if(ini_get('register_globals') == 'on')
 function postfixadmin_autoload($class) {
     $PATH = dirname(__FILE__) . '/model/' . $class . '.php';
 
-    if(is_file($PATH)) {
+    if (is_file($PATH)) {
         require_once($PATH);
         return true;
     }
@@ -60,15 +54,13 @@ function postfixadmin_autoload($class) {
 }
 spl_autoload_register('postfixadmin_autoload');
 
-require_once("$incpath/variables.inc.php");
-
-if(!is_file("$incpath/config.inc.php")) {
+if (!is_file("$incpath/config.inc.php")) {
     die("config.inc.php is missing!");
 }
 require_once("$incpath/config.inc.php");
 
-if(isset($CONF['configured'])) {
-    if($CONF['configured'] == FALSE) {
+if (isset($CONF['configured'])) {
+    if ($CONF['configured'] == false) {
         die("Please edit config.inc.php - change \$CONF['configured'] to true after setting your database settings");
     }
 }
@@ -77,29 +69,31 @@ Config::write($CONF);
 
 require_once("$incpath/languages/language.php");
 require_once("$incpath/functions.inc.php");
+require_once("$incpath/lib/random_compat.phar");
 
 if (defined('POSTFIXADMIN_CLI')) {
     $language = 'en'; # TODO: make configurable or autodetect from locale settings
 } else {
-    $language = check_language (); # TODO: storing the language only at login instead of calling check_language() on every page would save some processor cycles ;-)
+    $language = check_language(); # TODO: storing the language only at login instead of calling check_language() on every page would save some processor cycles ;-)
     $_SESSION['lang'] = $language;
 }
 
 require_once("$incpath/languages/" . $language . ".lang");
 
-if(!empty($CONF['language_hook']) && function_exists($CONF['language_hook'])) {
+if (!empty($CONF['language_hook']) && function_exists($CONF['language_hook'])) {
     $hook_func = $CONF['language_hook'];
-    $PALANG = $hook_func ($PALANG, $language);
+    $PALANG = $hook_func($PALANG, $language);
 }
 
 Config::write('__LANG', $PALANG);
 
+unset($incpath);
 
 if (!defined('POSTFIXADMIN_CLI')) {
-    if(!is_file("$incpath/smarty.inc.php")) {
+    if (!is_file(dirname(__FILE__) . "/lib/smarty.inc.php")) {
         die("smarty.inc.php is missing! Something is wrong...");
     }
-    require_once ("$incpath/smarty.inc.php");
+    require_once(dirname(__FILE__) . "/lib/smarty.inc.php");
 }
+
 /* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */
-?>
diff -pruN 3.0.2-2/composer.json 3.2-2/composer.json
--- 3.0.2-2/composer.json	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/composer.json	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,23 @@
+{
+    "name": "postfixadmin/postfixadmin",
+    "description": "web based administration interface for Postfix mail servers",
+    "type": "project",
+    "license": "GPL-2.0",
+    "scripts": {
+        "check-format": "php-cs-fixer fix --ansi --dry-run --diff",
+        "format": "php-cs-fixer fix --ansi",
+        "lint": "@php ./vendor/bin/parallel-lint --exclude vendor/ .",
+        "test": "@php ./vendor/bin/phpunit tests/"
+    },
+    "require": {
+        "php": ">=5.2"
+    },
+    "require-dev": {
+        "friendsofphp/php-cs-fixer": "^2.7",
+        "vimeo/psalm":"^1.0",
+        "jakub-onderka/php-parallel-lint": "^0.9.2",
+        "phpunit/phpunit": "^5.7",
+        "zendframework/zendframework1": "^1.12.0"
+    }
+
+}
diff -pruN 3.0.2-2/composer.lock 3.2-2/composer.lock
--- 3.0.2-2/composer.lock	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/composer.lock	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,2516 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "d81d48a0d7b315ede9f1b490c2fecce3",
+    "packages": [],
+    "packages-dev": [
+        {
+            "name": "composer/semver",
+            "version": "1.4.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/composer/semver.git",
+                "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573",
+                "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3.2 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.5 || ^5.0.5",
+                "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Composer\\Semver\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nils Adermann",
+                    "email": "naderman@naderman.de",
+                    "homepage": "http://www.naderman.de"
+                },
+                {
+                    "name": "Jordi Boggiano",
+                    "email": "j.boggiano@seld.be",
+                    "homepage": "http://seld.be"
+                },
+                {
+                    "name": "Rob Bast",
+                    "email": "rob.bast@gmail.com",
+                    "homepage": "http://robbast.nl"
+                }
+            ],
+            "description": "Semver library that offers utilities, version constraint parsing and validation.",
+            "keywords": [
+                "semantic",
+                "semver",
+                "validation",
+                "versioning"
+            ],
+            "time": "2016-08-30T16:08:34+00:00"
+        },
+        {
+            "name": "doctrine/annotations",
+            "version": "v1.4.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/annotations.git",
+                "reference": "54cacc9b81758b14e3ce750f205a393d52339e97"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97",
+                "reference": "54cacc9b81758b14e3ce750f205a393d52339e97",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/lexer": "1.*",
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "doctrine/cache": "1.*",
+                "phpunit/phpunit": "^5.7"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Jonathan Wage",
+                    "email": "jonwage@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Docblock Annotations Parser",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "annotations",
+                "docblock",
+                "parser"
+            ],
+            "time": "2017-02-24T16:22:25+00:00"
+        },
+        {
+            "name": "doctrine/instantiator",
+            "version": "1.0.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/instantiator.git",
+                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
+                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3,<8.0-DEV"
+            },
+            "require-dev": {
+                "athletic/athletic": "~0.1.8",
+                "ext-pdo": "*",
+                "ext-phar": "*",
+                "phpunit/phpunit": "~4.0",
+                "squizlabs/php_codesniffer": "~2.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Marco Pivetta",
+                    "email": "ocramius@gmail.com",
+                    "homepage": "http://ocramius.github.com/"
+                }
+            ],
+            "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+            "homepage": "https://github.com/doctrine/instantiator",
+            "keywords": [
+                "constructor",
+                "instantiate"
+            ],
+            "time": "2015-06-14T21:17:01+00:00"
+        },
+        {
+            "name": "doctrine/lexer",
+            "version": "v1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/lexer.git",
+                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
+                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Doctrine\\Common\\Lexer\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "lexer",
+                "parser"
+            ],
+            "time": "2014-09-09T13:34:57+00:00"
+        },
+        {
+            "name": "friendsofphp/php-cs-fixer",
+            "version": "v2.10.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
+                "reference": "74e4682a4073bc8bc2d4ff2b30a4873ac76cc1f1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/74e4682a4073bc8bc2d4ff2b30a4873ac76cc1f1",
+                "reference": "74e4682a4073bc8bc2d4ff2b30a4873ac76cc1f1",
+                "shasum": ""
+            },
+            "require": {
+                "composer/semver": "^1.4",
+                "doctrine/annotations": "^1.2",
+                "ext-json": "*",
+                "ext-tokenizer": "*",
+                "gecko-packages/gecko-php-unit": "^2.0 || ^3.0",
+                "php": "^5.6 || >=7.0 <7.3",
+                "php-cs-fixer/diff": "^1.2",
+                "symfony/console": "^3.2 || ^4.0",
+                "symfony/event-dispatcher": "^3.0 || ^4.0",
+                "symfony/filesystem": "^3.0 || ^4.0",
+                "symfony/finder": "^3.0 || ^4.0",
+                "symfony/options-resolver": "^3.0 || ^4.0",
+                "symfony/polyfill-php70": "^1.0",
+                "symfony/polyfill-php72": "^1.4",
+                "symfony/process": "^3.0 || ^4.0",
+                "symfony/stopwatch": "^3.0 || ^4.0"
+            },
+            "conflict": {
+                "hhvm": "*"
+            },
+            "require-dev": {
+                "johnkary/phpunit-speedtrap": "^1.1 || ^2.0@dev",
+                "justinrainbow/json-schema": "^5.0",
+                "keradus/cli-executor": "^1.0",
+                "mikey179/vfsstream": "^1.6",
+                "php-coveralls/php-coveralls": "^2.0",
+                "php-cs-fixer/accessible-object": "^1.0",
+                "phpunit/phpunit": "^5.7.23 || ^6.4.3",
+                "phpunitgoodpractices/traits": "^1.0",
+                "symfony/phpunit-bridge": "^3.2.2 || ^4.0"
+            },
+            "suggest": {
+                "ext-mbstring": "For handling non-UTF8 characters in cache signature.",
+                "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible."
+            },
+            "bin": [
+                "php-cs-fixer"
+            ],
+            "type": "application",
+            "autoload": {
+                "psr-4": {
+                    "PhpCsFixer\\": "src/"
+                },
+                "classmap": [
+                    "tests/Test/AbstractFixerTestCase.php",
+                    "tests/Test/AbstractIntegrationCaseFactory.php",
+                    "tests/Test/AbstractIntegrationTestCase.php",
+                    "tests/Test/Assert/AssertTokensTrait.php",
+                    "tests/Test/IntegrationCase.php",
+                    "tests/Test/IntegrationCaseFactory.php",
+                    "tests/Test/IntegrationCaseFactoryInterface.php",
+                    "tests/Test/InternalIntegrationCaseFactory.php",
+                    "tests/TestCase.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Dariusz RumiÅ„ski",
+                    "email": "dariusz.ruminski@gmail.com"
+                },
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "A tool to automatically fix PHP code style",
+            "time": "2018-02-03T08:30:06+00:00"
+        },
+        {
+            "name": "gecko-packages/gecko-php-unit",
+            "version": "v3.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/GeckoPackages/GeckoPHPUnit.git",
+                "reference": "6a866551dffc2154c1b091bae3a7877d39c25ca3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/GeckoPackages/GeckoPHPUnit/zipball/6a866551dffc2154c1b091bae3a7877d39c25ca3",
+                "reference": "6a866551dffc2154c1b091bae3a7877d39c25ca3",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.0"
+            },
+            "suggest": {
+                "ext-dom": "When testing with xml.",
+                "ext-libxml": "When testing with xml.",
+                "phpunit/phpunit": "This is an extension for it so make sure you have it some way."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "GeckoPackages\\PHPUnit\\": "src/PHPUnit"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Additional PHPUnit asserts and constraints.",
+            "homepage": "https://github.com/GeckoPackages",
+            "keywords": [
+                "extension",
+                "filesystem",
+                "phpunit"
+            ],
+            "time": "2017-08-23T07:46:41+00:00"
+        },
+        {
+            "name": "jakub-onderka/php-parallel-lint",
+            "version": "v0.9.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git",
+                "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/2ead2e4043ab125bee9554f356e0a86742c2d4fa",
+                "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "jakub-onderka/php-console-highlighter": "~0.3",
+                "nette/tester": "~1.3"
+            },
+            "suggest": {
+                "jakub-onderka/php-console-highlighter": "Highlight syntax in code snippet"
+            },
+            "bin": [
+                "parallel-lint"
+            ],
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "./"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jakub Onderka",
+                    "email": "jakub.onderka@gmail.com"
+                }
+            ],
+            "description": "This tool check syntax of PHP files about 20x faster than serial check.",
+            "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint",
+            "time": "2015-12-15T10:42:16+00:00"
+        },
+        {
+            "name": "myclabs/deep-copy",
+            "version": "1.7.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/myclabs/DeepCopy.git",
+                "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e",
+                "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "doctrine/collections": "^1.0",
+                "doctrine/common": "^2.6",
+                "phpunit/phpunit": "^4.1"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "DeepCopy\\": "src/DeepCopy/"
+                },
+                "files": [
+                    "src/DeepCopy/deep_copy.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Create deep copies (clones) of your objects",
+            "keywords": [
+                "clone",
+                "copy",
+                "duplicate",
+                "object",
+                "object graph"
+            ],
+            "time": "2017-10-19T19:58:43+00:00"
+        },
+        {
+            "name": "paragonie/random_compat",
+            "version": "v2.0.11",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/paragonie/random_compat.git",
+                "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8",
+                "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "4.*|5.*"
+            },
+            "suggest": {
+                "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "lib/random.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Paragon Initiative Enterprises",
+                    "email": "security@paragonie.com",
+                    "homepage": "https://paragonie.com"
+                }
+            ],
+            "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+            "keywords": [
+                "csprng",
+                "pseudorandom",
+                "random"
+            ],
+            "time": "2017-09-27T21:40:39+00:00"
+        },
+        {
+            "name": "php-cs-fixer/diff",
+            "version": "v1.3.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/PHP-CS-Fixer/diff.git",
+                "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/78bb099e9c16361126c86ce82ec4405ebab8e756",
+                "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.7.23 || ^6.4.3",
+                "symfony/process": "^3.3"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Kore Nordmann",
+                    "email": "mail@kore-nordmann.de"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                },
+                {
+                    "name": "SpacePossum"
+                }
+            ],
+            "description": "sebastian/diff v2 backport support for PHP5.6",
+            "homepage": "https://github.com/PHP-CS-Fixer",
+            "keywords": [
+                "diff"
+            ],
+            "time": "2018-02-15T16:58:55+00:00"
+        },
+        {
+            "name": "phpdocumentor/reflection-common",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
+                "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
+                "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.6"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "phpDocumentor\\Reflection\\": [
+                        "src"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jaap van Otterdijk",
+                    "email": "opensource@ijaap.nl"
+                }
+            ],
+            "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
+            "homepage": "http://www.phpdoc.org",
+            "keywords": [
+                "FQSEN",
+                "phpDocumentor",
+                "phpdoc",
+                "reflection",
+                "static analysis"
+            ],
+            "time": "2017-09-11T18:02:19+00:00"
+        },
+        {
+            "name": "phpdocumentor/reflection-docblock",
+            "version": "4.3.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+                "reference": "94fd0001232e47129dd3504189fa1c7225010d08"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08",
+                "reference": "94fd0001232e47129dd3504189fa1c7225010d08",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0",
+                "phpdocumentor/reflection-common": "^1.0.0",
+                "phpdocumentor/type-resolver": "^0.4.0",
+                "webmozart/assert": "^1.0"
+            },
+            "require-dev": {
+                "doctrine/instantiator": "~1.0.5",
+                "mockery/mockery": "^1.0",
+                "phpunit/phpunit": "^6.4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "phpDocumentor\\Reflection\\": [
+                        "src/"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mike van Riel",
+                    "email": "me@mikevanriel.com"
+                }
+            ],
+            "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
+            "time": "2017-11-30T07:14:17+00:00"
+        },
+        {
+            "name": "phpdocumentor/type-resolver",
+            "version": "0.4.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/TypeResolver.git",
+                "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
+                "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "phpdocumentor/reflection-common": "^1.0"
+            },
+            "require-dev": {
+                "mockery/mockery": "^0.9.4",
+                "phpunit/phpunit": "^5.2||^4.8.24"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "phpDocumentor\\Reflection\\": [
+                        "src/"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mike van Riel",
+                    "email": "me@mikevanriel.com"
+                }
+            ],
+            "time": "2017-07-14T14:27:02+00:00"
+        },
+        {
+            "name": "phpspec/prophecy",
+            "version": "1.7.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpspec/prophecy.git",
+                "reference": "9f901e29c93dae4aa77c0bb161df4276f9c9a1be"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/9f901e29c93dae4aa77c0bb161df4276f9c9a1be",
+                "reference": "9f901e29c93dae4aa77c0bb161df4276f9c9a1be",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/instantiator": "^1.0.2",
+                "php": "^5.3|^7.0",
+                "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
+                "sebastian/comparator": "^1.1|^2.0",
+                "sebastian/recursion-context": "^1.0|^2.0|^3.0"
+            },
+            "require-dev": {
+                "phpspec/phpspec": "^2.5|^3.2",
+                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.7.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Prophecy\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Konstantin Kudryashov",
+                    "email": "ever.zet@gmail.com",
+                    "homepage": "http://everzet.com"
+                },
+                {
+                    "name": "Marcello Duarte",
+                    "email": "marcello.duarte@gmail.com"
+                }
+            ],
+            "description": "Highly opinionated mocking framework for PHP 5.3+",
+            "homepage": "https://github.com/phpspec/prophecy",
+            "keywords": [
+                "Double",
+                "Dummy",
+                "fake",
+                "mock",
+                "spy",
+                "stub"
+            ],
+            "time": "2018-02-11T18:49:29+00:00"
+        },
+        {
+            "name": "phpunit/php-code-coverage",
+            "version": "4.0.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+                "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d",
+                "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "ext-xmlwriter": "*",
+                "php": "^5.6 || ^7.0",
+                "phpunit/php-file-iterator": "^1.3",
+                "phpunit/php-text-template": "^1.2",
+                "phpunit/php-token-stream": "^1.4.2 || ^2.0",
+                "sebastian/code-unit-reverse-lookup": "^1.0",
+                "sebastian/environment": "^1.3.2 || ^2.0",
+                "sebastian/version": "^1.0 || ^2.0"
+            },
+            "require-dev": {
+                "ext-xdebug": "^2.1.4",
+                "phpunit/phpunit": "^5.7"
+            },
+            "suggest": {
+                "ext-xdebug": "^2.5.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sb@sebastian-bergmann.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+            "keywords": [
+                "coverage",
+                "testing",
+                "xunit"
+            ],
+            "time": "2017-04-02T07:44:40+00:00"
+        },
+        {
+            "name": "phpunit/php-file-iterator",
+            "version": "1.4.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+                "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4",
+                "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sb@sebastian-bergmann.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+            "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+            "keywords": [
+                "filesystem",
+                "iterator"
+            ],
+            "time": "2017-11-27T13:52:08+00:00"
+        },
+        {
+            "name": "phpunit/php-text-template",
+            "version": "1.2.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-text-template.git",
+                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Simple template engine.",
+            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+            "keywords": [
+                "template"
+            ],
+            "time": "2015-06-21T13:50:34+00:00"
+        },
+        {
+            "name": "phpunit/php-timer",
+            "version": "1.0.9",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-timer.git",
+                "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
+                "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3.3 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sb@sebastian-bergmann.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Utility class for timing",
+            "homepage": "https://github.com/sebastianbergmann/php-timer/",
+            "keywords": [
+                "timer"
+            ],
+            "time": "2017-02-26T11:10:40+00:00"
+        },
+        {
+            "name": "phpunit/php-token-stream",
+            "version": "2.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
+                "reference": "791198a2c6254db10131eecfe8c06670700904db"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db",
+                "reference": "791198a2c6254db10131eecfe8c06670700904db",
+                "shasum": ""
+            },
+            "require": {
+                "ext-tokenizer": "*",
+                "php": "^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.2.4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Wrapper around PHP's tokenizer extension.",
+            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
+            "keywords": [
+                "tokenizer"
+            ],
+            "time": "2017-11-27T05:48:46+00:00"
+        },
+        {
+            "name": "phpunit/phpunit",
+            "version": "5.7.27",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/phpunit.git",
+                "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c",
+                "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "ext-json": "*",
+                "ext-libxml": "*",
+                "ext-mbstring": "*",
+                "ext-xml": "*",
+                "myclabs/deep-copy": "~1.3",
+                "php": "^5.6 || ^7.0",
+                "phpspec/prophecy": "^1.6.2",
+                "phpunit/php-code-coverage": "^4.0.4",
+                "phpunit/php-file-iterator": "~1.4",
+                "phpunit/php-text-template": "~1.2",
+                "phpunit/php-timer": "^1.0.6",
+                "phpunit/phpunit-mock-objects": "^3.2",
+                "sebastian/comparator": "^1.2.4",
+                "sebastian/diff": "^1.4.3",
+                "sebastian/environment": "^1.3.4 || ^2.0",
+                "sebastian/exporter": "~2.0",
+                "sebastian/global-state": "^1.1",
+                "sebastian/object-enumerator": "~2.0",
+                "sebastian/resource-operations": "~1.0",
+                "sebastian/version": "^1.0.6|^2.0.1",
+                "symfony/yaml": "~2.1|~3.0|~4.0"
+            },
+            "conflict": {
+                "phpdocumentor/reflection-docblock": "3.0.2"
+            },
+            "require-dev": {
+                "ext-pdo": "*"
+            },
+            "suggest": {
+                "ext-xdebug": "*",
+                "phpunit/php-invoker": "~1.1"
+            },
+            "bin": [
+                "phpunit"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "5.7.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "The PHP Unit Testing framework.",
+            "homepage": "https://phpunit.de/",
+            "keywords": [
+                "phpunit",
+                "testing",
+                "xunit"
+            ],
+            "time": "2018-02-01T05:50:59+00:00"
+        },
+        {
+            "name": "phpunit/phpunit-mock-objects",
+            "version": "3.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
+                "reference": "a23b761686d50a560cc56233b9ecf49597cc9118"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118",
+                "reference": "a23b761686d50a560cc56233b9ecf49597cc9118",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/instantiator": "^1.0.2",
+                "php": "^5.6 || ^7.0",
+                "phpunit/php-text-template": "^1.2",
+                "sebastian/exporter": "^1.2 || ^2.0"
+            },
+            "conflict": {
+                "phpunit/phpunit": "<5.4.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.4"
+            },
+            "suggest": {
+                "ext-soap": "*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.2.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sb@sebastian-bergmann.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Mock Object library for PHPUnit",
+            "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
+            "keywords": [
+                "mock",
+                "xunit"
+            ],
+            "time": "2017-06-30T09:13:00+00:00"
+        },
+        {
+            "name": "psr/log",
+            "version": "1.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/log.git",
+                "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+                "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Log\\": "Psr/Log/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for logging libraries",
+            "homepage": "https://github.com/php-fig/log",
+            "keywords": [
+                "log",
+                "psr",
+                "psr-3"
+            ],
+            "time": "2016-10-10T12:19:37+00:00"
+        },
+        {
+            "name": "sebastian/code-unit-reverse-lookup",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+                "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
+                "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.7 || ^6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Looks up which function or method a line of code belongs to",
+            "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+            "time": "2017-03-04T06:30:41+00:00"
+        },
+        {
+            "name": "sebastian/comparator",
+            "version": "1.2.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/comparator.git",
+                "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
+                "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "sebastian/diff": "~1.2",
+                "sebastian/exporter": "~1.2 || ~2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.2.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jeff Welch",
+                    "email": "whatthejeff@gmail.com"
+                },
+                {
+                    "name": "Volker Dusch",
+                    "email": "github@wallbash.com"
+                },
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@2bepublished.at"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Provides the functionality to compare PHP values for equality",
+            "homepage": "http://www.github.com/sebastianbergmann/comparator",
+            "keywords": [
+                "comparator",
+                "compare",
+                "equality"
+            ],
+            "time": "2017-01-29T09:50:25+00:00"
+        },
+        {
+            "name": "sebastian/diff",
+            "version": "1.4.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/diff.git",
+                "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4",
+                "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3.3 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Kore Nordmann",
+                    "email": "mail@kore-nordmann.de"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Diff implementation",
+            "homepage": "https://github.com/sebastianbergmann/diff",
+            "keywords": [
+                "diff"
+            ],
+            "time": "2017-05-22T07:24:03+00:00"
+        },
+        {
+            "name": "sebastian/environment",
+            "version": "2.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/environment.git",
+                "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
+                "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Provides functionality to handle HHVM/PHP environments",
+            "homepage": "http://www.github.com/sebastianbergmann/environment",
+            "keywords": [
+                "Xdebug",
+                "environment",
+                "hhvm"
+            ],
+            "time": "2016-11-26T07:53:53+00:00"
+        },
+        {
+            "name": "sebastian/exporter",
+            "version": "2.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/exporter.git",
+                "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4",
+                "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "sebastian/recursion-context": "~2.0"
+            },
+            "require-dev": {
+                "ext-mbstring": "*",
+                "phpunit/phpunit": "~4.4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jeff Welch",
+                    "email": "whatthejeff@gmail.com"
+                },
+                {
+                    "name": "Volker Dusch",
+                    "email": "github@wallbash.com"
+                },
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@2bepublished.at"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                },
+                {
+                    "name": "Adam Harvey",
+                    "email": "aharvey@php.net"
+                }
+            ],
+            "description": "Provides the functionality to export PHP variables for visualization",
+            "homepage": "http://www.github.com/sebastianbergmann/exporter",
+            "keywords": [
+                "export",
+                "exporter"
+            ],
+            "time": "2016-11-19T08:54:04+00:00"
+        },
+        {
+            "name": "sebastian/global-state",
+            "version": "1.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/global-state.git",
+                "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
+                "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.2"
+            },
+            "suggest": {
+                "ext-uopz": "*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Snapshotting of global state",
+            "homepage": "http://www.github.com/sebastianbergmann/global-state",
+            "keywords": [
+                "global state"
+            ],
+            "time": "2015-10-12T03:26:01+00:00"
+        },
+        {
+            "name": "sebastian/object-enumerator",
+            "version": "2.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+                "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7",
+                "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6",
+                "sebastian/recursion-context": "~2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~5"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+            "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+            "time": "2017-02-18T15:18:39+00:00"
+        },
+        {
+            "name": "sebastian/recursion-context",
+            "version": "2.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/recursion-context.git",
+                "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a",
+                "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jeff Welch",
+                    "email": "whatthejeff@gmail.com"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                },
+                {
+                    "name": "Adam Harvey",
+                    "email": "aharvey@php.net"
+                }
+            ],
+            "description": "Provides functionality to recursively process PHP variables",
+            "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+            "time": "2016-11-19T07:33:16+00:00"
+        },
+        {
+            "name": "sebastian/resource-operations",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/resource-operations.git",
+                "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
+                "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Provides a list of PHP built-in functions that operate on resources",
+            "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
+            "time": "2015-07-28T20:34:47+00:00"
+        },
+        {
+            "name": "sebastian/version",
+            "version": "2.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/version.git",
+                "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019",
+                "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+            "homepage": "https://github.com/sebastianbergmann/version",
+            "time": "2016-10-03T07:35:21+00:00"
+        },
+        {
+            "name": "symfony/console",
+            "version": "v3.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/console.git",
+                "reference": "26b6f419edda16c19775211987651cb27baea7f1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/console/zipball/26b6f419edda16c19775211987651cb27baea7f1",
+                "reference": "26b6f419edda16c19775211987651cb27baea7f1",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5.9|>=7.0.8",
+                "symfony/debug": "~2.8|~3.0|~4.0",
+                "symfony/polyfill-mbstring": "~1.0"
+            },
+            "conflict": {
+                "symfony/dependency-injection": "<3.4",
+                "symfony/process": "<3.3"
+            },
+            "require-dev": {
+                "psr/log": "~1.0",
+                "symfony/config": "~3.3|~4.0",
+                "symfony/dependency-injection": "~3.4|~4.0",
+                "symfony/event-dispatcher": "~2.8|~3.0|~4.0",
+                "symfony/lock": "~3.4|~4.0",
+                "symfony/process": "~3.3|~4.0"
+            },
+            "suggest": {
+                "psr/log": "For using the console logger",
+                "symfony/event-dispatcher": "",
+                "symfony/lock": "",
+                "symfony/process": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Console\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Console Component",
+            "homepage": "https://symfony.com",
+            "time": "2018-01-29T09:03:43+00:00"
+        },
+        {
+            "name": "symfony/debug",
+            "version": "v3.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/debug.git",
+                "reference": "53f6af2805daf52a43b393b93d2f24925d35c937"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/debug/zipball/53f6af2805daf52a43b393b93d2f24925d35c937",
+                "reference": "53f6af2805daf52a43b393b93d2f24925d35c937",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5.9|>=7.0.8",
+                "psr/log": "~1.0"
+            },
+            "conflict": {
+                "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
+            },
+            "require-dev": {
+                "symfony/http-kernel": "~2.8|~3.0|~4.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Debug\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Debug Component",
+            "homepage": "https://symfony.com",
+            "time": "2018-01-18T22:16:57+00:00"
+        },
+        {
+            "name": "symfony/event-dispatcher",
+            "version": "v3.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/event-dispatcher.git",
+                "reference": "26b87b6bca8f8f797331a30b76fdae5342dc26ca"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/26b87b6bca8f8f797331a30b76fdae5342dc26ca",
+                "reference": "26b87b6bca8f8f797331a30b76fdae5342dc26ca",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5.9|>=7.0.8"
+            },
+            "conflict": {
+                "symfony/dependency-injection": "<3.3"
+            },
+            "require-dev": {
+                "psr/log": "~1.0",
+                "symfony/config": "~2.8|~3.0|~4.0",
+                "symfony/dependency-injection": "~3.3|~4.0",
+                "symfony/expression-language": "~2.8|~3.0|~4.0",
+                "symfony/stopwatch": "~2.8|~3.0|~4.0"
+            },
+            "suggest": {
+                "symfony/dependency-injection": "",
+                "symfony/http-kernel": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\EventDispatcher\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony EventDispatcher Component",
+            "homepage": "https://symfony.com",
+            "time": "2018-01-03T07:37:34+00:00"
+        },
+        {
+            "name": "symfony/filesystem",
+            "version": "v3.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/filesystem.git",
+                "reference": "e078773ad6354af38169faf31c21df0f18ace03d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/filesystem/zipball/e078773ad6354af38169faf31c21df0f18ace03d",
+                "reference": "e078773ad6354af38169faf31c21df0f18ace03d",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5.9|>=7.0.8"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Filesystem\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Filesystem Component",
+            "homepage": "https://symfony.com",
+            "time": "2018-01-03T07:37:34+00:00"
+        },
+        {
+            "name": "symfony/finder",
+            "version": "v3.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/finder.git",
+                "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/613e26310776f49a1773b6737c6bd554b8bc8c6f",
+                "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5.9|>=7.0.8"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Finder\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Finder Component",
+            "homepage": "https://symfony.com",
+            "time": "2018-01-03T07:37:34+00:00"
+        },
+        {
+            "name": "symfony/options-resolver",
+            "version": "v3.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/options-resolver.git",
+                "reference": "f3109a6aedd20e35c3a33190e932c2b063b7b50e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/options-resolver/zipball/f3109a6aedd20e35c3a33190e932c2b063b7b50e",
+                "reference": "f3109a6aedd20e35c3a33190e932c2b063b7b50e",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5.9|>=7.0.8"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\OptionsResolver\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony OptionsResolver Component",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "config",
+                "configuration",
+                "options"
+            ],
+            "time": "2018-01-11T07:56:07+00:00"
+        },
+        {
+            "name": "symfony/polyfill-mbstring",
+            "version": "v1.7.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-mbstring.git",
+                "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b",
+                "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "suggest": {
+                "ext-mbstring": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Mbstring\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for the Mbstring extension",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "mbstring",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "time": "2018-01-30T19:27:44+00:00"
+        },
+        {
+            "name": "symfony/polyfill-php70",
+            "version": "v1.7.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-php70.git",
+                "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/3532bfcd8f933a7816f3a0a59682fc404776600f",
+                "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f",
+                "shasum": ""
+            },
+            "require": {
+                "paragonie/random_compat": "~1.0|~2.0",
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php70\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ],
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "time": "2018-01-30T19:27:44+00:00"
+        },
+        {
+            "name": "symfony/polyfill-php72",
+            "version": "v1.7.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-php72.git",
+                "reference": "8eca20c8a369e069d4f4c2ac9895144112867422"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/8eca20c8a369e069d4f4c2ac9895144112867422",
+                "reference": "8eca20c8a369e069d4f4c2ac9895144112867422",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php72\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "time": "2018-01-31T17:43:24+00:00"
+        },
+        {
+            "name": "symfony/process",
+            "version": "v3.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/process.git",
+                "reference": "09a5172057be8fc677840e591b17f385e58c7c0d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/process/zipball/09a5172057be8fc677840e591b17f385e58c7c0d",
+                "reference": "09a5172057be8fc677840e591b17f385e58c7c0d",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5.9|>=7.0.8"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Process\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Process Component",
+            "homepage": "https://symfony.com",
+            "time": "2018-01-29T09:03:43+00:00"
+        },
+        {
+            "name": "symfony/stopwatch",
+            "version": "v3.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/stopwatch.git",
+                "reference": "c865551df7c17e63fc1f09f763db04387f91ae4d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/stopwatch/zipball/c865551df7c17e63fc1f09f763db04387f91ae4d",
+                "reference": "c865551df7c17e63fc1f09f763db04387f91ae4d",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5.9|>=7.0.8"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Stopwatch\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Stopwatch Component",
+            "homepage": "https://symfony.com",
+            "time": "2018-01-03T07:37:34+00:00"
+        },
+        {
+            "name": "symfony/yaml",
+            "version": "v3.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/yaml.git",
+                "reference": "eab73b6c21d27ae4cd037c417618dfd4befb0bfe"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/yaml/zipball/eab73b6c21d27ae4cd037c417618dfd4befb0bfe",
+                "reference": "eab73b6c21d27ae4cd037c417618dfd4befb0bfe",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5.9|>=7.0.8"
+            },
+            "conflict": {
+                "symfony/console": "<3.4"
+            },
+            "require-dev": {
+                "symfony/console": "~3.4|~4.0"
+            },
+            "suggest": {
+                "symfony/console": "For validating YAML files using the lint command"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Yaml\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Yaml Component",
+            "homepage": "https://symfony.com",
+            "time": "2018-01-21T19:05:02+00:00"
+        },
+        {
+            "name": "webmozart/assert",
+            "version": "1.3.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/webmozart/assert.git",
+                "reference": "0df1908962e7a3071564e857d86874dad1ef204a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a",
+                "reference": "0df1908962e7a3071564e857d86874dad1ef204a",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3.3 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.6",
+                "sebastian/version": "^1.0.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.3-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Webmozart\\Assert\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@gmail.com"
+                }
+            ],
+            "description": "Assertions to validate method input/output with nice error messages.",
+            "keywords": [
+                "assert",
+                "check",
+                "validate"
+            ],
+            "time": "2018-01-29T19:49:41+00:00"
+        },
+        {
+            "name": "zendframework/zendframework1",
+            "version": "1.12.20",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zf1.git",
+                "reference": "737ef159654fbbef37cf9af742b2c8f9690c2ece"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zf1/zipball/737ef159654fbbef37cf9af742b2c8f9690c2ece",
+                "reference": "737ef159654fbbef37cf9af742b2c8f9690c2ece",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.2.11"
+            },
+            "require-dev": {
+                "phpunit/dbunit": "1.3.*",
+                "phpunit/phpunit": "3.7.*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.12.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Zend_": "library/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                "library/"
+            ],
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "Zend Framework 1",
+            "homepage": "http://framework.zend.com/",
+            "keywords": [
+                "ZF1",
+                "framework"
+            ],
+            "time": "2016-09-08T14:50:34+00:00"
+        }
+    ],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": [],
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": {
+        "php": ">=5.2"
+    },
+    "platform-dev": []
+}
diff -pruN 3.0.2-2/config.inc.php 3.2-2/config.inc.php
--- 3.0.2-2/config.inc.php	2016-10-20 21:26:13.000000000 +0000
+++ 3.2-2/config.inc.php	2018-05-02 20:37:27.000000000 +0000
@@ -8,13 +8,30 @@
  * 
  * Further details on the project are available at http://postfixadmin.sf.net 
  * 
- * @version $Id: config.inc.php 1876 2016-10-20 21:26:13Z christian_boltz $ 
+ * @version $Id$ 
  * @license GNU GPL v2 or later. 
  * 
  * File: config.inc.php
  * Contains configuration options.
  */
 
+
+################################################################################
+#                                                                              #
+#    PostfixAdmin default configuration                                        #
+#                                                                              #
+#    This file contains the PostfixAdmin default configuration settings.       #
+#                                                                              #
+#    Please do not edit this file.                                             #
+#                                                                              #
+#    Instead, add the options you want to change/override to                   #
+#    config.local.php (if it doesn't exist, create it).                        #
+#    This will make version upgrades much easier.                              #
+#                                                                              #
+################################################################################
+
+
+
 /*****************************************************************
  *  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
  * You have to set $CONF['configured'] = true; before the
@@ -86,11 +103,25 @@ $CONF['database_host'] = 'localhost';
 $CONF['database_user'] = 'postfix';
 $CONF['database_password'] = 'postfixadmin';
 $CONF['database_name'] = 'postfix';
+
+// Database SSL Config
+$CONF['database_use_ssl'] = false;
+$CONF['database_ssl_key'] = NULL;
+$CONF['database_ssl_cert'] = NULL;
+$CONF['database_ssl_ca'] = NULL;
+$CONF['database_ssl_ca_path'] = NULL;
+$CONF['database_ssl_cipher'] = NULL;
+
 // If you need to specify a different port for a MYSQL database connection, use e.g.
 //   $CONF['database_host'] = '172.30.33.66:3308';
-// If you need to specify a different port for POSTGRESQL database connection
+//
+// If you need to specify a different port for MySQLi(3306)/POSTGRESQL(5432) database connection
 //   uncomment and change the following
 // $CONF['database_port'] = '5432';
+//
+// If you wish to connect using a local socket file (e.g /var/run/mysql.sock) uncomment the below.
+// $CONF['database_socket'] = '/var/run/mysql/mysqld.sock';
+//
 // If sqlite is used, specify the database file path:
 //   $CONF['database_name'] = '/etc/postfix/sqlite/postfixadmin.db'
 
@@ -119,6 +150,10 @@ $CONF['database_tables'] = array (
 // Leave blank to send email from the logged-in Admin's Email address.
 $CONF['admin_email'] = '';
 
+// Site admin name
+// This will be used as signature in notification messages
+$CONF['admin_name'] = 'Postmaster';
+
 // Mail Server
 // Hostname (FQDN) of your mail server.
 // This is used to send email to Postfix in order to create mailboxes.
@@ -158,6 +193,9 @@ $CONF['authlib_default_flavor'] = 'md5ra
 // $CONF['dovecotpw'] = "/usr/sbin/dovecotpw";
 // for dovecot 2.x (dovecot 2.0.0 - 2.0.7 is not supported!)
 $CONF['dovecotpw'] = "/usr/sbin/doveadm pw";
+if(@file_exists('/usr/bin/doveadm')) { // @ to silence openbase_dir stuff; see https://github.com/postfixadmin/postfixadmin/issues/171
+    $CONF['dovecotpw'] = "/usr/bin/doveadm pw"; # debian
+}
 
 // Password validation
 // New/changed passwords will be validated using all regular expressions in the array.
@@ -364,6 +402,9 @@ $CONF['vacation_choice_of_reply'] = arra
 // to work you need to have the mailbox replicated in the alias table.
 // If you want to take control of these aliases as well set this to 'YES'.
 
+// If you don't want edit alias tab (user mode) set this to 'NO';
+$CONF['edit_alias'] = 'YES';
+
 // Alias control for superadmins
 $CONF['alias_control'] = 'YES';
 
@@ -396,6 +437,9 @@ $CONF['backup'] = 'NO';
 // Send Mail
 // If you don't want sendmail tab set this to 'NO';
 $CONF['sendmail'] = 'YES';
+// Set this to YES if you want to allow non-super-admins to
+// send mails to their users
+$CONF['sendmail_all_admins'] = 'NO';
 
 // Logging
 // If you don't want logging set this to 'NO';
@@ -561,8 +605,40 @@ $CONF['new_quota_table'] = 'YES';
 // $CONF['create_mailbox_subdirs_hostoptions']=array('novalidate-cert','norsh');
 // See also the "Optional flags for names" table at
 // http://www.php.net/manual/en/function.imap-open.php
-$CONF['create_mailbox_subdirs_hostoptions'] = array('');
+$CONF['create_mailbox_subdirs_hostoptions'] = array();
+
+// Optional:
+// Allows a user to reset his forgotten password with a code sent by email/SMS
+$CONF['forgotten_user_password_reset'] = true;
+// Allows an admin to reset his forgotten password with a code sent by email/SMS
+$CONF['forgotten_admin_password_reset'] = false;
+
+// Name of the function to send a SMS
+// Please use a name that begins with "x_" to prevent collisions
+// This function must accept 2 parameters: phone number and message,
+// and return true on success or false on failure
+// Note: if no sms_send_function is defined, the input field for the mobile
+// number won't be displayed
+$CONF['sms_send_function'] = '';
+
+/*
+// Example of send SMS function using Clickatell HTTP API
+function x_send_sms_clickatell($to, $message) {
+
+    $clickatell_api_id = 'CHANGEME';
+    $clickatell_user = 'CHANGEME';
+    $clickatell_password = 'CHANGEME';
+    $clickatell_sender = 'CHANGEME';
 
+    $url = 'https://api.clickatell.com/http/sendmsg?api_id=%s&user=%s&password=%s&to=%s&from=%s&text=%s';
+
+    $url = sprintf($url, $clickatell_api_id, $clickatell_user, $clickatell_password, $to, $clickatell_sender, urlencode($message));
+
+    $result = file_get_contents($url);
+
+    return $result !== false;
+}
+*/
 
 // Theme Config
 // Specify your own logo and CSS file
@@ -583,7 +659,7 @@ $CONF['xmlrpc_enabled'] = false;
 // file (config.local.php) instead of editing this file and override some
 // settings there.
 if (file_exists(dirname(__FILE__) . '/config.local.php')) {
-    include_once(dirname(__FILE__) . '/config.local.php');
+    require_once(dirname(__FILE__) . '/config.local.php');
 }
 
 //
diff -pruN 3.0.2-2/css/calendar.css 3.2-2/css/calendar.css
--- 3.0.2-2/css/calendar.css	2009-11-05 14:55:39.000000000 +0000
+++ 3.2-2/css/calendar.css	1970-01-01 00:00:00.000000000 +0000
@@ -1,95 +0,0 @@
-/* calendar icon */
-img.tcalIcon {
-	cursor: pointer;
-	margin-left: 1px;
-	vertical-align: middle;
-}
-/* calendar container element */
-div#tcal {
-	position: absolute;
-	visibility: hidden;
-	z-index: 100;
-	width: 158px;
-	padding: 2px 0 0 0;
-}
-/* all tables in calendar */
-div#tcal table {
-	width: 100%;
-	border: 1px solid silver;
-	border-collapse: collapse;
-	background-color: white;
-}
-/* navigation table */
-div#tcal table.ctrl {
-	border-bottom: 0;
-}
-/* navigation buttons */
-div#tcal table.ctrl td {
-	width: 15px;
-	height: 20px;
-}
-/* month year header */
-div#tcal table.ctrl th {
-	background-color: white;
-	color: black;
-	border: 0;
-}
-/* week days header */
-div#tcal th {
-	border: 1px solid silver;
-	border-collapse: collapse;
-	text-align: center;
-	padding: 3px 0;
-	font-family: tahoma, verdana, arial;
-	font-size: 10px;
-	background-color: gray;
-	color: white;
-}
-/* date cells */
-div#tcal td {
-	border: 0;
-	border-collapse: collapse;
-	text-align: center;
-	padding: 2px 0;
-	font-family: tahoma, verdana, arial;
-	font-size: 11px;
-	width: 22px;
-	cursor: pointer;
-}
-/* date highlight
-   in case of conflicting settings order here determines the priority from least to most important */
-div#tcal td.othermonth {
-	color: silver;
-}
-div#tcal td.weekend {
-	background-color: #ACD6F5;
-}
-div#tcal td.today {
-	border: 1px solid red;
-}
-div#tcal td.selected {
-	background-color: #FFB3BE;
-}
-/* iframe element used to suppress windowed controls in IE5/6 */
-iframe#tcalIF {
-	position: absolute;
-	visibility: hidden;
-	z-index: 98;
-	border: 0;
-}
-/* transparent shadow */
-div#tcalShade {
-	position: absolute;
-	visibility: hidden;
-	z-index: 99;
-}
-div#tcalShade table {
-	border: 0;
-	border-collapse: collapse;
-	width: 100%;
-}
-div#tcalShade table td {
-	border: 0;
-	border-collapse: collapse;
-	padding: 0;
-}
diff -pruN 3.0.2-2/css/default.css 3.2-2/css/default.css
--- 3.0.2-2/css/default.css	2016-05-15 19:20:59.000000000 +0000
+++ 3.2-2/css/default.css	1970-01-01 00:00:00.000000000 +0000
@@ -1,386 +0,0 @@
-@import url(calendar.css);
-body {
-	background: #ffffff;
-	color: #000000;
-	font-family: "BitStream Vera Sans", Verdana, Arial, Helvetica, sans-serif;
-	font-size: 11px;
-	font-weight: normal;
-	text-align: left;
-}
-
-#container {
-	width:970px;
-	margin:auto;
-}
-a {
-	text-decoration: none;
-	color: #888888;
-}
-
-a:hover {
-	text-decoration: underline;
-	color: #888888;
-}
-
-a:visited, a:active {
-	color: #888888;
-}
-
-table {
-	/* border-spacing: 0; */
-	/* padding: 0; */
-	border-collapse: collapse; /* for IE */
-	text-align: left;
-}
-
-input, .button, textarea {
-	padding: 6px;
-}
-
-input, .button, textarea, select {
-	font-family: "BitStream Vera Sans", Verdana, Arial, Helvetica, sans-serif;
-	font-size: 13px;
-}
-
-.readonly {
-	background:#eee;
-}
-
-.button {
-	border: 1px solid #aaaaaa;
-	color: #777777;
-	background: #dddddd;
-	padding: 3px 3px 3px 3px;
-}
-
-.button:hover, .button:focus {
-	background: #eee;
-	color: #666;
-	text-decoration:none;
-}
-
-.flat {
-	border: 1px solid #888888;
-}
-
-ul.flash-info {
-	border:2px solid #AFE1A6; /* medium green */
-	padding:1em;
-	max-width:970px;
-	margin-left:auto;
-	margin-right:auto;
-	list-style:none;
-}
-
-ul.flash-error {
-	border:2px solid #FF6347; /* tomato */
-	padding:1em;
-	max-width:970px;
-	margin-left:auto;
-	margin-right:auto;
-	list-style:none;
-}
-
-.error_msg {
-	color: #d01313;
-}
-
-#motd {
-	color: maroon;
-	padding-top:2em;
-}
-
-.standout {
-	color: maroon;
-	padding: 3px 3px 3px 3px;
-	text-align: center;
-}
-
-#login_header, #login, #main_menu, #overview,
-#admin_domains, #admin_virtual, .nav_bar, #alias_domain_table,
-#alias_table, #mailbox_table, #overview_table, #log_table,
-#admin_table, #footer, .subnav {
-	width: 990px;
-	margin: 0 auto;
-}
-
-#login_header {
-	padding-bottom: 10px;
-	text-align: left;
-}
-
-#login {
-	width: 990px;
-	margin: 0 auto;
-	background: url(../images/mail_bg.gif) right 50% no-repeat;
-}
-
-#login_table {
-	border-left: none;
-	border-right: 1px solid #999;
-	width: 400px;
-	margin: 0 0 0 200px;
-	border-collapse: separate;
-	border-spacing: 10px;
-}
-
-#login_table h4 {
-	font-size: 13px;
-}
-
-#menu, #tabbar {
-	text-align:center;
-	float:left;
-	width:100%; 
-	margin: 0 auto;
-	padding-top: 10px;
-	white-space: nowrap;
-}
-
-#menu ul, #tabbar  ul	{
-	padding: 0;
-	margin: 0;
-	margin-left:auto;
-	margin-right:auto;
-	list-style: none;
-	text-align: center;
-	position:relative;
-	width:990px;
-	float:left;
-}
-
-#menu li, #tabbar li {
-	float: left;
-	background: #efefef;
-	margin-right: 3px;
-	border-top: 4px solid #aaaaaa;
-	position:relative;
-}
-
-#menu li:hover, #menu li.sfhover, #tabbar li:hover, #tabbar li.sfhover {
-	background: #ccc;
-}
-
-#menu li ul, #tabbar li ul {
-	position: absolute;
-	width: auto;
-	left: -999em; 
-	right:auto;
-	background: #FFFFFF; 
-	color: #999999;
-	border:2px solid white;
-	border-top:none;
-	z-index:101;
-}
-
-#menu li:hover ul, #menu li.sfhover ul, #tabbar li:hover ul, #tabbar li.sfhover ul {
-   left: auto;
-}
-
-#menu li ul li, #tabbar li ul li {
-	float: none;
-	margin-right: 0px;
-	border-top:2px solid white;
-	text-align:left;
-	right:auto;
-}
-
-#menu a, #tabbar a {
-	display: block;
-	width: auto;
-	padding: 20px 5px 5px 5px;
-}
-
-#menu a, #tabbar a, #menu a:hover, #tabbar a:hover {
-	color: #888888;
-}
-
-#menu li ul li a, #tabbar li ul li a {
-	padding: 5px 5px 5px 5px;
-}
-
-.subnav p {
-	padding-left:10px;
-	margin-top:2em;
-	margin-bottom:0;
-	font-size:12px;
-}
-
-#edit_form table {
-	margin: 0 50px;
-	padding-top: 10px;
-	text-align: left;
-}
-
-#edit_form th  {
-	text-align: left;
-	font-size: 12px;
-	margin: 0;
-	line-height: 25px;
-}
-
-.hlp_center {
-	text-align: center;
-}
-
-.help_text {
-	text-align: center;
-	padding-top: 5px;
-	padding-bottom: 5px;
-}
-
-#main_menu table {
-	margin: 0 0;
-	text-align: left;
-	padding-top: 20px;
-	padding-bottom: 20px;
-}
-
-#main_menu table td {
-	padding-left: 30px;
-	padding-bottom: 5px;
-}
-
-#main_menu a {
-	padding-left: 8px;
-}
-
-#main_menu a:hover {
-	color: #333;
-	text-decoration: none;
-	padding-left: 4px;
-	border-bottom: none;
-	border-left: 4px solid #333;
-}
-
-#overview h4, #overview P, #overview FORM, #admin_virtual h4, #admin_virtual P, #admin_virtual FORM {
-	display: inline;
-	padding-right: 10px;
-	line-height: 30px;
-}
-
-#alias_domain_table .header, #alias_table .header, #mailbox_table .header, #overview_table .header, #log_table .header, #admin_table .header {
-	line-height: 20px;
-	background: #efefef;
-	color: black;
-}
-
-#alias_domain_table h3, #alias_table h3, #mailbox_table h3, #overview_table h3, #log_table h3, #admin_table h3 {
-	text-align: left;
-	font-size: 12px;
-	font-weight: bold;
-	padding-left: 20px;
-	line-height: 25px;
-	margin: 0;
-}
-
-#alias_domain_table .hilightoff, #alias_table .hilightoff, #mailbox_table .hilightoff, #overview_table .hilightoff, #log_table .hilightoff, #admin_table .hilighoff {
-	background: white;
-}
-
-#alias_domain_table .hilighton, #alias_table .hilighton, #mailbox_table .hilighton, #overview_table .hilighton, #log_table .hilighton, #admin_table .hilighton {
-	background: #eee; /*#D6FF85;*/ /*#ffdddd;*/
-}
-
-#alias_domain_table tr:hover, #alias_table tr:hover, #mailbox_table tr:hover, #overview_table tr:hover, #log_table tr:hover, #admin_table tr:hover {
-	background: #eee; /*#D6FF85;*/ /*#ffdddd;*/
-}
-
-th {
-	text-align: center;
-	padding:7px 0;
-	margin: 0 0 14px 0;
-	border-bottom: 1px solid #bbb;
-	color: #555555;
-}
-
-td {
-	padding:7px 7px;
-}
-
-td.label {
-	text-align:right;
-	margin-right:0px;
-}
-
-label {
-	padding-right:0;
-	font-weight:bold;
-	vertical-align:middle;
-}
-
-#alias_domain_table td, #alias_table td, #mailbox_table td, #overview_table td, #log_table td, #admin_table td {
-	text-align: left;
-}
-
-#footer {
-	width:975px;
-	margin: 20px auto;
-	border-top: 1px solid #bbbbbb;
-	background: #efefef;
-	color: #999999;
-	line-height: 20px;
-	text-align: left;
-	padding-left: 15px;
-	font-size: 9px;
-}
-
-#footer a {
-	text-decoration: none;
-	color: #999999;
-}
-
-#footer a:hover {
-	text-decoration: underline;
-	color: #777777;
-}
-
-div.setup {
-	width:700px;
-	margin-left:auto;
-	margin-right:auto;
-	text-align: left;
-}
-
-div.setup li {
-	padding-bottom:1em;
-}
-
-.searchresult {
-	background:lightgreen;
-}
-
-span.active { 
-	font-weight:bold; 
-}
-
-div.nav_bar {
-	text-align: left;
-}
-
-
-.quota {
-z-index:99;
-height:14px;
-position: absolute;
-}
-.quota_text {
-z-index:100;
-  text-align: center;
-  font-size: 10px;
-  color: #666;
-
-  cursor: default;
-  position: absolute;
-  width:120px;
-  height:14px;
-  margin-top:-14px;
-}
-.quota_bg { background-color: white; z-index:98; width:120px; height:14px;margin-top:-1px;margin-left:-1px;   border: 1px solid #999;}
-.quota_no_border { border:none; margin:0; }
-.quota_high { background: url(../images/quota-colors.png) repeat-x 0 -28px #f90509; }
-.quota_mid  { background: url(../images/quota-colors.png) repeat-x 0 -14px #e3e909; }
-.quota_low  { background: url(../images/quota-colors.png) repeat-x 0 0px #05f905; }
-.quota_text_high { color: white; }
-.quota_text_mid { color: #666; }
-.quota_text_low { color: #666; }
diff -pruN 3.0.2-2/debian/changelog 3.2-2/debian/changelog
--- 3.0.2-2/debian/changelog	2017-04-27 10:43:15.000000000 +0000
+++ 3.2-2/debian/changelog	2018-09-10 09:40:37.000000000 +0000
@@ -1,3 +1,18 @@
+postfixadmin (3.2-2) unstable; urgency=medium
+
+  * reupload with missing public folder included (closes: #908317)
+
+ -- Christoph Martin <martin@uni-mainz.de>  Mon, 10 Sep 2018 11:40:37 +0200
+
+postfixadmin (3.2-1) unstable; urgency=medium
+
+  [ Christoph Martin ]
+  * Move watch target to github
+  * Move Vcs-* to Salsa
+  * New upstream version 3.2
+
+ -- Christoph Martin <martin@uni-mainz.de>  Fri, 04 May 2018 11:39:57 +0200
+
 postfixadmin (3.0.2-2) unstable; urgency=medium
 
   * fix mysql connection problems (closes: #861260) see:
diff -pruN 3.0.2-2/debian/control 3.2-2/debian/control
--- 3.0.2-2/debian/control	2017-04-27 10:43:15.000000000 +0000
+++ 3.2-2/debian/control	2018-09-10 09:40:37.000000000 +0000
@@ -5,8 +5,8 @@ Maintainer: Norman Messtorff <normes@nor
 Uploaders: Gaudenz Steinlin <gaudenz@debian.org>, Christoph Martin <martin@uni-mainz.de>
 Build-Depends: debhelper (>= 7), po-debconf, dh-apache2
 Standards-Version: 3.9.6
-Vcs-Git: https://anonscm.debian.org/git/collab-maint/postfixadmin.git
-Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/postfixadmin.git
+Vcs-Browser: https://salsa.debian.org/debian/postfixadmin
+Vcs-Git: https://salsa.debian.org/debian/postfixadmin.git
 Homepage: http://postfixadmin.sourceforge.net
 
 Package: postfixadmin
diff -pruN 3.0.2-2/debian/patches/0001-db_credentials.patch 3.2-2/debian/patches/0001-db_credentials.patch
--- 3.0.2-2/debian/patches/0001-db_credentials.patch	2017-04-27 10:43:15.000000000 +0000
+++ 3.2-2/debian/patches/0001-db_credentials.patch	2018-09-10 09:40:37.000000000 +0000
@@ -8,9 +8,9 @@ Subject: db_credentials
 
 --- a/config.inc.php
 +++ b/config.inc.php
-@@ -15,6 +15,14 @@
-  * Contains configuration options.
-  */
+@@ -32,6 +32,14 @@
+ 
+ 
  
 +
 +// Debian: This loads the automatic generated DB credentials from 
@@ -23,7 +23,7 @@ Subject: db_credentials
  /*****************************************************************
   *  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
   * You have to set $CONF['configured'] = true; before the
-@@ -22,7 +30,7 @@
+@@ -39,7 +47,7 @@
   * Doing this implies you have changed this file as required.
   * i.e. configuring database etc; specifying setup.php password etc.
   */
@@ -32,7 +32,7 @@ Subject: db_credentials
  
  // In order to setup Postfixadmin, you MUST specify a hashed password here.
  // To create the hash, visit setup.php in a browser and type a password into the field,
-@@ -81,11 +89,11 @@
+@@ -98,11 +106,11 @@ function language_hook($PALANG, $languag
  // mysqli = MySQL 4.1+ or MariaDB
  // pgsql = PostgreSQL
  // sqlite = SQLite 3
@@ -46,8 +46,6 @@ Subject: db_credentials
 +$CONF['database_user'] = $dbuser;
 +$CONF['database_password'] = $dbpass;
 +$CONF['database_name'] = $dbname;
- // If you need to specify a different port for a MYSQL database connection, use e.g.
- //   $CONF['database_host'] = '172.30.33.66:3308';
- // If you need to specify a different port for POSTGRESQL database connection
-
-
+ 
+ // Database SSL Config
+ $CONF['database_use_ssl'] = false;
diff -pruN 3.0.2-2/debian/patches/0002-dovecotpw.patch 3.2-2/debian/patches/0002-dovecotpw.patch
--- 3.0.2-2/debian/patches/0002-dovecotpw.patch	2017-04-27 10:43:15.000000000 +0000
+++ 3.2-2/debian/patches/0002-dovecotpw.patch	2018-09-10 09:40:37.000000000 +0000
@@ -8,12 +8,12 @@ Last-Update: 2014-10-03
 This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
 --- a/config.inc.php
 +++ b/config.inc.php
-@@ -165,7 +165,7 @@ $CONF['authlib_default_flavor'] = 'md5ra
+@@ -200,7 +200,7 @@ $CONF['authlib_default_flavor'] = 'md5ra
  // for dovecot 1.x
  // $CONF['dovecotpw'] = "/usr/sbin/dovecotpw";
  // for dovecot 2.x (dovecot 2.0.0 - 2.0.7 is not supported!)
 -$CONF['dovecotpw'] = "/usr/sbin/doveadm pw";
 +$CONF['dovecotpw'] = "/usr/bin/doveadm pw";
- 
- // Password validation
- // New/changed passwords will be validated using all regular expressions in the array.
+ if(@file_exists('/usr/bin/doveadm')) { // @ to silence openbase_dir stuff; see https://github.com/postfixadmin/postfixadmin/issues/171
+     $CONF['dovecotpw'] = "/usr/bin/doveadm pw"; # debian
+ }
diff -pruN 3.0.2-2/debian/patches/0003-mysql-connection.patch 3.2-2/debian/patches/0003-mysql-connection.patch
--- 3.0.2-2/debian/patches/0003-mysql-connection.patch	2017-04-27 10:43:15.000000000 +0000
+++ 3.2-2/debian/patches/0003-mysql-connection.patch	2018-09-10 09:40:37.000000000 +0000
@@ -1,35 +0,0 @@
---- a/functions.inc.php
-+++ b/functions.inc.php
-@@ -1244,7 +1244,14 @@ function db_connect ($ignore_errors = 0)
-     global $DEBUG_TEXT;
-     if ($ignore_errors != 0) $DEBUG_TEXT = '';
-     $error_text = '';
--    $link = 0;
-+
-+    static $link;
-+    if (isset($link) && $link) {
-+        if ($ignore_errors) {
-+            return array($link, $error_text);
-+        }
-+        return $link;
-+    }    $link = 0;
- 
-     if ($CONF['database_type'] == "mysql") {
-         if (function_exists ("mysql_connect")) {
-@@ -1412,14 +1419,11 @@ function db_query ($query, $ignore_error
-     global $DEBUG_TEXT;
-     $result = "";
-     $number_rows = "";
--    static $link;
-+    $link = db_connect ();
-     $error_text = "";
-     if ($ignore_errors) $DEBUG_TEXT = "";
- 
--    # mysql and pgsql $link are resources, mysqli $link is an object
--    if (! (is_resource($link) || is_object($link) ) ) $link = db_connect ();
--
--    if ($CONF['database_type'] == "mysql") $result = @mysql_query ($query, $link) 
-+    if ($CONF['database_type'] == "mysql") $result = @mysql_query ($query, $link)
-         or $error_text = "Invalid query: " . mysql_error($link);
-     if ($CONF['database_type'] == "mysqli") $result = @mysqli_query ($link, $query) 
-         or $error_text = "Invalid query: " . mysqli_error($link);
diff -pruN 3.0.2-2/debian/patches/series 3.2-2/debian/patches/series
--- 3.0.2-2/debian/patches/series	2017-04-27 10:43:15.000000000 +0000
+++ 3.2-2/debian/patches/series	2018-09-10 09:40:37.000000000 +0000
@@ -1,3 +1,2 @@
 0001-db_credentials.patch
 0002-dovecotpw.patch
-0003-mysql-connection.patch
diff -pruN 3.0.2-2/debian/postfixadmin.dirs 3.2-2/debian/postfixadmin.dirs
--- 3.0.2-2/debian/postfixadmin.dirs	2017-04-27 10:43:15.000000000 +0000
+++ 3.2-2/debian/postfixadmin.dirs	2018-09-10 09:40:37.000000000 +0000
@@ -1,5 +1,5 @@
 usr/share/postfixadmin
-usr/share/postfixadmin/css
+#usr/share/postfixadmin/css
 usr/share/doc/postfixadmin
 etc/postfixadmin
 etc/apache2/conf-available
diff -pruN 3.0.2-2/debian/postfixadmin.install 3.2-2/debian/postfixadmin.install
--- 3.0.2-2/debian/postfixadmin.install	2017-04-27 10:43:15.000000000 +0000
+++ 3.2-2/debian/postfixadmin.install	2018-09-10 09:40:37.000000000 +0000
@@ -1,16 +1,10 @@
 *.php		usr/share/postfixadmin
-*.js		usr/share/postfixadmin
+public		usr/share/postfixadmin
 configs		usr/share/postfixadmin
-css		usr/share/postfixadmin
-images		usr/share/postfixadmin
 languages	usr/share/postfixadmin
 model		usr/share/postfixadmin
 scripts		usr/share/postfixadmin
-smarty		usr/share/postfixadmin
 templates	usr/share/postfixadmin
-templates_c	usr/share/postfixadmin
-users		usr/share/postfixadmin
-smarty		usr/share/postfixadmin
 configs     usr/share/postfixadmin
 debian/lighttpd/90-postfixadmin.conf	etc/lighttpd/conf-available
 debian/apache/postfixadmin.conf		etc/apache2/conf-available
diff -pruN 3.0.2-2/debian/watch 3.2-2/debian/watch
--- 3.0.2-2/debian/watch	2017-04-27 10:43:15.000000000 +0000
+++ 3.2-2/debian/watch	2018-09-10 09:40:37.000000000 +0000
@@ -1,2 +1,2 @@
 version=3
-http://sf.net/postfixadmin/postfixadmin-([\d\.]+)\.tar\.gz
+https://github.com/postfixadmin/postfixadmin/releases .*/archive/postfixadmin-(\d[\d.]*)\.tar\.gz
diff -pruN 3.0.2-2/delete.php 3.2-2/delete.php
--- 3.0.2-2/delete.php	2014-11-02 23:06:13.000000000 +0000
+++ 3.2-2/delete.php	1970-01-01 00:00:00.000000000 +0000
@@ -1,59 +0,0 @@
-<?php
-/** 
- * Postfix Admin 
- * 
- * LICENSE 
- * This source file is subject to the GPL license that is bundled with  
- * this package in the file LICENSE.TXT. 
- * 
- * Further details on the project are available at http://postfixadmin.sf.net 
- * 
- * @version $Id: delete.php 1733 2014-11-02 23:06:13Z christian_boltz $ 
- * @license GNU GPL v2 or later. 
- * 
- * File: delete.php
- * Used to delete admins, domains, mailboxes, aliases etc.
- *
- * Template File: none
- */
-
-require_once('common.php');
-
-if (safeget('token') != $_SESSION['PFA_token']) die('Invalid token!');
-
-$username = authentication_get_username(); # enforce login
-
-$id    = safeget('delete');
-$table = safeget('table');
-
-$handlerclass = ucfirst($table) . 'Handler';
-
-if ( !preg_match('/^[a-z]+$/', $table) || !file_exists("model/$handlerclass.php")) { # validate $table
-    die ("Invalid table name given!");
-}
-
-$is_admin = authentication_has_role('admin');
-
-$handler  = new $handlerclass(0, $username, $is_admin);
-$formconf = $handler->webformConfig();
-
-if ($is_admin) {
-    authentication_require_role($formconf['required_role']);
-} else {
-    if (empty($formconf['user_hardcoded_field'])) {
-        die($handlerclass . ' is not available for users');
-    }
-}
-
-if ($handler->init($id)) { # errors will be displayed as last step anyway, no need for duplicated code ;-)
-    $handler->delete();
-}
-
-flash_error($handler->errormsg);
-flash_info($handler->infomsg);
-
-header ("Location: " . $formconf['listview']);
-exit;
-
-/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */
-?>
diff -pruN 3.0.2-2/DOCUMENTS/DOVECOT.txt 3.2-2/DOCUMENTS/DOVECOT.txt
--- 3.0.2-2/DOCUMENTS/DOVECOT.txt	2014-01-21 15:38:11.000000000 +0000
+++ 3.2-2/DOCUMENTS/DOVECOT.txt	2018-05-02 20:37:27.000000000 +0000
@@ -29,7 +29,7 @@ changing to talk to a PostgreSQL or MySQ
 
 # BEGIN /etc/dovecot/dovecot.conf:
 # Change this to where your mail root is, this needs to match whatever structure postfix expects....
-
+# See also: https://wiki.dovecot.org/MailLocation - %d domain, %u full username, %n user part (%u with no domain)
 mail_location = maildir:/var/mail/vmail/%u/
 
 namespace inbox {
@@ -85,8 +85,6 @@ passdb {
 #        user = postfix
 #        group = postfix
 #    }
-#    user = postfix
-#    group = postfix
 #}
 
 # Needs to match Postfix virtual_uid_maps
@@ -132,7 +130,7 @@ user_query = SELECT maildir, 1001 AS uid
 
 
 # MYSQL :
-user_query = SELECT CONCAT('/var/vmail/mail/', maildir) AS home, 1001 AS uid, 1001 AS gid, 
+user_query = SELECT CONCAT('/var/mail/vmail/', maildir) AS home, 1001 AS uid, 1001 AS gid, 
 	CONCAT('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active='1'
 # PostgreSQL : (no Quota though) :
 # user_query = SELECT '/var/vmail/mail/' || maildir AS home, 1001 as uid, 1001 as gid FROM mailbox WHERE username = '%u' AND active = '1'
diff -pruN 3.0.2-2/DOCUMENTS/Postfix-Dovecot-Postgresql-Example.md 3.2-2/DOCUMENTS/Postfix-Dovecot-Postgresql-Example.md
--- 3.0.2-2/DOCUMENTS/Postfix-Dovecot-Postgresql-Example.md	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/DOCUMENTS/Postfix-Dovecot-Postgresql-Example.md	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,221 @@
+# Example configuration
+
+The below covers some default(ish) configuration things for using Postfix, Dovecot with PostgreSQL. 
+
+# Postfix
+
+Assumptions :
+
+ * Mail is delivered into /var/mail/vmail/foo@example.com/
+ * The user with id 8 is used for ownership of mail files. 
+ * PostgreSQL is running on the local server 
+ * Dovecot is running on the local server, and SASL is used to allow authenticated clients to mail out.
+
+
+## /etc/postfix/main.cf 
+
+The proxy: bits are optional, you may need to install an additional postfix package on your server to enable them.
+
+i.e. proxy:pgsql:/path/to/file is equivalent to pgsql:/path/to/file. Use of 'proxy:' may lead to a small performance boost.
+
+
+```
+relay_domains = $mydestination, proxy:pgsql:/etc/postfix/pgsql/relay_domains.cf
+virtual_alias_maps = proxy:pgsql:/etc/postfix/pgsql/virtual_alias_maps.cf
+virtual_mailbox_domains = proxy:pgsql:/etc/postfix/pgsql/virtual_domains_maps.cf
+virtual_mailbox_maps = proxy:pgsql:/etc/postfix/pgsql/virtual_mailbox_maps.cf
+virtual_mailbox_base = /var/mail/vmail
+virtual_mailbox_limit = 512000000
+virtual_minimum_uid = 8
+virtual_transport = virtual
+virtual_uid_maps = static:8
+virtual_gid_maps = static:8
+local_transport = virtual
+local_recipient_maps = $virtual_mailbox_maps
+```
+
+and for Postfix SASL support :
+
+```
+# SASL Auth for SMTP relaying
+smtpd_sasl_type = dovecot
+smtpd_sasl_path = private/auth
+smtpd_sasl_authenticated_header = yes
+smtpd_sasl_auth_enable = yes
+smtpd_sasl_security_options = noanonymous
+broken_sasl_auth_clients = yes
+```
+
+## /etc/postfix/pgsql/relay_domains.cf
+
+```
+user = postfix
+password = whatever
+hosts = localhost
+dbname = postfix
+query = SELECT domain FROM domain WHERE domain='%s' and backupmx = true
+```
+
+## /etc/postfix/pgsql/virtual_alias_maps.cf
+
+```
+user = postfix
+password = whatever
+hosts = localhost
+dbname = postfix
+query = SELECT goto FROM alias WHERE address='%s' AND active = true
+```
+
+## /etc/postfix/pgsql/virtual_domains_maps.cf
+
+```
+user = postfix
+password = whatever
+hosts = localhost
+dbname = postfix
+#query = SELECT domain FROM domain WHERE domain='%s'
+#optional query to use when relaying for backup MX
+query = SELECT domain FROM domain WHERE domain='%s' and backupmx = false and active = true
+```
+
+## /etc/postfix/pgsql/virtual_mailbox_limits.cf
+
+```
+# Used for quota
+user = postfix
+password = whatever
+hosts = localhost
+dbname = postfix
+query = SELECT quota FROM mailbox WHERE username='%s'
+```
+
+## /etc/postfix/pgsql/virtual_mailbox_maps.cf
+
+```
+user = postfix
+password = whatever
+hosts = localhost
+dbname = postfix
+query = SELECT maildir FROM mailbox WHERE username='%s' AND active = true
+```
+
+
+# Dovecot
+
+(This is from version 2.2.27, Debian Stretch)
+
+
+## /etc/dovecot/dovecot.conf 
+```
+mail_location = maildir:/var/mail/vmail/%u/
+
+namespace inbox {
+  type = private
+  inbox = yes
+  location =
+  mailbox Drafts {
+    special_use = \Drafts
+  }
+  mailbox Junk {
+    special_use = \Junk
+  }
+  mailbox Sent {
+    special_use = \Sent
+  }
+  mailbox "Sent Messages" {
+    special_use = \Sent
+  }
+  mailbox Trash {
+    special_use = \Trash
+  }
+  prefix =
+}
+
+protocols = "imap pop3"
+
+# Requires certificates ...
+#ssl = yes
+#ssl_cert = </etc/dovecot/private/something.pem
+#ssl_key =  </etc/letsencrypt/certs/something.key
+
+login_greeting = My Mail Server
+# http://wiki2.dovecot.org/Authentication/Mechanisms
+# login is for outlook express ...
+auth_mechanisms = plain login
+#auth_debug = yes
+#auth_debug_passwords=yes
+
+# Postfix - Sasl auth support.
+service auth {
+  # Postfix smtp-auth
+  unix_listener /var/spool/postfix/private/auth {
+    mode = 0660
+    user = postfix
+    group = postfix
+  }
+  # Auth process is run as this user.
+  user = postfix
+  group = postfix
+}
+
+service imap {
+    executable = imap
+}
+
+userdb {
+    driver = sql
+    args = /etc/dovecot/dovecot-sql.conf
+}
+
+passdb {
+    driver = sql
+    args = /etc/dovecot/dovecot-sql.conf
+}
+
+# Needs to match Postfix virtual_uid_maps
+first_valid_uid = 8
+
+# disallow or allow plaintext auth.
+disable_plaintext_auth = yes
+
+mail_plugins = $mail_plugins zlib
+
+plugin {
+    zlib_save_level = 6
+    zlib_save = gz
+}
+protocol imap {
+    mail_plugins = $mail_plugins imap_zlib
+}
+
+mail_max_userip_connections = 50
+log_path = /var/log/dovecot.log
+
+```
+
+
+## /etc/dovecot/dovecot-sql.conf
+
+Ideally dovecot has a different read only database user.
+
+
+```
+connect = host=localhost dbname=postfix user=dovecot password=whatever
+
+driver = pgsql
+
+# Default password scheme - change to match your Postfixadmin setting.
+# depends on your $CONF['encrypt'] setting:
+# md5crypt  -> MD5-CRYPT
+# md5       -> PLAIN-MD5
+# cleartext -> PLAIN
+default_pass_scheme = MD5-CRYPT
+
+# Query to retrieve password. user can be used to retrieve username in other
+# formats also.
+
+password_query = SELECT username AS user,password FROM mailbox WHERE username = '%u' AND active='1'
+
+# Query to retrieve user information, note uid matches dovecot.conf AND Postfix virtual_uid_maps parameter.
+user_query = SELECT '/var/vmail/mail/' || maildir AS home, 8 as uid, 8 as gid FROM mailbox WHERE username = '%u' AND active = '1'
+```
diff -pruN 3.0.2-2/DOCUMENTS/UPGRADE.txt 3.2-2/DOCUMENTS/UPGRADE.txt
--- 3.0.2-2/DOCUMENTS/UPGRADE.txt	2011-01-08 19:53:37.000000000 +0000
+++ 3.2-2/DOCUMENTS/UPGRADE.txt	2018-05-02 20:37:27.000000000 +0000
@@ -33,10 +33,11 @@ When you install from a previous version
 first. There are a lot of changes in the database structure since Postfix Admin
 1.5.4.
 
-  $ mysqldump -a -u root -p > /tmp/postfixadmin-backup.sql
+  $ mysqldump -u root -p postfixdb > /tmp/postfixadmin-backup.sql
 or
-  $ pg_dump -ad -u postfix postfix > /tmp/postfixadmin-backup.sql
+  $ pg_dump -ad -u postfix postfixdb > /tmp/postfixadmin-backup.sql
 
+(Replace postfixdb with your Postfixadmin database's name)
 
 2. Unarchive new Postfix Admin
 ------------------------------
@@ -53,28 +54,35 @@ to have change the permissions for Postf
 
   $ cd /usr/local/www/postfixadmin
   $ find -type f -print0 | xargs -0 chmod 640
-  $ find -type f -print0 | xargs -0 chown root:www
+  $ find -type f -print0 | xargs -0 chown root:www-data
 
-(the last command assumes your Apache is running with group "www")
+(the last command assumes your Apache is running with group "www-data")
 
-Since version 2.4 we use smarty templates. That means the templates_c directory
+Since version 3.0 we use smarty templates. That means the templates_c directory
 needs to be writeable for your webserver.
 
-  $ chown -R www-data templates_c/
+  $ cd /usr/local/www/postfixadmin
+  $ mkdir templates_c && chmod 750 templates_c && chown -R www-data templates_c
 
 (if your Apache runs as user "www-data")
 
+If you have SELinux enabled, also run (adust the path to match your setup)
+
+  $ sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/utils/pfadmin/public/templates_c(/.*)?"
+  $ sudo restorecon -Rv /var/www/utils/pfadmin/
+
 
 4. Configure
 ------------
+
 Check the config.inc.php file. There you can specify settings that are
 relevant to your setup.
 
 Comparing config.inc.php with your previous using "diff" might save you some
 time.
 
-You can use a config.local.php file to contain your local settings. These will override any 
-defined in config.inc.php - and save some time when upgrading to a new version of PostfixAdmin ;-)
+You can use a config.local.php file to contain your local settings. 
+These will override any defined in config.inc.php - and save some time when upgrading to a new version of PostfixAdmin ;-)
 
 5. Run setup.php
 ----------------------------------------
diff -pruN 3.0.2-2/editactive.php 3.2-2/editactive.php
--- 3.0.2-2/editactive.php	2015-04-06 23:09:58.000000000 +0000
+++ 3.2-2/editactive.php	1970-01-01 00:00:00.000000000 +0000
@@ -1,59 +0,0 @@
-<?php
-/**
- * Postfix Admin
- *
- * LICENSE
- * This source file is subject to the GPL license that is bundled with
- * this package in the file LICENSE.TXT
- *
- * Further details on the project are available at http://postfixadmin.sf.net
- *
- * @version $Id: editactive.php 1782 2015-04-06 23:09:58Z christian_boltz $
- * @license GNU GPL v2 or later.
- *
- * File: delete.php
- * Used to delete admins, domains, mailboxes, aliases etc.
- *
- * Template File: none
- */
-
-require_once('common.php');
-
-if (safeget('token') != $_SESSION['PFA_token']) die('Invalid token!');
-
-$username = authentication_get_username(); # enforce login
-
-$id     = safeget('id');
-$table  = safeget('table');
-$active = safeget('active');
-
-$handlerclass = ucfirst($table) . 'Handler';
-
-if ( !preg_match('/^[a-z]+$/', $table) || !file_exists("model/$handlerclass.php")) { # validate $table
-    die ("Invalid table name given!");
-}
-
-$handler = new $handlerclass(0, $username);
-
-$formconf = $handler->webformConfig();
-
-authentication_require_role($formconf['required_role']);
-
-if ($handler->init($id)) { # errors will be displayed as last step anyway, no need for duplicated code ;-)
-    if ($active != '0' && $active != '1') {
-        die(Config::Lang('invalid_parameter'));
-    }
-
-    if ( $handler->set(array('active' => $active)) ) {
-        $handler->store();
-    }
-}
-
-flash_error($handler->errormsg);
-flash_info($handler->infomsg);
-
-header ("Location: " . $formconf['listview']);
-exit;
-
-/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */
-?>
diff -pruN 3.0.2-2/edit.php 3.2-2/edit.php
--- 3.0.2-2/edit.php	2016-05-20 20:42:04.000000000 +0000
+++ 3.2-2/edit.php	1970-01-01 00:00:00.000000000 +0000
@@ -1,229 +0,0 @@
-<?php
-/** 
- * Postfix Admin 
- * 
- * LICENSE 
- * This source file is subject to the GPL license that is bundled with  
- * this package in the file LICENSE.TXT. 
- * 
- * Further details on the project are available at http://postfixadmin.sf.net 
- * 
- * @version $Id: edit.php 1842 2016-05-20 20:42:04Z christian_boltz $ 
- * @license GNU GPL v2 or later. 
- * 
- * File: edit.php
- * This file implements the handling of edit forms.
- * The form layout is retrieved from the *Handler classes, which also do
- * the actual work of verifying and storing the values.
- *
- * GET parameters:
- *      table   what to edit (*Handler)
- *      edit    item to edit (if net given: a new item will be created)
- *      additional parameters will be accepted if specified in *Handler->webformConfig()[prefill] when creating a new item
- */
-
-require_once('common.php');
-
-$username = authentication_get_username(); # enforce login
-
-$table = safepost('table', safeget('table'));
-$handlerclass = ucfirst($table) . 'Handler';
-
-if ( !preg_match('/^[a-z]+$/', $table) || !file_exists("model/$handlerclass.php")) { # validate $table
-    die ("Invalid table name given!");
-}
-
-$error = 0;
-
-$edit = safepost('edit', safeget('edit'));
-$new  = 0;
-if ($edit == "") $new = 1;
-
-$is_admin = authentication_has_role('admin');
-
-$handler  = new $handlerclass($new, $username, $is_admin);
-$formconf = $handler->webformConfig();
-
-if ($is_admin) {
-    authentication_require_role($formconf['required_role']);
-} else {
-    if (empty($formconf['user_hardcoded_field'])) {
-        die($handlerclass . ' is not available for users');
-    }
-}
-
-if ($new == 0 || $formconf['early_init']) {
-    if (!$handler->init($edit)) {
-        if (count($handler->errormsg) == 0) {
-            # should never happen and indicates a bug in $handler->init()
-            flash_error($handlerclass . "->init() failed, but didn't set any error message");
-        }
-        flash_error($handler->errormsg);
-        header ("Location: " . $formconf['listview']);
-        exit;
-    }
-}
-
-$form_fields = $handler->getStruct();
-$id_field    = $handler->getId_field();
-
-if ($_SERVER['REQUEST_METHOD'] == "GET") {
-    if ($new) { # new - prefill fields from URL parameters if allowed in $formconf['prefill']
-        if ( isset($formconf['prefill']) ) {
-            foreach ($formconf['prefill'] as $field) {
-                $prefillvalue = safeget($field, safesession("prefill:$table:$field"));
-                if ($prefillvalue != '') {
-                    $form_fields[$field]['default'] = $prefillvalue;
-                    $handler->prefill($field, $prefillvalue);
-                }
-            }
-        }
-        $form_fields = $handler->getStruct(); # refresh $form_fields - a prefill field might have changed something
-    } else { # edit mode - read values from database
-        if (!$handler->view()) {
-            flash_error($handler->errormsg);
-            header ("Location: " . $formconf['listview']);
-            exit;
-        } else {
-            $values = $handler->result;
-            $values[$id_field] = $edit;
-        }
-    }
-}
-
-
-if ($_SERVER['REQUEST_METHOD'] == "POST") {
-    if (safepost('token') != $_SESSION['PFA_token']) die('Invalid token!');
-    $inp_values = safepost('value', array() );
-
-    foreach($form_fields as $key => $field) {
-        if ($field['editable'] && $field['display_in_form']) {
-            if (!isset($inp_values[$key])) {
-                $inp_values[$key] = ''; # newer PHP versions don't include empty fields in $_POST (noticed with PHP 5.6.6)
-            }
-
-            if($field['type'] == 'bool' && $inp_values[$key] == '') {
-                $values[$key] = 0; # isset() for unchecked checkboxes is always false
-            } elseif($field['type'] == 'txtl') {
-                $values[$key] = $inp_values[$key];
-                $values[$key] = preg_replace ('/\\\r\\\n/', ',', $values[$key]);
-                $values[$key] = preg_replace ('/\r\n/',     ',', $values[$key]);
-                $values[$key] = preg_replace ('/,[\s]+/i',  ',', $values[$key]); 
-                $values[$key] = preg_replace ('/[\s]+,/i',  ',', $values[$key]); 
-                $values[$key] = preg_replace ('/,,*/',      ',', $values[$key]);
-                $values[$key] = preg_replace ('/,*$|^,*/',  '',  $values[$key]);
-                if ($values[$key] == '') {
-                    $values[$key] = array();
-                } else {
-                    $values[$key] = explode(",", $values[$key]);
-                }
-            } else {
-                $values[$key] = $inp_values[$key];
-            }
-        }
-    }
-
-    if (isset($formconf['hardcoded_edit']) && $formconf['hardcoded_edit']) {
-        $values[$id_field] = $form_fields[$id_field]['default'];
-    } elseif ($new == 0) {
-        $values[$id_field] = $edit;
-    }
-
-    if ($new && ($form_fields[$id_field]['display_in_form'] == 0)) {
-        if ($form_fields[$id_field]['editable'] == 1) { # address split to localpart and domain?
-            $values[$id_field] = $handler->mergeId($values);
-        } else { # probably auto_increment
-            $values[$id_field] = '';
-        }
-    }
-
-    if (!$handler->init($values[$id_field])) {
-        $error = 1;
-        $errormsg = $handler->errormsg;
-    }
-
-    if (!$handler->set($values)) {
-        $error = 1;
-        $errormsg = $handler->errormsg;
-    }
-
-    $form_fields = $handler->getStruct(); # refresh $form_fields - set() might have changed something
-
-    if ($error != 1) {
-        if (!$handler->store()) {
-            $errormsg = $handler->errormsg;
-        } else {
-            flash_info($handler->infomsg);
-
-            if (count($handler->errormsg)) { # might happen if domain_postcreation fails
-                flash_error($handler->errormsg);
-            }
-
-            # remember prefill values for next usage of the form
-            if ( isset($formconf['prefill']) ) {
-                foreach ($formconf['prefill'] as $field) {
-                    if (isset($values[$field])) {
-                        $_SESSION["prefill:$table:$field"] = $values[$field];
-                    }
-                }
-            }
-
-            if ($new == 0) {
-                header ("Location: " . $formconf['listview']);
-                exit;
-            } else {
-                header("Location: edit.php?table=$table");
-                exit;
-            }
-        }
-    }
-}
-
-if ($error != 1 && $new) { # no error and not in edit mode - reset fields to default for new item
-    $values = array();
-    foreach (array_keys($form_fields) as $key) {
-        $values[$key] = $form_fields[$key]['default'];
-    }
-}
-
-$errormsg = $handler->errormsg;
-$fielderror = array();
-
-foreach($form_fields as $key => $field) {
-  if($form_fields[$key]['display_in_form']) {
-
-    if (isset($errormsg[$key])) {
-        $fielderror[$key] = $errormsg[$key];
-        unset ($errormsg[$key]);
-    } else {
-        $fielderror[$key] = '';
-    }
-
-    if (isset($values[$key])) {
-        $smarty->assign ("value_$key", $values[$key]);
-    } else {
-        $smarty->assign ("value_$key", $form_fields[$key]['default']);
-    }
-  }
-}
-
-if (count($errormsg)) flash_error($errormsg); # display the remaining error messages (not related to a field) with flash_error
-
-if ($new) {
-    $smarty->assign ('mode', 'create');
-    $smarty->assign('formtitle', Config::lang($formconf['formtitle_create']));
-    $smarty->assign('submitbutton', Config::lang($formconf['create_button']));
-} else {
-    $smarty->assign ('mode', 'edit');
-    $smarty->assign('formtitle', Config::lang($formconf['formtitle_edit']));
-    $smarty->assign('submitbutton', Config::lang('save'));
-}
-
-$smarty->assign ('struct', $form_fields);
-$smarty->assign ('fielderror', $fielderror);
-$smarty->assign ('table', $table);
-$smarty->assign ('smarty_template', 'editform');
-$smarty->display ('index.tpl');
-
-/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */
-?>
diff -pruN 3.0.2-2/functions.inc.php 3.2-2/functions.inc.php
--- 3.0.2-2/functions.inc.php	2017-02-08 20:45:26.000000000 +0000
+++ 3.2-2/functions.inc.php	2018-05-02 20:37:27.000000000 +0000
@@ -1,22 +1,22 @@
 <?php
-/** 
- * Postfix Admin 
- * 
- * LICENSE 
- * This source file is subject to the GPL license that is bundled with  
- * this package in the file LICENSE.TXT. 
- * 
- * Further details on the project are available at http://postfixadmin.sf.net 
- * 
- * @version $Id: functions.inc.php 1894 2017-02-08 20:45:26Z christian_boltz $ 
- * @license GNU GPL v2 or later. 
- * 
+/**
+ * Postfix Admin
+ *
+ * LICENSE
+ * This source file is subject to the GPL license that is bundled with
+ * this package in the file LICENSE.TXT.
+ *
+ * Further details on the project are available at http://postfixadmin.sf.net
+ *
+ * @version $Id$
+ * @license GNU GPL v2 or later.
+ *
  * File: functions.inc.php
  * Contains re-usable code.
  */
 
-$version = '3.0.2';
-$min_db_version = 1835;  # update (at least) before a release with the latest function numbrer in upgrade.php
+$version = '3.2';
+$min_db_version = 1840;  # update (at least) before a release with the latest function numbrer in upgrade.php
 
 /**
  * check_session
@@ -34,7 +34,7 @@ function authentication_get_username() {
     }
 
     if (!isset($_SESSION['sessid'])) {
-        header ("Location: login.php");
+        header("Location: login.php");
         exit(0);
     }
     $SESSID_USERNAME = $_SESSION['sessid']['username'];
@@ -42,13 +42,13 @@ function authentication_get_username() {
 }
 
 /**
- * Returns the type of user - either 'user' or 'admin' 
+ * Returns the type of user - either 'user' or 'admin'
  * Returns false if neither (E.g. if not logged in)
  * @return String admin or user or (boolean) false.
  */
 function authentication_get_usertype() {
-    if(isset($_SESSION['sessid'])) {
-        if(isset($_SESSION['sessid']['type'])) {
+    if (isset($_SESSION['sessid'])) {
+        if (isset($_SESSION['sessid']['type'])) {
             return $_SESSION['sessid']['type'];
         }
     }
@@ -62,9 +62,9 @@ function authentication_get_usertype() {
  * Note, user < admin < global-admin
  */
 function authentication_has_role($role) {
-    if(isset($_SESSION['sessid'])) {
-        if(isset($_SESSION['sessid']['roles'])) {
-            if(in_array($role, $_SESSION['sessid']['roles'])) {
+    if (isset($_SESSION['sessid'])) {
+        if (isset($_SESSION['sessid']['roles'])) {
+            if (in_array($role, $_SESSION['sessid']['roles'])) {
                 return true;
             }
         }
@@ -73,7 +73,7 @@ function authentication_has_role($role)
 }
 
 /**
- * Used to enforce that $user has a particular role when 
+ * Used to enforce that $user has a particular role when
  * viewing a page.
  * If they are lacking a role, redirect them to login.php
  *
@@ -81,18 +81,35 @@ function authentication_has_role($role)
  */
 function authentication_require_role($role) {
     // redirect to appropriate page?
-    if(authentication_has_role($role)) {
-        return True;
+    if (authentication_has_role($role)) {
+        return true;
     }
 
     header("Location: login.php");
     exit(0);
 }
 
+/**
+ * Initialize a user or admin session
+ *
+ * @param String $username the user or admin name
+ * @param boolean $is_admin true if the user is an admin, false otherwise
+ * @return boolean true on success
+ */
+function init_session($username, $is_admin = false) {
+    $status = session_regenerate_id(true);
+    $_SESSION['sessid'] = array();
+    $_SESSION['sessid']['roles'] = array();
+    $_SESSION['sessid']['roles'][] = $is_admin ? 'admin' : 'user';
+    $_SESSION['sessid']['username'] = $username;
+    $_SESSION['PFA_token'] = md5(uniqid(rand(), true));
+
+    return $status;
+}
 
 /**
  * Add an error message for display on the next page that is rendered.
- * @param String/Array message(s) to show. 
+ * @param String/Array message(s) to show.
  *
  * Stores string in session. Flushed through header template.
  * @see _flash_string()
@@ -103,7 +120,7 @@ function flash_error($string) {
 
 /**
  * Used to display an info message on successful update.
- * @param String/Array message(s) to show. 
+ * @param String/Array message(s) to show.
  * Stores data in session.
  * @see _flash_string()
  */
@@ -121,10 +138,10 @@ function _flash_string($type, $string) {
         return;
     }
 
-    if(!isset($_SESSION['flash'])) {
+    if (!isset($_SESSION['flash'])) {
         $_SESSION['flash'] = array();
     }
-    if(!isset($_SESSION['flash'][$type])) {
+    if (!isset($_SESSION['flash'][$type])) {
         $_SESSION['flash'][$type] = array();
     }
     $_SESSION['flash'][$type][] = $string;
@@ -136,25 +153,25 @@ function _flash_string($type, $string) {
 // Call: check_language
 // Parameter: $use_post - set to 0 if $_POST should NOT be read
 //
-function check_language ($use_post = 1) {
+function check_language($use_post = 1) {
     global $supported_languages; # from languages/languages.php
 
     $lang = Config::read('default_language');
 
-    if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
-        $lang_array = preg_split ('/(\s*,\s*)/', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
+    if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+        $lang_array = preg_split('/(\s*,\s*)/', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
         if (safecookie('lang')) {
             array_unshift($lang_array, safecookie('lang')); # prefer language from cookie
         }
-        if ( $use_post && safepost('lang')) {
+        if ($use_post && safepost('lang')) {
             array_unshift($lang_array, safepost('lang')); # but prefer $_POST['lang'] even more
         }
 
-        for($i = 0; $i < count($lang_array); $i++) {
+        for ($i = 0; $i < count($lang_array); $i++) {
             $lang_next = $lang_array[$i];
             $lang_next = strtolower(trim($lang_next));
             $lang_next = preg_replace('/;.*$/', '', $lang_next); # remove things like ";q=0.8"
-            if(array_key_exists($lang_next, $supported_languages)) {
+            if (array_key_exists($lang_next, $supported_languages)) {
                 $lang = $lang_next;
                 break;
             }
@@ -175,7 +192,7 @@ function language_selector() {
 
     $selector = '<select name="lang" xml:lang="en" dir="ltr">';
 
-    foreach($supported_languages as $lang => $lang_name) {
+    foreach ($supported_languages as $lang => $lang_name) {
         if ($lang == $current_lang) {
             $selected = ' selected="selected"';
         } else {
@@ -191,15 +208,15 @@ function language_selector() {
 
 
 /**
- * Checks if a domain is valid 
+ * Checks if a domain is valid
  * @param string $domain
  * @return empty string if the domain is valid, otherwise string with the errormessage
  *
  * TODO: make check_domain able to handle as example .local domains
  * TODO: skip DNS check if the domain exists in PostfixAdmin?
  */
-function check_domain ($domain) {
-    if (!preg_match ('/^([-0-9A-Z]+\.)+' . '([-0-9A-Z]){2,13}$/i', ($domain))) {
+function check_domain($domain) {
+    if (!preg_match('/^([-0-9A-Z]+\.)+' . '([-0-9A-Z]){2,13}$/i', ($domain))) {
         return sprintf(Config::lang('pInvalidDomainRegex'), htmlentities($domain));
     }
 
@@ -207,15 +224,15 @@ function check_domain ($domain) {
 
         // Look for an AAAA, A, or MX record for the domain
 
-        if(function_exists('checkdnsrr')) {
+        if (function_exists('checkdnsrr')) {
             $start = microtime(true); # check for slow nameservers, part 1
 
             // AAAA (IPv6) is only available in PHP v. >= 5
-            if (version_compare(phpversion(), "5.0.0", ">=") && checkdnsrr($domain,'AAAA')) {
+            if (version_compare(phpversion(), "5.0.0", ">=") && checkdnsrr($domain, 'AAAA')) {
                 $retval = '';
-            } elseif (checkdnsrr($domain,'A')) {
+            } elseif (checkdnsrr($domain, 'A')) {
                 $retval = '';
-            } elseif (checkdnsrr($domain,'MX')) {
+            } elseif (checkdnsrr($domain, 'MX')) {
                 $retval = '';
             } else {
                 $retval = sprintf(Config::lang('pInvalidDomainDNS'), htmlentities($domain));
@@ -244,25 +261,31 @@ function check_domain ($domain) {
  * @return empty string if it's a valid email address, otherwise string with the errormessage
  * TODO: make check_email able to handle already added domains
  */
-function check_email ($email) {
+function check_email($email) {
     $ce_email=$email;
 
     //strip the vacation domain out if we are using it
     //and change from blah#foo.com@autoreply.foo.com to blah@foo.com
-    if (Config::bool('vacation')) { 
+    if (Config::bool('vacation')) {
         $vacation_domain = Config::read('vacation_domain');
         $ce_email = preg_replace("/@$vacation_domain\$/", '', $ce_email);
         $ce_email = preg_replace("/#/", '@', $ce_email);
     }
 
     // Perform non-domain-part sanity checks
-    if (!preg_match ('/^[-!#$%&\'*+\\.\/0-9=?A-Z^_{|}~]+' . '@' . '[^@]+$/i', $ce_email)) {
+    if (!preg_match('/^[-!#$%&\'*+\\.\/0-9=?A-Z^_{|}~]+' . '@' . '[^@]+$/i', $ce_email)) {
         return Config::lang_f('pInvalidMailRegex', $email);
     }
 
+    if (function_exists('filter_var')) {
+        $check = filter_var($email, FILTER_VALIDATE_EMAIL);
+        if (!$check) {
+            return Config::lang_f('pInvalidMailRegex', $email);
+        }
+    }
     // Determine domain name
     $matches=array();
-    if (!preg_match('|@(.+)$|',$ce_email,$matches)) {
+    if (!preg_match('|@(.+)$|', $ce_email, $matches)) {
         return Config::lang_f('pInvalidMailRegex', $email);
     }
     $domain=$matches[1];
@@ -277,26 +300,26 @@ function check_email ($email) {
  * Clean a string, escaping any meta characters that could be
  * used to disrupt an SQL string. i.e. "'" => "\'" etc.
  *
- * @param String (or Array) 
- * @return String (or Array) of cleaned data, suitable for use within an SQL
- *    statement.
+ * @param string|array parameters to escape
+ * @return string|array of cleaned data, suitable for use within an SQL statement.
  */
-function escape_string ($string) {
+function escape_string($string) {
     global $CONF;
     // if the string is actually an array, do a recursive cleaning.
     // Note, the array keys are not cleaned.
-    if(is_array($string)) {
+    if (is_array($string)) {
         $clean = array();
-        foreach(array_keys($string) as $row) {
-            $clean[$row] = escape_string($string[$row]);  
+        foreach ($string as $k => $v) {
+            $clean[$k] = escape_string($v);
         }
         return $clean;
     }
-    if (get_magic_quotes_gpc ()) {
+    if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
         $string = stripslashes($string);
     }
     if (!is_numeric($string)) {
         $link = db_connect();
+
         if ($CONF['database_type'] == "mysql") {
             $escaped_string = mysql_real_escape_string($string, $link);
         }
@@ -328,66 +351,75 @@ function escape_string ($string) {
  *       - or -
  *  $param = safeget('param', 'default')
  *
- *  @param String parameter name.
- *  @param String (optional) - default value if key is not set.
- *  @return String 
+ *  @param string $param parameter name.
+ *  @param string $default (optional) - default value if key is not set.
+ *  @return string
  */
-function safeget ($param, $default="") {
+function safeget($param, $default="") {
     $retval=$default;
-    if (isset($_GET[$param])) $retval=$_GET[$param];
+    if (isset($_GET[$param])) {
+        $retval=$_GET[$param];
+    }
     return $retval;
 }
 
 /**
- * safepost - similar to safeget()
+ * safepost - similar to safeget() but for $_POST
  * @see safeget()
- * @param String parameter name
- * @param String (optional) default value (defaults to "")
- * @return String - value in $_POST[$param] or $default
- * same as safeget, but for $_POST
+ * @param string $param parameter name
+ * @param string $default (optional) default value (defaults to "")
+ * @return string - value in $_POST[$param] or $default
  */
-function safepost ($param, $default="") {
+function safepost($param, $default="") {
     $retval=$default;
-    if (isset($_POST[$param])) $retval=$_POST[$param];
+    if (isset($_POST[$param])) {
+        $retval=$_POST[$param];
+    }
     return $retval;
 }
 
 /**
  * safeserver
  * @see safeget()
- * @param String $param 
- * @param String $default (optional)
- * @return String value from $_SERVER[$param] or $default
+ * @param string $param
+ * @param string $default (optional)
+ * @return string value from $_SERVER[$param] or $default
  */
-function safeserver ($param, $default="") {
+function safeserver($param, $default="") {
     $retval=$default;
-    if (isset($_SERVER[$param])) $retval=$_SERVER[$param];
+    if (isset($_SERVER[$param])) {
+        $retval=$_SERVER[$param];
+    }
     return $retval;
 }
 
 /**
  * safecookie
  * @see safeget()
- * @param String $param 
- * @param String $default (optional)
- * @return String value from $_COOKIE[$param] or $default
+ * @param string $param
+ * @param string $default (optional)
+ * @return string value from $_COOKIE[$param] or $default
  */
-function safecookie ($param, $default="") {
+function safecookie($param, $default="") {
     $retval=$default;
-    if (isset($_COOKIE[$param])) $retval=$_COOKIE[$param];
+    if (isset($_COOKIE[$param])) {
+        $retval=$_COOKIE[$param];
+    }
     return $retval;
 }
 
 /**
  * safesession
  * @see safeget()
- * @param String $param 
- * @param String $default (optional)
- * @return String value from $_SESSION[$param] or $default
+ * @param string $param
+ * @param string $default (optional)
+ * @return string value from $_SESSION[$param] or $default
  */
-function safesession ($param, $default="") {
+function safesession($param, $default="") {
     $retval=$default;
-    if (isset($_SESSION[$param])) $retval=$_SESSION[$param];
+    if (isset($_SESSION[$param])) {
+        $retval=$_SESSION[$param];
+    }
     return $retval;
 }
 
@@ -397,18 +429,22 @@ function safesession ($param, $default="
  * @param int $allow_editing
  * @param int $display_in_form
  * @param int display_in_list
- * @param String $type
- * @param String PALANG_label
- * @param String PALANG_desc
+ * @param string $type
+ * @param string PALANG_label
+ * @param string PALANG_desc
  * @param any optional $default
- * @param array optional $options
- * @param int or $not_in_db - if array, can contain the remaining parameters as associated array
+ * @param array $options optional options
+ * @param int or $not_in_db - if array, can contain the remaining parameters as associated array. Otherwise counts as $not_in_db
  * @param ...
  * @return array for $struct
  */
 function pacol($allow_editing, $display_in_form, $display_in_list, $type, $PALANG_label, $PALANG_desc, $default = "", $options = array(), $multiopt=0, $dont_write_to_db=0, $select="", $extrafrom="", $linkto="") {
-    if ($PALANG_label != '') $PALANG_label = Config::lang($PALANG_label);
-    if ($PALANG_desc  != '') $PALANG_desc  = Config::lang($PALANG_desc );
+    if ($PALANG_label != '') {
+        $PALANG_label = Config::lang($PALANG_label);
+    }
+    if ($PALANG_desc  != '') {
+        $PALANG_desc  = Config::lang($PALANG_desc);
+    }
 
     if (is_array($multiopt)) { # remaining parameters provided in named array
         $not_in_db = 0; # keep default value
@@ -441,8 +477,7 @@ function pacol($allow_editing, $display_
 // Action: Get all the properties of a domain.
 // Call: get_domain_properties (string domain)
 //
-function get_domain_properties ($domain) {
-
+function get_domain_properties($domain) {
     $handler = new DomainHandler();
     if (!$handler->init($domain)) {
         die("Error: " . join("\n", $handler->errormsg));
@@ -464,7 +499,7 @@ function get_domain_properties ($domain)
  *
  *  @param String idxfield - database field name to use as title
  *  @param String query - core part of the query (starting at "FROM")
- *  @return String 
+ *  @return String
  */
 function create_page_browser($idxfield, $querypart) {
     global $CONF;
@@ -478,12 +513,12 @@ function create_page_browser($idxfield,
 
     # get number of rows
     $query = "SELECT count(*) as counter FROM (SELECT $idxfield $querypart) AS tmp";
-    $result = db_query ($query);
+    $result = db_query($query);
     if ($result['rows'] > 0) {
-        $row = db_array ($result['result']);
+        $row = db_assoc($result['result']);
         $count_results = $row['counter'] -1; # we start counting at 0, not 1
     }
-#    echo "<p>rows: " . ($count_results +1) . " --- $query";
+    #    echo "<p>rows: " . ($count_results +1) . " --- $query";
 
     if ($count_results < $page_size) {
         return array(); # only one page - no pagebrowser required
@@ -502,16 +537,16 @@ function create_page_browser($idxfield,
     $page_size_zerobase = $page_size - 1;
     $query = "
         SELECT * FROM (
-            SELECT $idxfield AS label, @row := @row + 1 AS row $querypart 
+            SELECT $idxfield AS label, @row := @row + 1 AS row $querypart
         ) idx WHERE MOD(idx.row, $page_size) IN (0,$page_size_zerobase) OR idx.row = $count_results
-    "; 
+    ";
 
     if (db_pgsql()) {
         $query = "
             SELECT * FROM (
-                SELECT $idxfield AS label, nextval('rowcount') AS row $querypart 
+                SELECT $idxfield AS label, nextval('rowcount') AS row $querypart
             ) idx WHERE MOD(idx.row, $page_size) IN (0,$page_size_zerobase) OR idx.row = $count_results
-        "; 
+        ";
     }
 
     if (db_sqlite()) {
@@ -522,32 +557,30 @@ function create_page_browser($idxfield,
                 WHERE (row % $page_size) IN (0,$page_size_zerobase) OR row = $count_results";
     }
 
-#   echo "<p>$query";
-
-# TODO: $query is MySQL-specific
+    # TODO: $query is MySQL-specific
 
-# PostgreSQL: 
-# http://www.postgresql.org/docs/8.1/static/sql-createsequence.html
-# http://www.postgresonline.com/journal/archives/79-Simulating-Row-Number-in-PostgreSQL-Pre-8.4.html
-# http://www.pg-forum.de/sql/1518-nummerierung-der-abfrageergebnisse.html
-# CREATE TEMPORARY SEQUENCE foo MINVALUE 0 MAXVALUE $page_size_zerobase CYCLE
-# afterwards: DROP SEQUENCE foo
+    # PostgreSQL:
+    # http://www.postgresql.org/docs/8.1/static/sql-createsequence.html
+    # http://www.postgresonline.com/journal/archives/79-Simulating-Row-Number-in-PostgreSQL-Pre-8.4.html
+    # http://www.pg-forum.de/sql/1518-nummerierung-der-abfrageergebnisse.html
+    # CREATE TEMPORARY SEQUENCE foo MINVALUE 0 MAXVALUE $page_size_zerobase CYCLE
+    # afterwards: DROP SEQUENCE foo
 
-    $result = db_query ($query);
+    $result = db_query($query);
     if ($result['rows'] > 0) {
-        while ($row = db_array ($result['result'])) {
-            if ($row2 = db_array ($result['result'])) {
-                $label = substr($row['label'],0,$label_len) . '-' . substr($row2['label'],0,$label_len);
+        while ($row = db_assoc($result['result'])) {
+            if ($row2 = db_assoc($result['result'])) {
+                $label = substr($row['label'], 0, $label_len) . '-' . substr($row2['label'], 0, $label_len);
                 $pagebrowser[] = $label;
             } else { # only one row remaining
-                $label = substr($row['label'],0,$label_len);
+                $label = substr($row['label'], 0, $label_len);
                 $pagebrowser[] = $label;
             }
         }
     }
 
     if (db_pgsql()) {
-        db_query ("DROP SEQUENCE rowcount");
+        db_query("DROP SEQUENCE rowcount");
     }
 
     return $pagebrowser;
@@ -563,9 +596,11 @@ function create_page_browser($idxfield,
 // Action: Recalculates the quota from MBs to bytes (divide, /)
 // Call: divide_quota (string $quota)
 //
-function divide_quota ($quota) {
-    if ($quota == -1) return $quota;
-    $value = round($quota / Config::read('quota_multiplier'),2);
+function divide_quota($quota) {
+    if ($quota == -1) {
+        return $quota;
+    }
+    $value = round($quota / Config::read('quota_multiplier'), 2);
     return $value;
 }
 
@@ -576,11 +611,11 @@ function divide_quota ($quota) {
 // Action: Checks if the admin is the owner of the domain (or global-admin)
 // Call: check_owner (string admin, string domain)
 //
-function check_owner ($username, $domain) {
+function check_owner($username, $domain) {
     $table_domain_admins = table_by_key('domain_admins');
     $E_username = escape_string($username);
     $E_domain = escape_string($domain);
-    $result = db_query ("SELECT 1 FROM $table_domain_admins WHERE username='$E_username' AND (domain='$E_domain' OR domain='ALL') AND active='1'");
+    $result = db_query("SELECT 1 FROM $table_domain_admins WHERE username='$E_username' AND (domain='$E_domain' OR domain='ALL') AND active='1'");
 
     if ($result['rows'] == 1 || $result['rows'] == 2) { # "ALL" + specific domain permissions is possible
         # TODO: if superadmin, check if given domain exists in the database
@@ -597,11 +632,11 @@ function check_owner ($username, $domain
 
 
 /**
- * List domains for an admin user. 
+ * List domains for an admin user.
  * @param String $username
  * @return array of domain names.
  */
-function list_domains_for_admin ($username) {
+function list_domains_for_admin($username) {
     $table_domain = table_by_key('domain');
     $table_domain_admins = table_by_key('domain_admins');
 
@@ -610,22 +645,22 @@ function list_domains_for_admin ($userna
     $query = "SELECT $table_domain.domain FROM $table_domain ";
     $condition[] = "$table_domain.domain != 'ALL'";
 
-    $result = db_query ("SELECT username FROM $table_domain_admins WHERE username='$E_username' AND domain='ALL'");
+    $result = db_query("SELECT username FROM $table_domain_admins WHERE username='$E_username' AND domain='ALL'");
     if ($result['rows'] < 1) { # not a superadmin
         $query .= " LEFT JOIN $table_domain_admins ON $table_domain.domain=$table_domain_admins.domain ";
         $condition[] = "$table_domain_admins.username='$E_username' ";
         $condition[] = "$table_domain.active='"   . db_get_boolean(true)  . "'"; # TODO: does it really make sense to exclude inactive...
-        $condition[] = "$table_domain.backupmx='" . db_get_boolean(False) . "'"; # TODO: ... and backupmx domains for non-superadmins?
+        $condition[] = "$table_domain.backupmx='" . db_get_boolean(false) . "'"; # TODO: ... and backupmx domains for non-superadmins?
     }
 
     $query .= " WHERE " . join(' AND ', $condition);
     $query .= " ORDER BY $table_domain.domain";
 
-    $list = array ();
-    $result = db_query ($query);
+    $list = array();
+    $result = db_query($query);
     if ($result['rows'] > 0) {
         $i = 0;
-        while ($row = db_array ($result['result'])) {
+        while ($row = db_assoc($result['result'])) {
             $list[$i] = $row['domain'];
             $i++;
         }
@@ -640,14 +675,14 @@ function list_domains_for_admin ($userna
 // Action: List all available domains.
 // Call: list_domains ()
 //
-function list_domains () {
+function list_domains() {
     $list = array();
 
     $table_domain = table_by_key('domain');
-    $result = db_query ("SELECT domain FROM $table_domain WHERE domain!='ALL' ORDER BY domain");
+    $result = db_query("SELECT domain FROM $table_domain WHERE domain!='ALL' ORDER BY domain");
     if ($result['rows'] > 0) {
         $i = 0;
-        while ($row = db_array ($result['result'])) {
+        while ($row = db_assoc($result['result'])) {
             $list[$i] = $row['domain'];
             $i++;
         }
@@ -665,7 +700,7 @@ function list_domains () {
 //
 // was admin_list_admins
 //
-function list_admins () {
+function list_admins() {
     $handler = new AdminHandler();
 
     $handler->getList('');
@@ -679,14 +714,14 @@ function list_admins () {
 // Action: Encode a string according to RFC 1522 for use in headers if it contains 8-bit characters.
 // Call: encode_header (string header, string charset)
 //
-function encode_header ($string, $default_charset = "utf-8") {
-    if (strtolower ($default_charset) == 'iso-8859-1') {
-        $string = str_replace ("\240",' ',$string);
+function encode_header($string, $default_charset = "utf-8") {
+    if (strtolower($default_charset) == 'iso-8859-1') {
+        $string = str_replace("\240", ' ', $string);
     }
 
-    $j = strlen ($string);
-    $max_l = 75 - strlen ($default_charset) - 7;
-    $aRet = array ();
+    $j = strlen($string);
+    $max_l = 75 - strlen($default_charset) - 7;
+    $aRet = array();
     $ret = '';
     $iEncStart = $enc_init = false;
     $cur_l = $iOffset = 0;
@@ -704,20 +739,20 @@ function encode_header ($string, $defaul
                 }
                 $cur_l+=3;
                 if ($cur_l > ($max_l-2)) {
-                    $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
+                    $aRet[] = substr($string, $iOffset, $iEncStart-$iOffset);
                     $aRet[] = "=?$default_charset?Q?$ret?=";
                     $iOffset = $i;
                     $cur_l = 0;
                     $ret = '';
                     $iEncStart = false;
                 } else {
-                    $ret .= sprintf ("=%02X",ord($string{$i}));
+                    $ret .= sprintf("=%02X", ord($string{$i}));
                 }
                 break;
             case '(':
             case ')':
                 if ($iEncStart !== false) {
-                    $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
+                    $aRet[] = substr($string, $iOffset, $iEncStart-$iOffset);
                     $aRet[] = "=?$default_charset?Q?$ret?=";
                     $iOffset = $i;
                     $cur_l = 0;
@@ -729,7 +764,7 @@ function encode_header ($string, $defaul
                 if ($iEncStart !== false) {
                     $cur_l++;
                     if ($cur_l > $max_l) {
-                        $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
+                        $aRet[] = substr($string, $iOffset, $iEncStart-$iOffset);
                         $aRet[] = "=?$default_charset?Q?$ret?=";
                         $iOffset = $i;
                         $cur_l = 0;
@@ -741,21 +776,21 @@ function encode_header ($string, $defaul
                 }
                 break;
             default:
-                $k = ord ($string{$i});
+                $k = ord($string{$i});
                 if ($k > 126) {
                     if ($iEncStart === false) {
                         // do not start encoding in the middle of a string, also take the rest of the word.
-                        $sLeadString = substr ($string,0,$i);
-                        $aLeadString = explode (' ',$sLeadString);
-                        $sToBeEncoded = array_pop ($aLeadString);
-                        $iEncStart = $i - strlen ($sToBeEncoded);
+                        $sLeadString = substr($string, 0, $i);
+                        $aLeadString = explode(' ', $sLeadString);
+                        $sToBeEncoded = array_pop($aLeadString);
+                        $iEncStart = $i - strlen($sToBeEncoded);
                         $ret .= $sToBeEncoded;
-                        $cur_l += strlen ($sToBeEncoded);
+                        $cur_l += strlen($sToBeEncoded);
                     }
                     $cur_l += 3;
                     // first we add the encoded string that reached it's max size
                     if ($cur_l > ($max_l-2)) {
-                        $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
+                        $aRet[] = substr($string, $iOffset, $iEncStart-$iOffset);
                         $aRet[] = "=?$default_charset?Q?$ret?= ";
                         $cur_l = 3;
                         $ret = '';
@@ -763,12 +798,12 @@ function encode_header ($string, $defaul
                         $iEncStart = $i;
                     }
                     $enc_init = true;
-                    $ret .= sprintf ("=%02X", $k);
+                    $ret .= sprintf("=%02X", $k);
                 } else {
                     if ($iEncStart !== false) {
                         $cur_l++;
                         if ($cur_l > $max_l) {
-                            $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
+                            $aRet[] = substr($string, $iOffset, $iEncStart-$iOffset);
                             $aRet[] = "=?$default_charset?Q?$ret?=";
                             $iEncStart = false;
                             $iOffset = $i;
@@ -785,26 +820,25 @@ function encode_header ($string, $defaul
     }
     if ($enc_init) {
         if ($iEncStart !== false) {
-            $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
+            $aRet[] = substr($string, $iOffset, $iEncStart-$iOffset);
             $aRet[] = "=?$default_charset?Q?$ret?=";
         } else {
-            $aRet[] = substr ($string,$iOffset);
+            $aRet[] = substr($string, $iOffset);
         }
-        $string = implode ('',$aRet);
+        $string = implode('', $aRet);
     }
     return $string;
 }
 
 
 
-//
-// generate_password
-// Action: Generates a random password
-// Call: generate_password ()
-//
-function generate_password () {
-    // length of the generated password
-    $length = 8;
+/**
+ * Generate a random password of $length characters.
+ * @param int $length (optional, default: 12)
+ * @return string
+ *
+ */
+function generate_password($length = 12) {
 
     // define possible characters
     $possible = "2345678923456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ"; # skip 0 and 1 to avoid confusion with O and l
@@ -812,8 +846,12 @@ function generate_password () {
     // add random characters to $password until $length is reached
     $password = "";
     while (strlen($password) < $length) {
-        // pick a random character from the possible ones
-        $char = substr($possible, mt_rand(0, strlen($possible)-1), 1);
+        if (function_exists('random_int')) {
+            $random = random_int(0, strlen($possible) -1);
+        } else {
+            $random = mt_rand(0, strlen($possible) - 1);
+        }
+        $char = substr($possible, $random, 1);
 
         // we don't want this character if it's already in the password
         if (!strstr($password, $char)) {
@@ -828,7 +866,7 @@ function generate_password () {
 
 /**
  * Check if a password is strong enough based on the conditions in $CONF['password_validation']
- * @param String $password
+ * @param string $password
  * @return array of error messages, or empty array if the password is ok
  */
 function validate_password($password) {
@@ -854,164 +892,305 @@ function validate_password($password) {
     return $result;
 }
 
+function _pacrypt_md5crypt($pw, $pw_db) {
+    $split_salt = preg_split('/\$/', $pw_db);
+    if (isset($split_salt[2])) {
+        $salt = $split_salt[2];
+        return md5crypt($pw, $salt);
+    }
+
+    return md5crypt($pw);
+}
+
+function _pacrypt_crypt($pw, $pw_db) {
+    if ($pw_db) {
+        return crypt($pw, $pw_db);
+    }
+    return crypt($pw);
+}
+
+function _pacrypt_mysql_encrypt($pw, $pw_db) {
+    // See https://sourceforge.net/tracker/?func=detail&atid=937966&aid=1793352&group_id=191583
+    // this is apparently useful for pam_mysql etc.
+    $pw = escape_string($pw);
+    if ($pw_db!="") {
+        $salt=escape_string(substr($pw_db, 0, 2));
+        $res=db_query("SELECT ENCRYPT('".$pw."','".$salt."');");
+    } else {
+        $res=db_query("SELECT ENCRYPT('".$pw."');");
+    }
+    $l = db_row($res["result"]);
+    $password = $l[0];
+    return $password;
+}
+
+function _pacrypt_authlib($pw, $pw_db) {
+    global $CONF;
+    $flavor = $CONF['authlib_default_flavor'];
+    $salt = substr(create_salt(), 0, 2); # courier-authlib supports only two-character salts
+    if (preg_match('/^{.*}/', $pw_db)) {
+        // we have a flavor in the db -> use it instead of default flavor
+        $result = preg_split('/[{}]/', $pw_db, 3); # split at { and/or }
+        $flavor = $result[1];
+        $salt = substr($result[2], 0, 2);
+    }
+
+    if (stripos($flavor, 'md5raw') === 0) {
+        $password = '{' . $flavor . '}' . md5($pw);
+    } elseif (stripos($flavor, 'md5') === 0) {
+        $password = '{' . $flavor . '}' . base64_encode(md5($pw, true));
+    } elseif (stripos($flavor, 'crypt') === 0) {
+        $password = '{' . $flavor . '}' . crypt($pw, $salt);
+    } elseif (stripos($flavor, 'SHA') === 0) {
+        $password = '{' . $flavor . '}' . base64_encode(sha1($pw, true));
+    } else {
+        die("authlib_default_flavor '" . $flavor . "' unknown. Valid flavors are 'md5raw', 'md5', 'SHA' and 'crypt'");
+    }
+    return $password;
+}
 
 /**
- * Encrypt a password, using the apparopriate hashing mechanism as defined in 
- * config.inc.php ($CONF['encrypt']). 
- * When wanting to compare one pw to another, it's necessary to provide the salt used - hence
- * the second parameter ($pw_db), which is the existing hash from the DB.
- *
- * @param string $pw
- * @param string $encrypted password
- * @return string encrypted password.
+ * @param string $pw - plain text password
+ * @param string $pw_db - encrypted password, or '' for generation.
+ * @return string
  */
-function pacrypt ($pw, $pw_db="") {
+function _pacrypt_dovecot($pw, $pw_db) {
     global $CONF;
-    $password = "";
-    $salt = "";
 
-    if ($CONF['encrypt'] == 'md5crypt') {
-        $split_salt = preg_split ('/\$/', $pw_db);
-        if (isset ($split_salt[2])) {
-            $salt = $split_salt[2];
-        }
-        $password = md5crypt ($pw, $salt);
+    $split_method = preg_split('/:/', $CONF['encrypt']);
+    $method       = strtoupper($split_method[1]);
+    # If $pw_db starts with {method}, change $method accordingly
+    if (!empty($pw_db) && preg_match('/^\{([A-Z0-9.-]+)\}.+/', $pw_db, $method_matches)) {
+        $method = $method_matches[1];
+    }
+    if (! preg_match("/^[A-Z0-9.-]+$/", $method)) {
+        die("invalid dovecot encryption method");
+    }
+
+    # TODO: check against a fixed list?
+    # if (strtolower($method) == 'md5-crypt') die("\$CONF['encrypt'] = 'dovecot:md5-crypt' will not work because dovecotpw generates a random salt each time. Please use \$CONF['encrypt'] = 'md5crypt' instead.");
+    # $crypt_method = preg_match ("/.*-CRYPT$/", $method);
+
+    # digest-md5 and SCRAM-SHA-1 hashes include the username - until someone implements it, let's declare it as unsupported
+    if (strtolower($method) == 'digest-md5') {
+        die("Sorry, \$CONF['encrypt'] = 'dovecot:digest-md5' is not supported by PostfixAdmin.");
+    }
+    if (strtoupper($method) == 'SCRAM-SHA-1') {
+        die("Sorry, \$CONF['encrypt'] = 'dovecot:scram-sha-1' is not supported by PostfixAdmin.");
+    }
+    # TODO: add -u option for those hashes, or for everything that is salted (-u was available before dovecot 2.1 -> no problem with backward compability)
+
+    $dovecotpw = "doveadm pw";
+    if (!empty($CONF['dovecotpw'])) {
+        $dovecotpw = $CONF['dovecotpw'];
     }
 
-    elseif ($CONF['encrypt'] == 'md5') {
-        $password = md5($pw);
+    # Use proc_open call to avoid safe_mode problems and to prevent showing plain password in process table
+    $spec = array(
+        0 => array("pipe", "r"), // stdin
+        1 => array("pipe", "w"), // stdout
+        2 => array("pipe", "w"), // stderr
+    );
+
+    $nonsaltedtypes = "SHA|SHA1|SHA256|SHA512|CLEAR|CLEARTEXT|PLAIN|PLAIN-TRUNC|CRAM-MD5|HMAC-MD5|PLAIN-MD4|PLAIN-MD5|LDAP-MD5|LANMAN|NTLM|RPA";
+    $salted = ! preg_match("/^($nonsaltedtypes)(\.B64|\.BASE64|\.HEX)?$/", strtoupper($method));
+
+    $dovepasstest = '';
+    if ($salted && (!empty($pw_db))) {
+        # only use -t for salted passwords to be backward compatible with dovecot < 2.1
+        $dovepasstest = " -t " . escapeshellarg($pw_db);
     }
+    $pipe = proc_open("$dovecotpw '-s' $method$dovepasstest", $spec, $pipes);
+
+    if (!$pipe) {
+        die("can't proc_open $dovecotpw");
+    }
+
+    // use dovecot's stdin, it uses getpass() twice (except when using -t)
+    // Write pass in pipe stdin
+    if (empty($dovepasstest)) {
+        fwrite($pipes[0], $pw . "\n", 1+strlen($pw));
+        usleep(1000);
+    }
+    fwrite($pipes[0], $pw . "\n", 1+strlen($pw));
+    fclose($pipes[0]);
+
+    // Read hash from pipe stdout
+    $password = fread($pipes[1], "200");
 
-    elseif ($CONF['encrypt'] == 'system') {
-        if ($pw_db) {
-            $password = crypt($pw, $pw_db);
+    if (empty($dovepasstest)) {
+        if (!preg_match('/^\{' . $method . '\}/', $password)) {
+            $stderr_output = stream_get_contents($pipes[2]);
+            error_log('dovecotpw password encryption failed. STDERR output: '. $stderr_output);
+            die("can't encrypt password with dovecotpw, see error log for details");
+        }
+    } else {
+        if (!preg_match('(verified)', $password)) {
+            $password="Thepasswordcannotbeverified";
         } else {
-            $password = crypt($pw);
+            $password = rtrim(str_replace('(verified)', '', $password));
         }
     }
 
-    elseif ($CONF['encrypt'] == 'cleartext') {
-        $password = $pw;
+    fclose($pipes[1]);
+    fclose($pipes[2]);
+    proc_close($pipe);
+
+    if ((!empty($pw_db)) && (substr($pw_db, 0, 1) != '{')) {
+        # for backward compability with "old" dovecot passwords that don't have the {method} prefix
+        $password = str_replace('{' . $method . '}', '', $password);
     }
 
-    // See https://sourceforge.net/tracker/?func=detail&atid=937966&aid=1793352&group_id=191583
-    // this is apparently useful for pam_mysql etc.
-    elseif ($CONF['encrypt'] == 'mysql_encrypt') {
-        $pw = escape_string($pw);
-        if ($pw_db!="") {
-            $salt=escape_string(substr($pw_db,0,2));
-            $res=db_query("SELECT ENCRYPT('".$pw."','".$salt."');");
-        } else {
-            $res=db_query("SELECT ENCRYPT('".$pw."');");
-        }
-        $l = db_row($res["result"]);
-        $password = $l[0];
-    }
-    
-    elseif ($CONF['encrypt'] == 'authlib') {
-        $flavor = $CONF['authlib_default_flavor'];
-        $salt = substr(create_salt(), 0, 2); # courier-authlib supports only two-character salts
-        if(preg_match('/^{.*}/', $pw_db)) {
-            // we have a flavor in the db -> use it instead of default flavor
-            $result = preg_split('/[{}]/', $pw_db, 3); # split at { and/or }
-            $flavor = $result[1];  
-            $salt = substr($result[2], 0, 2);
-        }
- 
-        if(stripos($flavor, 'md5raw') === 0) {
-            $password = '{' . $flavor . '}' . md5($pw);
-        } elseif(stripos($flavor, 'md5') === 0) {
-            $password = '{' . $flavor . '}' . base64_encode(md5($pw, TRUE));
-        } elseif(stripos($flavor, 'crypt') === 0) {
-            $password = '{' . $flavor . '}' . crypt($pw, $salt);
-		} elseif(stripos($flavor, 'SHA') === 0) {
-			$password = '{' . $flavor . '}' . base64_encode(sha1($pw, TRUE));
-        } else {
-            die("authlib_default_flavor '" . $flavor . "' unknown. Valid flavors are 'md5raw', 'md5', 'SHA' and 'crypt'");
-        }
-    }
-    
-    elseif (preg_match("/^dovecot:/", $CONF['encrypt'])) {
-        $split_method = preg_split ('/:/', $CONF['encrypt']);
-        $method       = strtoupper($split_method[1]);
-        # If $pw_db starts with {method}, change $method accordingly
-        if (!empty($pw_db) && preg_match('/^\{([A-Z0-9.-]+)\}.+/', $pw_db, $method_matches)) { $method = $method_matches[1]; }
-        if (! preg_match("/^[A-Z0-9.-]+$/", $method)) { die("invalid dovecot encryption method"); }  # TODO: check against a fixed list?
-        # if (strtolower($method) == 'md5-crypt') die("\$CONF['encrypt'] = 'dovecot:md5-crypt' will not work because dovecotpw generates a random salt each time. Please use \$CONF['encrypt'] = 'md5crypt' instead."); 
-        # $crypt_method = preg_match ("/.*-CRYPT$/", $method);
-
-        # digest-md5 and SCRAM-SHA-1 hashes include the username - until someone implements it, let's declare it as unsupported
-        if (strtolower($method) == 'digest-md5') die("Sorry, \$CONF['encrypt'] = 'dovecot:digest-md5' is not supported by PostfixAdmin.");
-        if (strtoupper($method) == 'SCRAM-SHA-1') die("Sorry, \$CONF['encrypt'] = 'dovecot:scram-sha-1' is not supported by PostfixAdmin.");
-        # TODO: add -u option for those hashes, or for everything that is salted (-u was available before dovecot 2.1 -> no problem with backward compability)
-
-        $dovecotpw = "doveadm pw";
-        if (!empty($CONF['dovecotpw'])) $dovecotpw = $CONF['dovecotpw'];
-
-        # Use proc_open call to avoid safe_mode problems and to prevent showing plain password in process table
-        $spec = array(
-			0 => array("pipe", "r"), // stdin
-			1 => array("pipe", "w"), // stdout
-			2 => array("pipe", "w"), // stderr
-		);
-
-        $nonsaltedtypes = "SHA|SHA1|SHA256|SHA512|CLEAR|CLEARTEXT|PLAIN|PLAIN-TRUNC|CRAM-MD5|HMAC-MD5|PLAIN-MD4|PLAIN-MD5|LDAP-MD5|LANMAN|NTLM|RPA";
-        $salted = ! preg_match("/^($nonsaltedtypes)(\.B64|\.BASE64|\.HEX)?$/", strtoupper($method) );
-
-        $dovepasstest = '';
-        if ( $salted && (!empty($pw_db)) ) {
-            # only use -t for salted passwords to be backward compatible with dovecot < 2.1
-            $dovepasstest = " -t " . escapeshellarg($pw_db);
-        }
-        $pipe = proc_open("$dovecotpw '-s' $method$dovepasstest", $spec, $pipes);
-
-        if (!$pipe) {
-            die("can't proc_open $dovecotpw");
-        } else {
-            // use dovecot's stdin, it uses getpass() twice (except when using -t)
-			// Write pass in pipe stdin
-            if (empty($dovepasstest)) {
-                fwrite($pipes[0], $pw . "\n", 1+strlen($pw)); usleep(1000);
-            }
-			fwrite($pipes[0], $pw . "\n", 1+strlen($pw));
-			fclose($pipes[0]);
-
-			// Read hash from pipe stdout
-			$password = fread($pipes[1], "200");
-
-            if (empty($dovepasstest)) {
-                if ( !preg_match('/^\{' . $method . '\}/', $password)) {
-                    $stderr_output = stream_get_contents($pipes[2]);
-                    error_log('dovecotpw password encryption failed.');
-                    error_log('STDERR output: ' . $stderr_output);
-                    die("can't encrypt password with dovecotpw, see error log for details");
-                }
-            } else {
-                if ( !preg_match('(verified)', $password)) {
-                    $password="Thepasswordcannotbeverified";
-                } else {
-                    $password = rtrim(str_replace('(verified)', '', $password));
-                }
-            }
+    return rtrim($password);
+}
 
-			fclose($pipes[1]);
-			fclose($pipes[2]);
-			proc_close($pipe);
+/**
+ * @param string $pw
+ * @param string $pw_db (can be empty if setting a new password)
+ * @return string
+ */
+function _pacrypt_php_crypt($pw, $pw_db) {
+    global $CONF;
 
-            if ( (!empty($pw_db)) && (substr($pw_db,0,1) != '{') ) {
-                # for backward compability with "old" dovecot passwords that don't have the {method} prefix
-                $password = str_replace('{' . $method . '}', '', $password);
-            }
+    // use PHPs crypt(), which uses the system's crypt()
+    // same algorithms as used in /etc/shadow
+    // you can have mixed hash types in the database for authentication, changed passwords get specified hash type
+    // the algorithm for a new hash is chosen by feeding a salt with correct magic to crypt()
+    // set $CONF['encrypt'] to 'php_crypt' to use the default SHA512 crypt method
+    // set $CONF['encrypt'] to 'php_crypt:METHOD' to use another method; methods supported: DES, MD5, BLOWFISH, SHA256, SHA512
+    // tested on linux
+
+    if (strlen($pw_db) > 0) {
+        // existing pw provided. send entire password hash as salt for crypt() to figure out
+        $salt = $pw_db;
+    } else {
+        $salt_method = 'SHA512'; // hopefully a reasonable default (better than MD5)
+        // no pw provided. create new password hash
+        if (strpos($CONF['encrypt'], ':') !== false) {
+            // use specified hash method
+            $split_method = explode(':', $CONF['encrypt']);
+            $salt_method = $split_method[1];
+        }
+        // create appropriate salt for selected hash method
+        $salt = _php_crypt_generate_crypt_salt($salt_method);
+    }
+    // send it to PHPs crypt()
+    $password = crypt($pw, $salt);
+    return $password;
+}
+
+/**
+ * @param string $hash_type must be one of: MD5, DES, BLOWFISH, SHA256 or SHA512  (default)
+ * @return string
+ */
+function _php_crypt_generate_crypt_salt($hash_type='SHA512') {
+    // generate a salt (with magic matching chosen hash algorithm) for the PHP crypt() function
+
+    // most commonly used alphabet
+    $alphabet = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
 
-            $password = rtrim($password);
+    switch ($hash_type) {
+    case 'DES':
+        $alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+        $length = 2;
+        $salt = _php_crypt_random_string($alphabet, $length);
+        return $salt;
+
+    case 'MD5':
+        $length = 12;
+        $algorithm = '1';
+        $salt = _php_crypt_random_string($alphabet, $length);
+        return sprintf('$%s$%s', $algorithm, $salt);
+
+    case 'BLOWFISH':
+        $length = 22;
+        $cost = 10;
+        if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
+            $algorithm = '2y'; // bcrypt, with fixed unicode problem
+        } else {
+            $algorithm = '2a'; // bcrypt
+        }
+        $salt = _php_crypt_random_string($alphabet, $length);
+        return sprintf('$%s$%02d$%s', $algorithm, $cost, $salt);
+
+    case 'SHA256':
+        $length = 16;
+        $algorithm = '5';
+        $salt = _php_crypt_random_string($alphabet, $length);
+        return sprintf('$%s$%s', $algorithm, $salt);
+
+    case 'SHA512':
+        $length = 16;
+        $algorithm = '6';
+        $salt = _php_crypt_random_string($alphabet, $length);
+        return sprintf('$%s$%s', $algorithm, $salt);
+
+    default:
+        die("unknown hash type: '$hash_type'");
+    }
+}
+
+/**
+ * Generates a random string of specified $length from $characters.
+ * @param string $characters
+ * @param int $length
+ * @return string of given $length
+ */
+function _php_crypt_random_string($characters, $length) {
+    $random_int_exists = true;
+    if (!function_exists('random_int')) {
+        $random_int_exists = false;
+    }
+    $string = '';
+    for ($p = 0; $p < $length; $p++) {
+        if ($random_int_exists) {
+            $string .= $characters[random_int(0, strlen($characters) -1)];
+        } else {
+            // should really use a stronger randomness source
+            $string .= $characters[mt_rand(0, strlen($characters) - 1)];
         }
     }
+    return $string;
+}
+
 
-    else {
-        die ('unknown/invalid $CONF["encrypt"] setting: ' . $CONF['encrypt']);
+/**
+ * Encrypt a password, using the apparopriate hashing mechanism as defined in
+ * config.inc.php ($CONF['encrypt']).
+ * When wanting to compare one pw to another, it's necessary to provide the salt used - hence
+ * the second parameter ($pw_db), which is the existing hash from the DB.
+ *
+ * @param string $pw
+ * @param string $pw_db optional encrypted password
+ * @return string encrypted password.
+ */
+function pacrypt($pw, $pw_db="") {
+    global $CONF;
+
+    switch ($CONF['encrypt']) {
+        case 'md5crypt':
+            return _pacrypt_md5crypt($pw, $pw_db);
+        case 'md5':
+            return md5($pw);
+        case 'system':
+            return _pacrypt_crypt($pw, $pw_db);
+        case 'cleartext':
+            return $pw;
+        case 'mysql_encrypt':
+            return _pacrypt_mysql_encrypt($pw, $pw_db);
+        case 'authlib':
+            return _pacrypt_authlib($pw, $pw_db);
+    }
+
+    if (preg_match("/^dovecot:/", $CONF['encrypt'])) {
+        return _pacrypt_dovecot($pw, $pw_db);
     }
 
-    return $password;
+    if (substr($CONF['encrypt'], 0, 9) === 'php_crypt') {
+        return _pacrypt_php_crypt($pw, $pw_db);
+    }
+
+    die('unknown/invalid $CONF["encrypt"] setting: ' . $CONF['encrypt']);
 }
 
 //
@@ -1020,77 +1199,91 @@ function pacrypt ($pw, $pw_db="") {
 // Call: md5crypt (string cleartextpassword)
 //
 
-function md5crypt ($pw, $salt="", $magic="") {
+function md5crypt($pw, $salt="", $magic="") {
     $MAGIC = "$1$";
 
-    if ($magic == "") $magic = $MAGIC;
-    if ($salt == "") $salt = create_salt ();
-    $slist = explode ("$", $salt);
-    if ($slist[0] == "1") $salt = $slist[1];
+    if ($magic == "") {
+        $magic = $MAGIC;
+    }
+    if ($salt == "") {
+        $salt = create_salt();
+    }
+    $slist = explode("$", $salt);
+    if ($slist[0] == "1") {
+        $salt = $slist[1];
+    }
 
-    $salt = substr ($salt, 0, 8);
+    $salt = substr($salt, 0, 8);
     $ctx = $pw . $magic . $salt;
-    $final = hex2bin (md5 ($pw . $salt . $pw));
+    $final = hex2bin(md5($pw . $salt . $pw));
 
-    for ($i=strlen ($pw); $i>0; $i-=16) {
+    for ($i=strlen($pw); $i>0; $i-=16) {
         if ($i > 16) {
-            $ctx .= substr ($final,0,16);
+            $ctx .= substr($final, 0, 16);
         } else {
-            $ctx .= substr ($final,0,$i);
+            $ctx .= substr($final, 0, $i);
         }
     }
-    $i = strlen ($pw);
+    $i = strlen($pw);
 
     while ($i > 0) {
-        if ($i & 1) $ctx .= chr (0);
-        else $ctx .= $pw[0];
+        if ($i & 1) {
+            $ctx .= chr(0);
+        } else {
+            $ctx .= $pw[0];
+        }
         $i = $i >> 1;
     }
-    $final = hex2bin (md5 ($ctx));
+    $final = hex2bin(md5($ctx));
 
     for ($i=0;$i<1000;$i++) {
         $ctx1 = "";
         if ($i & 1) {
             $ctx1 .= $pw;
         } else {
-            $ctx1 .= substr ($final,0,16);
+            $ctx1 .= substr($final, 0, 16);
+        }
+        if ($i % 3) {
+            $ctx1 .= $salt;
+        }
+        if ($i % 7) {
+            $ctx1 .= $pw;
         }
-        if ($i % 3) $ctx1 .= $salt;
-        if ($i % 7) $ctx1 .= $pw;
         if ($i & 1) {
-            $ctx1 .= substr ($final,0,16);
+            $ctx1 .= substr($final, 0, 16);
         } else {
             $ctx1 .= $pw;
         }
-        $final = hex2bin (md5 ($ctx1));
+        $final = hex2bin(md5($ctx1));
     }
     $passwd = "";
-    $passwd .= to64 (((ord ($final[0]) << 16) | (ord ($final[6]) << 8) | (ord ($final[12]))), 4);
-    $passwd .= to64 (((ord ($final[1]) << 16) | (ord ($final[7]) << 8) | (ord ($final[13]))), 4);
-    $passwd .= to64 (((ord ($final[2]) << 16) | (ord ($final[8]) << 8) | (ord ($final[14]))), 4);
-    $passwd .= to64 (((ord ($final[3]) << 16) | (ord ($final[9]) << 8) | (ord ($final[15]))), 4);
-    $passwd .= to64 (((ord ($final[4]) << 16) | (ord ($final[10]) << 8) | (ord ($final[5]))), 4);
-    $passwd .= to64 (ord ($final[11]), 2);
+    $passwd .= to64(((ord($final[0]) << 16) | (ord($final[6]) << 8) | (ord($final[12]))), 4);
+    $passwd .= to64(((ord($final[1]) << 16) | (ord($final[7]) << 8) | (ord($final[13]))), 4);
+    $passwd .= to64(((ord($final[2]) << 16) | (ord($final[8]) << 8) | (ord($final[14]))), 4);
+    $passwd .= to64(((ord($final[3]) << 16) | (ord($final[9]) << 8) | (ord($final[15]))), 4);
+    $passwd .= to64(((ord($final[4]) << 16) | (ord($final[10]) << 8) | (ord($final[5]))), 4);
+    $passwd .= to64(ord($final[11]), 2);
     return "$magic$salt\$$passwd";
 }
 
-function create_salt () {
-    srand ((double) microtime ()*1000000);
-    $salt = substr (md5 (rand (0,9999999)), 0, 8);
+function create_salt() {
+    srand((double) microtime()*1000000);
+    $salt = substr(md5(rand(0, 9999999)), 0, 8);
     return $salt;
 }
 
 /**/ if (!function_exists('hex2bin')) { # PHP around 5.3.8 includes hex2bin as native function - http://php.net/hex2bin
-function hex2bin ($str) {
-    $len = strlen ($str);
-    $nstr = "";
-    for ($i=0;$i<$len;$i+=2) {
-        $num = sscanf (substr ($str,$i,2), "%x");
-        $nstr.=chr ($num[0]);
+    function hex2bin($str) {
+        $len = strlen($str);
+        $nstr = "";
+        for ($i=0;$i<$len;$i+=2) {
+            $num = sscanf(substr($str, $i, 2), "%x");
+            $nstr.=chr($num[0]);
+        }
+        return $nstr;
     }
-    return $nstr;
+    /**/
 }
-/**/ }
 
 /*
  * remove item $item from array $array
@@ -1103,12 +1296,12 @@ function remove_from_array($array, $item
         $found = 0;
     } else {
         $found = 1;
-        unset ($array[$ret]);
+        unset($array[$ret]);
     }
     return array($found, $array);
 }
 
-function to64 ($v, $n) {
+function to64($v, $n) {
     $ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
     $ret = "";
     while (($n - 1) >= 0) {
@@ -1133,13 +1326,13 @@ function to64 ($v, $n) {
  * @return bool - true on success, otherwise false
  * TODO: Replace this with something decent like PEAR::Mail or Zend_Mail.
  */
-function smtp_mail ($to, $from, $data, $body = "") {
+function smtp_mail($to, $from, $data, $body = "") {
     global $CONF;
     $smtpd_server = $CONF['smtp_server'];
     $smtpd_port = $CONF['smtp_port'];
     //$smtp_server = $_SERVER["SERVER_NAME"];
     $smtp_server = php_uname('n');
-    if(!empty($CONF['smtp_client'])) {
+    if (!empty($CONF['smtp_client'])) {
         $smtp_server = $CONF['smtp_client'];
     }
     $errno = "0";
@@ -1147,10 +1340,10 @@ function smtp_mail ($to, $from, $data, $
     $timeout = "30";
 
     if ($body != "") {
-        $maildata = 
+        $maildata =
             "To: " . $to . "\n"
             . "From: " . $from . "\n"
-            . "Subject: " . encode_header ($data) . "\n"
+            . "Subject: " . encode_header($data) . "\n"
             . "MIME-Version: 1.0\n"
             . "Content-Type: text/plain; charset=utf-8\n"
             . "Content-Transfer-Encoding: 8bit\n"
@@ -1161,26 +1354,26 @@ function smtp_mail ($to, $from, $data, $
         $maildata = $data;
     }
 
-    $fh = @fsockopen ($smtpd_server, $smtpd_port, $errno, $errstr, $timeout);
+    $fh = @fsockopen($smtpd_server, $smtpd_port, $errno, $errstr, $timeout);
 
     if (!$fh) {
         error_log("fsockopen failed - errno: $errno - errstr: $errstr");
         return false;
     } else {
         $res = smtp_get_response($fh);
-        fputs ($fh, "EHLO $smtp_server\r\n");
+        fputs($fh, "EHLO $smtp_server\r\n");
         $res = smtp_get_response($fh);
-        fputs ($fh, "MAIL FROM:<$from>\r\n");
+        fputs($fh, "MAIL FROM:<$from>\r\n");
         $res = smtp_get_response($fh);
-        fputs ($fh, "RCPT TO:<$to>\r\n");
+        fputs($fh, "RCPT TO:<$to>\r\n");
         $res = smtp_get_response($fh);
-        fputs ($fh, "DATA\r\n");
+        fputs($fh, "DATA\r\n");
         $res = smtp_get_response($fh);
-        fputs ($fh, "$maildata\r\n.\r\n");
+        fputs($fh, "$maildata\r\n.\r\n");
         $res = smtp_get_response($fh);
-        fputs ($fh, "QUIT\r\n");
+        fputs($fh, "QUIT\r\n");
         $res = smtp_get_response($fh);
-        fclose ($fh);
+        fclose($fh);
     }
     return true;
 }
@@ -1193,10 +1386,11 @@ function smtp_mail ($to, $from, $data, $
  */
 function smtp_get_admin_email() {
     $admin_email = Config::read('admin_email');
-	if(!empty($admin_email))
-		return $admin_email;
-	else
-		return authentication_get_username();
+    if (!empty($admin_email)) {
+        return $admin_email;
+    } else {
+        return authentication_get_username();
+    }
 }
 
 
@@ -1205,13 +1399,12 @@ function smtp_get_admin_email() {
 // Action: Get response from mail server
 // Call: smtp_get_response (string FileHandle)
 //
-function smtp_get_response ($fh) {
+function smtp_get_response($fh) {
     $res ='';
     do {
         $line = fgets($fh, 256);
         $res .= $line;
-    }
-    while (preg_match("/^\d\d\d\-/", $line));
+    } while (preg_match("/^\d\d\d\-/", $line));
     return $res;
 }
 
@@ -1238,38 +1431,62 @@ $DEBUG_TEXT = "\n
  *    - call die() in case of connection problems
  * b) with $ignore_errors == TRUE
  *    array($link, $error_text);
+ *
+ * @return resource connection to db (normally)
  */
-function db_connect ($ignore_errors = 0) {
+function db_connect($ignore_errors = false) {
     global $CONF;
     global $DEBUG_TEXT;
-    if ($ignore_errors != 0) $DEBUG_TEXT = '';
+    if ($ignore_errors != 0) {
+        $DEBUG_TEXT = '';
+    }
     $error_text = '';
+
+    static $link;
+    if (isset($link) && $link) {
+        if ($ignore_errors) {
+            return array($link, $error_text);
+        }
+        return $link;
+    }
     $link = 0;
 
     if ($CONF['database_type'] == "mysql") {
-        if (function_exists ("mysql_connect")) {
-            $link = @mysql_connect ($CONF['database_host'], $CONF['database_user'], $CONF['database_password']) or $error_text .= ("<p />DEBUG INFORMATION:<br />Connect: " .  mysql_error () . "$DEBUG_TEXT");
+        if (function_exists("mysql_connect")) {
+            $link = @mysql_connect($CONF['database_host'], $CONF['database_user'], $CONF['database_password']) or $error_text .= ("<p />DEBUG INFORMATION:<br />Connect: " .  mysql_error() . "$DEBUG_TEXT");
             if ($link) {
-                @mysql_query("SET CHARACTER SET utf8",$link);
-                @mysql_query("SET COLLATION_CONNECTION='utf8_general_ci'",$link);
-                @mysql_select_db ($CONF['database_name'], $link) or $error_text .= ("<p />DEBUG INFORMATION:<br />MySQL Select Database: " .  mysql_error () . "$DEBUG_TEXT");
+                @mysql_query("SET CHARACTER SET utf8", $link);
+                @mysql_query("SET COLLATION_CONNECTION='utf8_general_ci'", $link);
+                @mysql_select_db($CONF['database_name'], $link) or $error_text .= ("<p />DEBUG INFORMATION:<br />MySQL Select Database: " .  mysql_error() . "$DEBUG_TEXT");
             }
         } else {
             $error_text .= "<p />DEBUG INFORMATION:<br />MySQL 3.x / 4.0 functions not available! (php5-mysql installed?)<br />database_type = 'mysql' in config.inc.php, are you using a different database? $DEBUG_TEXT";
         }
     } elseif ($CONF['database_type'] == "mysqli") {
-        if (function_exists ("mysqli_connect")) {
-            $link = @mysqli_connect ($CONF['database_host'], $CONF['database_user'], $CONF['database_password']) or $error_text .= ("<p />DEBUG INFORMATION:<br />Connect: " .  mysqli_connect_error () . "$DEBUG_TEXT");
-            if ($link) {
-                @mysqli_query($link,"SET CHARACTER SET utf8");
-                @mysqli_query($link,"SET COLLATION_CONNECTION='utf8_general_ci'");
-                @mysqli_select_db ($link, $CONF['database_name']) or $error_text .= ("<p />DEBUG INFORMATION:<br />MySQLi Select Database: " .  mysqli_error ($link) . "$DEBUG_TEXT");
+        $is_connected = false;
+        if ($CONF['database_use_ssl']) {
+            if (function_exists("mysqli_real_connect")) {
+                $link = mysqli_init();
+                $link->ssl_set($CONF['database_ssl_key'], $CONF['database_ssl_cert'], $CONF['database_ssl_ca'], $CONF['database_ssl_ca_path'], $CONF['database_ssl_cipher']);
+                $connected = mysqli_real_connect($link, $CONF['database_host'], $CONF['database_user'], $CONF['database_password'], $CONF['database_name'], $CONF['database_port']);
+                $is_connected = $connected;
+            } else {
+                $error_text .= "<p />DEBUG INFORMATION:<br />MySQLi 5 functions not available! (php5-mysqli installed?)<br />database_type = 'mysqli' in config.inc.php, are you using a different database? $DEBUG_TEXT";
             }
         } else {
-            $error_text .= "<p />DEBUG INFORMATION:<br />MySQL 4.1 functions not available! (php5-mysqli installed?)<br />database_type = 'mysqli' in config.inc.php, are you using a different database? $DEBUG_TEXT";
+            if (function_exists("mysqli_connect")) {
+                $link = @mysqli_connect($CONF['database_host'], $CONF['database_user'], $CONF['database_password'], $CONF['database_name'], $CONF['database_port'], $CONF['database_socket']) or $error_text .= ("<p />DEBUG INFORMATION:<br />Connect: " . mysqli_connect_error() . "$DEBUG_TEXT");
+                $is_connected = $link;
+            } else {
+                $error_text .= "<p />DEBUG INFORMATION:<br />MySQL 4.1 functions not available! (php5-mysqli installed?)<br />database_type = 'mysqli' in config.inc.php, are you using a different database? $DEBUG_TEXT";
+            }
+        }
+        if ($is_connected) {
+            @mysqli_query($link, "SET CHARACTER SET utf8");
+            @mysqli_query($link, "SET COLLATION_CONNECTION='utf8_general_ci'");
         }
     } elseif (db_sqlite()) {
-        if (class_exists ("SQLite3")) {
+        if (class_exists("SQLite3")) {
             if ($CONF['database_name'] == '' || !is_dir(dirname($CONF['database_name'])) || !is_writable(dirname($CONF['database_name']))) {
                 $error_text .= ("<p />DEBUG INFORMATION<br />Connect: given database path does not exist, is not writable, or \$CONF['database_name'] is empty.");
             } else {
@@ -1280,13 +1497,15 @@ function db_connect ($ignore_errors = 0)
             $error_text .= "<p />DEBUG INFORMATION:<br />SQLite functions not available! (php5-sqlite installed?)<br />database_type = 'sqlite' in config.inc.php, are you using a different database? $DEBUG_TEXT";
         }
     } elseif (db_pgsql()) {
-        if (function_exists ("pg_pconnect")) {
-			if(!isset($CONF['database_port'])) {
-				$CONF['database_port'] = '5432';
-			}
+        if (function_exists("pg_pconnect")) {
+            if (!isset($CONF['database_port'])) {
+                $CONF['database_port'] = '5432';
+            }
             $connect_string = "host=" . $CONF['database_host'] . " port=" . $CONF['database_port'] . " dbname=" . $CONF['database_name'] . " user=" . $CONF['database_user'] . " password=" . $CONF['database_password'];
-            $link = @pg_pconnect ($connect_string) or $error_text .= ("<p />DEBUG INFORMATION:<br />Connect: failed to connect to database. $DEBUG_TEXT");
-            if ($link) pg_set_client_encoding($link, 'UNICODE');
+            $link = @pg_pconnect($connect_string) or $error_text .= ("<p />DEBUG INFORMATION:<br />Connect: failed to connect to database. $DEBUG_TEXT");
+            if ($link) {
+                pg_set_client_encoding($link, 'UNICODE');
+            }
         } else {
             $error_text .= "<p />DEBUG INFORMATION:<br />PostgreSQL functions not available! (php5-pgsql installed?)<br />database_type = 'pgsql' in config.inc.php, are you using a different database? $DEBUG_TEXT";
         }
@@ -1318,21 +1537,21 @@ function db_connect ($ignore_errors = 0)
  * @return String or int as appropriate.
  */
 function db_get_boolean($bool) {
-    if(! (is_bool($bool) || $bool == '0' || $bool == '1') ) {
+    if (! (is_bool($bool) || $bool == '0' || $bool == '1')) {
         error_log("Invalid usage of 'db_get_boolean($bool)'");
         die("Invalid usage of 'db_get_boolean($bool)'");
     }
 
-    if(db_pgsql()) {
+    if (db_pgsql()) {
         // return either true or false (unquoted strings)
-        if($bool) {
+        if ($bool) {
             return 't';
-        }  
+        }
         return 'f';
-    } elseif(Config::Read('database_type') == 'mysql' || Config::Read('database_type') == 'mysqli' || db_sqlite()) {
-        if($bool) {
-            return 1;  
-        } 
+    } elseif (Config::Read('database_type') == 'mysql' || Config::Read('database_type') == 'mysqli' || db_sqlite()) {
+        if ($bool) {
+            return 1;
+        }
         return 0;
     } else {
         die('Unknown value in $CONF[database_type]');
@@ -1354,8 +1573,7 @@ function db_quota_text($count, $quota, $
             WHEN '0' THEN (coalesce($count,0) || ' / " . escape_string(html_entity_decode('&infin;')) . "')
             ELSE (coalesce($count,0) || ' / ' || $quota)
         END AS $fieldname";
-    }
-    else {
+    } else {
         return " CASE $quota
             WHEN '-1' THEN CONCAT(coalesce($count,0), ' / -')
             WHEN '0' THEN CONCAT(coalesce($count,0), ' / ', '" . escape_string(html_entity_decode('&infin;')) . "')
@@ -1380,53 +1598,68 @@ function db_quota_percent($count, $quota
 }
 
 /**
+ * @return boolean true if it's a MySQL database variant.
+ */
+function db_mysql() {
+    $type = Config::Read('database_type');
+
+    if ($type == 'mysql' || $type == 'mysqli') {
+        return true;
+    }
+    return false;
+}
+
+/**
  * returns true if PostgreSQL is used, false otherwise
  */
 function db_pgsql() {
-    if(Config::Read('database_type')=='pgsql') {
+    if (Config::Read('database_type')=='pgsql') {
         return true;
-    } else {
-        return false;
     }
+    return false;
 }
 
 /**
  * returns true if SQLite is used, false otherwise
  */
 function db_sqlite() {
-    if(Config::Read('database_type')=='sqlite') {
+    if (Config::Read('database_type')=='sqlite') {
         return true;
     } else {
         return false;
     }
 }
 
-//
-// db_query
-// Action: Sends a query to the database and returns query result and number of rows
-// Call: db_query (string query)
-// Optional parameter: $ignore_errors = TRUE, used by upgrade.php
-//
-function db_query ($query, $ignore_errors = 0) {
+/**
+ * @param string $query SQL to execute
+ * @param int $ignore_errors (default 0 aka do not ignore errors)
+ * @return array ['result' => resource, 'rows' => int ,'error' => string]
+ */
+function db_query($query, $ignore_errors = 0) {
     global $CONF;
     global $DEBUG_TEXT;
     $result = "";
     $number_rows = "";
-    static $link;
+    $link = db_connect();
     $error_text = "";
-    if ($ignore_errors) $DEBUG_TEXT = "";
-
-    # mysql and pgsql $link are resources, mysqli $link is an object
-    if (! (is_resource($link) || is_object($link) ) ) $link = db_connect ();
+    if ($ignore_errors) {
+        $DEBUG_TEXT = "";
+    }
 
-    if ($CONF['database_type'] == "mysql") $result = @mysql_query ($query, $link) 
+    if ($CONF['database_type'] == "mysql") {
+        $result = @mysql_query($query, $link)
         or $error_text = "Invalid query: " . mysql_error($link);
-    if ($CONF['database_type'] == "mysqli") $result = @mysqli_query ($link, $query) 
+    }
+    if ($CONF['database_type'] == "mysqli") {
+        $result = @mysqli_query($link, $query)
         or $error_text = "Invalid query: " . mysqli_error($link);
-    if (db_sqlite()) $result = @$link->query($query)
+    }
+    if (db_sqlite()) {
+        $result = @$link->query($query)
         or $error_text = "Invalid query: " . $link->lastErrorMsg();
+    }
     if (db_pgsql()) {
-        $result = @pg_query ($link, $query) 
+        $result = @pg_query($link, $query)
             or $error_text = "Invalid query: " . pg_last_error();
     }
     if ($error_text != "" && $ignore_errors == 0) {
@@ -1437,10 +1670,12 @@ function db_query ($query, $ignore_error
 
     if ($error_text == "") {
         if (db_sqlite()) {
-            if($result->numColumns()) {
+            if ($result->numColumns()) {
                 // Query returned something
                 $num_rows = 0;
-                while(@$result->fetchArray(SQLITE3_ASSOC)) $num_rows++;
+                while (@$result->fetchArray(SQLITE3_ASSOC)) {
+                    $num_rows++;
+                }
                 $result->reset();
                 $number_rows = $num_rows;
             } else {
@@ -1449,19 +1684,31 @@ function db_query ($query, $ignore_error
             }
         } elseif (preg_match("/^SELECT/i", trim($query))) {
             // if $query was a SELECT statement check the number of rows with [database_type]_num_rows ().
-            if ($CONF['database_type'] == "mysql") $number_rows = mysql_num_rows ($result);
-            if ($CONF['database_type'] == "mysqli") $number_rows = mysqli_num_rows ($result);
-            if (db_pgsql()                        ) $number_rows = pg_num_rows ($result);
+            if ($CONF['database_type'] == "mysql") {
+                $number_rows = mysql_num_rows($result);
+            }
+            if ($CONF['database_type'] == "mysqli") {
+                $number_rows = mysqli_num_rows($result);
+            }
+            if (db_pgsql()) {
+                $number_rows = pg_num_rows($result);
+            }
         } else {
             // if $query was something else, UPDATE, DELETE or INSERT check the number of rows with
             // [database_type]_affected_rows ().
-            if ($CONF['database_type'] == "mysql") $number_rows = mysql_affected_rows ($link);
-            if ($CONF['database_type'] == "mysqli") $number_rows = mysqli_affected_rows ($link);
-            if (db_pgsql()                        ) $number_rows = pg_affected_rows ($result);
+            if ($CONF['database_type'] == "mysql") {
+                $number_rows = mysql_affected_rows($link);
+            }
+            if ($CONF['database_type'] == "mysqli") {
+                $number_rows = mysqli_affected_rows($link);
+            }
+            if (db_pgsql()) {
+                $number_rows = pg_affected_rows($result);
+            }
         }
     }
 
-    $return = array (
+    $return = array(
         "result" => $result,
         "rows" => $number_rows,
         "error" => $error_text
@@ -1475,59 +1722,90 @@ function db_query ($query, $ignore_error
 // Action: Returns a row from a table
 // Call: db_row (int result)
 
-function db_row ($result) {
+function db_row($result) {
     global $CONF;
     $row = "";
-    if ($CONF['database_type'] == "mysql") $row = mysql_fetch_row ($result);
-    if ($CONF['database_type'] == "mysqli") $row = mysqli_fetch_row ($result);
-    if (db_sqlite()                       ) $row = $result->fetchArray(SQLITE3_NUM);
-    if (db_pgsql()                        ) $row = pg_fetch_row ($result);
+    if ($CONF['database_type'] == "mysql") {
+        $row = mysql_fetch_row($result);
+    }
+    if ($CONF['database_type'] == "mysqli") {
+        $row = mysqli_fetch_row($result);
+    }
+    if (db_sqlite()) {
+        $row = $result->fetchArray(SQLITE3_NUM);
+    }
+    if (db_pgsql()) {
+        $row = pg_fetch_row($result);
+    }
     return $row;
 }
 
 
-
-// db_array
-// Action: Returns a row from a table
-// Call: db_array (int result)
-//
-function db_array ($result) {
+/**
+ * Return array from a db resource (presumably not associative).
+ * @param resource $result
+ * @return array|null|string
+ */
+function db_array($result) {
     global $CONF;
     $row = "";
-    if ($CONF['database_type'] == "mysql") $row = mysql_fetch_array ($result);
-    if ($CONF['database_type'] == "mysqli") $row = mysqli_fetch_array ($result);
-    if (db_sqlite()                       ) $row = $result->fetchArray();
-    if (db_pgsql()                        ) $row = pg_fetch_array ($result);
+    if ($CONF['database_type'] == "mysql") {
+        $row = mysql_fetch_array($result);
+    }
+    if ($CONF['database_type'] == "mysqli") {
+        $row = mysqli_fetch_array($result);
+    }
+    if (db_sqlite()) {
+        $row = $result->fetchArray();
+    }
+    if (db_pgsql()) {
+        $row = pg_fetch_array($result);
+    }
     return $row;
 }
 
 
-
-// db_assoc
-// Action: Returns a row from a table
-// Call: db_assoc(int result)
-//
-function db_assoc ($result) {
+/**
+ * Get an associative array from a DB query resource.
+ *
+ * @param resource $result
+ * @return array|null|string
+ */
+function db_assoc($result) {
     global $CONF;
     $row = "";
-    if ($CONF['database_type'] == "mysql") $row = mysql_fetch_assoc ($result);
-    if ($CONF['database_type'] == "mysqli") $row = mysqli_fetch_assoc ($result);
-    if (db_sqlite()                       ) $row = $result->fetchArray(SQLITE3_ASSOC);
-    if (db_pgsql()                        ) $row = pg_fetch_assoc ($result);
+    if ($CONF['database_type'] == "mysql") {
+        $row = mysql_fetch_assoc($result);
+    }
+    if ($CONF['database_type'] == "mysqli") {
+        $row = mysqli_fetch_assoc($result);
+    }
+    if (db_sqlite()) {
+        $row = $result->fetchArray(SQLITE3_ASSOC);
+    }
+    if (db_pgsql()) {
+        $row = pg_fetch_assoc($result);
+    }
     return $row;
 }
 
 
-
-//
-// db_delete
-// Action: Deletes a row from a specified table
-// Call: db_delete (string table, string where, string delete)
-//
-function db_delete ($table,$where,$delete,$additionalwhere='') {
+/**
+ * Delete a row from the specified table.
+ *
+ * DELETE FROM $table WHERE $where = $delete $aditionalWhere
+ *
+ * @param string $table
+ * @param string $where - should never be a user supplied value
+ * @param string $delete
+ * @param string $additionalwhere (default '').
+ * @return int|mixed rows deleted.
+ */
+function db_delete($table, $where, $delete, $additionalwhere='') {
     $table = table_by_key($table);
-    $query = "DELETE FROM $table WHERE " . escape_string($where) . "='" . escape_string($delete) . "' " . $additionalwhere;
-    $result = db_query ($query);
+
+    $query = "DELETE FROM $table WHERE $where ='" . escape_string($delete) . "' " . $additionalwhere;
+    $result = db_query($query);
 
     if ($result['rows'] >= 1) {
         return $result['rows'];
@@ -1541,19 +1819,20 @@ function db_delete ($table,$where,$delet
  * db_insert
  * Action: Inserts a row from a specified table
  * Call: db_insert (string table, array values [, array timestamp])
- * @param String - table name
+ *
+ * @param string - table name
  * @param array  - key/value map of data to insert into the table.
  * @param array (optional) - array of fields to set to now() - default: array('created', 'modified')
  * @return int - number of inserted rows
  */
-function db_insert ($table, $values, $timestamp = array('created', 'modified') ) {
-    $table = table_by_key ($table);
+function db_insert($table, $values, $timestamp = array('created', 'modified')) {
+    $table = table_by_key($table);
 
-    foreach(array_keys($values) as $key) {
+    foreach (array_keys($values) as $key) {
         $values[$key] = "'" . escape_string($values[$key]) . "'";
     }
 
-    foreach($timestamp as $key) {
+    foreach ($timestamp as $key) {
         if (db_sqlite()) {
             $values[$key] = "datetime('now')";
         } else {
@@ -1561,9 +1840,9 @@ function db_insert ($table, $values, $ti
         }
     }
 
-    $sql_values = "(" . implode(",",escape_string(array_keys($values))).") VALUES (".implode(",",$values).")";
+    $sql_values = "(" . implode(",", escape_string(array_keys($values))).") VALUES (".implode(",", $values).")";
 
-    $result = db_query ("INSERT INTO $table $sql_values");
+    $result = db_query("INSERT INTO $table $sql_values");
     return $result['rows'];
 }
 
@@ -1572,36 +1851,36 @@ function db_insert ($table, $values, $ti
  * db_update
  * Action: Updates a specified table
  * Call: db_update (string table, string where_col, string where_value, array values [, array timestamp])
- * @param String - table name
- * @param String - column of WHERE condition
- * @param String - value of WHERE condition
- * @param array - key/value map of data to insert into the table.
- * @param array (optional) - array of fields to set to now() - default: array('modified')
+ * @param string $table - table name
+ * @param string $where_col - column of WHERE condition
+ * @param string $where_value - value of WHERE condition
+ * @param array $values - key/value map of data to insert into the table.
+ * @param array $timestamp (optional) - array of fields to set to now() - default: array('modified')
  * @return int - number of updated rows
  */
-function db_update ($table, $where_col, $where_value, $values, $timestamp = array('modified') ) {
+function db_update($table, $where_col, $where_value, $values, $timestamp = array('modified')) {
     $where = $where_col . " = '" . escape_string($where_value) . "'";
-    return db_update_q ($table, $where, $values, $timestamp );
+    return db_update_q($table, $where, $values, $timestamp);
 }
 
 /**
  * db_update_q
  * Action: Updates a specified table
  * Call: db_update_q (string table, string where, array values [, array timestamp])
- * @param String - table name
- * @param String - WHERE condition (as SQL)
- * @param array - key/value map of data to insert into the table.
- * @param array (optional) - array of fields to set to now() - default: array('modified')
+ * @param string $table - table name
+ * @param string $where - WHERE condition (as SQL)
+ * @param array $values - key/value map of data to insert into the table.
+ * @param array $timestamp (optional) - array of fields to set to now() - default: array('modified')
  * @return int - number of updated rows
  */
-function db_update_q ($table, $where, $values, $timestamp = array('modified') ) {
-    $table = table_by_key ($table);
+function db_update_q($table, $where, $values, $timestamp = array('modified')) {
+    $table = table_by_key($table);
 
-    foreach(array_keys($values) as $key) {
-        $sql_values[$key] = escape_string($key) . "='" . escape_string($values[$key]) . "'";
+    foreach ($values as $key => $value) {
+        $sql_values[$key] = $key . "='" . escape_string($value) . "'";
     }
 
-    foreach($timestamp as $key) {
+    foreach ($timestamp as $key) {
         if (db_sqlite()) {
             $sql_values[$key] = escape_string($key) . "=datetime('now')";
         } else {
@@ -1609,38 +1888,12 @@ function db_update_q ($table, $where, $v
         }
     }
 
-    $sql="UPDATE $table SET ".implode(",",$sql_values)." WHERE $where";
+    $sql="UPDATE $table SET " . implode(",", $sql_values) . " WHERE $where";
 
-    $result = db_query ($sql);
+    $result = db_query($sql);
     return $result['rows'];
 }
 
-/**
- * db_begin / db_commit / db_rollback
- * Action: BEGIN / COMMIT / ROLLBACK transaction (PostgreSQL only!)
- * Call: db_begin()
- */
-function db_begin () {
-    if (db_pgsql()) { # TODO: also enable for mysql? (not supported by MyISAM, which is used for most tables)
-        db_query('BEGIN');
-    }
-}
-
-function db_commit () {
-    if (db_pgsql()) {
-        db_query('COMMIT');
-    }
-}
-
-function db_rollback () {
-    if (db_pgsql()) {
-        db_query('ROLLBACK');
-    }
-}
-
-
-
-
 
 /**
  * db_log
@@ -1648,7 +1901,11 @@ function db_rollback () {
  * Call: db_log (string domain, string action, string data)
  * Possible actions are defined in $LANG["pViewlog_action_$action"]
  */
-function db_log ($domain,$action,$data) {
+function db_log($domain, $action, $data) {
+    if (!Config::bool('logging')) {
+        return true;
+    }
+
     $REMOTE_ADDR = getRemoteAddr();
 
     $username = authentication_get_username();
@@ -1657,19 +1914,18 @@ function db_log ($domain,$action,$data)
         die("Invalid log action : $action");   // could do with something better?
     }
 
-    if (Config::bool('logging')) {
-        $logdata = array(
-            'username'  => "$username ($REMOTE_ADDR)",
-            'domain'    => $domain,
-            'action'    => $action,
-            'data'      => $data,
-        );
-        $result = db_insert('log', $logdata, array('timestamp') );
-        if ($result != 1) {
-            return false;
-        } else {
-            return true;
-        }
+
+    $logdata = array(
+        'username'  => "$username ($REMOTE_ADDR)",
+        'domain'    => $domain,
+        'action'    => $action,
+        'data'      => $data,
+    );
+    $result = db_insert('log', $logdata, array('timestamp'));
+    if ($result != 1) {
+        return false;
+    } else {
+        return true;
     }
 }
 
@@ -1677,21 +1933,23 @@ function db_log ($domain,$action,$data)
  * db_in_clause
  * Action: builds and returns the "field in(x, y)" clause for database queries
  * Call: db_in_clause (string field, array values)
+ * @param string $field
+ * @param array $values
  */
 function db_in_clause($field, $values) {
-	return " $field IN ('"
-	. implode("','",escape_string(array_values($values)))
-	. "') ";
+    return " $field IN ('"
+    . implode("','", escape_string(array_values($values)))
+    . "') ";
 }
 
 /**
  * db_where_clause
  * Action: builds and returns a WHERE clause for database queries. All given conditions will be AND'ed.
  * Call: db_where_clause (array $conditions, array $struct)
- * param array $condition: array('field' => 'value', 'field2' => 'value2, ...)
- * param array $struct - field structure, used for automatic bool conversion
- * param string $additional_raw_where - raw sniplet to include in the WHERE part - typically needs to start with AND
- * param array $searchmode - operators to use (=, <, > etc.) - defaults to = if not specified for a field (see 
+ * @param array $condition - array('field' => 'value', 'field2' => 'value2, ...)
+ * @param array $struct - field structure, used for automatic bool conversion
+ * @param string $additional_raw_where - raw sniplet to include in the WHERE part - typically needs to start with AND
+ * @param array $searchmode - operators to use (=, <, > etc.) - defaults to = if not specified for a field (see
  *                           $allowed_operators for available operators)
  *                           Note: the $searchmode operator will only be used if a $condition for that field is set.
  *                                 This also means you'll need to set a (dummy) condition for NULL and NOTNULL.
@@ -1699,20 +1957,22 @@ function db_in_clause($field, $values) {
 function db_where_clause($condition, $struct, $additional_raw_where = '', $searchmode = array()) {
     if (!is_array($condition)) {
         die('db_where_cond: parameter $cond is not an array!');
-    } elseif(!is_array($searchmode)) {
+    } elseif (!is_array($searchmode)) {
         die('db_where_cond: parameter $searchmode is not an array!');
     } elseif (count($condition) == 0 && trim($additional_raw_where) == '') {
-        die("db_where_cond: parameter is an empty array!"); # die() might sound harsh, but can prevent information leaks 
-    } elseif(!is_array($struct)) {
+        die("db_where_cond: parameter is an empty array!"); # die() might sound harsh, but can prevent information leaks
+    } elseif (!is_array($struct)) {
         die('db_where_cond: parameter $struct is not an array!');
     }
 
-    $allowed_operators = explode(' ', '< > >= <= = != <> CONT LIKE NULL NOTNULL');
+    $allowed_operators = array('<', '>', '>=', '<=', '=', '!=', '<>', 'CONT', 'LIKE', 'NULL', 'NOTNULL');
     $where_parts = array();
     $having_parts = array();
 
-    foreach($condition as $field => $value) {
-        if (isset($struct[$field]) && $struct[$field]['type'] == 'bool') $value = db_get_boolean($value);
+    foreach ($condition as $field => $value) {
+        if (isset($struct[$field]) && $struct[$field]['type'] == 'bool') {
+            $value = db_get_boolean($value);
+        }
         $operator = '=';
         if (isset($searchmode[$field])) {
             if (in_array($searchmode[$field], $allowed_operators)) {
@@ -1737,7 +1997,7 @@ function db_where_clause($condition, $st
             $querypart = $field . $operator . "'" . escape_string($value) . "'";
         }
 
-        if($struct[$field]['select'] != '') {
+        if (!empty($struct[$field]['select'])) {
             $having_parts[$field] = $querypart;
         } else {
             $where_parts[$field] = $querypart;
@@ -1745,34 +2005,51 @@ function db_where_clause($condition, $st
     }
     $query = ' WHERE 1=1 ';
     $query .= " $additional_raw_where ";
-    if (count($where_parts)  > 0) $query .= " AND    ( " . join(" AND ", $where_parts)  . " ) ";
-    if (count($having_parts) > 0) $query .= " HAVING ( " . join(" AND ", $having_parts) . " ) ";
+    if (count($where_parts)  > 0) {
+        $query .= " AND    ( " . join(" AND ", $where_parts)  . " ) ";
+    }
+    if (count($having_parts) > 0) {
+        $query .= " HAVING ( " . join(" AND ", $having_parts) . " ) ";
+    }
 
-	return $query;
+    return $query;
 }
 
-//
-// table_by_key
-// Action: Return table name for given key
-// Call: table_by_key (string table_key)
-//
-function table_by_key ($table_key) {
+/**
+ * Convert a programmatic db table name into what may be the actual name.
+ *
+ * Takes into consideration any CONF database_prefix or database_tables map
+ *
+ * If it's a MySQL database, then we return the name with backticks around it (`).
+ *
+ * @param string database table name.
+ * @return string - database table name with appropriate prefix (and quoting if MySQL)
+ */
+function table_by_key($table_key) {
     global $CONF;
-    if (empty($CONF['database_tables'][$table_key])) {
-        $table = $table_key;
-    } else {
+
+    $table = $table_key;
+
+    if (!empty($CONF['database_tables'][$table_key])) {
         $table = $CONF['database_tables'][$table_key];
     }
 
-    return $CONF['database_prefix'].$table;
+    $table = $CONF['database_prefix'] . $table;
+
+    if (db_mysql()) {
+        return "`" . $table . "`";
+    }
+
+    return $table;
 }
 
+
 /*
  * check if the database layout is up to date
  * returns the current 'version' value from the config table
  * if $error_out is True (default), die() with a message that recommends to run setup.php.
  */
-function check_db_version($error_out = True) {
+function check_db_version($error_out = true) {
     global $min_db_version;
 
     $table = table_by_key('config');
@@ -1780,7 +2057,7 @@ function check_db_version($error_out = T
     $sql = "SELECT value FROM $table WHERE name = 'version'";
     $r = db_query($sql);
 
-    if($r['rows'] == 1) {
+    if ($r['rows'] == 1) {
         $row = db_assoc($r['result']);
         $dbversion = $row['value'];
     } else {
@@ -1788,7 +2065,7 @@ function check_db_version($error_out = T
         db_query("INSERT INTO $table (name, value) VALUES ('version', '0')", 0, '');
     }
 
-    if ( ($dbversion < $min_db_version) && $error_out == True) {
+    if (($dbversion < $min_db_version) && $error_out == true) {
         echo "ERROR: The PostfixAdmin database layout is outdated (you have r$dbversion, but r$min_db_version is expected).\nPlease run setup.php to upgrade the database.\n";
         exit(1);
     }
@@ -1796,47 +2073,14 @@ function check_db_version($error_out = T
     return $dbversion;
 }
 
-/*
-   Called after an alias_domain has been deleted in the DBMS.
-   Returns: boolean.
- */
-# TODO: This function is never called
-function alias_domain_postdeletion($alias_domain) {
-    global $CONF;
-    $confpar='alias_domain_postdeletion_script';
-
-    if (!isset($CONF[$confpar]) || empty($CONF[$confpar])) {
-        return true;
-    }
-
-    if (empty($alias_domain)) {
-        print '<p>Warning: empty alias_domain parameter.</p>';
-        return false;
-    }
-
-    $cmdarg1=escapeshellarg($alias_domain);
-    $command=$CONF[$confpar]." $cmdarg1";
-    $retval=0;
-    $output=array();
-    $firstline='';
-    $firstline=exec($command,$output,$retval);
-    if (0!=$retval) {
-        error_log("Running $command yielded return value=$retval, first line of output=$firstline");
-        print '<p>WARNING: Problems running alias_domain postdeletion script!</p>';
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
 //
 // gen_show_status
-// Action: Return a string of colored &nbsp;'s that indicate 
+// Action: Return a string of colored &nbsp;'s that indicate
 //         the if an alias goto has an error or is sent to
-//         addresses list in show_custom_domains 
+//         addresses list in show_custom_domains
 // Call: gen_show_status (string alias_address)
 //
-function gen_show_status ($show_alias) {
+function gen_show_status($show_alias) {
     global $CONF;
     $table_alias = table_by_key('alias');
     $stat_string = "";
@@ -1844,9 +2088,9 @@ function gen_show_status ($show_alias) {
     $show_alias = escape_string($show_alias);
 
     $stat_goto = "";
-    $stat_result = db_query ("SELECT goto FROM $table_alias WHERE address='$show_alias'");
+    $stat_result = db_query("SELECT goto FROM $table_alias WHERE address='$show_alias'");
     if ($stat_result['rows'] > 0) {
-        $row = db_row ($stat_result['result']);
+        $row = db_row($stat_result['result']);
         $stat_goto = $row[0];
     }
 
@@ -1856,77 +2100,89 @@ function gen_show_status ($show_alias) {
     }
 
     // UNDELIVERABLE CHECK
-    if ( $CONF['show_undeliverable'] == 'YES' ) {
+    if ($CONF['show_undeliverable'] == 'YES') {
         $gotos=array();
-        $gotos=explode(',',$stat_goto);
+        $gotos=explode(',', $stat_goto);
         $undel_string="";
 
         //make sure this alias goes somewhere known
         $stat_ok = 1;
-        while ( ($g=array_pop($gotos)) && $stat_ok ) {
-            list(/*NULL*/,$stat_domain) = explode('@',$g);
+        foreach ($gotos as $g) {
+            if (!$stat_ok) {
+                break;
+            }
+            if (strpos($g, '@') === false) {
+                continue;
+            }
+
+            list($local_part, $stat_domain) = explode('@', $g);
+
             $stat_delimiter = "";
-			if (!empty($CONF['recipient_delimiter'])) {
-				$stat_delimiter = "OR address = '" . escape_string(preg_replace($delimiter_regex, "@", $g)) . "'";
-			}
-			$stat_result = db_query ("SELECT address FROM $table_alias WHERE address = '" . escape_string($g) . "' OR address = '@" . escape_string($stat_domain) . "' $stat_delimiter");
+            if (!empty($CONF['recipient_delimiter'])) {
+                $stat_delimiter = "OR address = '" . escape_string(preg_replace($delimiter_regex, "@", $g)) . "'";
+            }
+            $stat_result = db_query("SELECT address FROM $table_alias WHERE address = '" . escape_string($g) . "' OR address = '@" . escape_string($stat_domain) . "' $stat_delimiter");
             if ($stat_result['rows'] == 0) {
                 $stat_ok = 0;
             }
-            if ( $stat_ok == 0 ) {
-                if ( $stat_domain == $CONF['vacation_domain'] || in_array($stat_domain, $CONF['show_undeliverable_exceptions']) ) {
+            if ($stat_ok == 0) {
+                if ($stat_domain == $CONF['vacation_domain'] || in_array($stat_domain, $CONF['show_undeliverable_exceptions'])) {
                     $stat_ok = 1;
                 }
             }
         } // while
-        if ( $stat_ok == 0 ) {
-            $stat_string .= "<span style='background-color:" . $CONF['show_undeliverable_color'] .
-                "'>" . $CONF['show_status_text'] . "</span>&nbsp;";
+        if ($stat_ok == 0) {
+            $stat_string .= "<span style='background-color:" . $CONF['show_undeliverable_color'] . "'>" . $CONF['show_status_text'] . "</span>&nbsp;";
         } else {
             $stat_string .= $CONF['show_status_text'] . "&nbsp;";
-        } 
+        }
     }
 
     // POP/IMAP CHECK
-    if ( $CONF['show_popimap'] == 'YES' ) {
-		 $stat_delimiter = "";
-		 if (!empty($CONF['recipient_delimiter'])) {
-			 $stat_delimiter = ',' . preg_replace($delimiter_regex, "@", $stat_goto);
-		 }
+    if ($CONF['show_popimap'] == 'YES') {
+        $stat_delimiter = "";
+        if (!empty($CONF['recipient_delimiter'])) {
+            $stat_delimiter = ',' . preg_replace($delimiter_regex, "@", $stat_goto);
+        }
 
         //if the address passed in appears in its own goto field, its POP/IMAP
         # TODO: or not (might also be an alias loop) -> check mailbox table!
-        if ( preg_match ('/,' . $show_alias . ',/', ',' . $stat_goto . $stat_delimiter . ',') ) {
+        if (preg_match('/,' . $show_alias . ',/', ',' . $stat_goto . $stat_delimiter . ',')) {
             $stat_string .= "<span  style='background-color:" . $CONF['show_popimap_color'] .
                 "'>" . $CONF['show_status_text'] . "</span>&nbsp;";
         } else {
             $stat_string .= $CONF['show_status_text'] . "&nbsp;";
-        } 
+        }
     }
 
     // CUSTOM DESTINATION CHECK
-    if ( count($CONF['show_custom_domains']) > 0 ) {
-        for ($i = 0; $i < sizeof ($CONF['show_custom_domains']); $i++) {
-            if (preg_match ('/^.*' . $CONF['show_custom_domains'][$i] . '.*$/', $stat_goto)) {
+    if (count($CONF['show_custom_domains']) > 0) {
+        for ($i = 0; $i < sizeof($CONF['show_custom_domains']); $i++) {
+            if (preg_match('/^.*' . $CONF['show_custom_domains'][$i] . '.*$/', $stat_goto)) {
                 $stat_string .= "<span  style='background-color:" . $CONF['show_custom_colors'][$i] .
                     "'>" . $CONF['show_status_text'] . "</span>&nbsp;";
             } else {
                 $stat_string .= $CONF['show_status_text'] . "&nbsp;";
-            } 
-        } 
+            }
+        }
     } else {
         $stat_string .= ";&nbsp;";
-    } 
+    }
 
     //   $stat_string .= "<span style='background-color:green'> &nbsp; </span> &nbsp;" .
     //                  "<span style='background-color:blue'> &nbsp; </span> &nbsp;";
     return $stat_string;
 }
 
+/**
+ * @return string
+ */
 function getRemoteAddr() {
     $REMOTE_ADDR = 'localhost';
-    if (isset($_SERVER['REMOTE_ADDR'])) 
+    if (isset($_SERVER['REMOTE_ADDR'])) {
         $REMOTE_ADDR = $_SERVER['REMOTE_ADDR'];
+    }
+
     return $REMOTE_ADDR;
 }
 
diff -pruN 3.0.2-2/.gitignore 3.2-2/.gitignore
--- 3.0.2-2/.gitignore	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/.gitignore	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,5 @@
+/config.local.php
+/templates_c/*.tpl.php
+/templates_c/*menu.conf.php
+/vendor/
+/.php_cs.cache
Binary files 3.0.2-2/images/arrow-l.png and 3.2-2/images/arrow-l.png differ
Binary files 3.0.2-2/images/arrow-r.png and 3.2-2/images/arrow-r.png differ
Binary files 3.0.2-2/images/arrow-u.png and 3.2-2/images/arrow-u.png differ
Binary files 3.0.2-2/images/calendar/cal.gif and 3.2-2/images/calendar/cal.gif differ
Binary files 3.0.2-2/images/calendar/next_mon.gif and 3.2-2/images/calendar/next_mon.gif differ
Binary files 3.0.2-2/images/calendar/next_year.gif and 3.2-2/images/calendar/next_year.gif differ
Binary files 3.0.2-2/images/calendar/no_cal.gif and 3.2-2/images/calendar/no_cal.gif differ
Binary files 3.0.2-2/images/calendar/pixel.gif and 3.2-2/images/calendar/pixel.gif differ
Binary files 3.0.2-2/images/calendar/prev_mon.gif and 3.2-2/images/calendar/prev_mon.gif differ
Binary files 3.0.2-2/images/calendar/prev_year.gif and 3.2-2/images/calendar/prev_year.gif differ
Binary files 3.0.2-2/images/calendar/shade_bl.png and 3.2-2/images/calendar/shade_bl.png differ
Binary files 3.0.2-2/images/calendar/shade_bm.png and 3.2-2/images/calendar/shade_bm.png differ
Binary files 3.0.2-2/images/calendar/shade_br.png and 3.2-2/images/calendar/shade_br.png differ
Binary files 3.0.2-2/images/calendar/shade_mr.png and 3.2-2/images/calendar/shade_mr.png differ
Binary files 3.0.2-2/images/calendar/shade_tr.png and 3.2-2/images/calendar/shade_tr.png differ
diff -pruN 3.0.2-2/images/index.php 3.2-2/images/index.php
--- 3.0.2-2/images/index.php	2007-11-11 23:36:46.000000000 +0000
+++ 3.2-2/images/index.php	1970-01-01 00:00:00.000000000 +0000
@@ -1,17 +0,0 @@
-<?php
-//
-// File: index.php
-//
-// Template File: -none-
-//
-// Template Variables:
-//
-// -none-
-//
-// Form POST \ GET Variables:
-//
-// -none-
-//
-header ("Location: ../login.php");
-exit;
-?>
Binary files 3.0.2-2/images/logo-default.png and 3.2-2/images/logo-default.png differ
Binary files 3.0.2-2/images/mail_bg.gif and 3.2-2/images/mail_bg.gif differ
Binary files 3.0.2-2/images/postbox.png and 3.2-2/images/postbox.png differ
Binary files 3.0.2-2/images/postfixadmin2.png and 3.2-2/images/postfixadmin2.png differ
Binary files 3.0.2-2/images/postfixadmin2.xcf and 3.2-2/images/postfixadmin2.xcf differ
Binary files 3.0.2-2/images/postfixadmin.png and 3.2-2/images/postfixadmin.png differ
Binary files 3.0.2-2/images/quota-colors.png and 3.2-2/images/quota-colors.png differ
diff -pruN 3.0.2-2/index.php 3.2-2/index.php
--- 3.0.2-2/index.php	2013-11-10 15:57:32.000000000 +0000
+++ 3.2-2/index.php	2018-05-02 20:37:27.000000000 +0000
@@ -1,89 +1,9 @@
-<?php
-/** 
- * Postfix Admin 
- * 
- * LICENSE 
- * This source file is subject to the GPL license that is bundled with  
- * this package in the file LICENSE.TXT. 
- * 
- * Further details on the project are available at http://postfixadmin.sf.net 
- * 
- * @version $Id: index.php 1558 2013-11-10 15:57:32Z christian_boltz $ 
- * @license GNU GPL v2 or later. 
- * 
- * File: index.php
- * Shows a sort-of welcome page.
- * Template File: -none-
- *
- * Template Variables: -none-
- *
- * Form POST \ GET Variables: -none-
- */
-
-$CONF['configured'] = FALSE;
-@include_once('config.inc.php'); # hide error message because only $CONF['configured'] is checked here
-if ( $CONF['configured'] === TRUE )
-{
-    header ("Location: login.php");
-    exit;
-}
-?>
-
 <html>
-    <head>
-        <title>Welcome to Postfix Admin</title>
-    </head>
-    <body>
-        <img id="login_header_logo" src="images/logo-default.png" />
-        <h1>Welcome to Postfix Admin</h1>
-        <h2>What is it?</h2>
-        <p>Postfix Admin is a web based interface to configure and manage a Postfix based email server for many users.</p>
-        <p>Postfix Admin can also be used to </p>
-        <ul>
-            <li>Forward email to other addresses</li>
-            <li>Configure vacation/out-of-office auto responses</li>
-            <li>Add/edit/remove mail accounts</li>
-            <li>Add/edit/remove domains</li>
-            <li>Broadcast emails to all users of the system</li>
-            <li>Set quota on mailboxes</li>
-            <li>And more...</li>
-        </ul>
-
-        <h2>Licensing</h2>
-        <p>Postfix admin is released under the following license :</p>
-
-        <code>
-        This program is free software; you can redistribute it and/or modify
-        it under the terms of the GNU General Public License 2 as published by 
-        the Free Software Foundation. 
-        </code>
-
-        <p>See the following <a href="http://www.fsf.org/licenses/gpl-2.0.txt">FSF GPL2 page</a> for further information on the license.</p>
-
-        <h2>What now?</h2>
-
-        <ol>
-            <li>Read the <a href='INSTALL.TXT'>INSTALL.txt</a> file</li>
-            <li>Configure Postfix to use your chosen database - see (for example) the following pages :
-            <ul>
-                <li><a href="http://codepoets.co.uk/postfixadmin-postgresql-courier-squirrelmail-debian-etch-howto-tutorial">Postfix/PostgreSQL/Postfixadmin/Courier</a></li>
-                <li><a href="http://bliki.rimuhosting.com/space/knowledgebase/linux/mail/postfixadmin+on+debian+sarge">Postfix/MySQL/Postfixadmin/Dovecot</a></li>
-                <li><a href="http://gentoo-wiki.com/HOWTO_Setup_a_Virtual_Postfix/Courier_Mail_System_with_PostfixAdmin">Postfix/MySQL/Postfixamdin/Courier</a></li>
-            </ul>
-            <li>Use it</li>
-        </ol>
-        
-        <p><b>When you have configured Postfixadmin, this page will be replaced with a login page.</b></p>
-        <p>You can now run <a href="setup.php">setup</a> to make sure that all the PHP functions are available for Postfix Admin to run.<br />
-        <p> If you still encounter any problems, please check the documentation and website for more information.</p>
-        <h2>Postfix Admin Web sites</h2>
-        <p>For further help, or documentation please check out -
-        <a href="http://postfixadmin.org">Postfix Admin</a> web site<br />
-        <a href="http://sourceforge.net/forum/forum.php?forum_id=676076">Knowledge Base</a>
-        </p>
-        </p>
-    </body>
+<head>
+    <title>Postfix Admin</title>
+</head>
+<body>
+    <p>The Postfix Admin directory layout changed.</p>
+    <p>Please update your webserver config so that the DocumentRoot or Alias points to the directory "public".</p>
+</body>
 </html>
-<?php
-/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */
-?>
diff -pruN 3.0.2-2/INSTALL.TXT 3.2-2/INSTALL.TXT
--- 3.0.2-2/INSTALL.TXT	2016-10-20 21:26:13.000000000 +0000
+++ 3.2-2/INSTALL.TXT	2018-05-02 20:37:27.000000000 +0000
@@ -5,12 +5,16 @@
 # Licensed under GPL for more info check GPL-LICENSE.TXT
 #
 
-REQUIRED!!
-----------
-- You are using Postfix 2.0 or higher.
-- You are using Apache 1.3.27 / Lighttpd 1.3.15 or higher.
-- You are using PHP 5.1.2 or higher.
-- You are using MySQL 3.23 or higher (5.x recommended) OR PostgreSQL 7.4 (or higher)
+REQUIREMENTS
+------------
+- Postfix 2.0 or higher.
+- Apache 1.3.27 / Lighttpd 1.3.15 or higher.
+- PHP 5.1.2 or higher.
+- one of the following databases:
+  - MySQL 3.23 or higher (5.x recommended)
+  - MariaDB (counts as MySQL ;-)
+  - PostgreSQL 7.4 (or higher)
+  - SQLite 3.12 (or higher)
 
 
 READ THIS FIRST!
@@ -36,13 +40,26 @@ DOCUMENTS/ folder.
 
 1. Unarchive new Postfix Admin
 ------------------------------
-Make sure that you are in your WWW directory and then unarchive the
-Postfix Admin archive (whatever the filename is):
 
-  $ tar -zxvf postfixadmin-$version.tgz
+(if you installed PostfixAdmin as RPM or DEB package, you can obviously skip this step.)
 
+Assuming we are installing Postfixadmin into /srv/postfixadmin, then something like this should work :
 
-2. Setup a Database
+  $ mkdir -p /srv/postfixadmin
+  $ cd /srv/postfixadmin 
+  $ wget -O https://github.com/postfixadmin/postfixadmin/archive/postfixadmin-3.1.tar.gz postfixadmin-3.1.tar.gz
+  $ tar -zxvf postfixadmin-version.tgz
+
+
+2. Setup Web Server
+-------------------
+
+Assuming /var/www/html is where your webserver reads from :
+
+  $ ln -s /srv/postfixadmin/public /var/www/html/postfixadmin 
+
+
+3. Setup a Database
 -------------------
 
 With your chosen/preferred database server (i.e. MySQL or PostgreSQL), 
@@ -66,10 +83,10 @@ For PostgreSQL:
   CREATE DATABASE postfix OWNER postfix ENCODING 'unicode';
 
 
-3. Configure PostfixAdmin so it can find the database
+4. Configure PostfixAdmin so it can find the database
 -----------------------------------------------------
 
-Create a config.local.php file for your local configuration:
+Create /srv/postfixadmin/config.local.php file for your local configuration:
 
 <?php
 $CONF['database_type'] = 'mysqli';
@@ -97,14 +114,16 @@ $CONF['configured'] = true;
 
 
 PostfixAdmin does not require write access to any files except the templates_c 
-directory (smarty cache). You can therefore leave the files owned as root (or
+directory (smarty cache). You can therefore leave the files owned by root (or
 another user); as long as the web server user (e.g. www-data) can read them, it
 will be fine.
 For templates_c/, allow write access (only) for the web server user (e. g. www-data).
-The easiest way to do this is   chown -R www-data templates_c
+The easiest way to do this is   
+
+ $ chown -R www-data /srv/postfixadmin/templates_c
 
 
-4. Check settings, and create Admin user
+5. Check settings, and create Admin user
 ----------------------------------------
 
 Hit http://yourserver.tld/postfixadmin/setup.php in a web browser.
@@ -121,13 +140,13 @@ out - with appropriate instructions on w
 
 create the admin user using the form displayed.
 
-5. Use PostfixAdmin
+6. Use PostfixAdmin
 -------------------
 
 This is all that is needed. Fire up your browser and go to the site that you
 specified to host Postfix Admin.
 
-6. Integration with Postfix, Dovecot etc.
+7. Integration with Postfix, Dovecot etc.
 -----------------------------------------
 
 Now that PostfixAdmin is working, you need to do some configuration in Postfix,
@@ -151,9 +170,13 @@ You'll need to enable the xmlrpc link (s
 
 8. More information
 -------------------
-As of March 2007, PostfixAdmin moved to SourceForge.  For the
-forum posts and source updates, see:
 
-https://sourceforge.net/projects/postfixadmin
+The code and issue tracker is on GitHub:
+    https://github.com/postfixadmin/postfixadmin
+
+IRC - a community of people may be able to help in #postfixadmin on irc.freenode.net. 
+    See http://webchat.freenode.net/
+
+Legacy forum posts are on SourceForce at 
+    https://sourceforge.net/projects/postfixadmin
 
-There is also #postfixadmin on irc.freenode.net.
diff -pruN 3.0.2-2/languages/bg.lang 3.2-2/languages/bg.lang
--- 3.0.2-2/languages/bg.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/bg.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: bg.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Bulgarian
 // by Plamen Tonev
@@ -38,13 +38,13 @@ $PALANG['edit_not_allowed'] = 'You are n
 $PALANG['searchparams'] = 'Search parameters:'; # XXX
 $PALANG['pFooter_logged_as'] = 'ÐŸÐ¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ» %s'; # XXX # XXX Text change: 'logged in as %s' (the 'in' was missing)
 
-$PALANG['pLogin_welcome'] = 'ÐÐ´Ð¼Ð¸Ð½Ð¸ÑÑ‚Ñ€Ð°Ñ‚Ð¾Ñ€Ð° Ð¼Ð¾Ð¶Ðµ Ð´Ð° ÑÐµ Ð»Ð¾Ð³Ð½Ðµ Ð¾Ñ‚Ñ‚ÑƒÐº Ð·Ð° Ð°Ð´Ð¼Ð¸Ð½Ð¸ÑÑ‚Ñ€Ð¸Ñ€Ð°Ð½Ðµ Ð½Ð° Ð´Ð¾Ð¼ÐµÐ¹Ð½.';
-$PALANG['pLogin_username'] = 'Ð›Ð¾Ð³Ð¸Ð½ (Ðµ-Ð¼ÐµÐ¹Ð»)';
+$PALANG['pLogin_welcome'] = 'ÐÐ´Ð¼Ð¸Ð½Ð¸ÑÑ‚Ñ€Ð°Ñ‚Ð¾Ñ€ÑŠÑ‚ Ð¼Ð¾Ð¶Ðµ Ð´Ð° ÑÐµ Ð»Ð¾Ð³Ð½Ðµ Ð¾Ñ‚Ñ‚ÑƒÐº, Ð·Ð° Ð°Ð´Ð¼Ð¸Ð½Ð¸ÑÑ‚Ñ€Ð¸Ñ€Ð°Ð½Ðµ Ð½Ð° Ð´Ð¾Ð¼ÐµÐ¹Ð½.';
+$PALANG['pLogin_username'] = "&nbsp;Ð›Ð¾Ð³Ð¸Ð½ (Ðµ-Ð¼ÐµÐ¹Ð»)";
 $PALANG['password'] = 'ÐŸÐ°Ñ€Ð¾Ð»Ð°';
 $PALANG['pLogin_language'] = 'Language'; # XXX
 $PALANG['pLogin_button'] = 'Ð˜Ð·Ñ…Ð¾Ð´'; # XXX compare with pUsersLogin_button - should be "Login"
 $PALANG['pLogin_failed'] = 'Your email address or password are not correct.'; # XXX
-$PALANG['pLogin_login_users'] = 'ÐÐºÐ¾ ÑÑ‚Ðµ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ» Ð½Ð°Ñ‚Ð¸ÑÐ½ÐµÑ‚Ðµ Ñ‚ÑƒÐº Ð·Ð° Ð»Ð¾Ð³Ð²Ð°Ð½Ðµ Ð² Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»ÑÐºÐ°Ñ‚Ð° Ñ‡Ð°ÑÑ‚.';
+$PALANG['pLogin_login_users'] = 'ÐÐºÐ¾ ÑÑ‚Ðµ Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ», Ð½Ð°Ñ‚Ð¸ÑÐ½ÐµÑ‚Ðµ Ñ‚ÑƒÐº, Ð·Ð° Ð»Ð¾Ð³Ð²Ð°Ð½Ðµ Ð² Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»ÑÐºÐ°Ñ‚Ð° Ñ‡Ð°ÑÑ‚.';
 
 $PALANG['pMenu_main'] = 'Main'; # XXX
 $PALANG['pMenu_overview'] = 'ÐŸÑ€ÐµÐ³Ð»ÐµÐ´';
@@ -144,6 +144,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Ð’Ð¸Ðµ ÑÑ‚Ðµ Ð´Ð¾ÑÑ‚Ð¸Ð³Ð½Ð°Ð»Ð¸ ÑÐ²Ð¾Ñ Ð»Ð¸Ð¼Ð¸Ñ‚ Ð·Ð° ÑÑŠÐ·Ð´Ð°Ð²Ð°Ð½Ðµ Ð½Ð° Ð¿Ð¾Ñ‰ÐµÐ½ÑÐºÐ¸ ÐºÑƒÑ‚Ð¸Ð¸!';
 $PALANG['pCreate_mailbox_password_text'] = 'ÐŸÐ°Ñ€Ð¾Ð»Ð° Ð·Ð° POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'ÐŸÑŠÐ»Ð½Ð¾ Ð¸Ð¼Ðµ';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Ð¡ÑŠÐ·Ð´Ð°Ð¹ Ð¿Ð¾Ñ‰ÐµÐ½ÑÐºÐ° ÐºÑƒÑ‚Ð¸Ñ'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'ÐÐµ Ð¼Ð¾Ð³Ð° Ð´Ð° Ð´Ð¾Ð±Ð°Ð²Ñ Ð¿Ð¾Ñ‰ÐµÐ½ÑÐºÐ°Ñ‚Ð° ÐºÑƒÑ‚Ð¸Ñ Ð² Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð°Ñ‚Ð°! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'ÐŸÐ¾Ñ‰ÐµÐ½ÑÐºÐ°Ñ‚Ð° ÐºÑƒÑ‚Ð¸Ñ Ð±Ðµ ÑƒÑÐ¿ÐµÑˆÐ½Ð¾ ÑÑŠÐ·Ð´Ð°Ð´ÐµÐ½Ð° Ð¸ Ð´Ð¾Ð±Ð°Ð²ÐµÐ½Ð° Ð² Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð°Ñ‚Ð°! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -171,6 +175,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Ð¡Ð¼ÐµÐ½Ð¸ Ð¿Ð°Ñ€Ð¾Ð»Ð°';
 $PALANG['pPassword_result_error'] = 'ÐÐµ Ð¼Ð¾Ð³Ð° Ð´Ð° ÑÐ¼ÐµÐ½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ð°Ñ‚Ð°! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'ÐŸÐ°Ñ€Ð¾Ð»Ð°Ñ‚Ð° Ð²Ð¸ Ð±Ðµ ÑÐ¼ÐµÐ½ÐµÐ½Ð° ÑƒÑÐ¿ÐµÑˆÐ½Ð¾! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -186,7 +197,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Ð Ð°Ð·Ð³Ð»ÐµÐ¶Ð´Ð°Ð½Ðµ Ð½Ð° Ð¿Ð¾ÑÐ»ÐµÐ´Ð½Ð¸Ñ‚Ðµ 10 Ð´ÐµÐ¹ÑÑ‚Ð²Ð¸Ñ Ð·Ð° ';
+$PALANG['pViewlog_welcome'] = 'Ð Ð°Ð·Ð³Ð»ÐµÐ¶Ð´Ð°Ð½Ðµ Ð½Ð° Ð¿Ð¾ÑÐ»ÐµÐ´Ð½Ð¸Ñ‚Ðµ %s Ð´ÐµÐ¹ÑÑ‚Ð²Ð¸Ñ Ð·Ð° ';
 $PALANG['pViewlog_timestamp'] = 'Ð”Ð°Ñ‚Ð°';
 $PALANG['pViewlog_action'] = 'Ð”ÐµÐ¹ÑÑ‚Ð²Ð¸Ðµ';
 $PALANG['pViewlog_data'] = 'Ð”Ð°Ð½Ð½Ð¸';
@@ -292,6 +303,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'ÐŸÐ¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»ÑÐºÐ¸ Ð²Ñ…Ð¾Ð´ Ð·Ð° ÑÐ¼ÑÐ½Ð° Ð½Ð° Ð¿Ð°Ñ€Ð¾Ð»Ð° Ð¸ alias-Ð¸.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Ð’Ð°ÑˆÐ¸ÑÑ‚ Ð»Ð¾Ð³Ð¸Ð½ Ð½Ðµ Ðµ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÐµÐ½. ÐœÐ¾Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐµÑ‚Ðµ Ð·Ð° ÐºÐ¾Ñ€ÐµÐºÑ‚Ð½Ð¾ÑÑ‚ Ð½Ð° Ð²Ð°ÑˆÐ¸ÑÑ‚ Ðµ-Ð¼ÐµÐ¹Ð» Ð°Ð´Ñ€ÐµÑ!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Ð’Ð°ÑˆÐ°Ñ‚Ð° Ð¿Ð°Ñ€Ð¾Ð»Ð° Ð½Ðµ Ðµ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð½Ð°!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'ÐÐ²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÐ½ Ð¾Ñ‚Ð³Ð¾Ð²Ð¾Ñ€';
 $PALANG['pUsersMenu_edit_alias'] = 'Ð¡Ð¼ÑÐ½Ð° Ð½Ð° Ð¿Ñ€ÐµÐ½Ð°ÑÐ¾Ñ‡Ð²Ð°Ð½ÐµÑ‚Ð¾';
@@ -323,6 +335,8 @@ $PALANG['pBroadcast_name'] = 'Ð˜Ð¼Ðµ';
 $PALANG['pBroadcast_success'] = 'Ð’Ð°ÑˆÐµÑ‚Ð¾ ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ðµ Ð±ÐµÑˆÐµ Ð¸Ð·Ð¿Ñ€Ð°Ñ‚ÐµÐ½Ð¾.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Ð¡ÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ðµ Ð´Ð¾ Ð²ÑÐ¸Ñ‡ÐºÐ¸';
 $PALANG['pBroadcast_error_empty'] = 'ÐŸÐ¾Ð»ÐµÑ‚Ð°Ñ‚Ð° Ð˜Ð¼Ðµ, Ð—Ð°Ð³Ð»Ð°Ð²Ð¸Ðµ Ð¸ Ð¡ÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ðµ ÑÐ° Ð·Ð°Ð´ÑŠÐ»Ð¶Ð¸Ñ‚ÐµÐ»Ð½Ð¸!';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/ca.lang 3.2-2/languages/ca.lang
--- 3.0.2-2/languages/ca.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/ca.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: ca.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Catalan
 // by Jaume
@@ -142,6 +142,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Has arribat al lÃ­mit de creaciÃ³ de bÃºsties!';
 $PALANG['pCreate_mailbox_password_text'] = 'Contrasenya per a POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Nom complet';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Crear bÃºstia'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Imposible afegir una bÃºstia a la taula de bÃºsties! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'La bÃºstia ha estat afegida a la taula de bÃºsties! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -169,6 +173,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Canviar la contrasenya';
 $PALANG['pPassword_result_error'] = 'Imposible canviar la contrasenya! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'La seva contrasenya ha estat canviada! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -184,7 +195,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Veure les Ãºltimes 10 accions per ';
+$PALANG['pViewlog_welcome'] = 'Veure les Ãºltimes %s accions per ';
 $PALANG['pViewlog_timestamp'] = 'Data/Hora';
 $PALANG['pViewlog_action'] = 'AcciÃ³';
 $PALANG['pViewlog_data'] = 'Dades';
@@ -291,6 +302,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Login d\'usuaris per canviar la contrasenya i els Ã lies.';
 $PALANG['pUsersLogin_username_incorrect'] = 'El seu login no Ã©s correcte. Asseguri\'s d\'haver introduÃ¯t la seva adreÃ§a d\'e-mail com a login!';
 $PALANG['pUsersLogin_password_incorrect'] = 'La seva contrasenya no Ã©s correcta!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Resposta automÃ tica';
 $PALANG['pUsersMenu_edit_alias'] = 'Canviar la redirecciÃ³';
@@ -322,6 +334,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.'; # XXX
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/cn.lang 3.2-2/languages/cn.lang
--- 3.0.2-2/languages/cn.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/cn.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: cn.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Simplified Chinese
 // by Matthew <matthew at cnfug dot org>
@@ -143,6 +143,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'é‚®ç®±åœ°å€å·²ç»è¾¾åˆ°ä¸Šé™!';
 $PALANG['pCreate_mailbox_password_text'] = 'POP3/IMAP å¯†ç ';
 $PALANG['pCreate_mailbox_name_text'] = 'å…¨å';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'æ–°å»ºé‚®ç®±'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'ä¸èƒ½å°†é‚®ç®±å¢žåŠ åˆ°é‚®ç®±è¡¨ä¸­! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'å¢žåŠ é‚®ç®±æˆåŠŸ! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -170,6 +174,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'æ›´æ”¹å¯†ç '; # XXX check text - should be 'Change Password'
 $PALANG['pPassword_result_error'] = 'æ›´æ”¹å¯†ç å¤±è´¥! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'æ›´æ”¹å¯†ç æˆåŠŸ! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -185,7 +196,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'æŸ¥çœ‹æœ€æ–°çš„10é¡¹æ“ä½œæ—¥å¿— åŸŸå: ';
+$PALANG['pViewlog_welcome'] = 'æŸ¥çœ‹æœ€æ–°çš„%sé¡¹æ“ä½œæ—¥å¿— åŸŸå: ';
 $PALANG['pViewlog_timestamp'] = 'æ—¶é—´';
 $PALANG['pViewlog_action'] = 'æ“ä½œ';
 $PALANG['pViewlog_data'] = 'å†…å®¹';
@@ -291,6 +302,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'é‚®ä»¶ç”¨æˆ·ä»Žè¿™é‡Œç™»å½•ç®¡ç†ä½ çš„å¯†ç å’Œåˆ«å.';
 $PALANG['pUsersLogin_username_incorrect'] = 'ç™»å½•å¤±è´¥. è¯·ç¡®è®¤ä½ æ˜¯ä½¿ç”¨ä½ çš„é‚®ç®±åœ°å€ç™»å½•!';
 $PALANG['pUsersLogin_password_incorrect'] = 'ç™»å½•å¯†ç ä¸æ­£ç¡®!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'è‡ªåŠ¨å›žå¤';
 $PALANG['pUsersMenu_edit_alias'] = 'ä¿®æ”¹è½¬å‘';
@@ -322,6 +334,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.'; # XXX
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/cs.lang 3.2-2/languages/cs.lang
--- 3.0.2-2/languages/cs.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/cs.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: cs.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Czech Language Translation of PostfixAdmin
 // by Jakub
@@ -9,6 +9,8 @@
 // updated by Jan Laufik (jlaufik @ sf)
 //  * 2015-01-10
 //  * 2016-02-16
+// updated by Matyas Koc (admin@sufix.cz)
+//  * 2017-07-12
 
 $PALANG['YES'] = 'ANO';
 $PALANG['NO'] = 'NE';
@@ -39,7 +41,7 @@ $PALANG['must_be_numeric_bigger_than_nul
 $PALANG['must_be_boolean'] = '%s musÃ­ bÃ½t typu boolean';
 $PALANG['invalid_value_given'] = 'ZadÃ¡na nesprÃ¡vnÃ¡ hodnota pro %s';
 $PALANG['edit_not_allowed'] = 'NemÃ¡te oprÃ¡vnÄ›nÃ­ ke zmÄ›nÄ› %s';
-$PALANG['searchparams'] = 'Parametre vyhledÃ¡vÃ¡nÃ­:';
+$PALANG['searchparams'] = 'Parametry vyhledÃ¡vÃ¡nÃ­:';
 
 $PALANG['pFooter_logged_as'] = 'PÅ™ihlÃ¡Å¡en jako %s';
 
@@ -60,7 +62,7 @@ $PALANG['pMenu_fetchmail'] = 'StahovÃ¡nÃ
 $PALANG['pMenu_sendmail'] = 'Poslat email';
 $PALANG['pMenu_password'] = 'ZmÄ›nit heslo';
 $PALANG['pMenu_viewlog'] = 'ProhlÃ­Å¾et log';
-$PALANG['pMenu_logout'] = 'OdhlÃ¡sit.';
+$PALANG['pMenu_logout'] = 'OdhlÃ¡sit';
 
 $PALANG['pMain_welcome'] = 'VÃ­tejte v Postfix Adminu!';
 $PALANG['pMain_overview'] = 'VÃ½pis pÅ™esmÄ›rovÃ¡nÃ­ a schrÃ¡nek. MÅ¯Å¾ete je zde upravovat a mazat.';
@@ -71,12 +73,12 @@ $PALANG['pMain_password'] = 'ZmÄ›nit hes
 $PALANG['pMain_viewlog'] = 'ProhlÃ­Å¾et zÃ¡znamy zmÄ›n v domÃ©nÄ›.';
 $PALANG['pMain_logout'] = 'OdhlÃ¡sit ze systÃ©mu.';
 
-$PALANG['pOverview_disabled'] = 'ZakÃ¡zÃ¡no';
-$PALANG['pOverview_unlimited'] = 'NeomezenÃ©';
-$PALANG['pOverview_title'] = ':: DefinovanÃ© DomÃ©ny';
-$PALANG['pOverview_up_arrow'] = 'Na ZaÄÃ¡tek';
-$PALANG['pOverview_right_arrow'] = 'DalÅ¡Ã­ StrÃ¡nka';
-$PALANG['pOverview_left_arrow'] = 'PÅ™edchozÃ­ StrÃ¡nka';
+$PALANG['pOverview_disabled'] = 'zakÃ¡zÃ¡no';
+$PALANG['pOverview_unlimited'] = 'neomezenÃ©';
+$PALANG['pOverview_title'] = ':: DefinovanÃ© domÃ©ny';
+$PALANG['pOverview_up_arrow'] = 'Na zaÄÃ¡tek';
+$PALANG['pOverview_right_arrow'] = 'DalÅ¡Ã­ strÃ¡nka';
+$PALANG['pOverview_left_arrow'] = 'PÅ™edchozÃ­ strÃ¡nka';
 $PALANG['pOverview_alias_domain_title'] = ':: PÅ™esmÄ›rovÃ¡nÃ­ domÃ©n';
 $PALANG['pOverview_alias_title'] = ':: PÅ™esmÄ›rovÃ¡nÃ­';
 $PALANG['pOverview_mailbox_title'] = ':: SchrÃ¡nky';
@@ -91,7 +93,7 @@ $PALANG['name'] = 'JmÃ©no';
 $PALANG['pOverview_mailbox_quota'] = 'MÃ­sto (MB)';
 $PALANG['pOverview_vacation_edit'] = 'ZAPNUTO';
 $PALANG['pOverview_vacation_option'] = 'vypnuto';
-$PALANG['no_domains_for_this_admin'] = 'NemÃ¡te oprÃ¡vnÄ›nÃ­ ke zprÃ¡vÄ› Å¾Ã¡dnÃ© z domÃ©n.';
+$PALANG['no_domains_for_this_admin'] = 'NemÃ¡te oprÃ¡vnÄ›nÃ­ ke sprÃ¡vÄ› Å¾Ã¡dnÃ© z domÃ©n.';
 $PALANG['no_domains_exist'] = 'MusÃ­te vytvoÅ™it alespoÅˆ jednu domÃ©nu pÅ™edtÃ­m, neÅ¾ budete moci pouÅ¾Ã­t seznam schrÃ¡nek.';
 
 $PALANG['domain'] = 'DomÃ©na';
@@ -103,26 +105,26 @@ $PALANG['pDelete_delete_error'] = 'Nelze
 $PALANG['pDelete_delete_success'] = '%s odstranÄ›n.';
 $PALANG['pDelete_domain_error'] = 'Tato domÃ©na nenÃ­ vaÅ¡e ';
 $PALANG['pDelete_alias_error'] = 'Nelze odstranit pÅ™esmÄ›rovÃ¡nÃ­ ';
-$PALANG['pCreate_alias_domain_welcome'] = 'PouÅ¾Ã­t addresy jednÃ© z domÃ©n pro druhou.';
-$PALANG['pCreate_alias_domain_alias'] = 'PÅ™esmÄ›rovÃ¡na domÃ©na';
+$PALANG['pCreate_alias_domain_welcome'] = 'PouÅ¾Ã­t adresy jednÃ© z domÃ©n pro druhou.';
+$PALANG['pCreate_alias_domain_alias'] = 'PÅ™esmÄ›rovanÃ¡ domÃ©na';
 $PALANG['pCreate_alias_domain_alias_text'] = 'DomÃ©na, na kterou jsou mailovÃ© zprÃ¡vy zasÃ­lÃ¡ny.';
 $PALANG['pCreate_alias_domain_target'] = 'CÃ­lovÃ¡ domÃ©na';
 $PALANG['pCreate_alias_domain_target_text'] = 'DomÃ©na, na kterou jsou mailovÃ© zprÃ¡vy pÅ™esmÄ›rovÃ¡ny.';
 $PALANG['pCreate_alias_domain_error1'] = 'NemÃ¡te oprÃ¡vnÄ›nÃ­ vytvoÅ™it zvolenou konfiguraci.';
 $PALANG['pCreate_alias_domain_error2'] = 'ZvolenÃ¡ konfigurace je neplatnÃ¡, pouÅ¾ijte prosÃ­m jinou!';
-$PALANG['alias_domain_already_exists'] = 'Tato domÃ©na je jiÅ¾ definovanÃ¡ jako pÅ™esmÄ›rovÃ¡na!';
-$PALANG['alias_domain_does_not_exist'] = 'Tato domÃ©na nenÃ­ definovanÃ¡ jako pÅ™esmÄ›rovÃ¡na!';
+$PALANG['alias_domain_already_exists'] = 'Tato domÃ©na je jiÅ¾ definovanÃ¡ jako pÅ™esmÄ›rovanÃ¡!';
+$PALANG['alias_domain_does_not_exist'] = 'Tato domÃ©na nenÃ­ definovanÃ¡ jako pÅ™esmÄ›rovanÃ¡!';
 $PALANG['alias_domain_create_failed'] = 'VytvoÅ™enÃ­ pÅ™esmÄ›rovÃ¡nÃ­ domÃ©ny %s selhalo!';
 $PALANG['alias_domain_change_failed'] = 'ZmÄ›na pÅ™esmÄ›rovÃ¡nÃ­ domÃ©ny %s selhala!';
 $PALANG['pCreate_alias_domain_error4'] = 'VÅ¡echny domÃ©ny jiÅ¾ majÃ­ aktivnÃ­ pÅ™esmÄ›rovÃ¡nÃ­.';
 $PALANG['pCreate_alias_domain_success'] = 'PÅ™esmÄ›rovÃ¡nÃ­ domÃ©ny %s bylo bylo vytvoÅ™eno.';
-$PALANG['alias_domain_changed'] = 'PrÄ›smÄ›rovÃ¡na domÃ©na %s byla zmÄ›nena.';
+$PALANG['alias_domain_changed'] = 'PrÄ›smÄ›rovanÃ¡ domÃ©na %s byla zmÄ›nÄ›na.';
 $PALANG['alias_domain_to_itsself'] = 'DomÃ©na nemÅ¯Å¾e bÃ½t pÅ™esmÄ›rovÃ¡na na sebe samu!';
 $PALANG['delete_domain_aliasdomain_target'] = 'DomÃ©na %s je cÃ­lovou domÃ©nou pro jedno nebo vÃ­ce pÅ™esmÄ›rovÃ¡nÃ­, nemÅ¯Å¾e bÃ½t proto odstranÄ›na! (OdstraÅˆte nejdÅ™Ã­v pÅ™esmÄ›rovanou domÃ©nu.)';
 
-$PALANG['pCreate_alias_address_text_error1'] = 'Adresa neni platnÃ¡!';
+$PALANG['pCreate_alias_address_text_error1'] = 'Adresa nenÃ­ platnÃ¡!';
 $PALANG['alias_does_not_exist'] = 'Toto pÅ™esmÄ›rovÃ¡nÃ­ neexistuje!';
-$PALANG['email_address_already_exists'] = 'TakovÃ¡ emailovÃ¡ adresa jiÅ¾ existuje, zvolte jinou prosÃ­m!';
+$PALANG['email_address_already_exists'] = 'TakovÃ¡ emailovÃ¡ adresa jiÅ¾ existuje, zvolte prosÃ­m jinou!';
 $PALANG['pCreate_alias_address_text_error3'] = 'DosÃ¡hli jste limitu, nemÅ¯Å¾ete vytvÃ¡Å™et dalÅ¡Ã­ aliasy!';
 $PALANG['pCreate_alias_goto_text'] = 'Kam mÃ¡ poÅ¡ta chodit.';
 $PALANG['pCreate_alias_goto_text_error'] = 'CÃ­l nenÃ­ platnÃ½!';
@@ -131,24 +133,28 @@ $PALANG['pCreate_alias_result_success']
 $PALANG['alias_updated'] = 'PÅ™esmÄ›rovÃ¡nÃ­ %s bylo upraveno!';
 $PALANG['pCreate_alias_catchall_text'] = 'Pro vytvoÅ™enÃ­ domÃ©novÃ©ho koÅ¡e pouÅ¾ijte * jako alias. Pro pÅ™esmÄ›rovÃ¡nÃ­ domÃ©na -> domÃ©na pouÅ¾ijte *@domain.tld jako cÃ­l.';
 $PALANG['mailbox_alias_cant_be_deleted'] = 'Toto pÅ™esmÄ›rovÃ¡nÃ­ je svÃ¡zÃ¡no s emailem a nemÅ¯Å¾e bÃ½t proto vymazÃ¡no!';
-$PALANG['protected_alias_cant_be_deleted'] = 'The alias %s is protected and can only be deleted by a superadmin'; # XXX
+$PALANG['protected_alias_cant_be_deleted'] = 'Tento alias %s je chrÃ¡nÄ›nÃ½ a mÅ¯Å¾e bÃ½t odstranÄ›n pouze superadministrÃ¡torem';
 
 $PALANG['pEdit_alias_welcome'] = 'Upravit nastavenÃ­ pÅ™esmÄ›rovÃ¡nÃ­.';
 $PALANG['pEdit_alias_help'] = 'Je moÅ¾nÃ© zadat vÃ­ce cÃ­lovÃ½ch adres, jeden zÃ¡znam na Å™Ã¡dek.';
 $PALANG['alias'] = 'PÅ™esmÄ›rovÃ¡nÃ­';
 $PALANG['to'] = 'CÃ­l';
 $PALANG['pEdit_alias_goto_text_error1'] = 'Nezadali jste cÃ­l';
-$PALANG['pEdit_alias_goto_text_error2'] = 'EmailovÃ¡ adresa kterou jste zadali nenÃ­ platnÃ¡: ';
+$PALANG['pEdit_alias_goto_text_error2'] = 'EmailovÃ¡ adresa, kterou jste zadali nenÃ­ platnÃ¡: ';
 $PALANG['pEdit_alias_domain_result_error'] = 'NepodaÅ™ilo se upravit pÅ™esmÄ›rovÃ¡nÃ­ domÃ©ny!';
 $PALANG['pEdit_alias_forward_and_store'] = 'DoruÄovat i do schrÃ¡nky.';
 $PALANG['pEdit_alias_forward_only'] = 'PÅ™esmÄ›rovat pouze na danÃ© adresy.';
 $PALANG['pEdit_alias_result_error'] = 'NepodaÅ™ilo se upravit pÅ™esmÄ›rovÃ¡nÃ­! (%s)';
 
 $PALANG['pCreate_mailbox_welcome'] = 'VytvoÅ™it novou lokÃ¡lnÃ­ schrÃ¡nku v domÃ©nÄ›.';
-$PALANG['pCreate_mailbox_username_text_error1'] = 'Adresa neni platnÃ¡!';
+$PALANG['pCreate_mailbox_username_text_error1'] = 'Adresa nenÃ­ platnÃ¡!';
 $PALANG['pCreate_mailbox_username_text_error3'] = 'DosÃ¡hli jste limitu, nemÅ¯&cedil;ete vytvÃ¡Å™et dalÅ¡Ã­ schrÃ¡nky!';
 $PALANG['pCreate_mailbox_password_text'] = 'Heslo pro POP3/IMAP/SMTP';
 $PALANG['pCreate_mailbox_name_text'] = 'CelÃ© jmÃ©no';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Odeslat uvÃ­tacÃ­ email';
 $PALANG['pCreate_mailbox_result_error'] = 'VytvoÅ™enÃ­ schrÃ¡nky %s selhalo!';
 $PALANG['pCreate_mailbox_result_success'] = 'SchrÃ¡nka %s byla pÅ™idÃ¡na do tabulky schrÃ¡nek!';
@@ -156,7 +162,7 @@ $PALANG['pCreate_mailbox_result_succes_n
 $PALANG['mailbox_updated'] = "SchrÃ¡nka %s byla aktualizovÃ¡na.";
 $PALANG['mailbox_update_failed'] = "Aktualizace schrÃ¡nky %s selhala!";
 
-$PALANG['pEdit_mailbox_welcome'] = 'Upravit lokÃ¡lnÃ­ chrÃ¡nku v domÃ©nÄ›.';
+$PALANG['pEdit_mailbox_welcome'] = 'Upravit lokÃ¡lnÃ­ schrÃ¡nku v domÃ©nÄ›.';
 $PALANG['pEdit_mailbox_username'] = 'UÅ¾ivatelskÃ© jmÃ©no';
 $PALANG['pEdit_mailbox_password_text_error'] = 'ZadanÃ¡ hesla se neshodujÃ­!';
 $PALANG['pEdit_mailbox_quota'] = 'MÃ­sto';
@@ -176,9 +182,16 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'ZmÄ›na hesla';
 $PALANG['pPassword_result_error'] = 'NepodaÅ™ilo se zmÄ›nit heslo! (%s)';
 $PALANG['pPassword_result_success'] = 'Heslo bylo zmÄ›nÄ›no! (%s)';
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 
-$PALANG['pEdit_vacation_set'] = 'ZmÄ›nit / Nastavit zprÃ¡vu o nepÅ™Ã­tomnosti';
-$PALANG['pEdit_vacation_remove'] = 'Ostranit zprÃ¡vu o nepÅ™Ã­tomnosti';
+$PALANG['pEdit_vacation_set'] = 'ZmÄ›nit / nastavit zprÃ¡vu o nepÅ™Ã­tomnosti';
+$PALANG['pEdit_vacation_remove'] = 'Odstranit zprÃ¡vu o nepÅ™Ã­tomnosti';
 
 $PALANG['pVacation_result_error'] = 'Nebylo moÅ¾nÃ© aktualizovat nastavenÃ­ automatickÃ© odpovÄ›di pro %s!';
 $PALANG['pVacation_result_removed'] = 'AutomatickÃ¡ odpovÄ›Ä pro %s byla odstranÄ›na!';
@@ -193,7 +206,7 @@ $PALANG['reply_every_mail'] = 'OdpovÄ›dÄ
 $PALANG['reply_once_per_day'] = 'OdpovÄ›dÄ›t jednou za den';
 $PALANG['reply_once_per_week'] = 'OdpovÄ›dÄ›t jednou za tÃ½den';
 
-$PALANG['pViewlog_welcome'] = 'ProhlÃ­Å¾et 10 poslednÃ­ch akcÃ­ pro ';
+$PALANG['pViewlog_welcome'] = 'ProhlÃ­Å¾et %s poslednÃ­ch akcÃ­ pro ';
 $PALANG['pViewlog_timestamp'] = 'ÄŒasovÃ¡ znaÄka';
 $PALANG['pViewlog_action'] = 'Akce';
 $PALANG['pViewlog_data'] = 'PoznÃ¡mka';
@@ -217,7 +230,7 @@ $PALANG['pViewlog_action_edit_password']
 $PALANG['pViewlog_action_create_admin'] = 'vytvoÅ™enÃ­ administrÃ¡tora';
 $PALANG['pViewlog_action_edit_admin'] = 'zmÄ›na administrÃ¡tora';
 $PALANG['pViewlog_action_delete_admin'] = 'smazat administrÃ¡tora';
-$PALANG['pViewlog_action_edit_vacation'] = 'zmÄ›na zprÃ¡vy o nepÅ™Ã­tovmnosti';
+$PALANG['pViewlog_action_edit_vacation'] = 'zmÄ›na zprÃ¡vy o nepÅ™Ã­tomnosti';
 $PALANG['pViewlog_action_create_fetchmail'] = 'vytvoÅ™it Ãºlohu pro staÅ¾enÃ­ poÅ¡ty';
 $PALANG['pViewlog_action_edit_fetchmail'] = 'upravit Ãºlohu pro staÅ¾enÃ­ poÅ¡ty';
 $PALANG['pViewlog_action_delete_fetchmail'] = 'smazat Ãºlohu pro staÅ¾enÃ­ poÅ¡ty';
@@ -240,8 +253,8 @@ $PALANG['pAdminMenu_list_domain'] = 'Dom
 $PALANG['pAdminMenu_list_virtual'] = 'SchrÃ¡nky';
 $PALANG['pAdminMenu_backup'] = 'VytvoÅ™it zÃ¡lohu';
 $PALANG['pAdminMenu_create_domain_admins'] = 'AdministrÃ¡toÅ™i'; // unused
-$PALANG['pAdminMenu_create_admin'] = 'NovÃ½ AdministrÃ¡tor';
-$PALANG['pAdminMenu_create_domain'] = 'NovÃ¡ DomÃ©na';
+$PALANG['pAdminMenu_create_admin'] = 'NovÃ½ administrÃ¡tor';
+$PALANG['pAdminMenu_create_domain'] = 'NovÃ¡ domÃ©na';
 
 $PALANG['pAdminList_admin_count'] = 'DomÃ©ny';
 
@@ -249,10 +262,10 @@ $PALANG['description'] = 'Popis';
 $PALANG['aliases'] = 'PÅ™esmÄ›rovÃ¡nÃ­';
 $PALANG['pAdminList_domain_quota'] = 'KvÃ³ta domÃ©ny (MB)';
 $PALANG['pAdminList_domain_backupmx'] = 'ZÃ¡loÅ¾nÃ­ MX';
-$PALANG['last_modified'] = 'Naposledy ZmÄ›nÄ›no';
+$PALANG['last_modified'] = 'Naposledy zmÄ›nÄ›no';
 
 
-$PALANG['pAdminCreate_domain_welcome'] = 'PÅ™idat Novou DomÃ©nu';
+$PALANG['pAdminCreate_domain_welcome'] = 'PÅ™idat novou domÃ©nu';
 $PALANG['pAdminCreate_domain_domain_text_error'] = 'TakovÃ¡ domÃ©na uÅ¾ existuje!';
 $PALANG['domain_does_not_exist'] = 'Tato domÃ©na neexistuje!';
 $PALANG['pAdminCreate_domain_domain_text_error2'] = 'TakovÃ¡ domÃ©na nenÃ­ platnÃ¡!';
@@ -260,7 +273,7 @@ $PALANG['pAdminCreate_domain_defaultalia
 $PALANG['pAdminCreate_domain_button'] = 'PÅ™idat domÃ©nu';
 $PALANG['pAdminCreate_domain_result_error'] = 'NepodaÅ™ilo se pÅ™idat domÃ©nu! (%s)';
 $PALANG['pAdminCreate_domain_result_success'] = 'DomÃ©na byla pÅ™idÃ¡na! (%s)';
-$PALANG['domain_updated'] = 'DomÃ©na %s byla aktualizovanÃ¡.';
+$PALANG['domain_updated'] = 'DomÃ©na %s byla aktualizovÃ¡na.';
 $PALANG['pAdminDelete_admin_error'] = 'NepodaÅ™ilo se odstranit admin uÅ¾ivatele!';
 
 $PALANG['domain_postdel_failed'] = 'SpuÅ¡tÄ›nÃ­ skriptu po smazÃ¡nÃ­ domÃ©ny selhalo, zkontrolujte log soubor!';
@@ -269,7 +282,7 @@ $PALANG['mailbox_postdel_failed'] = 'Spu
 $PALANG['mailbox_postedit_failed'] = 'SpuÅ¡tenÃ­ skriptu po ÃºpravÄ› schrÃ¡nky selhalo, zkontrolujte log soubor!';
 $PALANG['mailbox_postcreate_failed'] = 'SpuÅ¡tenÃ­ skriptu po vytvoÅ™enÃ­ schrÃ¡nky selhalo, zkontrolujte log soubor!';
 $PALANG['pAdminDelete_alias_domain_error'] = 'NepodaÅ™ilo se odstranit pÅ™esmÄ›rovÃ¡nÃ­ domÃ©ny!';
-$PALANG['domain_conflict_vacation_domain'] = 'DomÃ©nu vyuÅ¾itou pro sprÃ¡vy o nepÅ™Ã­tomnosti nelze pouÅ¾Ã­t jako mailovou domÃ©nu!';
+$PALANG['domain_conflict_vacation_domain'] = 'DomÃ©nu vyuÅ¾itou pro zprÃ¡vy o nepÅ™Ã­tomnosti nelze pouÅ¾Ã­t jako mailovou domÃ©nu!';
 
 $PALANG['pAdminEdit_domain_welcome'] = 'Upravit domÃ©nu';
 $PALANG['pAdminEdit_domain_aliases_text'] = '-1 = znepÅ™Ã­stupnit | 0 = neomezenÄ›';
@@ -294,20 +307,21 @@ $PALANG['pAdminEdit_admin_welcome'] = 'U
 $PALANG['admin'] = 'AdministrÃ¡tor';
 $PALANG['password_again'] = 'Heslo (znovu)';
 $PALANG['super_admin'] = 'SuperuÅ¾ivatel';
-$PALANG['super_admin_desc'] = 'Super administrÃ¡tori majÃ­ pÅ™Ã­stup ke vÅ¡em domÃ©nÃ¡m, zprÃ¡vÄ› domÃ©n a ÃºÄtÅ¯ administrÃ¡torÅ¯.';
+$PALANG['super_admin_desc'] = 'Super administrÃ¡toÅ™i majÃ­ pÅ™Ã­stup ke vÅ¡em domÃ©nÃ¡m, sprÃ¡vÄ› domÃ©n a ÃºÄtÅ¯ administrÃ¡torÅ¯.';
 $PALANG['pAdminEdit_admin_result_error'] = 'NepodaÅ™ilo se upravit administrÃ¡tora! (%s)';
 $PALANG['pAdminEdit_admin_result_success'] = 'AdministrÃ¡tor %s byl upraven!';
 
 $PALANG['pUsersLogin_welcome'] = 'Zde se pÅ™ihlaÅ¡ujÃ­ uÅ¾ivatelÃ© pro zmÄ›nu hesla, pÅ™esmÄ›rovÃ¡nÃ­ nebo automatickÃ© odpovÄ›di.';
 $PALANG['pUsersLogin_username_incorrect'] = 'NesprÃ¡vnÃ© uÅ¾ivatelskÃ© jmeno. PÅ™ihlaÅ¡ujte se svojÃ­ emailovou adresou!';
 $PALANG['pUsersLogin_password_incorrect'] = 'NesprÃ¡vnÃ© heslo!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
-$PALANG['pUsersMenu_vacation'] = 'AutomatickÃ¡ OdpovÄ›Ä';
-$PALANG['pUsersMenu_edit_alias'] = 'ZmÄ›na PÅ™esmÄ›rovÃ¡nÃ­';
+$PALANG['pUsersMenu_vacation'] = 'AutomatickÃ¡ odpovÄ›Ä';
+$PALANG['pUsersMenu_edit_alias'] = 'ZmÄ›na pÅ™esmÄ›rovÃ¡nÃ­';
 
-$PALANG['pUsersMain_vacation'] = 'Nastavit ,,jsem pryÄ`` nebo podobnou automatickou odpovÄ›Ä.';
+$PALANG['pUsersMain_vacation'] = 'Nastavit "jsem pryÄ" nebo podobnou automatickou odpovÄ›Ä.';
 $PALANG['pUsersMain_vacationSet'] = $PALANG['pUsersMenu_vacation'] . ' je NASTAVENA, kliknÄ›te na \'' . $PALANG['pUsersMenu_vacation'] . '\' pro odstranÄ›nÃ­ nebo zmÄ›nu';
-$PALANG['pUsersMain_edit_alias'] = 'Nastavit / zmÄ›nÃ­t pÅ™esmÄ›rovÃ¡nÃ­';
+$PALANG['pUsersMain_edit_alias'] = 'Nastavit / zmÄ›nit pÅ™esmÄ›rovÃ¡nÃ­';
 $PALANG['pUsersMain_password'] = 'ZmÄ›nit heslo';
 
 $PALANG['pUsersVacation_welcome'] = 'AutomatickÃ¡ odpovÄ›Ä';
@@ -333,15 +347,16 @@ $PALANG['pBroadcast_title'] = 'Odeslat z
 $PALANG['pBroadcast_name'] = 'VaÅ¡e jmÃ©no';
 $PALANG['pBroadcast_success'] = 'ZprÃ¡va pro vÅ¡echny schrÃ¡nky byla odeslÃ¡na.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Poslat email vÅ¡em';
-$PALANG['pBroadcast_error_empty'] = 'Pole Od, PÅ™edmÄ›t a ZprÃ¡va by nemÄ›ly bÃ½t prÃ¡zdnÃ© !';
-
+$PALANG['pBroadcast_error_empty'] = 'Pole Od, PÅ™edmÄ›t a ZprÃ¡va by nemÄ›ly bÃ½t prÃ¡zdnÃ©!';
+$PALANG['broadcast_mailboxes_only'] = 'Pouze poslat do schrÃ¡nek';
+$PALANG['broadcast_to_domains'] = 'Poslat na domÃ©ny:';
 $PALANG['pStatus_undeliverable'] = 'moÅ¾nÃ¡ NEDORUÄŒITELNÃ‰ ';
 $PALANG['pStatus_custom'] = 'DoruÄeno do ';
 $PALANG['pStatus_popimap'] = 'POP/IMAP ';
 $PALANG['password_too_short'] = "Heslo je pÅ™Ã­liÅ¡ krÃ¡tkÃ© - je vyÅ¾adovÃ¡no minimÃ¡lnÄ› %s znakÅ¯";
 $PALANG['password_no_characters'] = "Heslo musÃ­ obsahovat alespoÅˆ %s znak(-y).";
 $PALANG['password_no_digits'] = "Heslo musÃ­ obsahovat alespoÅˆ %s ÄÃ­slici(-ce).";
-$PALANG['pInvalidDomainRegex'] = "NeplatnÃ© domÃ©novÃ© jmÃ©no  %s, nevyhovÄ›lo regulÃ¡rnÃ­mu vÃ½razu";
+$PALANG['pInvalidDomainRegex'] = "NeplatnÃ© domÃ©novÃ© jmÃ©no %s, nevyhovÄ›lo regulÃ¡rnÃ­mu vÃ½razu";
 $PALANG['pInvalidDomainDNS'] = "NeplatnÃ¡ domÃ©na %s, a/nebo nezjiÅ¡tÄ›n DNS zÃ¡znam.";
 $PALANG['pInvalidMailRegex'] = "NeplatnÃ¡ emailovÃ¡ adresa %s, nevyhovÄ›la regulÃ¡rnÃ­mu vÃ½razu.";
 $PALANG['pFetchmail_welcome'] = 'Stahovat poÅ¡tu pro:';
@@ -368,19 +383,19 @@ $PALANG['pFetchmail_field_keep']
 $PALANG['pFetchmail_field_protocol']        = 'Protokol';
 $PALANG['pFetchmail_field_usessl']          = 'SSL aktivnÃ­';
 $PALANG['pFetchmail_field_sslcertck']       = 'OveÅ™enÃ­ SSL certifikÃ¡tu';
-$PALANG['pFetchmail_field_sslcertpath']     = 'Cesta ku SSL certifikÃ¡tÅ¯m';
-$PALANG['pFetchmail_field_sslfingerprint']  = 'Otisk SSL certifikÃ¡tu (md5)';
-$PALANG['pFetchmail_field_extra_options']   = 'Extra Parametry';
+$PALANG['pFetchmail_field_sslcertpath']     = 'Cesta k SSL certifikÃ¡tÅ¯m';
+$PALANG['pFetchmail_field_sslfingerprint']  = 'Otisk SSL certifikÃ¡tu (MD5)';
+$PALANG['pFetchmail_field_extra_options']   = 'Extra parametry';
 $PALANG['pFetchmail_field_mda']             = 'MDA';
 $PALANG['pFetchmail_field_date']            = 'Datum';
-$PALANG['pFetchmail_field_returned_text']   = 'VÃ½stupnÃ­ Text';
+$PALANG['pFetchmail_field_returned_text']   = 'VÃ½stupnÃ­ text';
 $PALANG['pFetchmail_desc_id']               = 'ID zÃ¡znamu';
 $PALANG['pFetchmail_desc_mailbox']          = 'MÃ­stnÃ­ schrÃ¡nka';
-$PALANG['pFetchmail_desc_src_server']       = 'VzdÃ¡lenÃ½ Server';
+$PALANG['pFetchmail_desc_src_server']       = 'VzdÃ¡lenÃ½ server';
 $PALANG['pFetchmail_desc_src_auth']         = 'VÄ›tÅ¡inou \'password\''; # Translators: Please do NOT translate 'password' here
-$PALANG['pFetchmail_desc_src_user']         = 'VzdÃ¡lenÃ½ UÅ¾ivatel';
-$PALANG['pFetchmail_desc_src_password']     = 'Heslo VzdÃ¡lenÃ©ho UÅ¾ivatele';
-$PALANG['pFetchmail_desc_src_folder']       = 'VzdÃ¡lenÃ¡ SloÅ¾ka';
+$PALANG['pFetchmail_desc_src_user']         = 'VzdÃ¡lenÃ½ uÅ¾ivatel';
+$PALANG['pFetchmail_desc_src_password']     = 'Heslo vzdÃ¡lenÃ©ho uÅ¾ivatele';
+$PALANG['pFetchmail_desc_src_folder']       = 'VzdÃ¡lenÃ¡ sloÅ¾ka';
 $PALANG['pFetchmail_desc_poll_time']        = 'Stahovat kaÅ¾dÃ½ch ... minut';
 $PALANG['pFetchmail_desc_fetchall']         = 'ZÃ­skÃ¡vat vÅ¡echny starÃ© (pÅ™eÄtenÃ©) i novÃ© zprÃ¡vy';
 $PALANG['pFetchmail_desc_keep']             = 'PonechÃ¡vat staÅ¾enÃ© zprÃ¡vy na vzdÃ¡lenÃ©m mailserveru';
@@ -391,7 +406,7 @@ $PALANG['pFetchmail_desc_mda']
 $PALANG['pFetchmail_desc_date']             = 'Datum poslednÃ­ho staÅ¾enÃ­ poÅ¡ty/zmÄ›ny konfigurace';
 $PALANG['pFetchmail_desc_returned_text']    = 'VÃ½stupnÃ­ textovÃ½ zÃ¡znam poslednÃ­ho stahovÃ¡nÃ­ poÅ¡ty';
 $PALANG['dateformat_pgsql'] = 'dd-mm-YYYY'; # translators: rearrange to your local date format, but make sure it's a valid PostgreSQL date format
-$PALANG['dateformat_mysql'] = '%d-%m-%Y';   # translators: rearrange to your local date format, but make sure it's a valid MySQL date format
+$PALANG['dateformat_mysql'] = '%d.%m.%Y';   # translators: rearrange to your local date format, but make sure it's a valid MySQL date format
 
 $PALANG['please_keep_this_as_last_entry'] = ''; # needed for language-check.sh
 /* vim: set expandtab ft=php softtabstop=3 tabstop=3 shiftwidth=3: */
diff -pruN 3.0.2-2/languages/da.lang 3.2-2/languages/da.lang
--- 3.0.2-2/languages/da.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/da.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: da.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Danish
 // by Lars
@@ -148,6 +148,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3']       = 'Du har nÃ¥et grÃ¦nsen for antallet af postbokse til domÃ¦ne!';
 $PALANG['pCreate_mailbox_password_text'] = 'Adgangskode til POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Fulde navn';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Send velkomsthilsen'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Kan ikke tilfÃ¸je postboksen til postboks-tabellen! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'Postboksen er tilfÃ¸jet til postboks-tabellen! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -175,6 +179,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Ã†ndr adgangskode';
 $PALANG['pPassword_result_error'] = 'Kan ikke Ã¦ndre adgangskoden! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Din adgangskode er Ã¦ndret! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 
 $PALANG['pEdit_vacation_set'] = 'Ã†ndr / Angiv autosvar';
 $PALANG['pEdit_vacation_remove'] = 'Fjern autosvar';
@@ -192,7 +203,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Vis de sidste 10 poster for ';
+$PALANG['pViewlog_welcome'] = 'Vis de sidste %s poster for ';
 $PALANG['pViewlog_timestamp'] = 'Tidsstempel';
 $PALANG['pViewlog_action'] = 'Handling';
 $PALANG['pViewlog_data'] = 'Data';
@@ -300,6 +311,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Postboksbruger: Log ind for at Ã¦ndre adgangskode og videresending.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Dit brugernavn er forkert. Tjek at du bruger din emailadresse som brugernavn!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Din adgangskode er ikke korrekt!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Autosvar';
 $PALANG['pUsersMenu_edit_alias'] = 'RedigÃ©r videresending';
@@ -333,6 +345,8 @@ $PALANG['pBroadcast_name'] = 'Dit navn';
 $PALANG['pBroadcast_success'] = 'Din meddelelse er rundsendt.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Rundsend meddelse';
 $PALANG['pBroadcast_error_empty']       = 'Felterne "Dit navn", "Emne" og "Meddelelse" skal alle udfyldes.';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 
 $PALANG['pStatus_undeliverable'] = 'kan mÃ¥ske ikke leveres ';
 $PALANG['pStatus_custom'] = 'Leveres til ';
diff -pruN 3.0.2-2/languages/de.lang 3.2-2/languages/de.lang
--- 3.0.2-2/languages/de.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/de.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: de.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file German
 // by Tobias
@@ -145,6 +145,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Sie dÃ¼rfen leider nicht mehr Mailboxen fÃ¼r diese Domain anlegen!';
 $PALANG['pCreate_mailbox_password_text'] = 'Passwort fÃ¼r POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'VollstÃ¤ndiger Name';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'BegrÃ¼ÃŸungsmail senden';
 $PALANG['pCreate_mailbox_result_error'] = 'Das Erstellen der Mailbox %s ist fehlgeschlagen';
 $PALANG['pCreate_mailbox_result_success'] = 'Die Mailbox %s wurde in die Mailbox-Tabelle eingetragen.';
@@ -172,6 +176,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Passwort Ã¤ndern';
 $PALANG['pPassword_result_error'] = 'Das Passwort fÃ¼r %s konnte nicht geÃ¤ndert werden';
 $PALANG['pPassword_result_success'] = 'Das Passwort fÃ¼r %s wurde geÃ¤ndert.';
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 
 $PALANG['pEdit_vacation_set'] = 'Automatische Antwort Ã¤ndern / einrichten';
 $PALANG['pEdit_vacation_remove'] = 'Automatische Antwort abschalten';
@@ -189,7 +200,7 @@ $PALANG['reply_every_mail'] = 'Jede Mail
 $PALANG['reply_once_per_day'] = 'Einmal pro Tag antworten';
 $PALANG['reply_once_per_week'] = 'Einmal pro Woche antworten';
 
-$PALANG['pViewlog_welcome'] = 'Zeigt die letzten 10 Aktionen fÃ¼r ';
+$PALANG['pViewlog_welcome'] = 'Zeigt die letzten %s Aktionen fÃ¼r ';
 $PALANG['pViewlog_timestamp'] = 'Zeitpunkt';
 $PALANG['pViewlog_action'] = 'Aktion';
 $PALANG['pViewlog_data'] = 'Daten';
@@ -297,6 +308,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Benutzer bitte hier einloggen, um Weiterleitungen bzw. das Passwort zu Ã¤ndern.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Falscher Login! Bitte benutzen Sie ihre Email-Adresse als Login';
 $PALANG['pUsersLogin_password_incorrect'] = 'Falsches Passwort!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Automatische Antwort';
 $PALANG['pUsersMenu_edit_alias'] = 'Weiterleitung Ã¤ndern';
@@ -331,6 +343,8 @@ $PALANG['pBroadcast_name'] = 'Ihr Name';
 $PALANG['pBroadcast_success'] = 'Ihre Rundmail wurde gesendet.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Rundmail';
 $PALANG['pBroadcast_error_empty'] = 'Die Felder Name, Betreff und Nachricht dÃ¼rfen nicht leer sein!';
+$PALANG['broadcast_mailboxes_only'] = "Nur an PostfÃ¤cher senden";
+$PALANG['broadcast_to_domains'] = "Senden an Domains:";
 
 $PALANG['pStatus_undeliverable'] = 'mÃ¶glicherweise UNZUSTELLBAR ';
 $PALANG['pStatus_custom'] = 'Zustellung an ';
diff -pruN 3.0.2-2/languages/en.lang 3.2-2/languages/en.lang
--- 3.0.2-2/languages/en.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/en.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: en.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file English
 // by Mischa <mischa at high5 dot net>
@@ -44,7 +44,7 @@ $PALANG['pLogin_username'] = 'Login (ema
 $PALANG['password'] = 'Password';
 $PALANG['pLogin_language'] = 'Language';
 $PALANG['pLogin_button'] = 'Login';
-$PALANG['pLogin_failed'] = 'Your email address or password are not correct.';
+$PALANG['pLogin_failed'] = 'Your email address or password is not correct.';
 $PALANG['pLogin_login_users'] = 'Users click here to login to the user section.';
 
 $PALANG['pMenu_main'] = 'Main';
@@ -146,11 +146,15 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'You have reached your limit to create mailboxes!';
 $PALANG['pCreate_mailbox_password_text'] = 'Password for POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Full name';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone';
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten";
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail';
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten";
 $PALANG['pCreate_mailbox_mail'] = 'Send Welcome mail';
 $PALANG['pCreate_mailbox_result_error'] = 'Creating the mailbox %s failed!';
 $PALANG['pCreate_mailbox_result_success'] = 'The mailbox %s has been added to the mailbox table.';
 $PALANG['pCreate_mailbox_result_succes_nosubfolders'] = 'The mailbox %s has been added to the mailbox table, but none (or only some) of the predefined sub-folders could be created.';
-$PALANG['mailbox_updated'] = "The mailbox %s has been updated."; 
+$PALANG['mailbox_updated'] = "The mailbox %s has been updated.";
 $PALANG['mailbox_update_failed'] = "Updating the mailbox %s failed!";
 
 $PALANG['pEdit_mailbox_welcome'] = 'Edit a mailbox for your domain.';
@@ -174,6 +178,14 @@ $PALANG['change_password'] = 'Change Pas
 $PALANG['pPassword_result_error'] = 'Changing the password for %s failed!';
 $PALANG['pPassword_result_success'] = 'The password for %s has been changed.';
 
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.';
+$PALANG['pPassword_recovery_button'] = 'Send me the code';
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name'];
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name'];
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code.";
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS';
+$PALANG['pPassword_code_text_error'] = 'Invalid code';
+
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message';
 $PALANG['pEdit_vacation_remove'] = 'Remove away message';
 
@@ -190,7 +202,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day';
 $PALANG['reply_once_per_week'] = 'Reply once a week';
 
-$PALANG['pViewlog_welcome'] = 'View the last 10 actions for ';
+$PALANG['pViewlog_welcome'] = 'View the last %s actions for ';
 $PALANG['pViewlog_timestamp'] = 'Timestamp';
 $PALANG['pViewlog_action'] = 'Action';
 $PALANG['pViewlog_data'] = 'Data';
@@ -298,6 +310,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Mailbox users login to change your password and aliases.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Your login is not correct. Make sure that you login with your email address!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Your password is not correct!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password';
 
 $PALANG['pUsersMenu_vacation'] = 'Auto Response';
 $PALANG['pUsersMenu_edit_alias'] = 'Change your forward';
@@ -331,6 +344,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message';
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes';
+$PALANG['broadcast_to_domains'] = 'Send to domains:';
 
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE ';
 $PALANG['pStatus_custom'] = 'Delivers to ';
diff -pruN 3.0.2-2/languages/es.lang 3.2-2/languages/es.lang
--- 3.0.2-2/languages/es.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/es.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: es.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Spanish 
 // by Alvaro
@@ -143,6 +143,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Â¡Ha llegado al lÃ­mite de creaciÃ³n de buzones!';
 $PALANG['pCreate_mailbox_password_text'] = 'ContraseÃ±a para POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Nombre completo';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Enviar correo bienvenida';
 $PALANG['pCreate_mailbox_result_error'] = 'Â¡Imposible aÃ±adir un buzÃ³n a la tabla de buzones! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'Â¡El buzÃ³n ha sido aÃ±adido a la tabla de buzones! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -170,6 +174,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Cambiar contraseÃ±a'; # XXX check text - should be 'Change Password'
 $PALANG['pPassword_result_error'] = 'Â¡Imposible cambiar la contraseÃ±a! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Â¡Su contraseÃ±a ha sido cambiada! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 
 $PALANG['pEdit_vacation_set'] = 'Cambiar / Establecer mensaje de ausencia'; 
 $PALANG['pEdit_vacation_remove'] = 'Quitar mensaje de ausencia'; 
@@ -186,7 +197,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Ver las Ãºltimas 10 acciones para ';
+$PALANG['pViewlog_welcome'] = 'Ver las Ãºltimas %s acciones para ';
 $PALANG['pViewlog_timestamp'] = 'Fecha/Hora';
 $PALANG['pViewlog_action'] = 'AcciÃ³n';
 $PALANG['pViewlog_data'] = 'Datos';
@@ -293,6 +304,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Login de usuarios para cambiar la contraseÃ±a y alias.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Su login no es correcto. Â¡AsegÃºrese de haber introducido su direcciÃ³n de e-mail como login!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Â¡Su contraseÃ±a no es correcta!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Respuesta automÃ¡tica';
 $PALANG['pUsersMenu_edit_alias'] = 'Cambiar la redirecciÃ³n';
@@ -324,6 +336,8 @@ $PALANG['pBroadcast_name'] = 'Tu nombre'
 $PALANG['pBroadcast_success'] = 'Se ha enviado el mensaje.'; 
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'Â¡Los campos Nombre, Asunto y Mensaje no pueden estar vacÃ­os!'; 
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'posiblemente NO SE ENTREGÃ“'; 
 $PALANG['pStatus_custom'] = 'Enviado a '; 
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/et.lang 3.2-2/languages/et.lang
--- 3.0.2-2/languages/et.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/et.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: et.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Estonian
 // by Peeter Partel <peeter at sigma dot ee>
@@ -143,6 +143,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Oled kasutanud kogu postkastide arvu!';
 $PALANG['pCreate_mailbox_password_text'] = 'Parool POP3/IMAP\'le';
 $PALANG['pCreate_mailbox_name_text'] = 'TÃ¤ielikÂ nimi';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Loo postkast'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Postkasti lisamine tabelisse ebaÃµnnestus! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'Postkast lisati postkastide tabelisse! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -170,6 +174,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Muuda parool';
 $PALANG['pPassword_result_error'] = 'Parooli muutmine ebaÃµnnestus! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Parool on muudetud! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -185,7 +196,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Vaata 10 viimast muudatust domeeniga ';
+$PALANG['pViewlog_welcome'] = 'Vaata %s viimast muudatust domeeniga ';
 $PALANG['pViewlog_timestamp'] = 'Ajatempel';
 $PALANG['pViewlog_action'] = 'Toiming';
 $PALANG['pViewlog_data'] = 'Andmed';
@@ -291,6 +302,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Postkasti kasutaja sisse logimine muutmaks parooli ja aliast.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Kasutajanimi pole Ãµige. Veendu, et sisestatud kasutajanimi on e-postiÂ aadress!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Parool pole Ãµige!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Automaatne vastus';
 $PALANG['pUsersMenu_edit_alias'] = 'Muuda edasisaatmist';
@@ -326,6 +338,8 @@ $PALANG['pBroadcast_success'] = 'Your br
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/eu.lang 3.2-2/languages/eu.lang
--- 3.0.2-2/languages/eu.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/eu.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: eu.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Euskara
 // by Julen
@@ -141,6 +141,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Postontzi sorkuntza mugara iritsi zara!';
 $PALANG['pCreate_mailbox_password_text'] = 'POP3/IMAP-entzat pasahitza';
 $PALANG['pCreate_mailbox_name_text'] = 'Izen osoa';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Postontzia sortu'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Ezinezkoa postontzi taulara postontzia gehitzea! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'Postontzia postontzi taulara sartu da! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -168,6 +172,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Pasahitza aldatu';
 $PALANG['pPassword_result_error'] = 'Ezinezkoa pasahitza aldatzea! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Pasahitza aldatuta! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -183,7 +194,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Honen azken 10 ekintzak ikusi ';
+$PALANG['pViewlog_welcome'] = 'Honen azken %s ekintzak ikusi ';
 $PALANG['pViewlog_timestamp'] = 'Data/ordua';
 $PALANG['pViewlog_action'] = 'Ekintza';
 $PALANG['pViewlog_data'] = 'Datuak';
@@ -290,6 +301,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Erabiltzaileen logina pasahitz eta aliasa aldatzeko.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Login okerra. Ziurta zaitez posta helbidea login gisa sartu duzula!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Pasahitz okerra!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Erantzun automatikoa';
 $PALANG['pUsersMenu_edit_alias'] = 'Berbiderapen helbidea aldatu';
@@ -321,6 +333,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.'; # XXX
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/fi.lang 3.2-2/languages/fi.lang
--- 3.0.2-2/languages/fi.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/fi.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: fi.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Finnish
 // by Palo
@@ -143,6 +143,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Postilaatikoiden maksimimÃ¤Ã¤rÃ¤ saavutettu!';
 $PALANG['pCreate_mailbox_password_text'] = 'POP3/IMAP salasana';
 $PALANG['pCreate_mailbox_name_text'] = 'Koko nimi';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Luo postilaatikko'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Postilaatikon lisÃ¤Ã¤minen ei onnistu! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'Postilaatikko on lisÃ¤tty! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -170,6 +174,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Vaihda salasana';
 $PALANG['pPassword_result_error'] = 'Salasanan vaihto ei onnistunut! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Salasana vaihdettu! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Muuta / Aseta poissaoloviesti';
 $PALANG['pEdit_vacation_remove'] = 'Poista poissaoloviesti';
 $PALANG['pVacation_result_error'] = 'Automaattivastauksen asetuksia ei voitu pÃ¤ivittÃ¤Ã¤! (%s)'; # XXX Text changed to: Updating the auto response settings for %s failed
@@ -291,6 +302,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Salasanan vaihto.';
 $PALANG['pUsersLogin_username_incorrect'] = 'KÃ¤yttÃ¤jÃ¤tunnus tai salasana vÃ¤Ã¤rin!';
 $PALANG['pUsersLogin_password_incorrect'] = 'KÃ¤yttÃ¤jÃ¤tunnus tai salasana vÃ¤Ã¤rin!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Automaattivastaus';
 $PALANG['pUsersMenu_edit_alias'] = 'Muokkaa uudelleenohjausta';
@@ -322,6 +334,8 @@ $PALANG['pBroadcast_name'] = 'Nimesi';
 $PALANG['pBroadcast_success'] = 'Tiedostusviestisi on lÃ¤hetetty.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Tiedotusviesti';
 $PALANG['pBroadcast_error_empty'] = 'Nimi, Aihe tai Viesti kenttien ei pidÃ¤ olla tyhjiÃ¤!';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'ehkÃ¤ ei voida toimittaa ';
 $PALANG['pStatus_custom'] = 'Toimittaa osoiteeseen ';
 $PALANG['pStatus_popimap'] = 'POP/IMAP ';
diff -pruN 3.0.2-2/languages/fo.lang 3.2-2/languages/fo.lang
--- 3.0.2-2/languages/fo.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/fo.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: fo.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Faroese
 // by Danial
@@ -143,6 +143,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'TÃº hevur nÃ½tt tÃ­num marki at stovna postkassar!';
 $PALANG['pCreate_mailbox_password_text'] = 'LoyniorÃ° til POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Fult navn';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Stovna postkassa'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'FÃ¡i ikki stovnaÃ° postkassa! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'Postkassin er stovnaÃ°ur! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -170,6 +174,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Broyt loyniorÃ°';
 $PALANG['pPassword_result_error'] = 'FÃ¡i ikki broytt tÃ­tt loyniorÃ°! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'TÃ­tt loyniorÃ° er broytt! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -185,7 +196,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'VÃ­s seinastu 10 hendingarnar fyri ';
+$PALANG['pViewlog_welcome'] = 'VÃ­s seinastu %s hendingarnar fyri ';
 $PALANG['pViewlog_timestamp'] = 'TÃ­Ã°arstempul';
 $PALANG['pViewlog_action'] = 'Hending';
 $PALANG['pViewlog_data'] = 'DÃ¡ta';
@@ -291,6 +302,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Postkassa brÃºkarar loggi inn fyri at broyta loyniorÃ°, vÃ­Ã°arisending ella frÃ­tÃ­Ã°arboÃ°.';
 $PALANG['pUsersLogin_username_incorrect'] = 'TÃ­tt login er skeivt. Minst til at logga inn viÃ° tÃ­ni e-post adressu!';
 $PALANG['pUsersLogin_password_incorrect'] = 'TÃ­tt loyniorÃ° er skeivt!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'FrÃ­tÃ­Ã°arboÃ°';
 $PALANG['pUsersMenu_edit_alias'] = 'Broyt vÃ­Ã°arisending';
@@ -327,6 +339,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.'; # XXX
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/fr.lang 3.2-2/languages/fr.lang
--- 3.0.2-2/languages/fr.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/fr.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,10 +1,12 @@
 <?php
-# $Id: fr.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file French
 // by Kuthz
 // updated by Olivier ETIENNE
-// updated by Francois Grange (rumbaya @sf)
+// updated by FranÃ§ois GRANGE (rumbaya @sf)
+// updated by Carlos FERREIRA (@acs_ferreira)
+// updated by Aurelien BONANNI (abonanni @teicee)
 //
 
 $PALANG['YES'] = 'Oui';
@@ -14,37 +16,37 @@ $PALANG['del'] = 'Effacer';
 $PALANG['exit'] = 'Quitter';
 $PALANG['cancel'] = 'Annuler';
 $PALANG['save'] = 'Enregistrer les modifications';
-$PALANG['confirm'] = 'Etes vous sur de vouloir supprimer cet enregistrement\n';
-$PALANG['confirm_delete_admin'] = 'Do you really want to delete the admin %s?'; # XXX
-$PALANG['confirm_delete_alias'] = 'Do you really want to delete the alias %s?'; # XXX
-$PALANG['confirm_delete_aliasdomain'] = 'Do you really want to delete the alias domain %s?'; # XXX
-$PALANG['confirm_delete_domain'] = 'Etes-vous sur de vouloir effacer tous les enregistrements dans ce domaine ? Cette opÃ©ration ne pourra pas Ãªtre annulÃ©e.\n (%s)'; # XXX text changed to: 'Do you really want to delete all records for the domain %s? This can not be undone'
-$PALANG['confirm_delete_fetchmail'] = 'Do you really want to delete the fetchmail job %s?'; # XXX
-$PALANG['confirm_delete_mailbox'] = 'Do you really want to delete the mailbox %s?'; # XXX
-$PALANG['confirm_delete_vacation'] = 'Do you really want to delete the vacation message for %s?'; # XXX
-$PALANG['no_delete_permissions'] = 'You are not allowed to delete %s!'; # XXX
+$PALANG['confirm'] = 'ÃŠtes-vous sÃ»r de vouloir supprimer cet enregistrement\n';
+$PALANG['confirm_delete_admin'] = 'ÃŠtes-vous sÃ»r de vouloir supprimer l\'administrateur %s?';
+$PALANG['confirm_delete_alias'] = 'ÃŠtes-vous sÃ»r de vouloir supprimer l\'alias %s?';
+$PALANG['confirm_delete_aliasdomain'] = 'ÃŠtes-vous sÃ»r de vouloir supprimer l\'alias de domaine %s?';
+$PALANG['confirm_delete_domain'] = 'ÃŠtes-vous sÃ»r de vouloir effacer tous les enregistrements du domaine %s ? Cette opÃ©ration ne pourra pas Ãªtre annulÃ©e.\n';
+$PALANG['confirm_delete_fetchmail'] = 'ÃŠtes-vous sÃ»r de vouloir supprimer la tÃ¢che de rÃ©cupÃ©ration de courrier %s?';
+$PALANG['confirm_delete_mailbox'] = 'ÃŠtes-vous sÃ»r de vouloir supprimer la boÃ®te %s?';
+$PALANG['confirm_delete_vacation'] = 'ÃŠtes-vous sÃ»r de vouloir supprimer le message d\'absence pour %s?';
+$PALANG['no_delete_permissions'] = 'Vous n\'Ãªtes pas autorisÃ© Ã  supprimer %s !';
 $PALANG['check_update'] = 'VÃ©rifier les mises Ã  jour';
-$PALANG['invalid_parameter'] = 'ParamÃ¨tres invalides!';
+$PALANG['invalid_parameter'] = 'ParamÃ¨tres invalides !';
 $PALANG['show'] = 'Afficher:';
 $PALANG['all'] = 'Tous';
 $PALANG['created'] = 'CrÃ©Ã©';
 $PALANG['unknown'] = 'inconnu';
-$PALANG['download_csv'] = 'Download this list as CSV file'; # XXX
+$PALANG['download_csv'] = 'TÃ©lÃ©charger cette liste au format CSV';
 $PALANG['missing_field'] = 'Le champ %s est manquant';
-$PALANG['must_be_numeric'] = '%s doit Ãªtre numÃ©rique';
-$PALANG['must_be_numeric_bigger_than_null'] = '%s must be numeric and bigger than 0'; # XXX
+$PALANG['must_be_numeric'] = '%s doit Ãªtre au format numÃ©rique';
+$PALANG['must_be_numeric_bigger_than_null'] = '%s doit Ãªtre au format numÃ©rique et plus grand que 0';
 $PALANG['must_be_boolean'] = '%s doit Ãªtre boolÃ©en';
 $PALANG['invalid_value_given'] = 'Valeur incorrecte pour %s';
-$PALANG['edit_not_allowed'] = 'You are not allowed to edit %s'; # XXX
-$PALANG['searchparams'] = 'Search parameters:'; # XXX
+$PALANG['edit_not_allowed'] = 'Vous n\'Ãªtes pas autorisÃ© Ã  editer %s';
+$PALANG['searchparams'] = 'ParamÃ¨tre de recherche :';
 $PALANG['pFooter_logged_as'] = 'ConnectÃ© en tant que %s';
 
-$PALANG['pLogin_welcome'] = 'Entrez votre adresse courriel pour administrer votre domaine.';
-$PALANG['pLogin_username'] = 'Adresse courriel';
+$PALANG['pLogin_welcome'] = 'Entrez votre adresse email pour administrer votre domaine.';
+$PALANG['pLogin_username'] = 'Adresse email';
 $PALANG['password'] = 'Mot de passe';
 $PALANG['pLogin_language'] = 'Langue';
 $PALANG['pLogin_button'] = 'Entrer';
-$PALANG['pLogin_failed'] = 'Votre email ou mot de passe est incorrect.';
+$PALANG['pLogin_failed'] = 'Votre courriel ou mot de passe est incorrect.';
 $PALANG['pLogin_login_users'] = 'Utilisateurs, cliquez ici pour rejoindre votre section.';
 $PALANG['pMenu_main'] = 'Menu principal';
 
@@ -58,7 +60,7 @@ $PALANG['pMenu_password'] = 'Mot de pass
 $PALANG['pMenu_viewlog'] = 'Journal';
 $PALANG['pMenu_logout'] = 'Sortir';
 
-$PALANG['pMain_welcome'] = 'Bienvenue sur Postfix Admin!';
+$PALANG['pMain_welcome'] = 'Bienvenue sur Postfix Admin !';
 $PALANG['pMain_overview'] = 'Visualiser vos alias et comptes courriels. (Modifier/Effacer)';
 $PALANG['pMain_create_alias'] = 'Ajouter un nouvel alias Ã  votre domaine.';
 $PALANG['pMain_create_mailbox'] = 'Ajouter un nouveau compte courriel Ã  votre domaine.';
@@ -73,126 +75,138 @@ $PALANG['pOverview_title'] = ':: Domaine
 $PALANG['pOverview_up_arrow'] = 'Remonter';
 $PALANG['pOverview_right_arrow'] = 'Page suivante';
 $PALANG['pOverview_left_arrow'] = 'Page prÃ©cÃ©dente';
-$PALANG['pOverview_alias_domain_title'] = ':: Alias Domaine';
+$PALANG['pOverview_alias_domain_title'] = ':: Alias de domaine';
 $PALANG['pOverview_alias_title'] = ':: Alias';
 $PALANG['pOverview_mailbox_title'] = ':: Comptes courriels';
 $PALANG['go'] = 'Aller';
 $PALANG['pOverview_welcome'] = 'Vue d\'ensemble pour ';
-$PALANG['pOverview_alias_domain_aliases'] = 'Alias Domaines';
+$PALANG['pOverview_alias_domain_aliases'] = 'Alias de Domaines';
 $PALANG['pOverview_alias_address'] = 'De';
 $PALANG['active'] = 'Actif';
 $PALANG['and_x_more'] = '[et %s en plus...]';
 $PALANG['pOverview_mailbox_username'] = 'courriel';
 $PALANG['name'] = 'Nom';
-$PALANG['pOverview_mailbox_quota'] = 'Limite (MB)';
+$PALANG['pOverview_mailbox_quota'] = 'Limite (Mo)';
 $PALANG['pOverview_vacation_edit'] = 'REPONDEUR ACTIVE';
 $PALANG['pOverview_vacation_option'] = 'Configurer le rÃ©pondeur';
 $PALANG['no_domains_for_this_admin'] = 'Vous n\'avez de permissions pour aucun domaine.';
-$PALANG['no_domains_exist'] = 'Vous devez crÃ©er au moins un domaine avant d\'utiliser Liste Virtuels.';
+$PALANG['no_domains_exist'] = 'Vous devez crÃ©er au moins un domaine avant d\'utiliser la Liste des Virtuels.';
 
 $PALANG['domain'] = 'Domaine';
-$PALANG['pOverview_get_alias_domains'] = 'Alias Domaine';
+$PALANG['pOverview_get_alias_domains'] = 'Alias de domaine';
 $PALANG['mailboxes'] = 'Comptes courriels';
-$PALANG['pOverview_get_quota'] = 'Limite compte courriels (MB)';
+$PALANG['pOverview_get_quota'] = 'Limite compte courriels (Mo)';
 
 $PALANG['pDelete_delete_error'] = 'Impossible d\'effacer cette entrÃ©e ';
 $PALANG['pDelete_delete_success'] = '%s supprimÃ©.';
 $PALANG['pDelete_domain_error'] = 'Ce domaine n\'est pas le votre ';
 $PALANG['pDelete_alias_error'] = 'Impossible d\'effacer cet alias ';
 $PALANG['pCreate_alias_domain_welcome'] = 'Les adresses mirroirs de l\'un de vos domaines vers un autre.';
-$PALANG['pCreate_alias_domain_alias'] = 'Alias Domaine';
-$PALANG['pCreate_alias_domain_alias_text'] = 'Le domaine dans lequel les courriels viennent.';
-$PALANG['pCreate_alias_domain_target'] = 'Domaine Cible';
-$PALANG['pCreate_alias_domain_target_text'] = 'Le domaine o??s mails doivent aller.';
-$PALANG['pCreate_alias_domain_error1'] = 'Vous n\'etes pas autorisÃ© a crÃ©er la configuration choisie.';
-$PALANG['pCreate_alias_domain_error2'] = 'La configuration choisie est invalide, merci d\'en choisir une autre!';
-$PALANG['alias_domain_already_exists'] = 'Ce domaine est dÃ©jÃ  un alias de domaine!';
-$PALANG['alias_domain_does_not_exist'] = 'Ce domaine n\'est pas un alias de domaine!';
-$PALANG['alias_domain_create_failed'] = 'Echec de la crÃ©ation de l\'alias de domaine!';
-$PALANG['alias_domain_change_failed'] = 'Echec de la modification de l\'alias de domaine!';
+$PALANG['pCreate_alias_domain_alias'] = 'Alias de domaine';
+$PALANG['pCreate_alias_domain_alias_text'] = 'Le domaine de rÃ©cÃ©ption du courrier (source).';
+$PALANG['pCreate_alias_domain_target'] = 'Domaine cible';
+$PALANG['pCreate_alias_domain_target_text'] = 'Le domaine qui va rÃ©ceptionner le courrier Ã  la place.';
+$PALANG['pCreate_alias_domain_error1'] = 'Vous n\'Ãªtes pas autorisÃ© a crÃ©er la configuration choisie.';
+$PALANG['pCreate_alias_domain_error2'] = 'La configuration choisie est invalide, merci d\'en choisir une autre !';
+$PALANG['alias_domain_already_exists'] = 'Ce domaine est dÃ©jÃ  un alias de domaine !';
+$PALANG['alias_domain_does_not_exist'] = 'Ce domaine n\'est pas un alias de domaine !';
+$PALANG['alias_domain_create_failed'] = 'Ã‰chec de la crÃ©ation de l\'alias de domaine !';
+$PALANG['alias_domain_change_failed'] = 'Ã‰chec de la modification de l\'alias de domaine !';
 $PALANG['pCreate_alias_domain_error4'] = 'Tous les domaines sont dÃ©jÃ  un alias.';
 $PALANG['pCreate_alias_domain_success'] = 'L\'alias de domaine %s a Ã©tÃ© crÃ©Ã©.';
 $PALANG['alias_domain_changed'] = 'L\'alias de domaine %s a Ã©tÃ© modifiÃ©.';
-$PALANG['alias_domain_to_itsself'] = 'Un domaine ne peut pas Ãªtre son propre alias!';
-$PALANG['delete_domain_aliasdomain_target'] = 'Le domaine est la cible d\un ou plusieurs alias de domains et ne peut-Ãªtre supprimÃ©! (Supprimez les alias de domaine d\'abord.)';
-$PALANG['pCreate_alias_address_text_error1'] = 'Cet alias n\'est pas valide!';
-$PALANG['alias_does_not_exist'] = 'Cet alias n\'existe pas!';
-$PALANG['email_address_already_exists'] = 'Ce compte courriel existe dÃ©jÃ , choisissez-en un autre!';
+$PALANG['alias_domain_to_itsself'] = 'Un domaine ne peut pas Ãªtre son propre alias !';
+$PALANG['delete_domain_aliasdomain_target'] = 'Le domaine est la cible d\'un ou plusieurs alias de domaine et ne peut-Ãªtre supprimÃ© ! (Supprimez les alias de domaine d\'abord.)';
+$PALANG['pCreate_alias_address_text_error1'] = 'Cet alias n\'est pas valide !';
+$PALANG['alias_does_not_exist'] = 'Cet alias n\'existe pas !';
+$PALANG['email_address_already_exists'] = 'Ce compte courriel existe dÃ©jÃ , choisissez-en un autre !';
 $PALANG['pCreate_alias_address_text_error3'] = 'Vous avez atteint votre limite d\'alias crÃ©Ã©s !';
 $PALANG['pCreate_alias_goto_text'] = 'Destinataires des courriels.';
-$PALANG['pCreate_alias_goto_text_error'] = 'le champ Ã€ contient des erreurs!';
-$PALANG['pCreate_alias_result_error'] = 'Echec de la crÃ©ation de l\'alias %s!';
+$PALANG['pCreate_alias_goto_text_error'] = 'le champ Ã€ contient des erreurs !';
+$PALANG['pCreate_alias_result_error'] = 'Ã‰chec de la crÃ©ation de l\'alias %s !';
 $PALANG['pCreate_alias_result_success'] = 'L\'alias %s a Ã©tÃ© ajoutÃ© !';
-$PALANG['alias_updated'] = 'L\'alias %s a Ã©tÃ© mis Ã  jour!'; # XXX
-$PALANG['pCreate_alias_catchall_text'] = 'Pour ajouter un alias global, utilisez "*". Pour un transfert de domaine Ã  domaine, utilisez "*@domain.tld" dans le champs A.'; # XXX check/beautify - was split in two lines before
-$PALANG['mailbox_alias_cant_be_deleted'] = 'Cet alias appartient Ã  un compte courriel et ne peut Ãªtre supprimÃ©!';
-$PALANG['protected_alias_cant_be_deleted'] = 'The alias %s is protected and can only be deleted by a superadmin'; # XXX
+$PALANG['alias_updated'] = 'L\'alias %s a Ã©tÃ© mis Ã  jour !';
+$PALANG['pCreate_alias_catchall_text'] = 'Pour ajouter un alias global, utilisez "*". Pour un transfert de domaine Ã  domaine, utilisez "*@domain.tld" dans le champ Ã€.';
+$PALANG['mailbox_alias_cant_be_deleted'] = 'Cet alias appartient Ã  un compte courriel et ne peut donc pas Ãªtre supprimÃ© !';
+$PALANG['protected_alias_cant_be_deleted'] = 'L\'alias %s est protÃ©gÃ© et ne peut Ãªtre supprimÃ© que par un Super Administrateur.';
 
 $PALANG['pEdit_alias_welcome'] = 'Modifier les paramÃ¨tres de transfert.';
 $PALANG['pEdit_alias_help'] = 'Cibles multiples acceptÃ©es, une entrÃ©e par ligne.';
 $PALANG['alias'] = 'Alias';
 $PALANG['to'] = 'Ã€';
-$PALANG['pEdit_alias_goto_text_error1'] = 'Vous devez entrer quelques choses dans le champ Ã€';
-$PALANG['pEdit_alias_goto_text_error2'] = 'L\'adresse courriel que vous avez entrÃ© est invalide: ';
-$PALANG['pEdit_alias_domain_result_error'] = 'Impossible de modifier cet alias de domaine!';
-$PALANG['pEdit_alias_forward_and_store'] = 'Transferer une copie.';
-$PALANG['pEdit_alias_forward_only'] = 'Transferer les messages sans conserver de copie.';
-$PALANG['pEdit_alias_result_error'] = 'Echec de la modification de l\'alias %s!';
+$PALANG['pEdit_alias_goto_text_error1'] = 'Vous devez renseigner quelque chose dans le champ Ã€';
+$PALANG['pEdit_alias_goto_text_error2'] = 'L\'adresse email que vous avez indiquÃ© est invalide: ';
+$PALANG['pEdit_alias_domain_result_error'] = 'Impossible de modifier cet alias de domaine !';
+$PALANG['pEdit_alias_forward_and_store'] = 'Conserver une copie des messages dans la boite aux lettres.';
+$PALANG['pEdit_alias_forward_only'] = 'TransfÃ©rer les messages sans conserver de copie.';
+$PALANG['pEdit_alias_result_error'] = 'Ã‰chec de la modification de l\'alias %s !';
 
 $PALANG['pCreate_mailbox_welcome'] = 'Ajouter un nouveau compte courriel Ã  votre domaine.';
-$PALANG['pCreate_mailbox_username_text_error1'] = 'L\'adresse courriel est invalide!';
-$PALANG['pCreate_mailbox_username_text_error3'] = 'Vous avez atteint le nombre maximum de compte courriel !';
-$PALANG['pCreate_mailbox_password_text'] = 'Mot de passe pour compte POP3/IMAP';
+$PALANG['pCreate_mailbox_username_text_error1'] = 'L\'adresse email est invalide !';
+$PALANG['pCreate_mailbox_username_text_error3'] = 'Vous avez atteint le nombre maximum de comptes courriel !';
+$PALANG['pCreate_mailbox_password_text'] = 'Mot de passe pour le compte POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Nom complet';
+$PALANG['pCreate_mailbox_phone'] = 'TÃ©lÃ©phone mobile';
+$PALANG['pCreate_mailbox_phone_desc'] = "UtilisÃ© pour l'envoi de SMS en cas d'oubli du mot de passe";
+$PALANG['pCreate_mailbox_email'] = 'E-mail secondaire';
+$PALANG['pCreate_mailbox_email_desc'] = "UtilisÃ© en cas d'oubli du mot de passe";
 $PALANG['pCreate_mailbox_mail'] = 'Envoyer le message de bienvenue';
-$PALANG['pCreate_mailbox_result_error'] = 'Echec de la crÃ©ation du compte courriel %s!';
-$PALANG['pCreate_mailbox_result_success'] = 'Le compte courriel %s a Ã©tÃ© ajoutÃ© Ã  la table des comptes!';
-$PALANG['pCreate_mailbox_result_succes_nosubfolders'] = 'Le compte courriel %s a Ã©tÃ© ajoutÃ© Ã  la table, mais un ou plusieurs dossiers prÃ©dÃ©finis n\'ont pu Ãªtre crÃ©Ã©s!';
+$PALANG['pCreate_mailbox_result_error'] = 'Ã‰chec de la crÃ©ation du compte courriel %s !';
+$PALANG['pCreate_mailbox_result_success'] = 'Le compte courriel %s a Ã©tÃ© ajoutÃ© Ã  la table des comptes !';
+$PALANG['pCreate_mailbox_result_succes_nosubfolders'] = 'Le compte courriel %s a Ã©tÃ© ajoutÃ© Ã  la table, mais un ou plusieurs dossiers prÃ©dÃ©finis n\'ont pu Ãªtre crÃ©Ã©s !';
 $PALANG['mailbox_updated'] = "Le compte courriel %s a Ã©tÃ© mis Ã  jour.";
-$PALANG['mailbox_update_failed'] = "Echec de la mise Ã  jour du compte courriel %s!";
+$PALANG['mailbox_update_failed'] = "Ã‰chec de la mise Ã  jour du compte courriel %s !";
 
 $PALANG['pEdit_mailbox_welcome'] = 'Modifier un compte courriel.';
 $PALANG['pEdit_mailbox_username'] = 'Nom d\'utilisateur';
-$PALANG['pEdit_mailbox_password_text_error'] = 'Le mot de passe entrÃ© ne correspond pas!';
+$PALANG['pEdit_mailbox_password_text_error'] = 'Le mot de passe indiquÃ© ne correspond pas !';
 $PALANG['pEdit_mailbox_quota'] = 'Limite';
-$PALANG['pEdit_mailbox_quota_text'] = 'MB';
+$PALANG['pEdit_mailbox_quota_text'] = 'Mo';
 $PALANG['mb_max'] = 'Mo (max: %s)';
-$PALANG['pEdit_mailbox_quota_text_error'] = 'La limite fournie est trop haute!';
+$PALANG['pEdit_mailbox_quota_text_error'] = 'La limite fournie est trop Ã©levÃ©e !';
 $PALANG['pEdit_mailbox_domain_error'] = 'Ce domaine n\'est pas le votre: ';
 $PALANG['pEdit_mailbox_result_error'] = 'Impossible de modifier le compte courriel !';
 
-$PALANG['pPassword_welcome'] = 'Changer votre mot de passe.';
+$PALANG['pPassword_welcome'] = 'Modifier votre mot de passe.';
 $PALANG['pPassword_admin'] = 'Entrer';
 $PALANG['pPassword_password_current'] = 'Mot de passe actuel';
-$PALANG['pPassword_password_current_text_error'] = 'Vous n\'avez pas fournit le mot de passe actuel !';
+$PALANG['pPassword_password_current_text_error'] = 'Vous n\'avez pas fourni le mot de passe actuel !';
 $PALANG['pPassword_password'] = 'Nouveau mot de passe';
 $PALANG['pPassword_password2'] = 'Nouveau mot de passe (confirmation)';
-$PALANG['pPassword_password_text_error'] = 'Le mot de passe fourni ne correspond pas ou est vide!';
+$PALANG['pPassword_password_text_error'] = 'Le mot de passe fourni ne correspond pas ou est vide !';
 $PALANG['change_password'] = 'Changer le mot de passe';
-$PALANG['pPassword_result_error'] = 'Impossible de changer le mot de passe de %s!';
-$PALANG['pPassword_result_success'] = 'Le mot de passe de %s a Ã©tÃ© change!';
+$PALANG['pPassword_result_error'] = 'Impossible de changer le mot de passe de %s !';
+$PALANG['pPassword_result_success'] = 'Le mot de passe de %s a Ã©tÃ© changÃ© !';
+$PALANG['pPassword_recovery_title'] = 'Suivez les instructions pour rÃ©initialiser votre mot de passe.';
+$PALANG['pPassword_recovery_button'] = 'Envoyez-moi le code';
+$PALANG['pPassword_recovery_email_body'] = "Bonjour,\n\nUtilisez le lien suivant pour modifier votre mot de passe :\n%s\n\nSalutations,\n\n" . $CONF['admin_name'];
+$PALANG['pPassword_recovery_sms_body'] = "Bonjour,\nLe code pour modifier votre mot de passe: %s\n" . $CONF['admin_name'];
+$PALANG['pPassword_recovery_processed'] = "Nous avons traitÃ© votre demande. Si le nom d'utilisateur que vous avez saisi est valide, vous recevrez par e-mail/SMS un code de rÃ©initialisation du mot de passe.";
+$PALANG['pPassword_password_code'] = 'Code reÃ§u par email/SMS';
+$PALANG['pPassword_code_text_error'] = 'Code invalide';
+
 $PALANG['pEdit_vacation_set'] = 'Activer le rÃ©pondeur';
 $PALANG['pEdit_vacation_remove'] = 'DÃ©sactiver le rÃ©pondeur';
-$PALANG['pVacation_result_error'] = 'Impossible de mettre Ã  jour les rÃ©glages du rÃ©pondeur de %s!';
-$PALANG['pVacation_result_removed'] = 'Le rÃ©pondeur de %s a Ã©tÃ© dÃ©sactivÃ©!';
-$PALANG['pVacation_result_added'] = 'Le rÃ©pondeur de %s a Ã©tÃ© activÃ©!';
+$PALANG['pVacation_result_error'] = 'Impossible de mettre Ã  jour les paramÃ¨tres du rÃ©pondeur de %s !';
+$PALANG['pVacation_result_removed'] = 'Le rÃ©pondeur de %s a Ã©tÃ© dÃ©sactivÃ© !';
+$PALANG['pVacation_result_added'] = 'Le rÃ©pondeur de %s a Ã©tÃ© activÃ© !';
 $PALANG['pVacation_reply_type'] = 'Type de rÃ©ponse';
 $PALANG['pVacation_reply_delay_time'] = 'Intervalle';
 $PALANG['pVacation_reply_delay_time_text'] = 'DurÃ©e en secondes';
-$PALANG['pVacation_until_before_today'] = 'The Date of [Active until] is set  before Today'; # XXX
-$PALANG['pVacation_until_before_from'] = 'The Date of [Active until] is set before [Active from]'; # XXX
-$PALANG['reply_once'] = 'RÃ©pondre une fois';
+$PALANG['pVacation_until_before_today'] = 'La date de [Actif jusqu\'au] est antÃ¨rieure Ã  la date d\'aujourd\'hui';
+$PALANG['pVacation_until_before_from'] = 'La date de [Actif jusqu\'au] est antÃ¨rieure Ã  [Actif Ã  partir de]';
+$PALANG['reply_once'] = 'RÃ©pondre une seule fois';
 $PALANG['reply_every_mail'] = 'RÃ©pondre Ã  chaque message';
-$PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
+$PALANG['reply_once_per_day'] = 'RÃ©pondre une fois par jour';
 $PALANG['reply_once_per_week'] = 'RÃ©pondre une fois par semaine';
 
-$PALANG['pViewlog_welcome'] = 'Visualiser les 10 derniÃ¨res actions pour ';
+$PALANG['pViewlog_welcome'] = 'Visualiser les %s derniÃ¨res actions pour ';
 $PALANG['pViewlog_timestamp'] = 'Date/Heure';
 $PALANG['pViewlog_action'] = 'Action';
 $PALANG['pViewlog_data'] = 'Information';
-$PALANG['pViewlog_action_create_domain'] = 'crÃ©er domaine';
-$PALANG['pViewlog_action_delete_domain'] = 'supprimer domaine';
-$PALANG['pViewlog_action_edit_domain'] = 'modifier domaine';
+$PALANG['pViewlog_action_create_domain'] = 'crÃ©er le domaine';
+$PALANG['pViewlog_action_delete_domain'] = 'supprimer le domaine';
+$PALANG['pViewlog_action_edit_domain'] = 'modifier le domaine';
 $PALANG['pViewlog_action_create_mailbox'] = 'crÃ©er un compte courriel';
 $PALANG['pViewlog_action_delete_mailbox'] = 'supprimer un compte courriel';
 $PALANG['pViewlog_action_edit_mailbox'] = 'Ã©diter un compte courriel';
@@ -204,32 +218,32 @@ $PALANG['pViewlog_action_delete_alias']
 $PALANG['pViewlog_action_delete_alias_domain'] = 'supprimer un alias de domaine';
 $PALANG['pViewlog_action_edit_alias'] = 'Ã©diter un alias';
 $PALANG['pViewlog_action_edit_alias_state'] = 'activer un alias';
-$PALANG['pViewlog_action_edit_alias_domain_state'] = 'editer alias de domaine actif';
+$PALANG['pViewlog_action_edit_alias_domain_state'] = 'Ã©diter alias de domaine actif';
 $PALANG['pViewlog_action_edit_password'] = 'changer le mot de passe';
-$PALANG['pViewlog_action_create_admin'] = 'crÃ©er un admin';
-$PALANG['pViewlog_action_edit_admin'] = 'modifier un admin';
-$PALANG['pViewlog_action_delete_admin'] = 'delete admin'; # XXX
+$PALANG['pViewlog_action_create_admin'] = 'crÃ©er un administrateur';
+$PALANG['pViewlog_action_edit_admin'] = 'modifier un administrateur';
+$PALANG['pViewlog_action_delete_admin'] = 'effacer un administrateur';
 $PALANG['pViewlog_action_edit_vacation'] = 'modifier le rÃ©pondeur';
-$PALANG['pViewlog_action_create_fetchmail'] = 'create fetchmail job'; # XXX
-$PALANG['pViewlog_action_edit_fetchmail'] = 'edit fetchmail job'; # XXX
-$PALANG['pViewlog_action_delete_fetchmail'] = 'delete fetchmail job'; # XXX
+$PALANG['pViewlog_action_create_fetchmail'] = 'crÃ©er une tÃ¢che de rÃ©cupÃ©ration du courrier';
+$PALANG['pViewlog_action_edit_fetchmail'] = 'Ã©diter la tÃ¢che de rÃ©cupÃ©ration du courrier';
+$PALANG['pViewlog_action_delete_fetchmail'] = 'effacer la tÃ¢che de rÃ©cupÃ©ration du courrier';
 
-$PALANG['pViewlog_result_error'] = 'Impossible de trouver le journal des Ã©vÃ©nements!';
+$PALANG['pViewlog_result_error'] = 'Impossible de trouver le journal des Ã©vÃ©nements !';
 
 $PALANG['pSendmail_welcome'] = 'Envoyer un courriel.';
 $PALANG['from'] = 'De';
 $PALANG['pSendmail_to'] = 'Ã€';
-$PALANG['pSendmail_to_text_error'] = 'Ã€ est vide ou ce n\'est pas une adresse courriel valide!';
+$PALANG['pSendmail_to_text_error'] = 'Le champ "Ã€" est vide ou il ne contient pas une adresse email valide !';
 $PALANG['subject'] = 'Sujet';
 $PALANG['pSendmail_subject_text'] = 'Bienvenue';
 $PALANG['pSendmail_body'] = 'Message';
 $PALANG['pSendmail_button'] = 'Envoyer le message';
-$PALANG['pSendmail_result_error'] = 'Erreur lors de l\'envoit du message! (%s)'; # XXX text change - new: Unable to send email to %s!
-$PALANG['pSendmail_result_success'] = 'Le message a Ã©tÃ© envoyÃ©! (%s)'; # XXX text change - new: Email sent to %s.
+$PALANG['pSendmail_result_error'] = 'Impossible d\'envoyer le courriel Ã  %s !';
+$PALANG['pSendmail_result_success'] = 'Le message a Ã©tÃ© envoyÃ© Ã  l\'adresse %s.';
 
-$PALANG['pAdminMenu_list_admin'] = 'Liste Administrateurs';
-$PALANG['pAdminMenu_list_domain'] = 'Liste Domaines';
-$PALANG['pAdminMenu_list_virtual'] = 'Liste Virtuels';
+$PALANG['pAdminMenu_list_admin'] = 'Liste des administrateurs';
+$PALANG['pAdminMenu_list_domain'] = 'Liste des domaines';
+$PALANG['pAdminMenu_list_virtual'] = 'Liste des virtuels';
 $PALANG['pAdminMenu_backup'] = 'Sauvegarde';
 $PALANG['pAdminMenu_create_domain_admins'] = 'Administrateurs de domaines';
 $PALANG['pAdminMenu_create_admin'] = 'Nouvel administrateur';
@@ -240,59 +254,60 @@ $PALANG['pAdminList_admin_count'] = 'Dom
 $PALANG['description'] = 'Description';
 $PALANG['aliases'] = 'Alias';
 $PALANG['pAdminList_domain_quota'] = 'Quota du domaine (Mo)';
-$PALANG['pAdminList_domain_backupmx'] = 'MX Backup';
+$PALANG['pAdminList_domain_backupmx'] = 'Backup MX';
 $PALANG['last_modified'] = 'DerniÃ¨re modification';
 
 
 $PALANG['pAdminCreate_domain_welcome'] = 'Ajouter un nouveau domaine';
-$PALANG['pAdminCreate_domain_domain_text_error'] = 'Le domaine existe dÃ©jÃ !';
-$PALANG['domain_does_not_exist'] = 'Ce domaine n\'existe pas!';
-$PALANG['pAdminCreate_domain_domain_text_error2'] = 'Le domaine est non valide!';
+$PALANG['pAdminCreate_domain_domain_text_error'] = 'Le domaine existe dÃ©jÃ  !';
+$PALANG['domain_does_not_exist'] = 'Ce domaine n\'existe pas !';
+$PALANG['pAdminCreate_domain_domain_text_error2'] = 'Le domaine n\'est pas valide !';
 $PALANG['pAdminCreate_domain_defaultaliases'] = 'Ajouter les alias par dÃ©faut';
 $PALANG['pAdminCreate_domain_button'] = 'Ajouter un domaine';
-$PALANG['pAdminCreate_domain_result_error'] = 'Impossible d\'ajouter le domaine %s!';
-$PALANG['pAdminCreate_domain_result_success'] = 'Le domaine %s a Ã©tÃ© ajoutÃ©!';
+$PALANG['pAdminCreate_domain_result_error'] = 'Impossible d\'ajouter le domaine %s !';
+$PALANG['pAdminCreate_domain_result_success'] = 'Le domaine %s a Ã©tÃ© ajoutÃ© !';
 $PALANG['domain_updated'] = 'Le domaine %s a Ã©tÃ© mis Ã  jour.';
-$PALANG['pAdminDelete_admin_error'] = 'Impossible de supprimer l\'admin!';
+$PALANG['pAdminDelete_admin_error'] = 'Impossible de supprimer l\'administrateur !';
 
-$PALANG['domain_postdel_failed'] = 'Le script postdeletion du domaine a Ã©chouÃ©, consultez la log!';
-$PALANG['domain_postcreate_failed'] = 'Le script postcreate du domaine a Ã©chouÃ©, consultez la log!';
-$PALANG['mailbox_postdel_failed'] = 'Le script postdeletion du compte courriel a Ã©chouÃ©, consultez la log!';
-$PALANG['mailbox_postedit_failed'] = 'Le script postedit du compte courriel a Ã©chouÃ©, consultez la log!';
-$PALANG['mailbox_postcreate_failed'] = 'Le script postcreate du compte courriel a Ã©chouÃ©, consultez la log!';
-$PALANG['pAdminDelete_alias_domain_error'] = 'Impossible de supprimÃ© cet alias de domaine!';
-$PALANG['domain_conflict_vacation_domain'] = 'You can\'t use the vacation domain as mail domain!'; # XXX
+$PALANG['domain_postdel_failed'] = 'Le script "postdeletion" du domaine a Ã©chouÃ©, consultez le journal !';
+$PALANG['domain_postcreate_failed'] = 'Le script "postcreate" du domaine a Ã©chouÃ©, consultez le journal !';
+$PALANG['mailbox_postdel_failed'] = 'Le script "postdeletion" du compte courriel a Ã©chouÃ©, consultez le journal !';
+$PALANG['mailbox_postedit_failed'] = 'Le script "postedit" du compte courriel a Ã©chouÃ©, consultez le journal !';
+$PALANG['mailbox_postcreate_failed'] = 'Le script "postcreate" du compte courriel a Ã©chouÃ©, consultez le journal !';
+$PALANG['pAdminDelete_alias_domain_error'] = 'Impossible de supprimer cet alias de domaine !';
+$PALANG['domain_conflict_vacation_domain'] = 'Vous ne pouvez pas utiliser le domaine configurÃ© pour les rÃ©ponses automatiques !';
 
 $PALANG['pAdminEdit_domain_welcome'] = 'Modifier un domaine';
 $PALANG['pAdminEdit_domain_aliases_text'] = '-1 = dÃ©sactivÃ© | 0 = illimitÃ©';
 $PALANG['pAdminEdit_domain_maxquota'] = 'Limite maximum';
-$PALANG['pAdminEdit_domain_maxquota_text'] = 'MB | -1 = dÃ©sactivÃ© | 0 = illimitÃ©';
+$PALANG['pAdminEdit_domain_maxquota_text'] = 'Mo | -1 = dÃ©sactivÃ© | 0 = illimitÃ©';
 $PALANG['pAdminEdit_domain_quota'] = 'Quota du Domaine';
 $PALANG['transport'] = 'Transport';
 $PALANG['pAdminEdit_domain_transport_text'] = 'Definir le transport';
-$PALANG['pAdminEdit_domain_backupmx'] = 'Le serveur est un "backup MX"';
-$PALANG['pAdminEdit_domain_result_error'] = 'Echec de la mise Ã  jour du domaine %s';
+$PALANG['pAdminEdit_domain_backupmx'] = 'Le serveur est un "Backup MX"';
+$PALANG['pAdminEdit_domain_result_error'] = 'Ã‰chec de la mise Ã  jour du domaine %s';
 
 $PALANG['pAdminCreate_admin_welcome'] = 'Ajouter un nouvel administrateur de domaine';
-$PALANG['email_address'] = 'adresse courriel';
-$PALANG['pAdminCreate_admin_username_text_error1'] = 'Ce n\'est pas une adresse courriel administrateur valide!';
-$PALANG['admin_already_exists'] = 'Cet administrateur existe dÃ©jÃ !';
-$PALANG['admin_does_not_exist'] = 'L\'administrateur n\'existe pas!';
+$PALANG['email_address'] = 'adresse email';
+$PALANG['pAdminCreate_admin_username_text_error1'] = 'Ce n\'est pas une adresse email administrateur valide !';
+$PALANG['admin_already_exists'] = 'Cet administrateur existe dÃ©jÃ  !';
+$PALANG['admin_does_not_exist'] = 'L\'administrateur n\'existe pas !';
 $PALANG['pAdminCreate_admin_button'] = 'Ajouter un administrateur';
 $PALANG['pAdminCreate_admin_result_error'] = 'L\'ajout de l\administrateur %s a Ã©chouÃ©';
-$PALANG['pAdminCreate_admin_result_success'] = 'L\'administrateur %s a Ã©tÃ© ajoutÃ©!';
+$PALANG['pAdminCreate_admin_result_success'] = 'L\'administrateur %s a Ã©tÃ© ajoutÃ© !';
 
 $PALANG['pAdminEdit_admin_welcome'] = 'Modifier un domaine';
 $PALANG['admin'] = 'Administrateur';
 $PALANG['password_again'] = 'Mot de passe (confirmation)';
 $PALANG['super_admin'] = 'Super administrateur';
-$PALANG['super_admin_desc'] = 'Les Super administrateurs ont accÃ¨s Ã  tous les domaines, ils peuvent gÃ©rer les domaines et les comptes d\administrateur.';
-$PALANG['pAdminEdit_admin_result_error'] = 'Impossible de modifier l\'administrateur %s!';
-$PALANG['pAdminEdit_admin_result_success'] = 'L\'administrateur %s a Ã©tÃ© ajoutÃ©!';
-
-$PALANG['pUsersLogin_welcome'] = 'Entrer votre adresse courriel pour modifier votre mot de passe et vos transferts.';
-$PALANG['pUsersLogin_username_incorrect'] = 'L\'adresse courriel est invalide. Assurez-vous d\'avoir correctement saisie votre adresse courriel!';
-$PALANG['pUsersLogin_password_incorrect'] = 'Votre mot de passe est invalide!';
+$PALANG['super_admin_desc'] = 'Les Super administrateurs ont accÃ¨s Ã  tous les domaines, ils peuvent gÃ©rer les domaines et les comptes d\'administrateur.';
+$PALANG['pAdminEdit_admin_result_error'] = 'Impossible de modifier l\'administrateur %s !';
+$PALANG['pAdminEdit_admin_result_success'] = 'L\'administrateur %s a Ã©tÃ© ajoutÃ© !';
+
+$PALANG['pUsersLogin_welcome'] = 'Entrer votre adresse email pour modifier votre mot de passe et vos transferts.';
+$PALANG['pUsersLogin_username_incorrect'] = 'L\'adresse email est invalide. Assurez-vous d\'avoir correctement saisi votre adresse email !';
+$PALANG['pUsersLogin_password_incorrect'] = 'Votre mot de passe est invalide !';
+$PALANG['pUsersLogin_password_recover'] = 'J\'ai oubliÃ© mon mot de passe';
 
 $PALANG['pUsersMenu_vacation'] = 'RÃ©ponse Automatique';
 $PALANG['pUsersMenu_edit_alias'] = 'Modifier votre transfert';
@@ -303,12 +318,12 @@ $PALANG['pUsersMain_edit_alias'] = 'Modi
 $PALANG['pUsersMain_password'] = 'Changer votre mot de passe.';
 
 $PALANG['pUsersVacation_welcome'] = 'RÃ©pondeur Automatique.';
-$PALANG['pUsersVacation_welcome_text'] = 'Votre repondeur automatique est dÃ©jÃ  configurÃ©! (%s)'; # XXX Text changed to: 'Auto response for %s is active!'
+$PALANG['pUsersVacation_welcome_text'] = 'Le repondeur automatique pour l\'adresse %s est dÃ©jÃ  configurÃ© !';
 $PALANG['pUsersVacation_subject_text'] = 'Notification d\'absence';
 $PALANG['message'] = 'Message';
 $PALANG['pUsersVacation_body_text'] = <<<EOM
 Je suis absent du  au .
-Pour toute urgence, merci de contacter.
+Pour toute urgence, merci de contacter .
 EOM;
 $PALANG['pUsersVacation_activefrom'] = 'Depuis';
 $PALANG['pUsersVacation_activeuntil'] = 'Jusqu\'au';
@@ -323,64 +338,66 @@ $PALANG['pBroadcast_title'] = 'Envoyer u
 $PALANG['pBroadcast_name'] = 'Votre nom';
 $PALANG['pBroadcast_success'] = 'Votre message gÃ©nÃ©ral a Ã©tÃ© envoyÃ©.';
 $PALANG['pAdminMenu_broadcast_message'] = 'message gÃ©nÃ©ral';
-$PALANG['pBroadcast_error_empty'] = 'Les champs Nom, Sujet et Message ne peuvent pas Ãªtre vides!';
+$PALANG['pBroadcast_error_empty'] = 'Les champs "Nom", "Sujet" et "Message" ne peuvent pas Ãªtre vides !';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'Non dÃ©livrable ';
 $PALANG['pStatus_custom'] = 'DÃ©livrÃ© Ã  ';
 $PALANG['pStatus_popimap'] = 'POP/IMAP ';
-$PALANG['password_too_short'] = "Mot de passe trop court. - %s caractÃ¨res minimum";
-$PALANG['password_no_characters'] = "Votre mot de passe doit contenir au moins %s caractÃ¨res.";
-$PALANG['password_no_digits'] = "Votre mot de passe doit contenir au moins %s chiffres.";
-$PALANG['pInvalidDomainRegex'] = "Nom de domaine invalide %s, vÃ©rification regexp impossible";
-$PALANG['pInvalidDomainDNS'] = "Domaine invalide %s, et/ou non resolvable via les DNS";
-$PALANG['pInvalidMailRegex'] = "Adresse email %s invalide, vÃ©rification regexp impossible";
+$PALANG['password_too_short'] = 'Mot de passe trop court. - %s caractÃ¨res minimum';
+$PALANG['password_no_characters'] = 'Votre mot de passe doit contenir au moins %s caractÃ¨res.';
+$PALANG['password_no_digits'] = 'Votre mot de passe doit contenir au moins %s chiffres.';
+$PALANG['pInvalidDomainRegex'] = 'Nom de domaine invalide %s, vÃ©rification "regexp" impossible';
+$PALANG['pInvalidDomainDNS'] = 'Le domaine %s est invalide et/ou non resolvable via les DNS';
+$PALANG['pInvalidMailRegex'] = 'L\'adresse email %s est invalide, vÃ©rification "regexp" impossible';
 $PALANG['pFetchmail_welcome'] = 'RÃ©cupÃ©rer le courrier pour :';
 $PALANG['pFetchmail_new_entry'] = 'Nouvelle entrÃ©e';
-$PALANG['fetchmail_already_exists']         = 'This fetchmail job already exists!'; # XXX
-$PALANG['fetchmail_does_not_exist']         = 'This fetchmail job does not exist!'; # XXX
-$PALANG['pFetchmail_database_save_error'] = 'Impossible d\'enregistrer cette entrÃ©e dans la base!';
-$PALANG['pFetchmail_database_save_success'] = 'EntrÃ©e enregistrÃ©e dans la base.';
-$PALANG['pFetchmail_error_invalid_id'] = 'Aucune entrÃ©e trouvÃ©e avec l\'ID %s!';
-$PALANG['pFetchmail_invalid_mailbox'] = 'Compte courriel incorrect!';
-$PALANG['pFetchmail_server_missing'] = 'Merci d\'entrer le nom du serveur distant!';
-$PALANG['pFetchmail_user_missing'] = 'Merci d\'entrer le nom de l\'utilisateur distant!';
-$PALANG['pFetchmail_password_missing'] = 'Merci d\'entrer le mot de passe distant!';
-$PALANG['pFetchmail_field_id']              = 'ID';
-$PALANG['pFetchmail_field_mailbox']         = 'Compte courriel';
-$PALANG['pFetchmail_field_src_server']      = 'Serveur';
-$PALANG['pFetchmail_field_src_auth']        = 'Type Auth';
-$PALANG['pFetchmail_field_src_user']        = 'Utilisateur';
-$PALANG['pFetchmail_field_src_password']    = $PALANG['password']; # needed until fetchmail is migrated into FetchmailHandler
-$PALANG['pFetchmail_field_src_folder']      = 'Dossier';
-$PALANG['pFetchmail_field_poll_time']       = 'FrÃ©quence';
-$PALANG['pFetchmail_field_fetchall']        = 'Tout rÃ©cupÃ©rer';
-$PALANG['pFetchmail_field_keep']            = 'Conserver';
-$PALANG['pFetchmail_field_protocol']        = 'Protocole';
-$PALANG['pFetchmail_field_usessl']          = 'SSL activÃ©';
-$PALANG['pFetchmail_field_sslcertck']       = 'VÃ©rification du certificat SSL';
-$PALANG['pFetchmail_field_sslcertpath']     = 'Chemin des certificats SSL';
-$PALANG['pFetchmail_field_sslfingerprint']  = 'Empreinte SSL (md5)';
-$PALANG['pFetchmail_field_extra_options']   = 'Options supplÃ©mentaires';
-$PALANG['pFetchmail_field_mda']             = 'MDA';
-$PALANG['pFetchmail_field_date']            = 'Date';
-$PALANG['pFetchmail_field_returned_text']   = 'Message retour';
-$PALANG['pFetchmail_desc_id']               = 'Identifiant';
-$PALANG['pFetchmail_desc_mailbox']          = 'Compte courriel local';
-$PALANG['pFetchmail_desc_src_server']       = 'Serveur distant';
-$PALANG['pFetchmail_desc_src_auth']         = 'Surtout \'password\''; # Translators: Please do NOT translate 'password' here
-$PALANG['pFetchmail_desc_src_user']         = 'Utilisateur distant';
-$PALANG['pFetchmail_desc_src_password']     = 'Mot de passe distant';
-$PALANG['pFetchmail_desc_src_folder']       = 'Dossier distant';
-$PALANG['pFetchmail_desc_poll_time']        = 'VÃ©rifier toutes les ... minutes';
-$PALANG['pFetchmail_desc_fetchall']         = 'RÃ©cupÃ©rer tous les messages, nouveaux et dÃ©jÃ  lus';
-$PALANG['pFetchmail_desc_keep']             = 'Conserver une copie des messages sur le serveur';
-$PALANG['pFetchmail_desc_protocol']         = 'Protocole Ã  utiliser';
-$PALANG['pFetchmail_desc_usessl']           = 'Encryption SSL';
-$PALANG['pFetchmail_desc_extra_options']    = 'Options supplÃ©mentaires de Fetchmail';
-$PALANG['pFetchmail_desc_mda']              = 'Mail Delivery Agent';
-$PALANG['pFetchmail_desc_date']             = 'Date derniÃ¨re vÃ©rification/changement configuration';
-$PALANG['pFetchmail_desc_returned_text']    = 'Message derniÃ¨re vÃ©rification';
-$PALANG['dateformat_pgsql'] = 'dd-mm-YYYY'; # translators: rearrange to your local date format, but make sure it's a valid PostgreSQL date format
-$PALANG['dateformat_mysql'] = '%d-%m-%Y';   # translators: rearrange to your local date format, but make sure it's a valid MySQL date format
+$PALANG['fetchmail_already_exists'] = 'Cette tÃ¢che de rÃ©cupÃ©ration du courrier existe dÃ©jÃ  !';
+$PALANG['fetchmail_does_not_exist'] = 'Cette tÃ¢che de rÃ©cupÃ©ration du courrier n\'existe pas !';
+$PALANG['pFetchmail_database_save_error'] = 'Impossible d\'enregistrer cette entrÃ©e dans la base !';
+$PALANG['pFetchmail_database_save_success'] = 'EntrÃ©e correctement enregistrÃ©e dans la base.';
+$PALANG['pFetchmail_error_invalid_id'] = 'Aucune entrÃ©e trouvÃ©e avec l\'ID %s !';
+$PALANG['pFetchmail_invalid_mailbox'] = 'Compte courriel incorrect !';
+$PALANG['pFetchmail_server_missing'] = 'Merci d\'indiquer le nom du serveur distant !';
+$PALANG['pFetchmail_user_missing'] = 'Merci d\'indiquer le nom de l\'utilisateur distant !';
+$PALANG['pFetchmail_password_missing'] = 'Merci d\'indiquer le mot de passe distant !';
+$PALANG['pFetchmail_field_id'] = 'ID';
+$PALANG['pFetchmail_field_mailbox'] = 'Compte courriel';
+$PALANG['pFetchmail_field_src_server'] = 'Serveur';
+$PALANG['pFetchmail_field_src_auth'] = 'Type Auth';
+$PALANG['pFetchmail_field_src_user'] = 'Utilisateur';
+$PALANG['pFetchmail_field_src_password'] = $PALANG['password']; # needed until fetchmail is migrated into FetchmailHandler
+$PALANG['pFetchmail_field_src_folder'] = 'Dossier';
+$PALANG['pFetchmail_field_poll_time'] = 'FrÃ©quence';
+$PALANG['pFetchmail_field_fetchall'] = 'Tout rÃ©cupÃ©rer';
+$PALANG['pFetchmail_field_keep'] = 'Conserver';
+$PALANG['pFetchmail_field_protocol'] = 'Protocole';
+$PALANG['pFetchmail_field_usessl'] = 'SSL activÃ©';
+$PALANG['pFetchmail_field_sslcertck'] = 'VÃ©rification du certificat SSL';
+$PALANG['pFetchmail_field_sslcertpath'] = 'Chemin des certificats SSL';
+$PALANG['pFetchmail_field_sslfingerprint'] = 'Empreinte SSL (md5)';
+$PALANG['pFetchmail_field_extra_options'] = 'Options supplÃ©mentaires';
+$PALANG['pFetchmail_field_mda'] = 'MDA';
+$PALANG['pFetchmail_field_date'] = 'Date';
+$PALANG['pFetchmail_field_returned_text'] = 'Message retour';
+$PALANG['pFetchmail_desc_id'] = 'Identifiant';
+$PALANG['pFetchmail_desc_mailbox'] = 'Compte courriel local';
+$PALANG['pFetchmail_desc_src_server'] = 'Serveur distant';
+$PALANG['pFetchmail_desc_src_auth'] = 'Surtout \'password\''; # Translators: Please do NOT translate 'password' here
+$PALANG['pFetchmail_desc_src_user'] = 'Utilisateur distant';
+$PALANG['pFetchmail_desc_src_password'] = 'Mot de passe distant';
+$PALANG['pFetchmail_desc_src_folder'] = 'Dossier distant';
+$PALANG['pFetchmail_desc_poll_time'] = 'VÃ©rifier toutes les ... minutes';
+$PALANG['pFetchmail_desc_fetchall'] = 'RÃ©cupÃ©rer tous les messages, nouveaux et dÃ©jÃ  lus';
+$PALANG['pFetchmail_desc_keep'] = 'Conserver une copie des messages sur le serveur';
+$PALANG['pFetchmail_desc_protocol'] = 'Protocole Ã  utiliser';
+$PALANG['pFetchmail_desc_usessl'] = 'Encryption SSL';
+$PALANG['pFetchmail_desc_extra_options'] = 'Options supplÃ©mentaires de Fetchmail';
+$PALANG['pFetchmail_desc_mda'] = 'Mail Delivery Agent';
+$PALANG['pFetchmail_desc_date'] = 'Date de la derniÃ¨re vÃ©rification/changement de la configuration';
+$PALANG['pFetchmail_desc_returned_text'] = 'Message de la derniÃ¨re vÃ©rification';
+$PALANG['dateformat_pgsql'] = 'dd-mm-YYYY';
+$PALANG['dateformat_mysql'] = '%d-%m-%Y';
 
 $PALANG['please_keep_this_as_last_entry'] = ''; # needed for language-check.sh
 /* vim: set expandtab ft=php softtabstop=3 tabstop=3 shiftwidth=3: */
diff -pruN 3.0.2-2/languages/hr.lang 3.2-2/languages/hr.lang
--- 3.0.2-2/languages/hr.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/hr.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: hr.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Croatian
 // by Daniel Radetic <drade at boobah dot info>
@@ -142,6 +142,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Dostigli ste vaÂš limit poÂštanskih ormariÄ‡a!';
 $PALANG['pCreate_mailbox_password_text'] = 'Lozinka za POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Puno ime';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Stvori poÂštanski ormariÄ‡'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'PoÂštanski ormariÄ‡ nije moguÄe stvoriti! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'PoÂštanski ormariÄ‡ je uspjeÂšno stvoren! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -169,6 +173,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Promijeni lozinku';
 $PALANG['pPassword_result_error'] = 'Lozinku nije bilo moguÄe promijeniti! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Lozinka je uspjeÂšno promijenjena! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -184,7 +195,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Pogledaj zadnjih 10 akcija za ';
+$PALANG['pViewlog_welcome'] = 'Pogledaj zadnjih %s akcija za ';
 $PALANG['pViewlog_timestamp'] = 'Vrijeme';
 $PALANG['pViewlog_action'] = 'Akcija';
 $PALANG['pViewlog_data'] = 'Podaci';
@@ -290,6 +301,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Korisnici poÂštanskih ormariÄ‡a ukoliko Âželite promjeniti lozinku ili aliase.';
 $PALANG['pUsersLogin_username_incorrect'] = 'KorisniÄko ime nije pravilno! Morate upotrijebiti adresu vaÂše e-poÂšte!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Lozinka nije pravilna!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Obavijest o odsutnosti';
 $PALANG['pUsersMenu_edit_alias'] = 'Promijeni preusmjerenje';
@@ -320,6 +332,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.'; # XXX
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/hu.lang 3.2-2/languages/hu.lang
--- 3.0.2-2/languages/hu.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/hu.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: hu.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Hungarian
 // by Christian Hamar <krics at linuxforum dot hu> and Levente Farkas <lfarkas at lfarkas dot org>
@@ -145,6 +145,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'ElÃ©rted a maximÃ¡lis postafiÃ³k szÃ¡mot!';
 $PALANG['pCreate_mailbox_password_text'] = 'JelszÃ³ a POP3/IMAP -hoz';
 $PALANG['pCreate_mailbox_name_text'] = 'Teljes nÃ©v';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'PostafiÃ³k lÃ©trehozÃ¡sa'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'NemsikerÃ¼lt a postafiÃ³kot felvenni a mailbox adatbÃ¡zis tÃ¡blÃ¡ba! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'A postafiÃ³kot sikeresen felvettÃ¼k a mailbox adatbÃ¡zis tÃ¡blÃ¡ba! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -172,6 +176,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'JelszÃ³ megvÃ¡ltoztatÃ¡sa';
 $PALANG['pPassword_result_error'] = 'NemsikerÃ¼lt megvÃ¡ltoztatni a jelszavad! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'A jelszavad megvÃ¡ltozott! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 
 $PALANG['pEdit_vacation_set'] = 'Nem vagyok elÃ©rhatÅ‘ Ã¼zenet mÃ³dosÃ­tÃ¡s / beÃ¡llÃ­tÃ¡s';
 $PALANG['pEdit_vacation_remove'] = 'Nem vagyok elÃ©rhatÅ‘ Ã¼zenet tÃ¶rlÃ©se';
@@ -189,7 +200,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Az utolsÃ³ 10 esemÃ©ny megtekintÃ©se: ';
+$PALANG['pViewlog_welcome'] = 'Az utolsÃ³ %s esemÃ©ny megtekintÃ©se: ';
 $PALANG['pViewlog_timestamp'] = 'IdÃµbÃ©lyeg';
 $PALANG['pViewlog_action'] = 'AkciÃ³';
 $PALANG['pViewlog_data'] = 'Adat';
@@ -297,6 +308,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'A felhasznÃ¡lÃ³k ezen a felÃ¼leten tudnak bejelentkezni a levelezÃµ rendszerbe a sajÃ¡t felhasznÃ¡lÃ³ nevÃ¼kkel (azaz email cÃ­mÃ¼kkel) Ã©s itt tudjÃ¡k megvÃ¡ltoztatni az aliasokat, stb..'; # XXX check/beautify - was split in two lines before
 $PALANG['pUsersLogin_username_incorrect'] = 'Nem megfelelÃµ a Login (email) cÃ­m! KÃ©rlek pontosÃ­tsd!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Nem megfelelÃµ a jelszavad!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Automatikus VÃ¡lasz';
 $PALANG['pUsersMenu_edit_alias'] = 'ÃtirÃ¡nyÃ­tÃ¡s beÃ¡llÃ­tÃ¡sa';
@@ -332,6 +344,8 @@ $PALANG['pBroadcast_name'] = 'Neved';
 $PALANG['pBroadcast_success'] = 'Broadcast Ã¼zeneted elkÃ¼ldve.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast Ã¼zenet'; # XXX partly translated
 $PALANG['pBroadcast_error_empty'] = 'A nÃ©v, tÃ©ma Ã©s Ã¼zenet mezÅ‘k nem lehetnek Ã¼resek !';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 
 $PALANG['pStatus_undeliverable'] = 'lehet hogy nem kÃ©zbesÃ­thetÅ‘ ';
 $PALANG['pStatus_custom'] = 'Ide kÃ©zbesÃ­tÅ‘dik ';
diff -pruN 3.0.2-2/languages/index.php 3.2-2/languages/index.php
--- 3.0.2-2/languages/index.php	2007-11-11 23:36:46.000000000 +0000
+++ 3.2-2/languages/index.php	2018-05-02 20:37:27.000000000 +0000
@@ -1,6 +1,6 @@
 <?php
-// 
-// Postfix Admin 
+//
+// Postfix Admin
 // by Mischa Peters <mischa at high5 dot net>
 // Copyright (c) 2002 - 2005 High5!
 // Licensed under GPL for more info check GPL-LICENSE.TXT
@@ -17,6 +17,5 @@
 //
 // -none-
 //
-header ("Location: ../login.php");
+header("Location: ../login.php");
 exit;
-?>
diff -pruN 3.0.2-2/languages/is.lang 3.2-2/languages/is.lang
--- 3.0.2-2/languages/is.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/is.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: is.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Icelandic
 // by Gestur
@@ -143,6 +143,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'ÃžÃº hefur stofnaÃ° Ã¾au pÃ³stholf sem Ã¾Ãº hefur heimild til!';
 $PALANG['pCreate_mailbox_password_text'] = 'LykilorÃ° til aÃ° opna POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Fullt nafn';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Stofna pÃ³sthÃ³lf'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Get ekki bÃ¦tt viÃ° pÃ³sthÃ³lfi Ã­ mailbox tÃ¶fluna! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'PÃ³sthÃ³lfinu hefur veriÃ° bÃ¦tt viÃ° mailbox tÃ¶fluna! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -170,6 +174,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Breyta lykilorÃ°i';
 $PALANG['pPassword_result_error'] = 'Get ekki breytt lykilorÃ°i! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'LykilorÃ°inu hefur veriÃ° breytt! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -185,7 +196,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'SkoÃ°a sÃ­Ã°ustu 10 aÃ°gerÃ°ir fyrir ';
+$PALANG['pViewlog_welcome'] = 'SkoÃ°a sÃ­Ã°ustu %s aÃ°gerÃ°ir fyrir ';
 $PALANG['pViewlog_timestamp'] = 'TÃ­mi';
 $PALANG['pViewlog_action'] = 'aÃ°gerÃ°';
 $PALANG['pViewlog_data'] = 'gÃ¶gn';
@@ -291,6 +302,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'PÃ³sthÃ³lf notenda til aÃ° tengjast svo hÃ¦gt er aÃ° breyta lykilorÃ°i eÃ°a alias.';
 $PALANG['pUsersLogin_username_incorrect'] = 'InnskrÃ¡ning Ã¾Ã­n er rÃ¶ng, gaktu Ãºr skugga um aÃ° Ã¾Ãº tengist meÃ° rÃ©ttu pÃ³stfangi (email address)!';
 $PALANG['pUsersLogin_password_incorrect'] = 'LykilorÃ° Ã¾itt er rangt!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'SjÃ¡lfvirk svÃ¶run';
 $PALANG['pUsersMenu_edit_alias'] = 'Breyta Ã¡framsendingu';
@@ -322,6 +334,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.'; # XXX
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/it.lang 3.2-2/languages/it.lang
--- 3.0.2-2/languages/it.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/it.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: it.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Italian
 // by Massimiliano Stucchi <max at gufi dot org>
@@ -144,6 +144,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Hai raggiunto il limite per creare caselle di posta!';
 $PALANG['pCreate_mailbox_password_text'] = 'Password per POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Nome completo';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Crea casella di posta'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Impossibile aggiungere la casella di posta alla tabella delle caselle di posta! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'La casella di posta Ã¨ stata aggiunta alla tabella! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -171,6 +175,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Cambia Password'; # XXX check text - should be 'Change Password'
 $PALANG['pPassword_result_error'] = 'Impossibile cambiare password! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'La tua password Ã¨ stata modificata! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Cambia / inserisci messaggio';
 $PALANG['pEdit_vacation_remove'] = 'Rimuovi messaggio';
 $PALANG['pVacation_result_error'] = 'Impossibile registrare le modifiche! (%s)'; # XXX Text changed to: Updating the auto response settings for %s failed
@@ -186,7 +197,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Elenca gli ultimi dieci eventi per ';
+$PALANG['pViewlog_welcome'] = 'Elenca gli ultimi %s eventi per ';
 $PALANG['pViewlog_timestamp'] = 'Orario';
 $PALANG['pViewlog_action'] = 'Azione';
 $PALANG['pViewlog_data'] = 'Dati';
@@ -292,6 +303,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Gli utenti di caselle di posta devono entrare qui per modificare le proprie opzioni.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Il tuo nome utente non Ã¨ corretto. Assicurati di avere inserito il tuo indirizzo email!';
 $PALANG['pUsersLogin_password_incorrect'] = 'La tua password non Ã¨ corretta!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Risposta automatica';
 $PALANG['pUsersMenu_edit_alias'] = 'Cambia il tuo inoltro';
@@ -323,6 +335,8 @@ $PALANG['pBroadcast_name'] = 'Il tuo nom
 $PALANG['pBroadcast_success'] = 'Il tuo messaggio Ã¨ stato inoltrato a tutto il gruppo.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Invio di gruppo';
 $PALANG['pBroadcast_error_empty'] = 'Nome, oggetto e testo del messaggio non possono restare vuoti!';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'presumibilmente NON CONSEGNABILE ';
 $PALANG['pStatus_custom'] = 'In consegna a ';
 $PALANG['pStatus_popimap'] = 'POP/IMAP ';
diff -pruN 3.0.2-2/languages/ja.lang 3.2-2/languages/ja.lang
--- 3.0.2-2/languages/ja.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/ja.lang	2018-05-02 20:37:27.000000000 +0000
@@ -14,28 +14,28 @@ $PALANG['exit'] = 'çµ‚äº†';
 $PALANG['cancel'] = 'ã‚­ãƒ£ãƒ³ã‚»ãƒ«';
 $PALANG['save'] = 'å¤‰æ›´ã‚’ä¿å­˜';
 $PALANG['confirm'] = 'æœ¬å½“ã«å‰Šé™¤ã—ã¦ã‚‚ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ\n';
-$PALANG['confirm_delete_admin'] = 'Do you really want to delete the admin %s?'; # XXX
-$PALANG['confirm_delete_alias'] = 'Do you really want to delete the alias %s?'; # XXX
-$PALANG['confirm_delete_aliasdomain'] = 'Do you really want to delete the alias domain %s?'; # XXX
-$PALANG['confirm_delete_domain'] = 'æœ¬å½“ã«ã“ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã®ã™ã¹ã¦ã®æƒ…å ±ã‚’å‰Šé™¤ã—ã¦ã‚‚ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿã“ã‚Œã‚’å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“ã€‚\n (%s)'; # XXX text changed to: 'Do you really want to delete all records for the domain %s? This can not be undone'
-$PALANG['confirm_delete_fetchmail'] = 'Do you really want to delete the fetchmail job %s?'; # XXX
-$PALANG['confirm_delete_mailbox'] = 'Do you really want to delete the mailbox %s?'; # XXX
-$PALANG['confirm_delete_vacation'] = 'Do you really want to delete the vacation message for %s?'; # XXX
-$PALANG['no_delete_permissions'] = 'You are not allowed to delete %s!'; # XXX
+$PALANG['confirm_delete_admin'] = 'æœ¬å½“ã«ç®¡ç†è€… %s ã‚’å‰Šé™¤ã—ã¦ã‚‚ã‚ˆã‚ã—ã„ã§ã™ã‹?';
+$PALANG['confirm_delete_alias'] = 'æœ¬å½“ã«ã‚¨ã‚¤ãƒªã‚¢ã‚¹ %s ã‚’å‰Šé™¤ã—ã¦ã‚‚ã‚ˆã‚ã—ã„ã§ã™ã‹?';
+$PALANG['confirm_delete_aliasdomain'] = 'æœ¬å½“ã«ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãƒ‰ãƒ¡ã‚¤ãƒ³ %s ã‚’å‰Šé™¤ã—ã¦ã‚‚ã‚ˆã‚ã—ã„ã§ã™ã‹?';
+$PALANG['confirm_delete_domain'] = 'æœ¬å½“ã«ã“ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã®ã™ã¹ã¦ã®æƒ…å ±ã‚’å‰Šé™¤ã—ã¦ã‚‚ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿã“ã‚Œã‚’å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“ã€‚\n (%s)'; 
+$PALANG['confirm_delete_fetchmail'] = 'æœ¬å½“ã« fetchmail ã‚¸ãƒ§ãƒ– %s ã‚’å‰Šé™¤ã—ã¦ã‚‚ã‚ˆã‚ã—ã„ã§ã™ã‹?';
+$PALANG['confirm_delete_mailbox'] = 'æœ¬å½“ã«ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ %s ã‚’å‰Šé™¤ã—ã¦ã‚‚ã‚ˆã‚ã—ã„ã§ã™ã‹?';
+$PALANG['confirm_delete_vacation'] = 'æœ¬å½“ã«ã€%s ã®è‡ªå‹•å¿œç­”ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’å‰Šé™¤ã—ã¦ã‚‚ã‚ˆã‚ã—ã„ã§ã™ã‹?';
+$PALANG['no_delete_permissions'] = 'ã‚ãªãŸã«ã¯ã€%s ã‚’å‰Šé™¤ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“!';
 $PALANG['check_update'] = 'æ›´æ–°ã®ç¢ºèª';
 $PALANG['invalid_parameter'] = 'ç„¡åŠ¹ãªãƒ‘ãƒ©ãƒ¡ãƒ¼ã‚¿ã§ã™ã€‚';
 $PALANG['show'] = 'é–²è¦§:';
 $PALANG['all'] = 'å…¨ã¦';
-$PALANG['created'] = 'Created'; # XXX
-$PALANG['unknown'] = 'unknown'; # XXX
-$PALANG['download_csv'] = 'Download this list as CSV file'; # XXX
-$PALANG['missing_field'] = 'Field %s is missing'; # XXX
-$PALANG['must_be_numeric'] = '%s must be numeric'; # XXX
-$PALANG['must_be_numeric_bigger_than_null'] = '%s must be numeric and bigger than 0'; # XXX
-$PALANG['must_be_boolean'] = '%s must be boolean'; # XXX
-$PALANG['invalid_value_given'] = 'Invalid value given for %s'; # XXX
-$PALANG['edit_not_allowed'] = 'You are not allowed to edit %s'; # XXX
-$PALANG['searchparams'] = 'Search parameters:'; # XXX
+$PALANG['created'] = 'ä½œæˆæ—¥æ™‚';
+$PALANG['unknown'] = 'ä¸æ˜Ž';
+$PALANG['download_csv'] = 'ã“ã®ãƒªã‚¹ãƒˆã‚’ CSV ãƒ•ã‚¡ã‚¤ãƒ«ã¨ã—ã¦ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰';
+$PALANG['missing_field'] = 'ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ %s ãŒã‚ã‚Šã¾ã›ã‚“';
+$PALANG['must_be_numeric'] = '%s ã¯æ•°å­—ã§ãªãã¦ã¯ãªã‚Šã¾ã›ã‚“';
+$PALANG['must_be_numeric_bigger_than_null'] = '%s ã¯ã€æ•°å­—ã‹ã¤ 0 ã‚ˆã‚Šå¤§ãããªãã¦ã¯ãªã‚Šã¾ã›ã‚“';
+$PALANG['must_be_boolean'] = '%s ã¯çœŸå½å€¤ã§ãªãã¦ã¯ãªã‚Šã¾ã›ã‚“';
+$PALANG['invalid_value_given'] = '%s ã«ä¸Žãˆã‚‰ã‚ŒãŸå€¤ãŒä¸æ­£ã§ã™';
+$PALANG['edit_not_allowed'] = 'ã‚ãªãŸã«ã¯ã€%s ã‚’ç·¨é›†ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“';
+$PALANG['searchparams'] = 'æ¤œç´¢ãƒ‘ãƒ©ãƒ¡ãƒ¼ã‚¿:';
 
 $PALANG['pFooter_logged_as'] = 'ãƒ­ã‚°ã‚¤ãƒ³å %s';
 
@@ -49,9 +49,9 @@ $PALANG['pLogin_login_users'] = 'ä¸€èˆ¬ã
 
 $PALANG['pMenu_main'] = 'ãƒ¡ã‚¤ãƒ³';
 $PALANG['pMenu_overview'] = 'æ¦‚è¦';
-$PALANG['add_alias'] = 'è»¢é€å…ˆã®è¿½åŠ '; # XXX check text - should be 'Add Alias'
+$PALANG['add_alias'] = 'è»¢é€å…ˆã®è¿½åŠ ';
 $PALANG['add_alias_domain'] = 'ã‚¨ã‚¤ãƒªã‚¢ã‚¹ãƒ‰ãƒ¡ã‚¤ãƒ³ã®è¿½åŠ ';
-$PALANG['add_mailbox'] = 'ã‚¢ãƒ‰ãƒ¬ã‚¹ã®è¿½åŠ '; # XXX check text - should be 'Add Mailbox'
+$PALANG['add_mailbox'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã®è¿½åŠ ';
 $PALANG['pMenu_fetchmail'] = 'ãƒ¡ãƒ¼ãƒ«å–å¾—';
 $PALANG['pMenu_sendmail'] = 'ãƒ¡ãƒ¼ãƒ«é€ä¿¡';
 $PALANG['pMenu_password'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰';
@@ -60,7 +60,7 @@ $PALANG['pMenu_logout'] = 'ãƒ­ã‚°ã‚¢ã‚¦ã
 
 $PALANG['pMain_welcome'] = 'Postfix Admin ã¸ã‚ˆã†ã“ãï¼';
 $PALANG['pMain_overview'] = 'è»¢é€ã‚¢ãƒ‰ãƒ¬ã‚¹ã¨ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã®ä¸€è¦§ã‚’è¡¨ç¤ºã—ã¾ã™ã€‚ã“ã“ã‹ã‚‰ç·¨é›†ã¨å‰Šé™¤ãŒã§ãã¾ã™ã€‚';
-$PALANG['pMain_create_alias'] = 'æ–°ã—ã„è»¢é€ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’ä½œæˆã—ã¾ã™ã€‚'; # XXX check text - should be 'Create a new alias for your domain.'
+$PALANG['pMain_create_alias'] = 'æ–°ã—ã„è»¢é€ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’ä½œæˆã—ã¾ã™ã€‚';
 $PALANG['pMain_create_mailbox'] = 'æ–°ã—ã„ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’ä½œæˆã—ã¾ã™ã€‚';
 $PALANG['pMain_sendmail'] = 'æ–°ã—ã„ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã—ã¾ã™ã€‚';
 $PALANG['pMain_password'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¤‰æ›´ã—ã¾ã™ã€‚';
@@ -87,12 +87,12 @@ $PALANG['name'] = 'åå‰';
 $PALANG['pOverview_mailbox_quota'] = 'å®¹é‡åˆ¶é™ (MB)';
 $PALANG['pOverview_vacation_edit'] = 'è‡ªå‹•å¿œç­” åˆ©ç”¨ä¸­';
 $PALANG['pOverview_vacation_option'] = 'è‡ªå‹•å¿œç­”';
-$PALANG['no_domains_for_this_admin'] = 'You don\'t have permissions for any domains.'; # XXX
-$PALANG['no_domains_exist'] = 'You have to create at least one domain before you can use virtual list.'; # "virtual list" should match $PALANG['pAdminMenu_list_virtual'] # XXX
+$PALANG['no_domains_for_this_admin'] = 'ã‚ãªãŸã«ã¯ãƒ‰ãƒ¡ã‚¤ãƒ³ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“ã€‚';
+$PALANG['no_domains_exist'] = 'ã‚¢ãƒ‰ãƒ¬ã‚¹ä¸€è¦§ã‚’ä½¿ãˆã‚‹ã‚ˆã†ã«ã™ã‚‹å‰ã«ã€å°‘ãªãã¨ã‚‚ã²ã¨ã¤ã¯ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’ä½œæˆã—ãªãã¦ã¯ãªã‚Šã¾ã›ã‚“ã€‚'; # "virtual list" should match $PALANG['pAdminMenu_list_virtual']
 
 
 $PALANG['domain'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³';
-$PALANG['pOverview_get_alias_domains'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚¨ã‚¤ãƒªã‚¢ã‚¹';
+$PALANG['pOverview_get_alias_domains'] = 'åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³';
 $PALANG['mailboxes'] = 'ã‚¢ãƒ‰ãƒ¬ã‚¹æ•°';
 $PALANG['pOverview_get_quota'] = 'å®¹é‡åˆ¶é™ (MB)';
 $PALANG['pDelete_delete_error'] = 'ã‚¨ãƒ³ãƒˆãƒªã‚’å‰Šé™¤ã§ãã¾ã›ã‚“ã€‚ ';
@@ -104,63 +104,67 @@ $PALANG['pCreate_alias_domain_alias'] =
 $PALANG['pCreate_alias_domain_alias_text'] = 'ãƒ¡ãƒ¼ãƒ«ãŒã“ã®ãƒ‰ãƒ¡ã‚¤ãƒ³å®›ã«æ¥ã¾ã™ã€‚';
 $PALANG['pCreate_alias_domain_target'] = 'å®›å…ˆãƒ‰ãƒ¡ã‚¤ãƒ³';
 $PALANG['pCreate_alias_domain_target_text'] = 'ãƒ¡ãƒ¼ãƒ«ã‚’ã“ã®ãƒ‰ãƒ¡ã‚¤ãƒ³å®›ã«å±Šã‘ã¾ã™ã€‚';
-$PALANG['pCreate_alias_domain_error1'] = 'You are not allowed to create the chosen configuration.'; # XXX
-$PALANG['pCreate_alias_domain_error2'] = 'The chosen configuration is invalid, please choose a different one!'; # XXX
-$PALANG['alias_domain_already_exists'] = 'This domain is already an alias domain!'; # XXX
-$PALANG['alias_domain_does_not_exist'] = 'This domain isn\'t an alias domain!'; # XXX
-$PALANG['alias_domain_create_failed'] = 'Creating the alias domain %s failed!'; # XXX
-$PALANG['alias_domain_change_failed'] = 'Changing the alias domain %s failed!'; # XXX
+$PALANG['pCreate_alias_domain_error1'] = 'ã‚ãªãŸã«ã¯ã€é¸æŠžã—ãŸæ§‹æˆã‚’ä½œæˆã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“';
+$PALANG['pCreate_alias_domain_error2'] = 'é¸æŠžã—ãŸæ§‹æˆã¯ä¸æ­£ã§ã™ã€‚åˆ¥ã®æ§‹æˆã‚’é¸æŠžã—ã¦ä¸‹ã•ã„!';
+$PALANG['alias_domain_already_exists'] = 'ã“ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã¯æ—¢ã«åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ã§ã™!';
+$PALANG['alias_domain_does_not_exist'] = 'ã“ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã¯ã€åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ã§ã¯ã‚ã‚Šã¾ã›ã‚“!';
+$PALANG['alias_domain_create_failed'] = 'åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ %s ã‚’ä½œæˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚!';
+$PALANG['alias_domain_change_failed'] = 'åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ %s ã‚’å¤‰æ›´ã§ãã¾ã›ã‚“ã§ã—ãŸ!';
 $PALANG['pCreate_alias_domain_error4'] = 'å…¨ã¦ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ãŒã‚¨ã‚¤ãƒªã‚¢ã‚¹ã•ã‚Œã¦ã„ã¾ã™ã€‚';
-$PALANG['pCreate_alias_domain_success'] = 'The alias domain %s has been created.'; # XXX
-$PALANG['alias_domain_changed'] = 'The alias domain %s has been changed.'; # XXX
-$PALANG['alias_domain_to_itsself'] = 'A domain can\'t be an alias domain to itsself!'; # XXX
-$PALANG['delete_domain_aliasdomain_target'] = 'The domain %s is the target for one or more alias domains and can\'t be deleted! (Delete the alias domains first.)'; # XXX
+$PALANG['pCreate_alias_domain_success'] = 'åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ %s ã‚’ä½œæˆã—ã¾ã—ãŸã€‚';
+$PALANG['alias_domain_changed'] = 'åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ %s ã‚’å¤‰æ›´ã—ã¾ã—ãŸã€‚';
+$PALANG['alias_domain_to_itsself'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã¯ãã‚Œè‡ªèº«ãŒåˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ã§ã‚ã£ã¦ã¯ãªã‚Šã¾ã›ã‚“!';
+$PALANG['delete_domain_aliasdomain_target'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ %s ã¯ã²ã¨ã¤ã‚‚ã—ãã¯è¤‡æ•°ã®åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ã«ç´ä»˜ã„ã¦ã„ã¾ã™ã®ã§ã€å‰Šé™¤ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“! (ã¾ãšã€åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’å‰Šé™¤ã—ã¦ä¸‹ã•ã„ã€‚)';
 
 $PALANG['pCreate_alias_address_text_error1'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒç„¡åŠ¹ã§ã™ã€‚';
-$PALANG['alias_does_not_exist'] = 'This alias does not exist!'; # XXX
-$PALANG['email_address_already_exists'] = 'ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯æ—¢ã«å­˜åœ¨ã™ã‚‹ã®ã§ã€ åˆ¥ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’é¸æŠžã—ã¦ãã ã•ã„ã€‚'; # XXX check/beautify - was split in two lines before
+$PALANG['alias_does_not_exist'] = 'ã“ã®è»¢é€å…ˆã¯ã€å­˜åœ¨ã—ã¾ã›ã‚“!';
+$PALANG['email_address_already_exists'] = 'ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯æ—¢ã«å­˜åœ¨ã™ã‚‹ã®ã§ã€ åˆ¥ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’é¸æŠžã—ã¦ãã ã•ã„ã€‚';
 $PALANG['pCreate_alias_address_text_error3'] = 'è»¢é€ã‚¢ãƒ‰ãƒ¬ã‚¹ã®åˆ¶é™æ•°ã«é”ã—ã¾ã—ãŸã€‚';
 $PALANG['pCreate_alias_goto_text'] = 'ãƒ¡ãƒ¼ãƒ«ã‚’è»¢é€ã™ã‚‹ã‚¢ãƒ‰ãƒ¬ã‚¹';
 $PALANG['pCreate_alias_goto_text_error'] = 'è»¢é€å…ˆãŒç„¡åŠ¹ã§ã™ã€‚';
-$PALANG['pCreate_alias_result_error'] = 'è»¢é€å…ˆã‚’è¿½åŠ ã§ãã¾ã›ã‚“ï¼ (%s)'; # XXX Text changed to: Creating the alias %s failed!
-$PALANG['pCreate_alias_result_success'] = 'è»¢é€å…ˆã‚’è¿½åŠ ã—ã¾ã—ãŸã€‚'; # XXX text change: 'The alias %s has been created!'
-$PALANG['alias_updated'] = 'The alias %s has been updated!'; # XXX
-$PALANG['pCreate_alias_catchall_text'] = 'ã™ã¹ã¦ã®ãƒ¡ãƒ¼ãƒ«ã‚’å—ã‘å–ã‚‹ã«ã¯ã€è»¢é€å…ƒã« "*" ã‚’ä½¿ã„ã¾ã™ã€‚ åˆ¥ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã«ã™ã¹ã¦è»¢é€ã™ã‚‹ã«ã¯ã€è»¢é€å…ˆã« "*.domain.tld" ã‚’ä½¿ã„ã¾ã™ã€‚'; # XXX check/beautify - was split in two lines before
-$PALANG['mailbox_alias_cant_be_deleted'] = 'This alias belongs to a mailbox and can\'t be deleted!'; # XXX
-$PALANG['protected_alias_cant_be_deleted'] = 'The alias %s is protected and can only be deleted by a superadmin'; # XXX
-
-$PALANG['pEdit_alias_welcome'] = 'è»¢é€å…ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã®ç·¨é›†'; # XXX Text change to: 'Edit forwarding settings'
-$PALANG['pEdit_alias_help'] = '1è¡Œã«1ã‚¨ãƒ³ãƒˆãƒªã§ã™ã€‚'; # XXX # XXX Text change to: 'Accepts multiple targets, one entry per line.'
-$PALANG['alias'] = 'è»¢é€å…ƒ'; # XXX check text - should be 'Alias'
-$PALANG['to'] = 'è»¢é€å…ˆ'; # XXX check text - should be 'To'
+$PALANG['pCreate_alias_result_error'] = 'è»¢é€å…ˆ %s ã‚’è¿½åŠ ã§ãã¾ã›ã‚“ã§ã—ãŸ!';
+$PALANG['pCreate_alias_result_success'] = 'è»¢é€å…ˆ %s ã‚’è¿½åŠ ã—ã¾ã—ãŸã€‚';
+$PALANG['alias_updated'] = 'è»¢é€å…ˆ %s ã‚’æ›´æ–°ã—ã¾ã—ãŸ!';
+$PALANG['pCreate_alias_catchall_text'] = 'ã™ã¹ã¦ã®ãƒ¡ãƒ¼ãƒ«ã‚’å—ã‘å–ã‚‹ã«ã¯ã€è»¢é€å…ƒã« "*" ã‚’ä½¿ã„ã¾ã™ã€‚ åˆ¥ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã«ã™ã¹ã¦è»¢é€ã™ã‚‹ã«ã¯ã€è»¢é€å…ˆã« "*.domain.tld" ã‚’ä½¿ã„ã¾ã™ã€‚';
+$PALANG['mailbox_alias_cant_be_deleted'] = 'ã“ã®è»¢é€å…ˆã¯ã€ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«ç´ä»˜ã„ã¦ã„ã‚‹ã®ã§ã€å‰Šé™¤ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“!';
+$PALANG['protected_alias_cant_be_deleted'] = 'è»¢é€å…ˆ %s ã¯ä¿è­·ã•ã‚Œã¦ãŠã‚Šã€ç‰¹æ¨©ç®¡ç†è€…ã ã‘ãŒå‰Šé™¤ã§ãã¾ã™';
+
+$PALANG['pEdit_alias_welcome'] = 'è»¢é€å…ˆè¨­å®šã®ç·¨é›†';
+$PALANG['pEdit_alias_help'] = 'è¤‡æ•°ã®è»¢é€å…ˆã‚’è¨­å®šã§ãã¾ã™ã€‚1è¡Œã«1ã‚¨ãƒ³ãƒˆãƒªã§ã™ã€‚';
+$PALANG['alias'] = 'è»¢é€å…ƒ';
+$PALANG['to'] = 'è»¢é€å…ˆ';
 $PALANG['pEdit_alias_goto_text_error1'] = 'è»¢é€å…ˆãŒå…¥åŠ›ã•ã‚Œã¦ã„ã¾ã›ã‚“ã€‚';
 $PALANG['pEdit_alias_goto_text_error2'] = 'ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ç„¡åŠ¹ã§ã™: ';
-$PALANG['pEdit_alias_domain_result_error'] = 'Unable to modify the alias domain!'; # XXX
+$PALANG['pEdit_alias_domain_result_error'] = 'åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’ä¿®æ­£ã§ãã¾ã›ã‚“!';
 $PALANG['pEdit_alias_forward_and_store'] = 'ãƒ­ãƒ¼ã‚«ãƒ«ã®ãƒ¡ãƒ¼ãƒ«ãƒœãƒƒã‚¯ã‚¹ã«æ®‹ã™';
 $PALANG['pEdit_alias_forward_only'] = 'æŒ‡å®šã•ã‚ŒãŸè»¢é€ã‚¢ãƒ‰ãƒ¬ã‚¹ã®ã¿';
-$PALANG['pEdit_alias_result_error'] = 'ä¿®æ­£ã§ãã¾ã›ã‚“ï¼ (%s)'; # XXX Text changed to: Modifying the alias %s failed!
+$PALANG['pEdit_alias_result_error'] = 'åˆ¥å %s ã‚’æ›´æ–°ã§ãã¾ã›ã‚“ã§ã—ãŸ!';
 
 $PALANG['pCreate_mailbox_welcome'] = 'æ–°ã—ã„ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã®ä½œæˆ';
 $PALANG['pCreate_mailbox_username_text_error1'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒç„¡åŠ¹ã§ã™ã€‚';
 $PALANG['pCreate_mailbox_username_text_error3'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã®åˆ¶é™æ•°ã«é”ã—ã¾ã—ãŸã€‚';
 $PALANG['pCreate_mailbox_password_text'] = 'POP3/IMAPã®ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰';
 $PALANG['pCreate_mailbox_name_text'] = 'ãƒ•ãƒ«ãƒãƒ¼ãƒ ';
-$PALANG['pCreate_mailbox_mail'] = 'ã‚ˆã†ã“ããƒ¡ãƒ¼ãƒ«ã®é€ä¿¡'; # XXX Text change to 'Send Welcome mail'
-$PALANG['pCreate_mailbox_result_error'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’è¿½åŠ ã§ãã¾ã›ã‚“ï¼ (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
-$PALANG['pCreate_mailbox_result_success'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’è¿½åŠ ã—ã¾ã—ãŸã€‚ (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
-$PALANG['pCreate_mailbox_result_succes_nosubfolders'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’è¿½åŠ ã—ã¾ã—ãŸã€‚ã—ã‹ã—ã€ã„ãã¤ã‹ã®ã‚µãƒ–ãƒ•ã‚©ãƒ«ãƒ€ã®ä½œæˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚ (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table, but none (or only some) of the predefined sub-folders could be created.
-$PALANG['mailbox_updated'] = "The mailbox %s has been updated.";  # XXX
-$PALANG['mailbox_update_failed'] = "Updating the mailbox %s failed!"; # XXX
+$PALANG['pCreate_mailbox_phone'] = 'æºå¸¯é›»è©±';
+$PALANG['pCreate_mailbox_phone_desc'] = "ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¿˜ã‚ŒãŸæ™‚ã« SMS ã‚’é€ä¿¡ã™ã‚‹ã®ã«ä½¿ç”¨ã•ã‚Œã¾ã™";
+$PALANG['pCreate_mailbox_email'] = 'ãã®ä»–ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹';
+$PALANG['pCreate_mailbox_email_desc'] = "ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¿˜ã‚ŒãŸæ™‚ã®ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™";
+$PALANG['pCreate_mailbox_mail'] = 'ã‚ˆã†ã“ããƒ¡ãƒ¼ãƒ«ã®é€ä¿¡';
+$PALANG['pCreate_mailbox_result_error'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ %s ã‚’è¿½åŠ ã§ãã¾ã›ã‚“ã§ã—ãŸ!';
+$PALANG['pCreate_mailbox_result_success'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ %s ã‚’ãƒ†ãƒ¼ãƒ–ãƒ«ã«è¿½åŠ ã—ã¾ã—ãŸã€‚';
+$PALANG['pCreate_mailbox_result_succes_nosubfolders'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ %s ã‚’ãƒ†ãƒ¼ãƒ–ãƒ«ã«è¿½åŠ ã—ã¾ã—ãŸãŒã€è¦å®šã®ã‚µãƒ–ãƒ•ã‚©ãƒ«ãƒ€ã‚’ã„ãã¤ã‹ã€ã‚‚ã—ãã¯å…¨éƒ¨ã‚’ä½œæˆã§ãã¾ã›ã‚“ã§ã—ãŸ';
+$PALANG['mailbox_updated'] = "ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ %s ã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚";
+$PALANG['mailbox_update_failed'] = "ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ %s ã‚’æ›´æ–°ã§ãã¾ã›ã‚“ã§ã—ãŸ!";
 
 $PALANG['pEdit_mailbox_welcome'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã®ç·¨é›†';
-$PALANG['pEdit_mailbox_username'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹'; # XXX check / compare with pCreate_mailbox_username - should be "Username"
+$PALANG['pEdit_mailbox_username'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹';
 $PALANG['pEdit_mailbox_password_text_error'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ãŒä¸€è‡´ã—ã¾ã›ã‚“ã€‚';
 $PALANG['pEdit_mailbox_quota'] = 'å®¹é‡åˆ¶é™';
 $PALANG['pEdit_mailbox_quota_text'] = 'MB';
-$PALANG['mb_max'] = 'MB (max: %s)'; # XXX
+$PALANG['mb_max'] = 'MB (æœ€å¤§: %s)';
 $PALANG['pEdit_mailbox_quota_text_error'] = 'æŒ‡å®šã•ã‚ŒãŸå®¹é‡åˆ¶é™ãŒå¤§ãã™ãŽã¾ã™ã€‚';
 $PALANG['pEdit_mailbox_domain_error'] = 'ã“ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã¯ç®¡ç†å¤–ã§ã™: ';
-$PALANG['pEdit_mailbox_result_error'] = 'ä¿®æ­£ã§ãã¾ã›ã‚“ï¼';
+$PALANG['pEdit_mailbox_result_error'] = 'æ›´æ–°ã§ãã¾ã›ã‚“ã§ã—ãŸï¼';
 
 $PALANG['pPassword_welcome'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã®å¤‰æ›´';
 $PALANG['pPassword_admin'] = 'ãƒ­ã‚°ã‚¤ãƒ³';
@@ -168,55 +172,62 @@ $PALANG['pPassword_password_current'] =
 $PALANG['pPassword_password_current_text_error'] = 'ç¾åœ¨ã®ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ãŒå…¥åŠ›ã•ã‚Œã¦ã„ã¾ã›ã‚“ã€‚';
 $PALANG['pPassword_password'] = 'æ–°è¦ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰';
 $PALANG['pPassword_password2'] = 'æ–°è¦ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ (ç¢ºèª)';
-$PALANG['pPassword_password_text_error'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ãŒä¸€è‡´ã—ã¾ã›ã‚“ã€‚ ã¾ãŸã¯ç©ºã§ã™ã€‚'; # XXX check/beautify - was split in two lines before
-$PALANG['change_password'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰å¤‰æ›´';
-$PALANG['pPassword_result_error'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¤‰æ›´ã§ãã¾ã›ã‚“ï¼ (%s)'; # XXX Text changed to: Changing the password for %s failed!
-$PALANG['pPassword_result_success'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¤‰æ›´ã—ã¾ã—ãŸã€‚ (%s)'; # XXX Text changed to: The password for %s has been changed.
-
-$PALANG['pEdit_vacation_set'] = 'ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸å¤‰æ›´ï¼è¨­å®š';
-$PALANG['pEdit_vacation_remove'] = 'ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸è§£é™¤';
-
-$PALANG['pVacation_result_error'] = 'è‡ªå‹•å¿œç­”ã®è¨­å®šã‚’æ›´æ–°ã§ãã¾ã›ã‚“ã§ã—ãŸï¼ (%s)'; # XXX Text changed to: Updating the auto response settings for %s failed
-$PALANG['pVacation_result_removed'] = 'è‡ªå‹•å¿œç­”ã‚’è§£é™¤ã—ã¾ã—ãŸã€‚ (%s)'; # XXX Text changed to "Auto response for %s has been disabled!"
-$PALANG['pVacation_result_added'] = 'è‡ªå‹•å¿œç­”ã‚’è¨­å®šã—ã¾ã—ãŸã€‚ (%s)'; # XXX Text changed to "Auto response for %s has been enabled!"
-$PALANG['pVacation_reply_type'] = 'Choice of reply'; # XXX
-$PALANG['pVacation_reply_delay_time'] = 'Interval time'; # XXX
-$PALANG['pVacation_reply_delay_time_text'] = 'Time in seconds'; # XXX
-$PALANG['pVacation_until_before_today'] = 'The Date of [Active until] is set  before Today'; # XXX
-$PALANG['pVacation_until_before_from'] = 'The Date of [Active until] is set before [Active from]'; # XXX
-$PALANG['reply_once'] = 'Reply once'; # XXX
-$PALANG['reply_every_mail'] = 'Reply on every mail'; # XXX
-$PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
-$PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
+$PALANG['pPassword_password_text_error'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ãŒä¸€è‡´ã—ãªã„ã‹ã€ç©ºã§ã™ã€‚';
+$PALANG['change_password'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¤‰æ›´';
+$PALANG['pPassword_result_error'] = '%s ã®ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¤‰æ›´ã§ãã¾ã›ã‚“ã§ã—ãŸ!';
+$PALANG['pPassword_result_success'] = '%s ã®ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¤‰æ›´ã—ã¾ã—ãŸã€‚';
+$PALANG['pPassword_recovery_title'] = 'æ¬¡ã®æ‰‹é †ã«å¾“ã£ã¦ã€ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’ãƒªã‚»ãƒƒãƒˆã—ã¦ä¸‹ã•ã„ã€‚';
+$PALANG['pPassword_recovery_button'] = 'ã‚³ãƒ¼ãƒ‰ã‚’é€ä¿¡';
+$PALANG['pPassword_recovery_email_body'] = "å‰ç•¥\n\nãƒ¡ãƒ¼ãƒ«ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¤‰æ›´ã™ã‚‹ã«ã¯ã€æ¬¡ã®ãƒªãƒ³ã‚¯ã‚’ã‚¯ãƒªãƒƒã‚¯ã—ã¦ä¸‹ã•ã„ :\n%s\n\næ•¬å…·\n\n" . $CONF['admin_name'];
+$PALANG['pPassword_recovery_sms_body'] = "å‰ç•¥\nãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¤‰æ›´ã™ã‚‹ãŸã‚ã®ã‚³ãƒ¼ãƒ‰: %s\n" . $CONF['admin_name'];
+$PALANG['pPassword_recovery_processed'] = "ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’å—ã‘ä»˜ã‘ã¾ã—ãŸã€‚æ­£ã—ã„ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒå…¥åŠ›ã•ã‚Œã¦ã„ã‚Œã°ã€ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚³ãƒ¼ãƒ‰ã‚’ãƒ¡ãƒ¼ãƒ«/SMS ã§å—ä¿¡ã§ãã¾ã™ã€‚";
+$PALANG['pPassword_password_code'] = 'ãƒ¡ãƒ¼ãƒ«/SMS ã§é€ä¿¡ã•ã‚ŒãŸã‚³ãƒ¼ãƒ‰';
+$PALANG['pPassword_code_text_error'] = 'ä¸æ­£ãªã‚³ãƒ¼ãƒ‰';
+
+$PALANG['pEdit_vacation_set'] = 'ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’å¤‰æ›´ï¼è¨­å®š';
+$PALANG['pEdit_vacation_remove'] = 'ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’è§£é™¤';
+
+$PALANG['pVacation_result_error'] = '%s ã®è‡ªå‹•å¿œç­”ã®è¨­å®šã‚’æ›´æ–°ã§ãã¾ã›ã‚“ã§ã—ãŸ!';
+$PALANG['pVacation_result_removed'] = '%s ã®è‡ªå‹•å¿œç­”ã‚’è§£é™¤ã—ã¾ã—ãŸã€‚';
+$PALANG['pVacation_result_added'] = '%s ã®è‡ªå‹•å¿œç­”ã‚’è¨­å®šã—ã¾ã—ãŸã€‚';
+$PALANG['pVacation_reply_type'] = 'è¿”ä¿¡ã‚’é¸æŠž';
+$PALANG['pVacation_reply_delay_time'] = 'è¿”ä¿¡ã™ã‚‹ã¾ã§ã®é–“éš”';
+$PALANG['pVacation_reply_delay_time_text'] = 'æ™‚é–“ã¯ç§’ã§æŒ‡å®š';
+$PALANG['pVacation_until_before_today'] = '[å³ã®æ—¥æ™‚ã‹ã‚‰æœ‰åŠ¹] ã®æ—¥ä»˜ãŒã€æœ¬æ—¥ã‚ˆã‚Šå‰ã«æŒ‡å®šã•ã‚Œã¦ã„ã¾ã™';
+$PALANG['pVacation_until_before_from'] = '[å³ã®æ—¥æ™‚ã¾ã§æœ‰åŠ¹] ã®æ—¥ä»˜ãŒã€[å³ã®æ—¥æ™‚ã‹ã‚‰æœ‰åŠ¹] ã‚ˆã‚Šå‰ã«æŒ‡å®šã•ã‚Œã¦ã„ã¾ã™';
+$PALANG['reply_once'] = 'ä¸€åº¦ã ã‘è¿”ä¿¡';
+$PALANG['reply_every_mail'] = 'ãƒ¡ãƒ¼ãƒ«ã”ã¨ã«è¿”ä¿¡';
+$PALANG['reply_once_per_day'] = 'æ¯Žæ—¥è¿”ä¿¡';
+$PALANG['reply_once_per_week'] = 'é€±ã«ä¸€åº¦è¿”ä¿¡';
 
-$PALANG['pViewlog_welcome'] = 'éŽåŽ»10å€‹ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ ';
+$PALANG['pViewlog_welcome'] = 'éŽåŽ» %s å€‹ã®ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ ';
 $PALANG['pViewlog_timestamp'] = 'ã‚¿ã‚¤ãƒ ã‚¹ã‚¿ãƒ³ãƒ—';
 $PALANG['pViewlog_action'] = 'ã‚¢ã‚¯ã‚·ãƒ§ãƒ³';
 $PALANG['pViewlog_data'] = 'ãƒ‡ãƒ¼ã‚¿';
-$PALANG['pViewlog_action_create_domain'] = 'create domain'; # XXX
-$PALANG['pViewlog_action_delete_domain'] = 'delete domain'; # XXX
-$PALANG['pViewlog_action_edit_domain'] = 'edit domain'; # XXX
-
-$PALANG['pViewlog_action_create_mailbox'] = 'ã‚¢ãƒ‰ãƒ¬ã‚¹ä½œæˆ';
-$PALANG['pViewlog_action_delete_mailbox'] = 'ã‚¢ãƒ‰ãƒ¬ã‚¹å‰Šé™¤';
-$PALANG['pViewlog_action_edit_mailbox'] = 'ã‚¢ãƒ‰ãƒ¬ã‚¹ç·¨é›†';
-$PALANG['pViewlog_action_edit_mailbox_state'] = 'ã‚¢ãƒ‰ãƒ¬ã‚¹çŠ¶æ…‹ç·¨é›†';
-$PALANG['pViewlog_action_create_alias'] = 'è»¢é€å…ˆä½œæˆ';
-$PALANG['pViewlog_action_create_alias_domain'] = 'create alias domain'; # XXX
-$PALANG['pViewlog_action_edit_alias_domain'] = 'edit alias domain'; # XXX
-$PALANG['pViewlog_action_delete_alias'] = 'è»¢é€å…ˆå‰Šé™¤';
-$PALANG['pViewlog_action_delete_alias_domain'] = 'delete alias domain'; # XXX
-$PALANG['pViewlog_action_edit_alias'] = 'è»¢é€å…ˆç·¨é›†';
-$PALANG['pViewlog_action_edit_alias_state'] = 'è»¢é€å…ˆçŠ¶æ…‹ç·¨é›†';
-$PALANG['pViewlog_action_edit_alias_domain_state'] = 'edit alias domain active'; # XXX
-$PALANG['pViewlog_action_edit_password'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰å¤‰æ›´';
-$PALANG['pViewlog_action_create_admin'] = 'create admin'; # XXX
-$PALANG['pViewlog_action_edit_admin'] = 'edit admin'; # XXX
-$PALANG['pViewlog_action_delete_admin'] = 'delete admin'; # XXX
-$PALANG['pViewlog_action_edit_vacation'] = 'edit vacation'; # XXX
-$PALANG['pViewlog_action_create_fetchmail'] = 'create fetchmail job'; # XXX
-$PALANG['pViewlog_action_edit_fetchmail'] = 'edit fetchmail job'; # XXX
-$PALANG['pViewlog_action_delete_fetchmail'] = 'delete fetchmail job'; # XXX
+$PALANG['pViewlog_action_create_domain'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’ä½œæˆ';
+$PALANG['pViewlog_action_delete_domain'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’å‰Šé™¤';
+$PALANG['pViewlog_action_edit_domain'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’ç·¨é›†';
+
+$PALANG['pViewlog_action_create_mailbox'] = 'ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’ä½œæˆ';
+$PALANG['pViewlog_action_delete_mailbox'] = 'ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’å‰Šé™¤';
+$PALANG['pViewlog_action_edit_mailbox'] = 'ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’ç·¨é›†';
+$PALANG['pViewlog_action_edit_mailbox_state'] = 'ã‚¢ãƒ‰ãƒ¬ã‚¹ã®æœ‰åŠ¹ï¼ç„¡åŠ¹ã‚’ç·¨é›†';
+$PALANG['pViewlog_action_create_alias'] = 'è»¢é€å…ˆã‚’ä½œæˆ';
+$PALANG['pViewlog_action_create_alias_domain'] = 'åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’ä½œæˆ';
+$PALANG['pViewlog_action_edit_alias_domain'] = 'åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’ç·¨é›†';
+$PALANG['pViewlog_action_delete_alias'] = 'è»¢é€å…ˆã‚’å‰Šé™¤';
+$PALANG['pViewlog_action_delete_alias_domain'] = 'åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’å‰Šé™¤';
+$PALANG['pViewlog_action_edit_alias'] = 'è»¢é€å…ˆã‚’ç·¨é›†';
+$PALANG['pViewlog_action_edit_alias_state'] = 'è»¢é€å…ˆã®æœ‰åŠ¹ï¼ç„¡åŠ¹ã‚’ç·¨é›†';
+$PALANG['pViewlog_action_edit_alias_domain_state'] = 'åˆ¥åãƒ‰ãƒ¡ã‚¤ãƒ³ã®æœ‰åŠ¹ï¼ç„¡åŠ¹ã‚’å¤‰æ›´';
+$PALANG['pViewlog_action_edit_password'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¤‰æ›´';
+$PALANG['pViewlog_action_create_admin'] = 'ç®¡ç†è€…ã‚’ä½œæˆ';
+$PALANG['pViewlog_action_edit_admin'] = 'ç®¡ç†è€…ã‚’ç·¨é›†';
+$PALANG['pViewlog_action_delete_admin'] = 'ç®¡ç†è€…ã‚’å‰Šé™¤';
+$PALANG['pViewlog_action_edit_vacation'] = 'è‡ªå‹•å¿œç­”ã‚’ç·¨é›†';
+$PALANG['pViewlog_action_create_fetchmail'] = 'fetchmail ã‚¸ãƒ§ãƒ–ã‚’è¿½åŠ ';
+$PALANG['pViewlog_action_edit_fetchmail'] = 'fetchmail ã‚¸ãƒ§ãƒ–ã‚’ç·¨é›†';
+$PALANG['pViewlog_action_delete_fetchmail'] = 'fetchmail ã‚¸ãƒ§ãƒ–ã‚’å‰Šé™¤';
  
 $PALANG['pViewlog_result_error'] = 'ãƒ­ã‚°ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ï¼';
 
@@ -228,8 +239,8 @@ $PALANG['subject'] = 'ä»¶å';
 $PALANG['pSendmail_subject_text'] = 'ã‚ˆã†ã“ã';
 $PALANG['pSendmail_body'] = 'æœ¬æ–‡';
 $PALANG['pSendmail_button'] = 'ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸é€ä¿¡';
-$PALANG['pSendmail_result_error'] = 'ãƒ¡ãƒ¼ãƒ«ãŒé€ä¿¡ã§ãã¾ã›ã‚“ï¼ (%s)'; # XXX text change - new: Unable to send email to %s!
-$PALANG['pSendmail_result_success'] = 'ãƒ¡ãƒ¼ãƒ«ãŒé€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚ (%s)'; # XXX text change - new: Email sent to %s.
+$PALANG['pSendmail_result_error'] = '%s ã¸ãƒ¡ãƒ¼ãƒ«ãŒé€ä¿¡ã§ãã¾ã›ã‚“ï¼';
+$PALANG['pSendmail_result_success'] = '%s ã¸ãƒ¡ãƒ¼ãƒ«ãŒé€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚';
 
 $PALANG['pAdminMenu_list_admin'] = 'ç®¡ç†è€…ä¸€è¦§';
 $PALANG['pAdminMenu_list_domain'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ä¸€è¦§';
@@ -242,64 +253,65 @@ $PALANG['pAdminMenu_create_domain'] = 'æ
 $PALANG['pAdminList_admin_count'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³æ•°';
 
 $PALANG['description'] = 'èª¬æ˜Ž';
-$PALANG['aliases'] = 'è»¢é€æ•°'; # XXX check text - should be 'Aliases'
-$PALANG['pAdminList_domain_quota'] = 'Domain quota (MB)'; # XXX
+$PALANG['aliases'] = 'è»¢é€æ•°';
+$PALANG['pAdminList_domain_quota'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚¯ã‚ªãƒ¼ã‚¿ (MB)';
 $PALANG['pAdminList_domain_backupmx'] = 'ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ— MX';
 $PALANG['last_modified'] = 'æœ€çµ‚æ›´æ–°æ—¥';
 
 
 $PALANG['pAdminCreate_domain_welcome'] = 'æ–°ã—ã„ãƒ‰ãƒ¡ã‚¤ãƒ³ã®è¿½åŠ ';
 $PALANG['pAdminCreate_domain_domain_text_error'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ãŒæ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚';
-$PALANG['domain_does_not_exist'] = 'This domain does not exist!'; # XXX
+$PALANG['domain_does_not_exist'] = 'ã“ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã¯å­˜åœ¨ã—ã¾ã›ã‚“!';
 $PALANG['pAdminCreate_domain_domain_text_error2'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ãŒç„¡åŠ¹ã§ã™ã€‚';
 $PALANG['pAdminCreate_domain_defaultaliases'] = 'ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆè»¢é€å…ˆã®è¿½åŠ ';
-$PALANG['pAdminCreate_domain_button'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³è¿½åŠ ';
-$PALANG['pAdminCreate_domain_result_error'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’è¿½åŠ ã§ãã¾ã›ã‚“ï¼ (%s)'; # XXX Text changed to: Adding the domain %s failed!
-$PALANG['pAdminCreate_domain_result_success'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’è¿½åŠ ã—ã¾ã—ãŸã€‚ (%s)'; # XXX Text changed to: The domain %s has been added.
-$PALANG['domain_updated'] = 'The domain %s has been updated.'; # XXX
-$PALANG['pAdminDelete_admin_error'] = 'Unable to delete admin!'; # XXX
-
-$PALANG['domain_postdel_failed'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ãŒå‰Šé™¤ã§ãã¾ã›ã‚“ï¼'; # XXX Text changed to: The domain postdeletion script failed, check the error log for details!
-$PALANG['domain_postcreate_failed'] = 'The domain postcreate script failed, check the error log for details!'; # XXX
-$PALANG['mailbox_postdel_failed'] = 'The mailbox postdeletion script failed, check the error log for details!'; # XXX
-$PALANG['mailbox_postedit_failed'] = 'The mailbox postedit script failed, check the error log for details!'; # XXX
-$PALANG['mailbox_postcreate_failed'] = 'The mailbox postcreate script failed, check the error log for details!'; # XXX
-$PALANG['pAdminDelete_alias_domain_error'] = 'Unable to remove domain alias!'; # XXX
-$PALANG['domain_conflict_vacation_domain'] = 'You can\'t use the vacation domain as mail domain!'; # XXX
+$PALANG['pAdminCreate_domain_button'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’è¿½åŠ ';
+$PALANG['pAdminCreate_domain_result_error'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ %s ã‚’è¿½åŠ ã§ãã¾ã›ã‚“ã§ã—ãŸï¼';
+$PALANG['pAdminCreate_domain_result_success'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ %s ã‚’è¿½åŠ ã—ã¾ã—ãŸã€‚';
+$PALANG['domain_updated'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ %s ã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚';
+$PALANG['pAdminDelete_admin_error'] = 'ç®¡ç†è€…ã‚’å‰Šé™¤ã§ãã¾ã›ã‚“ã§ã—ãŸ';
+
+$PALANG['domain_postdel_failed'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã®å‰Šé™¤å¾Œã«ã€ã‚¹ã‚¯ãƒªãƒ—ãƒˆã®å®Ÿè¡ŒãŒå¤±æ•—ã—ã¾ã—ãŸï¼ è©³ã—ãã¯ã‚¨ãƒ©ãƒ¼ãƒ­ã‚°ã‚’å‚ç…§ã—ã¦ä¸‹ã•ã„ã€‚';
+$PALANG['domain_postcreate_failed'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã®ä½œæˆå¾Œã«ã€ã‚¹ã‚¯ãƒªãƒ—ãƒˆã®å®Ÿè¡ŒãŒå¤±æ•—ã—ã¾ã—ãŸ! è©³ã—ãã¯ã‚¨ãƒ©ãƒ¼ãƒ­ã‚°ã‚’å‚ç…§ã—ã¦ä¸‹ã•ã„ã€‚';
+$PALANG['mailbox_postdel_failed'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã®å‰Šé™¤å¾Œã«ã€ã‚¹ã‚¯ãƒªãƒ—ãƒˆã®å®Ÿè¡ŒãŒå¤±æ•—ã—ã¾ã—ãŸ! è©³ã—ãã¯ã‚¨ãƒ©ãƒ¼ãƒ­ã‚°ã‚’å‚ç…§ã—ã¦ä¸‹ã•ã„ã€‚';
+$PALANG['mailbox_postedit_failed'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã®ç·¨é›†å¾Œã«ã€ã‚¹ã‚¯ãƒªãƒ—ãƒˆã®å®Ÿè¡ŒãŒå¤±æ•—ã—ã¾ã—ãŸ! è©³ã—ãã¯ã‚¨ãƒ©ãƒ¼ãƒ­ã‚°ã‚’å‚ç…§ã—ã¦ä¸‹ã•ã„ã€‚';
+$PALANG['mailbox_postcreate_failed'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã®ä½œæˆå¾Œã«ã€ã‚¹ã‚¯ãƒªãƒ—ãƒˆã®å®Ÿè¡ŒãŒå¤±æ•—ã—ã¾ã—ãŸ! è©³ã—ãã¯ã‚¨ãƒ©ãƒ¼ãƒ­ã‚°ã‚’å‚ç…§ã—ã¦ä¸‹ã•ã„ã€‚';
+$PALANG['pAdminDelete_alias_domain_error'] = 'ç®¡ç†è€…ã®åˆ¥åã‚’å‰Šé™¤ã§ãã¾ã›ã‚“ã§ã—ãŸ!';
+$PALANG['domain_conflict_vacation_domain'] = 'ãƒ¡ãƒ¼ãƒ«ãƒ‰ãƒ¡ã‚¤ãƒ³ã¨ã—ã¦ã€è‡ªå‹•å¿œç­”ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’ä½¿ç”¨ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“!';
 
 $PALANG['pAdminEdit_domain_welcome'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã®ä¿®æ­£';
 $PALANG['pAdminEdit_domain_aliases_text'] = '-1 = ç„¡åŠ¹ | 0 = ç„¡åˆ¶é™';
 $PALANG['pAdminEdit_domain_maxquota'] = 'æœ€å¤§å®¹é‡åˆ¶é™';
 $PALANG['pAdminEdit_domain_maxquota_text'] = 'MB | -1 = ç„¡åŠ¹ | 0 = ç„¡åˆ¶é™';
-$PALANG['pAdminEdit_domain_quota'] = 'Domain Quota'; # XXX
+$PALANG['pAdminEdit_domain_quota'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚¯ã‚ªãƒ¼ã‚¿';
 $PALANG['transport'] = 'é…é€æ–¹æ³•';
 $PALANG['pAdminEdit_domain_transport_text'] = 'é…é€æ–¹æ³•ã®å®šç¾©';
 $PALANG['pAdminEdit_domain_backupmx'] = 'ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ— MXã‚µãƒ¼ãƒ';
-$PALANG['pAdminEdit_domain_result_error'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ãŒä¿®æ­£ã§ãã¾ã›ã‚“ï¼ (%s)'; # XXX Text changed to: Modifying the domain %s failed!
+$PALANG['pAdminEdit_domain_result_error'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ %s ã‚’ä¿®æ­£ã§ãã¾ã›ã‚“!';
 
 $PALANG['pAdminCreate_admin_welcome'] = 'æ–°ã—ã„ãƒ‰ãƒ¡ã‚¤ãƒ³ç®¡ç†è€…ã®è¿½åŠ ';
 $PALANG['email_address'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹';
 $PALANG['pAdminCreate_admin_username_text_error1'] = 'ç®¡ç†è€…ã¯æœ‰åŠ¹ãªãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã¯ã‚ã‚Šã¾ã›ã‚“ã€‚';
-$PALANG['admin_already_exists'] = 'ç®¡ç†è€…ã¯å­˜åœ¨ã™ã‚‹ã‹ç„¡åŠ¹ã§ã™ã€‚'; # XXX Text changed to: The admin already exists!
-$PALANG['admin_does_not_exist'] = 'The admin does not exist!'; # XXX
+$PALANG['admin_already_exists'] = 'ç®¡ç†è€…ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™!';
+$PALANG['admin_does_not_exist'] = 'ç®¡ç†è€…ãŒå­˜åœ¨ã—ã¾ã›ã‚“!';
 $PALANG['pAdminCreate_admin_button'] = 'ç®¡ç†è€…è¿½åŠ ';
-$PALANG['pAdminCreate_admin_result_error'] = 'ç®¡ç†è€…ã‚’è¿½åŠ ã§ãã¾ã›ã‚“ï¼ (%s)'; # XXX Text changed to: Adding the admin %s failed!
-$PALANG['pAdminCreate_admin_result_success'] = 'ç®¡ç†è€…ã‚’è¿½åŠ ã—ã¾ã—ãŸã€‚ (%s)'; # XXX Text changed to: The admin %s has been added.
+$PALANG['pAdminCreate_admin_result_error'] = 'ç®¡ç†è€… %s ã‚’è¿½åŠ ã§ãã¾ã›ã‚“ã§ã—ãŸ!';
+$PALANG['pAdminCreate_admin_result_success'] = 'ç®¡ç†è€… %s ã‚’è¿½åŠ ã—ã¾ã—ãŸã€‚';
 
 $PALANG['pAdminEdit_admin_welcome'] = 'ãƒ‰ãƒ¡ã‚¤ãƒ³ç®¡ç†è€…ã®ç·¨é›†';
-$PALANG['admin'] = 'ç®¡ç†è€…'; # XXX check / compare with pAdminCreate_admin_username - should be "admin"
+$PALANG['admin'] = 'ç®¡ç†è€…';
 $PALANG['password_again'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ (ç¢ºèª)';
 $PALANG['super_admin'] = 'ç‰¹æ¨©ç®¡ç†è€…';
-$PALANG['super_admin_desc'] = 'Super admins have access to all domains, can manage domains and admin accounts.'; # XXX
-$PALANG['pAdminEdit_admin_result_error'] = 'ç®¡ç†è€…ã‚’ä¿®æ­£ã§ãã¾ã›ã‚“ï¼ (%s)'; # XXX Text changed to: Modifying the admin %s failed!
-$PALANG['pAdminEdit_admin_result_success'] = 'ç®¡ç†è€…ã‚’ä¿®æ­£ã—ã¾ã—ãŸã€‚ (%s)'; # XXX Text changed to: The admin %s has been modified.
+$PALANG['super_admin_desc'] = 'ç‰¹æ¨©ç®¡ç†è€…ã¯ã™ã¹ã¦ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã«ã‚¢ã‚¯ã‚»ã‚¹ãŒå¯èƒ½ã§ã€ãƒ‰ãƒ¡ã‚¤ãƒ³ã¨ç®¡ç†è€…ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’ç®¡ç†ã§ãã¾ã™ã€‚';
+$PALANG['pAdminEdit_admin_result_error'] = 'ç®¡ç†è€… %s ã‚’æ›´æ–°ã§ãã¾ã›ã‚“ã§ã—ãŸ!';
+$PALANG['pAdminEdit_admin_result_success'] = 'ç®¡ç†è€… %s ã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚';
 
 $PALANG['pUsersLogin_welcome'] = 'ã‚ãªãŸã®ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã¨è»¢é€å…ˆãŒå¤‰æ›´ã§ãã¾ã™ã€‚';
 $PALANG['pUsersLogin_username_incorrect'] = 'ãƒ­ã‚°ã‚¤ãƒ³ãŒé•ã„ã¾ã™ã€‚æ­£ã—ã„ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’å…¥åŠ›ã—ã¦ãã ã•ã„ã€‚';
 $PALANG['pUsersLogin_password_incorrect'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ãŒé•ã„ã¾ã™ã€‚';
+$PALANG['pUsersLogin_password_recover'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¿˜ã‚Œã¾ã—ãŸ';
 
 $PALANG['pUsersMenu_vacation'] = 'è‡ªå‹•å¿œç­”';
-$PALANG['pUsersMenu_edit_alias'] = 'è»¢é€å…ˆå¤‰æ›´';
+$PALANG['pUsersMenu_edit_alias'] = 'è»¢é€å…ˆã‚’å¤‰æ›´';
 
 $PALANG['pUsersMain_vacation'] = 'ä¸åœ¨ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¾ãŸã¯è‡ªå‹•å¿œç­”ã‚’è¨­å®šã—ã¾ã™';
 $PALANG['pUsersMain_vacationSet'] = 'è‡ªå‹•å¿œç­”ã‚’åˆ©ç”¨ä¸­ã§ã™ã€‚ã€Œè‡ªå‹•å¿œç­”ã€ã‚’ã‚¯ãƒªãƒƒã‚¯ã—ã¦ç·¨é›†ï¼è§£é™¤ã§ãã¾ã™ã€‚';
@@ -307,18 +319,18 @@ $PALANG['pUsersMain_edit_alias'] = 'è»¢é
 $PALANG['pUsersMain_password'] = 'ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å¤‰æ›´ã—ã¾ã™ã€‚';
 
 $PALANG['pUsersVacation_welcome'] = 'è‡ªå‹•å¿œç­”';
-$PALANG['pUsersVacation_welcome_text'] = 'æ—¢ã«è‡ªå‹•å¿œç­”ã‚’æ§‹æˆã—ã¦ã‚ã‚Šã¾ã™ã€‚ (%s)'; # XXX Text changed to: 'Auto response for %s is active!'
+$PALANG['pUsersVacation_welcome_text'] = '%s ã®è‡ªå‹•å¿œç­”ã¯æœ‰åŠ¹ã§ã™!';
 $PALANG['pUsersVacation_subject_text'] = 'ä¸åœ¨';
-$PALANG['message'] = 'æœ¬æ–‡'; # XXX text changed to 'Message'
+$PALANG['message'] = 'æœ¬æ–‡';
 $PALANG['pUsersVacation_body_text'] = <<<EOM
 ç§ã¯ <date> ã‹ã‚‰ <date> ã¾ã§ä¸åœ¨ã§ã™ã€‚
 ç·Šæ€¥äº‹é …ã¯ <contact person> ã¾ã§é€£çµ¡ã—ã¦ãã ã•ã„ã€‚
 EOM;
-$PALANG['pUsersVacation_activefrom'] = 'Active from'; # XXX
-$PALANG['pUsersVacation_activeuntil'] = 'Active until'; # XXX
+$PALANG['pUsersVacation_activefrom'] = 'å³ã®æ—¥æ™‚ã‹ã‚‰æœ‰åŠ¹';
+$PALANG['pUsersVacation_activeuntil'] = 'å³ã®æ—¥æ™‚ã¾ã§æœ‰åŠ¹';
 
 
-$PALANG['pEdit_dbLog_editactive'] = 'change active state'; # XXX
+$PALANG['pEdit_dbLog_editactive'] = 'æœ‰åŠ¹ï¼ç„¡åŠ¹ã‚’å¤‰æ›´';
 
 $PALANG['pSearch'] = 'æ¤œç´¢';
 $PALANG['pSearch_welcome'] = 'æ¤œç´¢æ–‡å­—åˆ—: ';
@@ -330,31 +342,33 @@ $PALANG['pBroadcast_name'] = 'åå‰';
 $PALANG['pBroadcast_success'] = 'ãƒ–ãƒ­ãƒ¼ãƒ‰ã‚­ãƒ£ã‚¹ãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯é€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚';
 $PALANG['pAdminMenu_broadcast_message'] = 'ãƒ–ãƒ­ãƒ¼ãƒ‰ã‚­ãƒ£ã‚¹ãƒˆ';
 $PALANG['pBroadcast_error_empty'] = 'åå‰ã€ä»¶åã€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯å…¥åŠ›ãŒå¿…è¦ã§ã™ã€‚';
+$PALANG['broadcast_mailboxes_only'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã ã‘ã«é€ä¿¡';
+$PALANG['broadcast_to_domains'] = 'é€ä¿¡å…ˆã®ãƒ‰ãƒ¡ã‚¤ãƒ³:';
 
 $PALANG['pStatus_undeliverable'] = 'ãŠãã‚‰ãé…é€ä¸å¯èƒ½ ';
 $PALANG['pStatus_custom'] = 'é…é€å…ˆ ';
 $PALANG['pStatus_popimap'] = 'POP/IMAP ';
 
 $PALANG['password_too_short'] = "ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ãŒçŸ­ã™ãŽã¾ã™ã€‚æœ€ä½Ž %s æ–‡å­—å¿…è¦ã§ã™ã€‚";
-$PALANG['password_no_characters'] = "Your password must contain at least %s character(s)."; # XXX
-$PALANG['password_no_digits'] = "Your password must contain at least %s digit(s)."; # XXX
-$PALANG['pInvalidDomainRegex'] = "Invalid domain name %s, fails regexp check"; # XXX
-$PALANG['pInvalidDomainDNS'] = "Invalid domain %s, and/or not discoverable in DNS"; # XXX
-$PALANG['pInvalidMailRegex'] = "Invalid email address %s, fails regexp check"; # XXX
+$PALANG['password_no_characters'] = "ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã«ã¯ã€å°‘ãªãã¨ã‚‚ %s å€‹ã®è‹±å­—ãŒãªãã¦ã¯ãªã‚Šã¾ã›ã‚“ã€‚";
+$PALANG['password_no_digits'] = "ãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã«ã¯ã€å°‘ãªãã¨ã‚‚ %s å€‹ã®æ•°å­—ãŒãªãã¦ã¯ãªã‚Šã¾ã›ã‚“ã€‚";
+$PALANG['pInvalidDomainRegex'] = "ä¸æ­£ãªãƒ‰ãƒ¡ã‚¤ãƒ³åã§ã™[%s]ã€‚æ­£è¦è¡¨ç¾ãƒã‚§ãƒƒã‚¯ã§å¤±æ•—";
+$PALANG['pInvalidDomainDNS'] = "ä¸æ­£ãªãƒ‰ãƒ¡ã‚¤ãƒ³[%s]ã§ã‚ã‚‹ã‹ã€ã‚‚ã—ãã¯ DNS ã«è¦‹å½“ãŸã‚Šã¾ã›ã‚“";
+$PALANG['pInvalidMailRegex'] = "ä¸æ­£ãªãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã™[%s]ã€‚æ­£è¦è¡¨ç¾ãƒã‚§ãƒƒã‚¯ã§å¤±æ•—";
 
 $PALANG['pFetchmail_welcome'] = 'ãƒ¡ãƒ¼ãƒ«å–å¾—:';
 $PALANG['pFetchmail_new_entry'] = 'æ–°ã—ã„ã‚¨ãƒ³ãƒˆãƒª';
-$PALANG['fetchmail_already_exists']         = 'This fetchmail job already exists!'; # XXX
-$PALANG['fetchmail_does_not_exist']         = 'This fetchmail job does not exist!'; # XXX
+$PALANG['fetchmail_already_exists']         = 'ã“ã® fetchmail ã‚¸ãƒ§ãƒ–ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™!';
+$PALANG['fetchmail_does_not_exist']         = 'ã“ã® fetchmail ã‚¸ãƒ§ãƒ–ã¯å­˜åœ¨ã—ã¾ã›ã‚“!';
 $PALANG['pFetchmail_database_save_error'] = 'ã“ã®ã‚¨ãƒ³ãƒˆãƒªã‚’ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚';
 $PALANG['pFetchmail_database_save_success'] = 'ã‚¨ãƒ³ãƒˆãƒªã‚’ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ä¿å­˜ã—ã¾ã—ãŸã€‚';
 $PALANG['pFetchmail_error_invalid_id'] = 'ID %s ã®ã‚¨ãƒ³ãƒˆãƒªãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã€‚';
-$PALANG['pFetchmail_invalid_mailbox'] = 'ãƒ¡ãƒ¼ãƒ«ãƒœãƒƒã‚¯ã‚¹ãŒç„¡åŠ¹ã§ã™ï¼';
+$PALANG['pFetchmail_invalid_mailbox'] = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒç„¡åŠ¹ã§ã™ï¼';
 $PALANG['pFetchmail_server_missing'] = 'ãƒªãƒ¢ãƒ¼ãƒˆã‚µãƒ¼ãƒåã‚’å…¥åŠ›ã—ã¦ãã ã•ã„ã€‚';
 $PALANG['pFetchmail_user_missing'] = 'ãƒªãƒ¢ãƒ¼ãƒˆãƒ¦ãƒ¼ã‚¶åã‚’å…¥åŠ›ã—ã¦ãã ã•ã„ã€‚';
 $PALANG['pFetchmail_password_missing'] = 'ãƒªãƒ¢ãƒ¼ãƒˆãƒ‘ã‚¹ãƒ¯ãƒ¼ãƒ‰ã‚’å…¥åŠ›ã—ã¦ãã ã•ã„ã€‚';
 $PALANG['pFetchmail_field_id']              = 'ID';
-$PALANG['pFetchmail_field_mailbox']         = 'ãƒ¡ãƒ¼ãƒ«ãƒœãƒƒã‚¯ã‚¹';
+$PALANG['pFetchmail_field_mailbox']         = 'ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹';
 $PALANG['pFetchmail_field_src_server']      = 'ã‚µãƒ¼ãƒ';
 $PALANG['pFetchmail_field_src_auth']        = 'èªè¨¼ã‚¿ã‚¤ãƒ—';
 $PALANG['pFetchmail_field_src_user']        = 'ãƒ¦ãƒ¼ã‚¶';
@@ -364,10 +378,10 @@ $PALANG['pFetchmail_field_poll_time']
 $PALANG['pFetchmail_field_fetchall']        = 'ã™ã¹ã¦å–å¾—';
 $PALANG['pFetchmail_field_keep']            = 'æ®‹ã™';
 $PALANG['pFetchmail_field_protocol']        = 'ãƒ—ãƒ­ãƒˆã‚³ãƒ«';
-$PALANG['pFetchmail_field_usessl']          = 'SSL active'; # XXX
-$PALANG['pFetchmail_field_sslcertck']       = 'SSL certificate check'; # XXX
-$PALANG['pFetchmail_field_sslcertpath']     = 'SSL path to certificates'; # XXX
-$PALANG['pFetchmail_field_sslfingerprint']  = 'SSL fingerprint (md5)'; # XXX
+$PALANG['pFetchmail_field_usessl']          = 'SSL æœ‰åŠ¹';
+$PALANG['pFetchmail_field_sslcertck']       = 'SSL è¨¼æ˜Žæ›¸ãƒã‚§ãƒƒã‚¯';
+$PALANG['pFetchmail_field_sslcertpath']     = 'SSL è¨¼æ˜Žæ›¸ã¸ã®ãƒ‘ã‚¹';
+$PALANG['pFetchmail_field_sslfingerprint']  = 'SSL ãƒ•ã‚£ãƒ³ã‚¬ãƒ¼ãƒ—ãƒªãƒ³ãƒˆ (md5)';
 $PALANG['pFetchmail_field_extra_options']   = 'è¿½åŠ ã‚ªãƒ—ã‚·ãƒ§ãƒ³';
 $PALANG['pFetchmail_field_mda']             = 'MDA';
 $PALANG['pFetchmail_field_date']            = 'æ—¥ä»˜';
@@ -383,13 +397,13 @@ $PALANG['pFetchmail_desc_poll_time']
 $PALANG['pFetchmail_desc_fetchall']         = 'æ—¢èª­ã¨æ–°ç€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’å–å¾—ã™ã‚‹ã‹';
 $PALANG['pFetchmail_desc_keep']             = 'ãƒªãƒ¢ãƒ¼ãƒˆã‚µãƒ¼ãƒã«å–å¾—æ¸ˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’æ®‹ã™ã‹';
 $PALANG['pFetchmail_desc_protocol']         = 'åˆ©ç”¨ã™ã‚‹ãƒ—ãƒ­ãƒˆã‚³ãƒ«';
-$PALANG['pFetchmail_desc_usessl']           = 'SSL encryption'; # XXX
+$PALANG['pFetchmail_desc_usessl']           = 'SSL æš—å·åŒ–';
 $PALANG['pFetchmail_desc_extra_options']    = 'è¿½åŠ ã® fetchmail ã‚ªãƒ—ã‚·ãƒ§ãƒ³';
 $PALANG['pFetchmail_desc_mda']              = 'ãƒ¡ãƒ¼ãƒ«é…é€ã‚¨ãƒ¼ã‚¸ã‚§ãƒ³ãƒˆ (Mail Delivery Agent)';
 $PALANG['pFetchmail_desc_date']             = 'æœ€çµ‚å–å¾—ç¢ºèªï¼è¨­å®šå¤‰æ›´æ—¥æ™‚';
 $PALANG['pFetchmail_desc_returned_text']    = 'æ–°ç€ç¢ºèªã®æˆ»ã‚Šãƒ†ã‚­ã‚¹ãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸';
-$PALANG['dateformat_pgsql'] = 'YYYY-mm-dd'; # translators: rearrange to your local date format, but make sure it's a valid PostgreSQL date format # XXX
-$PALANG['dateformat_mysql'] = '%Y-%m-%d';   # translators: rearrange to your local date format, but make sure it's a valid MySQL date format # XXX
+$PALANG['dateformat_pgsql'] = 'YYYY-mm-dd'; # translators: rearrange to your local date format, but make sure it's a valid PostgreSQL date format
+$PALANG['dateformat_mysql'] = '%Y-%m-%d';   # translators: rearrange to your local date format, but make sure it's a valid MySQL date format
 
 $PALANG['please_keep_this_as_last_entry'] = ''; # needed for language-check.sh
 /* vim: set expandtab ft=php softtabstop=3 tabstop=3 shiftwidth=3: */
diff -pruN 3.0.2-2/languages/language.php 3.2-2/languages/language.php
--- 3.0.2-2/languages/language.php	2016-09-09 20:08:57.000000000 +0000
+++ 3.2-2/languages/language.php	2018-05-02 20:37:27.000000000 +0000
@@ -1,4 +1,6 @@
-<?php if( !defined('POSTFIXADMIN') ) die( "This file cannot be used standalone." ); ?>
+<?php if (!defined('POSTFIXADMIN')) {
+    die("This file cannot be used standalone.");
+} ?>
 <?php
 # List of supported languages
 $supported_languages = array(
diff -pruN 3.0.2-2/languages/language-update.sh 3.2-2/languages/language-update.sh
--- 3.0.2-2/languages/language-update.sh	2014-09-12 09:52:21.000000000 +0000
+++ 3.2-2/languages/language-update.sh	2018-05-02 20:37:27.000000000 +0000
@@ -8,7 +8,7 @@
  #
  # Further details on the project are available at http://postfixadmin.sf.net 
  #
- # @version $Id: language-update.sh 1686 2014-09-12 09:52:21Z christian_boltz $
+ # @version $Id$
  # @license GNU GPL v2 or later.
  #
  # File: language-update.sh
diff -pruN 3.0.2-2/languages/lt.lang 3.2-2/languages/lt.lang
--- 3.0.2-2/languages/lt.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/lt.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: lt.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Lithuanian 
 // by Giedrius <giedrius_balbieris at metalot dot com>
@@ -144,6 +144,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'IÅ¡naudota srities paÅ¡to dÄ—Å¾uÄiÅ³ kvota!';
 $PALANG['pCreate_mailbox_password_text'] = 'SlaptaÅ¾odis jungtis prie POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Vardas PavardÄ—';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'SiÅ³sti pasveikinimo Å¾inutÄ™';
 $PALANG['pCreate_mailbox_result_error'] = 'PaÅ¡to dÄ—Å¾utÄ—s uÅ¾registruoti nepavyko! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'PaÅ¡to dÄ—Å¾utÄ— uÅ¾registruota! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -171,6 +175,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Keisti slaptaÅ¾odÄ¯';
 $PALANG['pPassword_result_error'] = 'SlaptaÅ¾odÅ¾io pakeisti nepavyko! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'SlaptaÅ¾odis pakeistas! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Pakeisti / nustatyti atostogÅ³ praneÅ¡imÄ…';
 $PALANG['pEdit_vacation_remove'] = 'IÅ¡jungti atostogÅ³ praneÅ¡imÄ…';
 $PALANG['pVacation_result_error'] = 'Nepavyko pakeisti atostogÅ³ nustatymÅ³! (%s)'; # XXX Text changed to: Updating the auto response settings for %s failed
@@ -186,7 +197,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'PerÅ¾iÅ«rÄ—ti paskutinius 10 vartotojo veiksmÅ³ ';
+$PALANG['pViewlog_welcome'] = 'PerÅ¾iÅ«rÄ—ti paskutinius %s vartotojo veiksmÅ³ ';
 $PALANG['pViewlog_timestamp'] = 'Laikas';
 $PALANG['pViewlog_action'] = 'Veiksmas';
 $PALANG['pViewlog_data'] = 'Duomenys';
@@ -292,6 +303,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'PaÅ¡to vartotojai prisijungia ir keiÄia slaptaÅ¾odÅ¾ius ir sinonimus.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Prisijungti nepavyko. Ä®sitikinkite, kad gerai Ä¯vedÄ—te savo el.paÅ¡to adresÄ…!';
 $PALANG['pUsersLogin_password_incorrect'] = 'SlaptaÅ¾odis neteisingas!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Automatinis (atostogÅ³) atsakymas';
 $PALANG['pUsersMenu_edit_alias'] = 'Keisti laiÅ¡kÅ³ peradresacijÄ…';
@@ -328,6 +340,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.'; # XXX
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/mk.lang 3.2-2/languages/mk.lang
--- 3.0.2-2/languages/mk.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/mk.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: mk.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Macedonian
 // by Damjan Georgiev <dame at mol dot com dot mk>
@@ -143,6 +143,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Ð”Ð¾ÑÑ‚Ð¸Ð³Ð½Ð°Ñ‚ Ðµ Ð»Ð¸Ð¼Ð¸Ñ‚Ð¾Ñ‚ Ð½Ð° Ð¿Ð¾ÑˆÑ‚ÐµÐ½ÑÐºÐ¸ ÑÐ°Ð½Ð´Ð°Ñ‡Ð¸ÑšÐ°!';
 $PALANG['pCreate_mailbox_password_text'] = 'Ð›Ð¾Ð·Ð¸Ð½ÐºÐ° Ð·Ð° POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Ð¦ÐµÐ»Ð¾ Ð¸Ð¼Ðµ';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'ÐšÑ€ÐµÐ¸Ñ€Ð°ÑšÐµ Ð½Ð° Ð¿Ð¾ÑˆÑ‚ÐµÐ½ÑÐºÐ¾ ÑÐ°Ð½Ð´Ð°Ñ‡Ðµ'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'ÐÐµ Ð¼Ð¾Ð¶Ð°Ð¼ Ð´Ð° Ð´Ð¾Ð´Ð°Ð´Ð°Ð¼ Ð½Ð¾Ð²Ð¾ ÑÐ°Ð½Ð´Ð°Ñ‡Ðµ Ð½Ð° Ñ‚Ð°Ð±ÐµÐ»Ð°Ñ‚Ð°! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'ÐŸÐ¾ÑˆÑ‚ÐµÐ½ÑÐºÐ¾Ñ‚Ð¾ ÑÐ°Ð½Ð´Ð°Ñ‡Ðµ Ðµ Ð´Ð¾Ð´Ð°Ð´ÐµÐ½Ð¾ Ð½Ð° Ñ‚Ð°Ð±ÐµÐ»Ð°Ñ‚Ð°! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -170,6 +174,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'ÐŸÑ€Ð¾Ð¼ÐµÐ½Ð° Ð½Ð° Ð»Ð¾Ð·Ð¸Ð½ÐºÐ°';
 $PALANG['pPassword_result_error'] = 'ÐÐµ Ð¼Ð¾Ð¶Ð°Ð¼ Ð´Ð° Ñ˜Ð° Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ð°Ð¼ Ð²Ð°ÑˆÐ°Ñ‚Ð° Ð»Ð¾Ð·Ð¸Ð½ÐºÐ°! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Ð’Ð°ÑˆÐ°Ñ‚Ð° Ð»Ð¾Ð·Ð¸Ð½ÐºÐ° Ðµ ÑÐ¼ÐµÐ½ÐµÑ‚Ð°! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -185,7 +196,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'ÐŸÑ€ÐµÐ³Ð»ÐµÐ´ Ð½Ð° Ð¿Ð¾ÑÐ»ÐµÐ´Ð½Ð¸Ñ‚Ðµ 10 Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¸ Ð·Ð°: ';
+$PALANG['pViewlog_welcome'] = 'ÐŸÑ€ÐµÐ³Ð»ÐµÐ´ Ð½Ð° Ð¿Ð¾ÑÐ»ÐµÐ´Ð½Ð¸Ñ‚Ðµ %s Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¸ Ð·Ð°: ';
 $PALANG['pViewlog_timestamp'] = 'ÐœÐ°Ñ€ÐºÐµÑ€ (Timestamp)';
 $PALANG['pViewlog_action'] = 'ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ˜Ð°';
 $PALANG['pViewlog_data'] = 'Ð”Ð°Ñ‚ÑƒÐ¼';
@@ -292,6 +303,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Ð›Ð¾Ð³Ð¸Ð½ Ð·Ð° ÐºÐ¾Ñ€Ð¸ÑÐ½Ð¸Ñ†Ð¸ Ð½Ð° Ð¿Ð¾ÑˆÑ‚ÐµÐ½ÑÐºÐ¸ ÑÐ°Ð½Ð´Ð°Ñ‡Ð¸ÑšÐ°.ÐŸÑ€Ð¾Ð¼ÐµÐ½Ð° Ð½Ð° Ð»Ð¾Ð³Ð¸Ð½ Ð¸ Ð»Ð¾Ð·Ð¸Ð½ÐºÐ°';
 $PALANG['pUsersLogin_username_incorrect'] = 'ÐŸÐ¾Ð³Ñ€ÐµÑˆÐ½Ð¾ ÐºÐ¾Ñ€Ð¸ÑÐ½Ð¸Ñ‡ÐºÐ¾ Ð¸Ð¼Ðµ. Ð›Ð¾Ð³Ð¸Ñ€Ð°Ñ˜Ñ‚Ðµ ÑÐµ ÑÐ¾ Ð²Ð°ÑˆÐ°Ñ‚Ð° email Ð°Ð´Ñ€ÐµÑÐ°!';
 $PALANG['pUsersLogin_password_incorrect'] = 'ÐŸÐ¾Ð³Ñ€ÐµÑˆÐ½Ð° Ð»Ð¾Ð·Ð¸Ð½ÐºÐ°!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'ÐÐ²Ñ‚Ð¾Ð¼Ð°Ñ‚ÑÐºÐ¸ Ð¾Ð´Ð³Ð¾Ð²Ð¾Ñ€';
 $PALANG['pUsersMenu_edit_alias'] = 'ÐŸÑ€Ð¾Ð¼ÐµÐ½Ð° Ð½Ð° Ð¿Ñ€ÐµÐ¿Ñ€Ð°ÑœÐ°ÑšÐµ (forward)';
@@ -323,6 +335,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.'; # XXX
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/nb.lang 3.2-2/languages/nb.lang
--- 3.0.2-2/languages/nb.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/nb.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: nb.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Norwegian (bokmÃ¥l)
 // by Odd Henriksen
@@ -144,6 +144,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Du har nÃ¥dd grensen for antall e-postkontoer under dette domenet!';
 $PALANG['pCreate_mailbox_password_text'] = 'Passord for POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Fullt navn';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Send velkomstmelding'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Kunne ikke legge til e-postkontoen i mailbox-tabellen! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'E-postkontoen er blitt opprettet i mailbox-tabellen! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -171,6 +175,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Endre passord';
 $PALANG['pPassword_result_error'] = 'Kunne ikke endre passordet ditt! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Ditt passord er nÃ¥ endret! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Endre / angi fravÃ¦rsmelding';
 $PALANG['pEdit_vacation_remove'] = 'Fjern fravÃ¦rsmelding';
 $PALANG['pVacation_result_error'] = 'Kunne ikke oppdatere innstillinger for automatisk svar! (%s)'; # XXX Text changed to: Updating the auto response settings for %s failed
@@ -186,7 +197,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Vis de 10 siste handlingene for ';
+$PALANG['pViewlog_welcome'] = 'Vis de %s siste handlingene for ';
 $PALANG['pViewlog_timestamp'] = 'Klokkeslett';
 $PALANG['pViewlog_action'] = 'Handling';
 $PALANG['pViewlog_data'] = 'Data';
@@ -292,6 +303,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Brukere kan logge inn her for Ã¥ endre passord og videresending.';
 $PALANG['pUsersLogin_username_incorrect'] = 'PÃ¥loggingsinformasjonen er ikke korrekt. Husk Ã¥ bruke e-postadressen som brukernavn.';
 $PALANG['pUsersLogin_password_incorrect'] = 'Feil passord!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Automatisk svar';
 $PALANG['pUsersMenu_edit_alias'] = 'Endre videresending';
@@ -322,6 +334,8 @@ $PALANG['pBroadcast_name'] = 'Ditt navn'
 $PALANG['pBroadcast_success'] = 'Masseutsendelsesmeldingen ble sendt.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Send masseutsendelse';
 $PALANG['pBroadcast_error_empty'] = 'Feltene Ditt navn, Emne og Melding kan ikke vÃ¦re tomme!';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'kan kanskje IKKE LEVERES ';
 $PALANG['pStatus_custom'] = 'Leverer til ';
 $PALANG['pStatus_popimap'] = 'POP/IMAP ';
diff -pruN 3.0.2-2/languages/nl.lang 3.2-2/languages/nl.lang
--- 3.0.2-2/languages/nl.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/nl.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,9 +1,10 @@
 <?php
-# $Id: nl.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Dutch
 // by Mourik
 // updated by Johan Hendriks (sylhouette @sf)
+// updates by Jan Kruis ( jan @crossreference.nl
 //
 
 $PALANG['YES'] = 'Ja';
@@ -14,28 +15,28 @@ $PALANG['exit'] = 'BeÃ«indigen';
 $PALANG['cancel'] = 'Annuleren';
 $PALANG['save'] = 'Wijzigingen opslaan';
 $PALANG['confirm'] = 'Weet u het zeker dat u wilt verwijderen?\n';
-$PALANG['confirm_delete_admin'] = 'Do you really want to delete the admin %s?'; # XXX
-$PALANG['confirm_delete_alias'] = 'Do you really want to delete the alias %s?'; # XXX
-$PALANG['confirm_delete_aliasdomain'] = 'Do you really want to delete the alias domain %s?'; # XXX
-$PALANG['confirm_delete_domain'] = 'Weet u zeker dat u ALLE data van het domein wilt verwijderen? Dit kan niet ongedaan worden gemaakt!\n (%s)'; # XXX text changed to: 'Do you really want to delete all records for the domain %s? This can not be undone'
-$PALANG['confirm_delete_fetchmail'] = 'Do you really want to delete the fetchmail job %s?'; # XXX
-$PALANG['confirm_delete_mailbox'] = 'Do you really want to delete the mailbox %s?'; # XXX
-$PALANG['confirm_delete_vacation'] = 'Do you really want to delete the vacation message for %s?'; # XXX
-$PALANG['no_delete_permissions'] = 'You are not allowed to delete %s!'; # XXX
+$PALANG['confirm_delete_admin'] = 'Weet u zeker dat dat u de administrator %s wilt verwijderen?';
+$PALANG['confirm_delete_alias'] = 'Weet u zeker dat dat u de alias %s wilt verwijderen?';
+$PALANG['confirm_delete_aliasdomain'] = 'Weet u zeker dat dat u de alias domein %s wilt verwijderen?';
+$PALANG['confirm_delete_domain'] = 'Weet u zeker dat u ALLE gegevens van het domein %s wilt verwijderen? Dit kan niet ongedaan worden gemaakt!';
+$PALANG['confirm_delete_fetchmail'] = 'Weet u zeker dat dat u de fetchmail job %s wilt verwijderen?';
+$PALANG['confirm_delete_mailbox'] = 'Weet u zeker dat dat u de mailbox %s wilt verwijderen?';
+$PALANG['confirm_delete_vacation'] = 'Weet u zeker dat dat u de vakatie bericht voor %s wilt verwijderen?';
+$PALANG['no_delete_permissions'] = 'Je hebt geen toestemming om %s te verwijderen!';
 $PALANG['check_update'] = 'Zoeken naar nieuwe versie';
 $PALANG['invalid_parameter'] = 'ongeldige parameter!';
 $PALANG['show'] = 'Toon:';
 $PALANG['all'] = 'Alle';
-$PALANG['created'] = 'Aangemaakt'; #XXX
-$PALANG['unknown'] = 'onbekend'; #XXX
-$PALANG['download_csv'] = 'Download this list as CSV file'; # XXX
-$PALANG['missing_field'] = 'Veld %s is niet aanwezig'; #XXX
-$PALANG['must_be_numeric'] = '%s moet een getal zijn'; #XXX
-$PALANG['must_be_numeric_bigger_than_null'] = '%s must be numeric and bigger than 0'; # XXX
-$PALANG['must_be_boolean'] = '%s moet een boolean zijn'; #XXX
-$PALANG['invalid_value_given'] = 'Foutief waarde ingevooerd %s'; # XXX
-$PALANG['edit_not_allowed'] = 'You are not allowed to edit %s'; # XXX
-$PALANG['searchparams'] = 'Search parameters:'; # XXX
+$PALANG['created'] = 'Aangemaakt';
+$PALANG['unknown'] = 'onbekend';
+$PALANG['download_csv'] = 'Bewaar deze lijst als CSV bestand';
+$PALANG['missing_field'] = 'Veld %s is niet aanwezig';
+$PALANG['must_be_numeric'] = '%s moet een getal zijn';
+$PALANG['must_be_numeric_bigger_than_null'] = '%s moet een getal zijn en groter dan 0';
+$PALANG['must_be_boolean'] = '%s moet een boolean zijn';
+$PALANG['invalid_value_given'] = 'Foutief waarde ingevooerd %s';
+$PALANG['edit_not_allowed'] = 'Je hebt geen toestemming om %s aan te passen';
+$PALANG['searchparams'] = 'Zoek parameters:';
 $PALANG['pFooter_logged_as'] = 'aangemeld als %s';
 
 $PALANG['pLogin_welcome'] = 'Mail beheerders log hier in om uw domeinen te beheren.';
@@ -48,8 +49,8 @@ $PALANG['pLogin_login_users'] = 'Gebruik
 
 $PALANG['pMenu_main'] = 'Start';
 $PALANG['pMenu_overview'] = 'Overzicht';
-$PALANG['add_alias'] = 'Alias toevoegen'; # XXX check text - should be 'Add Alias'
-$PALANG['add_alias_domain'] = 'Domein alias toevoegen'; # XXX check text - should be 'Add Alias Domain'
+$PALANG['add_alias'] = 'Alias toevoegen';
+$PALANG['add_alias_domain'] = 'Domein alias toevoegen';
 $PALANG['add_mailbox'] = 'Mailbox toevoegen';
 $PALANG['pMenu_fetchmail'] = 'Externe email ophalen';
 $PALANG['pMenu_sendmail'] = 'Verstuur E-mail';
@@ -59,7 +60,7 @@ $PALANG['pMenu_logout'] = 'Uitloggen';
 
 $PALANG['pMain_welcome'] = 'Welkom bij Postfix Admin!';
 $PALANG['pMain_overview'] = 'Laat uw aliassen en mailboxen zien. U kunt ze vanaf hier bewerken / verwijderen.';
-$PALANG['pMain_create_alias'] = 'Maak een nieuwe alias aan voor uw domein.'; # XXX check text - should be 'Create a new alias for your domain.'
+$PALANG['pMain_create_alias'] = 'Maak een nieuwe alias aan voor uw domein.';
 $PALANG['pMain_create_mailbox'] = 'Maak een nieuwe mailbox aan voor uw domein.';
 $PALANG['pMain_sendmail'] = 'Verstuur een e-mail naar een van de nieuwe mailboxen.';
 $PALANG['pMain_password'] = 'Wijzig uw wachtwoord.';
@@ -86,18 +87,18 @@ $PALANG['name'] = 'Naam';
 $PALANG['pOverview_mailbox_quota'] = 'Quota (MB)';
 $PALANG['pOverview_vacation_edit'] = 'AUTOMATISCH BEANTWOORDEN IS ACTIEF';
 $PALANG['pOverview_vacation_option'] = 'Activeer automatisch beantwoorden';
-$PALANG['no_domains_for_this_admin'] = 'Je hebt geen elke domein toesteming.'; # XXX
-$PALANG['no_domains_exist'] = 'Je moet tenminste een domein aanmaken voordat je Virtueel overzicht kunt gebruiken.'; # "virtual list" should match $PALANG['pAdminMenu_list_virtual'] # XXX
+$PALANG['no_domains_for_this_admin'] = 'Je hebt voor geen elke domein toesteming.';
+$PALANG['no_domains_exist'] = 'Je moet tenminste een domein aanmaken voordat je virtueel overzicht kunt gebruiken.'; # "virtual list" should match $PALANG['pAdminMenu_list_virtual']
 
 $PALANG['domain'] = 'Domein';
 $PALANG['pOverview_get_alias_domains'] = 'Domein aliasen';
 $PALANG['mailboxes'] = 'Mailboxen';
 $PALANG['pOverview_get_quota'] = 'Mailbox Quota (MB)';
 
-$PALANG['pDelete_delete_error'] = 'Mislukt te verwijderen ';
+$PALANG['pDelete_delete_error'] = 'Niet in staat deze regel te verwijderen ';
 $PALANG['pDelete_delete_success'] = '%s verwijderd.';
 $PALANG['pDelete_domain_error'] = 'Dit is niet uw domein ';
-$PALANG['pDelete_alias_error'] = 'Niet in staat alias te verwijderen ';
+$PALANG['pDelete_alias_error'] = 'Niet in staat deze alias te verwijderen ';
 $PALANG['pCreate_alias_domain_welcome'] = 'Spiegel een van uw domeinen naar een ander domein.';
 $PALANG['pCreate_alias_domain_alias'] = 'Alias domein';
 $PALANG['pCreate_alias_domain_alias_text'] = 'Het domein waar mail voor binnen komt.';
@@ -105,28 +106,28 @@ $PALANG['pCreate_alias_domain_target'] =
 $PALANG['pCreate_alias_domain_target_text'] = 'Domein waar de mail naar toe moet.';
 $PALANG['pCreate_alias_domain_error1'] = 'U heeft niet genoeg rechten om de huidige configuratie te maken.';
 $PALANG['pCreate_alias_domain_error2'] = 'De huidige configuratie is ongeldig, slecteer een andere!';
-$PALANG['alias_domain_already_exists'] = 'Dit domein is al een alias domein!'; # XXX
-$PALANG['alias_domain_does_not_exist'] = 'Dit domein is geen alias domein!'; # XXX
-$PALANG['alias_domain_create_failed'] = 'Het aanmaken van het alias domein %s is niet gelukt!'; # XXX Text changed to: Creating the alias domain %s failed!
-$PALANG['alias_domain_change_failed'] = 'Het aanpassen van het alias domein %s is niet gelukt!'; # XXX
+$PALANG['alias_domain_already_exists'] = 'Dit domein is al een alias domein!';
+$PALANG['alias_domain_does_not_exist'] = 'Dit domein is geen alias domein!';
+$PALANG['alias_domain_create_failed'] = 'Het aanmaken van het alias domein %s is niet gelukt!';
+$PALANG['alias_domain_change_failed'] = 'Het aanpassen van het alias domein %s is niet gelukt!';
 $PALANG['pCreate_alias_domain_error4'] = 'Alle domeinen hebben al een alias!';
-$PALANG['pCreate_alias_domain_success'] = 'Het alias domein %s is aangemaakt'; # XXX Text changed to: The alias domain %s has been created.
-$PALANG['alias_domain_changed'] = 'Het alias domein %s is aangepast.'; # XXX
-$PALANG['alias_domain_to_itsself'] = 'Een domein kan niet een alias domein van zich zelf!'; # XXX
-$PALANG['delete_domain_aliasdomain_target'] = 'Het domein %s is onderdeel van een of meerdere domeinen en kan niet worden verwijderd! (Verwijder het alias domeins eerst.)'; # XXX
+$PALANG['pCreate_alias_domain_success'] = 'Het alias domein %s is aangemaakt';
+$PALANG['alias_domain_changed'] = 'Het alias domein %s is aangepast.';
+$PALANG['alias_domain_to_itsself'] = 'Een domein kan niet een alias domein van zich zelf!';
+$PALANG['delete_domain_aliasdomain_target'] = 'Het domein %s is onderdeel van een of meerdere domeinen en kan niet worden verwijderd! (Verwijder het alias domein eerst.)';
 
 $PALANG['pCreate_alias_address_text_error1'] = 'De Alias is niet geldig!';
-$PALANG['alias_does_not_exist'] = 'Deze alias bestaat niet!'; # XXX
-$PALANG['email_address_already_exists'] = 'Dit e-mail adres bestaat al, kies aub een andere.'; # XXX check text - should be 'This email address already exists, please choose a different one\!'
+$PALANG['alias_does_not_exist'] = 'Deze alias bestaat niet!';
+$PALANG['email_address_already_exists'] = 'Dit e-mail adres bestaat al, kies aub een andere.';
 $PALANG['pCreate_alias_address_text_error3'] = 'U bezit het maximum aantal aliassen.';
 $PALANG['pCreate_alias_goto_text'] = 'Waar de e-mails heen gestuurd worden.';
 $PALANG['pCreate_alias_goto_text_error'] = 'De NAAR is niet geldig.';
-$PALANG['pCreate_alias_result_error'] = 'Mislukt om de alias %s toe te voegen.!'; # XXX Text changed to: Creating the alias %s failed!
-$PALANG['pCreate_alias_result_success'] = 'De alias %s is toegevoegd.'; # XXX text change: 'The alias %s has been created!'
-$PALANG['alias_updated'] = 'De alias %s is bijgewerkt!'; # XXX
+$PALANG['pCreate_alias_result_error'] = 'Het is mislukt om de alias %s aan te maken!';
+$PALANG['pCreate_alias_result_success'] = 'De alias %s is aangemaakt.';
+$PALANG['alias_updated'] = 'De alias %s is bijgewerkt!';
 $PALANG['pCreate_alias_catchall_text'] = 'Om een catch-all te gebruiken, dient u een "*" (asteric) in te vullen als alias. Voor domein naar domein forwarding gebruik "*@domein.tld" als naar.';
-$PALANG['mailbox_alias_cant_be_deleted'] = 'De alias maakt onderdeel uit van mailbox en kan niet worden verwijderd!'; # XXX
-$PALANG['protected_alias_cant_be_deleted'] = 'The alias %s is protected and can only be deleted by a superadmin'; # XXX
+$PALANG['mailbox_alias_cant_be_deleted'] = 'De alias maakt onderdeel uit van mailbox en kan niet worden verwijderd!';
+$PALANG['protected_alias_cant_be_deleted'] = 'De alias %s is beschermd en kan alleen worden verwijderd door een superadministrator';
 
 $PALANG['pEdit_alias_welcome'] = 'Bewerk een alias voor uw domein.';
 $PALANG['pEdit_alias_help'] = 'Meerdere e-mailadressen toegestaan. Slechts Ã©Ã©n alias per regel.';
@@ -137,26 +138,30 @@ $PALANG['pEdit_alias_goto_text_error2']
 $PALANG['pEdit_alias_domain_result_error'] = 'Niet in staat de domein alias te bewerken!';
 $PALANG['pEdit_alias_forward_and_store'] = 'Lever af op de lokale mailbox.';
 $PALANG['pEdit_alias_forward_only'] = 'Alleen op opgegeven email adres afleveren.';
-$PALANG['pEdit_alias_result_error'] = 'Mislukt om de alias %s te bewerken!'; # XXX Text changed to: Modifying the alias %s failed!
+$PALANG['pEdit_alias_result_error'] = 'Bewerken van de alias %s is mislukt!';
 
 $PALANG['pCreate_mailbox_welcome'] = 'Maak een nieuw lokale mailbox voor uw domein.';
 $PALANG['pCreate_mailbox_username_text_error1'] = 'Het e-mail adres is niet geldig.';
 $PALANG['pCreate_mailbox_username_text_error3'] = 'U bezit het maximum aantal mailboxen.';
 $PALANG['pCreate_mailbox_password_text'] = 'Wachtwoord voor POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Volledige naam';
-$PALANG['pCreate_mailbox_mail'] = 'Mailbox toevoegen'; # XXX Text change to 'Send Welcome mail'
-$PALANG['pCreate_mailbox_result_error'] = 'Mislukt om de mailbox %s toe te voegen!'; # XXX Text changed to: Creating the mailbox %s failed!
-$PALANG['pCreate_mailbox_result_success'] = 'De mailbox %s is toegevoegd aan de mailbox tabel!'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
-$PALANG['pCreate_mailbox_result_succes_nosubfolders'] = 'De mailbox is aan de mailbox tabel toegevoegd, maar geen (of sommige) van de vooraf gedefinieerde sub-folders kon aangemaakt worden (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table, but none (or only some) of the predefined sub-folders could be created.
-$PALANG['mailbox_updated'] = "De mailbox %s is bijgewerkt.";  # XXX
-$PALANG['mailbox_update_failed'] = "Bijwerken van mailbox %s is mislukt!"; # XXX
+$PALANG['pCreate_mailbox_phone'] = 'Mobiele Telefoon';
+$PALANG['pCreate_mailbox_phone_desc'] = "Gebruik om een SMS te sturen als je het wachtwoord vergeten bent";
+$PALANG['pCreate_mailbox_email'] = 'Ander e-mail';
+$PALANG['pCreate_mailbox_email_desc'] = "Gebruik als je het wachtwoord vergeten bent";
+$PALANG['pCreate_mailbox_mail'] = 'Verstuur Welkoms mail';
+$PALANG['pCreate_mailbox_result_error'] = 'Het is mislukt om de mailbox %s aan te maken!';
+$PALANG['pCreate_mailbox_result_success'] = 'De mailbox %s is toegevoegd aan de mailbox tabel!';
+$PALANG['pCreate_mailbox_result_succes_nosubfolders'] = 'De mailbox %s is aan de mailbox tabel toegevoegd, maar geen (of sommige) van de vooraf gedefinieerde sub-folders kon niet worden aangemaakt.';
+$PALANG['mailbox_updated'] = "De mailbox %s is bijgewerkt.";
+$PALANG['mailbox_update_failed'] = "Bijwerken van mailbox %s is mislukt!";
 
 $PALANG['pEdit_mailbox_welcome'] = 'Bewerk een mailbox voor uw domein.';
 $PALANG['pEdit_mailbox_username'] = 'Gebruikersnaam';
 $PALANG['pEdit_mailbox_password_text_error'] = 'De wachtwoorden die u opgaf komen niet overeen.';
 $PALANG['pEdit_mailbox_quota'] = 'Quota';
 $PALANG['pEdit_mailbox_quota_text'] = 'MB';
-$PALANG['mb_max'] = 'MB (max: %s)'; # XXX
+$PALANG['mb_max'] = 'MB (max: %s)';
 $PALANG['pEdit_mailbox_quota_text_error'] = 'De quota die opgaf is te hoog.';
 $PALANG['pEdit_mailbox_domain_error'] = 'Dit domein is niet van nu: ';
 $PALANG['pEdit_mailbox_result_error'] = 'Mislukt om het wachtwoord te wijzigen.';
@@ -169,12 +174,19 @@ $PALANG['pPassword_password'] = 'Nieuw w
 $PALANG['pPassword_password2'] = 'Nieuw wachtwoord (nogmaals)';
 $PALANG['pPassword_password_text_error'] = 'De wachtwoorden die u opgaf komen niet overeen of zijn leeg.';
 $PALANG['change_password'] = 'Wijzig wachtwoord';
-$PALANG['pPassword_result_error'] = 'Het veranderen van het wachtwoord voor %s is mislukt!'; # XXX Text changed to: Changing the password for %s failed!
-$PALANG['pPassword_result_success'] = 'Uw wachtwoord voor %s is veranderd.'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_result_error'] = 'Het veranderen van het wachtwoord voor %s is mislukt!';
+$PALANG['pPassword_result_success'] = 'Uw wachtwoord voor %s is veranderd.';
+$PALANG['pPassword_recovery_title'] = 'Volg de aanwijzigingen om uw wachtwoord te veranderen.';
+$PALANG['pPassword_recovery_button'] = 'Stuur mij de code';
+$PALANG['pPassword_recovery_email_body'] = "Hallo,\n\nGebruik de volgende link om je email wachtwoord aan te passen :\n%s\n\nMet vriendelijk groet,\n\n" . $CONF['admin_name'];
+$PALANG['pPassword_recovery_sms_body'] = "Hallo,\nDe code om je  wachtwoord aan te passen is: %s\n" . $CONF['admin_name'];
+$PALANG['pPassword_recovery_processed'] = "Wij verwerkten je aanvraag. Als je een correte gebruikersnaam hebt ingevoerd, ontvang je per email/SMS een wachtwoord code.";
+$PALANG['pPassword_password_code'] = 'Stuur wachtwoord code per email/SMS';
+$PALANG['pPassword_code_text_error'] = 'Incorrecte code';
 
 $PALANG['pEdit_vacation_set'] = 'Verander / Activeer Automatisch beantwoorden';
 $PALANG['pEdit_vacation_remove'] = 'Deactiveer Automatisch beantwoorden';
-$PALANG['pVacation_result_error'] = 'Niet in staat automatisch beantwoorden te wijzigen! (%s)'; # XXX Text changed to: Updating the auto response settings for %s failed
+$PALANG['pVacation_result_error'] = 'Aanpassen van Automatisch beantwoorden voor %s mislikt!';
 $PALANG['pVacation_result_removed'] = 'Automatisch beantwoorden is voor %s gedeactiveerd!';
 $PALANG['pVacation_result_added'] = 'Automatisch beantwoorden is voor %s geactiveerd!';
 $PALANG['pVacation_reply_type'] = 'Keuze van beantwoording';
@@ -182,12 +194,12 @@ $PALANG['pVacation_reply_delay_time'] =
 $PALANG['pVacation_reply_delay_time_text'] = 'Tijd in seconds';
 $PALANG['pVacation_until_before_today'] = 'De datum van [Actief t/m] ligt voor vandaag'; 
 $PALANG['pVacation_until_before_from'] = 'De datum van [Actief t/m] ligt voor [Actief vanaf]'; 
-$PALANG['reply_once'] = 'eenmalige beantwoording'; # XXX
-$PALANG['reply_every_mail'] = 'Beantwoord elke keer'; # XXX
-$PALANG['reply_once_per_day'] = 'Beantwoord een keer per dag'; # XXX
-$PALANG['reply_once_per_week'] = 'Beantwoord een keer per week'; # XXX
+$PALANG['reply_once'] = 'eenmalige beantwoording';
+$PALANG['reply_every_mail'] = 'Beantwoord elke keer';
+$PALANG['reply_once_per_day'] = 'Beantwoord een keer per dag';
+$PALANG['reply_once_per_week'] = 'Beantwoord een keer per week';
 
-$PALANG['pViewlog_welcome'] = 'Laat de laatste 10 actie\'s zien van ';
+$PALANG['pViewlog_welcome'] = 'Laat de laatste %s actie\'s zien van ';
 $PALANG['pViewlog_timestamp'] = 'Tijd';
 $PALANG['pViewlog_action'] = 'Actie';
 $PALANG['pViewlog_data'] = 'Aanpassing';
@@ -200,20 +212,20 @@ $PALANG['pViewlog_action_edit_mailbox']
 $PALANG['pViewlog_action_edit_mailbox_state'] = 'status actieve mailbox bewerkt';
 $PALANG['pViewlog_action_create_alias'] = 'alias toegevoegd';
 $PALANG['pViewlog_action_create_alias_domain'] = 'maak domein alias';
-$PALANG['pViewlog_action_edit_alias_domain'] = 'Bewerk alias domein'; # XXX
+$PALANG['pViewlog_action_edit_alias_domain'] = 'Bewerk alias domein';
 $PALANG['pViewlog_action_delete_alias'] = 'alias verwijderd';
 $PALANG['pViewlog_action_delete_alias_domain'] = 'verwijder alias domein';
 $PALANG['pViewlog_action_edit_alias'] = 'alias bewerkt';
 $PALANG['pViewlog_action_edit_alias_state'] = 'status actieve alias bewerkt';
 $PALANG['pViewlog_action_edit_alias_domain_state'] = 'status actieve domein alias bewerkt';
 $PALANG['pViewlog_action_edit_password'] = 'wachtwoord aangepast';
-$PALANG['pViewlog_action_create_admin'] = 'create admin'; # XXX
-$PALANG['pViewlog_action_edit_admin'] = 'edit admin'; # XXX
-$PALANG['pViewlog_action_delete_admin'] = 'delete admin'; # XXX
-$PALANG['pViewlog_action_edit_vacation'] = 'edit vacation'; # XXX
-$PALANG['pViewlog_action_create_fetchmail'] = 'create fetchmail job'; # XXX
-$PALANG['pViewlog_action_edit_fetchmail'] = 'edit fetchmail job'; # XXX
-$PALANG['pViewlog_action_delete_fetchmail'] = 'delete fetchmail job'; # XXX
+$PALANG['pViewlog_action_create_admin'] = 'aanmaken administrator';
+$PALANG['pViewlog_action_edit_admin'] = 'aanpassen administrator';
+$PALANG['pViewlog_action_delete_admin'] = 'verwijderen administrator';
+$PALANG['pViewlog_action_edit_vacation'] = 'aanpassen vakatie';
+$PALANG['pViewlog_action_create_fetchmail'] = 'aanmaken fetchmail job';
+$PALANG['pViewlog_action_edit_fetchmail'] = 'aanpassen fetchmail job';
+$PALANG['pViewlog_action_delete_fetchmail'] = 'verwijderen fetchmail job';
 
 $PALANG['pViewlog_result_error'] = 'Mislukt om de logs te vinden!';
 
@@ -225,8 +237,8 @@ $PALANG['subject'] = 'Onderwerp';
 $PALANG['pSendmail_subject_text'] = 'Welkom';
 $PALANG['pSendmail_body'] = 'Inhoud';
 $PALANG['pSendmail_button'] = 'Verstuur bericht';
-$PALANG['pSendmail_result_error'] = 'Mislukt om mail te versturen! (%s)'; # XXX text change - new: Unable to send email to %s!
-$PALANG['pSendmail_result_success'] = 'E-mail verstuurd! (%s)'; # XXX text change - new: Email sent to %s.
+$PALANG['pSendmail_result_error'] = 'Mislukt om mail te versturen aan %s!';
+$PALANG['pSendmail_result_success'] = 'E-mail verstuurd aan %s.';
 
 $PALANG['pAdminMenu_list_admin'] = 'Beheerders overzicht';
 $PALANG['pAdminMenu_list_domain'] = 'Domein overzicht';
@@ -239,78 +251,79 @@ $PALANG['pAdminMenu_create_domain'] = 'V
 $PALANG['pAdminList_admin_count'] = 'Domeinen';
 
 $PALANG['description'] = 'Omschrijving';
-$PALANG['aliases'] = 'Aliassen'; # XXX check text - should be 'Aliases'
-$PALANG['pAdminList_domain_quota'] = 'Domein quota (MB)'; # XXX
+$PALANG['aliases'] = 'Aliassen';
+$PALANG['pAdminList_domain_quota'] = 'Domein quota (MB)';
 $PALANG['pAdminList_domain_backupmx'] = 'Back-up MX';
 $PALANG['last_modified'] = 'Laatst bewerkt';
 
 $PALANG['pAdminCreate_domain_welcome'] = 'Voeg een nieuw domein toe';
 $PALANG['pAdminCreate_domain_domain_text_error'] = 'Het domein bestaat al.';
-$PALANG['domain_does_not_exist'] = 'Dit domein bestaat niet!'; # XXX
+$PALANG['domain_does_not_exist'] = 'Dit domein bestaat niet!';
 $PALANG['pAdminCreate_domain_domain_text_error2'] = 'Het domein is niet geldig!';
 $PALANG['pAdminCreate_domain_defaultaliases'] = 'Gebruik standaard aliassen';
 $PALANG['pAdminCreate_domain_button'] = 'Voeg Domein toe';
-$PALANG['pAdminCreate_domain_result_error'] = 'Mislukt om het domein toe te voegen. (%s)'; # XXX Text changed to: Adding the domain %s failed!
-$PALANG['pAdminCreate_domain_result_success'] = 'Domein is toegevoegd! (%s)'; # XXX Text changed to: The domain %s has been added.
-$PALANG['domain_updated'] = 'Het domein %s is bijgewerkt.'; # XXX
+$PALANG['pAdminCreate_domain_result_error'] = 'Het aangemaakt van domein %s is mislukt!';
+$PALANG['pAdminCreate_domain_result_success'] = 'Domein %s is aangemaakt';
+$PALANG['domain_updated'] = 'Het domein %s is bijgewerkt.';
 $PALANG['pAdminDelete_admin_error'] = 'Niet in staat beheerder te verwijderen!';
-$PALANG['domain_postdel_failed'] = 'Niet in staat domein te verwijderen!'; # XXX Text changed to: The domain postdeletion script failed, check the error log for details!
-$PALANG['domain_postcreate_failed'] = 'Het domein vooraanmaak script is mislukt, controleer de log file voor meer informatie!'; # XXX
-$PALANG['mailbox_postdel_failed'] = 'Het mailbox postdeletion script is mislukt, controleer de log file voor meer informatie!'; # XXX
-$PALANG['mailbox_postedit_failed'] = 'Het mailbox postedit script is mislukt, controleer de log file voor meer informatie'; # XXX
-$PALANG['mailbox_postcreate_failed'] = 'Het mailbox postcreate script is mislukt, controleer de log file voor meer informatie!'; # XXX
+$PALANG['domain_postdel_failed'] = 'Het script "domein postdeletion" is mislukt, controleer de log file voor meer informatie!';
+$PALANG['domain_postcreate_failed'] = 'Het script "domein postcreation" is mislukt, controleer de log file voor meer informatie!';
+$PALANG['mailbox_postdel_failed'] = 'Het script "mailbox postdeletion" is mislukt, controleer de log file voor meer informatie!';
+$PALANG['mailbox_postedit_failed'] = 'Het script "mailbox postedit" is mislukt, controleer de log file voor meer informatie';
+$PALANG['mailbox_postcreate_failed'] = 'Het script "mailbox postcreation" is mislukt, controleer de log file voor meer informatie!';
 $PALANG['pAdminDelete_alias_domain_error'] = 'Niet in staat domein alias te verwijderen!';
-$PALANG['domain_conflict_vacation_domain'] = 'You can\'t use the vacation domain as mail domain!'; # XXX
+$PALANG['domain_conflict_vacation_domain'] = 'Je kunt het vakantie domein niet gebruiken als mail domein!';
 
 $PALANG['pAdminEdit_domain_welcome'] = 'Bewerk een domein';
 $PALANG['pAdminEdit_domain_aliases_text'] = '-1 = uit | 0 = onbeperkt';
 $PALANG['pAdminEdit_domain_maxquota'] = 'Max Quota';
 $PALANG['pAdminEdit_domain_maxquota_text'] = 'MB | -1 = uit | 0 = onbeperkt';
-$PALANG['pAdminEdit_domain_quota'] = 'Domein Quota'; # XXX
+$PALANG['pAdminEdit_domain_quota'] = 'Domein Quota';
 $PALANG['transport'] = 'Transport';
 $PALANG['pAdminEdit_domain_transport_text'] = 'Definieer transport';
 $PALANG['pAdminEdit_domain_backupmx'] = 'Mail server is back-up MX';
-$PALANG['pAdminEdit_domain_result_error'] = 'Het bewerken van domein %s is mislukt!'; # XXX Text changed to: Modifying the domain %s failed!
+$PALANG['pAdminEdit_domain_result_error'] = 'Het bewerken van domein %s is mislukt!';
 
 $PALANG['pAdminCreate_admin_welcome'] = 'Voeg een nieuw domein beheerder toe';
 $PALANG['email_address'] = 'E-mail adres';
 $PALANG['pAdminCreate_admin_username_text_error1'] = 'Beheerder is geen geldig e-mail adres!';
-$PALANG['admin_already_exists'] = 'De beheerder bestaat al of is niet geldig'; # XXX Text changed to: The admin already exists!
-$PALANG['admin_does_not_exist'] = 'De Beheerder bestaat niet!'; # XXX
+$PALANG['admin_already_exists'] = 'De beheerder bestaat al!';
+$PALANG['admin_does_not_exist'] = 'De Beheerder bestaat niet!';
 $PALANG['pAdminCreate_admin_button'] = 'Voeg beheerder toe';
-$PALANG['pAdminCreate_admin_result_error'] = 'Mislukt om beheerder toe te voegen! (%s)'; # XXX Text changed to: Adding the admin %s failed!
-$PALANG['pAdminCreate_admin_result_success'] = 'Beheerder is toegevoegd. (%s)'; # XXX Text changed to: The admin %s has been added.
+$PALANG['pAdminCreate_admin_result_error'] = 'Het aanmaken van de beheerder %s is mislukt!';
+$PALANG['pAdminCreate_admin_result_success'] = 'De beheerder %s is toegevoegd.';
 
 $PALANG['pAdminEdit_admin_welcome'] = 'Bewerk een domein beheerder';
 $PALANG['admin'] = 'Beheerder';
 $PALANG['password_again'] = 'Wachtwoord (nogmaals)';
 $PALANG['super_admin'] = 'Hoofd Beheerder';
-$PALANG['super_admin_desc'] = 'De hoofd Beheerder heeft toegang tot alle doameinen en kan alle domeinen en beheeraccounts aanpassen.'; # XXX
-$PALANG['pAdminEdit_admin_result_error'] = 'Het bewerken van beheerder %s is mislukt!'; # XXX Text changed to: Modifying the admin %s failed!
-$PALANG['pAdminEdit_admin_result_success'] = 'De beheerder %s is aangepast'; # XXX Text changed to: The admin %s has been modified.
+$PALANG['super_admin_desc'] = 'De hoofd Beheerder heeft toegang tot alle doameinen en kan alle domeinen en beheeraccounts aanpassen.';
+$PALANG['pAdminEdit_admin_result_error'] = 'Het bewerken van beheerder %s is mislukt!';
+$PALANG['pAdminEdit_admin_result_success'] = 'De beheerder %s is aangepast';
 
 $PALANG['pUsersLogin_welcome'] = 'Mailbox gebruikers login om uw wachtwoord en aliassen te bewerken.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Uw login is niet correct. U dient in te loggen met uw e-mail adres.';
 $PALANG['pUsersLogin_password_incorrect'] = 'Uw wachtwoord is niet correct.';
+$PALANG['pUsersLogin_password_recover'] = 'Ik ben mijn wachtwoord vergeten';
 
 $PALANG['pUsersMenu_vacation'] = 'Automatisch beantwoorden';
 $PALANG['pUsersMenu_edit_alias'] = 'Wijzig uw forward';
 
-$PALANG['pUsersMain_vacation'] = 'Stel een "out of office" bericht of automatisch beantwoorden voor uw e-mail in.';
+$PALANG['pUsersMain_vacation'] = 'Stel een "Afwezigheids bericht" bericht of automatisch beantwoorden voor uw e-mail in.';
 $PALANG['pUsersMain_vacationSet'] = $PALANG['pUsersMenu_vacation'] . ' is actief, click \'' . $PALANG['pUsersMenu_vacation'] . '\' to ' . $PALANG['edit'] . '/verwijderen';
 $PALANG['pUsersMain_edit_alias'] = 'Wijzig uw e-mail forwarding.';
 $PALANG['pUsersMain_password'] = 'Wijzig uw huidige wachtwoord.';
 
 $PALANG['pUsersVacation_welcome'] = 'Automatisch beantwoorden.';
-$PALANG['pUsersVacation_welcome_text'] = 'Automatisch beantwoorden voor %s is active. (%s)'; # XXX Text changed to: 'Auto response for %s is active!'
-$PALANG['pUsersVacation_subject_text'] = 'Out of Office';
+$PALANG['pUsersVacation_welcome_text'] = 'Automatisch beantwoorden voor %s is active.';
+$PALANG['pUsersVacation_subject_text'] = 'Afwezigheids bericht';
 $PALANG['message'] = 'Bericht';
 $PALANG['pUsersVacation_body_text'] = <<<EOM
-Ik zal afwezig zijn van <date> tot <date>.
+Ik zal afwezig zijn van %vandatum tot %totdatum.
 Voor belangrijke punten kunt u contact opnemen met <contact person>.
 EOM;
-$PALANG['pUsersVacation_activefrom'] = 'Actief vanaf'; # -> NOT OBSOLETE <-
-$PALANG['pUsersVacation_activeuntil'] = 'Actief t/m'; #  -> NOT OBSOLETE <-
+$PALANG['pUsersVacation_activefrom'] = 'Actief vanaf';
+$PALANG['pUsersVacation_activeuntil'] = 'Actief t/m';
 
 
 $PALANG['pEdit_dbLog_editactive'] = 'status verandert';
@@ -323,19 +336,21 @@ $PALANG['pBroadcast_name'] = 'Uw naam';
 $PALANG['pBroadcast_success'] = 'Uw algemene bericht is verzonden.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Algemeen bericht';
 $PALANG['pBroadcast_error_empty'] = 'De velden Naam, Onderwerp en Bericht mogen niet leeg zijn !';
+$PALANG['broadcast_mailboxes_only'] = 'Verstuur alleen aan mailboxen';
+$PALANG['broadcast_to_domains'] = 'Verstuur aan de domeinen:';
 $PALANG['pStatus_undeliverable'] = 'Misschien niet af te leveren ';
 $PALANG['pStatus_custom'] = 'Bezorgen op ';
 $PALANG['pStatus_popimap'] = 'POP/IMAP ';
 $PALANG['password_too_short'] = "Wachtwoord is te kort - moet minimaal %s karakters bevatten";
-$PALANG['password_no_characters'] = "Je wachtwoord moet minimaal %s karakter(s) bevatten."; # XXX
-$PALANG['password_no_digits'] = "Je wachtwoord moet minimaal %s getal(len) bevatten."; # XXX
+$PALANG['password_no_characters'] = "Je wachtwoord moet minimaal %s karakter(s) bevatten.";
+$PALANG['password_no_digits'] = "Je wachtwoord moet minimaal %s getal(len) bevatten.";
 $PALANG['pInvalidDomainRegex'] = "Ongeldig domein naam %s";
 $PALANG['pInvalidDomainDNS'] = "Ongeldig domein %s";
 $PALANG['pInvalidMailRegex'] = "Ongeldig email adres %s komt niet door de limietcheck"; # XXX text change to: "Invalid email address %s, fails regexp check"
 $PALANG['pFetchmail_welcome'] = 'Haal mail op voor:';
 $PALANG['pFetchmail_new_entry'] = 'Nieuw item';
-$PALANG['fetchmail_already_exists']         = 'This fetchmail job already exists!'; # XXX
-$PALANG['fetchmail_does_not_exist']         = 'This fetchmail job does not exist!'; # XXX
+$PALANG['fetchmail_already_exists']         = 'Deze "fetchmail job" bestaat al!';
+$PALANG['fetchmail_does_not_exist']         = 'Deze "fetchmail job" bestaat niet!';
 $PALANG['pFetchmail_database_save_error'] = 'Niet in staat dit item toe te voegen aan database!';
 $PALANG['pFetchmail_database_save_success'] = 'Item opgeslagen in database.';
 $PALANG['pFetchmail_error_invalid_id'] = 'Geen item met ID %s gevonden!';
diff -pruN 3.0.2-2/languages/nn.lang 3.2-2/languages/nn.lang
--- 3.0.2-2/languages/nn.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/nn.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: nn.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Norwegian - BokmÃ¥l
 // by Jon Arve WÃ¥lberg
@@ -142,6 +142,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Du er over grensen for antall e-postkontoer!';
 $PALANG['pCreate_mailbox_password_text'] = 'Passord for POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Fornavn og etternavn';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Opprett epostkonto'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Klarte ikke Ã¥ legge til e-postkontoen! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'E-postkontoen er opprettet! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -169,6 +173,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Endre Passord';
 $PALANG['pPassword_result_error'] = 'Klarte ikke Ã¥ endre passord! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Passordet ditt er nÃ¥ endret! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -184,7 +195,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Vis de 10 siste handlingene ';
+$PALANG['pViewlog_welcome'] = 'Vis de %s siste handlingene ';
 $PALANG['pViewlog_timestamp'] = 'Klokkeslett';
 $PALANG['pViewlog_action'] = 'Handling';
 $PALANG['pViewlog_data'] = 'Data';
@@ -291,6 +302,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Brukere, logg inn for Ã¥ endre passord og videresending.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Feil brukernavn! Bruk e-postadressen din for Ã¥ logge inn!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Feil passord!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Automatisk Svar';
 $PALANG['pUsersMenu_edit_alias'] = 'Endre videresending';
@@ -321,6 +333,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.'; # XXX
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/pl.lang 3.2-2/languages/pl.lang
--- 3.0.2-2/languages/pl.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/pl.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: pl.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Polish
 // by Jarek
@@ -145,6 +145,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'TwÃ³j limit kont pocztowych zostaÅ‚ osiÄ…gniety!';
 $PALANG['pCreate_mailbox_password_text'] = 'HasÅ‚o do POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'PeÅ‚na nazwa';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'UtwÃ³rz konto'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Nie moÅ¼na dodaÄ‡ konta do tabeli kont! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'Konto zostaÅ‚o dodane do tabeli kont! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -172,6 +176,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'ZmieÅ„ hasÅ‚o';
 $PALANG['pPassword_result_error'] = 'Nie moÅ¼na zmieniÄ‡ Twojego hasÅ‚a! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Twoje hasÅ‚o zostaÅ‚o zmienione! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 
 $PALANG['pEdit_vacation_set'] = 'ZmieÅ„ / Ustaw wiadomoÅ›Ä‡ automatycznej odpowiedzi';
 $PALANG['pEdit_vacation_remove'] = 'UsuÅ„ wiadomoÅ›Ä‡ automatycznej odpowiedzi';
@@ -188,7 +199,7 @@ $PALANG['reply_every_mail'] = 'Odpowiedz
 $PALANG['reply_once_per_day'] = 'Odpowiedz raz na dzieÅ„';
 $PALANG['reply_once_per_week'] = 'Odpowiedz raz na tydzieÅ„';
 
-$PALANG['pViewlog_welcome'] = 'PokaÅ¼ 10 ostatnich dziaÅ‚aÅ„ dla ';
+$PALANG['pViewlog_welcome'] = 'PokaÅ¼ %s ostatnich dziaÅ‚aÅ„ dla ';
 $PALANG['pViewlog_timestamp'] = 'Data';
 $PALANG['pViewlog_action'] = 'DziaÅ‚anie';
 $PALANG['pViewlog_data'] = 'Dane';
@@ -294,6 +305,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Zaloguj siÄ™ Å¼eby zmieniÄ‡ hasÅ‚o albo dodaÄ‡ aliasy.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Podana nazwa uÅ¼ytkownika jest nieprawidÅ‚owa! ';
 $PALANG['pUsersLogin_password_incorrect'] = 'Podane hasÅ‚o jest nieprawidÅ‚owe!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Auto odpowiedÅº';
 $PALANG['pUsersMenu_edit_alias'] = 'ZmieÅ„ przekierowania';
@@ -328,6 +340,8 @@ $PALANG['pBroadcast_name'] = 'Nazwa';
 $PALANG['pBroadcast_success'] = 'WiadomoÅ›Ä‡ do wszystkich zostaÅ‚a wysÅ‚ana.';
 $PALANG['pAdminMenu_broadcast_message'] = 'WiadomoÅ›Ä‡ do wszystkich';
 $PALANG['pBroadcast_error_empty'] = 'Pola Nazwa, Temat i WiadomoÅ›Ä‡ nie powinny byÄ‡ puste !';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'moÅ¼e byÄ‡ NIEDOSTARCZALNA ';
 $PALANG['pStatus_custom'] = 'DostarczyÄ‡ do ';
 $PALANG['pStatus_popimap'] = 'POP/IMAP ';
diff -pruN 3.0.2-2/languages/pt-br.lang 3.2-2/languages/pt-br.lang
--- 3.0.2-2/languages/pt-br.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/pt-br.lang	2018-05-02 20:37:27.000000000 +0000
@@ -147,6 +147,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'VocÃª alcanÃ§ou o limite de contas de email!';
 $PALANG['pCreate_mailbox_password_text'] = 'Senha para POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Nome completo';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Enviar mensagem de boas-vindas'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'NÃ£o foi possÃ­vel criar a conta de email! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'Conta de email criada! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -174,6 +178,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Alterar Senha';
 $PALANG['pPassword_result_error'] = 'NÃ£o foi possÃ­vel alterar sua senha! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Senha alterada! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 
 $PALANG['pEdit_vacation_set'] = 'Editar / Definir Mensagem';
 $PALANG['pEdit_vacation_remove'] = 'Remover Mensagem';
@@ -191,7 +202,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Ãšltimas 10 aÃ§Ãµes para ';
+$PALANG['pViewlog_welcome'] = 'Ãšltimas %s aÃ§Ãµes para ';
 $PALANG['pViewlog_timestamp'] = 'Data/Hora';
 $PALANG['pViewlog_action'] = 'AÃ§Ã£o';
 $PALANG['pViewlog_data'] = 'DescriÃ§Ã£o';
@@ -299,6 +310,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'UsuÃ¡rios devem se autenticar aqui para troca de senha e configuraÃ§Ã£o de redirecionamento de mensagens.';
 $PALANG['pUsersLogin_username_incorrect'] = 'UsuÃ¡rio invÃ¡lido. Certifique-se de ter digitado o email corretamente!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Senha invÃ¡lida!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Resposta AutomÃ¡tica';
 $PALANG['pUsersMenu_edit_alias'] = 'Configurar Redirecionamento';
@@ -332,6 +344,8 @@ $PALANG['pBroadcast_name'] = 'Seu nome';
 $PALANG['pBroadcast_success'] = 'Mensagem em massa enviada.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Mensagem em massa';
 $PALANG['pBroadcast_error_empty'] = 'Os campos Nome, Assunto e Mensagem devem ser preenchidos!';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 
 $PALANG['pStatus_undeliverable'] = 'talvez NÃƒO-ENTREGÃVEL ';
 $PALANG['pStatus_custom'] = 'Envia para ';
diff -pruN 3.0.2-2/languages/ro.lang 3.2-2/languages/ro.lang
--- 3.0.2-2/languages/ro.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/ro.lang	2018-05-02 20:37:27.000000000 +0000
@@ -145,6 +145,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Ati atins limita pentru creare de noi casute de mail!';
 $PALANG['pCreate_mailbox_password_text'] = 'Parola de la POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Numele complet';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Trimite mesaj de intampinare';
 $PALANG['pCreate_mailbox_result_error'] = 'Crearea casutei de mail %s a esuat!';
 $PALANG['pCreate_mailbox_result_success'] = 'Casuta de mail %s a fost adaugata cu succes.';
@@ -172,6 +176,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Schimbare parola';
 $PALANG['pPassword_result_error'] = 'Schimbarea parolei pentru %s a esuat!';
 $PALANG['pPassword_result_success'] = 'Parola pentru %s a fost schimbata.';
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 
 $PALANG['pEdit_vacation_set'] = 'Schimbare / Setare mesaj vacanta';
 $PALANG['pEdit_vacation_remove'] = 'Stergere mesaj vacanta';
@@ -189,7 +200,7 @@ $PALANG['reply_every_mail'] = 'Raspunde
 $PALANG['reply_once_per_day'] = 'Raspunde odata pe zi';
 $PALANG['reply_once_per_week'] = 'Raspunde odata pe saptamana';
 
-$PALANG['pViewlog_welcome'] = 'Vizualizati ultimele 100 operatii pentru ';
+$PALANG['pViewlog_welcome'] = 'Vizualizati ultimele %s operatii pentru ';
 $PALANG['pViewlog_timestamp'] = 'Data si ora';
 $PALANG['pViewlog_action'] = 'Operatie';
 $PALANG['pViewlog_data'] = 'Detalii';
@@ -297,6 +308,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Schimbare parola si alias-uri utilizatori';
 $PALANG['pUsersLogin_username_incorrect'] = 'Nume cont incorect. Verificati introducerea corecta a adresei de email!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Parola incorecta!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Raspuns automat';
 $PALANG['pUsersMenu_edit_alias'] = 'Redirectionare';
@@ -330,6 +342,8 @@ $PALANG['pBroadcast_name'] = 'Numele';
 $PALANG['pBroadcast_success'] = 'A fost trimis mesajul la toti utilizatorii.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Mesaj general';
 $PALANG['pBroadcast_error_empty'] = 'Campurile Nume, Subiect si Mesaj nu pot fi goale!';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 
 $PALANG['pStatus_undeliverable'] = 'probabil UNDELIVERABLE ';
 $PALANG['pStatus_custom'] = 'Livreaza la ';
diff -pruN 3.0.2-2/languages/ru.lang 3.2-2/languages/ru.lang
--- 3.0.2-2/languages/ru.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/ru.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: ru.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Russian
 // by Paul
@@ -147,6 +147,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Ð’Ñ‹ Ð´Ð¾ÑÑ‚Ð¸Ð³Ð»Ð¸ Ð»Ð¸Ð¼Ð¸Ñ‚Ð° Ð¿Ð¾ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸ÑŽ Ð¿Ð¾Ñ‡Ñ‚Ð¾Ð²Ñ‹Ñ… ÑÑ‰Ð¸ÐºÐ¾Ð²!';
 $PALANG['pCreate_mailbox_password_text'] = 'ÐŸÐ°Ñ€Ð¾Ð»ÑŒ Ð´Ð»Ñ POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'ÐŸÐ¾Ð»Ð½Ð¾Ðµ Ð¸Ð¼Ñ';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'ÐžÑ‚Ð¿Ñ€Ð°Ð²Ð¸Ñ‚ÑŒ Ð¿Ñ€Ð¸Ð²ÐµÑ‚ÑÑ‚Ð²ÐµÐ½Ð½Ð¾Ðµ Ð¿Ð¸ÑÑŒÐ¼Ð¾';
 $PALANG['pCreate_mailbox_result_error'] = 'ÐÐµÐ²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ ÑÑ‰Ð¸Ðº Ð² ÑÐ¿Ð¸ÑÐ¾Ðº ÑÑƒÑ‰ÐµÑÑ‚Ð²ÑƒÑŽÑ‰Ð¸Ñ… ÑÑ‰Ð¸ÐºÐ¾Ð²! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'ÐŸÐ¾Ñ‡Ñ‚Ð¾Ð²Ñ‹Ð¹ ÑÑ‰Ð¸Ðº Ð±Ñ‹Ð» ÑƒÑÐ¿ÐµÑˆÐ½Ð¾ ÑÐ¾Ð·Ð´Ð°Ð½! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -174,6 +178,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Ð˜Ð·Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ Ð¿Ð°Ñ€Ð¾Ð»ÑŒ';
 $PALANG['pPassword_result_error'] = 'ÐÐµÐ²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ Ð¸Ð·Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ Ð²Ð°Ñˆ Ð¿Ð°Ñ€Ð¾Ð»ÑŒ! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Ð’Ð°Ñˆ Ð¿Ð°Ñ€Ð¾Ð»ÑŒ Ð±Ñ‹Ð» Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 
 $PALANG['pEdit_vacation_set'] = 'ÐŸÐ¾Ð¼ÐµÐ½ÑÑ‚ÑŒ / Ð·Ð°Ð´Ð°Ñ‚ÑŒ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ðµ Ð¾Ð± Ð¾Ñ‚ÑÑƒÑ‚ÑÑ‚Ð²Ð¸Ð¸';
 $PALANG['pEdit_vacation_remove'] = 'Ð£Ð±Ñ€Ð°Ñ‚ÑŒ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ðµ Ð¾Ð± Ð¾Ñ‚ÑÑƒÑ‚ÑÑ‚Ð²Ð¸Ð¸';
@@ -191,7 +202,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'ÐŸÑ€Ð¾ÑÐ¼Ð¾Ñ‚Ñ€ÐµÑ‚ÑŒ 10 Ð¿Ð¾ÑÐ»ÐµÐ´Ð½Ð¸Ñ… Ð´ÐµÐ¹ÑÑ‚Ð²Ð¸Ð¹ Ð´Ð»Ñ  ';
+$PALANG['pViewlog_welcome'] = 'ÐŸÑ€Ð¾ÑÐ¼Ð¾Ñ‚Ñ€ÐµÑ‚ÑŒ %s Ð¿Ð¾ÑÐ»ÐµÐ´Ð½Ð¸Ñ… Ð´ÐµÐ¹ÑÑ‚Ð²Ð¸Ð¹ Ð´Ð»Ñ  ';
 $PALANG['pViewlog_timestamp'] = 'Ð’Ñ€ÐµÐ¼Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ/Ð¼Ð¾Ð´Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸';
 $PALANG['pViewlog_action'] = 'Ð”ÐµÐ¹ÑÑ‚Ð²Ð¸Ðµ';
 $PALANG['pViewlog_data'] = 'Ð”Ð°Ð½Ð½Ñ‹Ðµ';
@@ -299,6 +310,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Ð’Ñ…Ð¾Ð´ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¸ Ð°Ð»Ð¸Ð°ÑÐ¾Ð².';
 $PALANG['pUsersLogin_username_incorrect'] = 'Ð’Ð²ÐµÐ´ÐµÐ½Ð¾ Ð½ÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð¾Ðµ Ð¸Ð¼Ñ. ÐŸÑ€Ð¾Ð²ÐµÑ€ÑŒÑ‚Ðµ, Ñ‡Ñ‚Ð¾ Ð²Ñ‹ Ð²Ð²ÐµÐ»Ð¸ ÑÐ²Ð¾Ð¹ Ð°Ð´Ñ€ÐµÑ ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ð¹ Ð¿Ð¾Ñ‡Ñ‚Ñ‹!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Ð’Ð²ÐµÐ´ÐµÐ½ Ð½ÐµÐ²ÐµÑ€Ð½Ñ‹Ð¹ Ð¿Ð°Ñ€Ð¾Ð»ÑŒ!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'ÐÐ²Ñ‚Ð¾Ð¾Ñ‚Ð²ÐµÑ‚Ñ‡Ð¸Ðº';
 $PALANG['pUsersMenu_edit_alias'] = 'Ð˜Ð·Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ Ð¿ÐµÑ€ÐµÑÑ‹Ð»ÐºÑƒ Ð¿Ð¾Ñ‡Ñ‚Ñ‹';
@@ -332,6 +344,8 @@ $PALANG['pBroadcast_name'] = 'Ð’Ð°ÑˆÐµ Ð
 $PALANG['pBroadcast_success'] = 'Ð’Ð°ÑˆÐµ ÑˆÐ¸Ñ€Ð¾ÐºÐ¾Ð²ÐµÑ‰Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ðµ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ðµ Ð±Ñ‹Ð»Ð¾ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¾.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Ð¨Ð¸Ñ€Ð¾ÐºÐ¾Ð²ÐµÑ‰Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ðµ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ðµ';
 $PALANG['pBroadcast_error_empty'] = 'ÐŸÐ¾Ð»Ñ Ð˜Ð¼Ñ, Ð¢ÐµÐ¼Ð° Ð¸ Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ðµ Ð½Ðµ Ð´Ð¾Ð»Ð¶Ð½Ñ‹ Ð±Ñ‹Ñ‚ÑŒ Ð¿ÑƒÑÑ‚Ñ‹Ð¼Ð¸!';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 
 $PALANG['pStatus_undeliverable'] = 'Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ ÐÐ• Ð”ÐžÐ¡Ð¢ÐÐ’Ð›Ð•ÐÐž ';
 $PALANG['pStatus_custom'] = 'Ð”Ð¾ÑÑ‚Ð°Ð²Ð»ÑÐµÑ‚ÑÑ Ð´Ð»Ñ ';
diff -pruN 3.0.2-2/languages/sk.lang 3.2-2/languages/sk.lang
--- 3.0.2-2/languages/sk.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/sk.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: sk.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Slovak
 // by bajk (eszabo @sf)
@@ -12,45 +12,45 @@ $PALANG['edit'] = 'upraviÅ¥';
 $PALANG['del'] = 'zmazaÅ¥';
 $PALANG['exit'] = 'NaspÃ¤Å¥';
 $PALANG['cancel'] = 'ZruÅ¡iÅ¥';
-$PALANG['save'] = 'UloÅ¾iÅ¥'; # XXX Text change: "Save" -> "Save changes"
+$PALANG['save'] = 'UloÅ¾iÅ¥ zmeny';
 $PALANG['confirm'] = 'Ste si istÃ­?\n';
-$PALANG['confirm_delete_admin'] = 'Do you really want to delete the admin %s?'; # XXX
-$PALANG['confirm_delete_alias'] = 'Do you really want to delete the alias %s?'; # XXX
-$PALANG['confirm_delete_aliasdomain'] = 'Do you really want to delete the alias domain %s?'; # XXX
-$PALANG['confirm_delete_domain'] = 'Naozaj chcete zmazaÅ¥ vÅ¡etky zÃ¡znamy v tejto domÃ©ne? Toto nie je moÅ¾nÃ© vrÃ¡tiÅ¥!\n (%s)'; # XXX text changed to: 'Do you really want to delete all records for the domain %s? This can not be undone'
-$PALANG['confirm_delete_fetchmail'] = 'Do you really want to delete the fetchmail job %s?'; # XXX
-$PALANG['confirm_delete_mailbox'] = 'Do you really want to delete the mailbox %s?'; # XXX
-$PALANG['confirm_delete_vacation'] = 'Do you really want to delete the vacation message for %s?'; # XXX
-$PALANG['no_delete_permissions'] = 'You are not allowed to delete %s!'; # XXX
+$PALANG['confirm_delete_admin'] = 'Naozaj chcete zmazaÅ¥ administrÃ¡tora %s?';
+$PALANG['confirm_delete_alias'] = 'Naozaj chcete zmazaÅ¥ alias %s?';
+$PALANG['confirm_delete_aliasdomain'] = 'Naozaj chcete zmazaÅ¥ alias domÃ©ny %s?';
+$PALANG['confirm_delete_domain'] = 'Naozaj chcete zmazaÅ¥ vÅ¡etky zÃ¡znamy v domÃ©ne %s? Toto nie je moÅ¾nÃ© vrÃ¡tiÅ¥!';
+$PALANG['confirm_delete_fetchmail'] = 'Naozaj chcete zmazaÅ¥ sÅ¥ahovanie emailu %s?';
+$PALANG['confirm_delete_mailbox'] = 'Naozaj chcete zmazaÅ¥ schrÃ¡nku %s?';
+$PALANG['confirm_delete_vacation'] = 'Naozaj chcete zmazaÅ¥ automatickÃº odpoveÄ pre %s?';
+$PALANG['no_delete_permissions'] = 'NemÃ¡te oprÃ¡vnenie zmazaÅ¥ %s!';
 $PALANG['check_update'] = 'SkontrolovaÅ¥ aktualizÃ¡cie';
 $PALANG['invalid_parameter'] = 'NeplatnÃ½ parameter!';
-$PALANG['show'] = 'Show:'; # XXX
-$PALANG['all'] = 'All'; # XXX
-$PALANG['created'] = 'Created'; # XXX
-$PALANG['unknown'] = 'unknown'; # XXX
-$PALANG['download_csv'] = 'Download this list as CSV file'; # XXX
-$PALANG['missing_field'] = 'Field %s is missing'; # XXX
-$PALANG['must_be_numeric'] = '%s must be numeric'; # XXX
-$PALANG['must_be_numeric_bigger_than_null'] = '%s must be numeric and bigger than 0'; # XXX
-$PALANG['must_be_boolean'] = '%s must be boolean'; # XXX
-$PALANG['invalid_value_given'] = 'Invalid value given for %s'; # XXX
-$PALANG['edit_not_allowed'] = 'You are not allowed to edit %s'; # XXX
-$PALANG['searchparams'] = 'Search parameters:'; # XXX
-$PALANG['pFooter_logged_as'] = 'PrihlÃ¡senÃ½ ako %s'; # XXX Text change: 'logged in as %s' (the 'in' was missing)
+$PALANG['show'] = 'Zobraz:';
+$PALANG['all'] = 'VÅ¡etko';
+$PALANG['created'] = 'VytvorenÃ©';
+$PALANG['unknown'] = 'neznÃ¡me';
+$PALANG['download_csv'] = 'StiahnuÅ¥ ako CSV sÃºbor';
+$PALANG['missing_field'] = 'Pole %s chÃ½ba';
+$PALANG['must_be_numeric'] = '%s musÃ­ byÅ¥ ÄÃ­slo';
+$PALANG['must_be_numeric_bigger_than_null'] = '%s musÃ­ byÅ¥ ÄÃ­slo vÃ¤ÄÅ¡ie ako 0';
+$PALANG['must_be_boolean'] = '%s musÃ­ byÅ¥ typu boolean';
+$PALANG['invalid_value_given'] = 'NeplatnÃ¡ hodnota zadanÃ¡ pre %s';
+$PALANG['edit_not_allowed'] = 'NemÃ¡te oprÃ¡vnenie upravovaÅ¥ %s';
+$PALANG['searchparams'] = 'Parametre hÄ¾adania:';
+$PALANG['pFooter_logged_as'] = 'PrihlÃ¡senÃ½ ako %s';
 
 $PALANG['pLogin_welcome'] = 'PrihlÃ¡senie administrÃ¡torov pre sprÃ¡vu domÃ©n';
 $PALANG['pLogin_username'] = 'UÅ¾Ã­vateÄ¾skÃ© meno (email)';
 $PALANG['password'] = 'Heslo';
-$PALANG['pLogin_language'] = 'Language'; # XXX
+$PALANG['pLogin_language'] = 'Jazyk';
 $PALANG['pLogin_button'] = 'PrihlÃ¡siÅ¥';
 $PALANG['pLogin_failed'] = 'VÃ¡Å¡ email alebo heslo nie je sprÃ¡vne.';
 $PALANG['pLogin_login_users'] = 'Vstup do uÅ¾Ã­vateÄ¾skej sekcie';
 
 $PALANG['pMenu_main'] = 'HlavnÃ©';
 $PALANG['pMenu_overview'] = 'PrehÄ¾ad';
-$PALANG['add_alias'] = 'NovÃ½ alias'; # XXX check text - should be 'Add Alias'
-$PALANG['add_alias_domain'] = 'NovÃ½ alias domÃ©ny'; # XXX check text - should be 'Add Alias Domain'
-$PALANG['add_mailbox'] = 'NovÃ¡ schrÃ¡nka'; # XXX check text - should be 'Add Mailbox'
+$PALANG['add_alias'] = 'PridaÅ¥ alias';
+$PALANG['add_alias_domain'] = 'PridaÅ¥ alias domÃ©ny';
+$PALANG['add_mailbox'] = 'PridaÅ¥ schrÃ¡nku';
 $PALANG['pMenu_fetchmail'] = 'SÅ¥ahovanie emailu';
 $PALANG['pMenu_sendmail'] = 'PoslaÅ¥ email';
 $PALANG['pMenu_password'] = 'ZmeniÅ¥ heslo';
@@ -59,7 +59,7 @@ $PALANG['pMenu_logout'] = 'OdhlÃ¡siÅ¥';
 
 $PALANG['pMain_welcome'] = 'Vitajte v Postfix Admine!';
 $PALANG['pMain_overview'] = 'VÃ½pis aliasov a schrÃ¡nok. MÃ´Å¾ete ich tu upravovaÅ¥ a mazaÅ¥.';
-$PALANG['pMain_create_alias'] = 'VytvoriÅ¥ alias v tejto domÃ©ne.'; # XXX check text - should be 'Create a new alias for your domain.'
+$PALANG['pMain_create_alias'] = 'VytvoriÅ¥ alias v tejto domÃ©ne.';
 $PALANG['pMain_create_mailbox'] = 'VytvoriÅ¥ schrÃ¡nku v tejto domÃ©ne.';
 $PALANG['pMain_sendmail'] = 'PoslaÅ¥ email do jednej zo schrÃ¡nok.';
 $PALANG['pMain_password'] = 'ZmeniÅ¥ heslo administrÃ¡torskÃ©ho ÃºÄtu.';
@@ -79,15 +79,15 @@ $PALANG['go'] = 'PrejsÅ¥';
 $PALANG['pOverview_welcome'] = 'PrehÄ¾ad pre domÃ©nu ';
 $PALANG['pOverview_alias_domain_aliases'] = 'Aliasy domÃ©n';
 $PALANG['pOverview_alias_address'] = 'Od';
-$PALANG['active'] = 'AktÃ­vny'; # XXX check text - should be 'Active'
+$PALANG['active'] = 'AktÃ­vny';
 $PALANG['and_x_more'] = '[a %s ÄalÅ¡Ã­ch...]';
 $PALANG['pOverview_mailbox_username'] = 'Email';
 $PALANG['name'] = 'Meno';
 $PALANG['pOverview_mailbox_quota'] = 'KvÃ³ta (MB)';
 $PALANG['pOverview_vacation_edit'] = 'AUT. ODPOVEÄŽ';
 $PALANG['pOverview_vacation_option'] = 'aut. odpoveÄ';
-$PALANG['no_domains_for_this_admin'] = 'You don\'t have permissions for any domains.'; # XXX
-$PALANG['no_domains_exist'] = 'You have to create at least one domain before you can use virtual list.'; # "virtual list" should match $PALANG['pAdminMenu_list_virtual'] # XXX
+$PALANG['no_domains_for_this_admin'] = 'NemÃ¡te oprÃ¡vnenie pre Å¾iadne domÃ©ny.';
+$PALANG['no_domains_exist'] = 'MusÃ­te vytvoriÅ¥ aspoÅˆ jednu domÃ©nu.';
 
 $PALANG['domain'] = 'DomÃ©na';
 $PALANG['pOverview_get_alias_domains'] = 'Aliasy domÃ©n';
@@ -105,58 +105,62 @@ $PALANG['pCreate_alias_domain_target'] =
 $PALANG['pCreate_alias_domain_target_text'] = 'Kam sa email presmeruje';
 $PALANG['pCreate_alias_domain_error1'] = 'Nie ste oprÃ¡vnenÃ­ vytvoriÅ¥ zvolenÃº konfigurÃ¡ciu.';
 $PALANG['pCreate_alias_domain_error2'] = 'ZvolenÃ¡ konfigurÃ¡cia nie je platnÃ¡, zvoÄ¾te inÃº!';
-$PALANG['alias_domain_already_exists'] = 'This domain is already an alias domain!'; # XXX
-$PALANG['alias_domain_does_not_exist'] = 'This domain isn\'t an alias domain!'; # XXX
-$PALANG['alias_domain_create_failed'] = 'Chyba pri vkladanÃ­ do databÃ¡zy. (%s)'; # XXX Text changed to: Creating the alias domain %s failed!
-$PALANG['alias_domain_change_failed'] = 'Changing the alias domain %s failed!'; # XXX
+$PALANG['alias_domain_already_exists'] = 'Tento alias domÃ©ny uÅ¾ existuje!';
+$PALANG['alias_domain_does_not_exist'] = 'Tento alias domÃ©ny neexistuje!';
+$PALANG['alias_domain_create_failed'] = 'Nepodarilo sa vytvoriÅ¥ alias domÃ©ny %s!';
+$PALANG['alias_domain_change_failed'] = 'Nepodarilo sa upraviÅ¥ alias domÃ©ny %s!';
 $PALANG['pCreate_alias_domain_error4'] = 'VÅ¡etky domÃ©ny uÅ¾ majÃº aliasy.';
-$PALANG['pCreate_alias_domain_success'] = 'Alias domÃ©ny bol pridanÃ½ do tabuÄ¾ky! (%s)'; # XXX Text changed to: The alias domain %s has been created.
-$PALANG['alias_domain_changed'] = 'The alias domain %s has been changed.'; # XXX
-$PALANG['alias_domain_to_itsself'] = 'A domain can\'t be an alias domain to itsself!'; # XXX
-$PALANG['delete_domain_aliasdomain_target'] = 'The domain %s is the target for one or more alias domains and can\'t be deleted! (Delete the alias domains first.)'; # XXX
+$PALANG['pCreate_alias_domain_success'] = 'Alias domÃ©ny %s bol vytvorenÃ½.';
+$PALANG['alias_domain_changed'] = 'Alias domÃ©ny %s bol zmenenÃ½.';
+$PALANG['alias_domain_to_itsself'] = 'DomÃ©na nemÃ´Å¾e byÅ¥ alias na seba!';
+$PALANG['delete_domain_aliasdomain_target'] = 'DomÃ©na %s je cieÄ¾om najmenej jednÃ©ho aliasu domÃ©ny a nemÃ´Å¾e byÅ¥ zmazanÃ¡! (Najprv zmaÅ¾te aliasy domÃ©n.)';
 
 $PALANG['pCreate_alias_address_text_error1'] = 'Adresa nie je platnÃ¡!';
-$PALANG['alias_does_not_exist'] = 'This alias does not exist!'; # XXX
-$PALANG['email_address_already_exists'] = 'TakÃ¡to emailovÃ¡ adresa uÅ¾ existuje!'; # XXX check text - should be 'This email address already exists, please choose a different one\!'
+$PALANG['alias_does_not_exist'] = 'Tento alias neexistuje!';
+$PALANG['email_address_already_exists'] = 'TakÃ¡to emailovÃ¡ adresa uÅ¾ existuje!';
 $PALANG['pCreate_alias_address_text_error3'] = 'Dosiahli ste limit, nemÃ´Å¾ete vytvÃ¡raÅ¥ ÄalÅ¡ie aliasy!';
 $PALANG['pCreate_alias_goto_text'] = 'Kam mÃ¡ poÅ¡ta chodiÅ¥';
 $PALANG['pCreate_alias_goto_text_error'] = 'CieÄ¾ nie je platnÃ½!';
-$PALANG['pCreate_alias_result_error'] = 'Nepodarilo sa pridaÅ¥ alias do tabuÄ¾ky! (%s)'; # XXX Text changed to: Creating the alias %s failed!
-$PALANG['pCreate_alias_result_success'] = 'Alias bol pridanÃ½ do tabuÄ¾ky!'; # XXX text change: 'The alias %s has been created!'
-$PALANG['alias_updated'] = 'The alias %s has been updated!'; # XXX
-$PALANG['pCreate_alias_catchall_text'] = 'Pre vytvorenie domÃ©novÃ©ho koÅ¡a pouÅ¾ite * ako alias. Pre alias domÃ©na-domÃ©na pouÅ¾ite *@domain.tld ako cieÄ¾.'; # XXX check/beautify - was split in two lines before
-$PALANG['mailbox_alias_cant_be_deleted'] = 'This alias belongs to a mailbox and can\'t be deleted!'; # XXX
-$PALANG['protected_alias_cant_be_deleted'] = 'The alias %s is protected and can only be deleted by a superadmin'; # XXX
-
-$PALANG['pEdit_alias_welcome'] = 'UpraviÅ¥ aliasy'; # XXX Text change to: 'Edit forwarding settings'
-$PALANG['pEdit_alias_help'] = 'Jeden zÃ¡znam na riadku'; # XXX # XXX Text change to: 'Accepts multiple targets, one entry per line.'
-$PALANG['alias'] = 'Alias'; # XXX
-$PALANG['to'] = 'CieÄ¾'; # XXX check text - should be 'To'
+$PALANG['pCreate_alias_result_error'] = 'Nepodarilo sa vytvoriÅ¥ alias %s!';
+$PALANG['pCreate_alias_result_success'] = 'Alias %s bol vytvorenÃ½.';
+$PALANG['alias_updated'] = 'Alias %s bol aktualizovanÃ½.';
+$PALANG['pCreate_alias_catchall_text'] = 'Pre vytvorenie domÃ©novÃ©ho koÅ¡a pouÅ¾ite * ako alias. Pre alias domÃ©na-domÃ©na pouÅ¾ite *@domain.tld ako cieÄ¾.';
+$PALANG['mailbox_alias_cant_be_deleted'] = 'Tento alias patrÃ­ k schrÃ¡nke a nemÃ´Å¾e byÅ¥ zmazanÃ½!';
+$PALANG['protected_alias_cant_be_deleted'] = 'Alias %s je chrÃ¡nenÃ½ a mÃ´Å¾e ho zmazaÅ¥ len superadmin';
+
+$PALANG['pEdit_alias_welcome'] = 'UpraviÅ¥ alias';
+$PALANG['pEdit_alias_help'] = 'Jeden zÃ¡znam na riadok.';
+$PALANG['alias'] = 'Alias';
+$PALANG['to'] = 'CieÄ¾';
 $PALANG['pEdit_alias_goto_text_error1'] = 'Nezadali ste cieÄ¾';
 $PALANG['pEdit_alias_goto_text_error2'] = 'ZadanÃ¡ emailovÃ¡ adresa nie je platnÃ¡: ';
 $PALANG['pEdit_alias_domain_result_error'] = 'Nepodarilo sa zmeniÅ¥ alias domÃ©ny!';
 $PALANG['pEdit_alias_forward_and_store'] = 'DoruÄiÅ¥ aj do lokÃ¡lnej schrÃ¡nky';
 $PALANG['pEdit_alias_forward_only'] = 'Len presmerovaÅ¥ na zadanÃ© emailovÃ© adresy';
-$PALANG['pEdit_alias_result_error'] = 'Nepodarilo se upraviÅ¥ alias! (%s)'; # XXX Text changed to: Modifying the alias %s failed!
+$PALANG['pEdit_alias_result_error'] = 'Nepodarilo se upraviÅ¥ alias %s!';
 
 $PALANG['pCreate_mailbox_welcome'] = 'VytvoriÅ¥ novÃº schrÃ¡nku v domÃ©ne';
 $PALANG['pCreate_mailbox_username_text_error1'] = 'Adresa nie je platnÃ¡!';
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Dosiahli ste limit, nemÃ´Å¾ete vytvÃ¡raÅ¥ ÄalÅ¡ie schrÃ¡nky!';
 $PALANG['pCreate_mailbox_password_text'] = 'Heslo pre POP3/IMAP/SMTP';
 $PALANG['pCreate_mailbox_name_text'] = 'CelÃ© meno';
-$PALANG['pCreate_mailbox_mail'] = 'PoslaÅ¥ uvÃ­tacÃ­ email'; # XXX Text change to 'Send Welcome mail'
-$PALANG['pCreate_mailbox_result_error'] = 'Nepodarilo sa pridaÅ¥ schrÃ¡nku do tabuÄ¾ky! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
-$PALANG['pCreate_mailbox_result_success'] = 'SchrÃ¡nka bola pridanÃ¡ do tabuÄ¾ky! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
-$PALANG['pCreate_mailbox_result_succes_nosubfolders'] = 'SchrÃ¡nka bola pridanÃ¡ do tabuÄ¾ky, ale nepodarilo sa vytvoriÅ¥ (niektorÃ©) definovanÃ© adresÃ¡re (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table, but none (or only some) of the predefined sub-folders could be created.
-$PALANG['mailbox_updated'] = "The mailbox %s has been updated.";  # XXX
-$PALANG['mailbox_update_failed'] = "Updating the mailbox %s failed!"; # XXX
+$PALANG['pCreate_mailbox_phone'] = 'MobilnÃ½ telefÃ³n';
+$PALANG['pCreate_mailbox_phone_desc'] = "Na odoslanie SMS v prÃ­pade zabudnutÃ©ho hesla";
+$PALANG['pCreate_mailbox_email'] = 'InÃ½ e-mail';
+$PALANG['pCreate_mailbox_email_desc'] = "Pre prÃ­pad zabudnutÃ©ho hesla";
+$PALANG['pCreate_mailbox_mail'] = 'PoslaÅ¥ uvÃ­tacÃ­ email';
+$PALANG['pCreate_mailbox_result_error'] = 'Nepodarilo sa vytvoriÅ¥ schrÃ¡nku %s!';
+$PALANG['pCreate_mailbox_result_success'] = 'SchrÃ¡nka %s bola vytvorenÃ¡.';
+$PALANG['pCreate_mailbox_result_succes_nosubfolders'] = 'SchrÃ¡nka %s bola vytvorenÃ¡, ale nepodarilo sa vytvoriÅ¥ (niektorÃ©) definovanÃ© adresÃ¡re!';
+$PALANG['mailbox_updated'] = "SchrÃ¡nka %s bola upravenÃ¡.";
+$PALANG['mailbox_update_failed'] = "Nepodarilo sa upraviÅ¥ schrÃ¡nku %s!";
 
 $PALANG['pEdit_mailbox_welcome'] = 'UpraviÅ¥ schrÃ¡nku v domÃ©ne';
 $PALANG['pEdit_mailbox_username'] = 'UÅ¾Ã­vateÄ¾skÃ© meno';
 $PALANG['pEdit_mailbox_password_text_error'] = 'ZadanÃ¡ heslÃ¡ se nezhodujÃº!';
 $PALANG['pEdit_mailbox_quota'] = 'KvÃ³ta';
 $PALANG['pEdit_mailbox_quota_text'] = 'MB';
-$PALANG['mb_max'] = 'MB (max: %s)'; # XXX
+$PALANG['mb_max'] = 'MB (max: %s)';
 $PALANG['pEdit_mailbox_quota_text_error'] = 'ZadanÃ© miesto je prÃ­liÅ¡ veÄ¾kÃ©!';
 $PALANG['pEdit_mailbox_domain_error'] = 'TÃ¡to domÃ©na nie je vaÅ¡a: ';
 $PALANG['pEdit_mailbox_result_error'] = 'Nepodarilo sa upraviÅ¥ schrÃ¡nku!';
@@ -167,52 +171,59 @@ $PALANG['pPassword_password_current'] =
 $PALANG['pPassword_password_current_text_error'] = 'Nezadali ste sÃºÄasnÃ© heslo!';
 $PALANG['pPassword_password'] = 'NovÃ© heslo';
 $PALANG['pPassword_password2'] = 'NovÃ© heslo (znovu)';
-$PALANG['pPassword_password_text_error'] = 'ZadanÃ© heslÃ¡ sÃº rozdielne alebo prÃ¡zdne!'; # XXX check/beautify - was split in two lines before
-$PALANG['change_password'] = 'ZmeniÅ¥ heslo'; # XXX check text - should be 'Change Password'
-$PALANG['pPassword_result_error'] = 'Nepodarilo sa zmeniÅ¥ heslo! (%s)'; # XXX Text changed to: Changing the password for %s failed!
-$PALANG['pPassword_result_success'] = 'Heslo bolo zmenenÃ©! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_password_text_error'] = 'ZadanÃ© heslÃ¡ sÃº rozdielne alebo prÃ¡zdne!';
+$PALANG['change_password'] = 'ZmeniÅ¥ heslo';
+$PALANG['pPassword_result_error'] = 'Nepodarilo sa zmeniÅ¥ heslo pre %s';
+$PALANG['pPassword_result_success'] = 'Heslo bolo zmenenÃ© pre %s';
+$PALANG['pPassword_recovery_title'] = 'Postup pre zmenu hesla.';
+$PALANG['pPassword_recovery_button'] = 'OdoslaÅ¥ kÃ³d';
+$PALANG['pPassword_recovery_email_body'] = "PouÅ¾ite tento link na zmenu hesla pre email:\n%s\n\n" . $CONF['admin_name'];
+$PALANG['pPassword_recovery_sms_body'] = "KÃ³d na zmenu vaÅ¡eho hesla je: %s\n" . $CONF['admin_name'];
+$PALANG['pPassword_recovery_processed'] = "We processed your request. Ak ste zadali sprÃ¡vne meno, dostanete email/SMS s kÃ³dom na zmenu hesla.";
+$PALANG['pPassword_password_code'] = 'KÃ³d odoslanÃ½ cez email/SMS';
+$PALANG['pPassword_code_text_error'] = 'NeplatnÃ½ kÃ³d';
 $PALANG['pEdit_vacation_set'] = 'ZmeniÅ¥/nastaviÅ¥ aut. odpoveÄ';
 $PALANG['pEdit_vacation_remove'] = 'OdstrÃ¡niÅ¥ aut. odpoveÄ';
-$PALANG['pVacation_result_error'] = 'Neopdarilo sa zmeniÅ¥ automatickÃº odpoveÄ! (%s)'; # XXX Text changed to: Updating the auto response settings for %s failed
-$PALANG['pVacation_result_removed'] = 'AutomatickÃ¡ odpoveÄ bola odstrÃ¡nenÃ¡! (%s)'; # XXX Text changed to "Auto response for %s has been disabled!"
-$PALANG['pVacation_result_added'] = 'AutomatickÃ¡ odpoveÄ bola nastavenÃ¡! (%s)'; # XXX Text changed to "Auto response for %s has been enabled!"
-$PALANG['pVacation_reply_type'] = 'Choice of reply'; # XXX
-$PALANG['pVacation_reply_delay_time'] = 'Interval time'; # XXX
-$PALANG['pVacation_reply_delay_time_text'] = 'Time in seconds'; # XXX
-$PALANG['pVacation_until_before_today'] = 'The Date of [Active until] is set  before Today'; # XXX
-$PALANG['pVacation_until_before_from'] = 'The Date of [Active until] is set before [Active from]'; # XXX
-$PALANG['reply_once'] = 'Reply once'; # XXX
-$PALANG['reply_every_mail'] = 'Reply on every mail'; # XXX
-$PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
-$PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
+$PALANG['pVacation_result_error'] = 'Neopdarilo sa zmeniÅ¥ automatickÃº odpoveÄ pre %s!';
+$PALANG['pVacation_result_removed'] = 'AutomatickÃ¡ odpoveÄ pre %s bola odstrÃ¡nenÃ¡!';
+$PALANG['pVacation_result_added'] = 'AutomatickÃ¡ odpoveÄ pre %s bola nastavenÃ¡!';
+$PALANG['pVacation_reply_type'] = 'Ako odpovedaÅ¥';
+$PALANG['pVacation_reply_delay_time'] = 'ÄŒasovÃ½ interval';
+$PALANG['pVacation_reply_delay_time_text'] = 'ÄŒas v sekundÃ¡ch';
+$PALANG['pVacation_until_before_today'] = 'DÃ¡tum [AktÃ­vna do] je v minulosti!';
+$PALANG['pVacation_until_before_from'] = 'DÃ¡tum [AktÃ­vna do] je starÅ¡Ã­ ako [AktÃ­vna od]!';
+$PALANG['reply_once'] = 'OdpovedaÅ¥ raz';
+$PALANG['reply_every_mail'] = 'OdpovedaÅ¥ na kaÅ¾dÃº sprÃ¡vu';
+$PALANG['reply_once_per_day'] = 'OdpovedaÅ¥ raz za deÅˆ';
+$PALANG['reply_once_per_week'] = 'OdpovedaÅ¥ raz za tÃ½Å¾deÅˆ';
 
-$PALANG['pViewlog_welcome'] = 'PrehÄ¾ad 10 poslednÃ½ch akciÃ­ pre ';
+$PALANG['pViewlog_welcome'] = 'PrehÄ¾ad %s poslednÃ½ch akciÃ­ pre ';
 $PALANG['pViewlog_timestamp'] = 'ÄŒasovÃ¡ znaÄka';
 $PALANG['pViewlog_action'] = 'Akcia';
 $PALANG['pViewlog_data'] = 'Podrobnosti';
-$PALANG['pViewlog_action_create_domain'] = 'create domain'; # XXX
-$PALANG['pViewlog_action_delete_domain'] = 'delete domain'; # XXX
-$PALANG['pViewlog_action_edit_domain'] = 'edit domain'; # XXX
+$PALANG['pViewlog_action_create_domain'] = 'vytvorenie domÃ©ny';
+$PALANG['pViewlog_action_delete_domain'] = 'zruÅ¡enie domÃ©ny';
+$PALANG['pViewlog_action_edit_domain'] = 'zmena domÃ©ny';
 $PALANG['pViewlog_action_create_mailbox'] = 'vytvorenie schrÃ¡nky';
 $PALANG['pViewlog_action_delete_mailbox'] = 'zruÅ¡enie schrÃ¡nky';
 $PALANG['pViewlog_action_edit_mailbox'] = 'zmena schrÃ¡nky';
 $PALANG['pViewlog_action_edit_mailbox_state'] = 'zmena aktivity schrÃ¡nky';
 $PALANG['pViewlog_action_create_alias'] = 'vytvorenie aliasu';
 $PALANG['pViewlog_action_create_alias_domain'] = 'vytvorenie aliasu domÃ©ny';
-$PALANG['pViewlog_action_edit_alias_domain'] = 'edit alias domain'; # XXX
+$PALANG['pViewlog_action_edit_alias_domain'] = 'zmena aliasu domÃ©ny';
 $PALANG['pViewlog_action_delete_alias'] = 'zruÅ¡enie aliasu';
 $PALANG['pViewlog_action_delete_alias_domain'] = 'zruÅ¡enie aliasu domÃ©ny';
 $PALANG['pViewlog_action_edit_alias'] = 'zmena aliasu';
 $PALANG['pViewlog_action_edit_alias_state'] = 'zmena aktivity aliasu';
 $PALANG['pViewlog_action_edit_alias_domain_state'] = 'zmena aktivity aliasu domÃ©ny';
 $PALANG['pViewlog_action_edit_password'] = 'zmena hesla';
-$PALANG['pViewlog_action_create_admin'] = 'create admin'; # XXX
-$PALANG['pViewlog_action_edit_admin'] = 'edit admin'; # XXX
-$PALANG['pViewlog_action_delete_admin'] = 'delete admin'; # XXX
-$PALANG['pViewlog_action_edit_vacation'] = 'edit vacation'; # XXX
-$PALANG['pViewlog_action_create_fetchmail'] = 'create fetchmail job'; # XXX
-$PALANG['pViewlog_action_edit_fetchmail'] = 'edit fetchmail job'; # XXX
-$PALANG['pViewlog_action_delete_fetchmail'] = 'delete fetchmail job'; # XXX
+$PALANG['pViewlog_action_create_admin'] = 'vytvorenie administrÃ¡tora';
+$PALANG['pViewlog_action_edit_admin'] = 'zmena administrÃ¡tora';
+$PALANG['pViewlog_action_delete_admin'] = 'zruÅ¡enie administrÃ¡tora';
+$PALANG['pViewlog_action_edit_vacation'] = 'zmena aut. odpovede';
+$PALANG['pViewlog_action_create_fetchmail'] = 'vytvorenie sÅ¥ahovania';
+$PALANG['pViewlog_action_edit_fetchmail'] = 'zmena sÅ¥ahovania';
+$PALANG['pViewlog_action_delete_fetchmail'] = 'zruÅ¡enie sÅ¥ahovania';
 
 $PALANG['pViewlog_result_error'] = 'Nepodarilo sa nÃ¡jsÅ¥ zÃ¡znamy!';
 
@@ -224,74 +235,75 @@ $PALANG['subject'] = 'Predmet';
 $PALANG['pSendmail_subject_text'] = 'Vitajte';
 $PALANG['pSendmail_body'] = 'Obsah';
 $PALANG['pSendmail_button'] = 'PoslaÅ¥ email';
-$PALANG['pSendmail_result_error'] = 'Nepodarilo sa poslaÅ¥ email! (%s)'; # XXX text change - new: Unable to send email to %s!
-$PALANG['pSendmail_result_success'] = 'Email odoslanÃ½! (%s)'; # XXX text change - new: Email sent to %s.
+$PALANG['pSendmail_result_error'] = 'Nepodarilo sa poslaÅ¥ email na adresu %s!';
+$PALANG['pSendmail_result_success'] = 'Email odoslanÃ½ na adresu %s.';
 
 $PALANG['pAdminMenu_list_admin'] = 'AdministrÃ¡tori';
 $PALANG['pAdminMenu_list_domain'] = 'DomÃ©ny';
 $PALANG['pAdminMenu_list_virtual'] = 'Aliasy';
 $PALANG['pAdminMenu_backup'] = 'ZÃ¡lohovaÅ¥';
 $PALANG['pAdminMenu_create_domain_admins'] = 'DomÃ©novÃ­ administrÃ¡tori';
-$PALANG['pAdminMenu_create_admin'] = 'NovÃ½ admin';
+$PALANG['pAdminMenu_create_admin'] = 'NovÃ½ administrÃ¡tor';
 $PALANG['pAdminMenu_create_domain'] = 'NovÃ¡ domÃ©na';
 
 $PALANG['pAdminList_admin_count'] = 'DomÃ©ny';
 
 $PALANG['description'] = 'Popis';
-$PALANG['aliases'] = 'Aliasov'; # XXX check text - should be 'Aliases'
-$PALANG['pAdminList_domain_quota'] = 'Domain quota (MB)'; # XXX
+$PALANG['aliases'] = 'Aliasov';
+$PALANG['pAdminList_domain_quota'] = 'DomÃ©novÃ¡ kvÃ³ta (MB)';
 $PALANG['pAdminList_domain_backupmx'] = 'ZÃ¡loÅ¾nÃ½ MX';
 $PALANG['last_modified'] = 'PoslednÃ¡ zmena';
 
 
 $PALANG['pAdminCreate_domain_welcome'] = 'PridaÅ¥ novÃº domÃ©nu';
 $PALANG['pAdminCreate_domain_domain_text_error'] = 'TakÃ¡to domÃ©na uÅ¾ existuje!';
-$PALANG['domain_does_not_exist'] = 'This domain does not exist!'; # XXX
+$PALANG['domain_does_not_exist'] = 'TÃ¡to domÃ©na neexistuje!';
 $PALANG['pAdminCreate_domain_domain_text_error2'] = 'DomÃ©na nie je platnÃ¡!';
 $PALANG['pAdminCreate_domain_defaultaliases'] = 'VytvoriÅ¥ implicitnÃ© aliasy';
 $PALANG['pAdminCreate_domain_button'] = 'VytvoriÅ¥ domÃ©nu';
-$PALANG['pAdminCreate_domain_result_error'] = 'Nepodarilo sa pridaÅ¥ domÃ©nu! (%s)'; # XXX Text changed to: Adding the domain %s failed!
-$PALANG['pAdminCreate_domain_result_success'] = 'DomÃ©na bola pridanÃ¡! (%s)'; # XXX Text changed to: The domain %s has been added.
-$PALANG['domain_updated'] = 'The domain %s has been updated.'; # XXX
-$PALANG['pAdminDelete_admin_error'] = 'Unable to delete admin!'; # XXX
-$PALANG['domain_postdel_failed'] = 'Nepodarilo sa odstrÃ¡niÅ¥ domÃ©nu!'; # XXX Text changed to: The domain postdeletion script failed, check the error log for details!
-$PALANG['domain_postcreate_failed'] = 'The domain postcreate script failed, check the error log for details!'; # XXX
-$PALANG['mailbox_postdel_failed'] = 'The mailbox postdeletion script failed, check the error log for details!'; # XXX
-$PALANG['mailbox_postedit_failed'] = 'The mailbox postedit script failed, check the error log for details!'; # XXX
-$PALANG['mailbox_postcreate_failed'] = 'The mailbox postcreate script failed, check the error log for details!'; # XXX
+$PALANG['pAdminCreate_domain_result_error'] = 'Nepodarilo sa pridaÅ¥ domÃ©nu %s!';
+$PALANG['pAdminCreate_domain_result_success'] = 'DomÃ©na %s bola pridanÃ¡.';
+$PALANG['domain_updated'] = 'DomÃ©na %s bola zmenenÃ¡.';
+$PALANG['pAdminDelete_admin_error'] = 'Nepodarilo sa zmazaÅ¥ administrÃ¡tora!';
+$PALANG['domain_postdel_failed'] = 'Skript postdeletion pre domÃ©nu zlyhal, preverte log!';
+$PALANG['domain_postcreate_failed'] = 'Skript postcreate pre domÃ©nu zlyhal, preverte log!';
+$PALANG['mailbox_postdel_failed'] = 'Skript postdeletion pre schrÃ¡nku zlyhal, preverte log!';
+$PALANG['mailbox_postedit_failed'] = 'Skript postedit pre schrÃ¡nku zlyhal, preverte log!';
+$PALANG['mailbox_postcreate_failed'] = 'Skript postcreate pre schrÃ¡nku zlyhal, preverte log!';
 $PALANG['pAdminDelete_alias_domain_error'] = 'Nepodario sa odstrÃ¡niÅ¥ alias domÃ©ny!';
-$PALANG['domain_conflict_vacation_domain'] = 'You can\'t use the vacation domain as mail domain!'; # XXX
+$PALANG['domain_conflict_vacation_domain'] = 'NemÃ´Å¾ete pouÅ¾iÅ¥ domÃ©nu automatickej odpovede pre poÅ¡tu!';
 
 $PALANG['pAdminEdit_domain_welcome'] = 'UpraviÅ¥ domÃ©nu';
 $PALANG['pAdminEdit_domain_aliases_text'] = '-1 = zakÃ¡zaÅ¥ | 0 = neobmedzene';
 $PALANG['pAdminEdit_domain_maxquota'] = 'MaximÃ¡lna kvÃ³ta';
-$PALANG['pAdminEdit_domain_maxquota_text'] = 'MB | -1 = vypnÃºÅ¥ | 0 = neobmedzene'; # XXX check - should be "MB | -1 = disable | 0 = unlimited"
-$PALANG['pAdminEdit_domain_quota'] = 'Domain Quota'; # XXX
+$PALANG['pAdminEdit_domain_maxquota_text'] = 'MB | -1 = vypnÃºÅ¥ | 0 = neobmedzene';
+$PALANG['pAdminEdit_domain_quota'] = 'DomÃ©novÃ¡ kvÃ³ta';
 $PALANG['transport'] = 'Transport';
 $PALANG['pAdminEdit_domain_transport_text'] = 'PouÅ¾iÅ¥ transport';
 $PALANG['pAdminEdit_domain_backupmx'] = 'Mail server je zÃ¡loÅ¾nÃ½ MX';
-$PALANG['pAdminEdit_domain_result_error'] = 'Nepodarilo sa upraviÅ¥ domÃ©nu! (%s)'; # XXX Text changed to: Modifying the domain %s failed!
+$PALANG['pAdminEdit_domain_result_error'] = 'Nepodarilo sa upraviÅ¥ domÃ©nu %s!';
 
 $PALANG['pAdminCreate_admin_welcome'] = 'PridaÅ¥ novÃ©ho administrÃ¡tora';
 $PALANG['email_address'] = 'EmailovÃ¡ adresa';
 $PALANG['pAdminCreate_admin_username_text_error1'] = 'TÃ¡to adresa nie je platnÃ¡!';
-$PALANG['admin_already_exists'] = 'TakÃ¡to adresa uÅ¾ existuje!'; # XXX Text changed to: The admin already exists!
-$PALANG['admin_does_not_exist'] = 'The admin does not exist!'; # XXX
+$PALANG['admin_already_exists'] = 'AdministrÃ¡tor uÅ¾ existuje!';
+$PALANG['admin_does_not_exist'] = 'AdministrÃ¡tor neexistuje!';
 $PALANG['pAdminCreate_admin_button'] = 'VytvoriÅ¥ administrÃ¡tora';
-$PALANG['pAdminCreate_admin_result_error'] = 'Nepodarilo sa pridaÅ¥ administrÃ¡tora! (%s)'; # XXX Text changed to: Adding the admin %s failed!
-$PALANG['pAdminCreate_admin_result_success'] = 'AdministrÃ¡tor bol pridanÃ½! (%s)'; # XXX Text changed to: The admin %s has been added.
+$PALANG['pAdminCreate_admin_result_error'] = 'Nepodarilo sa pridaÅ¥ administrÃ¡tora %s!';
+$PALANG['pAdminCreate_admin_result_success'] = 'AdministrÃ¡tor %s bol pridanÃ½.';
 
 $PALANG['pAdminEdit_admin_welcome'] = 'UpraviÅ¥ domÃ©novÃ©ho administrÃ¡tora';
-$PALANG['admin'] = 'UÅ¾Ã­vateÄ¾skÃ© meno'; # XXX check text - should be 'Admin'
+$PALANG['admin'] = 'UÅ¾Ã­vateÄ¾skÃ© meno';
 $PALANG['password_again'] = 'Heslo (znovu)';
 $PALANG['super_admin'] = 'Super admin';
-$PALANG['super_admin_desc'] = 'Super admins have access to all domains, can manage domains and admin accounts.'; # XXX
-$PALANG['pAdminEdit_admin_result_error'] = 'Nepodarilo sa upraviÅ¥ administrÃ¡tora! (%s)'; # XXX Text changed to: Modifying the admin %s failed!
-$PALANG['pAdminEdit_admin_result_success'] = 'AdministrÃ¡tor bol upravenÃ½! (%s)'; # XXX Text changed to: The admin %s has been modified.
+$PALANG['super_admin_desc'] = 'Super admin mÃ¡ prÃ­stup k vÅ¡etkÃ½m domÃ©nam a spravuje administrÃ¡torskÃ© ÃºÄty.';
+$PALANG['pAdminEdit_admin_result_error'] = 'Nepodarilo sa upraviÅ¥ administrÃ¡tora %s!';
+$PALANG['pAdminEdit_admin_result_success'] = 'AdministrÃ¡tor %s bol upravenÃ½.';
 
 $PALANG['pUsersLogin_welcome'] = 'PrihlÃ¡senie uÅ¾Ã­vateÄ¾ov pre zmenu hesla alebo presmerovanie';
 $PALANG['pUsersLogin_username_incorrect'] = 'NesprÃ¡vnÃ© uÅ¾Ã­vateÄ¾skÃ© meno. Prihlasujte sa svojou emailovou adresou!';
 $PALANG['pUsersLogin_password_incorrect'] = 'NesprÃ¡vne heslo!';
+$PALANG['pUsersLogin_password_recover'] = 'Zabudol som heslo';
 
 $PALANG['pUsersMenu_vacation'] = 'AutomatickÃ¡ odpoveÄ';
 $PALANG['pUsersMenu_edit_alias'] = 'Presmerovanie';
@@ -302,9 +314,9 @@ $PALANG['pUsersMain_edit_alias'] = 'Nast
 $PALANG['pUsersMain_password'] = 'ZmeniÅ¥ heslo';
 
 $PALANG['pUsersVacation_welcome'] = 'AutomatickÃ¡ odpoveÄ';
-$PALANG['pUsersVacation_welcome_text'] = 'AutomatickÃ¡ odpoveÄ je zapnutÃ¡! (%s)'; # XXX Text changed to: 'Auto response for %s is active!'
+$PALANG['pUsersVacation_welcome_text'] = 'AutomatickÃ¡ odpoveÄ pre %s je zapnutÃ¡!';
 $PALANG['pUsersVacation_subject_text'] = 'Dovolenka';
-$PALANG['message'] = 'SprÃ¡va'; # XXX check text - should be 'Message'
+$PALANG['message'] = 'SprÃ¡va';
 $PALANG['pUsersVacation_body_text'] = <<<EOM
 Som na dovolenke od <date> od <date>.
 S neodkladnÃ½mi vecami kontaktujte <contact person>.
@@ -322,20 +334,22 @@ $PALANG['pBroadcast_title'] = 'PoslaÅ¥ h
 $PALANG['pBroadcast_name'] = 'VaÅ¡e meno';
 $PALANG['pBroadcast_success'] = 'HromadnÃ¡ sprÃ¡va bola odoslanÃ¡.';
 $PALANG['pAdminMenu_broadcast_message'] = 'HromadnÃ¡ sprÃ¡va';
-$PALANG['pBroadcast_error_empty'] = 'Polie VaÅ¡e meno, Predmet a Obsah nemÃ´Å¾u byÅ¥ prÃ¡zdne!';
+$PALANG['pBroadcast_error_empty'] = 'Polia VaÅ¡e meno, Predmet a Obsah nemÃ´Å¾u byÅ¥ prÃ¡zdne!';
+$PALANG['broadcast_mailboxes_only'] = 'PosielaÅ¥ len do schrÃ¡nok';
+$PALANG['broadcast_to_domains'] = 'PosielaÅ¥ na domÃ©ny:';
 $PALANG['pStatus_undeliverable'] = 'moÅ¾no NEDORUÄŒITEÄ½NÃ‰ ';
 $PALANG['pStatus_custom'] = 'DoruÄuje sa na ';
 $PALANG['pStatus_popimap'] = 'POP/IMAP ';
 $PALANG['password_too_short'] = "Heslo je prÃ­liÅ¡ krÃ¡tke - musÃ­ maÅ¥ aspoÅˆ %s znakov";
-$PALANG['password_no_characters'] = "Your password must contain at least %s character(s)."; # XXX
-$PALANG['password_no_digits'] = "Your password must contain at least %s digit(s)."; # XXX
+$PALANG['password_no_characters'] = "Heslo musÃ­ obsahovaÅ¥ aspoÅˆ %s pÃ­smen.";
+$PALANG['password_no_digits'] = "Heslo musÃ­ obsahovaÅ¥ aspoÅˆ %s ÄÃ­slic.";
 $PALANG['pInvalidDomainRegex'] = "NeplatnÃ½ nÃ¡zov domÃ©ny %s";
 $PALANG['pInvalidDomainDNS'] = "NeplatnÃ¡ domÃ©na %s alebo neexistuje jej DNS zÃ¡znam";
 $PALANG['pInvalidMailRegex'] = "NeplatnÃ¡ emailovÃ¡ adresa %s"; # text change to "Invalid email address %s, fails regexp check"
 $PALANG['pFetchmail_welcome'] = 'SÅ¥ahovanie emailu pre:';
 $PALANG['pFetchmail_new_entry'] = 'NovÃ¡ poloÅ¾ka';
-$PALANG['fetchmail_already_exists']         = 'This fetchmail job already exists!'; # XXX
-$PALANG['fetchmail_does_not_exist']         = 'This fetchmail job does not exist!'; # XXX
+$PALANG['fetchmail_already_exists']         = 'SÅ¥ahovanie uÅ¾ existuje!';
+$PALANG['fetchmail_does_not_exist']         = 'SÅ¥ahovanie neexistuje!';
 $PALANG['pFetchmail_database_save_error'] = 'Nepodarilo sa uloÅ¾iÅ¥ poloÅ¾ku do databÃ¡zy!';
 $PALANG['pFetchmail_database_save_success'] = 'PoloÅ¾ka uloÅ¾enÃ¡ do databÃ¡zy.';
 $PALANG['pFetchmail_error_invalid_id'] = 'PoloÅ¾ka s ID %s neexistuje!';
@@ -355,9 +369,9 @@ $PALANG['pFetchmail_field_fetchall']
 $PALANG['pFetchmail_field_keep']            = 'PonechaÅ¥';
 $PALANG['pFetchmail_field_protocol']        = 'Protokol';
 $PALANG['pFetchmail_field_usessl']          = 'SSL';
-$PALANG['pFetchmail_field_sslcertck']       = 'SSL certificate check'; # XXX
-$PALANG['pFetchmail_field_sslcertpath']     = 'SSL path to certificates'; # XXX
-$PALANG['pFetchmail_field_sslfingerprint']  = 'SSL fingerprint (md5)'; # XXX
+$PALANG['pFetchmail_field_sslcertck']       = 'SSL kontrola certifikÃ¡tov';
+$PALANG['pFetchmail_field_sslcertpath']     = 'SSL cesta k certifikÃ¡tom';
+$PALANG['pFetchmail_field_sslfingerprint']  = 'SSL odtlaÄok (md5)';
 $PALANG['pFetchmail_field_extra_options']   = 'Parametre';
 $PALANG['pFetchmail_field_mda']             = 'MDA';
 $PALANG['pFetchmail_field_date']            = 'DÃ¡tum';
@@ -378,8 +392,8 @@ $PALANG['pFetchmail_desc_extra_options']
 $PALANG['pFetchmail_desc_mda']              = 'DoruÄovacÃ­ program (Mail Delivery Agent)';
 $PALANG['pFetchmail_desc_date']             = 'DÃ¡tum poslednej zmeny konfigurÃ¡cie';
 $PALANG['pFetchmail_desc_returned_text']    = 'SprÃ¡va z poslednÃ©ho sÅ¥ahovania';
-$PALANG['dateformat_pgsql'] = 'YYYY-mm-dd'; # translators: rearrange to your local date format, but make sure it's a valid PostgreSQL date format # XXX
-$PALANG['dateformat_mysql'] = '%Y-%m-%d';   # translators: rearrange to your local date format, but make sure it's a valid MySQL date format # XXX
+$PALANG['dateformat_pgsql'] = 'dd.mm.YYYY'; # translators: rearrange to your local date format, but make sure it's a valid PostgreSQL date format
+$PALANG['dateformat_mysql'] = '%d.%m.%Y';   # translators: rearrange to your local date format, but make sure it's a valid MySQL date format
 
 $PALANG['please_keep_this_as_last_entry'] = ''; # needed for language-check.sh
 /* vim: set expandtab ft=php softtabstop=3 tabstop=3 shiftwidth=3: */
diff -pruN 3.0.2-2/languages/sl.lang 3.2-2/languages/sl.lang
--- 3.0.2-2/languages/sl.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/sl.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: sl.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Slovenian
 // by Nejc Skoberne <nejc at skoberne dot net>
@@ -143,6 +143,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Maksimalno Å¡tevilo predalov je preseÅ¾eno!';
 $PALANG['pCreate_mailbox_password_text'] = 'Geslo za POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'Polno ime';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Ustvari predal'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Predala ni bilo mogoÄe ustvariti! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'Predal je bil uspeÅ¡no ustvarjen! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -170,6 +174,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Spremeni geslo';
 $PALANG['pPassword_result_error'] = 'Gesla ni bilo mogoÄe spremeniti! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Geslo je bilo uspeÅ¡no spremenjeno! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -185,7 +196,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Seznam zadnjih 10 operacij za ';
+$PALANG['pViewlog_welcome'] = 'Seznam zadnjih %s operacij za ';
 $PALANG['pViewlog_timestamp'] = 'ÄŒas';
 $PALANG['pViewlog_action'] = 'Operacija';
 $PALANG['pViewlog_data'] = 'Podatki';
@@ -291,6 +302,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'ÄŒe Å¾elite spremeniti gesli ali nastaviti sporoÄilo o odsotnosti, se prijavite.';
 $PALANG['pUsersLogin_username_incorrect'] = 'UporabniÅ¡ko ime ni pravilno! Uporabiti morate svoj e-poÅ¡tni naslov!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Geslo ni pravilno!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Obvestilo o odsotnosti';
 $PALANG['pUsersMenu_edit_alias'] = 'Nastavi preusmeritev';
@@ -322,6 +334,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.'; # XXX
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/sv.lang 3.2-2/languages/sv.lang
--- 3.0.2-2/languages/sv.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/sv.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: sv.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Swedish
 // by Stefan Jakobsson <stefan at katrinet dot se>
@@ -146,6 +146,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Du har redan skapat max tillÃ¥tet antal brevlÃ¥dor!';
 $PALANG['pCreate_mailbox_password_text'] = 'LÃ¶senord fÃ¶r POP3/IMAP';
 $PALANG['pCreate_mailbox_name_text'] = 'FullstÃ¤ndigt namn';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Skicka vÃ¤lkomstmeddelande'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Misslyckades att skapa brevlÃ¥dan %s!';
 $PALANG['pCreate_mailbox_result_success'] = 'BrevlÃ¥dan %s har skapats!';
@@ -173,6 +177,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Ã„ndra lÃ¶senord';
 $PALANG['pPassword_result_error'] = 'Misslyckades att Ã¤ndra lÃ¶senordet fÃ¶r %s!';
 $PALANG['pPassword_result_success'] = 'LÃ¶senord fÃ¶r %s har Ã¤ndrats!';
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 
 $PALANG['pEdit_vacation_set'] = 'Ã„ndra / Aktivera meddelande fÃ¶r ledighet';
 $PALANG['pEdit_vacation_remove'] = 'Ta bort meddelande fÃ¶r ledighet';
@@ -190,7 +201,7 @@ $PALANG['reply_every_mail'] = 'Svara pÃ¥
 $PALANG['reply_once_per_day'] = 'Svara en gÃ¥ng om dagen';
 $PALANG['reply_once_per_week'] = 'Svara en gÃ¥ng i veckan';
 
-$PALANG['pViewlog_welcome'] = 'Visa de senaste 10 Ã¥tgÃ¤rderna fÃ¶r ';
+$PALANG['pViewlog_welcome'] = 'Visa de senaste %s Ã¥tgÃ¤rderna fÃ¶r ';
 $PALANG['pViewlog_timestamp'] = 'Tidpunkt';
 $PALANG['pViewlog_action'] = 'Ã…tgÃ¤rd';
 $PALANG['pViewlog_data'] = 'Data';
@@ -298,6 +309,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'AnvÃ¤ndare mÃ¥ste logga in hÃ¤r fÃ¶r att Ã¤ndra lÃ¶senord och alias.';
 $PALANG['pUsersLogin_username_incorrect'] = 'Inloggningsnamnet Ã¤r felaktigt. Logga in med din e-postadress!';
 $PALANG['pUsersLogin_password_incorrect'] = 'LÃ¶senord Ã¤r felaktigt!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Autosvar';
 $PALANG['pUsersMenu_edit_alias'] = 'Ã„ndra din vidarebefordringsadress';
@@ -331,6 +343,8 @@ $PALANG['pBroadcast_name'] = 'Ditt namn'
 $PALANG['pBroadcast_success'] = 'Ditt grupputskick har sÃ¤nts.';
 $PALANG['pAdminMenu_broadcast_message'] = 'Grupputskick';
 $PALANG['pBroadcast_error_empty'] = 'FÃ¤lten namn, Ã¤mne och meddelande ska inte vara tomma!';
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 
 $PALANG['pStatus_undeliverable'] = 'kan eventuellt ej levereras ';
 $PALANG['pStatus_custom'] = 'Levereras till ';
diff -pruN 3.0.2-2/languages/tr.lang 3.2-2/languages/tr.lang
--- 3.0.2-2/languages/tr.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/tr.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: tr.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file TÃ¼rkÃ§e
 // by Onuryalazi
@@ -143,6 +143,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'Posta kutusu yaratma limitinize eriÃ¾tiniz!';
 $PALANG['pCreate_mailbox_password_text'] = 'POP3/IMAP iÃ§in Ã¾ifre';
 $PALANG['pCreate_mailbox_name_text'] = 'Tam isim';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'Posta kutusu yarat'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'Posta kutusu posta kutusu tablosuna eklenemiyor! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'Posta kutusu tabloya eklendi! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -170,6 +174,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'Ãžifreyi deÃ°iÃ¾tir'; # XXX check text - should be 'Change Password'
 $PALANG['pPassword_result_error'] = 'Ãžifreniz deÃ°iÃ¾tirilemedi! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'Ã¾ifreniz deÃ°iÃ¾tirildi! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'Change / Set away message'; # XXX
 $PALANG['pEdit_vacation_remove'] = 'Remove away message'; # XXX
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -185,7 +196,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'Reply once per week'; # XXX
 
-$PALANG['pViewlog_welcome'] = 'Son 10 hareket:';
+$PALANG['pViewlog_welcome'] = 'Son %s hareket:';
 $PALANG['pViewlog_timestamp'] = 'Timestamp';
 $PALANG['pViewlog_action'] = 'Aksiyon';
 $PALANG['pViewlog_data'] = 'Veri';
@@ -291,6 +302,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'Posta kutusu sahipleri, Ã¾ifre ddeÃ°iÃ¾tirmek iÃ§in giriÃ¾ yapÃ½n.';
 $PALANG['pUsersLogin_username_incorrect'] = 'KullanÃ½cÃ½ adÃ½nÃ½z doÃ°ru deÃ°il. E-posta adresiniz ile giriÃ¾ yaptÃ½Ã°Ã½nÃ½zdan emin olunuz!';
 $PALANG['pUsersLogin_password_incorrect'] = 'Ãžifreniz doÃ°ru deÃ°il!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'Otomatik cevaplama';
 $PALANG['pUsersMenu_edit_alias'] = 'YÃ¶nlendirmen deÃ°iÃ¾tir';
@@ -322,6 +334,8 @@ $PALANG['pBroadcast_name'] = 'Your name'
 $PALANG['pBroadcast_success'] = 'Your broadcast message was sent.'; # XXX
 $PALANG['pAdminMenu_broadcast_message'] = 'Broadcast message'; # XXX
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'maybe UNDELIVERABLE '; # XXX
 $PALANG['pStatus_custom'] = 'Delivers to '; # XXX
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/languages/tw.lang 3.2-2/languages/tw.lang
--- 3.0.2-2/languages/tw.lang	2017-02-08 17:53:13.000000000 +0000
+++ 3.2-2/languages/tw.lang	2018-05-02 20:37:27.000000000 +0000
@@ -1,5 +1,5 @@
 <?php
-# $Id: tw.lang 1889 2017-02-08 17:53:13Z christian_boltz $
+# $Id$
 //
 // Language file Traditional Chinese
 // by John Chen (johnpupu @SF)
@@ -144,6 +144,10 @@ $PALANG['pCreate_mailbox_username_text_e
 $PALANG['pCreate_mailbox_username_text_error3'] = 'éƒµç®±åœ°å€å·²ç¶“é”åˆ°ä¸Šé™!';
 $PALANG['pCreate_mailbox_password_text'] = 'POP3/IMAP å¯†ç¢¼';
 $PALANG['pCreate_mailbox_name_text'] = 'å…¨å';
+$PALANG['pCreate_mailbox_phone'] = 'Mobile phone'; # XXX
+$PALANG['pCreate_mailbox_phone_desc'] = "Used to send a SMS if the password is forgotten"; # XXX
+$PALANG['pCreate_mailbox_email'] = 'Other e-mail'; # XXX
+$PALANG['pCreate_mailbox_email_desc'] = "Used if the password is forgotten"; # XXX
 $PALANG['pCreate_mailbox_mail'] = 'æ–°å»ºéƒµç®±'; # XXX Text change to 'Send Welcome mail'
 $PALANG['pCreate_mailbox_result_error'] = 'ä¸èƒ½å°‡éƒµç®±å¢žåŠ åˆ°éƒµç®±è¡¨ä¸­! (%s)'; # XXX Text changed to: Creating the mailbox %s failed!
 $PALANG['pCreate_mailbox_result_success'] = 'å¢žåŠ éƒµç®±æˆåŠŸ! (%s)'; # XXX Text changed to: The mailbox %s has been added to the mailbox table!
@@ -171,6 +175,13 @@ $PALANG['pPassword_password_text_error']
 $PALANG['change_password'] = 'æ›´æ”¹å¯†ç¢¼'; # XXX check text - should be 'Change Password'
 $PALANG['pPassword_result_error'] = 'æ›´æ”¹å¯†ç¢¼å¤±æ•—! (%s)'; # XXX Text changed to: Changing the password for %s failed!
 $PALANG['pPassword_result_success'] = 'æ›´æ”¹å¯†ç¢¼æˆåŠŸ! (%s)'; # XXX Text changed to: The password for %s has been changed.
+$PALANG['pPassword_recovery_title'] = 'Follow the instructions to reset your password.'; # XXX
+$PALANG['pPassword_recovery_button'] = 'Send me the code'; # XXX
+$PALANG['pPassword_recovery_email_body'] = "Hello,\n\nUse the following link to change your email password :\n%s\n\nRegards,\n\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_sms_body'] = "Hello,\nThe code to change your password is: %s\n" . $CONF['admin_name']; # XXX
+$PALANG['pPassword_recovery_processed'] = "We processed your request. If you entered a valid username, you'll receive an email/SMS with a password code."; # XXX
+$PALANG['pPassword_password_code'] = 'Code sent by email/SMS'; # XXX
+$PALANG['pPassword_code_text_error'] = 'Invalid code'; # XXX
 $PALANG['pEdit_vacation_set'] = 'å•Ÿå‹•è‡ªå‹•å›žè¦†';
 $PALANG['pEdit_vacation_remove'] = 'å–æ¶ˆè‡ªå‹•å›žè¦†';
 $PALANG['pVacation_result_error'] = 'Updating the auto response settings for %s failed'; # XXX
@@ -187,7 +198,7 @@ $PALANG['reply_every_mail'] = 'Reply on
 $PALANG['reply_once_per_day'] = 'Reply once a day'; # XXX
 $PALANG['reply_once_per_week'] = 'æ¯æ˜ŸæœŸå›žè¦†ä¸€æ¬¡';
 
-$PALANG['pViewlog_welcome'] = 'æŸ¥çœ‹æœ€æ–°çš„10é …æ“ä½œæ—¥èªŒ ç¶²åŸŸ: ';
+$PALANG['pViewlog_welcome'] = 'æŸ¥çœ‹æœ€æ–°çš„%sé …æ“ä½œæ—¥èªŒ ç¶²åŸŸ: ';
 $PALANG['pViewlog_timestamp'] = 'æ™‚é–“';
 $PALANG['pViewlog_action'] = 'æ“ä½œ';
 $PALANG['pViewlog_data'] = 'å…§å®¹';
@@ -293,6 +304,7 @@ $PALANG['pAdminEdit_admin_result_success
 $PALANG['pUsersLogin_welcome'] = 'éƒµä»¶ç”¨æˆ¶å¾žé€™è£¡ç™»éŒ„ç®¡ç†ä½ çš„å¯†ç¢¼å’Œåˆ¥å.';
 $PALANG['pUsersLogin_username_incorrect'] = 'ç™»éŒ„å¤±æ•—. è«‹ç¢ºèªä½ æ˜¯ä½¿ç”¨ä½ çš„éƒµç®±åœ°å€ç™»éŒ„!';
 $PALANG['pUsersLogin_password_incorrect'] = 'ç™»éŒ„å¯†ç¢¼ä¸æ­£ç¢º!';
+$PALANG['pUsersLogin_password_recover'] = 'I forgot my password'; # XXX
 
 $PALANG['pUsersMenu_vacation'] = 'è‡ªå‹•å›žè¦†';
 $PALANG['pUsersMenu_edit_alias'] = 'ä¿®æ”¹è½‰ç™¼';
@@ -324,6 +336,8 @@ $PALANG['pBroadcast_name'] = 'ä½ çš„åå
 $PALANG['pBroadcast_success'] = 'ä½ çµ¦æ‰€æœ‰ç”¨æˆ¶çš„éƒµä»¶å·²ç™¼å‡ºã€‚';
 $PALANG['pAdminMenu_broadcast_message'] = 'ç™¼é€çµ¦æ‰€æœ‰ç”¨æˆ¶';
 $PALANG['pBroadcast_error_empty'] = 'The fields Name, Subject and Message shouldn\'t be empty!'; # XXX
+$PALANG['broadcast_mailboxes_only'] = 'Only send to mailboxes'; # XXX
+$PALANG['broadcast_to_domains'] = 'Send to domains:'; # XXX
 $PALANG['pStatus_undeliverable'] = 'å¯èƒ½ç„¡æ³•é€éž ';
 $PALANG['pStatus_custom'] = 'é€éžè‡³ ';
 $PALANG['pStatus_popimap'] = 'POP/IMAP '; # XXX
diff -pruN 3.0.2-2/lib/random_compat.phar 3.2-2/lib/random_compat.phar
--- 3.0.2-2/lib/random_compat.phar	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/random_compat.phar	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,1527 @@
+<?php
+
+$web = 'index.php';
+
+if (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) {
+Phar::interceptFileFuncs();
+set_include_path('phar://' . __FILE__ . PATH_SEPARATOR . get_include_path());
+Phar::webPhar(null, $web);
+include 'phar://' . __FILE__ . '/' . Extract_Phar::START;
+return;
+}
+
+if (@(isset($_SERVER['REQUEST_URI']) && isset($_SERVER['REQUEST_METHOD']) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'POST'))) {
+Extract_Phar::go(true);
+$mimes = array(
+'phps' => 2,
+'c' => 'text/plain',
+'cc' => 'text/plain',
+'cpp' => 'text/plain',
+'c++' => 'text/plain',
+'dtd' => 'text/plain',
+'h' => 'text/plain',
+'log' => 'text/plain',
+'rng' => 'text/plain',
+'txt' => 'text/plain',
+'xsd' => 'text/plain',
+'php' => 1,
+'inc' => 1,
+'avi' => 'video/avi',
+'bmp' => 'image/bmp',
+'css' => 'text/css',
+'gif' => 'image/gif',
+'htm' => 'text/html',
+'html' => 'text/html',
+'htmls' => 'text/html',
+'ico' => 'image/x-ico',
+'jpe' => 'image/jpeg',
+'jpg' => 'image/jpeg',
+'jpeg' => 'image/jpeg',
+'js' => 'application/x-javascript',
+'midi' => 'audio/midi',
+'mid' => 'audio/midi',
+'mod' => 'audio/mod',
+'mov' => 'movie/quicktime',
+'mp3' => 'audio/mp3',
+'mpg' => 'video/mpeg',
+'mpeg' => 'video/mpeg',
+'pdf' => 'application/pdf',
+'png' => 'image/png',
+'swf' => 'application/shockwave-flash',
+'tif' => 'image/tiff',
+'tiff' => 'image/tiff',
+'wav' => 'audio/wav',
+'xbm' => 'image/xbm',
+'xml' => 'text/xml',
+);
+
+header("Cache-Control: no-cache, must-revalidate");
+header("Pragma: no-cache");
+
+$basename = basename(__FILE__);
+if (!strpos($_SERVER['REQUEST_URI'], $basename)) {
+chdir(Extract_Phar::$temp);
+include $web;
+return;
+}
+$pt = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], $basename) + strlen($basename));
+if (!$pt || $pt == '/') {
+$pt = $web;
+header('HTTP/1.1 301 Moved Permanently');
+header('Location: ' . $_SERVER['REQUEST_URI'] . '/' . $pt);
+exit;
+}
+$a = realpath(Extract_Phar::$temp . DIRECTORY_SEPARATOR . $pt);
+if (!$a || strlen(dirname($a)) < strlen(Extract_Phar::$temp)) {
+header('HTTP/1.0 404 Not Found');
+echo "<html>\n <head>\n  <title>File Not Found<title>\n </head>\n <body>\n  <h1>404 - File Not Found</h1>\n </body>\n</html>";
+exit;
+}
+$b = pathinfo($a);
+if (!isset($b['extension'])) {
+header('Content-Type: text/plain');
+header('Content-Length: ' . filesize($a));
+readfile($a);
+exit;
+}
+if (isset($mimes[$b['extension']])) {
+if ($mimes[$b['extension']] === 1) {
+include $a;
+exit;
+}
+if ($mimes[$b['extension']] === 2) {
+highlight_file($a);
+exit;
+}
+header('Content-Type: ' .$mimes[$b['extension']]);
+header('Content-Length: ' . filesize($a));
+readfile($a);
+exit;
+}
+}
+
+class Extract_Phar
+{
+static $temp;
+static $origdir;
+const GZ = 0x1000;
+const BZ2 = 0x2000;
+const MASK = 0x3000;
+const START = 'index.php';
+const LEN = 6643;
+
+static function go($return = false)
+{
+$fp = fopen(__FILE__, 'rb');
+fseek($fp, self::LEN);
+$L = unpack('V', $a = fread($fp, 4));
+$m = '';
+
+do {
+$read = 8192;
+if ($L[1] - strlen($m) < 8192) {
+$read = $L[1] - strlen($m);
+}
+$last = fread($fp, $read);
+$m .= $last;
+} while (strlen($last) && strlen($m) < $L[1]);
+
+if (strlen($m) < $L[1]) {
+die('ERROR: manifest length read was "' .
+strlen($m) .'" should be "' .
+$L[1] . '"');
+}
+
+$info = self::_unpack($m);
+$f = $info['c'];
+
+if ($f & self::GZ) {
+if (!function_exists('gzinflate')) {
+die('Error: zlib extension is not enabled -' .
+' gzinflate() function needed for zlib-compressed .phars');
+}
+}
+
+if ($f & self::BZ2) {
+if (!function_exists('bzdecompress')) {
+die('Error: bzip2 extension is not enabled -' .
+' bzdecompress() function needed for bz2-compressed .phars');
+}
+}
+
+$temp = self::tmpdir();
+
+if (!$temp || !is_writable($temp)) {
+$sessionpath = session_save_path();
+if (strpos ($sessionpath, ";") !== false)
+$sessionpath = substr ($sessionpath, strpos ($sessionpath, ";")+1);
+if (!file_exists($sessionpath) || !is_dir($sessionpath)) {
+die('Could not locate temporary directory to extract phar');
+}
+$temp = $sessionpath;
+}
+
+$temp .= '/pharextract/'.basename(__FILE__, '.phar');
+self::$temp = $temp;
+self::$origdir = getcwd();
+@mkdir($temp, 0777, true);
+$temp = realpath($temp);
+
+if (!file_exists($temp . DIRECTORY_SEPARATOR . md5_file(__FILE__))) {
+self::_removeTmpFiles($temp, getcwd());
+@mkdir($temp, 0777, true);
+@file_put_contents($temp . '/' . md5_file(__FILE__), '');
+
+foreach ($info['m'] as $path => $file) {
+$a = !file_exists(dirname($temp . '/' . $path));
+@mkdir(dirname($temp . '/' . $path), 0777, true);
+clearstatcache();
+
+if ($path[strlen($path) - 1] == '/') {
+@mkdir($temp . '/' . $path, 0777);
+} else {
+file_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));
+@chmod($temp . '/' . $path, 0666);
+}
+}
+}
+
+chdir($temp);
+
+if (!$return) {
+include self::START;
+}
+}
+
+static function tmpdir()
+{
+if (strpos(PHP_OS, 'WIN') !== false) {
+if ($var = getenv('TMP') ? getenv('TMP') : getenv('TEMP')) {
+return $var;
+}
+if (is_dir('/temp') || mkdir('/temp')) {
+return realpath('/temp');
+}
+return false;
+}
+if ($var = getenv('TMPDIR')) {
+return $var;
+}
+return realpath('/tmp');
+}
+
+static function _unpack($m)
+{
+$info = unpack('V', substr($m, 0, 4));
+ $l = unpack('V', substr($m, 10, 4));
+$m = substr($m, 14 + $l[1]);
+$s = unpack('V', substr($m, 0, 4));
+$o = 0;
+$start = 4 + $s[1];
+$ret['c'] = 0;
+
+for ($i = 0; $i < $info[1]; $i++) {
+ $len = unpack('V', substr($m, $start, 4));
+$start += 4;
+ $savepath = substr($m, $start, $len[1]);
+$start += $len[1];
+   $ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24)));
+$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3]
+& 0xffffffff);
+$ret['m'][$savepath][7] = $o;
+$o += $ret['m'][$savepath][2];
+$start += 24 + $ret['m'][$savepath][5];
+$ret['c'] |= $ret['m'][$savepath][4] & self::MASK;
+}
+return $ret;
+}
+
+static function extractFile($path, $entry, $fp)
+{
+$data = '';
+$c = $entry[2];
+
+while ($c) {
+if ($c < 8192) {
+$data .= @fread($fp, $c);
+$c = 0;
+} else {
+$c -= 8192;
+$data .= @fread($fp, 8192);
+}
+}
+
+if ($entry[4] & self::GZ) {
+$data = gzinflate($data);
+} elseif ($entry[4] & self::BZ2) {
+$data = bzdecompress($data);
+}
+
+if (strlen($data) != $entry[0]) {
+die("Invalid internal .phar file (size error " . strlen($data) . " != " .
+$stat[7] . ")");
+}
+
+if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) {
+die("Invalid internal .phar file (checksum error)");
+}
+
+return $data;
+}
+
+static function _removeTmpFiles($temp, $origdir)
+{
+chdir($temp);
+
+foreach (glob('*') as $f) {
+if (file_exists($f)) {
+is_dir($f) ? @rmdir($f) : @unlink($f);
+if (file_exists($f) && is_dir($f)) {
+self::_removeTmpFiles($f, getcwd());
+}
+}
+}
+
+@rmdir($temp);
+clearstatcache();
+chdir($origdir);
+}
+}
+
+Extract_Phar::go();
+__HALT_COMPILER(); ?>  
+          random_compat.phar       byte_safe_strings.phpU  ´BÅZU  
+ãÆ¶         cast_to_int.phpF
+  ´BÅZF
+  :)û%¶         error_polyfill.php¡  ´BÅZ¡  "]¶      	   index.phpM  ´BÅZM  t:•Ä¶         random_bytes_com_dotnet.phpW  ´BÅZW  ¡@¶         random_bytes_dev_urandom.php@  ´BÅZ@  Ù*‘ã¶         random_bytes_libsodium.php  ´BÅZ  Ñ;[c¶      !   random_bytes_libsodium_legacy.phpN  ´BÅZN  ƒ^L¶         random_bytes_mcrypt.phpÙ	  ´BÅZÙ	  ¯BS7¶         random_int.phpv  ´BÅZv  ôÍâ¶      <?php
+/**
+ * Random_* Compatibility Library
+ * for using the new PHP 7 random_* API in PHP 5 projects
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+if (!is_callable('RandomCompat_strlen')) {
+    if (
+        defined('MB_OVERLOAD_STRING') &&
+        ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING
+    ) {
+        /**
+         * strlen() implementation that isn't brittle to mbstring.func_overload
+         *
+         * This version uses mb_strlen() in '8bit' mode to treat strings as raw
+         * binary rather than UTF-8, ISO-8859-1, etc
+         *
+         * @param string $binary_string
+         *
+         * @throws TypeError
+         *
+         * @return int
+         */
+        function RandomCompat_strlen($binary_string)
+        {
+            if (!is_string($binary_string)) {
+                throw new TypeError(
+                    'RandomCompat_strlen() expects a string'
+                );
+            }
+
+            return (int) mb_strlen($binary_string, '8bit');
+        }
+
+    } else {
+        /**
+         * strlen() implementation that isn't brittle to mbstring.func_overload
+         *
+         * This version just used the default strlen()
+         *
+         * @param string $binary_string
+         *
+         * @throws TypeError
+         *
+         * @return int
+         */
+        function RandomCompat_strlen($binary_string)
+        {
+            if (!is_string($binary_string)) {
+                throw new TypeError(
+                    'RandomCompat_strlen() expects a string'
+                );
+            }
+            return (int) strlen($binary_string);
+        }
+    }
+}
+
+if (!is_callable('RandomCompat_substr')) {
+
+    if (
+        defined('MB_OVERLOAD_STRING')
+        &&
+        ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING
+    ) {
+        /**
+         * substr() implementation that isn't brittle to mbstring.func_overload
+         *
+         * This version uses mb_substr() in '8bit' mode to treat strings as raw
+         * binary rather than UTF-8, ISO-8859-1, etc
+         *
+         * @param string $binary_string
+         * @param int $start
+         * @param int $length (optional)
+         *
+         * @throws TypeError
+         *
+         * @return string
+         */
+        function RandomCompat_substr($binary_string, $start, $length = null)
+        {
+            if (!is_string($binary_string)) {
+                throw new TypeError(
+                    'RandomCompat_substr(): First argument should be a string'
+                );
+            }
+
+            if (!is_int($start)) {
+                throw new TypeError(
+                    'RandomCompat_substr(): Second argument should be an integer'
+                );
+            }
+
+            if ($length === null) {
+                /**
+                 * mb_substr($str, 0, NULL, '8bit') returns an empty string on
+                 * PHP 5.3, so we have to find the length ourselves.
+                 */
+                $length = RandomCompat_strlen($binary_string) - $start;
+            } elseif (!is_int($length)) {
+                throw new TypeError(
+                    'RandomCompat_substr(): Third argument should be an integer, or omitted'
+                );
+            }
+
+            // Consistency with PHP's behavior
+            if ($start === RandomCompat_strlen($binary_string) && $length === 0) {
+                return '';
+            }
+            if ($start > RandomCompat_strlen($binary_string)) {
+                return '';
+            }
+
+            return (string) mb_substr($binary_string, $start, $length, '8bit');
+        }
+
+    } else {
+
+        /**
+         * substr() implementation that isn't brittle to mbstring.func_overload
+         *
+         * This version just uses the default substr()
+         *
+         * @param string $binary_string
+         * @param int $start
+         * @param int $length (optional)
+         *
+         * @throws TypeError
+         *
+         * @return string
+         */
+        function RandomCompat_substr($binary_string, $start, $length = null)
+        {
+            if (!is_string($binary_string)) {
+                throw new TypeError(
+                    'RandomCompat_substr(): First argument should be a string'
+                );
+            }
+
+            if (!is_int($start)) {
+                throw new TypeError(
+                    'RandomCompat_substr(): Second argument should be an integer'
+                );
+            }
+
+            if ($length !== null) {
+                if (!is_int($length)) {
+                    throw new TypeError(
+                        'RandomCompat_substr(): Third argument should be an integer, or omitted'
+                    );
+                }
+
+                return (string) substr($binary_string, $start, $length);
+            }
+
+            return (string) substr($binary_string, $start);
+        }
+    }
+}
+<?php
+/**
+ * Random_* Compatibility Library
+ * for using the new PHP 7 random_* API in PHP 5 projects
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+if (!is_callable('RandomCompat_intval')) {
+    
+    /**
+     * Cast to an integer if we can, safely.
+     * 
+     * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
+     * (non-inclusive), it will sanely cast it to an int. If you it's equal to
+     * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats 
+     * lose precision, so the <= and => operators might accidentally let a float
+     * through.
+     * 
+     * @param int|float $number    The number we want to convert to an int
+     * @param bool      $fail_open Set to true to not throw an exception
+     * 
+     * @return float|int
+     * @psalm-suppress InvalidReturnType
+     *
+     * @throws TypeError
+     */
+    function RandomCompat_intval($number, $fail_open = false)
+    {
+        if (is_int($number) || is_float($number)) {
+            $number += 0;
+        } elseif (is_numeric($number)) {
+            $number += 0;
+        }
+
+        if (
+            is_float($number)
+            &&
+            $number > ~PHP_INT_MAX
+            &&
+            $number < PHP_INT_MAX
+        ) {
+            $number = (int) $number;
+        }
+
+        if (is_int($number)) {
+            return (int) $number;
+        } elseif (!$fail_open) {
+            throw new TypeError(
+                'Expected an integer.'
+            );
+        }
+        return $number;
+    }
+}
+<?php
+/**
+ * Random_* Compatibility Library 
+ * for using the new PHP 7 random_* API in PHP 5 projects
+ * 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+if (!class_exists('Error', false)) {
+    // We can't really avoid making this extend Exception in PHP 5.
+    class Error extends Exception
+    {
+        
+    }
+}
+
+if (!class_exists('TypeError', false)) {
+    if (is_subclass_of('Error', 'Exception')) {
+        class TypeError extends Error
+        {
+            
+        }
+    } else {
+        class TypeError extends Exception
+        {
+            
+        }
+    }
+}
+<?php
+/**
+ * Random_* Compatibility Library
+ * for using the new PHP 7 random_* API in PHP 5 projects
+ *
+ * @version 2.0.10
+ * @released 2017-03-13
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+if (!defined('PHP_VERSION_ID')) {
+    // This constant was introduced in PHP 5.2.7
+    $RandomCompatversion = array_map('intval', explode('.', PHP_VERSION));
+    define(
+        'PHP_VERSION_ID',
+        $RandomCompatversion[0] * 10000
+        + $RandomCompatversion[1] * 100
+        + $RandomCompatversion[2]
+    );
+    $RandomCompatversion = null;
+}
+
+/**
+ * PHP 7.0.0 and newer have these functions natively.
+ */
+if (PHP_VERSION_ID >= 70000) {
+    return;
+}
+
+if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
+    define('RANDOM_COMPAT_READ_BUFFER', 8);
+}
+
+$RandomCompatDIR = dirname(__FILE__);
+
+require_once $RandomCompatDIR . '/byte_safe_strings.php';
+require_once $RandomCompatDIR . '/cast_to_int.php';
+require_once $RandomCompatDIR . '/error_polyfill.php';
+
+if (!is_callable('random_bytes')) {
+    /**
+     * PHP 5.2.0 - 5.6.x way to implement random_bytes()
+     *
+     * We use conditional statements here to define the function in accordance
+     * to the operating environment. It's a micro-optimization.
+     *
+     * In order of preference:
+     *   1. Use libsodium if available.
+     *   2. fread() /dev/urandom if available (never on Windows)
+     *   3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)
+     *   4. COM('CAPICOM.Utilities.1')->GetRandom()
+     *
+     * See RATIONALE.md for our reasoning behind this particular order
+     */
+    if (extension_loaded('libsodium')) {
+        // See random_bytes_libsodium.php
+        if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) {
+            require_once $RandomCompatDIR . '/random_bytes_libsodium.php';
+        } elseif (method_exists('Sodium', 'randombytes_buf')) {
+            require_once $RandomCompatDIR . '/random_bytes_libsodium_legacy.php';
+        }
+    }
+
+    /**
+     * Reading directly from /dev/urandom:
+     */
+    if (DIRECTORY_SEPARATOR === '/') {
+        // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast
+        // way to exclude Windows.
+        $RandomCompatUrandom = true;
+        $RandomCompat_basedir = ini_get('open_basedir');
+
+        if (!empty($RandomCompat_basedir)) {
+            $RandomCompat_open_basedir = explode(
+                PATH_SEPARATOR,
+                strtolower($RandomCompat_basedir)
+            );
+            $RandomCompatUrandom = (array() !== array_intersect(
+                array('/dev', '/dev/', '/dev/urandom'),
+                $RandomCompat_open_basedir
+            ));
+            $RandomCompat_open_basedir = null;
+        }
+
+        if (
+            !is_callable('random_bytes')
+            &&
+            $RandomCompatUrandom
+            &&
+            @is_readable('/dev/urandom')
+        ) {
+            // Error suppression on is_readable() in case of an open_basedir
+            // or safe_mode failure. All we care about is whether or not we
+            // can read it at this point. If the PHP environment is going to
+            // panic over trying to see if the file can be read in the first
+            // place, that is not helpful to us here.
+
+            // See random_bytes_dev_urandom.php
+            require_once $RandomCompatDIR . '/random_bytes_dev_urandom.php';
+        }
+        // Unset variables after use
+        $RandomCompat_basedir = null;
+    } else {
+        $RandomCompatUrandom = false;
+    }
+
+    /**
+     * mcrypt_create_iv()
+     *
+     * We only want to use mcypt_create_iv() if:
+     *
+     * - random_bytes() hasn't already been defined
+     * - the mcrypt extensions is loaded
+     * - One of these two conditions is true:
+     *   - We're on Windows (DIRECTORY_SEPARATOR !== '/')
+     *   - We're not on Windows and /dev/urandom is readabale
+     *     (i.e. we're not in a chroot jail)
+     * - Special case:
+     *   - If we're not on Windows, but the PHP version is between
+     *     5.6.10 and 5.6.12, we don't want to use mcrypt. It will
+     *     hang indefinitely. This is bad.
+     *   - If we're on Windows, we want to use PHP >= 5.3.7 or else
+     *     we get insufficient entropy errors.
+     */
+    if (
+        !is_callable('random_bytes')
+        &&
+        // Windows on PHP < 5.3.7 is broken, but non-Windows is not known to be.
+        (DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307)
+        &&
+        // Prevent this code from hanging indefinitely on non-Windows;
+        // see https://bugs.php.net/bug.php?id=69833
+        (
+            DIRECTORY_SEPARATOR !== '/' ||
+            (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613)
+        )
+        &&
+        extension_loaded('mcrypt')
+    ) {
+        // See random_bytes_mcrypt.php
+        require_once $RandomCompatDIR . '/random_bytes_mcrypt.php';
+    }
+    $RandomCompatUrandom = null;
+
+    /**
+     * This is a Windows-specific fallback, for when the mcrypt extension
+     * isn't loaded.
+     */
+    if (
+        !is_callable('random_bytes')
+        &&
+        extension_loaded('com_dotnet')
+        &&
+        class_exists('COM')
+    ) {
+        $RandomCompat_disabled_classes = preg_split(
+            '#\s*,\s*#',
+            strtolower(ini_get('disable_classes'))
+        );
+
+        if (!in_array('com', $RandomCompat_disabled_classes)) {
+            try {
+                $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
+                if (method_exists($RandomCompatCOMtest, 'GetRandom')) {
+                    // See random_bytes_com_dotnet.php
+                    require_once $RandomCompatDIR . '/random_bytes_com_dotnet.php';
+                }
+            } catch (com_exception $e) {
+                // Don't try to use it.
+            }
+        }
+        $RandomCompat_disabled_classes = null;
+        $RandomCompatCOMtest = null;
+    }
+
+    /**
+     * throw new Exception
+     */
+    if (!is_callable('random_bytes')) {
+        /**
+         * We don't have any more options, so let's throw an exception right now
+         * and hope the developer won't let it fail silently.
+         *
+         * @param mixed $length
+         * @psalm-suppress MissingReturnType
+         * @throws Exception
+         * @return string
+         */
+        function random_bytes($length)
+        {
+            unset($length); // Suppress "variable not used" warnings.
+            throw new Exception(
+                'There is no suitable CSPRNG installed on your system'
+            );
+            return '';
+        }
+    }
+}
+
+if (!is_callable('random_int')) {
+    require_once $RandomCompatDIR . '/random_int.php';
+}
+
+$RandomCompatDIR = null;
+<?php
+/**
+ * Random_* Compatibility Library 
+ * for using the new PHP 7 random_* API in PHP 5 projects
+ * 
+ * The MIT License (MIT)
+ * 
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+if (!is_callable('random_bytes')) {
+    /**
+     * Windows with PHP < 5.3.0 will not have the function
+     * openssl_random_pseudo_bytes() available, so let's use
+     * CAPICOM to work around this deficiency.
+     *
+     * @param int $bytes
+     *
+     * @throws Exception
+     *
+     * @return string
+     */
+    function random_bytes($bytes)
+    {
+        try {
+            $bytes = RandomCompat_intval($bytes);
+        } catch (TypeError $ex) {
+            throw new TypeError(
+                'random_bytes(): $bytes must be an integer'
+            );
+        }
+
+        if ($bytes < 1) {
+            throw new Error(
+                'Length must be greater than 0'
+            );
+        }
+
+        $buf = '';
+        if (!class_exists('COM')) {
+            throw new Error(
+                'COM does not exist'
+            );
+        }
+        $util = new COM('CAPICOM.Utilities.1');
+        $execCount = 0;
+
+        /**
+         * Let's not let it loop forever. If we run N times and fail to
+         * get N bytes of random data, then CAPICOM has failed us.
+         */
+        do {
+            $buf .= base64_decode($util->GetRandom($bytes, 0));
+            if (RandomCompat_strlen($buf) >= $bytes) {
+                /**
+                 * Return our random entropy buffer here:
+                 */
+                return RandomCompat_substr($buf, 0, $bytes);
+            }
+            ++$execCount;
+        } while ($execCount < $bytes);
+
+        /**
+         * If we reach here, PHP has failed us.
+         */
+        throw new Exception(
+            'Could not gather sufficient random data'
+        );
+    }
+}<?php
+/**
+ * Random_* Compatibility Library 
+ * for using the new PHP 7 random_* API in PHP 5 projects
+ * 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
+    define('RANDOM_COMPAT_READ_BUFFER', 8);
+}
+
+if (!is_callable('random_bytes')) {
+    /**
+     * Unless open_basedir is enabled, use /dev/urandom for
+     * random numbers in accordance with best practices
+     *
+     * Why we use /dev/urandom and not /dev/random
+     * @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers
+     *
+     * @param int $bytes
+     *
+     * @throws Exception
+     *
+     * @return string
+     */
+    function random_bytes($bytes)
+    {
+        static $fp = null;
+        /**
+         * This block should only be run once
+         */
+        if (empty($fp)) {
+            /**
+             * We use /dev/urandom if it is a char device.
+             * We never fall back to /dev/random
+             */
+            $fp = fopen('/dev/urandom', 'rb');
+            if (!empty($fp)) {
+                $st = fstat($fp);
+                if (($st['mode'] & 0170000) !== 020000) {
+                    fclose($fp);
+                    $fp = false;
+                }
+            }
+
+            if (!empty($fp)) {
+                /**
+                 * stream_set_read_buffer() does not exist in HHVM
+                 *
+                 * If we don't set the stream's read buffer to 0, PHP will
+                 * internally buffer 8192 bytes, which can waste entropy
+                 *
+                 * stream_set_read_buffer returns 0 on success
+                 */
+                if (is_callable('stream_set_read_buffer')) {
+                    stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER);
+                }
+                if (is_callable('stream_set_chunk_size')) {
+                    stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER);
+                }
+            }
+        }
+
+        try {
+            $bytes = RandomCompat_intval($bytes);
+        } catch (TypeError $ex) {
+            throw new TypeError(
+                'random_bytes(): $bytes must be an integer'
+            );
+        }
+
+        if ($bytes < 1) {
+            throw new Error(
+                'Length must be greater than 0'
+            );
+        }
+
+        /**
+         * This if() block only runs if we managed to open a file handle
+         *
+         * It does not belong in an else {} block, because the above
+         * if (empty($fp)) line is logic that should only be run once per
+         * page load.
+         */
+        if (!empty($fp)) {
+            /**
+             * @var int
+             */
+            $remaining = $bytes;
+
+            /**
+             * @var string|bool
+             */
+            $buf = '';
+
+            /**
+             * We use fread() in a loop to protect against partial reads
+             */
+            do {
+                /**
+                 * @var string|bool
+                 */
+                $read = fread($fp, $remaining);
+                if (!is_string($read)) {
+                    if ($read === false) {
+                        /**
+                         * We cannot safely read from the file. Exit the
+                         * do-while loop and trigger the exception condition
+                         *
+                         * @var string|bool
+                         */
+                        $buf = false;
+                        break;
+                    }
+                }
+                /**
+                 * Decrease the number of bytes returned from remaining
+                 */
+                $remaining -= RandomCompat_strlen($read);
+                /**
+                 * @var string|bool
+                 */
+                $buf = $buf . $read;
+            } while ($remaining > 0);
+
+            /**
+             * Is our result valid?
+             */
+            if (is_string($buf)) {
+                if (RandomCompat_strlen($buf) === $bytes) {
+                    /**
+                     * Return our random entropy buffer here:
+                     */
+                    return $buf;
+                }
+            }
+        }
+
+        /**
+         * If we reach here, PHP has failed us.
+         */
+        throw new Exception(
+            'Error reading from source device'
+        );
+    }
+}
+<?php
+/**
+ * Random_* Compatibility Library 
+ * for using the new PHP 7 random_* API in PHP 5 projects
+ * 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+if (!is_callable('random_bytes')) {
+    /**
+     * If the libsodium PHP extension is loaded, we'll use it above any other
+     * solution.
+     *
+     * libsodium-php project:
+     * @ref https://github.com/jedisct1/libsodium-php
+     *
+     * @param int $bytes
+     *
+     * @throws Exception
+     *
+     * @return string
+     */
+    function random_bytes($bytes)
+    {
+        try {
+            $bytes = RandomCompat_intval($bytes);
+        } catch (TypeError $ex) {
+            throw new TypeError(
+                'random_bytes(): $bytes must be an integer'
+            );
+        }
+
+        if ($bytes < 1) {
+            throw new Error(
+                'Length must be greater than 0'
+            );
+        }
+
+        /**
+         * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
+         * generated in one invocation.
+         */
+        if ($bytes > 2147483647) {
+            $buf = '';
+            for ($i = 0; $i < $bytes; $i += 1073741824) {
+                $n = ($bytes - $i) > 1073741824
+                    ? 1073741824
+                    : $bytes - $i;
+                $buf .= \Sodium\randombytes_buf($n);
+            }
+        } else {
+            $buf = \Sodium\randombytes_buf($bytes);
+        }
+
+        if ($buf !== false) {
+            if (RandomCompat_strlen($buf) === $bytes) {
+                return $buf;
+            }
+        }
+
+        /**
+         * If we reach here, PHP has failed us.
+         */
+        throw new Exception(
+            'Could not gather sufficient random data'
+        );
+    }
+}
+<?php
+/**
+ * Random_* Compatibility Library 
+ * for using the new PHP 7 random_* API in PHP 5 projects
+ * 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+if (!is_callable('random_bytes')) {
+    /**
+     * If the libsodium PHP extension is loaded, we'll use it above any other
+     * solution.
+     *
+     * libsodium-php project:
+     * @ref https://github.com/jedisct1/libsodium-php
+     *
+     * @param int $bytes
+     *
+     * @throws Exception
+     *
+     * @return string
+     */
+    function random_bytes($bytes)
+    {
+        try {
+            $bytes = RandomCompat_intval($bytes);
+        } catch (TypeError $ex) {
+            throw new TypeError(
+                'random_bytes(): $bytes must be an integer'
+            );
+        }
+
+        if ($bytes < 1) {
+            throw new Error(
+                'Length must be greater than 0'
+            );
+        }
+
+        /**
+         * @var string
+         */
+        $buf = '';
+
+        /**
+         * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
+         * generated in one invocation.
+         */
+        if ($bytes > 2147483647) {
+            for ($i = 0; $i < $bytes; $i += 1073741824) {
+                $n = ($bytes - $i) > 1073741824
+                    ? 1073741824
+                    : $bytes - $i;
+                $buf .= Sodium::randombytes_buf((int) $n);
+            }
+        } else {
+            $buf .= Sodium::randombytes_buf((int) $bytes);
+        }
+
+        if (is_string($buf)) {
+            if (RandomCompat_strlen($buf) === $bytes) {
+                return $buf;
+            }
+        }
+
+        /**
+         * If we reach here, PHP has failed us.
+         */
+        throw new Exception(
+            'Could not gather sufficient random data'
+        );
+    }
+}
+<?php
+/**
+ * Random_* Compatibility Library 
+ * for using the new PHP 7 random_* API in PHP 5 projects
+ * 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+if (!is_callable('random_bytes')) {
+    /**
+     * Powered by ext/mcrypt (and thankfully NOT libmcrypt)
+     *
+     * @ref https://bugs.php.net/bug.php?id=55169
+     * @ref https://github.com/php/php-src/blob/c568ffe5171d942161fc8dda066bce844bdef676/ext/mcrypt/mcrypt.c#L1321-L1386
+     *
+     * @param int $bytes
+     *
+     * @throws Exception
+     *
+     * @return string
+     */
+    function random_bytes($bytes)
+    {
+        try {
+            $bytes = RandomCompat_intval($bytes);
+        } catch (TypeError $ex) {
+            throw new TypeError(
+                'random_bytes(): $bytes must be an integer'
+            );
+        }
+
+        if ($bytes < 1) {
+            throw new Error(
+                'Length must be greater than 0'
+            );
+        }
+
+        $buf = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
+        if (
+            $buf !== false
+            &&
+            RandomCompat_strlen($buf) === $bytes
+        ) {
+            /**
+             * Return our random entropy buffer here:
+             */
+            return $buf;
+        }
+
+        /**
+         * If we reach here, PHP has failed us.
+         */
+        throw new Exception(
+            'Could not gather sufficient random data'
+        );
+    }
+}
+<?php
+
+if (!is_callable('random_int')) {
+    /**
+     * Random_* Compatibility Library
+     * for using the new PHP 7 random_* API in PHP 5 projects
+     *
+     * The MIT License (MIT)
+     *
+     * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
+     *
+     * Permission is hereby granted, free of charge, to any person obtaining a copy
+     * of this software and associated documentation files (the "Software"), to deal
+     * in the Software without restriction, including without limitation the rights
+     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+     * copies of the Software, and to permit persons to whom the Software is
+     * furnished to do so, subject to the following conditions:
+     *
+     * The above copyright notice and this permission notice shall be included in
+     * all copies or substantial portions of the Software.
+     *
+     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+     * SOFTWARE.
+     */
+
+    /**
+     * Fetch a random integer between $min and $max inclusive
+     *
+     * @param int $min
+     * @param int $max
+     *
+     * @throws Exception
+     *
+     * @return int
+     */
+    function random_int($min, $max)
+    {
+        /**
+         * Type and input logic checks
+         *
+         * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
+         * (non-inclusive), it will sanely cast it to an int. If you it's equal to
+         * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
+         * lose precision, so the <= and => operators might accidentally let a float
+         * through.
+         */
+
+        try {
+            $min = RandomCompat_intval($min);
+        } catch (TypeError $ex) {
+            throw new TypeError(
+                'random_int(): $min must be an integer'
+            );
+        }
+
+        try {
+            $max = RandomCompat_intval($max);
+        } catch (TypeError $ex) {
+            throw new TypeError(
+                'random_int(): $max must be an integer'
+            );
+        }
+
+        /**
+         * Now that we've verified our weak typing system has given us an integer,
+         * let's validate the logic then we can move forward with generating random
+         * integers along a given range.
+         */
+        if ($min > $max) {
+            throw new Error(
+                'Minimum value must be less than or equal to the maximum value'
+            );
+        }
+
+        if ($max === $min) {
+            return (int) $min;
+        }
+
+        /**
+         * Initialize variables to 0
+         *
+         * We want to store:
+         * $bytes => the number of random bytes we need
+         * $mask => an integer bitmask (for use with the &) operator
+         *          so we can minimize the number of discards
+         */
+        $attempts = $bits = $bytes = $mask = $valueShift = 0;
+
+        /**
+         * At this point, $range is a positive number greater than 0. It might
+         * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to
+         * a float and we will lose some precision.
+         */
+        $range = $max - $min;
+
+        /**
+         * Test for integer overflow:
+         */
+        if (!is_int($range)) {
+
+            /**
+             * Still safely calculate wider ranges.
+             * Provided by @CodesInChaos, @oittaa
+             *
+             * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435
+             *
+             * We use ~0 as a mask in this case because it generates all 1s
+             *
+             * @ref https://eval.in/400356 (32-bit)
+             * @ref http://3v4l.org/XX9r5  (64-bit)
+             */
+            $bytes = PHP_INT_SIZE;
+            $mask = ~0;
+
+        } else {
+
+            /**
+             * $bits is effectively ceil(log($range, 2)) without dealing with
+             * type juggling
+             */
+            while ($range > 0) {
+                if ($bits % 8 === 0) {
+                    ++$bytes;
+                }
+                ++$bits;
+                $range >>= 1;
+                $mask = $mask << 1 | 1;
+            }
+            $valueShift = $min;
+        }
+
+        $val = 0;
+        /**
+         * Now that we have our parameters set up, let's begin generating
+         * random integers until one falls between $min and $max
+         */
+        do {
+            /**
+             * The rejection probability is at most 0.5, so this corresponds
+             * to a failure probability of 2^-128 for a working RNG
+             */
+            if ($attempts > 128) {
+                throw new Exception(
+                    'random_int: RNG is broken - too many rejections'
+                );
+            }
+
+            /**
+             * Let's grab the necessary number of random bytes
+             */
+            $randomByteString = random_bytes($bytes);
+
+            /**
+             * Let's turn $randomByteString into an integer
+             *
+             * This uses bitwise operators (<< and |) to build an integer
+             * out of the values extracted from ord()
+             *
+             * Example: [9F] | [6D] | [32] | [0C] =>
+             *   159 + 27904 + 3276800 + 201326592 =>
+             *   204631455
+             */
+            $val &= 0;
+            for ($i = 0; $i < $bytes; ++$i) {
+                $val |= ord($randomByteString[$i]) << ($i * 8);
+            }
+
+            /**
+             * Apply mask
+             */
+            $val &= $mask;
+            $val += $valueShift;
+
+            ++$attempts;
+            /**
+             * If $val overflows to a floating point number,
+             * ... or is larger than $max,
+             * ... or smaller than $min,
+             * then try again.
+             */
+        } while (!is_int($val) || $val > $max || $val < $min);
+
+        return (int) $val;
+    }
+}
+0e1 é¶hìUúc\H7€ÉlOS‘=ð˜©áÊ2ìE³!¼ù ÈS$5¿øåË#Œ Åà4‡”0!”Ôf‹O‡¥©ËZG©ÕáŒy>(ê$Òwšº¾Û(\ÔH°Z-”íÝ¬‡¯-vÖg      GBMB
\ No newline at end of file
diff -pruN 3.0.2-2/lib/random_compat.phar.pubkey 3.2-2/lib/random_compat.phar.pubkey
--- 3.0.2-2/lib/random_compat.phar.pubkey	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/random_compat.phar.pubkey	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,5 @@
+-----BEGIN PUBLIC KEY-----
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEEd+wCqJDrx5B4OldM0dQE0ZMX+lx1ZWm
+pui0SUqD4G29L3NGsz9UhJ/0HjBdbnkhIK5xviT0X5vtjacF6ajgcCArbTB+ds+p
++h7Q084NuSuIpNb6YPfoUFgC/CL9kAoc
+-----END PUBLIC KEY-----
diff -pruN 3.0.2-2/lib/random_compat.txt 3.2-2/lib/random_compat.txt
--- 3.0.2-2/lib/random_compat.txt	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/random_compat.txt	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,4 @@
+Downloaded on 2018/04/29.
+
+https://github.com/paragonie/random_compat/releases/download/v2.0.12/random_compat.phar.pubkey
+https://github.com/paragonie/random_compat/releases/download/v2.0.12/random_compat.phar
diff -pruN 3.0.2-2/lib/smarty/COPYING.lib 3.2-2/lib/smarty/COPYING.lib
--- 3.0.2-2/lib/smarty/COPYING.lib	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/COPYING.lib	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
\ No newline at end of file
diff -pruN 3.0.2-2/lib/smarty/libs/Autoloader.php 3.2-2/lib/smarty/libs/Autoloader.php
--- 3.0.2-2/lib/smarty/libs/Autoloader.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/Autoloader.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Smarty Autoloader
+ *
+ * @package    Smarty
+ */
+
+/**
+ * Smarty Autoloader
+ *
+ * @package    Smarty
+ * @author     Uwe Tews
+ *             Usage:
+ *                  require_once '...path/Autoloader.php';
+ *                  Smarty_Autoloader::register();
+ *             or
+ *                  include '...path/bootstrap.php';
+ *
+ *                  $smarty = new Smarty();
+ */
+class Smarty_Autoloader
+{
+   /**
+     * Filepath to Smarty root
+     *
+     * @var string
+     */
+    public static $SMARTY_DIR = null;
+
+    /**
+     * Filepath to Smarty internal plugins
+     *
+     * @var string
+     */
+    public static $SMARTY_SYSPLUGINS_DIR = null;
+
+    /**
+     * Array with Smarty core classes and their filename
+     *
+     * @var array
+     */
+    public static $rootClasses = array('smarty' => 'Smarty.class.php', 'smartybc' => 'SmartyBC.class.php',);
+
+    /**
+     * Registers Smarty_Autoloader backward compatible to older installations.
+     *
+     * @param bool $prepend Whether to prepend the autoloader or not.
+     */
+    public static function registerBC($prepend = false)
+    {
+        /**
+         * register the class autoloader
+         */
+        if (!defined('SMARTY_SPL_AUTOLOAD')) {
+            define('SMARTY_SPL_AUTOLOAD', 0);
+        }
+        if (SMARTY_SPL_AUTOLOAD &&
+            set_include_path(get_include_path() . PATH_SEPARATOR . SMARTY_SYSPLUGINS_DIR) !== false
+        ) {
+            $registeredAutoLoadFunctions = spl_autoload_functions();
+            if (!isset($registeredAutoLoadFunctions[ 'spl_autoload' ])) {
+                spl_autoload_register();
+            }
+        } else {
+            self::register($prepend);
+        }
+    }
+
+    /**
+     * Registers Smarty_Autoloader as an SPL autoloader.
+     *
+     * @param bool $prepend Whether to prepend the autoloader or not.
+     */
+    public static function register($prepend = false)
+    {
+        self::$SMARTY_DIR = defined('SMARTY_DIR') ? SMARTY_DIR : dirname(__FILE__) . DIRECTORY_SEPARATOR;
+        self::$SMARTY_SYSPLUGINS_DIR = defined('SMARTY_SYSPLUGINS_DIR') ? SMARTY_SYSPLUGINS_DIR :
+            self::$SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR;
+        if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
+            spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
+        } else {
+            spl_autoload_register(array(__CLASS__, 'autoload'));
+        }
+    }
+
+    /**
+     * Handles auto loading of classes.
+     *
+     * @param string $class A class name.
+     */
+    public static function autoload($class)
+    {
+        if ($class[ 0 ] !== 'S' && strpos($class, 'Smarty') !== 0) {
+            return;
+        }
+        $_class = strtolower($class);
+        if (isset(self::$rootClasses[ $_class ])) {
+            $file = self::$SMARTY_DIR . self::$rootClasses[ $_class ];
+            if (is_file($file)) {
+                include $file;
+            }
+        } else {
+            $file = self::$SMARTY_SYSPLUGINS_DIR . $_class . '.php';
+            if (is_file($file)) {
+                include $file;
+            }
+        }
+        return;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/bootstrap.php 3.2-2/lib/smarty/libs/bootstrap.php
--- 3.0.2-2/lib/smarty/libs/bootstrap.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/bootstrap.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,17 @@
+<?php
+/*
+ * This file is part of the Smarty package.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ * Load and register Smarty Autoloader
+ */
+if (!class_exists('Smarty_Autoloader')) {
+    require dirname(__FILE__) . '/Autoloader.php';
+}
+Smarty_Autoloader::register(true);
diff -pruN 3.0.2-2/lib/smarty/libs/debug.tpl 3.2-2/lib/smarty/libs/debug.tpl
--- 3.0.2-2/lib/smarty/libs/debug.tpl	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/debug.tpl	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,160 @@
+{capture name='_smarty_debug' assign=debug_output}
+    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+    <head>
+        <title>Smarty Debug Console</title>
+        <style type="text/css">
+            {literal}
+            body, h1, h2, h3, td, th, p {
+                font-family: sans-serif;
+                font-weight: normal;
+                font-size: 0.9em;
+                margin: 1px;
+                padding: 0;
+            }
+
+            h1 {
+                margin: 0;
+                text-align: left;
+                padding: 2px;
+                background-color: #f0c040;
+                color: black;
+                font-weight: bold;
+                font-size: 1.2em;
+            }
+
+            h2 {
+                background-color: #9B410E;
+                color: white;
+                text-align: left;
+                font-weight: bold;
+                padding: 2px;
+                border-top: 1px solid black;
+            }
+            h3 {
+                text-align: left;
+                font-weight: bold;
+                color: black;
+                font-size: 0.7em;
+                padding: 2px;
+            }
+
+            body {
+                background: black;
+            }
+
+            p, table, div {
+                background: #f0ead8;
+            }
+
+            p {
+                margin: 0;
+                font-style: italic;
+                text-align: center;
+            }
+
+            table {
+                width: 100%;
+            }
+
+            th, td {
+                font-family: monospace;
+                vertical-align: top;
+                text-align: left;
+            }
+
+            td {
+                color: green;
+            }
+
+            .odd {
+                background-color: #eeeeee;
+            }
+
+            .even {
+                background-color: #fafafa;
+            }
+
+            .exectime {
+                font-size: 0.8em;
+                font-style: italic;
+            }
+
+            #bold div {
+                color: black;
+                font-weight: bold;
+            }
+            #blue h3 {
+                color: blue;
+            }
+            #normal div {
+                color: black;
+                font-weight: normal;
+            }
+            #table_assigned_vars th {
+                color: blue;
+                font-weight: bold;
+            }
+
+            #table_config_vars th {
+                color: maroon;
+            }
+
+            {/literal}
+        </style>
+    </head>
+    <body>
+
+    <h1>Smarty {Smarty::SMARTY_VERSION} Debug Console
+        -  {if isset($template_name)}{$template_name|debug_print_var nofilter} {/if}{if !empty($template_data)}Total Time {$execution_time|string_format:"%.5f"}{/if}</h1>
+
+    {if !empty($template_data)}
+        <h2>included templates &amp; config files (load time in seconds)</h2>
+        <div>
+            {foreach $template_data as $template}
+                <font color=brown>{$template.name}</font>
+                <br>&nbsp;&nbsp;<span class="exectime">
+                (compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"})
+                 </span>
+                <br>
+            {/foreach}
+        </div>
+    {/if}
+
+    <h2>assigned template variables</h2>
+
+    <table id="table_assigned_vars">
+        {foreach $assigned_vars as $vars}
+            <tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
+                <td><h3><font color=blue>${$vars@key}</font></h3>
+                    {if isset($vars['nocache'])}<b>Nocache</b></br>{/if}
+                    {if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var nofilter}{/if}
+                </td>
+                <td><h3>Value</h3>{$vars['value']|debug_print_var:10:80 nofilter}</td>
+                <td>{if isset($vars['attributes'])}<h3>Attributes</h3>{$vars['attributes']|debug_print_var nofilter} {/if}</td>
+         {/foreach}
+    </table>
+
+    <h2>assigned config file variables</h2>
+
+    <table id="table_config_vars">
+        {foreach $config_vars as $vars}
+            <tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
+                <td><h3><font color=blue>#{$vars@key}#</font></h3>
+                    {if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var nofilter}{/if}
+                </td>
+                <td>{$vars['value']|debug_print_var:10:80 nofilter}</td>
+            </tr>
+        {/foreach}
+
+    </table>
+    </body>
+    </html>
+{/capture}
+<script type="text/javascript">
+    {$id = '__Smarty__'}
+    {if $display_mode}{$id = "$offset$template_name"|md5}{/if}
+    _smarty_console = window.open("", "console{$id}", "width=1024,height=600,left={$offset},top={$offset},resizable,scrollbars=yes");
+    _smarty_console.document.write("{$debug_output|escape:'javascript' nofilter}");
+    _smarty_console.document.close();
+</script>
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/block.textformat.php 3.2-2/lib/smarty/libs/plugins/block.textformat.php
--- 3.0.2-2/lib/smarty/libs/plugins/block.textformat.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/block.textformat.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Smarty plugin to format text blocks
+ *
+ * @package    Smarty
+ * @subpackage PluginsBlock
+ */
+/**
+ * Smarty {textformat}{/textformat} block plugin
+ * Type:     block function
+ * Name:     textformat
+ * Purpose:  format text a certain way with preset styles
+ *           or custom wrap/indent settings
+ * Params:
+ *
+ * - style         - string (email)
+ * - indent        - integer (0)
+ * - wrap          - integer (80)
+ * - wrap_char     - string ("\n")
+ * - indent_char   - string (" ")
+ * - wrap_boundary - boolean (true)
+ *
+ *
+ * @link   http://www.smarty.net/manual/en/language.function.textformat.php {textformat}
+ *         (Smarty online manual)
+ *
+ * @param array                    $params   parameters
+ * @param string                   $content  contents of the block
+ * @param Smarty_Internal_Template $template template object
+ * @param boolean                  &$repeat  repeat flag
+ *
+ * @return string content re-formatted
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @throws \SmartyException
+ */
+function smarty_block_textformat($params, $content, Smarty_Internal_Template $template, &$repeat)
+{
+    if (is_null($content)) {
+        return;
+    }
+    if (Smarty::$_MBSTRING) {
+        $template->_checkPlugins(array(array('function' => 'smarty_modifier_mb_wordwrap',
+                                             'file' => SMARTY_PLUGINS_DIR . 'modifier.mb_wordwrap.php')));
+    }
+
+    $style = null;
+    $indent = 0;
+    $indent_first = 0;
+    $indent_char = ' ';
+    $wrap = 80;
+    $wrap_char = "\n";
+    $wrap_cut = false;
+    $assign = null;
+
+    foreach ($params as $_key => $_val) {
+        switch ($_key) {
+            case 'style':
+            case 'indent_char':
+            case 'wrap_char':
+            case 'assign':
+                $$_key = (string) $_val;
+                break;
+
+            case 'indent':
+            case 'indent_first':
+            case 'wrap':
+                $$_key = (int) $_val;
+                break;
+
+            case 'wrap_cut':
+                $$_key = (bool) $_val;
+                break;
+
+            default:
+                trigger_error("textformat: unknown attribute '{$_key}'");
+        }
+    }
+
+    if ($style === 'email') {
+        $wrap = 72;
+    }
+    // split into paragraphs
+    $_paragraphs = preg_split('![\r\n]{2}!', $content);
+
+    foreach ($_paragraphs as &$_paragraph) {
+        if (!$_paragraph) {
+            continue;
+        }
+        // convert mult. spaces & special chars to single space
+        $_paragraph =
+            preg_replace(array('!\s+!' . Smarty::$_UTF8_MODIFIER,
+                               '!(^\s+)|(\s+$)!' . Smarty::$_UTF8_MODIFIER),
+                         array(' ',
+                               ''), $_paragraph);
+        // indent first line
+        if ($indent_first > 0) {
+            $_paragraph = str_repeat($indent_char, $indent_first) . $_paragraph;
+        }
+        // wordwrap sentences
+        if (Smarty::$_MBSTRING) {
+            $_paragraph = smarty_modifier_mb_wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut);
+        } else {
+            $_paragraph = wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut);
+        }
+        // indent lines
+        if ($indent > 0) {
+            $_paragraph = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraph);
+        }
+    }
+    $_output = implode($wrap_char . $wrap_char, $_paragraphs);
+
+    if ($assign) {
+        $template->assign($assign, $_output);
+    } else {
+        return $_output;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.counter.php 3.2-2/lib/smarty/libs/plugins/function.counter.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.counter.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.counter.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {counter} function plugin
+ * Type:     function
+ * Name:     counter
+ * Purpose:  print out a counter value
+ *
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @link   http://www.smarty.net/manual/en/language.function.counter.php {counter}
+ *         (Smarty online manual)
+ *
+ * @param array                    $params   parameters
+ * @param Smarty_Internal_Template $template template object
+ *
+ * @return string|null
+ */
+function smarty_function_counter($params, $template)
+{
+    static $counters = array();
+
+    $name = (isset($params[ 'name' ])) ? $params[ 'name' ] : 'default';
+    if (!isset($counters[ $name ])) {
+        $counters[ $name ] = array('start' => 1, 'skip' => 1, 'direction' => 'up', 'count' => 1);
+    }
+    $counter =& $counters[ $name ];
+
+    if (isset($params[ 'start' ])) {
+        $counter[ 'start' ] = $counter[ 'count' ] = (int) $params[ 'start' ];
+    }
+
+    if (!empty($params[ 'assign' ])) {
+        $counter[ 'assign' ] = $params[ 'assign' ];
+    }
+
+    if (isset($counter[ 'assign' ])) {
+        $template->assign($counter[ 'assign' ], $counter[ 'count' ]);
+    }
+
+    if (isset($params[ 'print' ])) {
+        $print = (bool) $params[ 'print' ];
+    } else {
+        $print = empty($counter[ 'assign' ]);
+    }
+
+    if ($print) {
+        $retval = $counter[ 'count' ];
+    } else {
+        $retval = null;
+    }
+
+    if (isset($params[ 'skip' ])) {
+        $counter[ 'skip' ] = $params[ 'skip' ];
+    }
+
+    if (isset($params[ 'direction' ])) {
+        $counter[ 'direction' ] = $params[ 'direction' ];
+    }
+
+    if ($counter[ 'direction' ] === 'down') {
+        $counter[ 'count' ] -= $counter[ 'skip' ];
+    } else {
+        $counter[ 'count' ] += $counter[ 'skip' ];
+    }
+
+    return $retval;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.cycle.php 3.2-2/lib/smarty/libs/plugins/function.cycle.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.cycle.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.cycle.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {cycle} function plugin
+ * Type:     function
+ * Name:     cycle
+ * Date:     May 3, 2002
+ * Purpose:  cycle through given values
+ * Params:
+ *
+ * - name      - name of cycle (optional)
+ * - values    - comma separated list of values to cycle, or an array of values to cycle
+ *               (this can be left out for subsequent calls)
+ * - reset     - boolean - resets given var to true
+ * - print     - boolean - print var or not. default is true
+ * - advance   - boolean - whether or not to advance the cycle
+ * - delimiter - the value delimiter, default is ","
+ * - assign    - boolean, assigns to template var instead of printed.
+ *
+ * Examples:
+ *
+ * {cycle values="#eeeeee,#d0d0d0d"}
+ * {cycle name=row values="one,two,three" reset=true}
+ * {cycle name=row}
+ *
+ *
+ * @link     http://www.smarty.net/manual/en/language.function.cycle.php {cycle}
+ *           (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author   credit to Mark Priatel <mpriatel@rogers.com>
+ * @author   credit to Gerard <gerard@interfold.com>
+ * @author   credit to Jason Sweat <jsweat_php@yahoo.com>
+ * @version  1.3
+ *
+ * @param array                    $params   parameters
+ * @param Smarty_Internal_Template $template template object
+ *
+ * @return string|null
+ */
+
+function smarty_function_cycle($params, $template)
+{
+    static $cycle_vars;
+
+    $name = (empty($params[ 'name' ])) ? 'default' : $params[ 'name' ];
+    $print = (isset($params[ 'print' ])) ? (bool) $params[ 'print' ] : true;
+    $advance = (isset($params[ 'advance' ])) ? (bool) $params[ 'advance' ] : true;
+    $reset = (isset($params[ 'reset' ])) ? (bool) $params[ 'reset' ] : false;
+
+    if (!isset($params[ 'values' ])) {
+        if (!isset($cycle_vars[ $name ][ 'values' ])) {
+            trigger_error('cycle: missing \'values\' parameter');
+
+            return;
+        }
+    } else {
+        if (isset($cycle_vars[ $name ][ 'values' ]) && $cycle_vars[ $name ][ 'values' ] !== $params[ 'values' ]) {
+            $cycle_vars[ $name ][ 'index' ] = 0;
+        }
+        $cycle_vars[ $name ][ 'values' ] = $params[ 'values' ];
+    }
+
+    if (isset($params[ 'delimiter' ])) {
+        $cycle_vars[ $name ][ 'delimiter' ] = $params[ 'delimiter' ];
+    } elseif (!isset($cycle_vars[ $name ][ 'delimiter' ])) {
+        $cycle_vars[ $name ][ 'delimiter' ] = ',';
+    }
+
+    if (is_array($cycle_vars[ $name ][ 'values' ])) {
+        $cycle_array = $cycle_vars[ $name ][ 'values' ];
+    } else {
+        $cycle_array = explode($cycle_vars[ $name ][ 'delimiter' ], $cycle_vars[ $name ][ 'values' ]);
+    }
+
+    if (!isset($cycle_vars[ $name ][ 'index' ]) || $reset) {
+        $cycle_vars[ $name ][ 'index' ] = 0;
+    }
+
+    if (isset($params[ 'assign' ])) {
+        $print = false;
+        $template->assign($params[ 'assign' ], $cycle_array[ $cycle_vars[ $name ][ 'index' ] ]);
+    }
+
+    if ($print) {
+        $retval = $cycle_array[ $cycle_vars[ $name ][ 'index' ] ];
+    } else {
+        $retval = null;
+    }
+
+    if ($advance) {
+        if ($cycle_vars[ $name ][ 'index' ] >= count($cycle_array) - 1) {
+            $cycle_vars[ $name ][ 'index' ] = 0;
+        } else {
+            $cycle_vars[ $name ][ 'index' ] ++;
+        }
+    }
+
+    return $retval;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.fetch.php 3.2-2/lib/smarty/libs/plugins/function.fetch.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.fetch.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.fetch.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,221 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {fetch} plugin
+ * Type:     function
+ * Name:     fetch
+ * Purpose:  fetch file, web or ftp data and display results
+ *
+ * @link   http://www.smarty.net/manual/en/language.function.fetch.php {fetch}
+ *         (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ *
+ * @param array                    $params   parameters
+ * @param Smarty_Internal_Template $template template object
+ *
+ * @throws SmartyException
+ * @return string|null if the assign parameter is passed, Smarty assigns the result to a template variable
+ */
+function smarty_function_fetch($params, $template)
+{
+    if (empty($params[ 'file' ])) {
+        trigger_error('[plugin] fetch parameter \'file\' cannot be empty', E_USER_NOTICE);
+
+        return;
+    }
+
+    // strip file protocol
+    if (stripos($params[ 'file' ], 'file://') === 0) {
+        $params[ 'file' ] = substr($params[ 'file' ], 7);
+    }
+
+    $protocol = strpos($params[ 'file' ], '://');
+    if ($protocol !== false) {
+        $protocol = strtolower(substr($params[ 'file' ], 0, $protocol));
+    }
+
+    if (isset($template->smarty->security_policy)) {
+        if ($protocol) {
+            // remote resource (or php stream, â€¦)
+            if (!$template->smarty->security_policy->isTrustedUri($params[ 'file' ])) {
+                return;
+            }
+        } else {
+            // local file
+            if (!$template->smarty->security_policy->isTrustedResourceDir($params[ 'file' ])) {
+                return;
+            }
+        }
+    }
+
+    $content = '';
+    if ($protocol === 'http') {
+        // http fetch
+        if ($uri_parts = parse_url($params[ 'file' ])) {
+            // set defaults
+            $host = $server_name = $uri_parts[ 'host' ];
+            $timeout = 30;
+            $accept = 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*';
+            $agent = 'Smarty Template Engine ' . Smarty::SMARTY_VERSION;
+            $referer = '';
+            $uri = !empty($uri_parts[ 'path' ]) ? $uri_parts[ 'path' ] : '/';
+            $uri .= !empty($uri_parts[ 'query' ]) ? '?' . $uri_parts[ 'query' ] : '';
+            $_is_proxy = false;
+            if (empty($uri_parts[ 'port' ])) {
+                $port = 80;
+            } else {
+                $port = $uri_parts[ 'port' ];
+            }
+            if (!empty($uri_parts[ 'user' ])) {
+                $user = $uri_parts[ 'user' ];
+            }
+            if (!empty($uri_parts[ 'pass' ])) {
+                $pass = $uri_parts[ 'pass' ];
+            }
+            // loop through parameters, setup headers
+            foreach ($params as $param_key => $param_value) {
+                switch ($param_key) {
+                    case 'file':
+                    case 'assign':
+                    case 'assign_headers':
+                        break;
+                    case 'user':
+                        if (!empty($param_value)) {
+                            $user = $param_value;
+                        }
+                        break;
+                    case 'pass':
+                        if (!empty($param_value)) {
+                            $pass = $param_value;
+                        }
+                        break;
+                    case 'accept':
+                        if (!empty($param_value)) {
+                            $accept = $param_value;
+                        }
+                        break;
+                    case 'header':
+                        if (!empty($param_value)) {
+                            if (!preg_match('![\w\d-]+: .+!', $param_value)) {
+                                trigger_error("[plugin] invalid header format '{$param_value}'", E_USER_NOTICE);
+
+                                return;
+                            } else {
+                                $extra_headers[] = $param_value;
+                            }
+                        }
+                        break;
+                    case 'proxy_host':
+                        if (!empty($param_value)) {
+                            $proxy_host = $param_value;
+                        }
+                        break;
+                    case 'proxy_port':
+                        if (!preg_match('!\D!', $param_value)) {
+                            $proxy_port = (int) $param_value;
+                        } else {
+                            trigger_error("[plugin] invalid value for attribute '{$param_key }'", E_USER_NOTICE);
+
+                            return;
+                        }
+                        break;
+                    case 'agent':
+                        if (!empty($param_value)) {
+                            $agent = $param_value;
+                        }
+                        break;
+                    case 'referer':
+                        if (!empty($param_value)) {
+                            $referer = $param_value;
+                        }
+                        break;
+                    case 'timeout':
+                        if (!preg_match('!\D!', $param_value)) {
+                            $timeout = (int) $param_value;
+                        } else {
+                            trigger_error("[plugin] invalid value for attribute '{$param_key}'", E_USER_NOTICE);
+
+                            return;
+                        }
+                        break;
+                    default:
+                        trigger_error("[plugin] unrecognized attribute '{$param_key}'", E_USER_NOTICE);
+
+                        return;
+                }
+            }
+            if (!empty($proxy_host) && !empty($proxy_port)) {
+                $_is_proxy = true;
+                $fp = fsockopen($proxy_host, $proxy_port, $errno, $errstr, $timeout);
+            } else {
+                $fp = fsockopen($server_name, $port, $errno, $errstr, $timeout);
+            }
+
+            if (!$fp) {
+                trigger_error("[plugin] unable to fetch: $errstr ($errno)", E_USER_NOTICE);
+
+                return;
+            } else {
+                if ($_is_proxy) {
+                    fputs($fp, 'GET ' . $params[ 'file' ] . " HTTP/1.0\r\n");
+                } else {
+                    fputs($fp, "GET $uri HTTP/1.0\r\n");
+                }
+                if (!empty($host)) {
+                    fputs($fp, "Host: $host\r\n");
+                }
+                if (!empty($accept)) {
+                    fputs($fp, "Accept: $accept\r\n");
+                }
+                if (!empty($agent)) {
+                    fputs($fp, "User-Agent: $agent\r\n");
+                }
+                if (!empty($referer)) {
+                    fputs($fp, "Referer: $referer\r\n");
+                }
+                if (isset($extra_headers) && is_array($extra_headers)) {
+                    foreach ($extra_headers as $curr_header) {
+                        fputs($fp, $curr_header . "\r\n");
+                    }
+                }
+                if (!empty($user) && !empty($pass)) {
+                    fputs($fp, 'Authorization: BASIC ' . base64_encode("$user:$pass") . "\r\n");
+                }
+
+                fputs($fp, "\r\n");
+                while (!feof($fp)) {
+                    $content .= fgets($fp, 4096);
+                }
+                fclose($fp);
+                $csplit = preg_split("!\r\n\r\n!", $content, 2);
+
+                $content = $csplit[ 1 ];
+
+                if (!empty($params[ 'assign_headers' ])) {
+                    $template->assign($params[ 'assign_headers' ], preg_split("!\r\n!", $csplit[ 0 ]));
+                }
+            }
+        } else {
+            trigger_error("[plugin fetch] unable to parse URL, check syntax", E_USER_NOTICE);
+
+            return;
+        }
+    } else {
+        $content = @file_get_contents($params[ 'file' ]);
+        if ($content === false) {
+            throw new SmartyException("{fetch} cannot read resource '" . $params[ 'file' ] . "'");
+        }
+    }
+
+    if (!empty($params[ 'assign' ])) {
+        $template->assign($params[ 'assign' ], $content);
+    } else {
+        return $content;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.html_checkboxes.php 3.2-2/lib/smarty/libs/plugins/function.html_checkboxes.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.html_checkboxes.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.html_checkboxes.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,262 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+/**
+ * Smarty {html_checkboxes} function plugin
+ * File:       function.html_checkboxes.php
+ * Type:       function
+ * Name:       html_checkboxes
+ * Date:       24.Feb.2003
+ * Purpose:    Prints out a list of checkbox input types
+ * Examples:
+ *
+ * {html_checkboxes values=$ids output=$names}
+ * {html_checkboxes values=$ids name='box' separator='<br>' output=$names}
+ * {html_checkboxes values=$ids checked=$checked separator='<br>' output=$names}
+ *
+ * Params:
+ *
+ * - name       (optional) - string default "checkbox"
+ * - values     (required) - array
+ * - options    (optional) - associative array
+ * - checked    (optional) - array default not set
+ * - separator  (optional) - ie <br> or &nbsp;
+ * - output     (optional) - the output next to each checkbox
+ * - assign     (optional) - assign the output as an array to this variable
+ * - escape     (optional) - escape the content (not value), defaults to true
+ *
+ *
+ * @link       http://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
+ *             (Smarty online manual)
+ * @author     Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author     credits to Monte Ohrt <monte at ohrt dot com>
+ * @version    1.0
+ *
+ * @param array                    $params   parameters
+ * @param Smarty_Internal_Template $template template object
+ *
+ * @return string
+ * @uses       smarty_function_escape_special_chars()
+ * @throws \SmartyException
+ */
+function smarty_function_html_checkboxes($params, Smarty_Internal_Template $template)
+{
+    $template->_checkPlugins(array(array('function' => 'smarty_function_escape_special_chars',
+                                         'file' => SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php')));
+
+    $name = 'checkbox';
+    $values = null;
+    $options = null;
+    $selected = array();
+    $separator = '';
+    $escape = true;
+    $labels = true;
+    $label_ids = false;
+    $output = null;
+
+    $extra = '';
+
+    foreach ($params as $_key => $_val) {
+        switch ($_key) {
+            case 'name':
+            case 'separator':
+                $$_key = (string) $_val;
+                break;
+
+            case 'escape':
+            case 'labels':
+            case 'label_ids':
+                $$_key = (bool) $_val;
+                break;
+
+            case 'options':
+                $$_key = (array) $_val;
+                break;
+
+            case 'values':
+            case 'output':
+                $$_key = array_values((array) $_val);
+                break;
+
+            case 'checked':
+            case 'selected':
+                if (is_array($_val)) {
+                    $selected = array();
+                    foreach ($_val as $_sel) {
+                        if (is_object($_sel)) {
+                            if (method_exists($_sel, '__toString')) {
+                                $_sel = smarty_function_escape_special_chars((string) $_sel->__toString());
+                            } else {
+                                trigger_error('html_checkboxes: selected attribute contains an object of class \'' .
+                                              get_class($_sel) . '\' without __toString() method', E_USER_NOTICE);
+                                continue;
+                            }
+                        } else {
+                            $_sel = smarty_function_escape_special_chars((string) $_sel);
+                        }
+                        $selected[ $_sel ] = true;
+                    }
+                } elseif (is_object($_val)) {
+                    if (method_exists($_val, '__toString')) {
+                        $selected = smarty_function_escape_special_chars((string) $_val->__toString());
+                    } else {
+                        trigger_error('html_checkboxes: selected attribute is an object of class \'' . get_class($_val) .
+                                      '\' without __toString() method', E_USER_NOTICE);
+                    }
+                } else {
+                    $selected = smarty_function_escape_special_chars((string) $_val);
+                }
+                break;
+
+            case 'checkboxes':
+                trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead',
+                              E_USER_WARNING);
+                $options = (array) $_val;
+                break;
+
+            case 'assign':
+                break;
+
+            case 'strict':
+                break;
+
+            case 'disabled':
+            case 'readonly':
+                if (!empty($params[ 'strict' ])) {
+                    if (!is_scalar($_val)) {
+                        trigger_error("html_options: {$_key} attribute must be a scalar, only boolean true or string '{$_key}' will actually add the attribute",
+                                      E_USER_NOTICE);
+                    }
+
+                    if ($_val === true || $_val === $_key) {
+                        $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"';
+                    }
+
+                    break;
+                }
+            // omit break; to fall through!
+
+            default:
+                if (!is_array($_val)) {
+                    $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
+                } else {
+                    trigger_error("html_checkboxes: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values)) {
+        return '';
+    } /* raise error here? */
+
+    $_html_result = array();
+
+    if (isset($options)) {
+        foreach ($options as $_key => $_val) {
+            $_html_result[] =
+                smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels,
+                                                       $label_ids, $escape);
+        }
+    } else {
+        foreach ($values as $_i => $_key) {
+            $_val = isset($output[ $_i ]) ? $output[ $_i ] : '';
+            $_html_result[] =
+                smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels,
+                                                       $label_ids, $escape);
+        }
+    }
+
+    if (!empty($params[ 'assign' ])) {
+        $template->assign($params[ 'assign' ], $_html_result);
+    } else {
+        return implode("\n", $_html_result);
+    }
+}
+/**
+ * @param      $name
+ * @param      $value
+ * @param      $output
+ * @param      $selected
+ * @param      $extra
+ * @param      $separator
+ * @param      $labels
+ * @param      $label_ids
+ * @param bool $escape
+ *
+ * @return string
+ */
+function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels,
+                                                   $label_ids, $escape = true)
+{
+    $_output = '';
+
+    if (is_object($value)) {
+        if (method_exists($value, '__toString')) {
+            $value = (string) $value->__toString();
+        } else {
+            trigger_error('html_options: value is an object of class \'' . get_class($value) .
+                          '\' without __toString() method', E_USER_NOTICE);
+
+            return '';
+        }
+    } else {
+        $value = (string) $value;
+    }
+
+    if (is_object($output)) {
+        if (method_exists($output, '__toString')) {
+            $output = (string) $output->__toString();
+        } else {
+            trigger_error('html_options: output is an object of class \'' . get_class($output) .
+                          '\' without __toString() method', E_USER_NOTICE);
+
+            return '';
+        }
+    } else {
+        $output = (string) $output;
+    }
+
+    if ($labels) {
+        if ($label_ids) {
+            $_id = smarty_function_escape_special_chars(preg_replace('![^\w\-\.]!' . Smarty::$_UTF8_MODIFIER, '_',
+                                                                     $name . '_' . $value));
+            $_output .= '<label for="' . $_id . '">';
+        } else {
+            $_output .= '<label>';
+        }
+    }
+
+    $name = smarty_function_escape_special_chars($name);
+    $value = smarty_function_escape_special_chars($value);
+    if ($escape) {
+        $output = smarty_function_escape_special_chars($output);
+    }
+
+    $_output .= '<input type="checkbox" name="' . $name . '[]" value="' . $value . '"';
+
+    if ($labels && $label_ids) {
+        $_output .= ' id="' . $_id . '"';
+    }
+
+    if (is_array($selected)) {
+        if (isset($selected[ $value ])) {
+            $_output .= ' checked="checked"';
+        }
+    } elseif ($value === $selected) {
+        $_output .= ' checked="checked"';
+    }
+
+    $_output .= $extra . ' />' . $output;
+    if ($labels) {
+        $_output .= '</label>';
+    }
+
+    $_output .= $separator;
+
+    return $_output;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.html_image.php 3.2-2/lib/smarty/libs/plugins/function.html_image.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.html_image.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.html_image.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,165 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {html_image} function plugin
+ * Type:     function
+ * Name:     html_image
+ * Date:     Feb 24, 2003
+ * Purpose:  format HTML tags for the image
+ * Examples: {html_image file="/images/masthead.gif"}
+ * Output:   <img src="/images/masthead.gif" width=400 height=23>
+ * Params:
+ *
+ * - file        - (required) - file (and path) of image
+ * - height      - (optional) - image height (default actual height)
+ * - width       - (optional) - image width (default actual width)
+ * - basedir     - (optional) - base directory for absolute paths, default is environment variable DOCUMENT_ROOT
+ * - path_prefix - prefix for path output (optional, default empty)
+ *
+ *
+ * @link    http://www.smarty.net/manual/en/language.function.html.image.php {html_image}
+ *          (Smarty online manual)
+ * @author  Monte Ohrt <monte at ohrt dot com>
+ * @author  credits to Duda <duda@big.hu>
+ * @version 1.0
+ *
+ * @param array                    $params   parameters
+ * @param Smarty_Internal_Template $template template object
+ *
+ * @throws SmartyException
+ * @return string
+ * @uses    smarty_function_escape_special_chars()
+ */
+function smarty_function_html_image($params, Smarty_Internal_Template $template)
+{
+    $template->_checkPlugins(array(array('function' => 'smarty_function_escape_special_chars',
+                                         'file' => SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php')));
+
+    $alt = '';
+    $file = '';
+    $height = '';
+    $width = '';
+    $extra = '';
+    $prefix = '';
+    $suffix = '';
+    $path_prefix = '';
+    $basedir = isset($_SERVER[ 'DOCUMENT_ROOT' ]) ? $_SERVER[ 'DOCUMENT_ROOT' ] : '';
+    foreach ($params as $_key => $_val) {
+        switch ($_key) {
+            case 'file':
+            case 'height':
+            case 'width':
+            case 'dpi':
+            case 'path_prefix':
+            case 'basedir':
+                $$_key = $_val;
+                break;
+
+            case 'alt':
+                if (!is_array($_val)) {
+                    $$_key = smarty_function_escape_special_chars($_val);
+                } else {
+                    throw new SmartyException ("html_image: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+
+            case 'link':
+            case 'href':
+                $prefix = '<a href="' . $_val . '">';
+                $suffix = '</a>';
+                break;
+
+            default:
+                if (!is_array($_val)) {
+                    $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
+                } else {
+                    throw new SmartyException ("html_image: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (empty($file)) {
+        trigger_error('html_image: missing \'file\' parameter', E_USER_NOTICE);
+
+        return;
+    }
+
+    if ($file[ 0 ] === '/') {
+        $_image_path = $basedir . $file;
+    } else {
+        $_image_path = $file;
+    }
+
+    // strip file protocol
+    if (stripos($params[ 'file' ], 'file://') === 0) {
+        $params[ 'file' ] = substr($params[ 'file' ], 7);
+    }
+
+    $protocol = strpos($params[ 'file' ], '://');
+    if ($protocol !== false) {
+        $protocol = strtolower(substr($params[ 'file' ], 0, $protocol));
+    }
+
+    if (isset($template->smarty->security_policy)) {
+        if ($protocol) {
+            // remote resource (or php stream, â€¦)
+            if (!$template->smarty->security_policy->isTrustedUri($params[ 'file' ])) {
+                return;
+            }
+        } else {
+            // local file
+            if (!$template->smarty->security_policy->isTrustedResourceDir($_image_path)) {
+                return;
+            }
+        }
+    }
+
+    if (!isset($params[ 'width' ]) || !isset($params[ 'height' ])) {
+        // FIXME: (rodneyrehm) getimagesize() loads the complete file off a remote resource, use custom [jpg,png,gif]header reader!
+        if (!$_image_data = @getimagesize($_image_path)) {
+            if (!file_exists($_image_path)) {
+                trigger_error("html_image: unable to find '{$_image_path}'", E_USER_NOTICE);
+
+                return;
+            } elseif (!is_readable($_image_path)) {
+                trigger_error("html_image: unable to read '{$_image_path}'", E_USER_NOTICE);
+
+                return;
+            } else {
+                trigger_error("html_image: '{$_image_path}' is not a valid image file", E_USER_NOTICE);
+
+                return;
+            }
+        }
+
+        if (!isset($params[ 'width' ])) {
+            $width = $_image_data[ 0 ];
+        }
+        if (!isset($params[ 'height' ])) {
+            $height = $_image_data[ 1 ];
+        }
+    }
+
+    if (isset($params[ 'dpi' ])) {
+        if (strstr($_SERVER[ 'HTTP_USER_AGENT' ], 'Mac')) {
+            // FIXME: (rodneyrehm) wrong dpi assumption
+            // don't know who thought this upâ€¦ even if it was true in 1998, it's definitely wrong in 2011.
+            $dpi_default = 72;
+        } else {
+            $dpi_default = 96;
+        }
+        $_resize = $dpi_default / $params[ 'dpi' ];
+        $width = round($width * $_resize);
+        $height = round($height * $_resize);
+    }
+
+    return $prefix . '<img src="' . $path_prefix . $file . '" alt="' . $alt . '" width="' . $width . '" height="' .
+           $height . '"' . $extra . ' />' . $suffix;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.html_options.php 3.2-2/lib/smarty/libs/plugins/function.html_options.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.html_options.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.html_options.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,225 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+/**
+ * Smarty {html_options} function plugin
+ * Type:     function
+ * Name:     html_options
+ * Purpose:  Prints the list of <option> tags generated from
+ *           the passed parameters
+ * Params:
+ *
+ * - name       (optional) - string default "select"
+ * - values     (required) - if no options supplied) - array
+ * - options    (required) - if no values supplied) - associative array
+ * - selected   (optional) - string default not set
+ * - output     (required) - if not options supplied) - array
+ * - id         (optional) - string default not set
+ * - class      (optional) - string default not set
+ *
+ *
+ * @link     http://www.smarty.net/manual/en/language.function.html.options.php {html_image}
+ *           (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author   Ralf Strehle (minor optimization) <ralf dot strehle at yahoo dot de>
+ *
+ * @param array                     $params parameters
+ *
+ * @param \Smarty_Internal_Template $template
+ *
+ * @return string
+ * @uses     smarty_function_escape_special_chars()
+ * @throws \SmartyException
+ */
+function smarty_function_html_options($params, Smarty_Internal_Template $template)
+{
+    $template->_checkPlugins(array(array('function' => 'smarty_function_escape_special_chars',
+                                         'file' => SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php')));
+
+    $name = null;
+    $values = null;
+    $options = null;
+    $selected = null;
+    $output = null;
+    $id = null;
+    $class = null;
+
+    $extra = '';
+
+    foreach ($params as $_key => $_val) {
+        switch ($_key) {
+            case 'name':
+            case 'class':
+            case 'id':
+                $$_key = (string) $_val;
+                break;
+
+            case 'options':
+                $options = (array) $_val;
+                break;
+
+            case 'values':
+            case 'output':
+                $$_key = array_values((array) $_val);
+                break;
+
+            case 'selected':
+                if (is_array($_val)) {
+                    $selected = array();
+                    foreach ($_val as $_sel) {
+                        if (is_object($_sel)) {
+                            if (method_exists($_sel, '__toString')) {
+                                $_sel = smarty_function_escape_special_chars((string) $_sel->__toString());
+                            } else {
+                                trigger_error('html_options: selected attribute contains an object of class \'' .
+                                              get_class($_sel) . '\' without __toString() method', E_USER_NOTICE);
+                                continue;
+                            }
+                        } else {
+                            $_sel = smarty_function_escape_special_chars((string) $_sel);
+                        }
+                        $selected[ $_sel ] = true;
+                    }
+                } elseif (is_object($_val)) {
+                    if (method_exists($_val, '__toString')) {
+                        $selected = smarty_function_escape_special_chars((string) $_val->__toString());
+                    } else {
+                        trigger_error('html_options: selected attribute is an object of class \'' . get_class($_val) .
+                                      '\' without __toString() method', E_USER_NOTICE);
+                    }
+                } else {
+                    $selected = smarty_function_escape_special_chars((string) $_val);
+                }
+                break;
+
+            case 'strict':
+                break;
+
+            case 'disabled':
+            case 'readonly':
+                if (!empty($params[ 'strict' ])) {
+                    if (!is_scalar($_val)) {
+                        trigger_error("html_options: {$_key} attribute must be a scalar, only boolean true or string '{$_key}' will actually add the attribute",
+                                      E_USER_NOTICE);
+                    }
+
+                    if ($_val === true || $_val === $_key) {
+                        $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"';
+                    }
+
+                    break;
+                }
+            // omit break; to fall through!
+
+            default:
+                if (!is_array($_val)) {
+                    $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
+                } else {
+                    trigger_error("html_options: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values)) {
+        /* raise error here? */
+
+        return '';
+    }
+
+    $_html_result = '';
+    $_idx = 0;
+
+    if (isset($options)) {
+        foreach ($options as $_key => $_val) {
+            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected, $id, $class, $_idx);
+        }
+    } else {
+        foreach ($values as $_i => $_key) {
+            $_val = isset($output[ $_i ]) ? $output[ $_i ] : '';
+            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected, $id, $class, $_idx);
+        }
+    }
+
+    if (!empty($name)) {
+        $_html_class = !empty($class) ? ' class="' . $class . '"' : '';
+        $_html_id = !empty($id) ? ' id="' . $id . '"' : '';
+        $_html_result =
+            '<select name="' . $name . '"' . $_html_class . $_html_id . $extra . '>' . "\n" . $_html_result .
+            '</select>' . "\n";
+    }
+
+    return $_html_result;
+}
+/**
+ * @param $key
+ * @param $value
+ * @param $selected
+ * @param $id
+ * @param $class
+ * @param $idx
+ *
+ * @return string
+ */
+function smarty_function_html_options_optoutput($key, $value, $selected, $id, $class, &$idx)
+{
+    if (!is_array($value)) {
+        $_key = smarty_function_escape_special_chars($key);
+        $_html_result = '<option value="' . $_key . '"';
+        if (is_array($selected)) {
+            if (isset($selected[ $_key ])) {
+                $_html_result .= ' selected="selected"';
+            }
+        } elseif ($_key === $selected) {
+            $_html_result .= ' selected="selected"';
+        }
+        $_html_class = !empty($class) ? ' class="' . $class . ' option"' : '';
+        $_html_id = !empty($id) ? ' id="' . $id . '-' . $idx . '"' : '';
+        if (is_object($value)) {
+            if (method_exists($value, '__toString')) {
+                $value = smarty_function_escape_special_chars((string) $value->__toString());
+            } else {
+                trigger_error('html_options: value is an object of class \'' . get_class($value) .
+                              '\' without __toString() method', E_USER_NOTICE);
+
+                return '';
+            }
+        } else {
+            $value = smarty_function_escape_special_chars((string) $value);
+        }
+        $_html_result .= $_html_class . $_html_id . '>' . $value . '</option>' . "\n";
+        $idx ++;
+    } else {
+        $_idx = 0;
+        $_html_result =
+            smarty_function_html_options_optgroup($key, $value, $selected, !empty($id) ? ($id . '-' . $idx) : null,
+                                                  $class, $_idx);
+        $idx ++;
+    }
+
+    return $_html_result;
+}
+/**
+ * @param $key
+ * @param $values
+ * @param $selected
+ * @param $id
+ * @param $class
+ * @param $idx
+ *
+ * @return string
+ */
+function smarty_function_html_options_optgroup($key, $values, $selected, $id, $class, &$idx)
+{
+    $optgroup_html = '<optgroup label="' . smarty_function_escape_special_chars($key) . '">' . "\n";
+    foreach ($values as $key => $value) {
+        $optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected, $id, $class, $idx);
+    }
+    $optgroup_html .= "</optgroup>\n";
+
+    return $optgroup_html;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.html_radios.php 3.2-2/lib/smarty/libs/plugins/function.html_radios.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.html_radios.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.html_radios.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,245 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+/**
+ * Smarty {html_radios} function plugin
+ * File:       function.html_radios.php
+ * Type:       function
+ * Name:       html_radios
+ * Date:       24.Feb.2003
+ * Purpose:    Prints out a list of radio input types
+ * Params:
+ *
+ * - name       (optional) - string default "radio"
+ * - values     (required) - array
+ * - options    (required) - associative array
+ * - checked    (optional) - array default not set
+ * - separator  (optional) - ie <br> or &nbsp;
+ * - output     (optional) - the output next to each radio button
+ * - assign     (optional) - assign the output as an array to this variable
+ * - escape     (optional) - escape the content (not value), defaults to true
+ *
+ * Examples:
+ *
+ * {html_radios values=$ids output=$names}
+ * {html_radios values=$ids name='box' separator='<br>' output=$names}
+ * {html_radios values=$ids checked=$checked separator='<br>' output=$names}
+ *
+ *
+ * @link    http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios}
+ *          (Smarty online manual)
+ * @author  Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author  credits to Monte Ohrt <monte at ohrt dot com>
+ * @version 1.0
+ *
+ * @param array                    $params   parameters
+ * @param Smarty_Internal_Template $template template object
+ *
+ * @return string
+ * @uses    smarty_function_escape_special_chars()
+ * @throws \SmartyException
+ */
+function smarty_function_html_radios($params, Smarty_Internal_Template $template)
+{
+    $template->_checkPlugins(array(array('function' => 'smarty_function_escape_special_chars',
+                                         'file' => SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php')));
+
+    $name = 'radio';
+    $values = null;
+    $options = null;
+    $selected = null;
+    $separator = '';
+    $escape = true;
+    $labels = true;
+    $label_ids = false;
+    $output = null;
+    $extra = '';
+
+    foreach ($params as $_key => $_val) {
+        switch ($_key) {
+            case 'name':
+            case 'separator':
+                $$_key = (string) $_val;
+                break;
+
+            case 'checked':
+            case 'selected':
+                if (is_array($_val)) {
+                    trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING);
+                } elseif (is_object($_val)) {
+                    if (method_exists($_val, '__toString')) {
+                        $selected = smarty_function_escape_special_chars((string) $_val->__toString());
+                    } else {
+                        trigger_error('html_radios: selected attribute is an object of class \'' . get_class($_val) .
+                                      '\' without __toString() method', E_USER_NOTICE);
+                    }
+                } else {
+                    $selected = (string) $_val;
+                }
+                break;
+
+            case 'escape':
+            case 'labels':
+            case 'label_ids':
+                $$_key = (bool) $_val;
+                break;
+
+            case 'options':
+                $$_key = (array) $_val;
+                break;
+
+            case 'values':
+            case 'output':
+                $$_key = array_values((array) $_val);
+                break;
+
+            case 'radios':
+                trigger_error('html_radios: the use of the "radios" attribute is deprecated, use "options" instead',
+                              E_USER_WARNING);
+                $options = (array) $_val;
+                break;
+
+            case 'assign':
+                break;
+
+            case 'strict':
+                break;
+
+            case 'disabled':
+            case 'readonly':
+                if (!empty($params[ 'strict' ])) {
+                    if (!is_scalar($_val)) {
+                        trigger_error("html_options: {$_key} attribute must be a scalar, only boolean true or string '$_key' will actually add the attribute",
+                                      E_USER_NOTICE);
+                    }
+
+                    if ($_val === true || $_val === $_key) {
+                        $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"';
+                    }
+
+                    break;
+                }
+            // omit break; to fall through!
+
+            default:
+                if (!is_array($_val)) {
+                    $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
+                } else {
+                    trigger_error("html_radios: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values)) {
+        /* raise error here? */
+
+        return '';
+    }
+
+    $_html_result = array();
+
+    if (isset($options)) {
+        foreach ($options as $_key => $_val) {
+            $_html_result[] =
+                smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels,
+                                                   $label_ids, $escape);
+        }
+    } else {
+        foreach ($values as $_i => $_key) {
+            $_val = isset($output[ $_i ]) ? $output[ $_i ] : '';
+            $_html_result[] =
+                smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels,
+                                                   $label_ids, $escape);
+        }
+    }
+
+    if (!empty($params[ 'assign' ])) {
+        $template->assign($params[ 'assign' ], $_html_result);
+    } else {
+        return implode("\n", $_html_result);
+    }
+}
+/**
+ * @param $name
+ * @param $value
+ * @param $output
+ * @param $selected
+ * @param $extra
+ * @param $separator
+ * @param $labels
+ * @param $label_ids
+ * @param $escape
+ *
+ * @return string
+ */
+function smarty_function_html_radios_output($name, $value, $output, $selected, $extra, $separator, $labels, $label_ids,
+                                               $escape)
+{
+    $_output = '';
+
+    if (is_object($value)) {
+        if (method_exists($value, '__toString')) {
+            $value = (string) $value->__toString();
+        } else {
+            trigger_error('html_options: value is an object of class \'' . get_class($value) .
+                          '\' without __toString() method', E_USER_NOTICE);
+
+            return '';
+        }
+    } else {
+        $value = (string) $value;
+    }
+
+    if (is_object($output)) {
+        if (method_exists($output, '__toString')) {
+            $output = (string) $output->__toString();
+        } else {
+            trigger_error('html_options: output is an object of class \'' . get_class($output) .
+                         '\' without __toString() method', E_USER_NOTICE);
+
+            return '';
+        }
+    } else {
+        $output = (string) $output;
+    }
+
+    if ($labels) {
+        if ($label_ids) {
+            $_id = smarty_function_escape_special_chars(preg_replace('![^\w\-\.]!' . Smarty::$_UTF8_MODIFIER, '_',
+                                                                     $name . '_' . $value));
+            $_output .= '<label for="' . $_id . '">';
+        } else {
+            $_output .= '<label>';
+        }
+    }
+
+    $name = smarty_function_escape_special_chars($name);
+    $value = smarty_function_escape_special_chars($value);
+    if ($escape) {
+        $output = smarty_function_escape_special_chars($output);
+    }
+
+    $_output .= '<input type="radio" name="' . $name . '" value="' . $value . '"';
+
+    if ($labels && $label_ids) {
+        $_output .= ' id="' . $_id . '"';
+    }
+
+    if ($value === $selected) {
+        $_output .= ' checked="checked"';
+    }
+
+    $_output .= $extra . ' />' . $output;
+    if ($labels) {
+        $_output .= '</label>';
+    }
+
+    $_output .= $separator;
+
+    return $_output;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.html_select_date.php 3.2-2/lib/smarty/libs/plugins/function.html_select_date.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.html_select_date.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.html_select_date.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,393 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+/**
+ * Smarty {html_select_date} plugin
+ * Type:     function
+ * Name:     html_select_date
+ * Purpose:  Prints the dropdowns for date selection.
+ * ChangeLog:
+ *
+ *            - 1.0 initial release
+ *            - 1.1 added support for +/- N syntax for begin
+ *              and end year values. (Monte)
+ *            - 1.2 added support for yyyy-mm-dd syntax for
+ *              time value. (Jan Rosier)
+ *            - 1.3 added support for choosing format for
+ *              month values (Gary Loescher)
+ *            - 1.3.1 added support for choosing format for
+ *              day values (Marcus Bointon)
+ *            - 1.3.2 support negative timestamps, force year
+ *              dropdown to include given date unless explicitly set (Monte)
+ *            - 1.3.4 fix behaviour of 0000-00-00 00:00:00 dates to match that
+ *              of 0000-00-00 dates (cybot, boots)
+ *            - 2.0 complete rewrite for performance,
+ *              added attributes month_names, *_id
+ *
+ *
+ * @link     http://www.smarty.net/manual/en/language.function.html.select.date.php {html_select_date}
+ *           (Smarty online manual)
+ * @version  2.0
+ * @author   Andrei Zmievski
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author   Rodney Rehm
+ *
+ * @param array                     $params parameters
+ *
+ * @param \Smarty_Internal_Template $template
+ *
+ * @return string
+ * @throws \SmartyException
+ */
+function smarty_function_html_select_date($params, Smarty_Internal_Template $template)
+{
+    $template->_checkPlugins(array(array('function' => 'smarty_function_escape_special_chars',
+                                         'file' => SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php')));
+    // generate timestamps used for month names only
+    static $_month_timestamps = null;
+    static $_current_year = null;
+    if ($_month_timestamps === null) {
+        $_current_year = date('Y');
+        $_month_timestamps = array();
+        for ($i = 1; $i <= 12; $i ++) {
+            $_month_timestamps[ $i ] = mktime(0, 0, 0, $i, 1, 2000);
+        }
+    }
+
+    /* Default values. */
+    $prefix = 'Date_';
+    $start_year = null;
+    $end_year = null;
+    $display_days = true;
+    $display_months = true;
+    $display_years = true;
+    $month_format = '%B';
+    /* Write months as numbers by default  GL */
+    $month_value_format = '%m';
+    $day_format = '%02d';
+    /* Write day values using this format MB */
+    $day_value_format = '%d';
+    $year_as_text = false;
+    /* Display years in reverse order? Ie. 2000,1999,.... */
+    $reverse_years = false;
+    /* Should the select boxes be part of an array when returned from PHP?
+       e.g. setting it to "birthday", would create "birthday[Day]",
+       "birthday[Month]" & "birthday[Year]". Can be combined with prefix */
+    $field_array = null;
+    /* <select size>'s of the different <select> tags.
+       If not set, uses default dropdown. */
+    $day_size = null;
+    $month_size = null;
+    $year_size = null;
+    /* Unparsed attributes common to *ALL* the <select>/<input> tags.
+       An example might be in the template: all_extra ='class ="foo"'. */
+    $all_extra = null;
+    /* Separate attributes for the tags. */
+    $day_extra = null;
+    $month_extra = null;
+    $year_extra = null;
+    /* Order in which to display the fields.
+       "D" -> day, "M" -> month, "Y" -> year. */
+    $field_order = 'MDY';
+    /* String printed between the different fields. */
+    $field_separator = "\n";
+    $option_separator = "\n";
+    $time = null;
+    // $all_empty = null;
+    // $day_empty = null;
+    // $month_empty = null;
+    // $year_empty = null;
+    $extra_attrs = '';
+    $all_id = null;
+    $day_id = null;
+    $month_id = null;
+    $year_id = null;
+
+    foreach ($params as $_key => $_value) {
+        switch ($_key) {
+            case 'time':
+                if (!is_array($_value) && $_value !== null) {
+                    $template->_checkPlugins(array(array('function' => 'smarty_make_timestamp',
+                                                         'file' => SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php')));
+                    $time = smarty_make_timestamp($_value);
+                }
+                break;
+
+            case 'month_names':
+                if (is_array($_value) && count($_value) === 12) {
+                    $$_key = $_value;
+                } else {
+                    trigger_error('html_select_date: month_names must be an array of 12 strings', E_USER_NOTICE);
+                }
+                break;
+
+            case 'prefix':
+            case 'field_array':
+            case 'start_year':
+            case 'end_year':
+            case 'day_format':
+            case 'day_value_format':
+            case 'month_format':
+            case 'month_value_format':
+            case 'day_size':
+            case 'month_size':
+            case 'year_size':
+            case 'all_extra':
+            case 'day_extra':
+            case 'month_extra':
+            case 'year_extra':
+            case 'field_order':
+            case 'field_separator':
+            case 'option_separator':
+            case 'all_empty':
+            case 'month_empty':
+            case 'day_empty':
+            case 'year_empty':
+            case 'all_id':
+            case 'month_id':
+            case 'day_id':
+            case 'year_id':
+                $$_key = (string) $_value;
+                break;
+
+            case 'display_days':
+            case 'display_months':
+            case 'display_years':
+            case 'year_as_text':
+            case 'reverse_years':
+                $$_key = (bool) $_value;
+                break;
+
+            default:
+                if (!is_array($_value)) {
+                    $extra_attrs .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_value) . '"';
+                } else {
+                    trigger_error("html_select_date: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    // Note: date() is faster than strftime()
+    // Note: explode(date()) is faster than date() date() date()
+    if (isset($params[ 'time' ]) && is_array($params[ 'time' ])) {
+        if (isset($params[ 'time' ][ $prefix . 'Year' ])) {
+            // $_REQUEST[$field_array] given
+            foreach (array('Y' => 'Year',
+                           'm' => 'Month',
+                           'd' => 'Day') as $_elementKey => $_elementName) {
+                $_variableName = '_' . strtolower($_elementName);
+                $$_variableName =
+                    isset($params[ 'time' ][ $prefix . $_elementName ]) ? $params[ 'time' ][ $prefix . $_elementName ] :
+                        date($_elementKey);
+            }
+        } elseif (isset($params[ 'time' ][ $field_array ][ $prefix . 'Year' ])) {
+            // $_REQUEST given
+            foreach (array('Y' => 'Year',
+                           'm' => 'Month',
+                           'd' => 'Day') as $_elementKey => $_elementName) {
+                $_variableName = '_' . strtolower($_elementName);
+                $$_variableName = isset($params[ 'time' ][ $field_array ][ $prefix . $_elementName ]) ?
+                    $params[ 'time' ][ $field_array ][ $prefix . $_elementName ] : date($_elementKey);
+            }
+        } else {
+            // no date found, use NOW
+            list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d'));
+        }
+    } elseif ($time === null) {
+        if (array_key_exists('time', $params)) {
+            $_year = $_month = $_day = $time = null;
+        } else {
+            list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d'));
+        }
+    } else {
+        list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d', $time));
+    }
+
+    // make syntax "+N" or "-N" work with $start_year and $end_year
+    // Note preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match) is slower than trim+substr
+    foreach (array('start',
+                   'end') as $key) {
+        $key .= '_year';
+        $t = $$key;
+        if ($t === null) {
+            $$key = (int) $_current_year;
+        } elseif ($t[ 0 ] === '+') {
+            $$key = (int) ($_current_year + (int) trim(substr($t, 1)));
+        } elseif ($t[ 0 ] === '-') {
+            $$key = (int) ($_current_year - (int) trim(substr($t, 1)));
+        } else {
+            $$key = (int) $$key;
+        }
+    }
+
+    // flip for ascending or descending
+    if (($start_year > $end_year && !$reverse_years) || ($start_year < $end_year && $reverse_years)) {
+        $t = $end_year;
+        $end_year = $start_year;
+        $start_year = $t;
+    }
+
+    // generate year <select> or <input>
+    if ($display_years) {
+        $_extra = '';
+        $_name = $field_array ? ($field_array . '[' . $prefix . 'Year]') : ($prefix . 'Year');
+        if ($all_extra) {
+            $_extra .= ' ' . $all_extra;
+        }
+        if ($year_extra) {
+            $_extra .= ' ' . $year_extra;
+        }
+
+        if ($year_as_text) {
+            $_html_years =
+                '<input type="text" name="' . $_name . '" value="' . $_year . '" size="4" maxlength="4"' . $_extra .
+                $extra_attrs . ' />';
+        } else {
+            $_html_years = '<select name="' . $_name . '"';
+            if ($year_id !== null || $all_id !== null) {
+                $_html_years .= ' id="' . smarty_function_escape_special_chars($year_id !== null ?
+                                                                                   ($year_id ? $year_id : $_name) :
+                                                                                   ($all_id ? ($all_id . $_name) :
+                                                                                       $_name)) . '"';
+            }
+            if ($year_size) {
+                $_html_years .= ' size="' . $year_size . '"';
+            }
+            $_html_years .= $_extra . $extra_attrs . '>' . $option_separator;
+
+            if (isset($year_empty) || isset($all_empty)) {
+                $_html_years .= '<option value="">' . (isset($year_empty) ? $year_empty : $all_empty) . '</option>' .
+                                $option_separator;
+            }
+
+            $op = $start_year > $end_year ? - 1 : 1;
+            for ($i = $start_year; $op > 0 ? $i <= $end_year : $i >= $end_year; $i += $op) {
+                $_html_years .= '<option value="' . $i . '"' . ($_year == $i ? ' selected="selected"' : '') . '>' . $i .
+                                '</option>' . $option_separator;
+            }
+
+            $_html_years .= '</select>';
+        }
+    }
+
+    // generate month <select> or <input>
+    if ($display_months) {
+        $_extra = '';
+        $_name = $field_array ? ($field_array . '[' . $prefix . 'Month]') : ($prefix . 'Month');
+        if ($all_extra) {
+            $_extra .= ' ' . $all_extra;
+        }
+        if ($month_extra) {
+            $_extra .= ' ' . $month_extra;
+        }
+
+        $_html_months = '<select name="' . $_name . '"';
+        if ($month_id !== null || $all_id !== null) {
+            $_html_months .= ' id="' . smarty_function_escape_special_chars($month_id !== null ?
+                                                                                ($month_id ? $month_id : $_name) :
+                                                                                ($all_id ? ($all_id . $_name) :
+                                                                                    $_name)) . '"';
+        }
+        if ($month_size) {
+            $_html_months .= ' size="' . $month_size . '"';
+        }
+        $_html_months .= $_extra . $extra_attrs . '>' . $option_separator;
+
+        if (isset($month_empty) || isset($all_empty)) {
+            $_html_months .= '<option value="">' . (isset($month_empty) ? $month_empty : $all_empty) . '</option>' .
+                             $option_separator;
+        }
+
+        for ($i = 1; $i <= 12; $i ++) {
+            $_val = sprintf('%02d', $i);
+            $_text = isset($month_names) ? smarty_function_escape_special_chars($month_names[ $i ]) :
+                ($month_format === '%m' ? $_val : strftime($month_format, $_month_timestamps[ $i ]));
+            $_value = $month_value_format === '%m' ? $_val : strftime($month_value_format, $_month_timestamps[ $i ]);
+            $_html_months .= '<option value="' . $_value . '"' . ($_val == $_month ? ' selected="selected"' : '') .
+                             '>' . $_text . '</option>' . $option_separator;
+        }
+
+        $_html_months .= '</select>';
+    }
+
+    // generate day <select> or <input>
+    if ($display_days) {
+        $_extra = '';
+        $_name = $field_array ? ($field_array . '[' . $prefix . 'Day]') : ($prefix . 'Day');
+        if ($all_extra) {
+            $_extra .= ' ' . $all_extra;
+        }
+        if ($day_extra) {
+            $_extra .= ' ' . $day_extra;
+        }
+
+        $_html_days = '<select name="' . $_name . '"';
+        if ($day_id !== null || $all_id !== null) {
+            $_html_days .= ' id="' .
+                           smarty_function_escape_special_chars($day_id !== null ? ($day_id ? $day_id : $_name) :
+                                                                    ($all_id ? ($all_id . $_name) : $_name)) . '"';
+        }
+        if ($day_size) {
+            $_html_days .= ' size="' . $day_size . '"';
+        }
+        $_html_days .= $_extra . $extra_attrs . '>' . $option_separator;
+
+        if (isset($day_empty) || isset($all_empty)) {
+            $_html_days .= '<option value="">' . (isset($day_empty) ? $day_empty : $all_empty) . '</option>' .
+                           $option_separator;
+        }
+
+        for ($i = 1; $i <= 31; $i ++) {
+            $_val = sprintf('%02d', $i);
+            $_text = $day_format === '%02d' ? $_val : sprintf($day_format, $i);
+            $_value = $day_value_format === '%02d' ? $_val : sprintf($day_value_format, $i);
+            $_html_days .= '<option value="' . $_value . '"' . ($_val == $_day ? ' selected="selected"' : '') . '>' .
+                           $_text . '</option>' . $option_separator;
+        }
+
+        $_html_days .= '</select>';
+    }
+
+    // order the fields for output
+    $_html = '';
+    for ($i = 0; $i <= 2; $i ++) {
+        switch ($field_order[ $i ]) {
+            case 'Y':
+            case 'y':
+                if (isset($_html_years)) {
+                    if ($_html) {
+                        $_html .= $field_separator;
+                    }
+                    $_html .= $_html_years;
+                }
+                break;
+
+            case 'm':
+            case 'M':
+                if (isset($_html_months)) {
+                    if ($_html) {
+                        $_html .= $field_separator;
+                    }
+                    $_html .= $_html_months;
+                }
+                break;
+
+            case 'd':
+            case 'D':
+                if (isset($_html_days)) {
+                    if ($_html) {
+                        $_html .= $field_separator;
+                    }
+                    $_html .= $_html_days;
+                }
+                break;
+        }
+    }
+
+    return $_html;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.html_select_time.php 3.2-2/lib/smarty/libs/plugins/function.html_select_time.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.html_select_time.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.html_select_time.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,370 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+/**
+ * Smarty {html_select_time} function plugin
+ * Type:     function
+ * Name:     html_select_time
+ * Purpose:  Prints the dropdowns for time selection
+ *
+ * @link     http://www.smarty.net/manual/en/language.function.html.select.time.php {html_select_time}
+ *           (Smarty online manual)
+ * @author   Roberto Berto <roberto@berto.net>
+ * @author   Monte Ohrt <monte AT ohrt DOT com>
+ *
+ * @param array                     $params parameters
+ *
+ * @param \Smarty_Internal_Template $template
+ *
+ * @return string
+ * @uses     smarty_make_timestamp()
+ * @throws \SmartyException
+ */
+function smarty_function_html_select_time($params, Smarty_Internal_Template $template)
+{
+    $template->_checkPlugins(array(array('function' => 'smarty_function_escape_special_chars',
+                                         'file' => SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php')));
+    $prefix = 'Time_';
+    $field_array = null;
+    $field_separator = "\n";
+    $option_separator = "\n";
+    $time = null;
+
+    $display_hours = true;
+    $display_minutes = true;
+    $display_seconds = true;
+    $display_meridian = true;
+
+    $hour_format = '%02d';
+    $hour_value_format = '%02d';
+    $minute_format = '%02d';
+    $minute_value_format = '%02d';
+    $second_format = '%02d';
+    $second_value_format = '%02d';
+
+    $hour_size = null;
+    $minute_size = null;
+    $second_size = null;
+    $meridian_size = null;
+
+    $all_empty = null;
+    $hour_empty = null;
+    $minute_empty = null;
+    $second_empty = null;
+    $meridian_empty = null;
+
+    $all_id = null;
+    $hour_id = null;
+    $minute_id = null;
+    $second_id = null;
+    $meridian_id = null;
+
+    $use_24_hours = true;
+    $minute_interval = 1;
+    $second_interval = 1;
+
+    $extra_attrs = '';
+    $all_extra = null;
+    $hour_extra = null;
+    $minute_extra = null;
+    $second_extra = null;
+    $meridian_extra = null;
+
+    foreach ($params as $_key => $_value) {
+        switch ($_key) {
+            case 'time':
+                if (!is_array($_value) && $_value !== null) {
+                    $template->_checkPlugins(array(array('function' => 'smarty_make_timestamp',
+                                                         'file' => SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php')));
+                    $time = smarty_make_timestamp($_value);
+                }
+                break;
+
+            case 'prefix':
+            case 'field_array':
+
+            case 'field_separator':
+            case 'option_separator':
+
+            case 'all_extra':
+            case 'hour_extra':
+            case 'minute_extra':
+            case 'second_extra':
+            case 'meridian_extra':
+
+            case 'all_empty':
+            case 'hour_empty':
+            case 'minute_empty':
+            case 'second_empty':
+            case 'meridian_empty':
+
+            case 'all_id':
+            case 'hour_id':
+            case 'minute_id':
+            case 'second_id':
+            case 'meridian_id':
+
+            case 'hour_format':
+            case 'hour_value_format':
+            case 'minute_format':
+            case 'minute_value_format':
+            case 'second_format':
+            case 'second_value_format':
+                $$_key = (string) $_value;
+                break;
+
+            case 'display_hours':
+            case 'display_minutes':
+            case 'display_seconds':
+            case 'display_meridian':
+            case 'use_24_hours':
+                $$_key = (bool) $_value;
+                break;
+
+            case 'minute_interval':
+            case 'second_interval':
+
+            case 'hour_size':
+            case 'minute_size':
+            case 'second_size':
+            case 'meridian_size':
+                $$_key = (int) $_value;
+                break;
+
+            default:
+                if (!is_array($_value)) {
+                    $extra_attrs .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_value) . '"';
+                } else {
+                    trigger_error("html_select_date: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (isset($params[ 'time' ]) && is_array($params[ 'time' ])) {
+        if (isset($params[ 'time' ][ $prefix . 'Hour' ])) {
+            // $_REQUEST[$field_array] given
+            foreach (array('H' => 'Hour',
+                           'i' => 'Minute',
+                           's' => 'Second') as $_elementKey => $_elementName) {
+                $_variableName = '_' . strtolower($_elementName);
+                $$_variableName =
+                    isset($params[ 'time' ][ $prefix . $_elementName ]) ? $params[ 'time' ][ $prefix . $_elementName ] :
+                        date($_elementKey);
+            }
+            $_meridian =
+                isset($params[ 'time' ][ $prefix . 'Meridian' ]) ? (' ' . $params[ 'time' ][ $prefix . 'Meridian' ]) :
+                    '';
+            $time = strtotime($_hour . ':' . $_minute . ':' . $_second . $_meridian);
+            list($_hour, $_minute, $_second) = $time = explode('-', date('H-i-s', $time));
+        } elseif (isset($params[ 'time' ][ $field_array ][ $prefix . 'Hour' ])) {
+            // $_REQUEST given
+            foreach (array('H' => 'Hour',
+                           'i' => 'Minute',
+                           's' => 'Second') as $_elementKey => $_elementName) {
+                $_variableName = '_' . strtolower($_elementName);
+                $$_variableName = isset($params[ 'time' ][ $field_array ][ $prefix . $_elementName ]) ?
+                    $params[ 'time' ][ $field_array ][ $prefix . $_elementName ] : date($_elementKey);
+            }
+            $_meridian = isset($params[ 'time' ][ $field_array ][ $prefix . 'Meridian' ]) ?
+                (' ' . $params[ 'time' ][ $field_array ][ $prefix . 'Meridian' ]) : '';
+            $time = strtotime($_hour . ':' . $_minute . ':' . $_second . $_meridian);
+            list($_hour, $_minute, $_second) = $time = explode('-', date('H-i-s', $time));
+        } else {
+            // no date found, use NOW
+            list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d'));
+        }
+    } elseif ($time === null) {
+        if (array_key_exists('time', $params)) {
+            $_hour = $_minute = $_second = $time = null;
+        } else {
+            list($_hour, $_minute, $_second) = $time = explode('-', date('H-i-s'));
+        }
+    } else {
+        list($_hour, $_minute, $_second) = $time = explode('-', date('H-i-s', $time));
+    }
+
+    // generate hour <select>
+    if ($display_hours) {
+        $_html_hours = '';
+        $_extra = '';
+        $_name = $field_array ? ($field_array . '[' . $prefix . 'Hour]') : ($prefix . 'Hour');
+        if ($all_extra) {
+            $_extra .= ' ' . $all_extra;
+        }
+        if ($hour_extra) {
+            $_extra .= ' ' . $hour_extra;
+        }
+
+        $_html_hours = '<select name="' . $_name . '"';
+        if ($hour_id !== null || $all_id !== null) {
+            $_html_hours .= ' id="' .
+                            smarty_function_escape_special_chars($hour_id !== null ? ($hour_id ? $hour_id : $_name) :
+                                                                     ($all_id ? ($all_id . $_name) : $_name)) . '"';
+        }
+        if ($hour_size) {
+            $_html_hours .= ' size="' . $hour_size . '"';
+        }
+        $_html_hours .= $_extra . $extra_attrs . '>' . $option_separator;
+
+        if (isset($hour_empty) || isset($all_empty)) {
+            $_html_hours .= '<option value="">' . (isset($hour_empty) ? $hour_empty : $all_empty) . '</option>' .
+                            $option_separator;
+        }
+
+        $start = $use_24_hours ? 0 : 1;
+        $end = $use_24_hours ? 23 : 12;
+        for ($i = $start; $i <= $end; $i ++) {
+            $_val = sprintf('%02d', $i);
+            $_text = $hour_format === '%02d' ? $_val : sprintf($hour_format, $i);
+            $_value = $hour_value_format === '%02d' ? $_val : sprintf($hour_value_format, $i);
+
+            if (!$use_24_hours) {
+                $_hour12 = $_hour == 0 ? 12 : ($_hour <= 12 ? $_hour : $_hour - 12);
+            }
+
+            $selected = $_hour !== null ? ($use_24_hours ? $_hour == $_val : $_hour12 == $_val) : null;
+            $_html_hours .= '<option value="' . $_value . '"' . ($selected ? ' selected="selected"' : '') . '>' .
+                            $_text . '</option>' . $option_separator;
+        }
+
+        $_html_hours .= '</select>';
+    }
+
+    // generate minute <select>
+    if ($display_minutes) {
+        $_html_minutes = '';
+        $_extra = '';
+        $_name = $field_array ? ($field_array . '[' . $prefix . 'Minute]') : ($prefix . 'Minute');
+        if ($all_extra) {
+            $_extra .= ' ' . $all_extra;
+        }
+        if ($minute_extra) {
+            $_extra .= ' ' . $minute_extra;
+        }
+
+        $_html_minutes = '<select name="' . $_name . '"';
+        if ($minute_id !== null || $all_id !== null) {
+            $_html_minutes .= ' id="' . smarty_function_escape_special_chars($minute_id !== null ?
+                                                                                 ($minute_id ? $minute_id : $_name) :
+                                                                                 ($all_id ? ($all_id . $_name) :
+                                                                                     $_name)) . '"';
+        }
+        if ($minute_size) {
+            $_html_minutes .= ' size="' . $minute_size . '"';
+        }
+        $_html_minutes .= $_extra . $extra_attrs . '>' . $option_separator;
+
+        if (isset($minute_empty) || isset($all_empty)) {
+            $_html_minutes .= '<option value="">' . (isset($minute_empty) ? $minute_empty : $all_empty) . '</option>' .
+                              $option_separator;
+        }
+
+        $selected = $_minute !== null ? ($_minute - $_minute % $minute_interval) : null;
+        for ($i = 0; $i <= 59; $i += $minute_interval) {
+            $_val = sprintf('%02d', $i);
+            $_text = $minute_format === '%02d' ? $_val : sprintf($minute_format, $i);
+            $_value = $minute_value_format === '%02d' ? $_val : sprintf($minute_value_format, $i);
+            $_html_minutes .= '<option value="' . $_value . '"' . ($selected === $i ? ' selected="selected"' : '') .
+                              '>' . $_text . '</option>' . $option_separator;
+        }
+
+        $_html_minutes .= '</select>';
+    }
+
+    // generate second <select>
+    if ($display_seconds) {
+        $_html_seconds = '';
+        $_extra = '';
+        $_name = $field_array ? ($field_array . '[' . $prefix . 'Second]') : ($prefix . 'Second');
+        if ($all_extra) {
+            $_extra .= ' ' . $all_extra;
+        }
+        if ($second_extra) {
+            $_extra .= ' ' . $second_extra;
+        }
+
+        $_html_seconds = '<select name="' . $_name . '"';
+        if ($second_id !== null || $all_id !== null) {
+            $_html_seconds .= ' id="' . smarty_function_escape_special_chars($second_id !== null ?
+                                                                                 ($second_id ? $second_id : $_name) :
+                                                                                 ($all_id ? ($all_id . $_name) :
+                                                                                     $_name)) . '"';
+        }
+        if ($second_size) {
+            $_html_seconds .= ' size="' . $second_size . '"';
+        }
+        $_html_seconds .= $_extra . $extra_attrs . '>' . $option_separator;
+
+        if (isset($second_empty) || isset($all_empty)) {
+            $_html_seconds .= '<option value="">' . (isset($second_empty) ? $second_empty : $all_empty) . '</option>' .
+                              $option_separator;
+        }
+
+        $selected = $_second !== null ? ($_second - $_second % $second_interval) : null;
+        for ($i = 0; $i <= 59; $i += $second_interval) {
+            $_val = sprintf('%02d', $i);
+            $_text = $second_format === '%02d' ? $_val : sprintf($second_format, $i);
+            $_value = $second_value_format === '%02d' ? $_val : sprintf($second_value_format, $i);
+            $_html_seconds .= '<option value="' . $_value . '"' . ($selected === $i ? ' selected="selected"' : '') .
+                              '>' . $_text . '</option>' . $option_separator;
+        }
+
+        $_html_seconds .= '</select>';
+    }
+
+    // generate meridian <select>
+    if ($display_meridian && !$use_24_hours) {
+        $_html_meridian = '';
+        $_extra = '';
+        $_name = $field_array ? ($field_array . '[' . $prefix . 'Meridian]') : ($prefix . 'Meridian');
+        if ($all_extra) {
+            $_extra .= ' ' . $all_extra;
+        }
+        if ($meridian_extra) {
+            $_extra .= ' ' . $meridian_extra;
+        }
+
+        $_html_meridian = '<select name="' . $_name . '"';
+        if ($meridian_id !== null || $all_id !== null) {
+            $_html_meridian .= ' id="' . smarty_function_escape_special_chars($meridian_id !== null ?
+                                                                                  ($meridian_id ? $meridian_id :
+                                                                                      $_name) :
+                                                                                  ($all_id ? ($all_id . $_name) :
+                                                                                      $_name)) . '"';
+        }
+        if ($meridian_size) {
+            $_html_meridian .= ' size="' . $meridian_size . '"';
+        }
+        $_html_meridian .= $_extra . $extra_attrs . '>' . $option_separator;
+
+        if (isset($meridian_empty) || isset($all_empty)) {
+            $_html_meridian .= '<option value="">' . (isset($meridian_empty) ? $meridian_empty : $all_empty) .
+                               '</option>' . $option_separator;
+        }
+
+        $_html_meridian .= '<option value="am"' . ($_hour > 0 && $_hour < 12 ? ' selected="selected"' : '') .
+                           '>AM</option>' . $option_separator . '<option value="pm"' .
+                           ($_hour < 12 ? '' : ' selected="selected"') . '>PM</option>' . $option_separator .
+                           '</select>';
+    }
+
+    $_html = '';
+    foreach (array('_html_hours',
+                   '_html_minutes',
+                   '_html_seconds',
+                   '_html_meridian') as $k) {
+        if (isset($$k)) {
+            if ($_html) {
+                $_html .= $field_separator;
+            }
+            $_html .= $$k;
+        }
+    }
+
+    return $_html;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.html_table.php 3.2-2/lib/smarty/libs/plugins/function.html_table.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.html_table.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.html_table.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,182 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {html_table} function plugin
+ * Type:     function
+ * Name:     html_table
+ * Date:     Feb 17, 2003
+ * Purpose:  make an html table from an array of data
+ * Params:
+ *
+ * - loop       - array to loop through
+ * - cols       - number of columns, comma separated list of column names
+ *                or array of column names
+ * - rows       - number of rows
+ * - table_attr - table attributes
+ * - th_attr    - table heading attributes (arrays are cycled)
+ * - tr_attr    - table row attributes (arrays are cycled)
+ * - td_attr    - table cell attributes (arrays are cycled)
+ * - trailpad   - value to pad trailing cells with
+ * - caption    - text for caption element
+ * - vdir       - vertical direction (default: "down", means top-to-bottom)
+ * - hdir       - horizontal direction (default: "right", means left-to-right)
+ * - inner      - inner loop (default "cols": print $loop line by line,
+ *                $loop will be printed column by column otherwise)
+ *
+ * Examples:
+ *
+ * {table loop=$data}
+ * {table loop=$data cols=4 tr_attr='"bgcolor=red"'}
+ * {table loop=$data cols="first,second,third" tr_attr=$colors}
+ *
+ *
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author   credit to Messju Mohr <messju at lammfellpuschen dot de>
+ * @author   credit to boots <boots dot smarty at yahoo dot com>
+ * @version  1.1
+ * @link     http://www.smarty.net/manual/en/language.function.html.table.php {html_table}
+ *           (Smarty online manual)
+ *
+ * @param array $params parameters
+ *
+ * @return string
+ */
+function smarty_function_html_table($params)
+{
+    $table_attr = 'border="1"';
+    $tr_attr = '';
+    $th_attr = '';
+    $td_attr = '';
+    $cols = $cols_count = 3;
+    $rows = 3;
+    $trailpad = '&nbsp;';
+    $vdir = 'down';
+    $hdir = 'right';
+    $inner = 'cols';
+    $caption = '';
+    $loop = null;
+
+    if (!isset($params[ 'loop' ])) {
+        trigger_error("html_table: missing 'loop' parameter", E_USER_WARNING);
+
+        return;
+    }
+
+    foreach ($params as $_key => $_value) {
+        switch ($_key) {
+            case 'loop':
+                $$_key = (array) $_value;
+                break;
+
+            case 'cols':
+                if (is_array($_value) && !empty($_value)) {
+                    $cols = $_value;
+                    $cols_count = count($_value);
+                } elseif (!is_numeric($_value) && is_string($_value) && !empty($_value)) {
+                    $cols = explode(',', $_value);
+                    $cols_count = count($cols);
+                } elseif (!empty($_value)) {
+                    $cols_count = (int) $_value;
+                } else {
+                    $cols_count = $cols;
+                }
+                break;
+
+            case 'rows':
+                $$_key = (int) $_value;
+                break;
+
+            case 'table_attr':
+            case 'trailpad':
+            case 'hdir':
+            case 'vdir':
+            case 'inner':
+            case 'caption':
+                $$_key = (string) $_value;
+                break;
+
+            case 'tr_attr':
+            case 'td_attr':
+            case 'th_attr':
+                $$_key = $_value;
+                break;
+        }
+    }
+
+    $loop_count = count($loop);
+    if (empty($params[ 'rows' ])) {
+        /* no rows specified */
+        $rows = ceil($loop_count / $cols_count);
+    } elseif (empty($params[ 'cols' ])) {
+        if (!empty($params[ 'rows' ])) {
+            /* no cols specified, but rows */
+            $cols_count = ceil($loop_count / $rows);
+        }
+    }
+
+    $output = "<table $table_attr>\n";
+
+    if (!empty($caption)) {
+        $output .= '<caption>' . $caption . "</caption>\n";
+    }
+
+    if (is_array($cols)) {
+        $cols = ($hdir === 'right') ? $cols : array_reverse($cols);
+        $output .= "<thead><tr>\n";
+
+        for ($r = 0; $r < $cols_count; $r ++) {
+            $output .= '<th' . smarty_function_html_table_cycle('th', $th_attr, $r) . '>';
+            $output .= $cols[ $r ];
+            $output .= "</th>\n";
+        }
+        $output .= "</tr></thead>\n";
+    }
+
+    $output .= "<tbody>\n";
+    for ($r = 0; $r < $rows; $r ++) {
+        $output .= "<tr" . smarty_function_html_table_cycle('tr', $tr_attr, $r) . ">\n";
+        $rx = ($vdir === 'down') ? $r * $cols_count : ($rows - 1 - $r) * $cols_count;
+
+        for ($c = 0; $c < $cols_count; $c ++) {
+            $x = ($hdir === 'right') ? $rx + $c : $rx + $cols_count - 1 - $c;
+            if ($inner !== 'cols') {
+                /* shuffle x to loop over rows*/
+                $x = floor($x / $cols_count) + ($x % $cols_count) * $rows;
+            }
+
+            if ($x < $loop_count) {
+                $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">" . $loop[ $x ] . "</td>\n";
+            } else {
+                $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">$trailpad</td>\n";
+            }
+        }
+        $output .= "</tr>\n";
+    }
+    $output .= "</tbody>\n";
+    $output .= "</table>\n";
+
+    return $output;
+}
+/**
+ * @param $name
+ * @param $var
+ * @param $no
+ *
+ * @return string
+ */
+function smarty_function_html_table_cycle($name, $var, $no)
+{
+    if (!is_array($var)) {
+        $ret = $var;
+    } else {
+        $ret = $var[ $no % count($var) ];
+    }
+
+    return ($ret) ? ' ' . $ret : '';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.mailto.php 3.2-2/lib/smarty/libs/plugins/function.mailto.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.mailto.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.mailto.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,153 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {mailto} function plugin
+ * Type:     function
+ * Name:     mailto
+ * Date:     May 21, 2002
+ * Purpose:  automate mailto address link creation, and optionally encode them.
+ * Params:
+ *
+ * - address    - (required) - e-mail address
+ * - text       - (optional) - text to display, default is address
+ * - encode     - (optional) - can be one of:
+ *                             * none : no encoding (default)
+ *                             * javascript : encode with javascript
+ *                             * javascript_charcode : encode with javascript charcode
+ *                             * hex : encode with hexadecimal (no javascript)
+ * - cc         - (optional) - address(es) to carbon copy
+ * - bcc        - (optional) - address(es) to blind carbon copy
+ * - subject    - (optional) - e-mail subject
+ * - newsgroups - (optional) - newsgroup(s) to post to
+ * - followupto - (optional) - address(es) to follow up to
+ * - extra      - (optional) - extra tags for the href link
+ *
+ * Examples:
+ *
+ * {mailto address="me@domain.com"}
+ * {mailto address="me@domain.com" encode="javascript"}
+ * {mailto address="me@domain.com" encode="hex"}
+ * {mailto address="me@domain.com" subject="Hello to you!"}
+ * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
+ * {mailto address="me@domain.com" extra='class="mailto"'}
+ *
+ *
+ * @link     http://www.smarty.net/manual/en/language.function.mailto.php {mailto}
+ *           (Smarty online manual)
+ * @version  1.2
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author   credits to Jason Sweat (added cc, bcc and subject functionality)
+ *
+ * @param array $params parameters
+ *
+ * @return string
+ */
+function smarty_function_mailto($params)
+{
+    static $_allowed_encoding =
+        array('javascript' => true, 'javascript_charcode' => true, 'hex' => true, 'none' => true);
+    $extra = '';
+
+    if (empty($params[ 'address' ])) {
+        trigger_error("mailto: missing 'address' parameter", E_USER_WARNING);
+
+        return;
+    } else {
+        $address = $params[ 'address' ];
+    }
+
+    $text = $address;
+    // netscape and mozilla do not decode %40 (@) in BCC field (bug?)
+    // so, don't encode it.
+    $search = array('%40', '%2C');
+    $replace = array('@', ',');
+    $mail_parms = array();
+    foreach ($params as $var => $value) {
+        switch ($var) {
+            case 'cc':
+            case 'bcc':
+            case 'followupto':
+                if (!empty($value)) {
+                    $mail_parms[] = $var . '=' . str_replace($search, $replace, rawurlencode($value));
+                }
+                break;
+
+            case 'subject':
+            case 'newsgroups':
+                $mail_parms[] = $var . '=' . rawurlencode($value);
+                break;
+
+            case 'extra':
+            case 'text':
+                $$var = $value;
+
+            default:
+        }
+    }
+
+    if ($mail_parms) {
+        $address .= '?' . join('&', $mail_parms);
+    }
+
+    $encode = (empty($params[ 'encode' ])) ? 'none' : $params[ 'encode' ];
+    if (!isset($_allowed_encoding[ $encode ])) {
+        trigger_error("mailto: 'encode' parameter must be none, javascript, javascript_charcode or hex",
+                      E_USER_WARNING);
+
+        return;
+    }
+    // FIXME: (rodneyrehm) document.write() excues me what? 1998 has passed!
+    if ($encode === 'javascript') {
+        $string = 'document.write(\'<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>\');';
+
+        $js_encode = '';
+        for ($x = 0, $_length = strlen($string); $x < $_length; $x ++) {
+            $js_encode .= '%' . bin2hex($string[ $x ]);
+        }
+
+        return '<script type="text/javascript">eval(unescape(\'' . $js_encode . '\'))</script>';
+    } elseif ($encode === 'javascript_charcode') {
+        $string = '<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>';
+
+        for ($x = 0, $y = strlen($string); $x < $y; $x ++) {
+            $ord[] = ord($string[ $x ]);
+        }
+
+        $_ret = "<script type=\"text/javascript\" language=\"javascript\">\n" . "{document.write(String.fromCharCode(" .
+                implode(',', $ord) . "))" . "}\n" . "</script>\n";
+
+        return $_ret;
+    } elseif ($encode === 'hex') {
+        preg_match('!^(.*)(\?.*)$!', $address, $match);
+        if (!empty($match[ 2 ])) {
+            trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript.", E_USER_WARNING);
+
+            return;
+        }
+        $address_encode = '';
+        for ($x = 0, $_length = strlen($address); $x < $_length; $x ++) {
+            if (preg_match('!\w!' . Smarty::$_UTF8_MODIFIER, $address[ $x ])) {
+                $address_encode .= '%' . bin2hex($address[ $x ]);
+            } else {
+                $address_encode .= $address[ $x ];
+            }
+        }
+        $text_encode = '';
+        for ($x = 0, $_length = strlen($text); $x < $_length; $x ++) {
+            $text_encode .= '&#x' . bin2hex($text[ $x ]) . ';';
+        }
+
+        $mailto = "&#109;&#97;&#105;&#108;&#116;&#111;&#58;";
+
+        return '<a href="' . $mailto . $address_encode . '" ' . $extra . '>' . $text_encode . '</a>';
+    } else {
+        // no encoding
+        return '<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>';
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/function.math.php 3.2-2/lib/smarty/libs/plugins/function.math.php
--- 3.0.2-2/lib/smarty/libs/plugins/function.math.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/function.math.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,109 @@
+<?php
+/**
+ * Smarty plugin
+ * This plugin is only for Smarty2 BC
+ *
+ * @package    Smarty
+ * @subpackage PluginsFunction
+ */
+
+/**
+ * Smarty {math} function plugin
+ * Type:     function
+ * Name:     math
+ * Purpose:  handle math computations in template
+ *
+ * @link     http://www.smarty.net/manual/en/language.function.math.php {math}
+ *           (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ *
+ * @param array                    $params   parameters
+ * @param Smarty_Internal_Template $template template object
+ *
+ * @return string|null
+ */
+function smarty_function_math($params, $template)
+{
+    static $_allowed_funcs =
+        array('int' => true, 'abs' => true, 'ceil' => true, 'cos' => true, 'exp' => true, 'floor' => true,
+              'log' => true, 'log10' => true, 'max' => true, 'min' => true, 'pi' => true, 'pow' => true, 'rand' => true,
+              'round' => true, 'sin' => true, 'sqrt' => true, 'srand' => true, 'tan' => true);
+    // be sure equation parameter is present
+    if (empty($params[ 'equation' ])) {
+        trigger_error("math: missing equation parameter", E_USER_WARNING);
+
+        return;
+    }
+
+    $equation = $params[ 'equation' ];
+
+    // make sure parenthesis are balanced
+    if (substr_count($equation, '(') !== substr_count($equation, ')')) {
+        trigger_error("math: unbalanced parenthesis", E_USER_WARNING);
+
+        return;
+    }
+
+    // disallow backticks
+    if (strpos($equation, '`') !== false) {
+        trigger_error("math: backtick character not allowed in equation", E_USER_WARNING);
+
+        return;
+    }
+
+    // also disallow dollar signs
+    if (strpos($equation, '$') !== false) {
+        trigger_error("math: dollar signs not allowed in equation", E_USER_WARNING);
+
+        return;
+    }
+
+    foreach ($params as $key => $val) {
+        if ($key !== 'equation' && $key !== 'format' && $key !== 'assign') {
+            // make sure value is not empty
+            if (strlen($val) === 0) {
+                trigger_error("math: parameter '{$key}' is empty", E_USER_WARNING);
+
+                return;
+            }
+            if (!is_numeric($val)) {
+                trigger_error("math: parameter '{$key}' is not numeric", E_USER_WARNING);
+
+                return;
+            }
+        }
+    }
+
+    // match all vars in equation, make sure all are passed
+    preg_match_all('!(?:0x[a-fA-F0-9]+)|([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)!', $equation, $match);
+
+    foreach ($match[ 1 ] as $curr_var) {
+        if ($curr_var && !isset($params[ $curr_var ]) && !isset($_allowed_funcs[ $curr_var ])) {
+            trigger_error("math: function call '{$curr_var}' not allowed, or missing parameter '{$curr_var}'", E_USER_WARNING);
+
+            return;
+        }
+    }
+
+    foreach ($params as $key => $val) {
+        if ($key !== 'equation' && $key !== 'format' && $key !== 'assign') {
+            $equation = preg_replace("/\b$key\b/", " \$params['$key'] ", $equation);
+        }
+    }
+    $smarty_math_result = null;
+    eval("\$smarty_math_result = " . $equation . ";");
+
+    if (empty($params[ 'format' ])) {
+        if (empty($params[ 'assign' ])) {
+            return $smarty_math_result;
+        } else {
+            $template->assign($params[ 'assign' ], $smarty_math_result);
+        }
+    } else {
+        if (empty($params[ 'assign' ])) {
+            printf($params[ 'format' ], $smarty_math_result);
+        } else {
+            $template->assign($params[ 'assign' ], sprintf($params[ 'format' ], $smarty_math_result));
+        }
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifier.capitalize.php 3.2-2/lib/smarty/libs/plugins/modifier.capitalize.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifier.capitalize.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifier.capitalize.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty capitalize modifier plugin
+ * Type:     modifier
+ * Name:     capitalize
+ * Purpose:  capitalize words in the string
+ * {@internal {$string|capitalize:true:true} is the fastest option for MBString enabled systems }}
+ *
+ * @param string  $string    string to capitalize
+ * @param boolean $uc_digits also capitalize "x123" to "X123"
+ * @param boolean $lc_rest   capitalize first letters, lowercase all following letters "aAa" to "Aaa"
+ *
+ * @return string capitalized string
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Rodney Rehm
+ */
+function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = false)
+{
+    if (Smarty::$_MBSTRING) {
+        if ($lc_rest) {
+            // uppercase (including hyphenated words)
+            $upper_string = mb_convert_case($string, MB_CASE_TITLE, Smarty::$_CHARSET);
+        } else {
+            // uppercase word breaks
+            $upper_string = preg_replace_callback("!(^|[^\p{L}'])([\p{Ll}])!S" . Smarty::$_UTF8_MODIFIER,
+                                                  'smarty_mod_cap_mbconvert_cb', $string);
+        }
+        // check uc_digits case
+        if (!$uc_digits) {
+            if (preg_match_all("!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!" . Smarty::$_UTF8_MODIFIER, $string, $matches,
+                               PREG_OFFSET_CAPTURE)) {
+                foreach ($matches[ 1 ] as $match) {
+                    $upper_string =
+                        substr_replace($upper_string, mb_strtolower($match[ 0 ], Smarty::$_CHARSET), $match[ 1 ],
+                                       strlen($match[ 0 ]));
+                }
+            }
+        }
+        $upper_string =
+            preg_replace_callback("!((^|\s)['\"])(\w)!" . Smarty::$_UTF8_MODIFIER, 'smarty_mod_cap_mbconvert2_cb',
+                                  $upper_string);
+        return $upper_string;
+    }
+
+    // lowercase first
+    if ($lc_rest) {
+        $string = strtolower($string);
+    }
+    // uppercase (including hyphenated words)
+    $upper_string =
+        preg_replace_callback("!(^|[^\p{L}'])([\p{Ll}])!S" . Smarty::$_UTF8_MODIFIER, 'smarty_mod_cap_ucfirst_cb',
+                              $string);
+    // check uc_digits case
+    if (!$uc_digits) {
+        if (preg_match_all("!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!" . Smarty::$_UTF8_MODIFIER, $string, $matches,
+                           PREG_OFFSET_CAPTURE)) {
+            foreach ($matches[ 1 ] as $match) {
+                $upper_string =
+                    substr_replace($upper_string, strtolower($match[ 0 ]), $match[ 1 ], strlen($match[ 0 ]));
+            }
+        }
+    }
+    $upper_string = preg_replace_callback("!((^|\s)['\"])(\w)!" . Smarty::$_UTF8_MODIFIER, 'smarty_mod_cap_ucfirst2_cb',
+                                          $upper_string);
+    return $upper_string;
+}
+
+/*
+ *
+ * Bug: create_function() use exhausts memory when used in long loops
+ * Fix: use declared functions for callbacks instead of using create_function()
+ * Note: This can be fixed using anonymous functions instead, but that requires PHP >= 5.3
+ *
+ * @author Kyle Renfrow
+ */
+/**
+ * @param $matches
+ *
+ * @return string
+ */
+function smarty_mod_cap_mbconvert_cb($matches)
+{
+    return stripslashes($matches[ 1 ]) . mb_convert_case(stripslashes($matches[ 2 ]), MB_CASE_UPPER, Smarty::$_CHARSET);
+}
+/**
+ * @param $matches
+ *
+ * @return string
+ */
+function smarty_mod_cap_mbconvert2_cb($matches)
+{
+    return stripslashes($matches[ 1 ]) . mb_convert_case(stripslashes($matches[ 3 ]), MB_CASE_UPPER, Smarty::$_CHARSET);
+}
+/**
+ * @param $matches
+ *
+ * @return string
+ */
+function smarty_mod_cap_ucfirst_cb($matches)
+{
+    return stripslashes($matches[ 1 ]) . ucfirst(stripslashes($matches[ 2 ]));
+}
+/**
+ * @param $matches
+ *
+ * @return string
+ */
+function smarty_mod_cap_ucfirst2_cb($matches)
+{
+    return stripslashes($matches[ 1 ]) . ucfirst(stripslashes($matches[ 3 ]));
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.cat.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.cat.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.cat.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.cat.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty cat modifier plugin
+ * Type:     modifier
+ * Name:     cat
+ * Date:     Feb 24, 2003
+ * Purpose:  catenate a value to a variable
+ * Input:    string to catenate
+ * Example:  {$var|cat:"foo"}
+ *
+ * @link     http://smarty.php.net/manual/en/language.modifier.cat.php cat
+ *           (Smarty online manual)
+ * @author   Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_cat($params)
+{
+    return '(' . implode(').(', $params) . ')';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.count_characters.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.count_characters.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.count_characters.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.count_characters.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty count_characters modifier plugin
+ * Type:     modifier
+ * Name:     count_characters
+ * Purpose:  count the number of characters in a text
+ *
+ * @link   http://www.smarty.net/manual/en/language.modifier.count.characters.php count_characters (Smarty online manual)
+ * @author Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_count_characters($params)
+{
+    if (!isset($params[ 1 ]) || $params[ 1 ] !== 'true') {
+        return 'preg_match_all(\'/[^\s]/' . Smarty::$_UTF8_MODIFIER . '\',' . $params[ 0 ] . ', $tmp)';
+    }
+    if (Smarty::$_MBSTRING) {
+        return 'mb_strlen(' . $params[ 0 ] . ', \'' . addslashes(Smarty::$_CHARSET) . '\')';
+    }
+    // no MBString fallback
+    return 'strlen(' . $params[ 0 ] . ')';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.count_paragraphs.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.count_paragraphs.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.count_paragraphs.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.count_paragraphs.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty count_paragraphs modifier plugin
+ * Type:     modifier
+ * Name:     count_paragraphs
+ * Purpose:  count the number of paragraphs in a text
+ *
+ * @link    http://www.smarty.net/manual/en/language.modifier.count.paragraphs.php
+ *          count_paragraphs (Smarty online manual)
+ * @author  Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_count_paragraphs($params)
+{
+    // count \r or \n characters
+    return '(preg_match_all(\'#[\r\n]+#\', ' . $params[ 0 ] . ', $tmp)+1)';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.count_sentences.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.count_sentences.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.count_sentences.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.count_sentences.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty count_sentences modifier plugin
+ * Type:     modifier
+ * Name:     count_sentences
+ * Purpose:  count the number of sentences in a text
+ *
+ * @link    http://www.smarty.net/manual/en/language.modifier.count.paragraphs.php
+ *          count_sentences (Smarty online manual)
+ * @author  Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_count_sentences($params)
+{
+    // find periods, question marks, exclamation marks with a word before but not after.
+    return 'preg_match_all("#\w[\.\?\!](\W|$)#S' . Smarty::$_UTF8_MODIFIER . '", ' . $params[ 0 ] . ', $tmp)';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.count_words.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.count_words.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.count_words.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.count_words.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty count_words modifier plugin
+ * Type:     modifier
+ * Name:     count_words
+ * Purpose:  count the number of words in a text
+ *
+ * @link   http://www.smarty.net/manual/en/language.modifier.count.words.php count_words (Smarty online manual)
+ * @author Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_count_words($params)
+{
+    if (Smarty::$_MBSTRING) {
+        // return 'preg_match_all(\'#[\w\pL]+#' . Smarty::$_UTF8_MODIFIER . '\', ' . $params[0] . ', $tmp)';
+        // expression taken from http://de.php.net/manual/en/function.str-word-count.php#85592
+        return 'preg_match_all(\'/\p{L}[\p{L}\p{Mn}\p{Pd}\\\'\x{2019}]*/' . Smarty::$_UTF8_MODIFIER . '\', ' .
+               $params[ 0 ] . ', $tmp)';
+    }
+    // no MBString fallback
+    return 'str_word_count(' . $params[ 0 ] . ')';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.default.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.default.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.default.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.default.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty default modifier plugin
+ * Type:     modifier
+ * Name:     default
+ * Purpose:  designate default value for empty variables
+ *
+ * @link   http://www.smarty.net/manual/en/language.modifier.default.php default (Smarty online manual)
+ * @author Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_default($params)
+{
+    $output = $params[ 0 ];
+    if (!isset($params[ 1 ])) {
+        $params[ 1 ] = "''";
+    }
+
+    array_shift($params);
+    foreach ($params as $param) {
+        $output = '(($tmp = @' . $output . ')===null||$tmp===\'\' ? ' . $param . ' : $tmp)';
+    }
+
+    return $output;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.escape.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.escape.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.escape.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.escape.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,115 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+/**
+ * Smarty escape modifier plugin
+ * Type:     modifier
+ * Name:     escape
+ * Purpose:  escape string for output
+ *
+ * @link   http://www.smarty.net/docsv2/en/language.modifier.escape count_characters (Smarty online manual)
+ * @author Rodney Rehm
+ *
+ * @param array                                 $params parameters
+ * @param  Smarty_Internal_TemplateCompilerBase $compiler
+ *
+ * @return string with compiled code
+ * @throws \SmartyException
+ */
+function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompilerBase $compiler)
+{
+    static $_double_encode = null;
+    static $is_loaded = false;
+    $compiler->template->_checkPlugins(array(array('function' => 'smarty_literal_compiler_param',
+                                         'file' => SMARTY_PLUGINS_DIR . 'shared.literal_compiler_param.php')));
+    if ($_double_encode === null) {
+        $_double_encode = version_compare(PHP_VERSION, '5.2.3', '>=');
+    }
+
+    try {
+        $esc_type = smarty_literal_compiler_param($params, 1, 'html');
+        $char_set = smarty_literal_compiler_param($params, 2, Smarty::$_CHARSET);
+        $double_encode = smarty_literal_compiler_param($params, 3, true);
+
+        if (!$char_set) {
+            $char_set = Smarty::$_CHARSET;
+        }
+
+        switch ($esc_type) {
+            case 'html':
+                if ($_double_encode) {
+                    return 'htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' .
+                           var_export($double_encode, true) . ')';
+                } elseif ($double_encode) {
+                    return 'htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')';
+                } else {
+                    // fall back to modifier.escape.php
+                }
+
+            case 'htmlall':
+                if (Smarty::$_MBSTRING) {
+                    if ($_double_encode) {
+                        // php >=5.2.3 - go native
+                        return 'mb_convert_encoding(htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' .
+                               var_export($char_set, true) . ', ' . var_export($double_encode, true) .
+                               '), "HTML-ENTITIES", ' . var_export($char_set, true) . ')';
+                    } elseif ($double_encode) {
+                        // php <5.2.3 - only handle double encoding
+                        return 'mb_convert_encoding(htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' .
+                               var_export($char_set, true) . '), "HTML-ENTITIES", ' . var_export($char_set, true) . ')';
+                    } else {
+                        // fall back to modifier.escape.php
+                    }
+                }
+
+                // no MBString fallback
+                if ($_double_encode) {
+                    // php >=5.2.3 - go native
+                    return 'htmlentities(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' .
+                           var_export($double_encode, true) . ')';
+                } elseif ($double_encode) {
+                    // php <5.2.3 - only handle double encoding
+                    return 'htmlentities(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')';
+                } else {
+                    // fall back to modifier.escape.php
+                }
+
+            case 'url':
+                return 'rawurlencode(' . $params[ 0 ] . ')';
+
+            case 'urlpathinfo':
+                return 'str_replace("%2F", "/", rawurlencode(' . $params[ 0 ] . '))';
+
+            case 'quotes':
+                // escape unescaped single quotes
+                return 'preg_replace("%(?<!\\\\\\\\)\'%", "\\\'",' . $params[ 0 ] . ')';
+
+            case 'javascript':
+                // escape quotes and backslashes, newlines, etc.
+                return 'strtr(' . $params[ 0 ] .
+                       ', array("\\\\" => "\\\\\\\\", "\'" => "\\\\\'", "\"" => "\\\\\"", "\\r" => "\\\\r", "\\n" => "\\\n", "</" => "<\/" ))';
+        }
+    }
+    catch (SmartyException $e) {
+        // pass through to regular plugin fallback
+    }
+
+    // could not optimize |escape call, so fallback to regular plugin
+    if ($compiler->template->caching && ($compiler->tag_nocache | $compiler->nocache)) {
+        $compiler->required_plugins[ 'nocache' ][ 'escape' ][ 'modifier' ][ 'file' ] =
+            SMARTY_PLUGINS_DIR . 'modifier.escape.php';
+        $compiler->required_plugins[ 'nocache' ][ 'escape' ][ 'modifier' ][ 'function' ] =
+            'smarty_modifier_escape';
+    } else {
+        $compiler->required_plugins[ 'compiled' ][ 'escape' ][ 'modifier' ][ 'file' ] =
+            SMARTY_PLUGINS_DIR . 'modifier.escape.php';
+        $compiler->required_plugins[ 'compiled' ][ 'escape' ][ 'modifier' ][ 'function' ] =
+            'smarty_modifier_escape';
+    }
+
+    return 'smarty_modifier_escape(' . join(', ', $params) . ')';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.from_charset.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.from_charset.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.from_charset.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.from_charset.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty from_charset modifier plugin
+ * Type:     modifier
+ * Name:     from_charset
+ * Purpose:  convert character encoding from $charset to internal encoding
+ *
+ * @author Rodney Rehm
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_from_charset($params)
+{
+    if (!Smarty::$_MBSTRING) {
+        // FIXME: (rodneyrehm) shouldn't this throw an error?
+        return $params[ 0 ];
+    }
+
+    if (!isset($params[ 1 ])) {
+        $params[ 1 ] = '"ISO-8859-1"';
+    }
+
+    return 'mb_convert_encoding(' . $params[ 0 ] . ', "' . addslashes(Smarty::$_CHARSET) . '", ' . $params[ 1 ] . ')';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.indent.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.indent.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.indent.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.indent.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty indent modifier plugin
+ * Type:     modifier
+ * Name:     indent
+ * Purpose:  indent lines of text
+ *
+ * @link   http://www.smarty.net/manual/en/language.modifier.indent.php indent (Smarty online manual)
+ * @author Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+
+function smarty_modifiercompiler_indent($params)
+{
+    if (!isset($params[ 1 ])) {
+        $params[ 1 ] = 4;
+    }
+    if (!isset($params[ 2 ])) {
+        $params[ 2 ] = "' '";
+    }
+
+    return 'preg_replace(\'!^!m\',str_repeat(' . $params[ 2 ] . ',' . $params[ 1 ] . '),' . $params[ 0 ] . ')';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.lower.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.lower.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.lower.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.lower.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty lower modifier plugin
+ * Type:     modifier
+ * Name:     lower
+ * Purpose:  convert string to lowercase
+ *
+ * @link   http://www.smarty.net/manual/en/language.modifier.lower.php lower (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+
+function smarty_modifiercompiler_lower($params)
+{
+    if (Smarty::$_MBSTRING) {
+        return 'mb_strtolower(' . $params[ 0 ] . ', \'' . addslashes(Smarty::$_CHARSET) . '\')';
+    }
+    // no MBString fallback
+    return 'strtolower(' . $params[ 0 ] . ')';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.noprint.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.noprint.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.noprint.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.noprint.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty noprint modifier plugin
+ * Type:     modifier
+ * Name:     noprint
+ * Purpose:  return an empty string
+ *
+ * @author   Uwe Tews
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_noprint()
+{
+    return "''";
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.string_format.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.string_format.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.string_format.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.string_format.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty string_format modifier plugin
+ * Type:     modifier
+ * Name:     string_format
+ * Purpose:  format strings via sprintf
+ *
+ * @link   http://www.smarty.net/manual/en/language.modifier.string.format.php string_format (Smarty online manual)
+ * @author Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_string_format($params)
+{
+    return 'sprintf(' . $params[ 1 ] . ',' . $params[ 0 ] . ')';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.strip.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.strip.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.strip.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.strip.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty strip modifier plugin
+ * Type:     modifier
+ * Name:     strip
+ * Purpose:  Replace all repeated spaces, newlines, tabs
+ *              with a single space or supplied replacement string.
+ * Example:  {$var|strip} {$var|strip:"&nbsp;"}
+ * Date:     September 25th, 2002
+ *
+ * @link   http://www.smarty.net/manual/en/language.modifier.strip.php strip (Smarty online manual)
+ * @author Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+
+function smarty_modifiercompiler_strip($params)
+{
+    if (!isset($params[ 1 ])) {
+        $params[ 1 ] = "' '";
+    }
+
+    return "preg_replace('!\s+!" . Smarty::$_UTF8_MODIFIER . "', {$params[1]},{$params[0]})";
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.strip_tags.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.strip_tags.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.strip_tags.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.strip_tags.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty strip_tags modifier plugin
+ * Type:     modifier
+ * Name:     strip_tags
+ * Purpose:  strip html tags from text
+ *
+ * @link   http://www.smarty.net/docs/en/language.modifier.strip.tags.tpl strip_tags (Smarty online manual)
+ * @author Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_strip_tags($params)
+{
+    if (!isset($params[ 1 ]) || $params[ 1 ] === true || trim($params[ 1 ], '"') === 'true') {
+        return "preg_replace('!<[^>]*?>!', ' ', {$params[0]})";
+    } else {
+        return 'strip_tags(' . $params[ 0 ] . ')';
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.to_charset.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.to_charset.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.to_charset.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.to_charset.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty to_charset modifier plugin
+ * Type:     modifier
+ * Name:     to_charset
+ * Purpose:  convert character encoding from internal encoding to $charset
+ *
+ * @author Rodney Rehm
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_to_charset($params)
+{
+    if (!Smarty::$_MBSTRING) {
+        // FIXME: (rodneyrehm) shouldn't this throw an error?
+        return $params[ 0 ];
+    }
+
+    if (!isset($params[ 1 ])) {
+        $params[ 1 ] = '"ISO-8859-1"';
+    }
+
+    return 'mb_convert_encoding(' . $params[ 0 ] . ', ' . $params[ 1 ] . ', "' . addslashes(Smarty::$_CHARSET) . '")';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.unescape.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.unescape.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.unescape.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.unescape.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty unescape modifier plugin
+ * Type:     modifier
+ * Name:     unescape
+ * Purpose:  unescape html entities
+ *
+ * @author Rodney Rehm
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_unescape($params)
+{
+    if (!isset($params[ 1 ])) {
+        $params[ 1 ] = 'html';
+    }
+    if (!isset($params[ 2 ])) {
+        $params[ 2 ] = '\'' . addslashes(Smarty::$_CHARSET) . '\'';
+    } else {
+        $params[ 2 ] = "'{$params[ 2 ]}'";
+    }
+
+    switch (trim($params[ 1 ], '"\'')) {
+        case 'entity':
+        case 'htmlall':
+            if (Smarty::$_MBSTRING) {
+                return 'mb_convert_encoding(' . $params[ 0 ] . ', ' . $params[ 2 ] . ', \'HTML-ENTITIES\')';
+            }
+
+            return 'html_entity_decode(' . $params[ 0 ] . ', ENT_NOQUOTES, ' . $params[ 2 ] . ')';
+
+        case 'html':
+            return 'htmlspecialchars_decode(' . $params[ 0 ] . ', ENT_QUOTES)';
+
+        case 'url':
+            return 'rawurldecode(' . $params[ 0 ] . ')';
+
+        default:
+            return $params[ 0 ];
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.upper.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.upper.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.upper.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.upper.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+
+/**
+ * Smarty upper modifier plugin
+ * Type:     modifier
+ * Name:     lower
+ * Purpose:  convert string to uppercase
+ *
+ * @link   http://smarty.php.net/manual/en/language.modifier.upper.php lower (Smarty online manual)
+ * @author Uwe Tews
+ *
+ * @param array $params parameters
+ *
+ * @return string with compiled code
+ */
+function smarty_modifiercompiler_upper($params)
+{
+    if (Smarty::$_MBSTRING) {
+        return 'mb_strtoupper(' . $params[ 0 ] . ', \'' . addslashes(Smarty::$_CHARSET) . '\')';
+    }
+    // no MBString fallback
+    return 'strtoupper(' . $params[ 0 ] . ')';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.wordwrap.php 3.2-2/lib/smarty/libs/plugins/modifiercompiler.wordwrap.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifiercompiler.wordwrap.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifiercompiler.wordwrap.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifierCompiler
+ */
+/**
+ * Smarty wordwrap modifier plugin
+ * Type:     modifier
+ * Name:     wordwrap
+ * Purpose:  wrap a string of text at a given length
+ *
+ * @link   http://smarty.php.net/manual/en/language.modifier.wordwrap.php wordwrap (Smarty online manual)
+ * @author Uwe Tews
+ *
+ * @param array                                 $params parameters
+ * @param \Smarty_Internal_TemplateCompilerBase $compiler
+ *
+ * @return string with compiled code
+ * @throws \SmartyException
+ */
+function smarty_modifiercompiler_wordwrap($params, Smarty_Internal_TemplateCompilerBase $compiler)
+{
+    if (!isset($params[ 1 ])) {
+        $params[ 1 ] = 80;
+    }
+    if (!isset($params[ 2 ])) {
+        $params[ 2 ] = '"\n"';
+    }
+    if (!isset($params[ 3 ])) {
+        $params[ 3 ] = 'false';
+    }
+    $function = 'wordwrap';
+    if (Smarty::$_MBSTRING) {
+        $function = $compiler->getPlugin('mb_wordwrap','modifier');
+    }
+    return $function . '(' . $params[ 0 ] . ',' . $params[ 1 ] . ',' . $params[ 2 ] . ',' . $params[ 3 ] . ')';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifier.date_format.php 3.2-2/lib/smarty/libs/plugins/modifier.date_format.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifier.date_format.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifier.date_format.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty date_format modifier plugin
+ * Type:     modifier
+ * Name:     date_format
+ * Purpose:  format datestamps via strftime
+ * Input:
+ *          - string: input date string
+ *          - format: strftime format for output
+ *          - default_date: default date if $string is empty
+ *
+ * @link   http://www.smarty.net/manual/en/language.modifier.date.format.php date_format (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ *
+ * @param string $string       input date string
+ * @param string $format       strftime format for output
+ * @param string $default_date default date if $string is empty
+ * @param string $formatter    either 'strftime' or 'auto'
+ *
+ * @return string |void
+ * @uses   smarty_make_timestamp()
+ */
+function smarty_modifier_date_format($string, $format = null, $default_date = '', $formatter = 'auto')
+{
+    if ($format === null) {
+        $format = Smarty::$_DATE_FORMAT;
+    }
+    /**
+     * require_once the {@link shared.make_timestamp.php} plugin
+     */
+    static $is_loaded = false;
+    if (!$is_loaded) {
+        if (!is_callable('smarty_make_timestamp')) {
+            require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php');
+        }
+        $is_loaded = true;
+    }
+    if ($string !== '' && $string !== '0000-00-00' && $string !== '0000-00-00 00:00:00') {
+        $timestamp = smarty_make_timestamp($string);
+    } elseif ($default_date !== '') {
+        $timestamp = smarty_make_timestamp($default_date);
+    } else {
+        return;
+    }
+    if ($formatter === 'strftime' || ($formatter === 'auto' && strpos($format, '%') !== false)) {
+        if (Smarty::$_IS_WINDOWS) {
+            $_win_from = array('%D',
+                               '%h',
+                               '%n',
+                               '%r',
+                               '%R',
+                               '%t',
+                               '%T');
+            $_win_to = array('%m/%d/%y',
+                             '%b',
+                             "\n",
+                             '%I:%M:%S %p',
+                             '%H:%M',
+                             "\t",
+                             '%H:%M:%S');
+            if (strpos($format, '%e') !== false) {
+                $_win_from[] = '%e';
+                $_win_to[] = sprintf('%\' 2d', date('j', $timestamp));
+            }
+            if (strpos($format, '%l') !== false) {
+                $_win_from[] = '%l';
+                $_win_to[] = sprintf('%\' 2d', date('h', $timestamp));
+            }
+            $format = str_replace($_win_from, $_win_to, $format);
+        }
+
+        return strftime($format, $timestamp);
+    } else {
+        return date($format, $timestamp);
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifier.debug_print_var.php 3.2-2/lib/smarty/libs/plugins/modifier.debug_print_var.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifier.debug_print_var.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifier.debug_print_var.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage Debug
+ */
+
+/**
+ * Smarty debug_print_var modifier plugin
+ * Type:     modifier
+ * Name:     debug_print_var
+ * Purpose:  formats variable contents for display in the console
+ *
+ * @author Monte Ohrt <monte at ohrt dot com>
+ *
+ * @param array|object $var     variable to be formatted
+ * @param int          $max     maximum recursion depth if $var is an array or object
+ * @param int          $length  maximum string length if $var is a string
+ * @param int          $depth   actual recursion depth
+ * @param array        $objects processed objects in actual depth to prevent recursive object processing
+ *
+ * @return string
+ */
+function smarty_modifier_debug_print_var($var, $max = 10, $length = 40, $depth = 0, $objects = array())
+{
+    $_replace = array("\n" => '\n', "\r" => '\r', "\t" => '\t');
+    switch (gettype($var)) {
+        case 'array' :
+            $results = '<b>Array (' . count($var) . ')</b>';
+            if ($depth === $max) {
+                break;
+            }
+            foreach ($var as $curr_key => $curr_val) {
+                $results .= '<br>' . str_repeat('&nbsp;', $depth * 2) . '<b>' . strtr($curr_key, $_replace) .
+                            '</b> =&gt; ' .
+                            smarty_modifier_debug_print_var($curr_val, $max, $length, ++ $depth, $objects);
+                $depth --;
+            }
+            break;
+
+        case 'object' :
+            $object_vars = get_object_vars($var);
+            $results = '<b>' . get_class($var) . ' Object (' . count($object_vars) . ')</b>';
+            if (in_array($var, $objects)) {
+                $results .= ' called recursive';
+                break;
+            }
+            if ($depth === $max) {
+                break;
+            }
+            $objects[] = $var;
+            foreach ($object_vars as $curr_key => $curr_val) {
+                $results .= '<br>' . str_repeat('&nbsp;', $depth * 2) . '<b> -&gt;' . strtr($curr_key, $_replace) .
+                            '</b> = ' . smarty_modifier_debug_print_var($curr_val, $max, $length, ++ $depth, $objects);
+                $depth --;
+            }
+            break;
+
+        case 'boolean' :
+        case 'NULL' :
+        case 'resource' :
+            if (true === $var) {
+                $results = 'true';
+            } elseif (false === $var) {
+                $results = 'false';
+            } elseif (null === $var) {
+                $results = 'null';
+            } else {
+                $results = htmlspecialchars((string) $var);
+            }
+            $results = '<i>' . $results . '</i>';
+            break;
+
+        case 'integer' :
+        case 'float' :
+            $results = htmlspecialchars((string) $var);
+            break;
+
+        case 'string' :
+            $results = strtr($var, $_replace);
+            if (Smarty::$_MBSTRING) {
+                if (mb_strlen($var, Smarty::$_CHARSET) > $length) {
+                    $results = mb_substr($var, 0, $length - 3, Smarty::$_CHARSET) . '...';
+                }
+            } else {
+                if (isset($var[ $length ])) {
+                    $results = substr($var, 0, $length - 3) . '...';
+                }
+            }
+
+            $results = htmlspecialchars('"' . $results . '"', ENT_QUOTES, Smarty::$_CHARSET);
+            break;
+
+        case 'unknown type' :
+        default :
+            $results = strtr((string) $var, $_replace);
+            if (Smarty::$_MBSTRING) {
+                if (mb_strlen($results, Smarty::$_CHARSET) > $length) {
+                    $results = mb_substr($results, 0, $length - 3, Smarty::$_CHARSET) . '...';
+                }
+            } else {
+                if (strlen($results) > $length) {
+                    $results = substr($results, 0, $length - 3) . '...';
+                }
+            }
+
+            $results = htmlspecialchars($results, ENT_QUOTES, Smarty::$_CHARSET);
+    }
+
+    return $results;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifier.escape.php 3.2-2/lib/smarty/libs/plugins/modifier.escape.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifier.escape.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifier.escape.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,235 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty escape modifier plugin
+ * Type:     modifier
+ * Name:     escape
+ * Purpose:  escape string for output
+ *
+ * @link   http://www.smarty.net/docs/en/language.modifier.escape
+ * @author Monte Ohrt <monte at ohrt dot com>
+ *
+ * @param string  $string        input string
+ * @param string  $esc_type      escape type
+ * @param string  $char_set      character set, used for htmlspecialchars() or htmlentities()
+ * @param boolean $double_encode encode already encoded entitites again, used for htmlspecialchars() or htmlentities()
+ *
+ * @return string escaped input string
+ */
+function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $double_encode = true)
+{
+    static $_double_encode = null;
+    static $is_loaded_1 = false;
+    static $is_loaded_2 = false;
+    if ($_double_encode === null) {
+        $_double_encode = version_compare(PHP_VERSION, '5.2.3', '>=');
+    }
+
+    if (!$char_set) {
+        $char_set = Smarty::$_CHARSET;
+    }
+
+    switch ($esc_type) {
+        case 'html':
+            if ($_double_encode) {
+                // php >=5.3.2 - go native
+                return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode);
+            } else {
+                if ($double_encode) {
+                    // php <5.2.3 - only handle double encoding
+                    return htmlspecialchars($string, ENT_QUOTES, $char_set);
+                } else {
+                    // php <5.2.3 - prevent double encoding
+                    $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);
+                    $string = htmlspecialchars($string, ENT_QUOTES, $char_set);
+                    $string = str_replace(array('%%%SMARTY_START%%%',
+                                                '%%%SMARTY_END%%%'), array('&',
+                                                                           ';'), $string);
+
+                    return $string;
+                }
+            }
+
+        case 'htmlall':
+            if (Smarty::$_MBSTRING) {
+                // mb_convert_encoding ignores htmlspecialchars()
+                if ($_double_encode) {
+                    // php >=5.3.2 - go native
+                    $string = htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode);
+                } else {
+                    if ($double_encode) {
+                        // php <5.2.3 - only handle double encoding
+                        $string = htmlspecialchars($string, ENT_QUOTES, $char_set);
+                    } else {
+                        // php <5.2.3 - prevent double encoding
+                        $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);
+                        $string = htmlspecialchars($string, ENT_QUOTES, $char_set);
+                        $string =
+                            str_replace(array('%%%SMARTY_START%%%',
+                                              '%%%SMARTY_END%%%'), array('&',
+                                                                         ';'), $string);
+
+                        return $string;
+                    }
+                }
+
+                // htmlentities() won't convert everything, so use mb_convert_encoding
+                return mb_convert_encoding($string, 'HTML-ENTITIES', $char_set);
+            }
+
+            // no MBString fallback
+            if ($_double_encode) {
+                return htmlentities($string, ENT_QUOTES, $char_set, $double_encode);
+            } else {
+                if ($double_encode) {
+                    return htmlentities($string, ENT_QUOTES, $char_set);
+                } else {
+                    $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);
+                    $string = htmlentities($string, ENT_QUOTES, $char_set);
+                    $string = str_replace(array('%%%SMARTY_START%%%',
+                                                '%%%SMARTY_END%%%'), array('&',
+                                                                           ';'), $string);
+
+                    return $string;
+                }
+            }
+
+        case 'url':
+            return rawurlencode($string);
+
+        case 'urlpathinfo':
+            return str_replace('%2F', '/', rawurlencode($string));
+
+        case 'quotes':
+            // escape unescaped single quotes
+            return preg_replace("%(?<!\\\\)'%", "\\'", $string);
+
+        case 'hex':
+            // escape every byte into hex
+            // Note that the UTF-8 encoded character Ã¤ will be represented as %c3%a4
+            $return = '';
+            $_length = strlen($string);
+            for ($x = 0; $x < $_length; $x ++) {
+                $return .= '%' . bin2hex($string[ $x ]);
+            }
+
+            return $return;
+
+        case 'hexentity':
+            $return = '';
+            if (Smarty::$_MBSTRING) {
+                if (!$is_loaded_1) {
+                    if (!is_callable('smarty_mb_to_unicode')) {
+                        require_once(SMARTY_PLUGINS_DIR . 'shared.mb_unicode.php');
+                    }
+                    $is_loaded_1 = true;
+                }
+                $return = '';
+                foreach (smarty_mb_to_unicode($string, Smarty::$_CHARSET) as $unicode) {
+                    $return .= '&#x' . strtoupper(dechex($unicode)) . ';';
+                }
+
+                return $return;
+            }
+            // no MBString fallback
+            $_length = strlen($string);
+            for ($x = 0; $x < $_length; $x ++) {
+                $return .= '&#x' . bin2hex($string[ $x ]) . ';';
+            }
+
+            return $return;
+
+        case 'decentity':
+            $return = '';
+            if (Smarty::$_MBSTRING) {
+                if (!$is_loaded_1) {
+                    if (!is_callable('smarty_mb_to_unicode')) {
+                        require_once(SMARTY_PLUGINS_DIR . 'shared.mb_unicode.php');
+                    }
+                    $is_loaded_1 = true;
+                }
+                $return = '';
+                foreach (smarty_mb_to_unicode($string, Smarty::$_CHARSET) as $unicode) {
+                    $return .= '&#' . $unicode . ';';
+                }
+
+                return $return;
+            }
+            // no MBString fallback
+            $_length = strlen($string);
+            for ($x = 0; $x < $_length; $x ++) {
+                $return .= '&#' . ord($string[ $x ]) . ';';
+            }
+
+            return $return;
+
+        case 'javascript':
+            // escape quotes and backslashes, newlines, etc.
+            return strtr($string, array('\\' => '\\\\',
+                                        "'" => "\\'",
+                                        '"' => '\\"',
+                                        "\r" => '\\r',
+                                        "\n" => '\\n',
+                                        '</' => '<\/'));
+
+        case 'mail':
+            if (Smarty::$_MBSTRING) {
+                if (!$is_loaded_2) {
+                    if (!is_callable('smarty_mb_str_replace')) {
+                        require_once(SMARTY_PLUGINS_DIR . 'shared.mb_str_replace.php');
+                    }
+                    $is_loaded_2 = true;
+                }
+                return smarty_mb_str_replace(array('@',
+                                                   '.'), array(' [AT] ',
+                                                               ' [DOT] '), $string);
+            }
+            // no MBString fallback
+            return str_replace(array('@',
+                                     '.'), array(' [AT] ',
+                                                 ' [DOT] '), $string);
+
+        case 'nonstd':
+            // escape non-standard chars, such as ms document quotes
+            $return = '';
+            if (Smarty::$_MBSTRING) {
+                if (!$is_loaded_1) {
+                    if (!is_callable('smarty_mb_to_unicode')) {
+                        require_once(SMARTY_PLUGINS_DIR . 'shared.mb_unicode.php');
+                    }
+                    $is_loaded_1 = true;
+                }
+                foreach (smarty_mb_to_unicode($string, Smarty::$_CHARSET) as $unicode) {
+                    if ($unicode >= 126) {
+                        $return .= '&#' . $unicode . ';';
+                    } else {
+                        $return .= chr($unicode);
+                    }
+                }
+
+                return $return;
+            }
+
+            $_length = strlen($string);
+            for ($_i = 0; $_i < $_length; $_i ++) {
+                $_ord = ord(substr($string, $_i, 1));
+                // non-standard char, escape it
+                if ($_ord >= 126) {
+                    $return .= '&#' . $_ord . ';';
+                } else {
+                    $return .= substr($string, $_i, 1);
+                }
+            }
+
+            return $return;
+
+        default:
+            return $string;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifier.mb_wordwrap.php 3.2-2/lib/smarty/libs/plugins/modifier.mb_wordwrap.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifier.mb_wordwrap.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifier.mb_wordwrap.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifier
+ */
+/**
+ * Smarty wordwrap modifier plugin
+ * Type:     modifier
+ * Name:     mb_wordwrap
+ * Purpose:  Wrap a string to a given number of characters
+ *
+
+ * @link   http://php.net/manual/en/function.wordwrap.php for similarity
+ *
+ * @param  string  $str   the string to wrap
+ * @param  int     $width the width of the output
+ * @param  string  $break the character used to break the line
+ * @param  boolean $cut   ignored parameter, just for the sake of
+ *
+ * @return string  wrapped string
+ * @author Rodney Rehm
+ */
+function smarty_modifier_mb_wordwrap($str, $width = 75, $break = "\n", $cut = false)
+{
+    // break words into tokens using white space as a delimiter
+    $tokens = preg_split('!(\s)!S' . Smarty::$_UTF8_MODIFIER, $str, -1, PREG_SPLIT_NO_EMPTY + PREG_SPLIT_DELIM_CAPTURE);
+    $length = 0;
+    $t = '';
+    $_previous = false;
+    $_space = false;
+
+    foreach ($tokens as $_token) {
+        $token_length = mb_strlen($_token, Smarty::$_CHARSET);
+        $_tokens = array($_token);
+        if ($token_length > $width) {
+            if ($cut) {
+                $_tokens = preg_split('!(.{' . $width . '})!S' . Smarty::$_UTF8_MODIFIER,
+                                      $_token,
+                                      -1,
+                                      PREG_SPLIT_NO_EMPTY + PREG_SPLIT_DELIM_CAPTURE);
+            }
+        }
+
+        foreach ($_tokens as $token) {
+            $_space = !!preg_match('!^\s$!S' . Smarty::$_UTF8_MODIFIER, $token);
+            $token_length = mb_strlen($token, Smarty::$_CHARSET);
+            $length += $token_length;
+
+            if ($length > $width) {
+                // remove space before inserted break
+                if ($_previous) {
+                    $t = mb_substr($t, 0, -1, Smarty::$_CHARSET);
+                }
+
+                if (!$_space) {
+                    // add the break before the token
+                    if (!empty($t)) {
+                        $t .= $break;
+                    }
+                    $length = $token_length;
+                }
+            } else if ($token === "\n") {
+                // hard break must reset counters
+                $length = 0;
+            }
+            $_previous = $_space;
+            // add the token
+            $t .= $token;
+        }
+    }
+
+    return $t;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifier.regex_replace.php 3.2-2/lib/smarty/libs/plugins/modifier.regex_replace.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifier.regex_replace.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifier.regex_replace.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty regex_replace modifier plugin
+ * Type:     modifier
+ * Name:     regex_replace
+ * Purpose:  regular expression search/replace
+ *
+ * @link    http://smarty.php.net/manual/en/language.modifier.regex.replace.php
+ *          regex_replace (Smarty online manual)
+ * @author  Monte Ohrt <monte at ohrt dot com>
+ *
+ * @param string       $string  input string
+ * @param string|array $search  regular expression(s) to search for
+ * @param string|array $replace string(s) that should be replaced
+ * @param int          $limit   the maximum number of replacements
+ *
+ * @return string
+ */
+function smarty_modifier_regex_replace($string, $search, $replace, $limit = - 1)
+{
+    if (is_array($search)) {
+        foreach ($search as $idx => $s) {
+            $search[ $idx ] = _smarty_regex_replace_check($s);
+        }
+    } else {
+        $search = _smarty_regex_replace_check($search);
+    }
+
+    return preg_replace($search, $replace, $string, $limit);
+}
+
+/**
+ * @param  string $search string(s) that should be replaced
+ *
+ * @return string
+ * @ignore
+ */
+function _smarty_regex_replace_check($search)
+{
+    // null-byte injection detection
+    // anything behind the first null-byte is ignored
+    if (($pos = strpos($search, "\0")) !== false) {
+        $search = substr($search, 0, $pos);
+    }
+    // remove eval-modifier from $search
+    if (preg_match('!([a-zA-Z\s]+)$!s', $search, $match) && (strpos($match[ 1 ], 'e') !== false)) {
+        $search = substr($search, 0, - strlen($match[ 1 ])) . preg_replace('![e\s]+!', '', $match[ 1 ]);
+    }
+
+    return $search;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifier.replace.php 3.2-2/lib/smarty/libs/plugins/modifier.replace.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifier.replace.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifier.replace.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty replace modifier plugin
+ * Type:     modifier
+ * Name:     replace
+ * Purpose:  simple search/replace
+ *
+ * @link   http://smarty.php.net/manual/en/language.modifier.replace.php replace (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Uwe Tews
+ *
+ * @param string $string  input string
+ * @param string $search  text to search for
+ * @param string $replace replacement text
+ *
+ * @return string
+ */
+function smarty_modifier_replace($string, $search, $replace)
+{
+    static $is_loaded = false;
+    if (Smarty::$_MBSTRING) {
+        if (!$is_loaded) {
+            if (!is_callable('smarty_mb_str_replace')) {
+                require_once(SMARTY_PLUGINS_DIR . 'shared.mb_str_replace.php');
+            }
+            $is_loaded = true;
+        }
+         return smarty_mb_str_replace($search, $replace, $string);
+    }
+
+    return str_replace($search, $replace, $string);
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifier.spacify.php 3.2-2/lib/smarty/libs/plugins/modifier.spacify.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifier.spacify.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifier.spacify.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty spacify modifier plugin
+ * Type:     modifier
+ * Name:     spacify
+ * Purpose:  add spaces between characters in a string
+ *
+ * @link   http://smarty.php.net/manual/en/language.modifier.spacify.php spacify (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ *
+ * @param string $string       input string
+ * @param string $spacify_char string to insert between characters.
+ *
+ * @return string
+ */
+function smarty_modifier_spacify($string, $spacify_char = ' ')
+{
+    // wellâ€¦ what about charsets besides latin and UTF-8?
+    return implode($spacify_char, preg_split('//' . Smarty::$_UTF8_MODIFIER, $string, - 1, PREG_SPLIT_NO_EMPTY));
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/modifier.truncate.php 3.2-2/lib/smarty/libs/plugins/modifier.truncate.php
--- 3.0.2-2/lib/smarty/libs/plugins/modifier.truncate.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/modifier.truncate.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsModifier
+ */
+
+/**
+ * Smarty truncate modifier plugin
+ * Type:     modifier
+ * Name:     truncate
+ * Purpose:  Truncate a string to a certain length if necessary,
+ *               optionally splitting in the middle of a word, and
+ *               appending the $etc string or inserting $etc into the middle.
+ *
+ * @link   http://smarty.php.net/manual/en/language.modifier.truncate.php truncate (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ *
+ * @param string  $string      input string
+ * @param integer $length      length of truncated text
+ * @param string  $etc         end string
+ * @param boolean $break_words truncate at word boundary
+ * @param boolean $middle      truncate in the middle of text
+ *
+ * @return string truncated string
+ */
+function smarty_modifier_truncate($string, $length = 80, $etc = '...', $break_words = false, $middle = false)
+{
+    if ($length === 0) {
+        return '';
+    }
+
+    if (Smarty::$_MBSTRING) {
+        if (mb_strlen($string, Smarty::$_CHARSET) > $length) {
+            $length -= min($length, mb_strlen($etc, Smarty::$_CHARSET));
+            if (!$break_words && !$middle) {
+                $string = preg_replace('/\s+?(\S+)?$/' . Smarty::$_UTF8_MODIFIER, '',
+                                       mb_substr($string, 0, $length + 1, Smarty::$_CHARSET));
+            }
+            if (!$middle) {
+                return mb_substr($string, 0, $length, Smarty::$_CHARSET) . $etc;
+            }
+
+            return mb_substr($string, 0, $length / 2, Smarty::$_CHARSET) . $etc .
+                   mb_substr($string, - $length / 2, $length, Smarty::$_CHARSET);
+        }
+
+        return $string;
+    }
+
+    // no MBString fallback
+    if (isset($string[ $length ])) {
+        $length -= min($length, strlen($etc));
+        if (!$break_words && !$middle) {
+            $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length + 1));
+        }
+        if (!$middle) {
+            return substr($string, 0, $length) . $etc;
+        }
+
+        return substr($string, 0, $length / 2) . $etc . substr($string, - $length / 2);
+    }
+
+    return $string;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/outputfilter.trimwhitespace.php 3.2-2/lib/smarty/libs/plugins/outputfilter.trimwhitespace.php
--- 3.0.2-2/lib/smarty/libs/plugins/outputfilter.trimwhitespace.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/outputfilter.trimwhitespace.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFilter
+ */
+
+/**
+ * Smarty trimwhitespace outputfilter plugin
+ * Trim unnecessary whitespace from HTML markup.
+ *
+ * @author   Rodney Rehm
+ *
+ * @param string $source input string
+ *
+ * @return string filtered output
+ * @todo     substr_replace() is not overloaded by mbstring.func_overload - so this function might fail!
+ */
+function smarty_outputfilter_trimwhitespace($source)
+{
+    $store = array();
+    $_store = 0;
+    $_offset = 0;
+
+    // Unify Line-Breaks to \n
+    $source = preg_replace('/\015\012|\015|\012/', "\n", $source);
+
+    // capture Internet Explorer and KnockoutJS Conditional Comments
+    if (preg_match_all('#<!--((\[[^\]]+\]>.*?<!\[[^\]]+\])|(\s*/?ko\s+.+))-->#is', $source, $matches,
+                       PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
+        foreach ($matches as $match) {
+            $store[] = $match[ 0 ][ 0 ];
+            $_length = strlen($match[ 0 ][ 0 ]);
+            $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@';
+            $source = substr_replace($source, $replace, $match[ 0 ][ 1 ] - $_offset, $_length);
+
+            $_offset += $_length - strlen($replace);
+            $_store ++;
+        }
+    }
+
+    // Strip all HTML-Comments
+    // yes, even the ones in <script> - see http://stackoverflow.com/a/808850/515124
+    $source = preg_replace('#<!--.*?-->#ms', '', $source);
+
+    // capture html elements not to be messed with
+    $_offset = 0;
+    if (preg_match_all('#(<script[^>]*>.*?</script[^>]*>)|(<textarea[^>]*>.*?</textarea[^>]*>)|(<pre[^>]*>.*?</pre[^>]*>)#is',
+                       $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
+        foreach ($matches as $match) {
+            $store[] = $match[ 0 ][ 0 ];
+            $_length = strlen($match[ 0 ][ 0 ]);
+            $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@';
+            $source = substr_replace($source, $replace, $match[ 0 ][ 1 ] - $_offset, $_length);
+
+            $_offset += $_length - strlen($replace);
+            $_store ++;
+        }
+    }
+
+    $expressions = array(// replace multiple spaces between tags by a single space
+                         // can't remove them entirely, becaue that might break poorly implemented CSS display:inline-block elements
+                         '#(:SMARTY@!@|>)\s+(?=@!@SMARTY:|<)#s' => '\1 \2',
+                         // remove spaces between attributes (but not in attribute values!)
+                         '#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5',
+                         // note: for some very weird reason trim() seems to remove spaces inside attributes.
+                         // maybe a \0 byte or something is interfering?
+                         '#^\s+<#Ss' => '<', '#>\s+$#Ss' => '>',);
+
+    $source = preg_replace(array_keys($expressions), array_values($expressions), $source);
+    // note: for some very weird reason trim() seems to remove spaces inside attributes.
+    // maybe a \0 byte or something is interfering?
+    // $source = trim( $source );
+
+    $_offset = 0;
+    if (preg_match_all('#@!@SMARTY:([0-9]+):SMARTY@!@#is', $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
+        foreach ($matches as $match) {
+            $_length = strlen($match[ 0 ][ 0 ]);
+            $replace = $store[ $match[ 1 ][ 0 ] ];
+            $source = substr_replace($source, $replace, $match[ 0 ][ 1 ] + $_offset, $_length);
+
+            $_offset += strlen($replace) - $_length;
+            $_store ++;
+        }
+    }
+
+    return $source;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/shared.escape_special_chars.php 3.2-2/lib/smarty/libs/plugins/shared.escape_special_chars.php
--- 3.0.2-2/lib/smarty/libs/plugins/shared.escape_special_chars.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/shared.escape_special_chars.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Smarty shared plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsShared
+ */
+
+/**
+ * escape_special_chars common function
+ * Function: smarty_function_escape_special_chars
+ * Purpose:  used by other smarty functions to escape
+ *           special chars except for already escaped ones
+ *
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ *
+ * @param  string $string text that should by escaped
+ *
+ * @return string
+ */
+function smarty_function_escape_special_chars($string)
+{
+    if (!is_array($string)) {
+        if (version_compare(PHP_VERSION, '5.2.3', '>=')) {
+            $string = htmlspecialchars($string, ENT_COMPAT, Smarty::$_CHARSET, false);
+        } else {
+            $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);
+            $string = htmlspecialchars($string);
+            $string = str_replace(array('%%%SMARTY_START%%%', '%%%SMARTY_END%%%'), array('&', ';'), $string);
+        }
+    }
+
+    return $string;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/shared.literal_compiler_param.php 3.2-2/lib/smarty/libs/plugins/shared.literal_compiler_param.php
--- 3.0.2-2/lib/smarty/libs/plugins/shared.literal_compiler_param.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/shared.literal_compiler_param.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsShared
+ */
+
+/**
+ * evaluate compiler parameter
+ *
+ * @param array   $params  parameter array as given to the compiler function
+ * @param integer $index   array index of the parameter to convert
+ * @param mixed   $default value to be returned if the parameter is not present
+ *
+ * @return mixed evaluated value of parameter or $default
+ * @throws SmartyException if parameter is not a literal (but an expression, variable, â€¦)
+ * @author Rodney Rehm
+ */
+function smarty_literal_compiler_param($params, $index, $default = null)
+{
+    // not set, go default
+    if (!isset($params[ $index ])) {
+        return $default;
+    }
+    // test if param is a literal
+    if (!preg_match('/^([\'"]?)[a-zA-Z0-9-]+(\\1)$/', $params[ $index ])) {
+        throw new SmartyException('$param[' . $index .
+                                  '] is not a literal and is thus not evaluatable at compile time');
+    }
+
+    $t = null;
+    eval("\$t = " . $params[ $index ] . ";");
+
+    return $t;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/shared.make_timestamp.php 3.2-2/lib/smarty/libs/plugins/shared.make_timestamp.php
--- 3.0.2-2/lib/smarty/libs/plugins/shared.make_timestamp.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/shared.make_timestamp.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Smarty shared plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsShared
+ */
+
+/**
+ * Function: smarty_make_timestamp
+ * Purpose:  used by other smarty functions to make a timestamp from a string.
+ *
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ *
+ * @param DateTime|int|string $string date object, timestamp or string that can be converted using strtotime()
+ *
+ * @return int
+ */
+function smarty_make_timestamp($string)
+{
+    if (empty($string)) {
+        // use "now":
+        return time();
+    } elseif ($string instanceof DateTime ||
+              (interface_exists('DateTimeInterface', false) && $string instanceof DateTimeInterface)
+    ) {
+        return (int) $string->format('U'); // PHP 5.2 BC
+    } elseif (strlen($string) === 14 && ctype_digit($string)) {
+        // it is mysql timestamp format of YYYYMMDDHHMMSS?
+        return mktime(substr($string, 8, 2), substr($string, 10, 2), substr($string, 12, 2), substr($string, 4, 2),
+                      substr($string, 6, 2), substr($string, 0, 4));
+    } elseif (is_numeric($string)) {
+        // it is a numeric string, we handle it as timestamp
+        return (int) $string;
+    } else {
+        // strtotime should handle it
+        $time = strtotime($string);
+        if ($time === - 1 || $time === false) {
+            // strtotime() was not able to parse $string, use "now":
+            return time();
+        }
+
+        return $time;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/shared.mb_str_replace.php 3.2-2/lib/smarty/libs/plugins/shared.mb_str_replace.php
--- 3.0.2-2/lib/smarty/libs/plugins/shared.mb_str_replace.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/shared.mb_str_replace.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Smarty shared plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsShared
+ */
+if (!function_exists('smarty_mb_str_replace')) {
+    /**
+     * Multibyte string replace
+     *
+     * @param  string|string[] $search  the string to be searched
+     * @param  string|string[] $replace the replacement string
+     * @param  string          $subject the source string
+     * @param  int             &$count  number of matches found
+     *
+     * @return string replaced string
+     * @author Rodney Rehm
+     */
+    function smarty_mb_str_replace($search, $replace, $subject, &$count = 0)
+    {
+        if (!is_array($search) && is_array($replace)) {
+            return false;
+        }
+        if (is_array($subject)) {
+            // call mb_replace for each single string in $subject
+            foreach ($subject as &$string) {
+                $string = smarty_mb_str_replace($search, $replace, $string, $c);
+                $count += $c;
+            }
+        } else if (is_array($search)) {
+            if (!is_array($replace)) {
+                foreach ($search as &$string) {
+                    $subject = smarty_mb_str_replace($string, $replace, $subject, $c);
+                    $count += $c;
+                }
+            } else {
+                $n = max(count($search), count($replace));
+                while ($n--) {
+                    $subject = smarty_mb_str_replace(current($search), current($replace), $subject, $c);
+                    $count += $c;
+                    next($search);
+                    next($replace);
+                }
+            }
+        } else {
+            $parts = mb_split(preg_quote($search), $subject);
+            $count = count($parts) - 1;
+            $subject = implode($replace, $parts);
+        }
+        return $subject;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/shared.mb_unicode.php 3.2-2/lib/smarty/libs/plugins/shared.mb_unicode.php
--- 3.0.2-2/lib/smarty/libs/plugins/shared.mb_unicode.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/shared.mb_unicode.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Smarty shared plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsShared
+ */
+
+/**
+ * convert characters to their decimal unicode equivalents
+ *
+ * @link   http://www.ibm.com/developerworks/library/os-php-unicode/index.html#listing3 for inspiration
+ *
+ * @param string $string   characters to calculate unicode of
+ * @param string $encoding encoding of $string, if null mb_internal_encoding() is used
+ *
+ * @return array sequence of unicodes
+ * @author Rodney Rehm
+ */
+function smarty_mb_to_unicode($string, $encoding = null)
+{
+    if ($encoding) {
+        $expanded = mb_convert_encoding($string, 'UTF-32BE', $encoding);
+    } else {
+        $expanded = mb_convert_encoding($string, 'UTF-32BE');
+    }
+
+    return unpack('N*', $expanded);
+}
+
+/**
+ * convert unicodes to the character of given encoding
+ *
+ * @link   http://www.ibm.com/developerworks/library/os-php-unicode/index.html#listing3 for inspiration
+ *
+ * @param integer|array $unicode  single unicode or list of unicodes to convert
+ * @param string        $encoding encoding of returned string, if null mb_internal_encoding() is used
+ *
+ * @return string unicode as character sequence in given $encoding
+ * @author Rodney Rehm
+ */
+function smarty_mb_from_unicode($unicode, $encoding = null)
+{
+    $t = '';
+    if (!$encoding) {
+        $encoding = mb_internal_encoding();
+    }
+    foreach ((array) $unicode as $utf32be) {
+        $character = pack('N*', $utf32be);
+        $t .= mb_convert_encoding($character, $encoding, 'UTF-32BE');
+    }
+
+    return $t;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/plugins/variablefilter.htmlspecialchars.php 3.2-2/lib/smarty/libs/plugins/variablefilter.htmlspecialchars.php
--- 3.0.2-2/lib/smarty/libs/plugins/variablefilter.htmlspecialchars.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/plugins/variablefilter.htmlspecialchars.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Smarty plugin
+ *
+ * @package    Smarty
+ * @subpackage PluginsFilter
+ */
+/**
+ * Smarty htmlspecialchars variablefilter plugin
+ *
+ * @param string                    $source input string
+ * @param \Smarty_Internal_Template $template
+ *
+ * @return string filtered output
+ */
+function smarty_variablefilter_htmlspecialchars($source, Smarty_Internal_Template $template)
+{
+    return htmlspecialchars($source, ENT_QUOTES, Smarty::$_CHARSET);
+}
diff -pruN 3.0.2-2/lib/smarty/libs/SmartyBC.class.php 3.2-2/lib/smarty/libs/SmartyBC.class.php
--- 3.0.2-2/lib/smarty/libs/SmartyBC.class.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/SmartyBC.class.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,474 @@
+<?php
+/**
+ * Project:     Smarty: the PHP compiling template engine
+ * File:        SmartyBC.class.php
+ * SVN:         $Id: $
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * For questions, help, comments, discussion, etc., please join the
+ * Smarty mailing list. Send a blank e-mail to
+ * smarty-discussion-subscribe@googlegroups.com
+ *
+ * @link      http://www.smarty.net/
+ * @copyright 2008 New Digital Group, Inc.
+ * @author    Monte Ohrt <monte at ohrt dot com>
+ * @author    Uwe Tews
+ * @author    Rodney Rehm
+ * @package   Smarty
+ */
+/**
+ * @ignore
+ */
+require_once(dirname(__FILE__) . '/Smarty.class.php');
+
+/**
+ * Smarty Backward Compatibility Wrapper Class
+ *
+ * @package Smarty
+ */
+class SmartyBC extends Smarty
+{
+    /**
+     * Smarty 2 BC
+     *
+     * @var string
+     */
+    public $_version = self::SMARTY_VERSION;
+
+    /**
+     * This is an array of directories where trusted php scripts reside.
+     *
+     * @var array
+     */
+    public $trusted_dir = array();
+
+    /**
+     * Initialize new SmartyBC object
+     *
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * wrapper for assign_by_ref
+     *
+     * @param string $tpl_var the template variable name
+     * @param mixed  &$value  the referenced value to assign
+     */
+    public function assign_by_ref($tpl_var, &$value)
+    {
+        $this->assignByRef($tpl_var, $value);
+    }
+
+    /**
+     * wrapper for append_by_ref
+     *
+     * @param string  $tpl_var the template variable name
+     * @param mixed   &$value  the referenced value to append
+     * @param boolean $merge   flag if array elements shall be merged
+     */
+    public function append_by_ref($tpl_var, &$value, $merge = false)
+    {
+        $this->appendByRef($tpl_var, $value, $merge);
+    }
+
+    /**
+     * clear the given assigned template variable.
+     *
+     * @param string $tpl_var the template variable to clear
+     */
+    public function clear_assign($tpl_var)
+    {
+        $this->clearAssign($tpl_var);
+    }
+
+    /**
+     * Registers custom function to be used in templates
+     *
+     * @param string $function      the name of the template function
+     * @param string $function_impl the name of the PHP function to register
+     * @param bool   $cacheable
+     * @param mixed  $cache_attrs
+     *
+     * @throws \SmartyException
+     */
+    public function register_function($function, $function_impl, $cacheable = true, $cache_attrs = null)
+    {
+        $this->registerPlugin('function', $function, $function_impl, $cacheable, $cache_attrs);
+    }
+
+    /**
+     * Unregister custom function
+     *
+     * @param string $function name of template function
+     */
+    public function unregister_function($function)
+    {
+        $this->unregisterPlugin('function', $function);
+    }
+
+    /**
+     * Registers object to be used in templates
+     *
+     * @param string  $object        name of template object
+     * @param object  $object_impl   the referenced PHP object to register
+     * @param array   $allowed       list of allowed methods (empty = all)
+     * @param boolean $smarty_args   smarty argument format, else traditional
+     * @param array   $block_methods list of methods that are block format
+     *
+     * @throws SmartyException
+     * @internal param array $block_functs list of methods that are block format
+     */
+    public function register_object($object, $object_impl, $allowed = array(), $smarty_args = true,
+                                    $block_methods = array())
+    {
+        settype($allowed, 'array');
+        settype($smarty_args, 'boolean');
+        $this->registerObject($object, $object_impl, $allowed, $smarty_args, $block_methods);
+    }
+
+    /**
+     * Unregister object
+     *
+     * @param string $object name of template object
+     */
+    public function unregister_object($object)
+    {
+        $this->unregisterObject($object);
+    }
+
+    /**
+     * Registers block function to be used in templates
+     *
+     * @param string $block      name of template block
+     * @param string $block_impl PHP function to register
+     * @param bool   $cacheable
+     * @param mixed  $cache_attrs
+     *
+     * @throws \SmartyException
+     */
+    public function register_block($block, $block_impl, $cacheable = true, $cache_attrs = null)
+    {
+        $this->registerPlugin('block', $block, $block_impl, $cacheable, $cache_attrs);
+    }
+
+    /**
+     * Unregister block function
+     *
+     * @param string $block name of template function
+     */
+    public function unregister_block($block)
+    {
+        $this->unregisterPlugin('block', $block);
+    }
+
+    /**
+     * Registers compiler function
+     *
+     * @param string $function      name of template function
+     * @param string $function_impl name of PHP function to register
+     * @param bool   $cacheable
+     *
+     * @throws \SmartyException
+     */
+    public function register_compiler_function($function, $function_impl, $cacheable = true)
+    {
+        $this->registerPlugin('compiler', $function, $function_impl, $cacheable);
+    }
+
+    /**
+     * Unregister compiler function
+     *
+     * @param string $function name of template function
+     */
+    public function unregister_compiler_function($function)
+    {
+        $this->unregisterPlugin('compiler', $function);
+    }
+
+    /**
+     * Registers modifier to be used in templates
+     *
+     * @param string $modifier      name of template modifier
+     * @param string $modifier_impl name of PHP function to register
+     *
+     * @throws \SmartyException
+     */
+    public function register_modifier($modifier, $modifier_impl)
+    {
+        $this->registerPlugin('modifier', $modifier, $modifier_impl);
+    }
+
+    /**
+     * Unregister modifier
+     *
+     * @param string $modifier name of template modifier
+     */
+    public function unregister_modifier($modifier)
+    {
+        $this->unregisterPlugin('modifier', $modifier);
+    }
+
+    /**
+     * Registers a resource to fetch a template
+     *
+     * @param string $type      name of resource
+     * @param array  $functions array of functions to handle resource
+     */
+    public function register_resource($type, $functions)
+    {
+        $this->registerResource($type, $functions);
+    }
+
+    /**
+     * Unregister a resource
+     *
+     * @param string $type name of resource
+     */
+    public function unregister_resource($type)
+    {
+        $this->unregisterResource($type);
+    }
+
+    /**
+     * Registers a prefilter function to apply
+     * to a template before compiling
+     *
+     * @param callable $function
+     *
+     * @throws \SmartyException
+     */
+    public function register_prefilter($function)
+    {
+        $this->registerFilter('pre', $function);
+    }
+
+    /**
+     * Unregister a prefilter function
+     *
+     * @param callable $function
+     */
+    public function unregister_prefilter($function)
+    {
+        $this->unregisterFilter('pre', $function);
+    }
+
+    /**
+     * Registers a postfilter function to apply
+     * to a compiled template after compilation
+     *
+     * @param callable $function
+     *
+     * @throws \SmartyException
+     */
+    public function register_postfilter($function)
+    {
+        $this->registerFilter('post', $function);
+    }
+
+    /**
+     * Unregister a postfilter function
+     *
+     * @param callable $function
+     */
+    public function unregister_postfilter($function)
+    {
+        $this->unregisterFilter('post', $function);
+    }
+
+    /**
+     * Registers an output filter function to apply
+     * to a template output
+     *
+     * @param callable $function
+     *
+     * @throws \SmartyException
+     */
+    public function register_outputfilter($function)
+    {
+        $this->registerFilter('output', $function);
+    }
+
+    /**
+     * Unregister an outputfilter function
+     *
+     * @param callable $function
+     */
+    public function unregister_outputfilter($function)
+    {
+        $this->unregisterFilter('output', $function);
+    }
+
+    /**
+     * load a filter of specified type and name
+     *
+     * @param string $type filter type
+     * @param string $name filter name
+     *
+     * @throws \SmartyException
+     */
+    public function load_filter($type, $name)
+    {
+        $this->loadFilter($type, $name);
+    }
+
+    /**
+     * clear cached content for the given template and cache id
+     *
+     * @param  string $tpl_file   name of template file
+     * @param  string $cache_id   name of cache_id
+     * @param  string $compile_id name of compile_id
+     * @param  string $exp_time   expiration time
+     *
+     * @return boolean
+     */
+    public function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null)
+    {
+        return $this->clearCache($tpl_file, $cache_id, $compile_id, $exp_time);
+    }
+
+    /**
+     * clear the entire contents of cache (all templates)
+     *
+     * @param  string $exp_time expire time
+     *
+     * @return boolean
+     */
+    public function clear_all_cache($exp_time = null)
+    {
+        return $this->clearCache(null, null, null, $exp_time);
+    }
+
+    /**
+     * test to see if valid cache exists for this template
+     *
+     * @param  string $tpl_file name of template file
+     * @param  string $cache_id
+     * @param  string $compile_id
+     *
+     * @return bool
+     * @throws \Exception
+     * @throws \SmartyException
+     */
+    public function is_cached($tpl_file, $cache_id = null, $compile_id = null)
+    {
+        return $this->isCached($tpl_file, $cache_id, $compile_id);
+    }
+
+    /**
+     * clear all the assigned template variables.
+     */
+    public function clear_all_assign()
+    {
+        $this->clearAllAssign();
+    }
+
+    /**
+     * clears compiled version of specified template resource,
+     * or all compiled template files if one is not specified.
+     * This function is for advanced use only, not normally needed.
+     *
+     * @param  string $tpl_file
+     * @param  string $compile_id
+     * @param  string $exp_time
+     *
+     * @return boolean results of {@link smarty_core_rm_auto()}
+     */
+    public function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null)
+    {
+        return $this->clearCompiledTemplate($tpl_file, $compile_id, $exp_time);
+    }
+
+    /**
+     * Checks whether requested template exists.
+     *
+     * @param  string $tpl_file
+     *
+     * @return bool
+     * @throws \SmartyException
+     */
+    public function template_exists($tpl_file)
+    {
+        return $this->templateExists($tpl_file);
+    }
+
+    /**
+     * Returns an array containing template variables
+     *
+     * @param  string $name
+     *
+     * @return array
+     */
+    public function get_template_vars($name = null)
+    {
+        return $this->getTemplateVars($name);
+    }
+
+    /**
+     * Returns an array containing config variables
+     *
+     * @param  string $name
+     *
+     * @return array
+     */
+    public function get_config_vars($name = null)
+    {
+        return $this->getConfigVars($name);
+    }
+
+    /**
+     * load configuration values
+     *
+     * @param string $file
+     * @param string $section
+     * @param string $scope
+     */
+    public function config_load($file, $section = null, $scope = 'global')
+    {
+        $this->ConfigLoad($file, $section, $scope);
+    }
+
+    /**
+     * return a reference to a registered object
+     *
+     * @param  string $name
+     *
+     * @return object
+     */
+    public function get_registered_object($name)
+    {
+        return $this->getRegisteredObject($name);
+    }
+
+    /**
+     * clear configuration values
+     *
+     * @param string $var
+     */
+    public function clear_config($var = null)
+    {
+        $this->clearConfig($var);
+    }
+
+    /**
+     * trigger Smarty error
+     *
+     * @param string  $error_msg
+     * @param integer $error_type
+     */
+    public function trigger_error($error_msg, $error_type = E_USER_WARNING)
+    {
+        trigger_error("Smarty error: $error_msg", $error_type);
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/Smarty.class.php 3.2-2/lib/smarty/libs/Smarty.class.php
--- 3.0.2-2/lib/smarty/libs/Smarty.class.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/Smarty.class.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,1372 @@
+<?php
+/**
+ * Project:     Smarty: the PHP compiling template engine
+ * File:        Smarty.class.php
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * For questions, help, comments, discussion, etc., please join the
+ * Smarty mailing list. Send a blank e-mail to
+ * smarty-discussion-subscribe@googlegroups.com
+ *
+ * @link      http://www.smarty.net/
+ * @copyright 2018 New Digital Group, Inc.
+ * @copyright 2018 Uwe Tews
+ * @author    Monte Ohrt <monte at ohrt dot com>
+ * @author    Uwe Tews   <uwe dot tews at gmail dot com>
+ * @author    Rodney Rehm
+ * @package   Smarty
+ * @version   3.1.32
+ */
+/**
+ * set SMARTY_DIR to absolute path to Smarty library files.
+ * Sets SMARTY_DIR only if user application has not already defined it.
+ */
+if (!defined('SMARTY_DIR')) {
+    /**
+     *
+     */
+    define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR);
+}
+/**
+ * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins.
+ * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it.
+ */
+if (!defined('SMARTY_SYSPLUGINS_DIR')) {
+    /**
+     *
+     */
+    define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR);
+}
+if (!defined('SMARTY_PLUGINS_DIR')) {
+    /**
+     *
+     */
+    define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DIRECTORY_SEPARATOR);
+}
+if (!defined('SMARTY_MBSTRING')) {
+    /**
+     *
+     */
+    define('SMARTY_MBSTRING', function_exists('mb_get_info'));
+}
+if (!defined('SMARTY_RESOURCE_CHAR_SET')) {
+    // UTF-8 can only be done properly when mbstring is available!
+    /**
+     * @deprecated in favor of Smarty::$_CHARSET
+     */
+    define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1');
+}
+if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) {
+    /**
+     * @deprecated in favor of Smarty::$_DATE_FORMAT
+     */
+    define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y');
+}
+/**
+ * Load Smarty_Autoloader
+ */
+if (!class_exists('Smarty_Autoloader')) {
+    include dirname(__FILE__) . '/bootstrap.php';
+}
+/**
+ * Load always needed external class files
+ */
+require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php';
+require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_extension_handler.php';
+require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php';
+require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php';
+require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php';
+require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php';
+require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php';
+require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_resource_base.php';
+require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php';
+
+/**
+ * This is the main Smarty class
+ *
+ * @package Smarty
+ *
+ * The following methods will be dynamically loaded by the extension handler when they are called.
+ * They are located in a corresponding Smarty_Internal_Method_xxxx class
+ *
+ * @method int clearAllCache(int $exp_time = null, string $type = null)
+ * @method int clearCache(string $template_name, string $cache_id = null, string $compile_id = null, int $exp_time = null, string $type = null)
+ * @method int compileAllTemplates(string $extension = '.tpl', bool $force_compile = false, int $time_limit = 0, $max_errors = null)
+ * @method int compileAllConfig(string $extension = '.conf', bool $force_compile = false, int $time_limit = 0, $max_errors = null)
+ * @method int clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
+ */
+class Smarty extends Smarty_Internal_TemplateBase
+{
+    /**
+     * smarty version
+     */
+    const SMARTY_VERSION = '3.1.32';
+    /**
+     * define variable scopes
+     */
+    const SCOPE_LOCAL    = 1;
+    const SCOPE_PARENT   = 2;
+    const SCOPE_TPL_ROOT = 4;
+    const SCOPE_ROOT     = 8;
+    const SCOPE_SMARTY   = 16;
+    const SCOPE_GLOBAL   = 32;
+    /**
+     * define caching modes
+     */
+    const CACHING_OFF              = 0;
+    const CACHING_LIFETIME_CURRENT = 1;
+    const CACHING_LIFETIME_SAVED   = 2;
+    /**
+     * define constant for clearing cache files be saved expiration dates
+     */
+    const CLEAR_EXPIRED = -1;
+    /**
+     * define compile check modes
+     */
+    const COMPILECHECK_OFF       = 0;
+    const COMPILECHECK_ON        = 1;
+    const COMPILECHECK_CACHEMISS = 2;
+    /**
+     * define debug modes
+     */
+    const DEBUG_OFF        = 0;
+    const DEBUG_ON         = 1;
+    const DEBUG_INDIVIDUAL = 2;
+    /**
+     * modes for handling of "<?php ... ?>" tags in templates.
+     */
+    const PHP_PASSTHRU = 0; //-> print tags as plain text
+    const PHP_QUOTE    = 1; //-> escape tags as entities
+    const PHP_REMOVE   = 2; //-> escape tags as entities
+    const PHP_ALLOW    = 3; //-> escape tags as entities
+    /**
+     * filter types
+     */
+    const FILTER_POST     = 'post';
+    const FILTER_PRE      = 'pre';
+    const FILTER_OUTPUT   = 'output';
+    const FILTER_VARIABLE = 'variable';
+    /**
+     * plugin types
+     */
+    const PLUGIN_FUNCTION         = 'function';
+    const PLUGIN_BLOCK            = 'block';
+    const PLUGIN_COMPILER         = 'compiler';
+    const PLUGIN_MODIFIER         = 'modifier';
+    const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler';
+    /**
+     * assigned global tpl vars
+     */
+    public static $global_tpl_vars = array();
+    /**
+     * Flag denoting if Multibyte String functions are available
+     */
+    public static $_MBSTRING = SMARTY_MBSTRING;
+    /**
+     * The character set to adhere to (e.g. "UTF-8")
+     */
+    public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET;
+    /**
+     * The date format to be used internally
+     * (accepts date() and strftime())
+     */
+    public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT;
+    /**
+     * Flag denoting if PCRE should run in UTF-8 mode
+     */
+    public static $_UTF8_MODIFIER = 'u';
+    /**
+     * Flag denoting if operating system is windows
+     */
+    public static $_IS_WINDOWS = false;
+    /**
+     * auto literal on delimiters with whitespace
+     *
+     * @var boolean
+     */
+    public $auto_literal = true;
+    /**
+     * display error on not assigned variables
+     *
+     * @var boolean
+     */
+    public $error_unassigned = false;
+    /**
+     * look up relative file path in include_path
+     *
+     * @var boolean
+     */
+    public $use_include_path = false;
+    /**
+     * flag if template_dir is normalized
+     *
+     * @var bool
+     */
+    public $_templateDirNormalized = false;
+    /**
+     * joined template directory string used in cache keys
+     *
+     * @var string
+     */
+    public $_joined_template_dir = null;
+    /**
+     * flag if config_dir is normalized
+     *
+     * @var bool
+     */
+    public $_configDirNormalized = false;
+    /**
+     * joined config directory string used in cache keys
+     *
+     * @var string
+     */
+    public $_joined_config_dir = null;
+    /**
+     * default template handler
+     *
+     * @var callable
+     */
+    public $default_template_handler_func = null;
+    /**
+     * default config handler
+     *
+     * @var callable
+     */
+    public $default_config_handler_func = null;
+    /**
+     * default plugin handler
+     *
+     * @var callable
+     */
+    public $default_plugin_handler_func = null;
+    /**
+     * flag if template_dir is normalized
+     *
+     * @var bool
+     */
+    public $_compileDirNormalized = false;
+    /**
+     * flag if plugins_dir is normalized
+     *
+     * @var bool
+     */
+    public $_pluginsDirNormalized = false;
+    /**
+     * flag if template_dir is normalized
+     *
+     * @var bool
+     */
+    public $_cacheDirNormalized = false;
+    /**
+     * force template compiling?
+     *
+     * @var boolean
+     */
+    public $force_compile = false;
+     /**
+     * use sub dirs for compiled/cached files?
+     *
+     * @var boolean
+     */
+    public $use_sub_dirs = false;
+    /**
+     * allow ambiguous resources (that are made unique by the resource handler)
+     *
+     * @var boolean
+     */
+    public $allow_ambiguous_resources = false;
+    /**
+     * merge compiled includes
+     *
+     * @var boolean
+     */
+    public $merge_compiled_includes = false;
+    /*
+    * flag for behaviour when extends: resource  and {extends} tag are used simultaneous
+    *   if false disable execution of {extends} in templates called by extends resource.
+    *   (behaviour as versions < 3.1.28)
+    *
+    * @var boolean
+    */
+    public $extends_recursion = true;
+    /**
+     * force cache file creation
+     *
+     * @var boolean
+     */
+    public $force_cache = false;
+    /**
+     * template left-delimiter
+     *
+     * @var string
+     */
+    public $left_delimiter = "{";
+    /**
+     * template right-delimiter
+     *
+     * @var string
+     */
+    public $right_delimiter = "}";
+    /**
+     * array of strings which shall be treated as literal by compiler
+     *
+     * @var array string
+     */
+    public $literals = array();
+    /**
+     * class name
+     * This should be instance of Smarty_Security.
+     *
+     * @var string
+     * @see Smarty_Security
+     */
+    public $security_class = 'Smarty_Security';
+    /**
+     * implementation of security class
+     *
+     * @var Smarty_Security
+     */
+    public $security_policy = null;
+    /**
+     * controls handling of PHP-blocks
+     *
+     * @var integer
+     */
+    public $php_handling = self::PHP_PASSTHRU;
+    /**
+     * controls if the php template file resource is allowed
+     *
+     * @var bool
+     */
+    public $allow_php_templates = false;
+    /**
+     * debug mode
+     * Setting this to true enables the debug-console.
+     *
+     * @var boolean
+     */
+    public $debugging = false;
+    /**
+     * This determines if debugging is enable-able from the browser.
+     * <ul>
+     *  <li>NONE => no debugging control allowed</li>
+     *  <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
+     * </ul>
+     *
+     * @var string
+     */
+    public $debugging_ctrl = 'NONE';
+    /**
+     * Name of debugging URL-param.
+     * Only used when $debugging_ctrl is set to 'URL'.
+     * The name of the URL-parameter that activates debugging.
+     *
+     * @var string
+     */
+    public $smarty_debug_id = 'SMARTY_DEBUG';
+    /**
+     * Path of debug template.
+     *
+     * @var string
+     */
+    public $debug_tpl = null;
+    /**
+     * When set, smarty uses this value as error_reporting-level.
+     *
+     * @var int
+     */
+    public $error_reporting = null;
+    /**
+     * Controls whether variables with the same name overwrite each other.
+     *
+     * @var boolean
+     */
+    public $config_overwrite = true;
+    /**
+     * Controls whether config values of on/true/yes and off/false/no get converted to boolean.
+     *
+     * @var boolean
+     */
+    public $config_booleanize = true;
+    /**
+     * Controls whether hidden config sections/vars are read from the file.
+     *
+     * @var boolean
+     */
+    public $config_read_hidden = false;
+    /**
+     * locking concurrent compiles
+     *
+     * @var boolean
+     */
+    public $compile_locking = true;
+    /**
+     * Controls whether cache resources should use locking mechanism
+     *
+     * @var boolean
+     */
+    public $cache_locking = false;
+    /**
+     * seconds to wait for acquiring a lock before ignoring the write lock
+     *
+     * @var float
+     */
+    public $locking_timeout = 10;
+    /**
+     * resource type used if none given
+     * Must be an valid key of $registered_resources.
+     *
+     * @var string
+     */
+    public $default_resource_type = 'file';
+    /**
+     * caching type
+     * Must be an element of $cache_resource_types.
+     *
+     * @var string
+     */
+    public $caching_type = 'file';
+    /**
+     * config type
+     *
+     * @var string
+     */
+    public $default_config_type = 'file';
+    /**
+     * check If-Modified-Since headers
+     *
+     * @var boolean
+     */
+    public $cache_modified_check = false;
+    /**
+     * registered plugins
+     *
+     * @var array
+     */
+    public $registered_plugins = array();
+    /**
+     * registered objects
+     *
+     * @var array
+     */
+    public $registered_objects = array();
+    /**
+     * registered classes
+     *
+     * @var array
+     */
+    public $registered_classes = array();
+    /**
+     * registered filters
+     *
+     * @var array
+     */
+    public $registered_filters = array();
+    /**
+     * registered resources
+     *
+     * @var array
+     */
+    public $registered_resources = array();
+    /**
+     * registered cache resources
+     *
+     * @var array
+     */
+    public $registered_cache_resources = array();
+    /**
+     * autoload filter
+     *
+     * @var array
+     */
+    public $autoload_filters = array();
+    /**
+     * default modifier
+     *
+     * @var array
+     */
+    public $default_modifiers = array();
+    /**
+     * autoescape variable output
+     *
+     * @var boolean
+     */
+    public $escape_html = false;
+    /**
+     * start time for execution time calculation
+     *
+     * @var int
+     */
+    public $start_time = 0;
+    /**
+     * required by the compiler for BC
+     *
+     * @var string
+     */
+    public $_current_file = null;
+    /**
+     * internal flag to enable parser debugging
+     *
+     * @var bool
+     */
+    public $_parserdebug = false;
+    /**
+     * This object type (Smarty = 1, template = 2, data = 4)
+     *
+     * @var int
+     */
+    public $_objType = 1;
+    /**
+     * Debug object
+     *
+     * @var Smarty_Internal_Debug
+     */
+    public $_debug = null;
+    /**
+     * template directory
+     *
+     * @var array
+     */
+    protected $template_dir = array('./templates/');
+    /**
+     * flags for normalized template directory entries
+     *
+     * @var array
+     */
+    protected $_processedTemplateDir = array();
+    /**
+     * config directory
+     *
+     * @var array
+     */
+    protected $config_dir = array('./configs/');
+    /**
+     * flags for normalized template directory entries
+     *
+     * @var array
+     */
+    protected $_processedConfigDir = array();
+    /**
+     * compile directory
+     *
+     * @var string
+     */
+    protected $compile_dir = './templates_c/';
+    /**
+     * plugins directory
+     *
+     * @var array
+     */
+    protected $plugins_dir = array();
+    /**
+     * cache directory
+     *
+     * @var string
+     */
+    protected $cache_dir = './cache/';
+    /**
+     * removed properties
+     *
+     * @var string[]
+     */
+    protected $obsoleteProperties = array('resource_caching', 'template_resource_caching', 'direct_access_security',
+                                          '_dir_perms', '_file_perms', 'plugin_search_order',
+                                          'inheritance_merge_compiled_includes', 'resource_cache_mode',);
+    /**
+     * List of private properties which will call getter/setter on a direct access
+     *
+     * @var string[]
+     */
+    protected $accessMap = array('template_dir' => 'TemplateDir', 'config_dir' => 'ConfigDir',
+                                 'plugins_dir'  => 'PluginsDir', 'compile_dir' => 'CompileDir',
+                                 'cache_dir'    => 'CacheDir',);
+
+    /**
+     * Initialize new Smarty object
+     */
+    public function __construct()
+    {
+        $this->_clearTemplateCache();
+        parent::__construct();
+        if (is_callable('mb_internal_encoding')) {
+            mb_internal_encoding(Smarty::$_CHARSET);
+        }
+        $this->start_time = microtime(true);
+        if (isset($_SERVER[ 'SCRIPT_NAME' ])) {
+            Smarty::$global_tpl_vars[ 'SCRIPT_NAME' ] = new Smarty_Variable($_SERVER[ 'SCRIPT_NAME' ]);
+        }
+        // Check if we're running on windows
+        Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
+        // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8
+        if (Smarty::$_CHARSET !== 'UTF-8') {
+            Smarty::$_UTF8_MODIFIER = '';
+        }
+    }
+
+    /**
+     * Enable error handler to mute expected messages
+     *
+     * @return boolean
+     * @deprecated
+     */
+    public static function muteExpectedErrors()
+    {
+        return Smarty_Internal_ErrorHandler::muteExpectedErrors();
+    }
+
+    /**
+     * Disable error handler muting expected messages
+     *
+     * @deprecated
+     */
+    public static function unmuteExpectedErrors()
+    {
+        restore_error_handler();
+    }
+
+    /**
+     * Check if a template resource exists
+     *
+     * @param  string $resource_name template name
+     *
+     * @return bool status
+     * @throws \SmartyException
+     */
+    public function templateExists($resource_name)
+    {
+        // create source object
+        $source = Smarty_Template_Source::load(null, $this, $resource_name);
+        return $source->exists;
+    }
+
+    /**
+     * Loads security class and enables security
+     *
+     * @param  string|Smarty_Security $security_class if a string is used, it must be class-name
+     *
+     * @return Smarty                 current Smarty instance for chaining
+     * @throws SmartyException        when an invalid class name is provided
+     */
+    public function enableSecurity($security_class = null)
+    {
+        Smarty_Security::enableSecurity($this, $security_class);
+        return $this;
+    }
+
+    /**
+     * Disable security
+     *
+     * @return Smarty current Smarty instance for chaining
+     */
+    public function disableSecurity()
+    {
+        $this->security_policy = null;
+        return $this;
+    }
+
+    /**
+     * Add template directory(s)
+     *
+     * @param  string|array $template_dir directory(s) of template sources
+     * @param  string       $key          of the array element to assign the template dir to
+     * @param bool          $isConfig     true for config_dir
+     *
+     * @return Smarty          current Smarty instance for chaining
+     */
+    public function addTemplateDir($template_dir, $key = null, $isConfig = false)
+    {
+        if ($isConfig) {
+            $processed = &$this->_processedConfigDir;
+            $dir = &$this->config_dir;
+            $this->_configDirNormalized = false;
+        } else {
+            $processed = &$this->_processedTemplateDir;
+            $dir = &$this->template_dir;
+            $this->_templateDirNormalized = false;
+        }
+        if (is_array($template_dir)) {
+            foreach ($template_dir as $k => $v) {
+                if (is_int($k)) {
+                    // indexes are not merged but appended
+                    $dir[] = $v;
+                } else {
+                    // string indexes are overridden
+                    $dir[ $k ] = $v;
+                    unset($processed[ $key ]);
+                }
+            }
+        } else {
+            if ($key !== null) {
+                // override directory at specified index
+                $dir[ $key ] = $template_dir;
+                unset($processed[ $key ]);
+            } else {
+                // append new directory
+                $dir[] = $template_dir;
+            }
+        }
+        return $this;
+    }
+
+    /**
+     * Get template directories
+     *
+     * @param mixed $index    index of directory to get, null to get all
+     * @param bool  $isConfig true for config_dir
+     *
+     * @return array list of template directories, or directory of $index
+     */
+    public function getTemplateDir($index = null, $isConfig = false)
+    {
+        if ($isConfig) {
+            $dir = &$this->config_dir;
+        } else {
+            $dir = &$this->template_dir;
+        }
+        if ($isConfig ? !$this->_configDirNormalized : !$this->_templateDirNormalized) {
+            $this->_normalizeTemplateConfig($isConfig);
+        }
+        if ($index !== null) {
+            return isset($dir[ $index ]) ? $dir[ $index ] : null;
+        }
+        return $dir;
+    }
+
+    /**
+     * Set template directory
+     *
+     * @param  string|array $template_dir directory(s) of template sources
+     * @param bool          $isConfig     true for config_dir
+     *
+     * @return \Smarty current Smarty instance for chaining
+     */
+    public function setTemplateDir($template_dir, $isConfig = false)
+    {
+        if ($isConfig) {
+            $this->config_dir = array();
+            $this->_processedConfigDir = array();
+        } else {
+            $this->template_dir = array();
+            $this->_processedTemplateDir = array();
+        }
+        $this->addTemplateDir($template_dir, null, $isConfig);
+        return $this;
+    }
+
+    /**
+     * Add config directory(s)
+     *
+     * @param string|array $config_dir directory(s) of config sources
+     * @param mixed        $key        key of the array element to assign the config dir to
+     *
+     * @return Smarty current Smarty instance for chaining
+     */
+    public function addConfigDir($config_dir, $key = null)
+    {
+        return $this->addTemplateDir($config_dir, $key, true);
+    }
+
+    /**
+     * Get config directory
+     *
+     * @param mixed $index index of directory to get, null to get all
+     *
+     * @return array configuration directory
+     */
+    public function getConfigDir($index = null)
+    {
+        return $this->getTemplateDir($index, true);
+    }
+
+    /**
+     * Set config directory
+     *
+     * @param $config_dir
+     *
+     * @return Smarty       current Smarty instance for chaining
+     */
+    public function setConfigDir($config_dir)
+    {
+        return $this->setTemplateDir($config_dir, true);
+    }
+
+    /**
+     * Adds directory of plugin files
+     *
+     * @param null|array|string $plugins_dir
+     *
+     * @return Smarty current Smarty instance for chaining
+     */
+    public function addPluginsDir($plugins_dir)
+    {
+        if (empty($this->plugins_dir)) {
+            $this->plugins_dir[] = SMARTY_PLUGINS_DIR;
+        }
+        $this->plugins_dir = array_merge($this->plugins_dir, (array)$plugins_dir);
+        $this->_pluginsDirNormalized = false;
+        return $this;
+    }
+
+    /**
+     * Get plugin directories
+     *
+     * @return array list of plugin directories
+     */
+    public function getPluginsDir()
+    {
+        if (empty($this->plugins_dir)) {
+            $this->plugins_dir[] = SMARTY_PLUGINS_DIR;
+            $this->_pluginsDirNormalized = false;
+        }
+        if (!$this->_pluginsDirNormalized) {
+            if (!is_array($this->plugins_dir)) {
+                $this->plugins_dir = (array)$this->plugins_dir;
+            }
+            foreach ($this->plugins_dir as $k => $v) {
+                $this->plugins_dir[ $k ] = $this->_realpath(rtrim($v, "/\\") . DIRECTORY_SEPARATOR, true);
+            }
+            $this->_cache[ 'plugin_files' ] = array();
+            $this->_pluginsDirNormalized = true;
+        }
+        return $this->plugins_dir;
+    }
+
+    /**
+     * Set plugins directory
+     *
+     * @param  string|array $plugins_dir directory(s) of plugins
+     *
+     * @return Smarty       current Smarty instance for chaining
+     */
+    public function setPluginsDir($plugins_dir)
+    {
+        $this->plugins_dir = (array)$plugins_dir;
+        $this->_pluginsDirNormalized = false;
+        return $this;
+    }
+
+    /**
+     * Get compiled directory
+     *
+     * @return string path to compiled templates
+     */
+    public function getCompileDir()
+    {
+        if (!$this->_compileDirNormalized) {
+            $this->_normalizeDir('compile_dir', $this->compile_dir);
+            $this->_compileDirNormalized = true;
+        }
+        return $this->compile_dir;
+    }
+
+    /**
+     *
+     * @param  string $compile_dir directory to store compiled templates in
+     *
+     * @return Smarty current Smarty instance for chaining
+     */
+    public function setCompileDir($compile_dir)
+    {
+        $this->_normalizeDir('compile_dir', $compile_dir);
+        $this->_compileDirNormalized = true;
+        return $this;
+    }
+
+    /**
+     * Get cache directory
+     *
+     * @return string path of cache directory
+     */
+    public function getCacheDir()
+    {
+        if (!$this->_cacheDirNormalized) {
+            $this->_normalizeDir('cache_dir', $this->cache_dir);
+            $this->_cacheDirNormalized = true;
+        }
+        return $this->cache_dir;
+    }
+
+    /**
+     * Set cache directory
+     *
+     * @param  string $cache_dir directory to store cached templates in
+     *
+     * @return Smarty current Smarty instance for chaining
+     */
+    public function setCacheDir($cache_dir)
+    {
+        $this->_normalizeDir('cache_dir', $cache_dir);
+        $this->_cacheDirNormalized = true;
+        return $this;
+    }
+
+    /**
+     * creates a template object
+     *
+     * @param  string  $template   the resource handle of the template file
+     * @param  mixed   $cache_id   cache id to be used with this template
+     * @param  mixed   $compile_id compile id to be used with this template
+     * @param  object  $parent     next higher level of Smarty variables
+     * @param  boolean $do_clone   flag is Smarty object shall be cloned
+     *
+     * @return \Smarty_Internal_Template template object
+     * @throws \SmartyException
+     */
+    public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true)
+    {
+        if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) {
+            $parent = $cache_id;
+            $cache_id = null;
+        }
+        if ($parent !== null && is_array($parent)) {
+            $data = $parent;
+            $parent = null;
+        } else {
+            $data = null;
+        }
+        if (!$this->_templateDirNormalized) {
+            $this->_normalizeTemplateConfig(false);
+        }
+        $_templateId = $this->_getTemplateId($template, $cache_id, $compile_id);
+        $tpl = null;
+        if ($this->caching && isset(Smarty_Internal_Template::$isCacheTplObj[ $_templateId ])) {
+            $tpl = $do_clone ? clone Smarty_Internal_Template::$isCacheTplObj[ $_templateId ] :
+                Smarty_Internal_Template::$isCacheTplObj[ $_templateId ];
+            $tpl->inheritance = null;
+            $tpl->tpl_vars = $tpl->config_vars = array();
+        } else if (!$do_clone && isset(Smarty_Internal_Template::$tplObjCache[ $_templateId ])) {
+            $tpl = clone Smarty_Internal_Template::$tplObjCache[ $_templateId ];
+            $tpl->inheritance = null;
+            $tpl->tpl_vars = $tpl->config_vars = array();
+        } else {
+            /* @var Smarty_Internal_Template $tpl */
+            $tpl = new $this->template_class($template, $this, null, $cache_id, $compile_id, null, null);
+            $tpl->templateId = $_templateId;
+        }
+        if ($do_clone) {
+            $tpl->smarty = clone $tpl->smarty;
+        }
+        $tpl->parent = $parent ? $parent : $this;
+        // fill data if present
+        if (!empty($data) && is_array($data)) {
+            // set up variable values
+            foreach ($data as $_key => $_val) {
+                $tpl->tpl_vars[ $_key ] = new Smarty_Variable($_val);
+            }
+        }
+        if ($this->debugging || $this->debugging_ctrl === 'URL') {
+            $tpl->smarty->_debug = new Smarty_Internal_Debug();
+            // check URL debugging control
+            if (!$this->debugging && $this->debugging_ctrl === 'URL') {
+                $tpl->smarty->_debug->debugUrl($tpl->smarty);
+            }
+        }
+        return $tpl;
+    }
+
+    /**
+     * Takes unknown classes and loads plugin files for them
+     * class name format: Smarty_PluginType_PluginName
+     * plugin filename format: plugintype.pluginname.php
+     *
+     * @param  string $plugin_name class plugin name to load
+     * @param  bool   $check       check if already loaded
+     *
+     * @throws SmartyException
+     * @return string |boolean filepath of loaded file or false
+     */
+    public function loadPlugin($plugin_name, $check = true)
+    {
+        return $this->ext->loadPlugin->loadPlugin($this, $plugin_name, $check);
+    }
+
+    /**
+     * Get unique template id
+     *
+     * @param string                    $template_name
+     * @param null|mixed                $cache_id
+     * @param null|mixed                $compile_id
+     * @param null                      $caching
+     * @param \Smarty_Internal_Template $template
+     *
+     * @return string
+     * @throws \SmartyException
+     */
+    public function _getTemplateId($template_name,
+                                   $cache_id = null,
+                                   $compile_id = null,
+                                   $caching = null,
+                                   Smarty_Internal_Template $template = null)
+    {
+        $template_name = (strpos($template_name, ':') === false) ? "{$this->default_resource_type}:{$template_name}" :
+            $template_name;
+        $cache_id = $cache_id === null ? $this->cache_id : $cache_id;
+        $compile_id = $compile_id === null ? $this->compile_id : $compile_id;
+        $caching = (int)($caching === null ? $this->caching : $caching);
+        if ((isset($template) && strpos($template_name, ':.') !== false) || $this->allow_ambiguous_resources) {
+            $_templateId =
+                Smarty_Resource::getUniqueTemplateName((isset($template) ? $template : $this), $template_name) .
+                "#{$cache_id}#{$compile_id}#{$caching}";
+        } else {
+            $_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}#{$caching}";
+        }
+        if (isset($_templateId[ 150 ])) {
+            $_templateId = sha1($_templateId);
+        }
+        return $_templateId;
+    }
+
+    /**
+     * Normalize path
+     *  - remove /./ and /../
+     *  - make it absolute if required
+     *
+     * @param string $path      file path
+     * @param bool   $realpath  if true - convert to absolute
+     *                          false - convert to relative
+     *                          null - keep as it is but remove /./ /../
+     *
+     * @return string
+     */
+    public function _realpath($path, $realpath = null)
+    {
+        static $nds = null;
+        static $sepDotsep = null;
+        static $sepDot = null;
+        static $sepSep =null;
+        if (!isset($nds)) {
+            $nds = array('/' => '\\', '\\' => '/');
+            $sepDotsep = DIRECTORY_SEPARATOR . '.' . DIRECTORY_SEPARATOR;
+            $sepDot = DIRECTORY_SEPARATOR . '.';
+            $sepSep = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
+        }
+        // normalize DIRECTORY_SEPARATOR
+        $path = str_replace(array($nds[DIRECTORY_SEPARATOR], $sepDotsep), DIRECTORY_SEPARATOR, $path);
+        if (strpos($path,$sepDot) === false && (($realpath === false && $path[0] === '.') || $realpath === null) && $path[0] !== '\\') {
+            return $path;
+        }
+        preg_match('%^(?<root>(?:[[:alpha:]]:[\\\\]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?<path>(.*))$%u',
+                   $path,
+                   $parts);
+        $path = $parts[ 'path' ];
+        if ($parts[ 'root' ] === '\\') {
+            $parts[ 'root' ] = substr(getcwd(), 0, 2) . $parts[ 'root' ];
+        } else {
+            if ($realpath !== null && !$parts[ 'root' ]) {
+                $path = getcwd() . DIRECTORY_SEPARATOR . $path;
+            }
+        }
+       // remove noop 'DIRECTORY_SEPARATOR DIRECTORY_SEPARATOR' and 'DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR' patterns
+        $path = str_replace(array($sepDotsep,$sepSep), DIRECTORY_SEPARATOR, $path);
+        // resolve '..DIRECTORY_SEPARATOR' pattern, smallest first
+        if (strpos($path, '..' . DIRECTORY_SEPARATOR) !== false &&
+            preg_match_all('#[\\\\/]([.][.][\\\\/])+#u', $path, $match)
+        ) {
+            $counts = array();
+            foreach ($match[ 0 ] as $m) {
+                $counts[] = (int)((strlen($m) - 1) / 3);
+            }
+            sort($counts);
+            foreach ($counts as $count) {
+                $path = preg_replace('#([\\\\/]+[^\\\\/]+){' . $count .
+                                     '}[\\\\/]+([.][.][\\\\/]+){' . $count . '}#u',
+                                     DIRECTORY_SEPARATOR,
+                                     $path);
+            }
+        }
+        return $realpath !== false ? $parts[ 'root' ] . $path : str_ireplace(getcwd(), '.', $parts[ 'root' ] . $path);
+    }
+
+    /**
+     * Empty template objects cache
+     */
+    public function _clearTemplateCache()
+    {
+        Smarty_Internal_Template::$isCacheTplObj = array();
+        Smarty_Internal_Template::$tplObjCache = array();
+    }
+
+    /**
+     * @param boolean $use_sub_dirs
+     */
+    public function setUseSubDirs($use_sub_dirs)
+    {
+        $this->use_sub_dirs = $use_sub_dirs;
+    }
+
+    /**
+     * @param int $error_reporting
+     */
+    public function setErrorReporting($error_reporting)
+    {
+        $this->error_reporting = $error_reporting;
+    }
+
+    /**
+     * @param boolean $escape_html
+     */
+    public function setEscapeHtml($escape_html)
+    {
+        $this->escape_html = $escape_html;
+    }
+
+    /**
+     * Return auto_literal flag
+     *
+     * @return boolean
+     */
+    public function getAutoLiteral()
+    {
+        return $this->auto_literal;
+    }
+
+    /**
+     * Set auto_literal flag
+     *
+     * @param boolean $auto_literal
+     */
+    public function setAutoLiteral($auto_literal = true)
+    {
+        $this->auto_literal = $auto_literal;
+    }
+
+    /**
+     * @param boolean $force_compile
+     */
+    public function setForceCompile($force_compile)
+    {
+        $this->force_compile = $force_compile;
+    }
+
+    /**
+     * @param boolean $merge_compiled_includes
+     */
+    public function setMergeCompiledIncludes($merge_compiled_includes)
+    {
+        $this->merge_compiled_includes = $merge_compiled_includes;
+    }
+
+    /**
+     * Get left delimiter
+     *
+     * @return string
+     */
+    public function getLeftDelimiter()
+    {
+        return $this->left_delimiter;
+    }
+
+    /**
+     * Set left delimiter
+     *
+     * @param string $left_delimiter
+     */
+    public function setLeftDelimiter($left_delimiter)
+    {
+        $this->left_delimiter = $left_delimiter;
+    }
+
+    /**
+     * Get right delimiter
+     *
+     * @return string $right_delimiter
+     */
+    public function getRightDelimiter()
+    {
+        return $this->right_delimiter;
+    }
+
+    /**
+     * Set right delimiter
+     *
+     * @param string
+     */
+    public function setRightDelimiter($right_delimiter)
+    {
+        $this->right_delimiter = $right_delimiter;
+    }
+
+    /**
+     * @param boolean $debugging
+     */
+    public function setDebugging($debugging)
+    {
+        $this->debugging = $debugging;
+    }
+
+    /**
+     * @param boolean $config_overwrite
+     */
+    public function setConfigOverwrite($config_overwrite)
+    {
+        $this->config_overwrite = $config_overwrite;
+    }
+
+    /**
+     * @param boolean $config_booleanize
+     */
+    public function setConfigBooleanize($config_booleanize)
+    {
+        $this->config_booleanize = $config_booleanize;
+    }
+
+    /**
+     * @param boolean $config_read_hidden
+     */
+    public function setConfigReadHidden($config_read_hidden)
+    {
+        $this->config_read_hidden = $config_read_hidden;
+    }
+
+    /**
+     * @param boolean $compile_locking
+     */
+    public function setCompileLocking($compile_locking)
+    {
+        $this->compile_locking = $compile_locking;
+    }
+
+    /**
+     * @param string $default_resource_type
+     */
+    public function setDefaultResourceType($default_resource_type)
+    {
+        $this->default_resource_type = $default_resource_type;
+    }
+
+    /**
+     * @param string $caching_type
+     */
+    public function setCachingType($caching_type)
+    {
+        $this->caching_type = $caching_type;
+    }
+
+    /**
+     * Test install
+     *
+     * @param null $errors
+     */
+    public function testInstall(&$errors = null)
+    {
+        Smarty_Internal_TestInstall::testInstall($this, $errors);
+    }
+
+    /**
+     * Get Smarty object
+     *
+     * @return Smarty
+     */
+    public function _getSmartyObj()
+    {
+        return $this;
+    }
+
+    /**
+     * <<magic>> Generic getter.
+     * Calls the appropriate getter function.
+     * Issues an E_USER_NOTICE if no valid getter is found.
+     *
+     * @param  string $name property name
+     *
+     * @return mixed
+     * @throws \SmartyException
+     */
+    public function __get($name)
+    {
+        if (isset($this->accessMap[ $name ])) {
+            $method = 'get' . $this->accessMap[ $name ];
+            return $this->{$method}();
+        } else if (isset($this->_cache[ $name ])) {
+            return $this->_cache[ $name ];
+        } else if (in_array($name, $this->obsoleteProperties)) {
+            return null;
+        } else {
+            trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
+        }
+        return null;
+    }
+
+    /**
+     * <<magic>> Generic setter.
+     * Calls the appropriate setter function.
+     * Issues an E_USER_NOTICE if no valid setter is found.
+     *
+     * @param string $name  property name
+     * @param mixed  $value parameter passed to setter
+     *
+     * @throws \SmartyException
+     */
+    public function __set($name, $value)
+    {
+        if (isset($this->accessMap[ $name ])) {
+            $method = 'set' . $this->accessMap[ $name ];
+            $this->{$method}($value);
+        } else if (in_array($name, $this->obsoleteProperties)) {
+            return;
+        } else {
+            if (is_object($value) && method_exists($value, $name)) {
+                $this->$name = $value;
+            } else {
+                trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
+            }
+        }
+    }
+
+    /**
+     * Normalize and set directory string
+     *
+     * @param string $dirName cache_dir or compile_dir
+     * @param string $dir     filepath of folder
+     */
+    private function _normalizeDir($dirName, $dir)
+    {
+        $this->{$dirName} = $this->_realpath(rtrim($dir, "/\\") . DIRECTORY_SEPARATOR, true);
+        if (class_exists('Smarty_Internal_ErrorHandler', false)) {
+            if (!isset(Smarty_Internal_ErrorHandler::$mutedDirectories[ $this->{$dirName} ])) {
+                Smarty_Internal_ErrorHandler::$mutedDirectories[ $this->{$dirName} ] = null;
+            }
+        }
+    }
+
+    /**
+     * Normalize template_dir or config_dir
+     *
+     * @param bool $isConfig true for config_dir
+     *
+     */
+    private function _normalizeTemplateConfig($isConfig)
+    {
+        if ($isConfig) {
+            $processed = &$this->_processedConfigDir;
+            $dir = &$this->config_dir;
+        } else {
+            $processed = &$this->_processedTemplateDir;
+            $dir = &$this->template_dir;
+        }
+        if (!is_array($dir)) {
+            $dir = (array)$dir;
+        }
+        foreach ($dir as $k => $v) {
+            if (!isset($processed[ $k ])) {
+                $dir[ $k ] = $v = $this->_realpath(rtrim($v, "/\\") . DIRECTORY_SEPARATOR, true);
+                $processed[ $k ] = true;
+            }
+        }
+        $isConfig ? $this->_configDirNormalized = true : $this->_templateDirNormalized = true;
+        $isConfig ? $this->_joined_config_dir = join('#', $this->config_dir) :
+            $this->_joined_template_dir = join('#', $this->template_dir);
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource_custom.php 3.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource_custom.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource_custom.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource_custom.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,276 @@
+<?php
+/**
+ * Smarty Internal Plugin
+ *
+ * @package    Smarty
+ * @subpackage Cacher
+ */
+
+/**
+ * Cache Handler API
+ *
+ * @package    Smarty
+ * @subpackage Cacher
+ * @author     Rodney Rehm
+ */
+abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
+{
+    /**
+     * fetch cached content and its modification time from data source
+     *
+     * @param  string  $id         unique cache content identifier
+     * @param  string  $name       template name
+     * @param  string  $cache_id   cache id
+     * @param  string  $compile_id compile id
+     * @param  string  $content    cached content
+     * @param  integer $mtime      cache modification timestamp (epoch)
+     *
+     * @return void
+     */
+    abstract protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime);
+
+    /**
+     * Fetch cached content's modification timestamp from data source
+     * {@internal implementing this method is optional.
+     *  Only implement it if modification times can be accessed faster than loading the complete cached content.}}
+     *
+     * @param  string $id         unique cache content identifier
+     * @param  string $name       template name
+     * @param  string $cache_id   cache id
+     * @param  string $compile_id compile id
+     *
+     * @return integer|boolean timestamp (epoch) the template was modified, or false if not found
+     */
+    protected function fetchTimestamp($id, $name, $cache_id, $compile_id)
+    {
+        return false;
+    }
+
+    /**
+     * Save content to cache
+     *
+     * @param  string       $id         unique cache content identifier
+     * @param  string       $name       template name
+     * @param  string       $cache_id   cache id
+     * @param  string       $compile_id compile id
+     * @param  integer|null $exp_time   seconds till expiration or null
+     * @param  string       $content    content to cache
+     *
+     * @return boolean      success
+     */
+    abstract protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content);
+
+    /**
+     * Delete content from cache
+     *
+     * @param  string|null  $name       template name
+     * @param  string|null  $cache_id   cache id
+     * @param  string|null  $compile_id compile id
+     * @param  integer|null $exp_time   seconds till expiration time in seconds or null
+     *
+     * @return integer      number of deleted caches
+     */
+    abstract protected function delete($name, $cache_id, $compile_id, $exp_time);
+
+    /**
+     * populate Cached Object with meta data from Resource
+     *
+     * @param  Smarty_Template_Cached   $cached    cached object
+     * @param  Smarty_Internal_Template $_template template object
+     *
+     * @return void
+     */
+    public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
+    {
+        $_cache_id = isset($cached->cache_id) ? preg_replace('![^\w\|]+!', '_', $cached->cache_id) : null;
+        $_compile_id = isset($cached->compile_id) ? preg_replace('![^\w]+!', '_', $cached->compile_id) : null;
+        $path = $cached->source->uid . $_cache_id . $_compile_id;
+        $cached->filepath = sha1($path);
+        if ($_template->smarty->cache_locking) {
+            $cached->lock_id = sha1('lock.' . $path);
+        }
+        $this->populateTimestamp($cached);
+    }
+
+    /**
+     * populate Cached Object with timestamp and exists from Resource
+     *
+     * @param Smarty_Template_Cached $cached
+     *
+     * @return void
+     */
+    public function populateTimestamp(Smarty_Template_Cached $cached)
+    {
+        $mtime =
+            $this->fetchTimestamp($cached->filepath, $cached->source->name, $cached->cache_id, $cached->compile_id);
+        if ($mtime !== null) {
+            $cached->timestamp = $mtime;
+            $cached->exists = !!$cached->timestamp;
+
+            return;
+        }
+        $timestamp = null;
+        $this->fetch($cached->filepath, $cached->source->name, $cached->cache_id, $cached->compile_id, $cached->content,
+                     $timestamp);
+        $cached->timestamp = isset($timestamp) ? $timestamp : false;
+        $cached->exists = !!$cached->timestamp;
+    }
+
+    /**
+     * Read the cached template and process the header
+     *
+     * @param \Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template
+     * @param  Smarty_Template_Cached   $cached      cached object
+     * @param boolean                   $update      flag if called because cache update
+     *
+     * @return boolean                 true or false if the cached content does not exist
+     */
+    public function process(Smarty_Internal_Template $_smarty_tpl, Smarty_Template_Cached $cached = null,
+                            $update = false)
+    {
+        if (!$cached) {
+            $cached = $_smarty_tpl->cached;
+        }
+        $content = $cached->content ? $cached->content : null;
+        $timestamp = $cached->timestamp ? $cached->timestamp : null;
+        if ($content === null || !$timestamp) {
+            $this->fetch($_smarty_tpl->cached->filepath, $_smarty_tpl->source->name, $_smarty_tpl->cache_id,
+                         $_smarty_tpl->compile_id, $content, $timestamp);
+        }
+        if (isset($content)) {
+            eval('?>' . $content);
+            $cached->content = null;
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Write the rendered template output to cache
+     *
+     * @param  Smarty_Internal_Template $_template template object
+     * @param  string                   $content   content to cache
+     *
+     * @return boolean                  success
+     */
+    public function writeCachedContent(Smarty_Internal_Template $_template, $content)
+    {
+        return $this->save($_template->cached->filepath, $_template->source->name, $_template->cache_id,
+                           $_template->compile_id, $_template->cache_lifetime, $content);
+    }
+
+    /**
+     * Read cached template from cache
+     *
+     * @param  Smarty_Internal_Template $_template template object
+     *
+     * @return string|boolean  content
+     */
+    public function readCachedContent(Smarty_Internal_Template $_template)
+    {
+        $content = $_template->cached->content ? $_template->cached->content : null;
+        $timestamp = null;
+        if ($content === null) {
+            $timestamp = null;
+            $this->fetch($_template->cached->filepath, $_template->source->name, $_template->cache_id,
+                         $_template->compile_id, $content, $timestamp);
+        }
+        if (isset($content)) {
+            return $content;
+        }
+        return false;
+    }
+
+    /**
+     * Empty cache
+     *
+     * @param  Smarty  $smarty   Smarty object
+     * @param  integer $exp_time expiration time (number of seconds, not timestamp)
+     *
+     * @return integer number of cache files deleted
+     */
+    public function clearAll(Smarty $smarty, $exp_time = null)
+    {
+        return $this->delete(null, null, null, $exp_time);
+    }
+
+    /**
+     * Empty cache for a specific template
+     *
+     * @param  Smarty  $smarty        Smarty object
+     * @param  string  $resource_name template name
+     * @param  string  $cache_id      cache id
+     * @param  string  $compile_id    compile id
+     * @param  integer $exp_time      expiration time (number of seconds, not timestamp)
+     *
+     * @return int number of cache files deleted
+     * @throws \SmartyException
+     */
+    public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
+    {
+        $cache_name = null;
+
+        if (isset($resource_name)) {
+            $source = Smarty_Template_Source::load(null, $smarty, $resource_name);
+            if ($source->exists) {
+                $cache_name = $source->name;
+            } else {
+                return 0;
+            }
+        }
+
+        return $this->delete($cache_name, $cache_id, $compile_id, $exp_time);
+    }
+
+    /**
+     * Check is cache is locked for this template
+     *
+     * @param  Smarty                 $smarty Smarty object
+     * @param  Smarty_Template_Cached $cached cached object
+     *
+     * @return boolean               true or false if cache is locked
+     */
+    public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        $id = $cached->lock_id;
+        $name = $cached->source->name . '.lock';
+
+        $mtime = $this->fetchTimestamp($id, $name, $cached->cache_id, $cached->compile_id);
+        if ($mtime === null) {
+            $this->fetch($id, $name, $cached->cache_id, $cached->compile_id, $content, $mtime);
+        }
+        return $mtime && ($t = time()) - $mtime < $smarty->locking_timeout;
+    }
+
+    /**
+     * Lock cache for this template
+     *
+     * @param Smarty                 $smarty Smarty object
+     * @param Smarty_Template_Cached $cached cached object
+     *
+     * @return bool|void
+     */
+    public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        $cached->is_locked = true;
+        $id = $cached->lock_id;
+        $name = $cached->source->name . '.lock';
+        $this->save($id, $name, $cached->cache_id, $cached->compile_id, $smarty->locking_timeout, '');
+    }
+
+    /**
+     * Unlock cache for this template
+     *
+     * @param Smarty                 $smarty Smarty object
+     * @param Smarty_Template_Cached $cached cached object
+     *
+     * @return bool|void
+     */
+    public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        $cached->is_locked = false;
+        $name = $cached->source->name . '.lock';
+        $this->delete($name, $cached->cache_id, $cached->compile_id, null);
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource_keyvaluestore.php 3.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource_keyvaluestore.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource_keyvaluestore.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource_keyvaluestore.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,508 @@
+<?php
+/**
+ * Smarty Internal Plugin
+ *
+ * @package    Smarty
+ * @subpackage Cacher
+ */
+
+/**
+ * Smarty Cache Handler Base for Key/Value Storage Implementations
+ * This class implements the functionality required to use simple key/value stores
+ * for hierarchical cache groups. key/value stores like memcache or APC do not support
+ * wildcards in keys, therefore a cache group cannot be cleared like "a|*" - which
+ * is no problem to filesystem and RDBMS implementations.
+ * This implementation is based on the concept of invalidation. While one specific cache
+ * can be identified and cleared, any range of caches cannot be identified. For this reason
+ * each level of the cache group hierarchy can have its own value in the store. These values
+ * are nothing but microtimes, telling us when a particular cache group was cleared for the
+ * last time. These keys are evaluated for every cache read to determine if the cache has
+ * been invalidated since it was created and should hence be treated as inexistent.
+ * Although deep hierarchies are possible, they are not recommended. Try to keep your
+ * cache groups as shallow as possible. Anything up 3-5 parents should be ok. So
+ * Â»a|b|cÂ« is a good depth where Â»a|b|c|d|e|f|g|h|i|j|kÂ« isn't. Try to join correlating
+ * cache groups: if your cache groups look somewhat like Â»a|b|$page|$items|$whateverÂ«
+ * consider using Â»a|b|c|$page-$items-$whateverÂ« instead.
+ *
+ * @package    Smarty
+ * @subpackage Cacher
+ * @author     Rodney Rehm
+ */
+abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
+{
+    /**
+     * cache for contents
+     *
+     * @var array
+     */
+    protected $contents = array();
+
+    /**
+     * cache for timestamps
+     *
+     * @var array
+     */
+    protected $timestamps = array();
+
+    /**
+     * populate Cached Object with meta data from Resource
+     *
+     * @param  Smarty_Template_Cached   $cached    cached object
+     * @param  Smarty_Internal_Template $_template template object
+     *
+     * @return void
+     */
+    public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
+    {
+        $cached->filepath = $_template->source->uid . '#' . $this->sanitize($cached->source->resource) . '#' .
+                            $this->sanitize($cached->cache_id) . '#' . $this->sanitize($cached->compile_id);
+
+        $this->populateTimestamp($cached);
+    }
+
+    /**
+     * populate Cached Object with timestamp and exists from Resource
+     *
+     * @param  Smarty_Template_Cached $cached cached object
+     *
+     * @return void
+     */
+    public function populateTimestamp(Smarty_Template_Cached $cached)
+    {
+        if (!$this->fetch($cached->filepath, $cached->source->name, $cached->cache_id, $cached->compile_id, $content,
+                          $timestamp, $cached->source->uid)
+        ) {
+            return;
+        }
+        $cached->content = $content;
+        $cached->timestamp = (int) $timestamp;
+        $cached->exists = !!$cached->timestamp;
+    }
+
+    /**
+     * Read the cached template and process the header
+     *
+     * @param \Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template
+     * @param  Smarty_Template_Cached   $cached      cached object
+     * @param boolean                   $update      flag if called because cache update
+     *
+     * @return boolean                 true or false if the cached content does not exist
+     */
+    public function process(Smarty_Internal_Template $_smarty_tpl, Smarty_Template_Cached $cached = null,
+                            $update = false)
+    {
+        if (!$cached) {
+            $cached = $_smarty_tpl->cached;
+        }
+        $content = $cached->content ? $cached->content : null;
+        $timestamp = $cached->timestamp ? $cached->timestamp : null;
+        if ($content === null || !$timestamp) {
+            if (!$this->fetch($_smarty_tpl->cached->filepath, $_smarty_tpl->source->name, $_smarty_tpl->cache_id,
+                              $_smarty_tpl->compile_id, $content, $timestamp, $_smarty_tpl->source->uid)
+            ) {
+                return false;
+            }
+        }
+        if (isset($content)) {
+            eval('?>' . $content);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Write the rendered template output to cache
+     *
+     * @param  Smarty_Internal_Template $_template template object
+     * @param  string                   $content   content to cache
+     *
+     * @return boolean                  success
+     */
+    public function writeCachedContent(Smarty_Internal_Template $_template, $content)
+    {
+        $this->addMetaTimestamp($content);
+
+        return $this->write(array($_template->cached->filepath => $content), $_template->cache_lifetime);
+    }
+
+    /**
+     * Read cached template from cache
+     *
+     * @param  Smarty_Internal_Template $_template template object
+     *
+     * @return string|false  content
+     */
+    public function readCachedContent(Smarty_Internal_Template $_template)
+    {
+        $content = $_template->cached->content ? $_template->cached->content : null;
+        $timestamp = null;
+        if ($content === null) {
+            if (!$this->fetch($_template->cached->filepath, $_template->source->name, $_template->cache_id,
+                              $_template->compile_id, $content, $timestamp, $_template->source->uid)
+            ) {
+                return false;
+            }
+        }
+        if (isset($content)) {
+            return $content;
+        }
+        return false;
+    }
+
+    /**
+     * Empty cache
+     * {@internal the $exp_time argument is ignored altogether }}
+     *
+     * @param  Smarty  $smarty   Smarty object
+     * @param  integer $exp_time expiration time [being ignored]
+     *
+     * @return integer number of cache files deleted [always -1]
+     * @uses purge() to clear the whole store
+     * @uses invalidate() to mark everything outdated if purge() is inapplicable
+     */
+    public function clearAll(Smarty $smarty, $exp_time = null)
+    {
+        if (!$this->purge()) {
+            $this->invalidate(null);
+        }
+        return - 1;
+    }
+
+    /**
+     * Empty cache for a specific template
+     * {@internal the $exp_time argument is ignored altogether}}
+     *
+     * @param  Smarty  $smarty        Smarty object
+     * @param  string  $resource_name template name
+     * @param  string  $cache_id      cache id
+     * @param  string  $compile_id    compile id
+     * @param  integer $exp_time      expiration time [being ignored]
+     *
+     * @return int number of cache files deleted [always -1]
+     * @throws \SmartyException
+     * @uses buildCachedFilepath() to generate the CacheID
+     * @uses invalidate() to mark CacheIDs parent chain as outdated
+     * @uses delete() to remove CacheID from cache
+     */
+    public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
+    {
+        $uid = $this->getTemplateUid($smarty, $resource_name);
+        $cid = $uid . '#' . $this->sanitize($resource_name) . '#' . $this->sanitize($cache_id) . '#' .
+               $this->sanitize($compile_id);
+        $this->delete(array($cid));
+        $this->invalidate($cid, $resource_name, $cache_id, $compile_id, $uid);
+        return - 1;
+    }
+
+    /**
+     * Get template's unique ID
+     *
+     * @param  Smarty $smarty        Smarty object
+     * @param  string $resource_name template name
+     *
+     * @return string filepath of cache file
+     * @throws \SmartyException
+     *
+     */
+    protected function getTemplateUid(Smarty $smarty, $resource_name)
+    {
+        if (isset($resource_name)) {
+            $source = Smarty_Template_Source::load(null, $smarty, $resource_name);
+            if ($source->exists) {
+                return $source->uid;
+            }
+        }
+        return '';
+    }
+
+    /**
+     * Sanitize CacheID components
+     *
+     * @param  string $string CacheID component to sanitize
+     *
+     * @return string sanitized CacheID component
+     */
+    protected function sanitize($string)
+    {
+        $string = trim($string, '|');
+        if (!$string) {
+            return '';
+        }
+        return preg_replace('#[^\w\|]+#S', '_', $string);
+    }
+
+    /**
+     * Fetch and prepare a cache object.
+     *
+     * @param  string  $cid           CacheID to fetch
+     * @param  string  $resource_name template name
+     * @param  string  $cache_id      cache id
+     * @param  string  $compile_id    compile id
+     * @param  string  $content       cached content
+     * @param  integer &$timestamp    cached timestamp (epoch)
+     * @param  string  $resource_uid  resource's uid
+     *
+     * @return boolean success
+     */
+    protected function fetch($cid, $resource_name = null, $cache_id = null, $compile_id = null, &$content = null,
+                             &$timestamp = null, $resource_uid = null)
+    {
+        $t = $this->read(array($cid));
+        $content = !empty($t[ $cid ]) ? $t[ $cid ] : null;
+        $timestamp = null;
+
+        if ($content && ($timestamp = $this->getMetaTimestamp($content))) {
+            $invalidated =
+                $this->getLatestInvalidationTimestamp($cid, $resource_name, $cache_id, $compile_id, $resource_uid);
+            if ($invalidated > $timestamp) {
+                $timestamp = null;
+                $content = null;
+            }
+        }
+
+        return !!$content;
+    }
+
+    /**
+     * Add current microtime to the beginning of $cache_content
+     * {@internal the header uses 8 Bytes, the first 4 Bytes are the seconds, the second 4 Bytes are the microseconds}}
+     *
+     * @param string &$content the content to be cached
+     */
+    protected function addMetaTimestamp(&$content)
+    {
+        $mt = explode(' ', microtime());
+        $ts = pack('NN', $mt[ 1 ], (int) ($mt[ 0 ] * 100000000));
+        $content = $ts . $content;
+    }
+
+    /**
+     * Extract the timestamp the $content was cached
+     *
+     * @param  string &$content the cached content
+     *
+     * @return float  the microtime the content was cached
+     */
+    protected function getMetaTimestamp(&$content)
+    {
+        extract(unpack('N1s/N1m/a*content', $content));
+        /**
+         * @var  int $s
+         * @var  int $m
+         */
+        return $s + ($m / 100000000);
+    }
+
+    /**
+     * Invalidate CacheID
+     *
+     * @param  string $cid           CacheID
+     * @param  string $resource_name template name
+     * @param  string $cache_id      cache id
+     * @param  string $compile_id    compile id
+     * @param  string $resource_uid  source's uid
+     *
+     * @return void
+     */
+    protected function invalidate($cid = null, $resource_name = null, $cache_id = null, $compile_id = null,
+                                  $resource_uid = null)
+    {
+        $now = microtime(true);
+        $key = null;
+        // invalidate everything
+        if (!$resource_name && !$cache_id && !$compile_id) {
+            $key = 'IVK#ALL';
+        } // invalidate all caches by template
+        else {
+            if ($resource_name && !$cache_id && !$compile_id) {
+                $key = 'IVK#TEMPLATE#' . $resource_uid . '#' . $this->sanitize($resource_name);
+            } // invalidate all caches by cache group
+            else {
+                if (!$resource_name && $cache_id && !$compile_id) {
+                    $key = 'IVK#CACHE#' . $this->sanitize($cache_id);
+                } // invalidate all caches by compile id
+                else {
+                    if (!$resource_name && !$cache_id && $compile_id) {
+                        $key = 'IVK#COMPILE#' . $this->sanitize($compile_id);
+                    } // invalidate by combination
+                    else {
+                        $key = 'IVK#CID#' . $cid;
+                    }
+                }
+            }
+        }
+        $this->write(array($key => $now));
+    }
+
+    /**
+     * Determine the latest timestamp known to the invalidation chain
+     *
+     * @param  string $cid           CacheID to determine latest invalidation timestamp of
+     * @param  string $resource_name template name
+     * @param  string $cache_id      cache id
+     * @param  string $compile_id    compile id
+     * @param  string $resource_uid  source's filepath
+     *
+     * @return float  the microtime the CacheID was invalidated
+     */
+    protected function getLatestInvalidationTimestamp($cid, $resource_name = null, $cache_id = null, $compile_id = null,
+                                                      $resource_uid = null)
+    {
+        // abort if there is no CacheID
+        if (false && !$cid) {
+            return 0;
+        }
+        // abort if there are no InvalidationKeys to check
+        if (!($_cid = $this->listInvalidationKeys($cid, $resource_name, $cache_id, $compile_id, $resource_uid))) {
+            return 0;
+        }
+
+        // there are no InValidationKeys
+        if (!($values = $this->read($_cid))) {
+            return 0;
+        }
+        // make sure we're dealing with floats
+        $values = array_map('floatval', $values);
+
+        return max($values);
+    }
+
+    /**
+     * Translate a CacheID into the list of applicable InvalidationKeys.
+     * Splits 'some|chain|into|an|array' into array( '#clearAll#', 'some', 'some|chain', 'some|chain|into', ... )
+     *
+     * @param  string $cid           CacheID to translate
+     * @param  string $resource_name template name
+     * @param  string $cache_id      cache id
+     * @param  string $compile_id    compile id
+     * @param  string $resource_uid  source's filepath
+     *
+     * @return array  list of InvalidationKeys
+     * @uses $invalidationKeyPrefix to prepend to each InvalidationKey
+     */
+    protected function listInvalidationKeys($cid, $resource_name = null, $cache_id = null, $compile_id = null,
+                                            $resource_uid = null)
+    {
+        $t = array('IVK#ALL');
+        $_name = $_compile = '#';
+        if ($resource_name) {
+            $_name .= $resource_uid . '#' . $this->sanitize($resource_name);
+            $t[] = 'IVK#TEMPLATE' . $_name;
+        }
+        if ($compile_id) {
+            $_compile .= $this->sanitize($compile_id);
+            $t[] = 'IVK#COMPILE' . $_compile;
+        }
+        $_name .= '#';
+        $cid = trim($cache_id, '|');
+        if (!$cid) {
+            return $t;
+        }
+        $i = 0;
+        while (true) {
+            // determine next delimiter position
+            $i = strpos($cid, '|', $i);
+            // add complete CacheID if there are no more delimiters
+            if ($i === false) {
+                $t[] = 'IVK#CACHE#' . $cid;
+                $t[] = 'IVK#CID' . $_name . $cid . $_compile;
+                $t[] = 'IVK#CID' . $_name . $_compile;
+                break;
+            }
+            $part = substr($cid, 0, $i);
+            // add slice to list
+            $t[] = 'IVK#CACHE#' . $part;
+            $t[] = 'IVK#CID' . $_name . $part . $_compile;
+            // skip past delimiter position
+            $i ++;
+        }
+
+        return $t;
+    }
+
+    /**
+     * Check is cache is locked for this template
+     *
+     * @param  Smarty                 $smarty Smarty object
+     * @param  Smarty_Template_Cached $cached cached object
+     *
+     * @return boolean               true or false if cache is locked
+     */
+    public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        $key = 'LOCK#' . $cached->filepath;
+        $data = $this->read(array($key));
+
+        return $data && time() - $data[ $key ] < $smarty->locking_timeout;
+    }
+
+    /**
+     * Lock cache for this template
+     *
+     * @param Smarty                 $smarty Smarty object
+     * @param Smarty_Template_Cached $cached cached object
+     *
+     * @return bool|void
+     */
+    public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        $cached->is_locked = true;
+        $key = 'LOCK#' . $cached->filepath;
+        $this->write(array($key => time()), $smarty->locking_timeout);
+    }
+
+    /**
+     * Unlock cache for this template
+     *
+     * @param Smarty                 $smarty Smarty object
+     * @param Smarty_Template_Cached $cached cached object
+     *
+     * @return bool|void
+     */
+    public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        $cached->is_locked = false;
+        $key = 'LOCK#' . $cached->filepath;
+        $this->delete(array($key));
+    }
+
+    /**
+     * Read values for a set of keys from cache
+     *
+     * @param  array $keys list of keys to fetch
+     *
+     * @return array list of values with the given keys used as indexes
+     */
+    abstract protected function read(array $keys);
+
+    /**
+     * Save values for a set of keys to cache
+     *
+     * @param  array $keys   list of values to save
+     * @param  int   $expire expiration time
+     *
+     * @return boolean true on success, false on failure
+     */
+    abstract protected function write(array $keys, $expire = null);
+
+    /**
+     * Remove values from cache
+     *
+     * @param  array $keys list of keys to delete
+     *
+     * @return boolean true on success, false on failure
+     */
+    abstract protected function delete(array $keys);
+
+    /**
+     * Remove *all* values from cache
+     *
+     * @return boolean true on success, false on failure
+     */
+    protected function purge()
+    {
+        return false;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource.php 3.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_cacheresource.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,220 @@
+<?php
+/**
+ * Smarty Internal Plugin
+ *
+ * @package    Smarty
+ * @subpackage Cacher
+ */
+
+/**
+ * Cache Handler API
+ *
+ * @package    Smarty
+ * @subpackage Cacher
+ * @author     Rodney Rehm
+ */
+abstract class Smarty_CacheResource
+{
+    /**
+     * resource types provided by the core
+     *
+     * @var array
+     */
+    protected static $sysplugins = array('file' => 'smarty_internal_cacheresource_file.php',);
+
+    /**
+     * populate Cached Object with meta data from Resource
+     *
+     * @param Smarty_Template_Cached   $cached    cached object
+     * @param Smarty_Internal_Template $_template template object
+     *
+     * @return void
+     */
+    abstract public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template);
+
+    /**
+     * populate Cached Object with timestamp and exists from Resource
+     *
+     * @param Smarty_Template_Cached $cached
+     *
+     * @return void
+     */
+    abstract public function populateTimestamp(Smarty_Template_Cached $cached);
+
+    /**
+     * Read the cached template and process header
+     *
+     * @param Smarty_Internal_Template $_template template object
+     * @param Smarty_Template_Cached   $cached    cached object
+     * @param boolean                  $update    flag if called because cache update
+     *
+     * @return boolean true or false if the cached content does not exist
+     */
+    abstract public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached = null,
+                                     $update = false);
+
+    /**
+     * Write the rendered template output to cache
+     *
+     * @param Smarty_Internal_Template $_template template object
+     * @param string                   $content   content to cache
+     *
+     * @return boolean success
+     */
+    abstract public function writeCachedContent(Smarty_Internal_Template $_template, $content);
+
+    /**
+     * Read cached template from cache
+     *
+     * @param  Smarty_Internal_Template $_template template object
+     *
+     * @return string  content
+     */
+    abstract function readCachedContent(Smarty_Internal_Template $_template);
+
+    /**
+     * Return cached content
+     *
+     * @param Smarty_Internal_Template $_template template object
+     *
+     * @return null|string
+     */
+    public function getCachedContent(Smarty_Internal_Template $_template)
+    {
+        if ($_template->cached->handler->process($_template)) {
+            ob_start();
+            $unifunc = $_template->cached->unifunc;
+            $unifunc($_template);
+            return ob_get_clean();
+        }
+
+        return null;
+    }
+
+    /**
+     * Empty cache
+     *
+     * @param Smarty  $smarty   Smarty object
+     * @param integer $exp_time expiration time (number of seconds, not timestamp)
+     *
+     * @return integer number of cache files deleted
+     */
+    abstract public function clearAll(Smarty $smarty, $exp_time = null);
+
+    /**
+     * Empty cache for a specific template
+     *
+     * @param Smarty  $smarty        Smarty object
+     * @param string  $resource_name template name
+     * @param string  $cache_id      cache id
+     * @param string  $compile_id    compile id
+     * @param integer $exp_time      expiration time (number of seconds, not timestamp)
+     *
+     * @return integer number of cache files deleted
+     */
+    abstract public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time);
+
+    /**
+     * @param Smarty                 $smarty
+     * @param Smarty_Template_Cached $cached
+     *
+     * @return bool|null
+     */
+    public function locked(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        // theoretically locking_timeout should be checked against time_limit (max_execution_time)
+        $start = microtime(true);
+        $hadLock = null;
+        while ($this->hasLock($smarty, $cached)) {
+            $hadLock = true;
+            if (microtime(true) - $start > $smarty->locking_timeout) {
+                // abort waiting for lock release
+                return false;
+            }
+            sleep(1);
+        }
+
+        return $hadLock;
+    }
+
+    /**
+     * Check is cache is locked for this template
+     *
+     * @param Smarty                 $smarty
+     * @param Smarty_Template_Cached $cached
+     *
+     * @return bool
+     */
+    public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        // check if lock exists
+        return false;
+    }
+
+    /**
+     * Lock cache for this template
+     *
+     * @param Smarty                 $smarty
+     * @param Smarty_Template_Cached $cached
+     *
+     * @return bool
+     */
+    public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        // create lock
+        return true;
+    }
+
+    /**
+     * Unlock cache for this template
+     *
+     * @param Smarty                 $smarty
+     * @param Smarty_Template_Cached $cached
+     *
+     * @return bool
+     */
+    public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        // release lock
+        return true;
+    }
+
+    /**
+     * Load Cache Resource Handler
+     *
+     * @param Smarty $smarty Smarty object
+     * @param string $type   name of the cache resource
+     *
+     * @throws SmartyException
+     * @return Smarty_CacheResource Cache Resource Handler
+     */
+    public static function load(Smarty $smarty, $type = null)
+    {
+        if (!isset($type)) {
+            $type = $smarty->caching_type;
+        }
+
+        // try smarty's cache
+        if (isset($smarty->_cache[ 'cacheresource_handlers' ][ $type ])) {
+            return $smarty->_cache[ 'cacheresource_handlers' ][ $type ];
+        }
+
+        // try registered resource
+        if (isset($smarty->registered_cache_resources[ $type ])) {
+            // do not cache these instances as they may vary from instance to instance
+            return $smarty->_cache[ 'cacheresource_handlers' ][ $type ] = $smarty->registered_cache_resources[ $type ];
+        }
+        // try sysplugins dir
+        if (isset(self::$sysplugins[ $type ])) {
+            $cache_resource_class = 'Smarty_Internal_CacheResource_' . ucfirst($type);
+            return $smarty->_cache[ 'cacheresource_handlers' ][ $type ] = new $cache_resource_class();
+        }
+        // try plugins dir
+        $cache_resource_class = 'Smarty_CacheResource_' . ucfirst($type);
+        if ($smarty->loadPlugin($cache_resource_class)) {
+            return $smarty->_cache[ 'cacheresource_handlers' ][ $type ] = new $cache_resource_class();
+        }
+        // give up
+        throw new SmartyException("Unable to load cache resource '{$type}'");
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smartycompilerexception.php 3.2-2/lib/smarty/libs/sysplugins/smartycompilerexception.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smartycompilerexception.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smartycompilerexception.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * Smarty compiler exception class
+ *
+ * @package Smarty
+ */
+class SmartyCompilerException extends SmartyException
+{
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        return ' --> Smarty Compiler: ' . $this->message . ' <-- ';
+    }
+
+    /**
+     * The line number of the template error
+     *
+     * @type int|null
+     */
+    public $line = null;
+
+    /**
+     * The template source snippet relating to the error
+     *
+     * @type string|null
+     */
+    public $source = null;
+
+    /**
+     * The raw text of the error message
+     *
+     * @type string|null
+     */
+    public $desc = null;
+
+    /**
+     * The resource identifier or template name
+     *
+     * @type string|null
+     */
+    public $template = null;
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_data.php 3.2-2/lib/smarty/libs/sysplugins/smarty_data.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_data.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_data.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Smarty Plugin Data
+ * This file contains the data object
+ *
+ * @package    Smarty
+ * @subpackage Template
+ * @author     Uwe Tews
+ */
+
+/**
+ * class for the Smarty data object
+ * The Smarty data object will hold Smarty variables in the current scope
+ *
+ * @package    Smarty
+ * @subpackage Template
+ */
+class Smarty_Data extends Smarty_Internal_Data
+{
+    /**
+     * Counter
+     *
+     * @var int
+     */
+    static $count = 0;
+
+    /**
+     * Data block name
+     *
+     * @var string
+     */
+    public $dataObjectName = '';
+
+    /**
+     * Smarty object
+     *
+     * @var Smarty
+     */
+    public $smarty = null;
+
+    /**
+     * create Smarty data object
+     *
+     * @param Smarty|array                    $_parent parent template
+     * @param Smarty|Smarty_Internal_Template $smarty  global smarty instance
+     * @param string                          $name    optional data block name
+     *
+     * @throws SmartyException
+     */
+    public function __construct($_parent = null, $smarty = null, $name = null)
+    {
+        parent::__construct();
+        self::$count ++;
+        $this->dataObjectName = 'Data_object ' . (isset($name) ? "'{$name}'" : self::$count);
+        $this->smarty = $smarty;
+        if (is_object($_parent)) {
+            // when object set up back pointer
+            $this->parent = $_parent;
+        } elseif (is_array($_parent)) {
+            // set up variable values
+            foreach ($_parent as $_key => $_val) {
+                $this->tpl_vars[ $_key ] = new Smarty_Variable($_val);
+            }
+        } elseif ($_parent !== null) {
+            throw new SmartyException('Wrong type for template variables');
+        }
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smartyexception.php 3.2-2/lib/smarty/libs/sysplugins/smartyexception.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smartyexception.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smartyexception.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * Smarty exception class
+ *
+ * @package Smarty
+ */
+class SmartyException extends Exception
+{
+    public static $escape = false;
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        return ' --> Smarty: ' . (self::$escape ? htmlentities($this->message) : $this->message) . ' <-- ';
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_block.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_block.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_block.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_block.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * Smarty {block} tag class
+ *
+ * @package    Smarty
+ * @subpackage PluginsInternal
+ * @author     Uwe Tews
+ */
+class Smarty_Internal_Block
+{
+    /**
+     * Block name
+     *
+     * @var string
+     */
+    public $name = '';
+
+    /**
+     * Hide attribute
+     *
+     * @var bool
+     */
+    public $hide = false;
+
+    /**
+     * Append attribute
+     *
+     * @var bool
+     */
+    public $append = false;
+
+    /**
+     * prepend attribute
+     *
+     * @var bool
+     */
+    public $prepend = false;
+
+    /**
+     * Block calls $smarty.block.child
+     *
+     * @var bool
+     */
+    public $callsChild = false;
+
+    /**
+     * Inheritance child block
+     *
+     * @var Smarty_Internal_Block|null
+     */
+    public $child = null;
+
+    /**
+     * Inheritance calling parent block
+     *
+     * @var Smarty_Internal_Block|null
+     */
+    public $parent = null;
+
+    /**
+     * Inheritance Template index
+     *
+     * @var int
+     */
+    public $tplIndex = 0;
+
+    /**
+     * Smarty_Internal_Block constructor.
+     * - if outer level {block} of child template ($state === 1) save it as child root block
+     * - otherwise process inheritance and render
+     *
+     * @param string   $name     block name
+     * @param int|null $tplIndex index of outer level {block} if nested
+     */
+    public function __construct($name, $tplIndex)
+    {
+        $this->name = $name;
+        $this->tplIndex = $tplIndex;
+    }
+
+    /**
+     * Compiled block code overloaded by {block} class
+     *
+     * @param \Smarty_Internal_Template $tpl
+     */
+    public function callBlock(Smarty_Internal_Template $tpl)
+    {
+    }
+}
\ No newline at end of file
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_cacheresource_file.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_cacheresource_file.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_cacheresource_file.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_cacheresource_file.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,229 @@
+<?php
+/**
+ * Smarty Internal Plugin CacheResource File
+ *
+ * @package    Smarty
+ * @subpackage Cacher
+ * @author     Uwe Tews
+ * @author     Rodney Rehm
+ */
+/**
+ * This class does contain all necessary methods for the HTML cache on file system
+ * Implements the file system as resource for the HTML cache Version ussing nocache inserts.
+ *
+ * @package    Smarty
+ * @subpackage Cacher
+ */
+class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
+{
+    /**
+     * populate Cached Object with meta data from Resource
+     *
+     * @param Smarty_Template_Cached   $cached    cached object
+     * @param Smarty_Internal_Template $_template template object
+     *
+     * @return void
+     */
+    public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
+    {
+        $source = &$_template->source;
+        $smarty = &$_template->smarty;
+        $_compile_dir_sep = $smarty->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';
+        $_filepath = sha1($source->uid . $smarty->_joined_template_dir);
+        $cached->filepath = $smarty->getCacheDir();
+        if (isset($_template->cache_id)) {
+            $cached->filepath .= preg_replace(array('![^\w|]+!',
+                                                    '![|]+!'),
+                                              array('_',
+                                                    $_compile_dir_sep),
+                                              $_template->cache_id) . $_compile_dir_sep;
+        }
+        if (isset($_template->compile_id)) {
+            $cached->filepath .= preg_replace('![^\w]+!', '_', $_template->compile_id) . $_compile_dir_sep;
+        }
+        // if use_sub_dirs, break file into directories
+        if ($smarty->use_sub_dirs) {
+            $cached->filepath .= $_filepath[ 0 ] . $_filepath[ 1 ] . DIRECTORY_SEPARATOR . $_filepath[ 2 ] .
+                                 $_filepath[ 3 ] .
+                                 DIRECTORY_SEPARATOR .
+                                 $_filepath[ 4 ] . $_filepath[ 5 ] . DIRECTORY_SEPARATOR;
+        }
+        $cached->filepath .= $_filepath;
+        $basename = $source->handler->getBasename($source);
+        if (!empty($basename)) {
+            $cached->filepath .= '.' . $basename;
+        }
+        if ($smarty->cache_locking) {
+            $cached->lock_id = $cached->filepath . '.lock';
+        }
+        $cached->filepath .= '.php';
+        $cached->timestamp = $cached->exists = is_file($cached->filepath);
+        if ($cached->exists) {
+            $cached->timestamp = filemtime($cached->filepath);
+        }
+    }
+
+    /**
+     * populate Cached Object with timestamp and exists from Resource
+     *
+     * @param Smarty_Template_Cached $cached cached object
+     *
+     * @return void
+     */
+    public function populateTimestamp(Smarty_Template_Cached $cached)
+    {
+        $cached->timestamp = $cached->exists = is_file($cached->filepath);
+        if ($cached->exists) {
+            $cached->timestamp = filemtime($cached->filepath);
+        }
+    }
+
+    /**
+     * Read the cached template and process its header
+     *
+     * @param \Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template
+     * @param Smarty_Template_Cached    $cached      cached object
+     * @param bool                      $update      flag if called because cache update
+     *
+     * @return boolean true or false if the cached content does not exist
+     */
+    public function process(Smarty_Internal_Template $_smarty_tpl,
+                            Smarty_Template_Cached $cached = null,
+                            $update = false)
+    {
+        $_smarty_tpl->cached->valid = false;
+        if ($update && defined('HHVM_VERSION')) {
+            eval('?>' . file_get_contents($_smarty_tpl->cached->filepath));
+            return true;
+        } else {
+            return @include $_smarty_tpl->cached->filepath;
+        }
+    }
+
+    /**
+     * Write the rendered template output to cache
+     *
+     * @param Smarty_Internal_Template $_template template object
+     * @param string                   $content   content to cache
+     *
+     * @return bool success
+     * @throws \SmartyException
+     */
+    public function writeCachedContent(Smarty_Internal_Template $_template, $content)
+    {
+        if ($_template->smarty->ext->_writeFile->writeFile($_template->cached->filepath,
+                                                           $content,
+                                                           $_template->smarty) === true
+        ) {
+            if (function_exists('opcache_invalidate') &&
+                (!function_exists('ini_get') || strlen(ini_get('opcache.restrict_api'))) < 1
+            ) {
+                opcache_invalidate($_template->cached->filepath, true);
+            } else if (function_exists('apc_compile_file')) {
+                apc_compile_file($_template->cached->filepath);
+            }
+            $cached = $_template->cached;
+            $cached->timestamp = $cached->exists = is_file($cached->filepath);
+            if ($cached->exists) {
+                $cached->timestamp = filemtime($cached->filepath);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Read cached template from cache
+     *
+     * @param  Smarty_Internal_Template $_template template object
+     *
+     * @return string  content
+     */
+    public function readCachedContent(Smarty_Internal_Template $_template)
+    {
+        if (is_file($_template->cached->filepath)) {
+            return file_get_contents($_template->cached->filepath);
+        }
+        return false;
+    }
+
+    /**
+     * Empty cache
+     *
+     * @param Smarty  $smarty
+     * @param integer $exp_time expiration time (number of seconds, not timestamp)
+     *
+     * @return integer number of cache files deleted
+     */
+    public function clearAll(Smarty $smarty, $exp_time = null)
+    {
+        return $smarty->ext->_cacheResourceFile->clear($smarty, null, null, null, $exp_time);
+    }
+
+    /**
+     * Empty cache for a specific template
+     *
+     * @param Smarty  $smarty
+     * @param string  $resource_name template name
+     * @param string  $cache_id      cache id
+     * @param string  $compile_id    compile id
+     * @param integer $exp_time      expiration time (number of seconds, not timestamp)
+     *
+     * @return integer number of cache files deleted
+     */
+    public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time)
+    {
+        return $smarty->ext->_cacheResourceFile->clear($smarty, $resource_name, $cache_id, $compile_id, $exp_time);
+    }
+
+    /**
+     * Check is cache is locked for this template
+     *
+     * @param Smarty                 $smarty Smarty object
+     * @param Smarty_Template_Cached $cached cached object
+     *
+     * @return boolean true or false if cache is locked
+     */
+    public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
+            clearstatcache(true, $cached->lock_id);
+        } else {
+            clearstatcache();
+        }
+        if (is_file($cached->lock_id)) {
+            $t = filemtime($cached->lock_id);
+            return $t && (time() - $t < $smarty->locking_timeout);
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Lock cache for this template
+     *
+     * @param Smarty                 $smarty Smarty object
+     * @param Smarty_Template_Cached $cached cached object
+     *
+     * @return bool|void
+     */
+    public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        $cached->is_locked = true;
+        touch($cached->lock_id);
+    }
+
+    /**
+     * Unlock cache for this template
+     *
+     * @param Smarty                 $smarty Smarty object
+     * @param Smarty_Template_Cached $cached cached object
+     *
+     * @return bool|void
+     */
+    public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
+    {
+        $cached->is_locked = false;
+        @unlink($cached->lock_id);
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_append.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_append.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_append.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_append.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Append
+ * Compiles the {append} tag
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Append Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Append extends Smarty_Internal_Compile_Assign
+{
+    /**
+     * Compiles code for the {append} tag
+     *
+     * @param  array                                $args      array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler  compiler object
+     * @param  array                                $parameter array with compilation parameter
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
+    {
+        // the following must be assigned at runtime because it will be overwritten in parent class
+        $this->required_attributes = array('var', 'value');
+        $this->shorttag_order = array('var', 'value');
+        $this->optional_attributes = array('scope', 'index');
+        $this->mapCache = array();
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        // map to compile assign attributes
+        if (isset($_attr[ 'index' ])) {
+            $_params[ 'smarty_internal_index' ] = '[' . $_attr[ 'index' ] . ']';
+            unset($_attr[ 'index' ]);
+        } else {
+            $_params[ 'smarty_internal_index' ] = '[]';
+        }
+        $_new_attr = array();
+        foreach ($_attr as $key => $value) {
+            $_new_attr[] = array($key => $value);
+        }
+        // call compile assign
+        return parent::compile($_new_attr, $compiler, $_params);
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_assign.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_assign.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_assign.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_assign.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Assign
+ * Compiles the {assign} tag
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Assign Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $option_flags = array('nocache', 'noscope');
+
+   /**
+     * Valid scope names
+     *
+     * @var array
+     */
+    public $valid_scopes = array('local' => Smarty::SCOPE_LOCAL, 'parent' => Smarty::SCOPE_PARENT,
+                                 'root' => Smarty::SCOPE_ROOT, 'global' => Smarty::SCOPE_GLOBAL,
+                                 'tpl_root' => Smarty::SCOPE_TPL_ROOT, 'smarty' => Smarty::SCOPE_SMARTY);
+
+    /**
+     * Compiles code for the {assign} tag
+     *
+     * @param  array                                $args      array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler  compiler object
+     * @param  array                                $parameter array with compilation parameter
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
+    {
+        // the following must be assigned at runtime because it will be overwritten in Smarty_Internal_Compile_Append
+        $this->required_attributes = array('var', 'value');
+        $this->shorttag_order = array('var', 'value');
+        $this->optional_attributes = array('scope');
+        $this->mapCache = array();
+        $_nocache = false;
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        // nocache ?
+        if ($_var = $compiler->getId($_attr[ 'var' ])) {
+            $_var = "'{$_var}'";
+        } else {
+            $_var = $_attr[ 'var' ];
+        }
+        if ($compiler->tag_nocache || $compiler->nocache) {
+            $_nocache = true;
+            // create nocache var to make it know for further compiling
+            $compiler->setNocacheInVariable($_attr[ 'var' ]);
+        }
+        // scope setup
+        if ($_attr[ 'noscope' ]) {
+            $_scope = - 1;
+        } else {
+            $_scope = $compiler->convertScope($_attr, $this->valid_scopes);
+        }
+        // optional parameter
+        $_params = '';
+        if ($_nocache || $_scope) {
+            $_params .= ' ,' . var_export($_nocache, true);
+        }
+        if ($_scope) {
+            $_params .= ' ,' . $_scope;
+        }
+        if (isset($parameter[ 'smarty_internal_index' ])) {
+            $output =
+                "<?php \$_tmp_array = isset(\$_smarty_tpl->tpl_vars[{$_var}]) ? \$_smarty_tpl->tpl_vars[{$_var}]->value : array();\n";
+            $output .= "if (!is_array(\$_tmp_array) || \$_tmp_array instanceof ArrayAccess) {\n";
+            $output .= "settype(\$_tmp_array, 'array');\n";
+            $output .= "}\n";
+            $output .= "\$_tmp_array{$parameter['smarty_internal_index']} = {$_attr['value']};\n";
+            $output .= "\$_smarty_tpl->_assignInScope({$_var}, \$_tmp_array{$_params});?>";
+        } else {
+            $output = "<?php \$_smarty_tpl->_assignInScope({$_var}, {$_attr['value']}{$_params});?>";
+        }
+        return $output;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compilebase.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compilebase.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compilebase.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compilebase.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,195 @@
+<?php
+/**
+ * Smarty Internal Plugin CompileBase
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * This class does extend all internal compile plugins
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+abstract class Smarty_Internal_CompileBase
+{
+    /**
+     * Array of names of required attribute required by tag
+     *
+     * @var array
+     */
+    public $required_attributes = array();
+
+    /**
+     * Array of names of optional attribute required by tag
+     * use array('_any') if there is no restriction of attributes names
+     *
+     * @var array
+     */
+    public $optional_attributes = array();
+
+    /**
+     * Shorttag attribute order defined by its names
+     *
+     * @var array
+     */
+    public $shorttag_order = array();
+
+    /**
+     * Array of names of valid option flags
+     *
+     * @var array
+     */
+    public $option_flags = array('nocache');
+
+    /**
+     * Mapping array for boolean option value
+     *
+     * @var array
+     */
+    public $optionMap = array(1 => true, 0 => false, 'true' => true, 'false' => false);
+
+    /**
+     * Mapping array with attributes as key
+     *
+     * @var array
+     */
+    public $mapCache = array();
+
+    /**
+     * This function checks if the attributes passed are valid
+     * The attributes passed for the tag to compile are checked against the list of required and
+     * optional attributes. Required attributes must be present. Optional attributes are check against
+     * the corresponding list. The keyword '_any' specifies that any attribute will be accepted
+     * as valid
+     *
+     * @param  object $compiler   compiler object
+     * @param  array  $attributes attributes applied to the tag
+     *
+     * @return array  of mapped attributes for further processing
+     */
+    public function getAttributes($compiler, $attributes)
+    {
+        $_indexed_attr = array();
+        if (!isset($this->mapCache[ 'option' ])) {
+            $this->mapCache[ 'option' ] = array_fill_keys($this->option_flags, true);
+        }
+        foreach ($attributes as $key => $mixed) {
+            // shorthand ?
+            if (!is_array($mixed)) {
+                // option flag ?
+                if (isset($this->mapCache[ 'option' ][ trim($mixed, '\'"') ])) {
+                    $_indexed_attr[ trim($mixed, '\'"') ] = true;
+                    // shorthand attribute ?
+                } elseif (isset($this->shorttag_order[ $key ])) {
+                    $_indexed_attr[ $this->shorttag_order[ $key ] ] = $mixed;
+                } else {
+                    // too many shorthands
+                    $compiler->trigger_template_error('too many shorthand attributes', null, true);
+                }
+                // named attribute
+            } else {
+                foreach ($mixed as $k => $v) {
+                    // option flag?
+                    if (isset($this->mapCache[ 'option' ][ $k ])) {
+                        if (is_bool($v)) {
+                            $_indexed_attr[ $k ] = $v;
+                        } else {
+                            if (is_string($v)) {
+                                $v = trim($v, '\'" ');
+                            }
+                            if (isset($this->optionMap[ $v ])) {
+                                $_indexed_attr[ $k ] = $this->optionMap[ $v ];
+                            } else {
+                                $compiler->trigger_template_error("illegal value '" . var_export($v, true) .
+                                                                  "' for option flag '{$k}'", null, true);
+                            }
+                        }
+                        // must be named attribute
+                    } else {
+                        $_indexed_attr[ $k ] = $v;
+                    }
+                }
+            }
+        }
+        // check if all required attributes present
+        foreach ($this->required_attributes as $attr) {
+            if (!isset($_indexed_attr[ $attr ])) {
+                $compiler->trigger_template_error("missing '{$attr}' attribute", null, true);
+            }
+        }
+        // check for not allowed attributes
+        if ($this->optional_attributes !== array('_any')) {
+            if (!isset($this->mapCache[ 'all' ])) {
+                $this->mapCache[ 'all' ] =
+                    array_fill_keys(array_merge($this->required_attributes, $this->optional_attributes,
+                                                $this->option_flags), true);
+            }
+            foreach ($_indexed_attr as $key => $dummy) {
+                if (!isset($this->mapCache[ 'all' ][ $key ]) && $key !== 0) {
+                    $compiler->trigger_template_error("unexpected '{$key}' attribute", null, true);
+                }
+            }
+        }
+        // default 'false' for all option flags not set
+        foreach ($this->option_flags as $flag) {
+            if (!isset($_indexed_attr[ $flag ])) {
+                $_indexed_attr[ $flag ] = false;
+            }
+        }
+        if (isset($_indexed_attr[ 'nocache' ]) && $_indexed_attr[ 'nocache' ]) {
+            $compiler->tag_nocache = true;
+        }
+        return $_indexed_attr;
+    }
+
+    /**
+     * Push opening tag name on stack
+     * Optionally additional data can be saved on stack
+     *
+     * @param object $compiler compiler object
+     * @param string $openTag  the opening tag's name
+     * @param mixed  $data     optional data saved
+     */
+    public function openTag($compiler, $openTag, $data = null)
+    {
+        array_push($compiler->_tag_stack, array($openTag, $data));
+    }
+
+    /**
+     * Pop closing tag
+     * Raise an error if this stack-top doesn't match with expected opening tags
+     *
+     * @param  object       $compiler    compiler object
+     * @param  array|string $expectedTag the expected opening tag names
+     *
+     * @return mixed        any type the opening tag's name or saved data
+     */
+    public function closeTag($compiler, $expectedTag)
+    {
+        if (count($compiler->_tag_stack) > 0) {
+            // get stacked info
+            list($_openTag, $_data) = array_pop($compiler->_tag_stack);
+            // open tag must match with the expected ones
+            if (in_array($_openTag, (array) $expectedTag)) {
+                if (is_null($_data)) {
+                    // return opening tag
+                    return $_openTag;
+                } else {
+                    // return restored data
+                    return $_data;
+                }
+            }
+            // wrong nesting of tags
+            $compiler->trigger_template_error("unclosed '{$compiler->smarty->left_delimiter}{$_openTag}{$compiler->smarty->right_delimiter}' tag");
+
+            return;
+        }
+        // wrong nesting of tags
+        $compiler->trigger_template_error('unexpected closing tag', null, true);
+
+        return;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block_child.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block_child.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block_child.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block_child.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,24 @@
+<?php
+/*
+ * This file is part of Smarty.
+ *
+ * (c) 2015 Uwe Tews
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Smarty Internal Plugin Compile Block Child Class
+ *
+ * @author Uwe Tews <uwe.tews@googlemail.com>
+ */
+class Smarty_Internal_Compile_Block_Child extends Smarty_Internal_Compile_Child
+{
+    /**
+     * Tag name
+     *
+     * @var string
+     */
+    public $tag = 'block_child';
+}
\ No newline at end of file
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block_parent.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block_parent.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block_parent.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block_parent.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,31 @@
+<?php
+/*
+ * This file is part of Smarty.
+ *
+ * (c) 2015 Uwe Tews
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Smarty Internal Plugin Compile Block Parent Class
+ *
+ * @author Uwe Tews <uwe.tews@googlemail.com>
+ */
+class Smarty_Internal_Compile_Block_Parent extends Smarty_Internal_Compile_Child
+{
+    /**
+     * Tag name
+     *
+     * @var string
+     */
+    public $tag = 'block_parent';
+
+    /**
+     * Block type
+     *
+     * @var string
+     */
+    public $blockType = 'Parent';
+}
\ No newline at end of file
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_block.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,176 @@
+<?php
+/*
+ * This file is part of Smarty.
+ *
+ * (c) 2015 Uwe Tews
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Smarty Internal Plugin Compile Block Class
+ *
+ * @author Uwe Tews <uwe.tews@googlemail.com>
+ */
+class Smarty_Internal_Compile_Block extends Smarty_Internal_Compile_Shared_Inheritance
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $required_attributes = array('name');
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('name');
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $option_flags = array('hide', 'nocache');
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('assign');
+
+    /**
+     * Compiles code for the {block} tag
+     *
+     * @param  array                                 $args      array with attributes from parser
+     * @param  \Smarty_Internal_TemplateCompilerBase $compiler  compiler object
+     * @param  array                                 $parameter array with compilation parameter
+     *
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
+    {
+        if (!isset($compiler->_cache[ 'blockNesting' ])) {
+            $compiler->_cache[ 'blockNesting' ] = 0;
+        }
+        if ($compiler->_cache[ 'blockNesting' ] === 0) {
+            // make sure that inheritance gets initialized in template code
+            $this->registerInit($compiler);
+            $this->option_flags = array('hide', 'nocache', 'append', 'prepend');
+        } else {
+            $this->option_flags = array('hide', 'nocache');
+        }
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        ++$compiler->_cache[ 'blockNesting' ];
+        $_className = 'Block_' . preg_replace('![^\w]+!', '_', uniqid(rand(), true));
+        $compiler->_cache[ 'blockName' ][ $compiler->_cache[ 'blockNesting' ] ] = $_attr[ 'name' ];
+        $compiler->_cache[ 'blockClass' ][ $compiler->_cache[ 'blockNesting' ] ] = $_className;
+        $compiler->_cache[ 'blockParams' ][ $compiler->_cache[ 'blockNesting' ] ] = array();
+        $compiler->_cache[ 'blockParams' ][ 1 ][ 'subBlocks' ][ trim($_attr[ 'name' ], '"\'') ][] = $_className;
+        $this->openTag($compiler,
+                       'block',
+                       array($_attr, $compiler->nocache, $compiler->parser->current_buffer,
+                             $compiler->template->compiled->has_nocache_code,
+                             $compiler->template->caching));
+        $compiler->saveRequiredPlugins(true);
+        $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
+        $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
+        $compiler->template->compiled->has_nocache_code = false;
+        $compiler->suppressNocacheProcessing = true;
+    }
+}
+/**
+ * Smarty Internal Plugin Compile BlockClose Class
+ *
+ */
+class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_Inheritance
+{
+    /**
+     * Compiles code for the {/block} tag
+     *
+     * @param  array                                $args      array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler  compiler object
+     * @param  array                                $parameter array with compilation parameter
+     *
+     * @return bool true
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
+    {
+        list($_attr, $_nocache, $_buffer, $_has_nocache_code, $_caching) = $this->closeTag($compiler, array('block'));
+        // init block parameter
+        $_block = $compiler->_cache[ 'blockParams' ][ $compiler->_cache[ 'blockNesting' ] ];
+        unset($compiler->_cache[ 'blockParams' ][ $compiler->_cache[ 'blockNesting' ] ]);
+        $_name = $_attr[ 'name' ];
+        $_assign = isset($_attr[ 'assign' ]) ? $_attr[ 'assign' ] : null;
+        unset($_attr[ 'assign' ], $_attr[ 'name' ]);
+        foreach ($_attr as $name => $stat) {
+            if ((is_bool($stat) && $stat !== false) || (!is_bool($stat) && $stat !== 'false')) {
+                $_block[ $name ] = 'true';
+            }
+        }
+        $_className = $compiler->_cache[ 'blockClass' ][ $compiler->_cache[ 'blockNesting' ] ];
+        // get compiled block code
+        $_functionCode = $compiler->parser->current_buffer;
+        // setup buffer for template function code
+        $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
+
+        $output = "<?php\n";
+        $output .= "/* {block {$_name}} */\n";
+        $output .= "class {$_className} extends Smarty_Internal_Block\n";
+        $output .= "{\n";
+        foreach ($_block as $property => $value) {
+            $output .= "public \${$property} = " . var_export($value,true) .";\n";
+        }
+        $output .= "public function callBlock(Smarty_Internal_Template \$_smarty_tpl) {\n";
+        $output .= $compiler->compileRequiredPlugins();
+        $compiler->restoreRequiredPlugins();
+        if ($compiler->template->compiled->has_nocache_code) {
+            $output .= "\$_smarty_tpl->cached->hashes['{$compiler->template->compiled->nocache_hash}'] = true;\n";
+        }
+        if (isset($_assign)) {
+            $output .= "ob_start();\n";
+        }
+        $output .= "?>\n";
+        $compiler->parser->current_buffer->append_subtree($compiler->parser,
+                                                          new Smarty_Internal_ParseTree_Tag($compiler->parser,
+                                                                                            $output));
+        $compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
+        $output = "<?php\n";
+        if (isset($_assign)) {
+            $output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
+        }
+        $output .= "}\n";
+        $output .= "}\n";
+        $output .= "/* {/block {$_name}} */\n\n";
+        $output .= "?>\n";
+        $compiler->parser->current_buffer->append_subtree($compiler->parser,
+                                                          new Smarty_Internal_ParseTree_Tag($compiler->parser,
+                                                                                            $output));
+        $compiler->blockOrFunctionCode .= $compiler->parser->current_buffer->to_smarty_php($compiler->parser);
+        $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
+        // restore old status
+        $compiler->template->compiled->has_nocache_code = $_has_nocache_code;
+        $compiler->tag_nocache = $compiler->nocache;
+        $compiler->nocache = $_nocache;
+        $compiler->parser->current_buffer = $_buffer;
+        $output = "<?php \n";
+        if ($compiler->_cache[ 'blockNesting' ] === 1) {
+            $output .= "\$_smarty_tpl->inheritance->instanceBlock(\$_smarty_tpl, '$_className', $_name);\n";
+        } else {
+            $output .= "\$_smarty_tpl->inheritance->instanceBlock(\$_smarty_tpl, '$_className', $_name, \$this->tplIndex);\n";
+        }
+        $output .= "?>\n";
+        --$compiler->_cache[ 'blockNesting' ];
+        if ($compiler->_cache[ 'blockNesting' ] === 0) {
+            unset($compiler->_cache[ 'blockNesting' ]);
+        }
+        $compiler->has_code = true;
+        $compiler->suppressNocacheProcessing = true;
+        return $output;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_break.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_break.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_break.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_break.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,119 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Break
+ * Compiles the {break} tag
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Break Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('levels');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('levels');
+
+    /**
+    * Tag name may be overloaded by Smarty_Internal_Compile_Continue
+    *
+    * @var string
+    */
+    public $tag = 'break';
+
+    /**
+     * Compiles code for the {break} tag
+     *
+     * @param  array                                $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        list($levels, $foreachLevels) = $this->checkLevels($args, $compiler);
+        $output = "<?php ";
+        if ($foreachLevels > 0 && $this->tag === 'continue') {
+            $foreachLevels--;
+        }
+        if ($foreachLevels > 0) {
+            /* @var Smarty_Internal_Compile_Foreach $foreachCompiler */
+            $foreachCompiler = $compiler->getTagCompiler('foreach');
+            $output .= $foreachCompiler->compileRestore($foreachLevels);
+        }
+        $output .= "{$this->tag} {$levels};?>";
+        return $output;
+    }
+
+    /**
+     * check attributes and return array of break and foreach levels
+     *
+     * @param  array                                $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return array
+     * @throws \SmartyCompilerException
+     */
+    public function checkLevels($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        static $_is_loopy = array('for' => true, 'foreach' => true, 'while' => true, 'section' => true);
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+
+        if ($_attr[ 'nocache' ] === true) {
+            $compiler->trigger_template_error('nocache option not allowed', null, true);
+        }
+
+        if (isset($_attr[ 'levels' ])) {
+            if (!is_numeric($_attr[ 'levels' ])) {
+                $compiler->trigger_template_error('level attribute must be a numeric constant', null, true);
+            }
+            $levels = $_attr[ 'levels' ];
+        } else {
+            $levels = 1;
+        }
+        $level_count = $levels;
+        $stack_count = count($compiler->_tag_stack) - 1;
+        $foreachLevels = 0;
+        $lastTag = '';
+        while ($level_count > 0 && $stack_count >= 0) {
+            if (isset($_is_loopy[ $compiler->_tag_stack[ $stack_count ][ 0 ] ])) {
+                $lastTag = $compiler->_tag_stack[ $stack_count ][ 0 ];
+                if ($level_count === 0) {
+                    break;
+                }
+                $level_count --;
+                if ($compiler->_tag_stack[ $stack_count ][ 0 ] === 'foreach') {
+                    $foreachLevels ++;
+                }
+            }
+            $stack_count --;
+        }
+        if ($level_count !== 0) {
+            $compiler->trigger_template_error("cannot {$this->tag} {$levels} level(s)", null, true);
+        }
+        if ($lastTag === 'foreach' && $this->tag === 'break' && $foreachLevels > 0) {
+            $foreachLevels --;
+        }
+        return array($levels, $foreachLevels);
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_call.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_call.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_call.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_call.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Function_Call
+ * Compiles the calls of user defined tags defined by {function}
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Function_Call Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Call extends Smarty_Internal_CompileBase
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $required_attributes = array('name');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('name');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('_any');
+
+    /**
+     * Compiles the calls of user defined tags defined by {function}
+     *
+     * @param  array  $args     array with attributes from parser
+     * @param  object $compiler compiler object
+     *
+     * @return string compiled code
+     */
+    public function compile($args, $compiler)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        // save possible attributes
+        if (isset($_attr[ 'assign' ])) {
+            // output will be stored in a smarty variable instead of being displayed
+            $_assign = $_attr[ 'assign' ];
+        }
+        //$_name = trim($_attr['name'], "''");
+        $_name = $_attr[ 'name' ];
+        unset($_attr[ 'name' ], $_attr[ 'assign' ], $_attr[ 'nocache' ]);
+        // set flag (compiled code of {function} must be included in cache file
+        if (!$compiler->template->caching || $compiler->nocache || $compiler->tag_nocache) {
+            $_nocache = 'true';
+        } else {
+            $_nocache = 'false';
+        }
+        $_paramsArray = array();
+        foreach ($_attr as $_key => $_value) {
+            if (is_int($_key)) {
+                $_paramsArray[] = "$_key=>$_value";
+            } else {
+                $_paramsArray[] = "'$_key'=>$_value";
+            }
+        }
+        $_params = 'array(' . implode(',', $_paramsArray) . ')';
+        //$compiler->suppressNocacheProcessing = true;
+        // was there an assign attribute
+        if (isset($_assign)) {
+            $_output =
+                "<?php ob_start();\n\$_smarty_tpl->smarty->ext->_tplFunction->callTemplateFunction(\$_smarty_tpl, {$_name}, {$_params}, {$_nocache});\n\$_smarty_tpl->assign({$_assign}, ob_get_clean());?>\n";
+        } else {
+            $_output =
+                "<?php \$_smarty_tpl->smarty->ext->_tplFunction->callTemplateFunction(\$_smarty_tpl, {$_name}, {$_params}, {$_nocache});?>\n";
+        }
+        return $_output;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_capture.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_capture.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_capture.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_capture.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Capture
+ * Compiles the {capture} tag
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Capture Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Capture extends Smarty_Internal_CompileBase
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('name');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('name', 'assign', 'append');
+
+    /**
+     * Compiles code for the {$smarty.capture.xxx}
+     *
+     * @param  array                            $args      array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase$compiler  compiler object
+     * @param  array                            $parameter array with compilation parameter
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+     */
+    public static function compileSpecialVariable($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = null)
+    {
+        $tag = trim($parameter[ 0 ], '"\'');
+        $name = isset($parameter[ 1 ]) ? $compiler->getId($parameter[ 1 ]) : null;
+        if (!$name) {
+            //$compiler->trigger_template_error("missing or illegal \$smarty.{$tag} name attribute", null, true);
+        }
+        return '$_smarty_tpl->smarty->ext->_capture->getBuffer($_smarty_tpl'.(isset($name)?", '{$name}')":')');
+    }
+
+    /**
+     * Compiles code for the {capture} tag
+     *
+     * @param  array                            $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     * @param null                              $parameter
+     *
+     * @return string compiled code
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = null)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args, $parameter, 'capture');
+
+        $buffer = isset($_attr[ 'name' ]) ? $_attr[ 'name' ] : "'default'";
+        $assign = isset($_attr[ 'assign' ]) ? $_attr[ 'assign' ] : 'null';
+        $append = isset($_attr[ 'append' ]) ? $_attr[ 'append' ] : 'null';
+
+        $compiler->_cache[ 'capture_stack' ][] = array($compiler->nocache);
+        // maybe nocache because of nocache variables
+        $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
+        $_output = "<?php \$_smarty_tpl->smarty->ext->_capture->open(\$_smarty_tpl, $buffer, $assign, $append);?>";
+
+        return $_output;
+    }
+}
+
+/**
+ * Smarty Internal Plugin Compile Captureclose Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_CaptureClose extends Smarty_Internal_CompileBase
+{
+    /**
+     * Compiles code for the {/capture} tag
+     *
+     * @param  array                            $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     * @param null                              $parameter
+     *
+     * @return string compiled code
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args, $parameter, '/capture');
+        // must endblock be nocache?
+        if ($compiler->nocache) {
+            $compiler->tag_nocache = true;
+        }
+
+        list($compiler->nocache) = array_pop($compiler->_cache[ 'capture_stack' ]);
+
+        return "<?php \$_smarty_tpl->smarty->ext->_capture->close(\$_smarty_tpl);?>";
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_child.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_child.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_child.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_child.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,77 @@
+<?php
+/*
+ * This file is part of Smarty.
+ *
+ * (c) 2015 Uwe Tews
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Smarty Internal Plugin Compile Child Class
+ *
+ * @author Uwe Tews <uwe.tews@googlemail.com>
+ */
+class Smarty_Internal_Compile_Child extends Smarty_Internal_CompileBase
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('assign');
+
+    /**
+     * Tag name
+     *
+     * @var string
+     */
+    public $tag = 'child';
+
+    /**
+     * Block type
+     *
+     * @var string
+     */
+    public $blockType = 'Child';
+
+    /**
+     * Compiles code for the {child} tag
+     *
+     * @param  array                                 $args      array with attributes from parser
+     * @param  \Smarty_Internal_TemplateCompilerBase $compiler  compiler object
+     * @param  array                                 $parameter array with compilation parameter
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        $tag = isset($parameter[0]) ? "'{$parameter[0]}'" : "'{{$this->tag}}'";
+        if (!isset($compiler->_cache[ 'blockNesting' ])) {
+            $compiler->trigger_template_error("{$tag} used outside {block} tags ",
+                                              $compiler->parser->lex->taglineno);
+        }
+        $compiler->has_code = true;
+        $compiler->suppressNocacheProcessing = true;
+        if ($this->blockType === 'Child') {
+            $compiler->_cache[ 'blockParams' ][ $compiler->_cache[ 'blockNesting' ] ][ 'callsChild' ] = 'true';
+        }
+        $_assign = isset($_attr[ 'assign' ]) ? $_attr[ 'assign' ] : null;
+        $output = "<?php \n";
+        if (isset($_assign)) {
+            $output .= "ob_start();\n";
+        }
+        $output .= '$_smarty_tpl->inheritance->call' . $this->blockType . '($_smarty_tpl, $this' .
+                   ($this->blockType === 'Child' ? '' : ", {$tag}"). ");\n";
+        if (isset($_assign)) {
+            $output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
+        }
+        $output .="?>\n";
+        return $output;
+    }
+}
\ No newline at end of file
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_config_load.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_config_load.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_config_load.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_config_load.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Config Load
+ * Compiles the {config load} tag
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Config Load Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Config_Load extends Smarty_Internal_CompileBase
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $required_attributes = array('file');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('file', 'section');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('section', 'scope');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $option_flags = array('nocache', 'noscope');
+
+    /**
+     * Valid scope names
+     *
+     * @var array
+     */
+    public $valid_scopes = array('local' => Smarty::SCOPE_LOCAL, 'parent' => Smarty::SCOPE_PARENT,
+                                 'root' => Smarty::SCOPE_ROOT, 'tpl_root' => Smarty::SCOPE_TPL_ROOT,
+                                 'smarty' => Smarty::SCOPE_SMARTY, 'global' => Smarty::SCOPE_SMARTY);
+
+    /**
+     * Compiles code for the {config_load} tag
+     *
+     * @param  array                                $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+
+        if ($_attr[ 'nocache' ] === true) {
+            $compiler->trigger_template_error('nocache option not allowed', null, true);
+        }
+
+        // save possible attributes
+        $conf_file = $_attr[ 'file' ];
+        if (isset($_attr[ 'section' ])) {
+            $section = $_attr[ 'section' ];
+        } else {
+            $section = 'null';
+        }
+        // scope setup
+        if ($_attr[ 'noscope' ]) {
+            $_scope = - 1;
+        } else {
+            $_scope = $compiler->convertScope($_attr, $this->valid_scopes);
+        }
+
+        // create config object
+        $_output =
+            "<?php\n\$_smarty_tpl->smarty->ext->configLoad->_loadConfigFile(\$_smarty_tpl, {$conf_file}, {$section}, {$_scope});\n?>\n";
+
+        return $_output;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_continue.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_continue.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_continue.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_continue.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Continue
+ * Compiles the {continue} tag
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Continue Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Continue extends Smarty_Internal_Compile_Break
+{
+    /**
+    * Tag name
+    *
+    * @var string
+    */
+    public $tag = 'continue';
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_debug.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_debug.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_debug.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_debug.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Debug
+ * Compiles the {debug} tag.
+ * It opens a window the the Smarty Debugging Console.
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Debug Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Debug extends Smarty_Internal_CompileBase
+{
+    /**
+     * Compiles code for the {debug} tag
+     *
+     * @param  array  $args     array with attributes from parser
+     * @param  object $compiler compiler object
+     *
+     * @return string compiled code
+     */
+    public function compile($args, $compiler)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+
+        // compile always as nocache
+        $compiler->tag_nocache = true;
+
+        // display debug template
+        $_output =
+            "<?php \$_smarty_debug = new Smarty_Internal_Debug;\n \$_smarty_debug->display_debug(\$_smarty_tpl);\n";
+        $_output .= "unset(\$_smarty_debug);\n?>";
+        return $_output;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_eval.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_eval.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_eval.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_eval.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Eval
+ * Compiles the {eval} tag.
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Eval Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Eval extends Smarty_Internal_CompileBase
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $required_attributes = array('var');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('assign');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('var', 'assign');
+
+    /**
+     * Compiles code for the {eval} tag
+     *
+     * @param  array  $args     array with attributes from parser
+     * @param  object $compiler compiler object
+     *
+     * @return string compiled code
+     */
+    public function compile($args, $compiler)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        if (isset($_attr[ 'assign' ])) {
+            // output will be stored in a smarty variable instead of being displayed
+            $_assign = $_attr[ 'assign' ];
+        }
+
+        // create template object
+        $_output = "\$_template = new {$compiler->smarty->template_class}('eval:'.{$_attr[ 'var' ]}, \$_smarty_tpl->smarty, \$_smarty_tpl);";
+        //was there an assign attribute?
+        if (isset($_assign)) {
+            $_output .= "\$_smarty_tpl->assign($_assign,\$_template->fetch());";
+        } else {
+            $_output .= 'echo $_template->fetch();';
+        }
+
+        return "<?php $_output ?>";
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_extends.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_extends.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_extends.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_extends.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,151 @@
+<?php
+
+/**
+ * Smarty Internal Plugin Compile extend
+ * Compiles the {extends} tag
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile extend Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Extends extends Smarty_Internal_Compile_Shared_Inheritance
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $required_attributes = array('file');
+
+    /**
+     * Array of names of optional attribute required by tag
+     * use array('_any') if there is no restriction of attributes names
+     *
+     * @var array
+     */
+    public $optional_attributes = array('extends_resource');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('file');
+
+    /**
+     * Compiles code for the {extends} tag extends: resource
+     *
+     * @param array                                 $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+     * @throws \SmartyException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        if ($_attr[ 'nocache' ] === true) {
+            $compiler->trigger_template_error('nocache option not allowed', $compiler->parser->lex->line - 1);
+        }
+        if (strpos($_attr[ 'file' ], '$_tmp') !== false) {
+            $compiler->trigger_template_error('illegal value for file attribute', $compiler->parser->lex->line - 1);
+        }
+        // add code to initialize inheritance
+        $this->registerInit($compiler, true);
+        $file = trim($_attr[ 'file' ], '\'"');
+        if (strlen($file) > 8 && substr($file, 0, 8) === 'extends:') {
+            // generate code for each template
+            $files = array_reverse(explode('|', substr($file, 8)));
+            $i = 0;
+            foreach ($files as $file) {
+                if ($file[ 0 ] === '"') {
+                    $file = trim($file, '".');
+                } else {
+                    $file = "'{$file}'";
+                }
+                $i ++;
+                if ($i === count($files) && isset($_attr[ 'extends_resource' ])) {
+                    $this->compileEndChild($compiler);
+                }
+                $this->compileInclude($compiler, $file);
+            }
+            if (!isset($_attr[ 'extends_resource' ])) {
+                $this->compileEndChild($compiler);
+            }
+        } else {
+            $this->compileEndChild($compiler, $_attr[ 'file' ]);
+        }
+        $compiler->has_code = false;
+        return '';
+    }
+
+    /**
+     * Add code for inheritance endChild() method to end of template
+     *
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler
+     * @param null|string                           $template optional inheritance parent template
+     *
+     * @throws \SmartyCompilerException
+     * @throws \SmartyException
+     */
+    private function compileEndChild(Smarty_Internal_TemplateCompilerBase $compiler, $template = null)
+    {
+        $inlineUids = '';
+        if (isset($template) && $compiler->smarty->merge_compiled_includes) {
+            $code = $compiler->compileTag('include', array($template, array('scope' => 'parent')));
+            if (preg_match('/([,][\s]*[\'][a-z0-9]+[\'][,][\s]*[\']content.*[\'])[)]/', $code, $match)) {
+                $inlineUids = $match[ 1 ];
+            }
+        }
+        $compiler->parser->template_postfix[] = new Smarty_Internal_ParseTree_Tag($compiler->parser,
+                                                                                  '<?php $_smarty_tpl->inheritance->endChild($_smarty_tpl' .
+                                                                                  (isset($template) ?
+                                                                                      ", {$template}{$inlineUids}" :
+                                                                                      '') . ");\n?>");
+    }
+
+    /**
+     * Add code for including subtemplate to end of template
+     *
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler
+     * @param  string                               $template subtemplate name
+     *
+     * @throws \SmartyCompilerException
+     * @throws \SmartyException
+     */
+    private function compileInclude(Smarty_Internal_TemplateCompilerBase $compiler, $template)
+    {
+        $compiler->parser->template_postfix[] = new Smarty_Internal_ParseTree_Tag($compiler->parser,
+                                                                                  $compiler->compileTag('include',
+                                                                                                        array($template,
+                                                                                                              array('scope' => 'parent'))));
+    }
+
+    /**
+     * Create source code for {extends} from source components array
+     *
+     * @param \Smarty_Internal_Template $template
+     *
+     * @return string
+     */
+    public static function extendsSourceArrayCode(Smarty_Internal_Template $template)
+    {
+        $resources = array();
+        foreach ($template->source->components as $source) {
+            $resources[] = $source->resource;
+        }
+        return $template->smarty->left_delimiter . 'extends file=\'extends:' . join('|', $resources) .
+               '\' extends_resource=true' . $template->smarty->right_delimiter;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_foreach.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_foreach.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_foreach.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_foreach.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,343 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Foreach
+ * Compiles the {foreach} {foreachelse} {/foreach} tags
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Foreach Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Foreach extends Smarty_Internal_Compile_Private_ForeachSection
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $required_attributes = array('from', 'item');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('name', 'key', 'properties');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('from', 'item', 'key', 'name');
+
+    /**
+     * counter
+     *
+     * @var int
+     */
+    public $counter = 0;
+
+    /**
+     * Name of this tag
+     *
+     * @var string
+     */
+    public $tagName = 'foreach';
+
+    /**
+     * Valid properties of $smarty.foreach.name.xxx variable
+     *
+     * @var array
+     */
+    public $nameProperties = array('first', 'last', 'index', 'iteration', 'show', 'total');
+
+    /**
+     * Valid properties of $item@xxx variable
+     *
+     * @var array
+     */
+    public $itemProperties = array('first', 'last', 'index', 'iteration', 'show', 'total', 'key');
+
+    /**
+     * Flag if tag had name attribute
+     *
+     * @var bool
+     */
+    public $isNamed = false;
+
+    /**
+     * Compiles code for the {foreach} tag
+     *
+     * @param  array                                $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+     * @throws \SmartyException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        $compiler->loopNesting ++;
+        // init
+        $this->isNamed = false;
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        $from = $_attr[ 'from' ];
+        $item = $compiler->getId($_attr[ 'item' ]);
+        if ($item === false) {
+            $item = $compiler->getVariableName($_attr[ 'item' ]);
+        }
+        $key = $name = null;
+        $attributes = array('item' => $item);
+        if (isset($_attr[ 'key' ])) {
+            $key = $compiler->getId($_attr[ 'key' ]);
+            if ($key === false) {
+                $key = $compiler->getVariableName($_attr[ 'key' ]);
+            }
+            $attributes[ 'key' ] = $key;
+        }
+        if (isset($_attr[ 'name' ])) {
+            $this->isNamed = true;
+            $name = $attributes[ 'name' ] = $compiler->getId($_attr[ 'name' ]);
+        }
+        foreach ($attributes as $a => $v) {
+            if ($v === false) {
+                $compiler->trigger_template_error("'{$a}' attribute/variable has illegal value", null, true);
+            }
+        }
+        $fromName = $compiler->getVariableName($_attr[ 'from' ]);
+        if ($fromName) {
+            foreach (array('item', 'key') as $a) {
+                if (isset($attributes[ $a ]) && $attributes[ $a ] === $fromName) {
+                    $compiler->trigger_template_error("'{$a}' and 'from' may not have same variable name '{$fromName}'",
+                                                      null, true);
+                }
+            }
+        }
+
+        $itemVar = "\$_smarty_tpl->tpl_vars['{$item}']";
+        $local = '$__foreach_' . $attributes[ 'item' ] . '_' . $this->counter ++ . '_';
+        // search for used tag attributes
+        $itemAttr = array();
+        $namedAttr = array();
+        $this->scanForProperties($attributes, $compiler);
+        if (!empty($this->matchResults[ 'item' ])) {
+            $itemAttr = $this->matchResults[ 'item' ];
+        }
+        if (!empty($this->matchResults[ 'named' ])) {
+            $namedAttr = $this->matchResults[ 'named' ];
+        }
+        if (isset($_attr[ 'properties' ]) && preg_match_all('/[\'](.*?)[\']/', $_attr[ 'properties' ], $match)) {
+            foreach ($match[ 1 ] as $prop) {
+                if (in_array($prop, $this->itemProperties)) {
+                    $itemAttr[ $prop ] = true;
+                } else {
+                    $compiler->trigger_template_error("Invalid property '{$prop}'", null, true);
+                }
+            }
+            if ($this->isNamed) {
+                foreach ($match[ 1 ] as $prop) {
+                    if (in_array($prop, $this->nameProperties)) {
+                        $nameAttr[ $prop ] = true;
+                    } else {
+                        $compiler->trigger_template_error("Invalid property '{$prop}'", null, true);
+                    }
+                }
+            }
+        }
+        if (isset($itemAttr[ 'first' ])) {
+            $itemAttr[ 'index' ] = true;
+        }
+        if (isset($namedAttr[ 'first' ])) {
+            $namedAttr[ 'index' ] = true;
+        }
+        if (isset($namedAttr[ 'last' ])) {
+            $namedAttr[ 'iteration' ] = true;
+            $namedAttr[ 'total' ] = true;
+        }
+        if (isset($itemAttr[ 'last' ])) {
+            $itemAttr[ 'iteration' ] = true;
+            $itemAttr[ 'total' ] = true;
+        }
+        if (isset($namedAttr[ 'show' ])) {
+            $namedAttr[ 'total' ] = true;
+        }
+        if (isset($itemAttr[ 'show' ])) {
+            $itemAttr[ 'total' ] = true;
+        }
+        $keyTerm = '';
+        if (isset($attributes[ 'key' ])) {
+            $keyTerm = "\$_smarty_tpl->tpl_vars['{$key}']->value => ";
+        }
+        if (isset($itemAttr[ 'key' ])) {
+            $keyTerm = "{$itemVar}->key => ";
+        }
+        if ($this->isNamed) {
+            $foreachVar = "\$_smarty_tpl->tpl_vars['__smarty_foreach_{$attributes['name']}']";
+        }
+        $needTotal = isset($itemAttr[ 'total' ]);
+        // Register tag
+        $this->openTag($compiler, 'foreach',
+                       array('foreach', $compiler->nocache, $local, $itemVar, empty($itemAttr) ? 1 : 2));
+        // maybe nocache because of nocache variables
+        $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
+        // generate output code
+        $output = "<?php\n";
+        $output .= "\$_from = \$_smarty_tpl->smarty->ext->_foreach->init(\$_smarty_tpl, $from, " .
+                   var_export($item, true);
+        if ($name || $needTotal || $key) {
+            $output .= ', ' . var_export($needTotal, true);
+        }
+        if ($name || $key) {
+            $output .= ', ' . var_export($key, true);
+        }
+        if ($name) {
+            $output .= ', ' . var_export($name, true) . ', ' . var_export($namedAttr, true);
+        }
+        $output .= ");\n";
+        if (isset($itemAttr[ 'show' ])) {
+            $output .= "{$itemVar}->show = ({$itemVar}->total > 0);\n";
+        }
+        if (isset($itemAttr[ 'iteration' ])) {
+            $output .= "{$itemVar}->iteration = 0;\n";
+        }
+        if (isset($itemAttr[ 'index' ])) {
+            $output .= "{$itemVar}->index = -1;\n";
+        }
+        $output .= "if (\$_from !== null) {\n";
+        $output .= "foreach (\$_from as {$keyTerm}{$itemVar}->value) {\n";
+        if (isset($attributes[ 'key' ]) && isset($itemAttr[ 'key' ])) {
+            $output .= "\$_smarty_tpl->tpl_vars['{$key}']->value = {$itemVar}->key;\n";
+        }
+        if (isset($itemAttr[ 'iteration' ])) {
+            $output .= "{$itemVar}->iteration++;\n";
+        }
+        if (isset($itemAttr[ 'index' ])) {
+            $output .= "{$itemVar}->index++;\n";
+        }
+        if (isset($itemAttr[ 'first' ])) {
+            $output .= "{$itemVar}->first = !{$itemVar}->index;\n";
+        }
+        if (isset($itemAttr[ 'last' ])) {
+            $output .= "{$itemVar}->last = {$itemVar}->iteration === {$itemVar}->total;\n";
+        }
+        if (isset($foreachVar)) {
+            if (isset($namedAttr[ 'iteration' ])) {
+                $output .= "{$foreachVar}->value['iteration']++;\n";
+            }
+            if (isset($namedAttr[ 'index' ])) {
+                $output .= "{$foreachVar}->value['index']++;\n";
+            }
+            if (isset($namedAttr[ 'first' ])) {
+                $output .= "{$foreachVar}->value['first'] = !{$foreachVar}->value['index'];\n";
+            }
+            if (isset($namedAttr[ 'last' ])) {
+                $output .= "{$foreachVar}->value['last'] = {$foreachVar}->value['iteration'] === {$foreachVar}->value['total'];\n";
+            }
+        }
+        if (!empty($itemAttr)) {
+            $output .= "{$local}saved = {$itemVar};\n";
+        }
+        $output .= '?>';
+
+        return $output;
+    }
+
+    /**
+     * Compiles code for to restore saved template variables
+     *
+     * @param int $levels number of levels to restore
+     *
+     * @return string compiled code
+     */
+    public function compileRestore($levels)
+    {
+        return "\$_smarty_tpl->smarty->ext->_foreach->restore(\$_smarty_tpl, {$levels});";
+    }
+}
+
+/**
+ * Smarty Internal Plugin Compile Foreachelse Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Foreachelse extends Smarty_Internal_CompileBase
+{
+    /**
+     * Compiles code for the {foreachelse} tag
+     *
+     * @param  array                                $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return string compiled code
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+
+        list($openTag, $nocache, $local, $itemVar, $restore) = $this->closeTag($compiler, array('foreach'));
+        $this->openTag($compiler, 'foreachelse', array('foreachelse', $nocache, $local, $itemVar, 0));
+        $output = "<?php\n";
+        if ($restore === 2) {
+            $output .= "{$itemVar} = {$local}saved;\n";
+        }
+        $output .= "}\n} else {\n?>";
+        return $output;
+    }
+}
+
+/**
+ * Smarty Internal Plugin Compile Foreachclose Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Foreachclose extends Smarty_Internal_CompileBase
+{
+    /**
+     * Compiles code for the {/foreach} tag
+     *
+     * @param  array                                $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+      */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        $compiler->loopNesting --;
+        // must endblock be nocache?
+        if ($compiler->nocache) {
+            $compiler->tag_nocache = true;
+        }
+
+        list($openTag, $compiler->nocache, $local, $itemVar, $restore) =
+            $this->closeTag($compiler, array('foreach', 'foreachelse'));
+        $output = "<?php\n";
+
+        if ($restore === 2) {
+            $output .= "{$itemVar} = {$local}saved;\n";
+        }
+        if ($restore > 0) {
+            $output .= "}\n";
+        }
+        $output .= "}\n";
+        /* @var Smarty_Internal_Compile_Foreach $foreachCompiler */
+        $foreachCompiler = $compiler->getTagCompiler('foreach');
+        $output .= $foreachCompiler->compileRestore(1);
+        $output .= "?>";
+        return $output;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_for.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_for.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_for.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_for.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,170 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile For
+ * Compiles the {for} {forelse} {/for} tags
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile For Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_For extends Smarty_Internal_CompileBase
+{
+    /**
+     * Compiles code for the {for} tag
+     * Smarty 3 does implement two different syntax's:
+     * - {for $var in $array}
+     * For looping over arrays or iterators
+     * - {for $x=0; $x<$y; $x++}
+     * For general loops
+     * The parser is generating different sets of attribute by which this compiler can
+     * determine which syntax is used.
+     *
+     * @param  array  $args      array with attributes from parser
+     * @param  object $compiler  compiler object
+     * @param  array  $parameter array with compilation parameter
+     *
+     * @return string compiled code
+     */
+    public function compile($args, $compiler, $parameter)
+    {
+        $compiler->loopNesting ++;
+        if ($parameter === 0) {
+            $this->required_attributes = array('start', 'to');
+            $this->optional_attributes = array('max', 'step');
+        } else {
+            $this->required_attributes = array('start', 'ifexp', 'var', 'step');
+            $this->optional_attributes = array();
+        }
+        $this->mapCache = array();
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+
+        $output = "<?php\n";
+        if ($parameter === 1) {
+            foreach ($_attr[ 'start' ] as $_statement) {
+                if (is_array($_statement[ 'var' ])) {
+                    $var = $_statement[ 'var' ][ 'var' ];
+                    $index = $_statement[ 'var' ][ 'smarty_internal_index' ];
+                } else {
+                    $var = $_statement[ 'var' ];
+                    $index = '';
+                }
+                $output .= "\$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable(null, \$_smarty_tpl->isRenderingCache);\n";
+                $output .= "\$_smarty_tpl->tpl_vars[$var]->value{$index} = {$_statement['value']};\n";
+            }
+            if (is_array($_attr[ 'var' ])) {
+                $var = $_attr[ 'var' ][ 'var' ];
+                $index = $_attr[ 'var' ][ 'smarty_internal_index' ];
+            } else {
+                $var = $_attr[ 'var' ];
+                $index = '';
+            }
+            $output .= "if ($_attr[ifexp]) {\nfor (\$_foo=true;$_attr[ifexp]; \$_smarty_tpl->tpl_vars[$var]->value{$index}$_attr[step]) {\n";
+        } else {
+            $_statement = $_attr[ 'start' ];
+            if (is_array($_statement[ 'var' ])) {
+                $var = $_statement[ 'var' ][ 'var' ];
+                $index = $_statement[ 'var' ][ 'smarty_internal_index' ];
+            } else {
+                $var = $_statement[ 'var' ];
+                $index = '';
+            }
+            $output .= "\$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable(null, \$_smarty_tpl->isRenderingCache);";
+            if (isset($_attr[ 'step' ])) {
+                $output .= "\$_smarty_tpl->tpl_vars[$var]->step = $_attr[step];";
+            } else {
+                $output .= "\$_smarty_tpl->tpl_vars[$var]->step = 1;";
+            }
+            if (isset($_attr[ 'max' ])) {
+                $output .= "\$_smarty_tpl->tpl_vars[$var]->total = (int) min(ceil((\$_smarty_tpl->tpl_vars[$var]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$var]->step)),$_attr[max]);\n";
+            } else {
+                $output .= "\$_smarty_tpl->tpl_vars[$var]->total = (int) ceil((\$_smarty_tpl->tpl_vars[$var]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$var]->step));\n";
+            }
+            $output .= "if (\$_smarty_tpl->tpl_vars[$var]->total > 0) {\n";
+            $output .= "for (\$_smarty_tpl->tpl_vars[$var]->value{$index} = $_statement[value], \$_smarty_tpl->tpl_vars[$var]->iteration = 1;\$_smarty_tpl->tpl_vars[$var]->iteration <= \$_smarty_tpl->tpl_vars[$var]->total;\$_smarty_tpl->tpl_vars[$var]->value{$index} += \$_smarty_tpl->tpl_vars[$var]->step, \$_smarty_tpl->tpl_vars[$var]->iteration++) {\n";
+            $output .= "\$_smarty_tpl->tpl_vars[$var]->first = \$_smarty_tpl->tpl_vars[$var]->iteration === 1;";
+            $output .= "\$_smarty_tpl->tpl_vars[$var]->last = \$_smarty_tpl->tpl_vars[$var]->iteration === \$_smarty_tpl->tpl_vars[$var]->total;";
+        }
+        $output .= '?>';
+
+        $this->openTag($compiler, 'for', array('for', $compiler->nocache));
+        // maybe nocache because of nocache variables
+        $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
+        // return compiled code
+        return $output;
+    }
+}
+
+/**
+ * Smarty Internal Plugin Compile Forelse Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Forelse extends Smarty_Internal_CompileBase
+{
+    /**
+     * Compiles code for the {forelse} tag
+     *
+     * @param  array  $args      array with attributes from parser
+     * @param  object $compiler  compiler object
+     * @param  array  $parameter array with compilation parameter
+     *
+     * @return string compiled code
+     */
+    public function compile($args, $compiler, $parameter)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+
+        list($openTag, $nocache) = $this->closeTag($compiler, array('for'));
+        $this->openTag($compiler, 'forelse', array('forelse', $nocache));
+
+        return "<?php }} else { ?>";
+    }
+}
+
+/**
+ * Smarty Internal Plugin Compile Forclose Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Forclose extends Smarty_Internal_CompileBase
+{
+    /**
+     * Compiles code for the {/for} tag
+     *
+     * @param  array  $args      array with attributes from parser
+     * @param  object $compiler  compiler object
+     * @param  array  $parameter array with compilation parameter
+     *
+     * @return string compiled code
+     */
+    public function compile($args, $compiler, $parameter)
+    {
+        $compiler->loopNesting --;
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        // must endblock be nocache?
+        if ($compiler->nocache) {
+            $compiler->tag_nocache = true;
+        }
+
+        list($openTag, $compiler->nocache) = $this->closeTag($compiler, array('for', 'forelse'));
+
+        $output = "<?php }\n";
+        if ($openTag !== 'forelse') {
+            $output .= "}\n";
+        }
+        $output .= "?>";
+        return $output;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_function.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_function.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_function.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_function.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,209 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Function
+ * Compiles the {function} {/function} tags
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Function Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase
+{
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $required_attributes = array('name');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('name');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('_any');
+
+    /**
+     * Compiles code for the {function} tag
+     *
+     * @param  array                                $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return bool true
+     * @throws \SmartyCompilerException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+
+        if ($_attr[ 'nocache' ] === true) {
+            $compiler->trigger_template_error('nocache option not allowed', null, true);
+        }
+        unset($_attr[ 'nocache' ]);
+        $_name = trim($_attr[ 'name' ], '\'"');
+        $compiler->parent_compiler->tpl_function[ $_name ] = array();
+        $save = array($_attr, $compiler->parser->current_buffer, $compiler->template->compiled->has_nocache_code,
+                      $compiler->template->caching);
+        $this->openTag($compiler, 'function', $save);
+        // Init temporary context
+        $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
+        $compiler->template->compiled->has_nocache_code = false;
+        $compiler->saveRequiredPlugins(true);
+        return true;
+    }
+}
+
+/**
+ * Smarty Internal Plugin Compile Functionclose Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
+{
+
+    /**
+     * Compiler object
+     *
+     * @var object
+     */
+    private $compiler = null;
+
+    /**
+     * Compiles code for the {/function} tag
+     *
+     * @param  array                                       $args     array with attributes from parser
+     * @param object|\Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return bool true
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        $this->compiler = $compiler;
+        $saved_data = $this->closeTag($compiler, array('function'));
+        $_attr = $saved_data[ 0 ];
+        $_name = trim($_attr[ 'name' ], '\'"');
+        $compiler->parent_compiler->tpl_function[ $_name ][ 'compiled_filepath' ] =
+            $compiler->parent_compiler->template->compiled->filepath;
+        $compiler->parent_compiler->tpl_function[ $_name ][ 'uid' ] = $compiler->template->source->uid;
+        $_parameter = $_attr;
+        unset($_parameter[ 'name' ]);
+        // default parameter
+        $_paramsArray = array();
+        foreach ($_parameter as $_key => $_value) {
+            if (is_int($_key)) {
+                $_paramsArray[] = "$_key=>$_value";
+            } else {
+                $_paramsArray[] = "'$_key'=>$_value";
+            }
+        }
+        if (!empty($_paramsArray)) {
+            $_params = 'array(' . implode(',', $_paramsArray) . ')';
+            $_paramsCode = "\$params = array_merge($_params, \$params);\n";
+        } else {
+            $_paramsCode = '';
+        }
+        $_functionCode = $compiler->parser->current_buffer;
+        // setup buffer for template function code
+        $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
+
+        $_funcName = "smarty_template_function_{$_name}_{$compiler->template->compiled->nocache_hash}";
+        $_funcNameCaching = $_funcName . '_nocache';
+        if ($compiler->template->compiled->has_nocache_code) {
+            $compiler->parent_compiler->tpl_function[ $_name ][ 'call_name_caching' ] = $_funcNameCaching;
+            $output = "<?php\n";
+            $output .= "/* {$_funcNameCaching} */\n";
+            $output .= "if (!function_exists('{$_funcNameCaching}')) {\n";
+            $output .= "function {$_funcNameCaching} (Smarty_Internal_Template \$_smarty_tpl,\$params) {\n";
+            $output .= "ob_start();\n";
+            $output .= $compiler->compileRequiredPlugins();
+            $output .= "\$_smarty_tpl->compiled->has_nocache_code = true;\n";
+            $output .= $_paramsCode;
+            $output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}\n";
+            $output .= "\$params = var_export(\$params, true);\n";
+            $output .= "echo \"/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/<?php ";
+            $output .= "\\\$_smarty_tpl->smarty->ext->_tplFunction->saveTemplateVariables(\\\$_smarty_tpl, '{$_name}');\nforeach (\$params as \\\$key => \\\$value) {\n\\\$_smarty_tpl->tpl_vars[\\\$key] = new Smarty_Variable(\\\$value, \\\$_smarty_tpl->isRenderingCache);\n}\n?>";
+            $output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\";?>";
+            $compiler->parser->current_buffer->append_subtree($compiler->parser,
+                                                              new Smarty_Internal_ParseTree_Tag($compiler->parser,
+                                                                                                $output));
+            $compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
+            $output = "<?php echo \"/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/<?php ";
+            $output .= "\\\$_smarty_tpl->smarty->ext->_tplFunction->restoreTemplateVariables(\\\$_smarty_tpl, '{$_name}');?>\n";
+            $output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\";\n?>";
+            $output .= "<?php echo str_replace('{$compiler->template->compiled->nocache_hash}', \$_smarty_tpl->compiled->nocache_hash, ob_get_clean());\n";
+            $output .= "}\n}\n";
+            $output .= "/*/ {$_funcName}_nocache */\n\n";
+            $output .= "?>\n";
+            $compiler->parser->current_buffer->append_subtree($compiler->parser,
+                                                              new Smarty_Internal_ParseTree_Tag($compiler->parser,
+                                                                                                $output));
+            $_functionCode = new Smarty_Internal_ParseTree_Tag($compiler->parser,
+                                                               preg_replace_callback("/((<\?php )?echo '\/\*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/([\S\s]*?)\/\*\/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/",
+                                                                                     array($this, 'removeNocache'),
+                                                                                     $_functionCode->to_smarty_php($compiler->parser)));
+        }
+        $compiler->parent_compiler->tpl_function[ $_name ][ 'call_name' ] = $_funcName;
+        $output = "<?php\n";
+        $output .= "/* {$_funcName} */\n";
+        $output .= "if (!function_exists('{$_funcName}')) {\n";
+        $output .= "function {$_funcName}(Smarty_Internal_Template \$_smarty_tpl,\$params) {\n";
+        $output .= $_paramsCode;
+        $output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}\n";
+        $output .= $compiler->compileCheckPlugins(array_merge($compiler->required_plugins[ 'compiled' ], $compiler->required_plugins[ 'nocache' ]));
+        $output .= "?>\n";
+        $compiler->parser->current_buffer->append_subtree($compiler->parser,
+                                                          new Smarty_Internal_ParseTree_Tag($compiler->parser,
+                                                                                            $output));
+        $compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
+        $output = "<?php\n}}\n";
+        $output .= "/*/ {$_funcName} */\n\n";
+        $output .= "?>\n";
+        $compiler->parser->current_buffer->append_subtree($compiler->parser,
+                                                          new Smarty_Internal_ParseTree_Tag($compiler->parser,
+                                                                                            $output));
+        $compiler->parent_compiler->blockOrFunctionCode .= $compiler->parser->current_buffer->to_smarty_php($compiler->parser);
+       // restore old buffer
+        $compiler->parser->current_buffer = $saved_data[ 1 ];
+        // restore old status
+        $compiler->restoreRequiredPlugins();
+        $compiler->template->compiled->has_nocache_code = $saved_data[ 2 ];
+        $compiler->template->caching = $saved_data[ 3 ];
+        return true;
+    }
+
+    /**
+     * Remove nocache code
+     *
+     * @param $match
+     *
+     * @return string
+     */
+    function removeNocache($match)
+    {
+        $code =
+            preg_replace("/((<\?php )?echo '\/\*%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/)|(\/\*\/%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/",
+                         '', $match[ 0 ]);
+        $code = str_replace(array('\\\'', '\\\\\''), array('\'', '\\\''), $code);
+        return $code;
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_if.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_if.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_if.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_if.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,209 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile If
+ * Compiles the {if} {else} {elseif} {/if} tags
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile If Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_If extends Smarty_Internal_CompileBase
+{
+    /**
+     * Compiles code for the {if} tag
+     *
+     * @param array                                 $args      array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler  compiler object
+     * @param array                                 $parameter array with compilation parameter
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        $this->openTag($compiler, 'if', array(1, $compiler->nocache));
+        // must whole block be nocache ?
+        $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
+
+        if (!isset($parameter['if condition'])) {
+            $compiler->trigger_template_error('missing if condition', null, true);
+        }
+
+        if (is_array($parameter[ 'if condition' ])) {
+            if (is_array($parameter[ 'if condition' ][ 'var' ])) {
+                $var = $parameter[ 'if condition' ][ 'var' ][ 'var' ];
+            } else {
+                $var = $parameter[ 'if condition' ][ 'var' ];
+            }
+            if ($compiler->nocache) {
+                // create nocache var to make it know for further compiling
+                $compiler->setNocacheInVariable($var);
+            }
+            $prefixVar = $compiler->getNewPrefixVariable();
+            $_output = "<?php {$prefixVar} = {$parameter[ 'if condition' ][ 'value' ]};?>\n";
+            $assignAttr = array();
+            $assignAttr[][ 'value' ] = $prefixVar;
+            $assignCompiler = new Smarty_Internal_Compile_Assign();
+            if (is_array($parameter[ 'if condition' ][ 'var' ])) {
+                $assignAttr[][ 'var' ] = $parameter[ 'if condition' ][ 'var' ][ 'var' ];
+                $_output .= $assignCompiler->compile($assignAttr, $compiler,
+                                                    array('smarty_internal_index' => $parameter[ 'if condition' ][ 'var' ][ 'smarty_internal_index' ]));
+            } else {
+                $assignAttr[][ 'var' ] = $parameter[ 'if condition' ][ 'var' ];
+                $_output .= $assignCompiler->compile($assignAttr, $compiler, array());
+            }
+            $_output .= "<?php if ({$prefixVar}) {?>";
+            return $_output;
+        } else {
+            return "<?php if ({$parameter['if condition']}) {?>";
+        }
+    }
+}
+
+/**
+ * Smarty Internal Plugin Compile Else Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Else extends Smarty_Internal_CompileBase
+{
+    /**
+     * Compiles code for the {else} tag
+     *
+     * @param array                                 $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return string compiled code
+      */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        list($nesting, $compiler->tag_nocache) = $this->closeTag($compiler, array('if', 'elseif'));
+        $this->openTag($compiler, 'else', array($nesting, $compiler->tag_nocache));
+
+        return '<?php } else { ?>';
+    }
+}
+
+/**
+ * Smarty Internal Plugin Compile ElseIf Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Elseif extends Smarty_Internal_CompileBase
+{
+    /**
+     * Compiles code for the {elseif} tag
+     *
+     * @param array                                 $args      array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler  compiler object
+     * @param array                                 $parameter array with compilation parameter
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+
+        list($nesting, $compiler->tag_nocache) = $this->closeTag($compiler, array('if', 'elseif'));
+
+        if (!isset($parameter['if condition'])) {
+            $compiler->trigger_template_error('missing elseif condition', null, true);
+        }
+
+        $assignCode = '';
+        $var = '';
+        if (is_array($parameter[ 'if condition' ])) {
+            $condition_by_assign = true;
+            if (is_array($parameter[ 'if condition' ][ 'var' ])) {
+                $var = $parameter[ 'if condition' ][ 'var' ][ 'var' ];
+            } else {
+                $var = $parameter[ 'if condition' ][ 'var' ];
+            }
+            if ($compiler->nocache) {
+                // create nocache var to make it know for further compiling
+                $compiler->setNocacheInVariable($var);
+            }
+            $prefixVar = $compiler->getNewPrefixVariable();
+            $assignCode = "<?php {$prefixVar} = {$parameter[ 'if condition' ][ 'value' ]};?>\n";
+            $assignCompiler = new Smarty_Internal_Compile_Assign();
+            $assignAttr = array();
+            $assignAttr[][ 'value' ] = $prefixVar;
+            if (is_array($parameter[ 'if condition' ][ 'var' ])) {
+                $assignAttr[][ 'var' ] = $parameter[ 'if condition' ][ 'var' ][ 'var' ];
+                $assignCode .= $assignCompiler->compile($assignAttr, $compiler,
+                                                       array('smarty_internal_index' => $parameter[ 'if condition' ][ 'var' ][ 'smarty_internal_index' ]));
+            } else {
+                $assignAttr[][ 'var' ] = $parameter[ 'if condition' ][ 'var' ];
+                $assignCode .= $assignCompiler->compile($assignAttr, $compiler, array());
+            }
+        } else {
+            $condition_by_assign = false;
+        }
+
+        $prefixCode = $compiler->getPrefixCode();
+        if (empty($prefixCode)) {
+            if ($condition_by_assign) {
+                $this->openTag($compiler, 'elseif', array($nesting + 1, $compiler->tag_nocache));
+                $_output = $compiler->appendCode("<?php } else {\n?>", $assignCode);
+                return $compiler->appendCode($_output, "<?php if ({$prefixVar}) {?>");
+            } else {
+                $this->openTag($compiler, 'elseif', array($nesting, $compiler->tag_nocache));
+                return "<?php } elseif ({$parameter['if condition']}) {?>";
+            }
+        } else {
+            $_output = $compiler->appendCode("<?php } else {\n?>", $prefixCode);
+            $this->openTag($compiler, 'elseif', array($nesting + 1, $compiler->tag_nocache));
+            if ($condition_by_assign) {
+                $_output = $compiler->appendCode($_output, $assignCode);
+                return $compiler->appendCode($_output, "<?php if ({$prefixVar}) {?>");
+            } else {
+                return $compiler->appendCode($_output, "<?php if ({$parameter['if condition']}) {?>");
+            }
+        }
+    }
+}
+
+/**
+ * Smarty Internal Plugin Compile Ifclose Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Ifclose extends Smarty_Internal_CompileBase
+{
+    /**
+     * Compiles code for the {/if} tag
+     *
+     * @param array                                 $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return string compiled code
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        // must endblock be nocache?
+        if ($compiler->nocache) {
+            $compiler->tag_nocache = true;
+        }
+        list($nesting, $compiler->nocache) = $this->closeTag($compiler, array('if', 'else', 'elseif'));
+        $tmp = '';
+        for ($i = 0; $i < $nesting; $i ++) {
+            $tmp .= '}';
+        }
+
+        return "<?php {$tmp}?>";
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_include.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_include.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_include.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_include.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,331 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Include
+ * Compiles the {include} tag
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+/**
+ * Smarty Internal Plugin Compile Include Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
+{
+    /**
+     * caching mode to create nocache code but no cache file
+     */
+    const CACHING_NOCACHE_CODE = 9999;
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $required_attributes = array('file');
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('file');
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $option_flags = array('nocache', 'inline', 'caching');
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('_any');
+    /**
+     * Valid scope names
+     *
+     * @var array
+     */
+    public $valid_scopes = array('parent' => Smarty::SCOPE_PARENT, 'root' => Smarty::SCOPE_ROOT,
+                                 'global' => Smarty::SCOPE_GLOBAL, 'tpl_root' => Smarty::SCOPE_TPL_ROOT,
+                                 'smarty' => Smarty::SCOPE_SMARTY);
+
+    /**
+     * Compiles code for the {include} tag
+     *
+     * @param  array                                  $args     array with attributes from parser
+     * @param  Smarty_Internal_SmartyTemplateCompiler $compiler compiler object
+     *
+     * @return string
+     * @throws \Exception
+     * @throws \SmartyCompilerException
+     * @throws \SmartyException
+     */
+    public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler)
+    {
+        $uid = $t_hash = null;
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        $fullResourceName = $source_resource = $_attr[ 'file' ];
+        $variable_template = false;
+        $cache_tpl = false;
+        // parse resource_name
+        if (preg_match('/^([\'"])(([A-Za-z0-9_\-]{2,})[:])?(([^$()]+)|(.+))\1$/', $source_resource, $match)) {
+            $type = !empty($match[ 3 ]) ? $match[ 3 ] : $compiler->template->smarty->default_resource_type;
+            $name = !empty($match[ 5 ]) ? $match[ 5 ] : $match[ 6 ];
+            $handler = Smarty_Resource::load($compiler->smarty, $type);
+            if ($handler->recompiled || $handler->uncompiled) {
+                $variable_template = true;
+            }
+            if (!$variable_template) {
+                if ($type !== 'string') {
+                    $fullResourceName = "{$type}:{$name}";
+                    $compiled = $compiler->parent_compiler->template->compiled;
+                    if (isset($compiled->includes[ $fullResourceName ])) {
+                        $compiled->includes[ $fullResourceName ]++;
+                        $cache_tpl = true;
+                    } else {
+                        if ("{$compiler->template->source->type}:{$compiler->template->source->name}" ==
+                            $fullResourceName
+                        ) {
+                            // recursive call of current template
+                            $compiled->includes[ $fullResourceName ] = 2;
+                            $cache_tpl = true;
+                        } else {
+                            $compiled->includes[ $fullResourceName ] = 1;
+                        }
+                    }
+                    $fullResourceName = $match[ 1 ] . $fullResourceName . $match[ 1 ];
+                }
+            }
+            if (empty($match[ 5 ])) {
+                $variable_template = true;
+            }
+        } else {
+            $variable_template = true;
+        }
+        // scope setup
+        $_scope = $compiler->convertScope($_attr, $this->valid_scopes);
+        // set flag to cache subtemplate object when called within loop or template name is variable.
+        if ($cache_tpl || $variable_template || $compiler->loopNesting > 0) {
+            $_cache_tpl = 'true';
+        } else {
+            $_cache_tpl = 'false';
+        }
+        // assume caching is off
+        $_caching = Smarty::CACHING_OFF;
+        $call_nocache = $compiler->tag_nocache || $compiler->nocache;
+        // caching was on and {include} is not in nocache mode
+        if ($compiler->template->caching && !$compiler->nocache && !$compiler->tag_nocache) {
+            $_caching = self::CACHING_NOCACHE_CODE;
+        }
+        // flag if included template code should be merged into caller
+        $merge_compiled_includes = ($compiler->smarty->merge_compiled_includes || $_attr[ 'inline' ] === true) &&
+                                   !$compiler->template->source->handler->recompiled;
+        if ($merge_compiled_includes) {
+            // variable template name ?
+            if ($variable_template) {
+                $merge_compiled_includes = false;
+            }
+            // variable compile_id?
+            if (isset($_attr[ 'compile_id' ]) && $compiler->isVariable($_attr[ 'compile_id' ])) {
+                $merge_compiled_includes = false;
+            }
+        }
+        /*
+        * if the {include} tag provides individual parameter for caching or compile_id
+        * the subtemplate must not be included into the common cache file and is treated like
+        * a call in nocache mode.
+        *
+        */
+        if ($_attr[ 'nocache' ] !== true && $_attr[ 'caching' ]) {
+            $_caching = $_new_caching = (int)$_attr[ 'caching' ];
+            $call_nocache = true;
+        } else {
+            $_new_caching = Smarty::CACHING_LIFETIME_CURRENT;
+        }
+        if (isset($_attr[ 'cache_lifetime' ])) {
+            $_cache_lifetime = $_attr[ 'cache_lifetime' ];
+            $call_nocache = true;
+            $_caching = $_new_caching;
+        } else {
+            $_cache_lifetime = '$_smarty_tpl->cache_lifetime';
+        }
+        if (isset($_attr[ 'cache_id' ])) {
+            $_cache_id = $_attr[ 'cache_id' ];
+            $call_nocache = true;
+            $_caching = $_new_caching;
+        } else {
+            $_cache_id = '$_smarty_tpl->cache_id';
+        }
+        if (isset($_attr[ 'compile_id' ])) {
+            $_compile_id = $_attr[ 'compile_id' ];
+        } else {
+            $_compile_id = '$_smarty_tpl->compile_id';
+        }
+        // if subtemplate will be called in nocache mode do not merge
+        if ($compiler->template->caching && $call_nocache) {
+            $merge_compiled_includes = false;
+        }
+        // assign attribute
+        if (isset($_attr[ 'assign' ])) {
+            // output will be stored in a smarty variable instead of being displayed
+            if ($_assign = $compiler->getId($_attr[ 'assign' ])) {
+                $_assign = "'{$_assign}'";
+                if ($compiler->tag_nocache || $compiler->nocache || $call_nocache) {
+                    // create nocache var to make it know for further compiling
+                    $compiler->setNocacheInVariable($_attr[ 'assign' ]);
+                }
+            } else {
+                $_assign = $_attr[ 'assign' ];
+            }
+        }
+        $has_compiled_template = false;
+        if ($merge_compiled_includes) {
+            $c_id = isset($_attr[ 'compile_id' ]) ? $_attr[ 'compile_id' ] : $compiler->template->compile_id;
+            // we must observe different compile_id and caching
+            $t_hash = sha1($c_id . ($_caching ? '--caching' : '--nocaching'));
+            $compiler->smarty->allow_ambiguous_resources = true;
+            /* @var Smarty_Internal_Template $tpl */
+            $tpl = new $compiler->smarty->template_class (trim($fullResourceName, '"\''), $compiler->smarty,
+                                                          $compiler->template, $compiler->template->cache_id, $c_id,
+                                                          $_caching);
+            $uid = $tpl->source->type . $tpl->source->uid;
+            if (!isset($compiler->parent_compiler->mergedSubTemplatesData[ $uid ][ $t_hash ])) {
+                $has_compiled_template = $this->compileInlineTemplate($compiler, $tpl, $t_hash);
+            } else {
+                $has_compiled_template = true;
+            }
+            unset($tpl);
+        }
+        // delete {include} standard attributes
+        unset($_attr[ 'file' ], $_attr[ 'assign' ], $_attr[ 'cache_id' ], $_attr[ 'compile_id' ], $_attr[ 'cache_lifetime' ], $_attr[ 'nocache' ], $_attr[ 'caching' ], $_attr[ 'scope' ], $_attr[ 'inline' ]);
+        // remaining attributes must be assigned as smarty variable
+        $_vars = 'array()';
+        if (!empty($_attr)) {
+            $_pairs = array();
+            // create variables
+            foreach ($_attr as $key => $value) {
+                $_pairs[] = "'$key'=>$value";
+            }
+            $_vars = 'array(' . join(',', $_pairs) . ')';
+        }
+        $update_compile_id = $compiler->template->caching && !$compiler->tag_nocache && !$compiler->nocache &&
+                             $_compile_id !== '$_smarty_tpl->compile_id';
+        if ($has_compiled_template && !$call_nocache) {
+            $_output = "<?php\n";
+            if ($update_compile_id) {
+                $_output .= $compiler->makeNocacheCode("\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n");
+            }
+            if (!empty($_attr) && $_caching === 9999 && $compiler->template->caching) {
+                $_vars_nc = "foreach ($_vars as \$ik => \$iv) {\n";
+                $_vars_nc .= "\$_smarty_tpl->tpl_vars[\$ik] =  new Smarty_Variable(\$iv);\n";
+                $_vars_nc .= "}\n";
+                $_output .= substr($compiler->processNocacheCode('<?php ' . $_vars_nc . "?>\n", true), 6, -3);
+            }
+            if (isset($_assign)) {
+                $_output .= "ob_start();\n";
+            }
+            $_output .= "\$_smarty_tpl->_subTemplateRender({$fullResourceName}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$uid][$t_hash]['uid']}', '{$compiler->parent_compiler->mergedSubTemplatesData[$uid][$t_hash]['func']}');\n";
+            if (isset($_assign)) {
+                $_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
+            }
+            if ($update_compile_id) {
+                $_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n");
+            }
+            $_output .= "?>";
+            return $_output;
+        }
+        if ($call_nocache) {
+            $compiler->tag_nocache = true;
+        }
+        $_output = "<?php ";
+        if ($update_compile_id) {
+            $_output .= "\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n";
+        }
+        // was there an assign attribute
+        if (isset($_assign)) {
+            $_output .= "ob_start();\n";
+        }
+        $_output .= "\$_smarty_tpl->_subTemplateRender({$fullResourceName}, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_scope, {$_cache_tpl});\n";
+        if (isset($_assign)) {
+            $_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
+        }
+        if ($update_compile_id) {
+            $_output .= "\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n";
+        }
+        $_output .= "?>";
+        return $_output;
+    }
+
+    /**
+     * Compile inline sub template
+     *
+     * @param \Smarty_Internal_SmartyTemplateCompiler $compiler
+     * @param \Smarty_Internal_Template               $tpl
+     * @param  string                                 $t_hash
+     *
+     * @return bool
+     * @throws \Exception
+     * @throws \SmartyException
+     */
+    public function compileInlineTemplate(Smarty_Internal_SmartyTemplateCompiler $compiler,
+                                          Smarty_Internal_Template $tpl,
+                                          $t_hash)
+    {
+        $uid = $tpl->source->type . $tpl->source->uid;
+        if (!($tpl->source->handler->uncompiled) && $tpl->source->exists) {
+            $compiler->parent_compiler->mergedSubTemplatesData[ $uid ][ $t_hash ][ 'uid' ] = $tpl->source->uid;
+            if (isset($compiler->template->inheritance)) {
+                $tpl->inheritance = clone $compiler->template->inheritance;
+            }
+            $tpl->compiled = new Smarty_Template_Compiled();
+            $tpl->compiled->nocache_hash = $compiler->parent_compiler->template->compiled->nocache_hash;
+            $tpl->loadCompiler();
+            // save unique function name
+            $compiler->parent_compiler->mergedSubTemplatesData[ $uid ][ $t_hash ][ 'func' ] =
+            $tpl->compiled->unifunc = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
+            // make sure whole chain gets compiled
+            $tpl->mustCompile = true;
+            $compiler->parent_compiler->mergedSubTemplatesData[ $uid ][ $t_hash ][ 'nocache_hash' ] =
+                $tpl->compiled->nocache_hash;
+            if ($tpl->source->type === 'file') {
+                $sourceInfo = $tpl->source->filepath;
+            } else {
+                $basename = $tpl->source->handler->getBasename($tpl->source);
+                $sourceInfo = $tpl->source->type . ':' .
+                              ($basename ? $basename : $tpl->source->name);
+            }
+            // get compiled code
+            $compiled_code = "<?php\n\n";
+            $compiled_code .= "/* Start inline template \"{$sourceInfo}\" =============================*/\n";
+            $compiled_code .= "function {$tpl->compiled->unifunc} (Smarty_Internal_Template \$_smarty_tpl) {\n";
+            $compiled_code .= "?>\n" . $tpl->compiler->compileTemplateSource($tpl, null, $compiler->parent_compiler);
+            $compiled_code .= "<?php\n";
+            $compiled_code .= "}\n?>\n";
+            $compiled_code .= $tpl->compiler->postFilter($tpl->compiler->blockOrFunctionCode);
+            $compiled_code .= "<?php\n\n";
+            $compiled_code .= "/* End inline template \"{$sourceInfo}\" =============================*/\n";
+            $compiled_code .= '?>';
+            unset($tpl->compiler);
+            if ($tpl->compiled->has_nocache_code) {
+                // replace nocache_hash
+                $compiled_code =
+                    str_replace("{$tpl->compiled->nocache_hash}",
+                                $compiler->template->compiled->nocache_hash,
+                                $compiled_code);
+                $compiler->template->compiled->has_nocache_code = true;
+            }
+            $compiler->parent_compiler->mergedSubTemplatesCode[ $tpl->compiled->unifunc ] = $compiled_code;
+            return true;
+        } else {
+            return false;
+        }
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_include_php.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_include_php.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_include_php.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_include_php.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,106 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Include PHP
+ * Compiles the {include_php} tag
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+/**
+ * Smarty Internal Plugin Compile Insert Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Include_Php extends Smarty_Internal_CompileBase
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $required_attributes = array('file');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('file');
+
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('once', 'assign');
+
+    /**
+     * Compiles code for the {include_php} tag
+     *
+     * @param  array                                $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return string
+     * @throws \SmartyCompilerException
+     * @throws \SmartyException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        if (!($compiler->smarty instanceof SmartyBC)) {
+            throw new SmartyException("{include_php} is deprecated, use SmartyBC class to enable");
+        }
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        /** @var Smarty_Internal_Template $_smarty_tpl
+         * used in evaluated code
+         */
+        $_smarty_tpl = $compiler->template;
+        $_filepath = false;
+        $_file = null;
+        eval('$_file = @' . $_attr[ 'file' ] . ';');
+        if (!isset($compiler->smarty->security_policy) && file_exists($_file)) {
+            $_filepath = $compiler->smarty->_realpath($_file, true);
+        } else {
+            if (isset($compiler->smarty->security_policy)) {
+                $_dir = $compiler->smarty->security_policy->trusted_dir;
+            } else {
+                $_dir = $compiler->smarty->trusted_dir;
+            }
+            if (!empty($_dir)) {
+                foreach ((array)$_dir as $_script_dir) {
+                    $_path = $compiler->smarty->_realpath($_script_dir . DIRECTORY_SEPARATOR . $_file, true);
+                    if (file_exists($_path)) {
+                        $_filepath = $_path;
+                        break;
+                    }
+                }
+            }
+        }
+        if ($_filepath === false) {
+            $compiler->trigger_template_error("{include_php} file '{$_file}' is not readable", null, true);
+        }
+        if (isset($compiler->smarty->security_policy)) {
+            $compiler->smarty->security_policy->isTrustedPHPDir($_filepath);
+        }
+        if (isset($_attr[ 'assign' ])) {
+            // output will be stored in a smarty variable instead of being displayed
+            $_assign = $_attr[ 'assign' ];
+        }
+        $_once = '_once';
+        if (isset($_attr[ 'once' ])) {
+            if ($_attr[ 'once' ] === 'false') {
+                $_once = '';
+            }
+        }
+        if (isset($_assign)) {
+            return "<?php ob_start();\ninclude{$_once} ('{$_filepath}');\n\$_smarty_tpl->assign({$_assign},ob_get_clean());\n?>";
+        } else {
+            return "<?php include{$_once} ('{$_filepath}');?>\n";
+        }
+    }
+}
diff -pruN 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_insert.php 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_insert.php
--- 3.0.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_insert.php	1970-01-01 00:00:00.000000000 +0000
+++ 3.2-2/lib/smarty/libs/sysplugins/smarty_internal_compile_insert.php	2018-05-02 20:37:27.000000000 +0000
@@ -0,0 +1,150 @@
+<?php
+/**
+ * Smarty Internal Plugin Compile Insert
+ * Compiles the {insert} tag
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ * @author     Uwe Tews
+ */
+
+/**
+ * Smarty Internal Plugin Compile Insert Class
+ *
+ * @package    Smarty
+ * @subpackage Compiler
+ */
+class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
+{
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $required_attributes = array('name');
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $shorttag_order = array('name');
+    /**
+     * Attribute definition: Overwrites base class.
+     *
+     * @var array
+     * @see Smarty_Internal_CompileBase
+     */
+    public $optional_attributes = array('_any');
+
+    /**
+     * Compiles code for the {insert} tag
+     *
+     * @param  array                                $args     array with attributes from parser
+     * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
+     *
+     * @return string compiled code
+     * @throws \SmartyCompilerException
+     * @throws \SmartyException
+     */
+    public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
+    {
+        // check and get attributes
+        $_attr = $this->getAttributes($compiler, $args);
+        $nocacheParam = $compiler->template->caching && ($compiler->tag_nocache || $compiler->nocache);
+        if (!$nocacheParam) {
+            // do not compile as nocache code
+            $compiler->suppressNocacheProcessing = true;
+        }
+        $compiler->tag_nocache = true;
+        $_smarty_tpl = $compiler->template;
+        $_name = null;
+        $_script = null;
+        $_output = '<?php ';
+        // save possible attributes
+        eval('$_name = @' . $_attr[ 'name' ] . ';');
+        if (isset($_attr[ 'assign' ])) {
+            // output will be stored in a smarty variable instead of being displayed
+            $_assign = $_attr[ 'assign' ];
+            // create variable to make sure that the compiler knows about its nocache status
+            $var = trim($_attr[ 'assign' ], '\'');
+            if (isset($compiler->template->tpl_vars[ $var ])) {
+                $compiler->template->tpl_vars[ $var ]->nocache = true;
+            } else {
+                $compiler->template->tpl_vars[ $var ] = new Smarty_Variable(null, true);
+            }
+        }
+        if (isset($_attr[ 'script' ])) {
+            // script which must be included
+            $_function = "smarty_insert_{$_name}";
+            $_smarty_tpl = $compiler->template;
+            $_filepath = false;
+            eval('$_script = @' . $_attr[ 'script' ] . ';');
+            if (!isset($compiler->smarty->security_policy) && file_exists($_script)) {
+                $_filepath = $_script;
+            } else {
+                if (isset($compiler->smarty->security_policy)) {
+                    $_dir = $compiler->smarty->security_policy->trusted_dir;
+                } else {
+                    $_dir = $compiler->smarty instanceof SmartyBC ? $compiler->smarty->trusted_dir : null;
+                }
+                if (!empty($_dir)) {
+                    foreach ((array)$_dir as $_script_dir) {
+                        $_script_dir = rtrim($_script_dir, '/\\') . DIRECTORY_SEPARATOR;
+                        if (file_exists($_script_dir . $_script)) {
+                            $_filepath = $_script_dir . $_script;
+                            break;
+                        }
+                    }
+                }
+            }
+            if ($_filepath === false) {
+                $compiler->trigger_template_error("{insert} missing script file '{$_script}'", null, true);
+            }
+            // code for script file loading
+            $_output .= "require_once '{$_filepath}' ;";
+            require_once $_filepath;
+            if (!is_callable($_function)) {
+                $compiler->trigger_template_error(" {insert} function '{$_function}' is not callable in script file '{$_script}'",
+                                                  null,
+                                                  true);
+            }
+        } else {
+            $_filepath = 'null';
+            $_function = "insert_{$_name}";
+            // function in PHP script ?
+            if (!is_callable($_function)) {
+                // try plugin
+                if (!$_function = $compiler->getPlugin($_name, 'insert')) {
+                    $compiler->trigger_template_error("{insert} no function or plugin found for '{$_name}'",
+                                                      null,
+                                                      true);
+                }
+            }
+        }
+        // delete {insert} standard attributes
+        unset($