From 2332b2279d8a8599b4f041370315edc9544b1560 Mon Sep 17 00:00:00 2001
From: tbrehm <t.brehm@ispconfig.org>
Date: Fri, 02 Aug 2013 10:48:38 -0400
Subject: [PATCH] Added support for mongodb. Many thanks to MaddinXx for the patch. http://www.howtoforge.com/forums/showthread.php?t=62691

---
 server/lib/classes/monitor_tools.inc.php                    |   57 
 interface/web/monitor/lib/lang/en.lng                       |    3 
 interface/web/sites/form/database_user.tform.php            |   10 
 interface/web/monitor/lib/lang/de.lng                       |    3 
 server/mods-available/monitor_core_module.inc.php           |   44 
 interface/web/monitor/lib/module.conf.php                   |    7 
 interface/web/admin/form/server_config.tform.php            |   72 
 interface/web/sites/lib/lang/de_database_list.lng           |    1 
 install/sql/incremental/upd_0055.sql                        |    2 
 interface/web/admin/lib/lang/de_server_config.lng           |    1 
 interface/web/sites/lib/lang/en_web_backup_list.lng         |    9 
 install/sql/ispconfig3.sql                                  |  213 +-
 interface/web/sites/database_user_edit.php                  |   62 
 interface/web/sites/form/database.tform.php                 |    9 
 interface/web/monitor/show_data.php                         |    7 
 server/cron_daily.php                                       |  248 ++-
 server/plugins-available/backup_plugin.inc.php              |   66 
 interface/web/sites/templates/database_list.htm             |   11 
 interface/lib/classes/tform.inc.php                         | 1806 ++++++++++++++--------------
 interface/lib/shelluser_blacklist                           |    3 
 interface/web/admin/templates/server_config_rescue_edit.htm |   16 
 server/mods-available/rescue_core_module.inc.php            |  175 +
 interface/web/admin/lib/lang/en_server_config.lng           |    3 
 interface/lib/classes/tools_monitor.inc.php                 |   34 
 interface/web/sites/lib/lang/de_database_admin_list.lng     |    1 
 interface/web/sites/lib/lang/de_web_backup_list.lng         |    1 
 server/plugins-available/mongo_clientdb_plugin.inc.php      |  820 +++++++++++++
 interface/web/sites/list/database.list.php                  |   15 
 interface/web/sites/lib/lang/en_database_list.lng           |    3 
 interface/web/sites/templates/database_admin_list.htm       |   11 
 interface/web/sites/lib/lang/en_database_admin_list.lng     |    3 
 31 files changed, 2,433 insertions(+), 1,283 deletions(-)

diff --git a/install/sql/incremental/upd_0055.sql b/install/sql/incremental/upd_0055.sql
new file mode 100644
index 0000000..7bcfa71
--- /dev/null
+++ b/install/sql/incremental/upd_0055.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `web_backup` CHANGE `backup_type` `backup_type` enum('web','mongodb','mysql') NOT NULL DEFAULT 'web';
+ALTER TABLE `web_database_user` ADD `database_password_mongo` varchar(32) DEFAULT NULL AFTER `database_password`;
diff --git a/install/sql/ispconfig3.sql b/install/sql/ispconfig3.sql
index cb2033d..e9bdf95 100644
--- a/install/sql/ispconfig3.sql
+++ b/install/sql/ispconfig3.sql
@@ -26,24 +26,24 @@
 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
--- Includes 
--- 
+-- Includes
+--
 -- iso_country_list.sql
--- 
+--
 -- This will create and then populate a MySQL table with a list of the names and
 -- ISO 3166 codes for countries in existence as of the date below.
--- 
+--
 -- For updates to this file, see http://27.org/isocountrylist/
 -- For more about ISO 3166, see http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html
--- 
+--
 -- Created by getisocountrylist.pl on Sun Nov  2 14:59:20 2003.
 -- Wm. Rhodes <iso_country_list@27.org>
--- 
+--
 
--- 
+--
 -- ISPConfig 3
 -- DB-Version: 3.0.0.9
--- 
+--
 
 SET FOREIGN_KEY_CHECKS = 0;
 
@@ -252,9 +252,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `client_template`
--- 
+--
 
 CREATE TABLE `client_template` (
   `template_id` int(11) unsigned NOT NULL auto_increment,
@@ -262,7 +262,7 @@
   `sys_groupid` int(11) unsigned NOT NULL default '0',
   `sys_perm_user` varchar(5) default NULL,
   `sys_perm_group` varchar(5) default NULL,
-  `sys_perm_other` varchar(5) default NULL,  
+  `sys_perm_other` varchar(5) default NULL,
   `template_name` varchar(64) NOT NULL,
   `template_type` varchar(1) NOT NULL default 'm',
   `limit_maildomain` int(11) NOT NULL default '-1',
@@ -330,9 +330,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `cron`
--- 
+--
 CREATE TABLE `cron` (
   `id` int(11) unsigned NOT NULL auto_increment,
   `sys_userid` int(11) unsigned NOT NULL default '0',
@@ -355,9 +355,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `directive_snippets`
--- 
+--
 
 CREATE TABLE IF NOT EXISTS `directive_snippets` (
   `directive_snippets_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
@@ -375,9 +375,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `dns_rr`
--- 
+--
 
 CREATE TABLE `dns_rr` (
   `id` int(11) unsigned NOT NULL auto_increment,
@@ -425,9 +425,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `dns_soa`
--- 
+--
 
 CREATE TABLE `dns_soa` (
   `id` int(10) unsigned NOT NULL auto_increment,
@@ -457,9 +457,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `dns_template`
--- 
+--
 
 CREATE TABLE `dns_template` (
   `template_id` int(11) unsigned NOT NULL auto_increment,
@@ -493,9 +493,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `firewall`
--- 
+--
 
 CREATE TABLE `firewall` (
   `firewall_id` int(11) unsigned NOT NULL auto_increment,
@@ -513,9 +513,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `ftp_user`
--- 
+--
 
 CREATE TABLE `ftp_user` (
   `ftp_user_id` int(11) unsigned NOT NULL auto_increment,
@@ -607,9 +607,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `mail_access`
--- 
+--
 
 CREATE TABLE `mail_access` (
   `access_id` int(11) unsigned NOT NULL auto_increment,
@@ -629,9 +629,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `mail_content_filter`
--- 
+--
 
 CREATE TABLE `mail_content_filter` (
   `content_filter_id` int(11) unsigned NOT NULL auto_increment,
@@ -651,9 +651,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `mail_domain`
--- 
+--
 
 CREATE TABLE `mail_domain` (
   `domain_id` int(11) unsigned NOT NULL auto_increment,
@@ -675,9 +675,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `mail_forwarding`
--- 
+--
 
 CREATE TABLE `mail_forwarding` (
   `forwarding_id` int(11) unsigned NOT NULL auto_increment,
@@ -698,9 +698,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `mail_get`
--- 
+--
 
 CREATE TABLE `mail_get` (
   `mailget_id` int(11) unsigned NOT NULL auto_increment,
@@ -764,9 +764,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `mail_traffic`
--- 
+--
 
 CREATE TABLE `mail_traffic` (
   `traffic_id` int(11) unsigned NOT NULL auto_increment,
@@ -779,9 +779,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `mail_transport`
--- 
+--
 
 CREATE TABLE `mail_transport` (
   `transport_id` int(11) unsigned NOT NULL auto_increment,
@@ -802,9 +802,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `mail_user`
--- 
+--
 
 CREATE TABLE `mail_user` (
   `mailuser_id` int(11) unsigned NOT NULL auto_increment,
@@ -848,9 +848,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `mail_user_filter`
--- 
+--
 
 CREATE TABLE `mail_user_filter` (
   `filter_id` int(11) unsigned NOT NULL auto_increment,
@@ -1061,9 +1061,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `remote_session`
--- 
+--
 
 CREATE TABLE `remote_session` (
   `remote_session` varchar(64) NOT NULL,
@@ -1075,9 +1075,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `remote_user`
--- 
+--
 
 CREATE TABLE `remote_user` (
   `remote_userid` int(11) unsigned NOT NULL auto_increment,
@@ -1094,9 +1094,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `server`
--- 
+--
 
 CREATE TABLE `server` (
   `server_id` int(11) unsigned NOT NULL auto_increment,
@@ -1124,9 +1124,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `server_ip`
--- 
+--
 
 CREATE TABLE `server_ip` (
   `server_ip_id` int(11) unsigned NOT NULL auto_increment,
@@ -1200,9 +1200,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `software_package`
--- 
+--
 
 CREATE TABLE `software_package` (
   `package_id` int(11) unsigned NOT NULL auto_increment,
@@ -1223,9 +1223,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `software_repo`
--- 
+--
 
 CREATE TABLE `software_repo` (
   `software_repo_id` int(11) unsigned NOT NULL auto_increment,
@@ -1244,9 +1244,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `software_update`
--- 
+--
 
 CREATE TABLE `software_update` (
   `software_update_id` int(11) unsigned NOT NULL auto_increment,
@@ -1266,9 +1266,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `software_update_inst`
--- 
+--
 
 CREATE TABLE `software_update_inst` (
   `software_update_inst_id` int(11) unsigned NOT NULL auto_increment,
@@ -1282,9 +1282,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `spamfilter_policy`
--- 
+--
 
 CREATE TABLE `spamfilter_policy` (
   `id` int(11) unsigned NOT NULL auto_increment,
@@ -1335,9 +1335,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `spamfilter_users`
--- 
+--
 
 CREATE TABLE `spamfilter_users` (
   `id` int(11) unsigned NOT NULL auto_increment,
@@ -1358,9 +1358,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `spamfilter_wblist`
--- 
+--
 
 CREATE TABLE `spamfilter_wblist` (
   `wblist_id` int(11) unsigned NOT NULL auto_increment,
@@ -1380,9 +1380,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `support_message`
--- 
+--
 
 CREATE TABLE `support_message` (
   `support_message_id` int(11) unsigned NOT NULL auto_increment,
@@ -1414,9 +1414,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `sys_datalog`
--- 
+--
 
 CREATE TABLE `sys_datalog` (
   `datalog_id` int(11) unsigned NOT NULL auto_increment,
@@ -1434,9 +1434,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `sys_dbsync`
--- 
+--
 
 CREATE TABLE `sys_dbsync` (
   `id` int(11) unsigned NOT NULL auto_increment,
@@ -1458,9 +1458,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `sys_filesync`
--- 
+--
 
 CREATE TABLE `sys_filesync` (
   `id` int(11) unsigned NOT NULL auto_increment,
@@ -1478,9 +1478,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `sys_group`
--- 
+--
 
 CREATE TABLE `sys_group` (
   `groupid` int(11) unsigned NOT NULL auto_increment,
@@ -1492,9 +1492,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `sys_ini`
--- 
+--
 
 CREATE TABLE `sys_ini` (
   `sysini_id` int(11) unsigned NOT NULL auto_increment,
@@ -1504,9 +1504,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `sys_log`
--- 
+--
 
 CREATE TABLE `sys_log` (
   `syslog_id` int(11) unsigned NOT NULL auto_increment,
@@ -1572,9 +1572,9 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `sys_user`
--- 
+--
 
 CREATE TABLE `sys_user` (
   `userid` int(11) unsigned NOT NULL auto_increment,
@@ -1595,7 +1595,7 @@
   `default_group` int(11) unsigned NOT NULL default '0',
   `client_id` int(11) unsigned NOT NULL default '0',
   `id_rsa` VARCHAR( 2000 ) NOT NULL default '',
-  `ssh_rsa` VARCHAR( 600 ) NOT NULL default '', 
+  `ssh_rsa` VARCHAR( 600 ) NOT NULL default '',
   PRIMARY KEY  (`userid`)
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
 
@@ -1632,14 +1632,14 @@
   `backup_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
   `server_id` int(10) unsigned NOT NULL,
   `parent_domain_id` int(10) unsigned NOT NULL,
-  `backup_type` enum('web','mysql') NOT NULL DEFAULT 'web',
+  `backup_type` enum('web','mongodb','mysql') NOT NULL DEFAULT 'web',
   `backup_mode` varchar(64) NOT NULL DEFAULT  '',
   `tstamp` int(10) unsigned NOT NULL,
   `filename` varchar(255) NOT NULL,
   `filesize` VARCHAR(10) NOT NULL,
   PRIMARY KEY (`backup_id`)
-) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
-
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
+
 -- --------------------------------------------------------
 
 --
@@ -1688,14 +1688,15 @@
   `database_user` varchar(64) DEFAULT NULL,
   `database_user_prefix` varchar(50) NOT NULL default '',
   `database_password` varchar(64) DEFAULT NULL,
+  `database_password_mongo` varchar(32) DEFAULT NULL,
   PRIMARY KEY (`database_user_id`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table  `web_domain`
--- 
+--
 
 CREATE TABLE `web_domain` (
   `domain_id` int(11) unsigned NOT NULL auto_increment,
@@ -2095,41 +2096,41 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Dumping data for table `dns_template`
--- 
+--
 
 INSERT INTO `dns_template` (`template_id`, `sys_userid`, `sys_groupid`, `sys_perm_user`, `sys_perm_group`, `sys_perm_other`, `name`, `fields`, `template`, `visible`) VALUES (1, 1, 1, 'riud', 'riud', '', 'Default', 'DOMAIN,IP,NS1,NS2,EMAIL', '[ZONE]\norigin={DOMAIN}.\nns={NS1}.\nmbox={EMAIL}.\nrefresh=7200\nretry=540\nexpire=604800\nminimum=86400\nttl=3600\n\n[DNS_RECORDS]\nA|{DOMAIN}.|{IP}|0|3600\nA|www|{IP}|0|3600\nA|mail|{IP}|0|3600\nNS|{DOMAIN}.|{NS1}.|0|3600\nNS|{DOMAIN}.|{NS2}.|0|3600\nMX|{DOMAIN}.|mail.{DOMAIN}.|10|3600', 'y');
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Dumping data for table `help_faq`
--- 
+--
 
 INSERT INTO `help_faq` VALUES (1,1,0,'I would like to know ...','Yes, of course.',1,1,'riud','riud','r');
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Dumping data for table `help_faq_sections`
--- 
+--
 
 INSERT INTO `help_faq_sections` VALUES (1,'General',0,NULL,NULL,NULL,NULL,NULL);
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Dumping data for table `software_repo`
--- 
+--
 
 INSERT INTO `software_repo` (`software_repo_id`, `sys_userid`, `sys_groupid`, `sys_perm_user`, `sys_perm_group`, `sys_perm_other`, `repo_name`, `repo_url`, `repo_username`, `repo_password`, `active`) VALUES (1, 1, 1, 'riud', 'riud', '', 'ISPConfig Addons', 'http://repo.ispconfig.org/addons/', '', '', 'n');
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Dumping data for table `spamfilter_policy`
--- 
+--
 
 INSERT INTO `spamfilter_policy` (`id`, `sys_userid`, `sys_groupid`, `sys_perm_user`, `sys_perm_group`, `sys_perm_other`, `policy_name`, `virus_lover`, `spam_lover`, `banned_files_lover`, `bad_header_lover`, `bypass_virus_checks`, `bypass_spam_checks`, `bypass_banned_checks`, `bypass_header_checks`, `spam_modifies_subj`, `virus_quarantine_to`, `spam_quarantine_to`, `banned_quarantine_to`, `bad_header_quarantine_to`, `clean_quarantine_to`, `other_quarantine_to`, `spam_tag_level`, `spam_tag2_level`, `spam_kill_level`, `spam_dsn_cutoff_level`, `spam_quarantine_cutoff_level`, `addr_extension_virus`, `addr_extension_spam`, `addr_extension_banned`, `addr_extension_bad_header`, `warnvirusrecip`, `warnbannedrecip`, `warnbadhrecip`, `newvirus_admin`, `virus_admin`, `banned_admin`, `bad_header_admin`, `spam_admin`, `spam_subject_tag`, `spam_subject_tag2`, `message_size_limit`, `banned_rulenames`) VALUES(1, 1, 0, 'riud', 'riud', 'r', 'Non-paying', 'N', 'N', 'N', 'N', 'Y', 'Y', 'Y', 'N', 'Y', '', '', '', '', '', '', 3, 7, 10, 0, 0, '', '', '', '', 'N', 'N', 'N', '', '', '', '', '', '', '', 0, '');
 INSERT INTO `spamfilter_policy` (`id`, `sys_userid`, `sys_groupid`, `sys_perm_user`, `sys_perm_group`, `sys_perm_other`, `policy_name`, `virus_lover`, `spam_lover`, `banned_files_lover`, `bad_header_lover`, `bypass_virus_checks`, `bypass_spam_checks`, `bypass_banned_checks`, `bypass_header_checks`, `spam_modifies_subj`, `virus_quarantine_to`, `spam_quarantine_to`, `banned_quarantine_to`, `bad_header_quarantine_to`, `clean_quarantine_to`, `other_quarantine_to`, `spam_tag_level`, `spam_tag2_level`, `spam_kill_level`, `spam_dsn_cutoff_level`, `spam_quarantine_cutoff_level`, `addr_extension_virus`, `addr_extension_spam`, `addr_extension_banned`, `addr_extension_bad_header`, `warnvirusrecip`, `warnbannedrecip`, `warnbadhrecip`, `newvirus_admin`, `virus_admin`, `banned_admin`, `bad_header_admin`, `spam_admin`, `spam_subject_tag`, `spam_subject_tag2`, `message_size_limit`, `banned_rulenames`) VALUES(2, 1, 0, 'riud', 'riud', 'r', 'Uncensored', 'Y', 'Y', 'Y', 'Y', 'N', 'N', 'N', 'N', 'N', NULL, NULL, NULL, NULL, NULL, NULL, 3, 999, 999, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
@@ -2141,34 +2142,34 @@
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Dumping data for table `sys_group`
--- 
+--
 
 INSERT INTO `sys_group` (`groupid`, `name`, `description`, `client_id`) VALUES (1, 'admin', 'Administrators group', 0);
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Dumping data for table `sys_ini`
--- 
+--
 
 INSERT INTO `sys_ini` (`sysini_id`, `config`) VALUES (1, '');
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Dumping data for table `sys_user`
--- 
+--
 
 INSERT INTO `sys_theme` (`var_id`, `tpl_name`, `username`, `logo_url`) VALUES (NULL, 'default', 'global', 'themes/default/images/header_logo.png');
 INSERT INTO `sys_theme` (`var_id`, `tpl_name`, `username`, `logo_url`) VALUES (NULL, 'default-v2', 'global', 'themes/default-v2/images/header_logo.png');
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Dumping data for table `sys_user`
--- 
+--
 
 INSERT INTO `sys_user` (`userid`, `sys_userid`, `sys_groupid`, `sys_perm_user`, `sys_perm_group`, `sys_perm_other`, `username`, `passwort`, `modules`, `startmodule`, `app_theme`, `typ`, `active`, `language`, `groups`, `default_group`, `client_id`) VALUES (1, 1, 0, 'riud', 'riud', '', 'admin', '21232f297a57a5a743894a0e4a801fc3', 'dashboard,admin,client,mail,monitor,sites,dns,vm,tools,help', 'dashboard', 'default', 'admin', 1, 'en', '1,2', 1, 0);
 
@@ -2179,5 +2180,5 @@
 --
 
 INSERT INTO sys_config VALUES ('1','db','db_version','3.0.5.2');
-
+
 SET FOREIGN_KEY_CHECKS = 1;
diff --git a/interface/lib/classes/tform.inc.php b/interface/lib/classes/tform.inc.php
index 23b05ce..d1fd373 100644
--- a/interface/lib/classes/tform.inc.php
+++ b/interface/lib/classes/tform.inc.php
@@ -7,14 +7,14 @@
 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:
 
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright notice,
-      this list of conditions and the following disclaimer in the documentation
-      and/or other materials provided with the distribution.
-    * Neither the name of ISPConfig nor the names of its contributors
-      may be used to endorse or promote products derived from this software without
-      specific prior written permission.
+	* Redistributions of source code must retain the above copyright notice,
+	  this list of conditions and the following disclaimer.
+	* Redistributions in binary form must reproduce the above copyright notice,
+	  this list of conditions and the following disclaimer in the documentation
+	  and/or other materials provided with the distribution.
+	* Neither the name of ISPConfig nor the names of its contributors
+	  may be used to endorse or promote products derived from this software without
+	  specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -60,250 +60,250 @@
 
 class tform {
 
-        /**
-        * Definition of the database table (array)
-        * @var tableDef
-        */
-        var $tableDef;
+		/**
+		* Definition of the database table (array)
+		* @var tableDef
+		*/
+		var $tableDef;
 
-        /**
-        * Private
-        * @var action
-        */
-        var $action;
+		/**
+		* Private
+		* @var action
+		*/
+		var $action;
 
-        /**
-        * Table name (String)
-        * @var table_name
-        */
-        var $table_name;
+		/**
+		* Table name (String)
+		* @var table_name
+		*/
+		var $table_name;
 
-        /**
-        * Debug Variable
-        * @var debug
-        */
-        var $debug = 0;
+		/**
+		* Debug Variable
+		* @var debug
+		*/
+		var $debug = 0;
 
-        /**
-        * name of the primary field of the database table (string)
-        * @var table_index
-        */
-        var $table_index;
+		/**
+		* name of the primary field of the database table (string)
+		* @var table_index
+		*/
+		var $table_index;
 
-        /**
-        * contains the error messages
-        * @var errorMessage
-        */
-        var $errorMessage = '';
+		/**
+		* contains the error messages
+		* @var errorMessage
+		*/
+		var $errorMessage = '';
 
-        var $dateformat = "d.m.Y";
-    	var $formDef = array();
-        var $wordbook;
-        var $module;
-        var $primary_id;
+		var $dateformat = "d.m.Y";
+		var $formDef = array();
+		var $wordbook;
+		var $module;
+		var $primary_id;
 		var $diffrec = array();
 
-        /**
-        * Loading of the table definition
-        *
-        * @param file: path to the form definition file
-        * @return true
-        */
-        /*
-        function loadTableDef($file) {
-                global $app,$conf;
+		/**
+		* Loading of the table definition
+		*
+		* @param file: path to the form definition file
+		* @return true
+		*/
+		/*
+		function loadTableDef($file) {
+				global $app,$conf;
 
-                include_once($file);
-                $this->tableDef = $table;
-                $this->table_name = $table_name;
-                $this->table_index = $table_index;
-                return true;
-        }
-        */
+				include_once($file);
+				$this->tableDef = $table;
+				$this->table_name = $table_name;
+				$this->table_index = $table_index;
+				return true;
+		}
+		*/
 
-    function loadFormDef($file,$module = '') {
-                global $app,$conf;
+	function loadFormDef($file,$module = '') {
+				global $app,$conf;
 
-                include($file);
-                $this->formDef = $form;
+				include($file);
+				$this->formDef = $form;
 
-                $this->module = $module;
+				$this->module = $module;
 				$wb = array();
-				
+
 				include_once(ISPC_ROOT_PATH.'/lib/lang/'.$_SESSION['s']['language'].'.lng');
-				
+
 				if(is_array($wb)) $wb_global = $wb;
-				
-                if($module == '') {
+
+				if($module == '') {
 					$lng_file = "lib/lang/".$_SESSION["s"]["language"]."_".$this->formDef["name"].".lng";
 					if(!file_exists($lng_file)) $lng_file = "lib/lang/en_".$this->formDef["name"].".lng";
 					include($lng_file);
-                } else {
+				} else {
 					$lng_file = "../$module/lib/lang/".$_SESSION["s"]["language"]."_".$this->formDef["name"].".lng";
 					if(!file_exists($lng_file)) $lng_file = "../$module/lib/lang/en_".$this->formDef["name"].".lng";
 					include($lng_file);
-                }
+				}
 
 				if(is_array($wb_global)) {
 					$wb = $app->functions->array_merge($wb_global,$wb);
 				}
 				if(isset($wb_global)) unset($wb_global);
-				
-                $this->wordbook = $wb;
-				
+
+				$this->wordbook = $wb;
+
 				$this->dateformat = $app->lng('conf_format_dateshort');
 
-                return true;
-        }
+				return true;
+		}
 
 
-        /**
-        * Converts the data in the array to human readable format
-        * Datatype conversion e.g. to show the data in lists
-        *
-        * @param record
-        * @return record
-        */
-        function decode($record,$tab) {
-                global $conf, $app;
+		/**
+		* Converts the data in the array to human readable format
+		* Datatype conversion e.g. to show the data in lists
+		*
+		* @param record
+		* @return record
+		*/
+		function decode($record,$tab) {
+				global $conf, $app;
 				if(!is_array($this->formDef['tabs'][$tab])) $app->error("Tab does not exist or the tab is empty (TAB: $tab).");
-                $new_record = '';
+				$new_record = '';
 				$table_idx = $this->formDef['db_table_idx'];
 				if(isset($record[$table_idx])) $new_record[$table_idx] = $app->functions->intval($record[$table_idx ]);
-				
+
 				if(is_array($record)) {
 						foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
-                                
+
 								//* Apply filter to record value.
 								if(isset($field['filters']) && is_array($field['filters'])) {
 									$record[$key] = $this->filterField($key, (isset($record[$key]))?$record[$key]:'', $field['filters'], 'SHOW');
 								}
-								
+
 								switch ($field['datatype']) {
-                                case 'VARCHAR':
-                                        $new_record[$key] = $record[$key];
-                                break;
+								case 'VARCHAR':
+										$new_record[$key] = $record[$key];
+								break;
 
-                                case 'TEXT':
-                                        $new_record[$key] = $record[$key];
-                                break;
+								case 'TEXT':
+										$new_record[$key] = $record[$key];
+								break;
 
-                                case 'DATETSTAMP':
-                                        if($record[$key] > 0) {
-                                                $new_record[$key] = date($this->dateformat,$record[$key]);
-                                        }
-                                break;
-								
+								case 'DATETSTAMP':
+										if($record[$key] > 0) {
+												$new_record[$key] = date($this->dateformat,$record[$key]);
+										}
+								break;
+
 								case 'DATE':
-                                        if($record[$key] != '' && $record[$key] != '0000-00-00') {
+										if($record[$key] != '' && $record[$key] != '0000-00-00') {
 												$tmp = explode('-',$record[$key]);
-                                                $new_record[$key] = date($this->dateformat,mktime(0, 0, 0, $tmp[1]  , $tmp[2], $tmp[0]));
-                                        }
-                                break;
+												$new_record[$key] = date($this->dateformat,mktime(0, 0, 0, $tmp[1]  , $tmp[2], $tmp[0]));
+										}
+								break;
 
-                                case 'INTEGER':
-                                        $new_record[$key] = $app->functions->intval($record[$key]);
-                                break;
+								case 'INTEGER':
+										$new_record[$key] = $app->functions->intval($record[$key]);
+								break;
 
-                                case 'DOUBLE':
-                                        $new_record[$key] = $record[$key];
-                                break;
+								case 'DOUBLE':
+										$new_record[$key] = $record[$key];
+								break;
 
-                                case 'CURRENCY':
-                                        $new_record[$key] = $app->functions->currency_format($record[$key]);
-                                break;
+								case 'CURRENCY':
+										$new_record[$key] = $app->functions->currency_format($record[$key]);
+								break;
 
-                                default:
-                                        $new_record[$key] = $record[$key];
-                                }
-                        }
+								default:
+										$new_record[$key] = $record[$key];
+								}
+						}
 
-                }
-				
-        return $new_record;
-        }
+				}
 
-        /**
-        * Get the key => value array of a form filled from a datasource definitiom
-        *
-        * @param field = array with field definition
-        * @param record = Dataset as array
-        * @return key => value array for the value field of a form
-        */
+		return $new_record;
+		}
 
-        function getDatasourceData($field, $record) {
-                global $app;
+		/**
+		* Get the key => value array of a form filled from a datasource definitiom
+		*
+		* @param field = array with field definition
+		* @param record = Dataset as array
+		* @return key => value array for the value field of a form
+		*/
 
-                $values = array();
+		function getDatasourceData($field, $record) {
+				global $app;
 
-                if($field["datasource"]["type"] == 'SQL') {
+				$values = array();
 
-                        // Preparing SQL string. We will replace some
-                        // common placeholders
-                        $querystring = $field["datasource"]["querystring"];
-                        $querystring = str_replace("{USERID}",$_SESSION["s"]["user"]["userid"],$querystring);
-                        $querystring = str_replace("{GROUPID}",$_SESSION["s"]["user"]["default_group"],$querystring);
-                        $querystring = str_replace("{GROUPS}",$_SESSION["s"]["user"]["groups"],$querystring);
-                        $table_idx = $this->formDef['db_table_idx'];
-						
+				if($field["datasource"]["type"] == 'SQL') {
+
+						// Preparing SQL string. We will replace some
+						// common placeholders
+						$querystring = $field["datasource"]["querystring"];
+						$querystring = str_replace("{USERID}",$_SESSION["s"]["user"]["userid"],$querystring);
+						$querystring = str_replace("{GROUPID}",$_SESSION["s"]["user"]["default_group"],$querystring);
+						$querystring = str_replace("{GROUPS}",$_SESSION["s"]["user"]["groups"],$querystring);
+						$table_idx = $this->formDef['db_table_idx'];
+
 						$tmp_recordid = (isset($record[$table_idx]))?$record[$table_idx]:0;
-                        $querystring = str_replace("{RECORDID}",$tmp_recordid,$querystring);
+						$querystring = str_replace("{RECORDID}",$tmp_recordid,$querystring);
 						unset($tmp_recordid);
-						
-                        $querystring = str_replace("{AUTHSQL}",$this->getAuthSQL('r'),$querystring);
-						
-                        // Getting the records
-                        $tmp_records = $app->db->queryAllRecords($querystring);
-                        if($app->db->errorMessage != '') die($app->db->errorMessage);
-                        if(is_array($tmp_records)) {
-                                $key_field = $field["datasource"]["keyfield"];
-                                $value_field = $field["datasource"]["valuefield"];
-                                foreach($tmp_records as $tmp_rec) {
-                                        $tmp_id = $tmp_rec[$key_field];
-                                        $values[$tmp_id] = $tmp_rec[$value_field];
-                                }
-                        }
-                }
 
-                if($field["datasource"]["type"] == 'CUSTOM') {
-                        // Calls a custom class to validate this record
-                        if($field["datasource"]['class'] != '' and $field["datasource"]['function'] != '') {
-                                $datasource_class = $field["datasource"]['class'];
-                                $datasource_function = $field["datasource"]['function'];
-                                $app->uses($datasource_class);
-                                $values = $app->$datasource_class->$datasource_function($field, $record);
-                        } else {
-                                $this->errorMessage .= "Custom datasource class or function is empty<br />\r\n";
-                        }
-                }
-                
-                if(isset($field['filters']) && is_array($field['filters'])) {
-                    $new_values = array();
-                    foreach($values as $index => $value) {
-                        $new_index = $this->filterField($index, $index, $field['filters'], 'SHOW');
-                        $new_values[$new_index] = $this->filterField($index, (isset($values[$index]))?$values[$index]:'', $field['filters'], 'SHOW');
-                    }
-                    $values = $new_values;
-                    unset($new_values);
-                    unset($new_index);
-                }
+						$querystring = str_replace("{AUTHSQL}",$this->getAuthSQL('r'),$querystring);
 
-                return $values;
+						// Getting the records
+						$tmp_records = $app->db->queryAllRecords($querystring);
+						if($app->db->errorMessage != '') die($app->db->errorMessage);
+						if(is_array($tmp_records)) {
+								$key_field = $field["datasource"]["keyfield"];
+								$value_field = $field["datasource"]["valuefield"];
+								foreach($tmp_records as $tmp_rec) {
+										$tmp_id = $tmp_rec[$key_field];
+										$values[$tmp_id] = $tmp_rec[$value_field];
+								}
+						}
+				}
 
-        }
-		
+				if($field["datasource"]["type"] == 'CUSTOM') {
+						// Calls a custom class to validate this record
+						if($field["datasource"]['class'] != '' and $field["datasource"]['function'] != '') {
+								$datasource_class = $field["datasource"]['class'];
+								$datasource_function = $field["datasource"]['function'];
+								$app->uses($datasource_class);
+								$values = $app->$datasource_class->$datasource_function($field, $record);
+						} else {
+								$this->errorMessage .= "Custom datasource class or function is empty<br />\r\n";
+						}
+				}
+
+				if(isset($field['filters']) && is_array($field['filters'])) {
+					$new_values = array();
+					foreach($values as $index => $value) {
+						$new_index = $this->filterField($index, $index, $field['filters'], 'SHOW');
+						$new_values[$new_index] = $this->filterField($index, (isset($values[$index]))?$values[$index]:'', $field['filters'], 'SHOW');
+					}
+					$values = $new_values;
+					unset($new_values);
+					unset($new_index);
+				}
+
+				return $values;
+
+		}
+
 		//* If the parameter 'valuelimit' is set
 		function applyValueLimit($limit,$values) {
-			
+
 			global $app;
-			
+
 			$limit_parts = explode(':',$limit);
-			
+
 			//* values are limited to a comma separated list
 			if($limit_parts[0] == 'list') {
 				$allowed = explode(',',$limit_parts[1]);
 			}
-			
+
 			//* values are limited to a field in the client settings
 			if($limit_parts[0] == 'client') {
 				if($_SESSION["s"]["user"]["typ"] == 'admin') {
@@ -314,7 +314,7 @@
 					$allowed = explode(',',$client['lm']);
 				}
 			}
-			
+
 			//* values are limited to a field in the reseller settings
 			if($limit_parts[0] == 'reseller') {
 				if($_SESSION["s"]["user"]["typ"] == 'admin') {
@@ -326,12 +326,12 @@
 					//echo "SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id";
 					//* If the client belongs to a reseller, we will check against the reseller Limit too
 					if($client['parent_client_id'] != 0) {
-				
+
 						//* first we need to know the groups of this reseller
 						$tmp = $app->db->queryOneRecord("SELECT userid, groups FROM sys_user WHERE client_id = ".$client['parent_client_id']);
 						$reseller_groups = $tmp["groups"];
 						$reseller_userid = $tmp["userid"];
-				
+
 						// Get the limits of the reseller of the logged in client
 						$client_group_id = $_SESSION["s"]["user"]["default_group"];
 						$reseller = $app->db->queryOneRecord("SELECT ".$limit_parts[1]." as lm FROM client WHERE client_id = ".$client['parent_client_id']);
@@ -341,7 +341,7 @@
 					}
 				} // end if admin
 			} // end if reseller
-			
+
 			//* values are limited to a field in the system settings
 			if($limit_parts[0] == 'system') {
 				$app->uses('getconf');
@@ -349,295 +349,295 @@
 				$tmp_key = $limit_parts[2];
 				$allowed = $tmp_conf[$tmp_key];
 			}
-			
+
 			$values_new = array();
 			foreach($values as $key => $val) {
 				if(in_array($key,$allowed)) $values_new[$key] = $val;
 			}
-			
+
 			return $values_new;
 		}
 
 
-        /**
-        * Prepare the data record to show the data in a form.
-        *
-        * @param record = Datensatz als Array
-        * @param action = NEW oder EDIT
-        * @return record
-        */
-        function getHTML($record, $tab, $action = 'NEW') {
+		/**
+		* Prepare the data record to show the data in a form.
+		*
+		* @param record = Datensatz als Array
+		* @param action = NEW oder EDIT
+		* @return record
+		*/
+		function getHTML($record, $tab, $action = 'NEW') {
 
-                global $app;
+				global $app;
 
-                $this->action = $action;
+				$this->action = $action;
 
-                if(!is_array($this->formDef)) $app->error("No form definition found.");
-                if(!is_array($this->formDef['tabs'][$tab])) $app->error("The tab is empty or does not exist (TAB: $tab).");
+				if(!is_array($this->formDef)) $app->error("No form definition found.");
+				if(!is_array($this->formDef['tabs'][$tab])) $app->error("The tab is empty or does not exist (TAB: $tab).");
 
-                $new_record = array();
-                if($action == 'EDIT') {
-                        $record = $this->decode($record,$tab);
-                        if(is_array($record)) {
-                                foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
-								
-                                        if(isset($record[$key])) {
+				$new_record = array();
+				if($action == 'EDIT') {
+						$record = $this->decode($record,$tab);
+						if(is_array($record)) {
+								foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
+
+										if(isset($record[$key])) {
 											$val = $record[$key];
 										} else {
 											$val = '';
 										}
 
-                                        // If Datasource is set, get the data from there
-                                        if(isset($field['datasource']) && is_array($field['datasource'])) {
+										// If Datasource is set, get the data from there
+										if(isset($field['datasource']) && is_array($field['datasource'])) {
 												if(is_array($field["value"])) {
 													//$field["value"] = array_merge($field["value"],$this->getDatasourceData($field, $record));
 													$field["value"] = $app->functions->array_merge($field["value"],$this->getDatasourceData($field, $record));
 												} else {
-                                                	$field["value"] = $this->getDatasourceData($field, $record);
+													$field["value"] = $this->getDatasourceData($field, $record);
 												}
-                                        }
-										
+										}
+
 										// If a limitation for the values is set
 										if(isset($field['valuelimit']) && is_array($field["value"])) {
 											$field["value"] = $this->applyValueLimit($field['valuelimit'],$field["value"]);
 										}
 
-                                        switch ($field['formtype']) {
-                                        case 'SELECT':
+										switch ($field['formtype']) {
+										case 'SELECT':
 												$out = '';
-                                                if(is_array($field['value'])) {
-                                                        foreach($field['value'] as $k => $v) {
-                                                                $selected = ($k == $val)?' SELECTED':'';
+												if(is_array($field['value'])) {
+														foreach($field['value'] as $k => $v) {
+																$selected = ($k == $val)?' SELECTED':'';
 																if(!empty($this->wordbook[$v]))
 																	$v = $this->wordbook[$v];
-                                                                $out .= "<option value='$k'$selected>".$this->lng($v)."</option>\r\n";
-                                                        }
-                                                }
-                                                $new_record[$key] = $out;
-                                        break;
-                                        case 'MULTIPLE':
-                                                if(is_array($field['value'])) {
+																$out .= "<option value='$k'$selected>".$this->lng($v)."</option>\r\n";
+														}
+												}
+												$new_record[$key] = $out;
+										break;
+										case 'MULTIPLE':
+												if(is_array($field['value'])) {
 
-                                                        // Split
-                                                        $vals = explode($field['separator'],$val);
+														// Split
+														$vals = explode($field['separator'],$val);
 
-                                                        // write HTML
-                                                        $out = '';
-                                                        foreach($field['value'] as $k => $v) {
+														// write HTML
+														$out = '';
+														foreach($field['value'] as $k => $v) {
 
-                                                                $selected = '';
-                                                                foreach($vals as $tvl) {
-                                                                        if(trim($tvl) == trim($k)) $selected = ' SELECTED';
-                                                                }
+																$selected = '';
+																foreach($vals as $tvl) {
+																		if(trim($tvl) == trim($k)) $selected = ' SELECTED';
+																}
 
-                                                                $out .= "<option value='$k'$selected>$v</option>\r\n";
-                                                        }
-                                                }
-                                                $new_record[$key] = $out;
-                                        break;
+																$out .= "<option value='$k'$selected>$v</option>\r\n";
+														}
+												}
+												$new_record[$key] = $out;
+										break;
 
-                                        case 'PASSWORD':
-                                                $new_record[$key] = '';
-                                        break;
+										case 'PASSWORD':
+												$new_record[$key] = '';
+										break;
 
-                                        case 'CHECKBOX':
-                                                $checked = ($val == $field['value'][1])?' CHECKED':'';
-                                                $new_record[$key] = "<input name=\"".$key."\" id=\"".$key."\" value=\"".$field['value'][1]."\" type=\"checkbox\" $checked />\r\n";
-                                        break;
+										case 'CHECKBOX':
+												$checked = ($val == $field['value'][1])?' CHECKED':'';
+												$new_record[$key] = "<input name=\"".$key."\" id=\"".$key."\" value=\"".$field['value'][1]."\" type=\"checkbox\" $checked />\r\n";
+										break;
 
-                                        case 'CHECKBOXARRAY':
-                                                if(is_array($field['value'])) {
+										case 'CHECKBOXARRAY':
+												if(is_array($field['value'])) {
 
-                                                        // aufsplitten ergebnisse
-                                                        $vals = explode($field['separator'],$val);
+														// aufsplitten ergebnisse
+														$vals = explode($field['separator'],$val);
 
-                                                        // HTML schreiben
-                                                        $out = '';
-                                                        $elementNo = 0;
-                                                        foreach($field['value'] as $k => $v) {
+														// HTML schreiben
+														$out = '';
+														$elementNo = 0;
+														foreach($field['value'] as $k => $v) {
 
-                                                                $checked = '';
-                                                                foreach($vals as $tvl) {
-                                                                        if(trim($tvl) == trim($k)) $checked = ' CHECKED';
-                                                                }
-                                                                // $out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"checkbox\" $checked /> $v</label>\r\n";
+																$checked = '';
+																foreach($vals as $tvl) {
+																		if(trim($tvl) == trim($k)) $checked = ' CHECKED';
+																}
+																// $out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"checkbox\" $checked /> $v</label>\r\n";
 																$out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"checkbox\" $checked /> $v</label><br/>\r\n";
-                                                                $elementNo++;
-                                                        }
-                                                }
-                                                $new_record[$key] = $out;
-                                        break;
+																$elementNo++;
+														}
+												}
+												$new_record[$key] = $out;
+										break;
 
-                                        case 'RADIO':
-                                                if(is_array($field['value'])) {
+										case 'RADIO':
+												if(is_array($field['value'])) {
 
-                                                        // HTML schreiben
-                                                        $out = '';
-                                                        $elementNo = 0;
-                                                        foreach($field['value'] as $k => $v) {
-                                                                $checked = ($k == $val)?' CHECKED':'';
-                                                                //$out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"radio\" $checked/> $v</label>\r\n";
+														// HTML schreiben
+														$out = '';
+														$elementNo = 0;
+														foreach($field['value'] as $k => $v) {
+																$checked = ($k == $val)?' CHECKED':'';
+																//$out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"radio\" $checked/> $v</label>\r\n";
 																$out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"radio\" $checked/> $v </label>\r\n";
-                                                                $elementNo++;
-                                                        }
-                                                }
-                                                $new_record[$key] = $out;
-                                        break;
-                                        
-                                        case 'DATETIME':
-                                        		if (strtotime($val) !== false) {
-                                        			$dt_value = $val;
-                                        		} elseif ( isset($field['default']) && (strtotime($field['default']) !== false) ) {
-                                        			$dt_value = $field['default'];
-                                        		} else {
-                                        			$dt_value = 0;
-                                        		}
-                                        		
-                                        		$display_seconds = (isset($field['display_seconds']) && $field['display_seconds'] == true) ? true : false;
-		                              
-		                                        $new_record[$key] = $this->_getDateTimeHTML($key, $dt_value, $display_seconds);
-                                        break;
+																$elementNo++;
+														}
+												}
+												$new_record[$key] = $out;
+										break;
 
-                                        default:
+										case 'DATETIME':
+												if (strtotime($val) !== false) {
+													$dt_value = $val;
+												} elseif ( isset($field['default']) && (strtotime($field['default']) !== false) ) {
+													$dt_value = $field['default'];
+												} else {
+													$dt_value = 0;
+												}
+
+												$display_seconds = (isset($field['display_seconds']) && $field['display_seconds'] == true) ? true : false;
+
+												$new_record[$key] = $this->_getDateTimeHTML($key, $dt_value, $display_seconds);
+										break;
+
+										default:
 											if(isset($record[$key])) {
-                                                $new_record[$key] = htmlspecialchars($record[$key]);
+												$new_record[$key] = htmlspecialchars($record[$key]);
 											} else {
 												$new_record[$key] = '';
 											}
-                                        }
-                                }
-                        }
-                } else {
-                        // Action: NEW
-                        foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
+										}
+								}
+						}
+				} else {
+						// Action: NEW
+						foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
 
-                                // If Datasource is set, get the data from there
-                                if(@is_array($field['datasource'])) {
-                                	if(is_array($field["value"])) {
+								// If Datasource is set, get the data from there
+								if(@is_array($field['datasource'])) {
+									if(is_array($field["value"])) {
 										$field["value"] = $app->functions->array_merge($field["value"],$this->getDatasourceData($field, $record));
 									} else {
-                                    	$field["value"] = $this->getDatasourceData($field, $record);
+										$field["value"] = $this->getDatasourceData($field, $record);
 									}
-                                }
-								
+								}
+
 								// If a limitation for the values is set
 								if(isset($field['valuelimit']) && is_array($field["value"])) {
 									$field["value"] = $this->applyValueLimit($field['valuelimit'],$field["value"]);
 								}
 
-                                switch ($field['formtype']) {
-                                case 'SELECT':
-                                        if(is_array($field['value'])) {
-                                                $out = '';
-                                                foreach($field['value'] as $k => $v) {
-                                                    $selected = ($k == $field["default"])?' SELECTED':'';
-                                                    $out .= "<option value='$k'$selected>".$this->lng($v)."</option>\r\n";
-                                                }
-                                        }
-                                        if(isset($out)) $new_record[$key] = $out;
-                                break;
-                                case 'MULTIPLE':
-                                                if(is_array($field['value'])) {
+								switch ($field['formtype']) {
+								case 'SELECT':
+										if(is_array($field['value'])) {
+												$out = '';
+												foreach($field['value'] as $k => $v) {
+													$selected = ($k == $field["default"])?' SELECTED':'';
+													$out .= "<option value='$k'$selected>".$this->lng($v)."</option>\r\n";
+												}
+										}
+										if(isset($out)) $new_record[$key] = $out;
+								break;
+								case 'MULTIPLE':
+												if(is_array($field['value'])) {
 
-                                                        // aufsplitten ergebnisse
-                                                        $vals = explode($field['separator'],$val);
+														// aufsplitten ergebnisse
+														$vals = explode($field['separator'],$val);
 
-                                                        // HTML schreiben
-                                                        $out = '';
-                                                        foreach($field['value'] as $k => $v) {
+														// HTML schreiben
+														$out = '';
+														foreach($field['value'] as $k => $v) {
 
-                                                                $out .= "<option value='$k'>$v</option>\r\n";
-                                                        }
-                                                }
-                                                $new_record[$key] = $out;
-                                        break;
+																$out .= "<option value='$k'>$v</option>\r\n";
+														}
+												}
+												$new_record[$key] = $out;
+										break;
 
-                                case 'PASSWORD':
-                                        $new_record[$key] = '';
-                                break;
+								case 'PASSWORD':
+										$new_record[$key] = '';
+								break;
 
-                                case 'CHECKBOX':
-                                        // $checked = (empty($field["default"]))?'':' CHECKED';
-										                    $checked = ($field["default"] == $field['value'][1])?' CHECKED':'';
-                                        $new_record[$key] = "<input name=\"".$key."\" id=\"".$key."\" value=\"".$field['value'][1]."\" type=\"checkbox\" $checked />\r\n"; 
-                                break;
+								case 'CHECKBOX':
+										// $checked = (empty($field["default"]))?'':' CHECKED';
+															$checked = ($field["default"] == $field['value'][1])?' CHECKED':'';
+										$new_record[$key] = "<input name=\"".$key."\" id=\"".$key."\" value=\"".$field['value'][1]."\" type=\"checkbox\" $checked />\r\n";
+								break;
 
-                                case 'CHECKBOXARRAY':
-                                        if(is_array($field['value'])) {
+								case 'CHECKBOXARRAY':
+										if(is_array($field['value'])) {
 
-                                                // aufsplitten ergebnisse
-                                                $vals = explode($field['separator'],$field["default"]);
+												// aufsplitten ergebnisse
+												$vals = explode($field['separator'],$field["default"]);
 
-                                                // HTML schreiben
-                                                $out = '';
-                                                $elementNo = 0;
-                                                foreach($field['value'] as $k => $v) {
+												// HTML schreiben
+												$out = '';
+												$elementNo = 0;
+												foreach($field['value'] as $k => $v) {
 
-                                                        $checked = '';
-                                                        foreach($vals as $tvl) {
-                                                                if(trim($tvl) == trim($k)) $checked = ' CHECKED';
-                                                        }
-                                                        // $out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"checkbox\" $checked /> $v</label>\r\n";
+														$checked = '';
+														foreach($vals as $tvl) {
+																if(trim($tvl) == trim($k)) $checked = ' CHECKED';
+														}
+														// $out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"checkbox\" $checked /> $v</label>\r\n";
 														$out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"checkbox\" $checked /> $v</label> &nbsp;\r\n";
-                                                        $elementNo++;
-                                                }
-                                        }
-                                        $new_record[$key] = $out;
-                                break;
+														$elementNo++;
+												}
+										}
+										$new_record[$key] = $out;
+								break;
 
-                                case 'RADIO':
-                                        if(is_array($field['value'])) {
+								case 'RADIO':
+										if(is_array($field['value'])) {
 
-                                                // HTML schreiben
-                                                $out = '';
-                                                $elementNo = 0;
-                                                foreach($field['value'] as $k => $v) {
-                                                        $checked = ($k == $field["default"])?' CHECKED':'';
-                                                        //$out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"radio\" $checked/> $v</label>\r\n";
+												// HTML schreiben
+												$out = '';
+												$elementNo = 0;
+												foreach($field['value'] as $k => $v) {
+														$checked = ($k == $field["default"])?' CHECKED':'';
+														//$out .= "<label for=\"".$key."[]\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key."[]\" value=\"$k\" type=\"radio\" $checked/> $v</label>\r\n";
 														$out .= "<label for=\"".$key.$elementNo."\" class=\"inlineLabel\"><input name=\"".$key."[]\" id=\"".$key.$elementNo."\" value=\"$k\" type=\"radio\" $checked/> $v</label>\r\n";
-                                                        $elementNo++;
-                                                }
-                                        }
-                                        $new_record[$key] = $out;
-                                break;
-                                
-                                case 'DATETIME':
-                                        $dt_value = (isset($field['default'])) ? $field['default'] : 0;
-                                        $display_seconds = (isset($field['display_seconds']) && $field['display_seconds'] == true) ? true : false;
-                              
-                                        $new_record[$key] = $this->_getDateTimeHTML($key, $dt_value, $display_seconds);
-                                break;
+														$elementNo++;
+												}
+										}
+										$new_record[$key] = $out;
+								break;
 
-                                default:
-                                        $new_record[$key] = htmlspecialchars($field['default']);
-                                }
-                        }
+								case 'DATETIME':
+										$dt_value = (isset($field['default'])) ? $field['default'] : 0;
+										$display_seconds = (isset($field['display_seconds']) && $field['display_seconds'] == true) ? true : false;
 
-                }
+										$new_record[$key] = $this->_getDateTimeHTML($key, $dt_value, $display_seconds);
+								break;
 
-                if($this->debug == 1) $this->dbg($new_record);
+								default:
+										$new_record[$key] = htmlspecialchars($field['default']);
+								}
+						}
 
-                return $new_record;
-        }
+				}
 
-        /**
-        * Rewrite the record data to be stored in the database
-        * and check values with regular expressions.
-        *
-        * @param record = Datensatz als Array
-        * @return record
-        */
-        function encode($record,$tab,$dbencode = true) {
+				if($this->debug == 1) $this->dbg($new_record);
+
+				return $new_record;
+		}
+
+		/**
+		* Rewrite the record data to be stored in the database
+		* and check values with regular expressions.
+		*
+		* @param record = Datensatz als Array
+		* @return record
+		*/
+		function encode($record,$tab,$dbencode = true) {
 			global $app;
-			
-                if(!is_array($this->formDef['tabs'][$tab])) $app->error("Tab is empty or does not exist (TAB: $tab).");
-                //$this->errorMessage = '';
 
-                if(is_array($record)) {
-                        foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
-								
+				if(!is_array($this->formDef['tabs'][$tab])) $app->error("Tab is empty or does not exist (TAB: $tab).");
+				//$this->errorMessage = '';
+
+				if(is_array($record)) {
+						foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
+
 								//* Apply filter to record value
-                                if(isset($field['filters']) && is_array($field['filters'])) {
+								if(isset($field['filters']) && is_array($field['filters'])) {
 									$record[$key] = $this->filterField($key, (isset($record[$key]))?$record[$key]:'', $field['filters'], 'SAVE');
 								}
 								//* Validate record value
@@ -645,31 +645,31 @@
 									$this->validateField($key, (isset($record[$key]))?$record[$key]:'', $field['validators']);
 								}
 
-                                switch ($field['datatype']) {
-                                case 'VARCHAR':
-                                        if(!@is_array($record[$key])) {
+								switch ($field['datatype']) {
+								case 'VARCHAR':
+										if(!@is_array($record[$key])) {
 												$new_record[$key] = (isset($record[$key]))?$record[$key]:'';
-                                        } else {
-                                                $new_record[$key] = implode($field['separator'],$record[$key]);
-                                        }
-                                break;
-                                case 'TEXT':
-                                        if(!is_array($record[$key])) {
-                                                $new_record[$key] = $record[$key];
-                                        } else {
-                                                $new_record[$key] = implode($field['separator'],$record[$key]);
-                                        }
-                                break;
-                                case 'DATETSTAMP':
-                                        if($record[$key] > 0) {
-                                                list($tag,$monat,$jahr) = explode('.',$record[$key]);
-                                                $new_record[$key] = mktime(0,0,0,$monat,$tag,$jahr);
-                                        } else {
+										} else {
+												$new_record[$key] = implode($field['separator'],$record[$key]);
+										}
+								break;
+								case 'TEXT':
+										if(!is_array($record[$key])) {
+												$new_record[$key] = $record[$key];
+										} else {
+												$new_record[$key] = implode($field['separator'],$record[$key]);
+										}
+								break;
+								case 'DATETSTAMP':
+										if($record[$key] > 0) {
+												list($tag,$monat,$jahr) = explode('.',$record[$key]);
+												$new_record[$key] = mktime(0,0,0,$monat,$tag,$jahr);
+										} else {
 											$new_record[$key] = 0;
 										}
-                                break;
+								break;
 								case 'DATE':
-                                        if($record[$key] != '' && $record[$key] != '0000-00-00') {
+										if($record[$key] != '' && $record[$key] != '0000-00-00') {
 												if(function_exists('date_parse_from_format')) {
 													$date_parts = date_parse_from_format($this->dateformat,$record[$key]);
 													//list($tag,$monat,$jahr) = explode('.',$record[$key]);
@@ -682,67 +682,67 @@
 													$tmp = strtotime($record[$key]);
 													$new_record[$key] = date('Y-m-d',$tmp);
 												}
-                                        } else {
+										} else {
 											$new_record[$key] = '0000-00-00';
 										}
-                                break;
-                                case 'INTEGER':
+								break;
+								case 'INTEGER':
 										$new_record[$key] = (isset($record[$key]))?$app->functions->intval($record[$key]):0;
-                                        //if($new_record[$key] != $record[$key]) $new_record[$key] = $field['default'];
-                                        //if($key == 'refresh') die($record[$key]);
-                                break;
-                                case 'DOUBLE':
-                                        $new_record[$key] = $record[$key];
-                                break;
-                                case 'CURRENCY':
-                                        $new_record[$key] = str_replace(",",".",$record[$key]);
-                                break;
-                                
-                                case 'DATETIME':
-                                		if (is_array($record[$key]))
-                                		{
-	                                		$filtered_values = array_map(create_function('$item','return (int)$item;'), $record[$key]);
-                                			extract($filtered_values, EXTR_PREFIX_ALL, '_dt');
-                                			
-                                			if ($_dt_day != 0 && $_dt_month != 0 && $_dt_year != 0) {
-	                                			$new_record[$key] = date( 'Y-m-d H:i:s', mktime($_dt_hour, $_dt_minute, $_dt_second, $_dt_month, $_dt_day, $_dt_year) );
-	                                		}
-                                		}
-                                break;
-                                }
+										//if($new_record[$key] != $record[$key]) $new_record[$key] = $field['default'];
+										//if($key == 'refresh') die($record[$key]);
+								break;
+								case 'DOUBLE':
+										$new_record[$key] = $record[$key];
+								break;
+								case 'CURRENCY':
+										$new_record[$key] = str_replace(",",".",$record[$key]);
+								break;
 
-                                // The use of the field value is deprecated, use validators instead
-                                if(isset($field['regex']) && $field['regex'] != '') {
-                                        // Enable that "." matches also newlines
-                                        $field['regex'] .= 's';
-                                        if(!preg_match($field['regex'], $record[$key])) {
-                                                $errmsg = $field['errmsg'];
-                                                $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
-                                        }
-                                }
-								
+								case 'DATETIME':
+										if (is_array($record[$key]))
+										{
+											$filtered_values = array_map(create_function('$item','return (int)$item;'), $record[$key]);
+											extract($filtered_values, EXTR_PREFIX_ALL, '_dt');
+
+											if ($_dt_day != 0 && $_dt_month != 0 && $_dt_year != 0) {
+												$new_record[$key] = date( 'Y-m-d H:i:s', mktime($_dt_hour, $_dt_minute, $_dt_second, $_dt_month, $_dt_day, $_dt_year) );
+											}
+										}
+								break;
+								}
+
+								// The use of the field value is deprecated, use validators instead
+								if(isset($field['regex']) && $field['regex'] != '') {
+										// Enable that "." matches also newlines
+										$field['regex'] .= 's';
+										if(!preg_match($field['regex'], $record[$key])) {
+												$errmsg = $field['errmsg'];
+												$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
+										}
+								}
+
 								//* Add slashes to all records, when we encode data which shall be inserted into mysql.
 								if($dbencode == true) $new_record[$key] = $app->db->quote($new_record[$key]);
-                        }
-                }
-                return $new_record;
-        }
-		
-		/**
-        * process the filters for a given field.
-        *
-        * @param field_name = Name of the field
-        * @param field_value = value of the field
-        * @param filters = Array of filters
-		* @param filter_event = 'SAVE'or 'SHOW'
-        * @return record
-        */
+						}
+				}
+				return $new_record;
+		}
 
-        function filterField($field_name, $field_value, $filters, $filter_event) {
+		/**
+		* process the filters for a given field.
+		*
+		* @param field_name = Name of the field
+		* @param field_value = value of the field
+		* @param filters = Array of filters
+		* @param filter_event = 'SAVE'or 'SHOW'
+		* @return record
+		*/
+
+		function filterField($field_name, $field_value, $filters, $filter_event) {
 
 			global $app;
 			$returnval = $field_value;
-				
+
 			//* Loop trough all filters
 			foreach($filters as $filter) {
 				if($filter['event'] == $filter_event) {
@@ -765,157 +765,157 @@
 					}
 				}
 			}
-            return $returnval;
-        }
+			return $returnval;
+		}
 
-        /**
-        * process the validators for a given field.
-        *
-        * @param field_name = Name of the field
-        * @param field_value = value of the field
-        * @param validatoors = Array of validators
-        * @return record
-        */
+		/**
+		* process the validators for a given field.
+		*
+		* @param field_name = Name of the field
+		* @param field_value = value of the field
+		* @param validatoors = Array of validators
+		* @return record
+		*/
 
-        function validateField($field_name, $field_value, $validators) {
+		function validateField($field_name, $field_value, $validators) {
 
-                global $app;
-				
+				global $app;
+
 				$escape = '`';
-				
-                // loop trough the validators
-                foreach($validators as $validator) {
 
-                        switch ($validator['type']) {
-                                case 'REGEX':
-                                        $validator['regex'] .= 's';
-                                        if(!preg_match($validator['regex'], $field_value)) {
-                                                $errmsg = $validator['errmsg'];
-                                                if(isset($this->wordbook[$errmsg])) {
-                                                	$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
+				// loop trough the validators
+				foreach($validators as $validator) {
+
+						switch ($validator['type']) {
+								case 'REGEX':
+										$validator['regex'] .= 's';
+										if(!preg_match($validator['regex'], $field_value)) {
+												$errmsg = $validator['errmsg'];
+												if(isset($this->wordbook[$errmsg])) {
+													$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
 												} else {
 													$this->errorMessage .= $errmsg."<br />\r\n";
 												}
-                                        }
-                                break;
-                                case 'UNIQUE':
+										}
+								break;
+								case 'UNIQUE':
 										if($validator['allowempty'] != 'y') $validator['allowempty'] = 'n';
 										if($validator['allowempty'] == 'n' || ($validator['allowempty'] == 'y' && $field_value != '')){
 											if($this->action == 'NEW') {
-                                                $num_rec = $app->db->queryOneRecord("SELECT count(*) as number FROM ".$escape.$this->formDef['db_table'].$escape. " WHERE $field_name = '".$app->db->quote($field_value)."'");
-                                                if($num_rec["number"] > 0) {
-                                                        $errmsg = $validator['errmsg'];
+												$num_rec = $app->db->queryOneRecord("SELECT count(*) as number FROM ".$escape.$this->formDef['db_table'].$escape. " WHERE $field_name = '".$app->db->quote($field_value)."'");
+												if($num_rec["number"] > 0) {
+														$errmsg = $validator['errmsg'];
 														if(isset($this->wordbook[$errmsg])) {
-                                                        	$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
+															$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
 														} else {
 															$this->errorMessage .= $errmsg."<br />\r\n";
 														}
-                                                }
+												}
 											} else {
-                                                $num_rec = $app->db->queryOneRecord("SELECT count(*) as number FROM ".$escape.$this->formDef['db_table'].$escape. " WHERE $field_name = '".$app->db->quote($field_value)."' AND ".$this->formDef['db_table_idx']." != ".$this->primary_id);
-                                                if($num_rec["number"] > 0) {
-                                                        $errmsg = $validator['errmsg'];
-                                                        if(isset($this->wordbook[$errmsg])) {
-                                                        	$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
+												$num_rec = $app->db->queryOneRecord("SELECT count(*) as number FROM ".$escape.$this->formDef['db_table'].$escape. " WHERE $field_name = '".$app->db->quote($field_value)."' AND ".$this->formDef['db_table_idx']." != ".$this->primary_id);
+												if($num_rec["number"] > 0) {
+														$errmsg = $validator['errmsg'];
+														if(isset($this->wordbook[$errmsg])) {
+															$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
 														} else {
 															$this->errorMessage .= $errmsg."<br />\r\n";
 														}
-                                                }
+												}
 											}
 										}
-                                break;
-                                case 'NOTEMPTY':
-                                        if(empty($field_value)) {
-                                                $errmsg = $validator['errmsg'];
-                                                if(isset($this->wordbook[$errmsg])) {
-                                                    $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
+								break;
+								case 'NOTEMPTY':
+										if(empty($field_value)) {
+												$errmsg = $validator['errmsg'];
+												if(isset($this->wordbook[$errmsg])) {
+													$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
 												} else {
 													$this->errorMessage .= $errmsg."<br />\r\n";
 												}
-                                        }
-                                break;
-                                case 'ISEMAIL':
-                                    if(function_exists('filter_var')) {
+										}
+								break;
+								case 'ISEMAIL':
+									if(function_exists('filter_var')) {
 										if(filter_var($field_value, FILTER_VALIDATE_EMAIL) === false) {
 											$errmsg = $validator['errmsg'];
-                                            if(isset($this->wordbook[$errmsg])) {
-                                                $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
+											if(isset($this->wordbook[$errmsg])) {
+												$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
 											} else {
 												$this->errorMessage .= $errmsg."<br />\r\n";
 											}
-                                        }
+										}
 									} else {
 										if(!preg_match("/^\w+[\w\.\-\+]*\w{0,}@\w+[\w.-]*\w+\.[a-zA-Z0-9\-]{2,30}$/i", $field_value)) {
-                                                $errmsg = $validator['errmsg'];
-                                                if(isset($this->wordbook[$errmsg])) {
-                                                    $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
+												$errmsg = $validator['errmsg'];
+												if(isset($this->wordbook[$errmsg])) {
+													$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
 												} else {
 													$this->errorMessage .= $errmsg."<br />\r\n";
 												}
-                                        }
+										}
 									}
-                                break;
-                                case 'ISINT':
+								break;
+								case 'ISINT':
 									if(function_exists('filter_var') && $field_value < 2147483647) {
 										if($field_value != '' && filter_var($field_value, FILTER_VALIDATE_INT) === false) {
 											$errmsg = $validator['errmsg'];
 											if(isset($this->wordbook[$errmsg])) {
-                                                $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
+												$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
 											} else {
 												$this->errorMessage .= $errmsg."<br />\r\n";
 											}
-                                        }
+										}
 									} else {
-                                        $tmpval = $app->functions->intval($field_value);
-                                        if($tmpval === 0 and !empty($field_value)) {
-                                                $errmsg = $validator['errmsg'];
-                                                if(isset($this->wordbook[$errmsg])) {
-                                                    $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
+										$tmpval = $app->functions->intval($field_value);
+										if($tmpval === 0 and !empty($field_value)) {
+												$errmsg = $validator['errmsg'];
+												if(isset($this->wordbook[$errmsg])) {
+													$this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
 												} else {
 													$this->errorMessage .= $errmsg."<br />\r\n";
 												}
-                                        }
+										}
 									}
-                                break;
-                                case 'ISPOSITIVE':
-                                        if(!is_numeric($field_value) || $field_value <= 0){
-                                          $errmsg = $validator['errmsg'];
-                                          if(isset($this->wordbook[$errmsg])) {
-                                             $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
+								break;
+								case 'ISPOSITIVE':
+										if(!is_numeric($field_value) || $field_value <= 0){
+										  $errmsg = $validator['errmsg'];
+										  if(isset($this->wordbook[$errmsg])) {
+											 $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
 										  } else {
 											 $this->errorMessage .= $errmsg."<br />\r\n";
 										  }
-                                        }
-                                break;
+										}
+								break;
 				case 'ISV6PREFIX':
 					$v6_prefix_ok = 0;
 					$explode_field_value = explode(':',$field_value);
 					if ($explode_field_value[count($explode_field_value)-1]=='' && $explode_field_value[count($explode_field_value)-2]=='' ){
-					        if ( count($explode_field_value) <= 9 ) {
-					                if(filter_var(substr($field_value,0,strlen($field_value)-2),FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) or filter_var(substr($field_value,0,strlen($field_value)-2).'::0',FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) or filter_var(substr($field_value,0,strlen($field_value)-2).':0',FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) ) {
-					                        $v6_prefix_ok = 1;
-                					}
-        					}
-					} else { 
-						$v6_prefix_ok = 2; 
+							if ( count($explode_field_value) <= 9 ) {
+									if(filter_var(substr($field_value,0,strlen($field_value)-2),FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) or filter_var(substr($field_value,0,strlen($field_value)-2).'::0',FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) or filter_var(substr($field_value,0,strlen($field_value)-2).':0',FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) ) {
+											$v6_prefix_ok = 1;
+									}
+							}
+					} else {
+						$v6_prefix_ok = 2;
 					}
 					// check subnet against defined server-ipv6
 					$sql_v6 = $app->db->queryOneRecord("SELECT ip_address FROM server_ip WHERE ip_type = 'IPv6' AND virtualhost = 'y' LIMIT 0,1");
 					$sql_v6_explode=explode(':',$sql_v6['ip_address']);
-					if ( count($sql_v6_explode) < count($explode_field_value) && isset($sql_v6['ip_address']) )  { 
-						$v6_prefix_ok = 3; 
+					if ( count($sql_v6_explode) < count($explode_field_value) && isset($sql_v6['ip_address']) )  {
+						$v6_prefix_ok = 3;
 					}
-					if($v6_prefix_ok == 0) { 
-						$errmsg = $validator['errmsg']; 
+					if($v6_prefix_ok == 0) {
+						$errmsg = $validator['errmsg'];
 					}
-					if($v6_prefix_ok == 2) { 
-						$errmsg = 'IPv6 Prefix must end with ::'; 
+					if($v6_prefix_ok == 2) {
+						$errmsg = 'IPv6 Prefix must end with ::';
 					}
-					if($v6_prefix_ok == 3) { 
-						$errmsg = 'IPv6 Prefix too long (according to Server IP Addresses)'; 
+					if($v6_prefix_ok == 3) {
+						$errmsg = 'IPv6 Prefix too long (according to Server IP Addresses)';
 					}
 					if($v6_prefix_ok <> 1){
-						$this->errorMessage .= $errmsg."<br />\r\n"; 
+						$this->errorMessage .= $errmsg."<br />\r\n";
 					}
 				break;
 								case 'ISIPV4':
@@ -927,15 +927,15 @@
 									$vip=0;
 								}
 								}else{$vip=0;}
-                                        if($vip==0) {
+										if($vip==0) {
 										$errmsg = $validator['errmsg'];
-                                          if(isset($this->wordbook[$errmsg])) {
-                                             $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
+										  if(isset($this->wordbook[$errmsg])) {
+											 $this->errorMessage .= $this->wordbook[$errmsg]."<br />\r\n";
 										  } else {
 											 $this->errorMessage .= $errmsg."<br />\r\n";
 										  }
 										}
-                                break;
+								break;
 								case 'ISIP':
 								if($validator['allowempty'] != 'y') $validator['allowempty'] = 'n';
 								if($validator['allowempty'] == 'y' && $field_value == '') {
@@ -979,13 +979,13 @@
 										}
 									}
 								}
-                                break;
+								break;
 								case 'RANGE':
-                                        //* Checks if the value is within the given range or above / below a value
+										//* Checks if the value is within the given range or above / below a value
 										//* Range examples: < 10 = ":10", between 2 and 10 = "2:10", above 5 = "5:".
 										$range_parts = explode(':',trim($validator['range']));
 										$ok = true;
-                                        if($range_parts[0] != '' && $field_value < $range_parts[0]) {
+										if($range_parts[0] != '' && $field_value < $range_parts[0]) {
 											$ok = false;
 										}
 										if($range_parts[1] != '' && $field_value > $range_parts[1]) {
@@ -998,76 +998,76 @@
 											} else {
 												$this->errorMessage .= $errmsg."<br />\r\n";
 											}
-                                        }
+										}
 										unset($range_parts);
-                                break;
-                                case 'CUSTOM':
-                                        // Calls a custom class to validate this record
-                                        if($validator['class'] != '' and $validator['function'] != '') {
-                                                $validator_class = $validator['class'];
-                                                $validator_function = $validator['function'];
-                                                $app->uses($validator_class);
-                                                $this->errorMessage .= $app->$validator_class->$validator_function($field_name, $field_value, $validator);
-                                        } else {
-                                                $this->errorMessage .= "Custom validator class or function is empty<br />\r\n";
-                                        }
-                                break;
+								break;
+								case 'CUSTOM':
+										// Calls a custom class to validate this record
+										if($validator['class'] != '' and $validator['function'] != '') {
+												$validator_class = $validator['class'];
+												$validator_function = $validator['function'];
+												$app->uses($validator_class);
+												$this->errorMessage .= $app->$validator_class->$validator_function($field_name, $field_value, $validator);
+										} else {
+												$this->errorMessage .= "Custom validator class or function is empty<br />\r\n";
+										}
+								break;
 								default:
 									$this->errorMessage .= "Unknown Validator: ".$validator['type'];
 								break;
-                        }
+						}
 
 
-                }
+				}
 
-                return true;
-        }
+				return true;
+		}
 
-        /**
-        * Create SQL statement
-        *
-        * @param record = Datensatz als Array
-        * @param action = INSERT oder UPDATE
-        * @param primary_id
-        * @return record
-        */
-        function getSQL($record, $tab, $action = 'INSERT', $primary_id = 0, $sql_ext_where = '') {
+		/**
+		* Create SQL statement
+		*
+		* @param record = Datensatz als Array
+		* @param action = INSERT oder UPDATE
+		* @param primary_id
+		* @return record
+		*/
+		function getSQL($record, $tab, $action = 'INSERT', $primary_id = 0, $sql_ext_where = '') {
 
-                global $app;
+				global $app;
 
-                // If there are no data records on the tab, return empty sql string
-                if(count($this->formDef['tabs'][$tab]['fields']) == 0) return '';
+				// If there are no data records on the tab, return empty sql string
+				if(count($this->formDef['tabs'][$tab]['fields']) == 0) return '';
 
-                // checking permissions
-                if($this->formDef['auth'] == 'yes' && $_SESSION["s"]["user"]["typ"] != 'admin') {
-                        if($action == "INSERT") {
-                                if(!$this->checkPerm($primary_id,'i')) $this->errorMessage .= "Insert denied.<br />\r\n";
-                        } else {
-                                if(!$this->checkPerm($primary_id,'u')) $this->errorMessage .= "Update denied.<br />\r\n";
-                        }
-                }
+				// checking permissions
+				if($this->formDef['auth'] == 'yes' && $_SESSION["s"]["user"]["typ"] != 'admin') {
+						if($action == "INSERT") {
+								if(!$this->checkPerm($primary_id,'i')) $this->errorMessage .= "Insert denied.<br />\r\n";
+						} else {
+								if(!$this->checkPerm($primary_id,'u')) $this->errorMessage .= "Update denied.<br />\r\n";
+						}
+				}
 
-                $this->action = $action;
-                $this->primary_id = $primary_id;
+				$this->action = $action;
+				$this->primary_id = $primary_id;
 
-                $record = $this->encode($record,$tab,true);
-                $sql_insert_key = '';
-                $sql_insert_val = '';
-                $sql_update = '';
+				$record = $this->encode($record,$tab,true);
+				$sql_insert_key = '';
+				$sql_insert_val = '';
+				$sql_update = '';
 
-                if(!is_array($this->formDef)) $app->error("Form definition not found.");
-                if(!is_array($this->formDef['tabs'][$tab])) $app->error("The tab is empty or does not exist (TAB: $tab).");
+				if(!is_array($this->formDef)) $app->error("Form definition not found.");
+				if(!is_array($this->formDef['tabs'][$tab])) $app->error("The tab is empty or does not exist (TAB: $tab).");
 
-                // go trough all fields of the tab
-                if(is_array($record)) {
-                foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
-                                // Wenn es kein leeres Passwortfeld ist
-                                if (!($field['formtype'] == 'PASSWORD' and $record[$key] == '')) {
-                                        // Erzeuge Insert oder Update Quelltext
-                                        if($action == "INSERT") {
-                                                if($field['formtype'] == 'PASSWORD') {
-                                                        $sql_insert_key .= "`$key`, ";
-                                                        if($field['encryption'] == 'CRYPT') {
+				// go trough all fields of the tab
+				if(is_array($record)) {
+				foreach($this->formDef['tabs'][$tab]['fields'] as $key => $field) {
+								// Wenn es kein leeres Passwortfeld ist
+								if (!($field['formtype'] == 'PASSWORD' and $record[$key] == '')) {
+										// Erzeuge Insert oder Update Quelltext
+										if($action == "INSERT") {
+												if($field['formtype'] == 'PASSWORD') {
+														$sql_insert_key .= "`$key`, ";
+														if($field['encryption'] == 'CRYPT') {
 																$record[$key] = $app->auth->crypt_password(stripslashes($record[$key]));
 																$sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
 														} elseif ($field['encryption'] == 'MYSQL') {
@@ -1076,13 +1076,13 @@
 																$sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
 														} elseif ($field['encryption'] == 'CLEARTEXT') {
 																$sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
-                                                        } else {
-                                                                $record[$key] = md5(stripslashes($record[$key]));
+														} else {
+																$record[$key] = md5(stripslashes($record[$key]));
 																$sql_insert_val .= "'".$app->db->quote($record[$key])."', ";
-                                                        }
-														
-                                                } elseif ($field['formtype'] == 'CHECKBOX') {
-                                                        $sql_insert_key .= "`$key`, ";
+														}
+
+												} elseif ($field['formtype'] == 'CHECKBOX') {
+														$sql_insert_key .= "`$key`, ";
 														if($record[$key] == '') {
 															// if a checkbox is not set, we set it to the unchecked value
 															$sql_insert_val .= "'".$field['value'][0]."', ";
@@ -1090,14 +1090,14 @@
 														} else {
 															$sql_insert_val .= "'".$record[$key]."', ";
 														}
-                                                } else {
-                                                        $sql_insert_key .= "`$key`, ";
-                                                        $sql_insert_val .= "'".$record[$key]."', ";
-                                                }
-                                        } else {
-                                                if($field['formtype'] == 'PASSWORD') {
+												} else {
+														$sql_insert_key .= "`$key`, ";
+														$sql_insert_val .= "'".$record[$key]."', ";
+												}
+										} else {
+												if($field['formtype'] == 'PASSWORD') {
 														if(isset($field['encryption']) && $field['encryption'] == 'CRYPT') {
-                                                                $record[$key] = $app->auth->crypt_password(stripslashes($record[$key]));
+																$record[$key] = $app->auth->crypt_password(stripslashes($record[$key]));
 																$sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
 														} elseif (isset($field['encryption']) && $field['encryption'] == 'MYSQL') {
 																$tmp = $app->db->queryOneRecord("SELECT PASSWORD('".$app->db->quote(stripslashes($record[$key]))."') as `crypted`");
@@ -1105,12 +1105,12 @@
 																$sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
 														} elseif (isset($field['encryption']) && $field['encryption'] == 'CLEARTEXT') {
 																$sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
-                                                        } else {
-                                                                $record[$key] = md5(stripslashes($record[$key]));
+														} else {
+																$record[$key] = md5(stripslashes($record[$key]));
 																$sql_update .= "`$key` = '".$app->db->quote($record[$key])."', ";
-                                                        }
-                                                        
-                                                } elseif ($field['formtype'] == 'CHECKBOX') {
+														}
+
+												} elseif ($field['formtype'] == 'CHECKBOX') {
 														if($record[$key] == '') {
 															// if a checkbox is not set, we set it to the unchecked value
 															$sql_update .= "`$key` = '".$field['value'][0]."', ";
@@ -1118,343 +1118,343 @@
 														} else {
 															$sql_update .= "`$key` = '".$record[$key]."', ";
 														}
-                                                } else {
-                                                        $sql_update .= "`$key` = '".$record[$key]."', ";
-                                                }
-                                        }
-                                } else {
-									// we unset the password filed, if empty to tell the datalog function 
+												} else {
+														$sql_update .= "`$key` = '".$record[$key]."', ";
+												}
+										}
+								} else {
+									// we unset the password filed, if empty to tell the datalog function
 									// that the password has not been changed
-								    unset($record[$key]);
+									unset($record[$key]);
 								}
-                        }
-        }
+						}
+		}
 
 
-                // Add backticks for incomplete table names
-                if(stristr($this->formDef['db_table'],'.')) {
-                        $escape = '';
-                } else {
-                        $escape = '`';
-                }
+				// Add backticks for incomplete table names
+				if(stristr($this->formDef['db_table'],'.')) {
+						$escape = '';
+				} else {
+						$escape = '`';
+				}
 
 
-                if($action == "INSERT") {
-                        if($this->formDef['auth'] == 'yes') {
-                                // Set user and group
-                                $sql_insert_key .= "`sys_userid`, ";
-                                $sql_insert_val .= ($this->formDef["auth_preset"]["userid"] > 0)?"'".$this->formDef["auth_preset"]["userid"]."', ":"'".$_SESSION["s"]["user"]["userid"]."', ";
-                                $sql_insert_key .= "`sys_groupid`, ";
-                                $sql_insert_val .= ($this->formDef["auth_preset"]["groupid"] > 0)?"'".$this->formDef["auth_preset"]["groupid"]."', ":"'".$_SESSION["s"]["user"]["default_group"]."', ";
-                                $sql_insert_key .= "`sys_perm_user`, ";
-                                $sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_user"]."', ";
-                                $sql_insert_key .= "`sys_perm_group`, ";
-                                $sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_group"]."', ";
-                                $sql_insert_key .= "`sys_perm_other`, ";
-                                $sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_other"]."', ";
-                        }
-                        $sql_insert_key = substr($sql_insert_key,0,-2);
-                        $sql_insert_val = substr($sql_insert_val,0,-2);
-                        $sql = "INSERT INTO ".$escape.$this->formDef['db_table'].$escape." ($sql_insert_key) VALUES ($sql_insert_val)";
-                } else {
+				if($action == "INSERT") {
+						if($this->formDef['auth'] == 'yes') {
+								// Set user and group
+								$sql_insert_key .= "`sys_userid`, ";
+								$sql_insert_val .= ($this->formDef["auth_preset"]["userid"] > 0)?"'".$this->formDef["auth_preset"]["userid"]."', ":"'".$_SESSION["s"]["user"]["userid"]."', ";
+								$sql_insert_key .= "`sys_groupid`, ";
+								$sql_insert_val .= ($this->formDef["auth_preset"]["groupid"] > 0)?"'".$this->formDef["auth_preset"]["groupid"]."', ":"'".$_SESSION["s"]["user"]["default_group"]."', ";
+								$sql_insert_key .= "`sys_perm_user`, ";
+								$sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_user"]."', ";
+								$sql_insert_key .= "`sys_perm_group`, ";
+								$sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_group"]."', ";
+								$sql_insert_key .= "`sys_perm_other`, ";
+								$sql_insert_val .= "'".$this->formDef["auth_preset"]["perm_other"]."', ";
+						}
+						$sql_insert_key = substr($sql_insert_key,0,-2);
+						$sql_insert_val = substr($sql_insert_val,0,-2);
+						$sql = "INSERT INTO ".$escape.$this->formDef['db_table'].$escape." ($sql_insert_key) VALUES ($sql_insert_val)";
+				} else {
 					if($this->formDef['auth'] == 'yes') {
-                        if($primary_id != 0) {
-                                $sql_update = substr($sql_update,0,-2);
-                                $sql = "UPDATE ".$escape.$this->formDef['db_table'].$escape." SET ".$sql_update." WHERE ".$this->getAuthSQL('u')." AND ".$this->formDef['db_table_idx']." = ".$primary_id;
-                                if($sql_ext_where != '') $sql .= " and ".$sql_ext_where;
-                        } else {
-                                $app->error("Primary ID fehlt!");
-                        }
+						if($primary_id != 0) {
+								$sql_update = substr($sql_update,0,-2);
+								$sql = "UPDATE ".$escape.$this->formDef['db_table'].$escape." SET ".$sql_update." WHERE ".$this->getAuthSQL('u')." AND ".$this->formDef['db_table_idx']." = ".$primary_id;
+								if($sql_ext_where != '') $sql .= " and ".$sql_ext_where;
+						} else {
+								$app->error("Primary ID fehlt!");
+						}
 					} else {
 						if($primary_id != 0) {
-                                $sql_update = substr($sql_update,0,-2);
-                                $sql = "UPDATE ".$escape.$this->formDef['db_table'].$escape." SET ".$sql_update." WHERE ".$this->formDef['db_table_idx']." = ".$primary_id;
-                                if($sql_ext_where != '') $sql .= " and ".$sql_ext_where;
-                        } else {
-                                $app->error("Primary ID fehlt!");
-                        }
+								$sql_update = substr($sql_update,0,-2);
+								$sql = "UPDATE ".$escape.$this->formDef['db_table'].$escape." SET ".$sql_update." WHERE ".$this->formDef['db_table_idx']." = ".$primary_id;
+								if($sql_ext_where != '') $sql .= " and ".$sql_ext_where;
+						} else {
+								$app->error("Primary ID fehlt!");
+						}
 					}
 					//* return a empty string if there is nothing to update
 					if(trim($sql_update) == '') $sql = '';
-                }
+				}
 
-                return $sql;
-        }
+				return $sql;
+		}
 
-        /**
-        * Debugging arrays.
-        *
-        * @param array_data
-        */
-        function dbg($array_data) {
+		/**
+		* Debugging arrays.
+		*
+		* @param array_data
+		*/
+		function dbg($array_data) {
 
-                echo "<pre>";
-                print_r($array_data);
-                echo "</pre>";
+				echo "<pre>";
+				print_r($array_data);
+				echo "</pre>";
 
-        }
+		}
 
 
-    function showForm() {
-            global $app,$conf;
+	function showForm() {
+			global $app,$conf;
 
-        if(!is_array($this->formDef)) die("Form Definition wurde nicht geladen.");
+		if(!is_array($this->formDef)) die("Form Definition wurde nicht geladen.");
 
-                $active_tab = $this->getNextTab();
+				$active_tab = $this->getNextTab();
 
-        // go trough the tabs
-        foreach( $this->formDef["tabs"] as $key => $tab) {
+		// go trough the tabs
+		foreach( $this->formDef["tabs"] as $key => $tab) {
 
-            $tab['name'] = $key;
+			$tab['name'] = $key;
 			// Translate the title of the tab
 			$tab['title'] = $this->lng($tab['title']);
-			
-            if($tab['name'] == $active_tab) {
 
-                // If module is set, then set the template path relative to the module..
-                if($this->module != '') $tab["template"] = "../".$this->module."/".$tab["template"];
+			if($tab['name'] == $active_tab) {
 
-                // Generate the template if it does not exist yet.
-				
-				
-								
-                if(!is_file($tab["template"])) {
-                     $app->uses('tform_tpl_generator');
-                     $app->tform_tpl_generator->buildHTML($this->formDef,$tab['name']);
-                }
-                $app->tpl->setVar('readonly_tab', (isset($tab['readonly']) && $tab['readonly'] == true));
-                $app->tpl->setInclude('content_tpl',$tab["template"]);
-                $tab["active"] = 1;
-                $_SESSION["s"]["form"]["tab"] = $tab['name'];
-            } else {
-                    $tab["active"] = 0;
-            }
+				// If module is set, then set the template path relative to the module..
+				if($this->module != '') $tab["template"] = "../".$this->module."/".$tab["template"];
 
-                        // Unset unused variables.
-                        unset($tab["fields"]);
-                        unset($tab["plugins"]);
+				// Generate the template if it does not exist yet.
 
-            $frmTab[] = $tab;
-        }
 
-        // setting form tabs
-        $app->tpl->setLoop("formTab", $frmTab);
 
-                // Set form action
-                $app->tpl->setVar('form_action',$this->formDef["action"]);
-                $app->tpl->setVar('form_active_tab',$active_tab);
+				if(!is_file($tab["template"])) {
+					 $app->uses('tform_tpl_generator');
+					 $app->tform_tpl_generator->buildHTML($this->formDef,$tab['name']);
+				}
+				$app->tpl->setVar('readonly_tab', (isset($tab['readonly']) && $tab['readonly'] == true));
+				$app->tpl->setInclude('content_tpl',$tab["template"]);
+				$tab["active"] = 1;
+				$_SESSION["s"]["form"]["tab"] = $tab['name'];
+			} else {
+					$tab["active"] = 0;
+			}
 
-                // Set form title
-                $form_hint = $this->lng($this->formDef["title"]);
-                if($this->formDef["description"] != '') $form_hint .= '<div class="pageForm_description">'.$this->lng($this->formDef["description"]).'</div>';
-                $app->tpl->setVar('form_hint',$form_hint);
+						// Unset unused variables.
+						unset($tab["fields"]);
+						unset($tab["plugins"]);
 
-                // Set Wordbook for this form
+			$frmTab[] = $tab;
+		}
 
-                $app->tpl->setVar($this->wordbook);
-    	}
+		// setting form tabs
+		$app->tpl->setLoop("formTab", $frmTab);
+
+				// Set form action
+				$app->tpl->setVar('form_action',$this->formDef["action"]);
+				$app->tpl->setVar('form_active_tab',$active_tab);
+
+				// Set form title
+				$form_hint = $this->lng($this->formDef["title"]);
+				if($this->formDef["description"] != '') $form_hint .= '<div class="pageForm_description">'.$this->lng($this->formDef["description"]).'</div>';
+				$app->tpl->setVar('form_hint',$form_hint);
+
+				// Set Wordbook for this form
+
+				$app->tpl->setVar($this->wordbook);
+		}
 
 		function getDataRecord($primary_id) {
 			global $app;
 			$escape = '`';
 			$sql = "SELECT * FROM ".$escape.$this->formDef['db_table'].$escape." WHERE ".$this->formDef['db_table_idx']." = ".$primary_id;
-            return $app->db->queryOneRecord($sql);
+			return $app->db->queryOneRecord($sql);
 		}
-		
 
-        function datalogSave($action,$primary_id, $record_old, $record_new) {
-                global $app,$conf;
-				
+
+		function datalogSave($action,$primary_id, $record_old, $record_new) {
+				global $app,$conf;
+
 				$app->db->datalogSave($this->formDef['db_table'], $action, $this->formDef['db_table_idx'], $primary_id, $record_old, $record_new);
 				return true;
-				
-				/*
-                // Add backticks for incomplete table names.
-                if(stristr($this->formDef['db_table'],'.')) {
-                        $escape = '';
-                } else {
-                        $escape = '`';
-                }
 
-                $this->diffrec = array();
-				
+				/*
+				// Add backticks for incomplete table names.
+				if(stristr($this->formDef['db_table'],'.')) {
+						$escape = '';
+				} else {
+						$escape = '`';
+				}
+
+				$this->diffrec = array();
+
 				// Full diff records for ISPConfig, they have a different format then the simple diffrec
 				$diffrec_full = array();
 
-                if(is_array($record_old) && count($record_old) > 0) {
-                        foreach($record_old as $key => $val) {
-                                //if(isset($record_new[$key]) && $record_new[$key] != $val) {
+				if(is_array($record_old) && count($record_old) > 0) {
+						foreach($record_old as $key => $val) {
+								//if(isset($record_new[$key]) && $record_new[$key] != $val) {
 								if(!isset($record_new[$key]) || $record_new[$key] != $val) {
-                                    // Record has changed
+									// Record has changed
 									$diffrec_full['old'][$key] = $val;
 									$diffrec_full['new'][$key] = $record_new[$key];
 									$this->diffrec[$key] = array(	'new' => $record_new[$key],
-                                                               		'old' => $val);
-                                } else {
+															   		'old' => $val);
+								} else {
 									$diffrec_full['old'][$key] = $val;
 									$diffrec_full['new'][$key] = $val;
 								}
-                        }
-                } elseif(is_array($record_new)) {
-                        foreach($record_new as $key => $val) {
-                                if(isset($record_new[$key]) && $record_old[$key] != $val) {
-                                    // Record has changed
+						}
+				} elseif(is_array($record_new)) {
+						foreach($record_new as $key => $val) {
+								if(isset($record_new[$key]) && $record_old[$key] != $val) {
+									// Record has changed
 									$diffrec_full['new'][$key] = $val;
 									$diffrec_full['old'][$key] = $record_old[$key];
 									$this->diffrec[$key] = array(	'old' => @$record_old[$key],
-                                                               		'new' => $val);
-                                } else {
+															   		'new' => $val);
+								} else {
 									$diffrec_full['new'][$key] = $val;
 									$diffrec_full['old'][$key] = $val;
 								}
-                        }
-                }
-				
+						}
+				}
+
 				//$this->diffrec = $diffrec;
 				// Insert the server_id, if the record has a server_id
 				$server_id = (isset($record_old["server_id"]) && $record_old["server_id"] > 0)?$record_old["server_id"]:0;
 				if(isset($record_new["server_id"])) $server_id = $record_new["server_id"];
 
-                if(count($this->diffrec) > 0) {
+				if(count($this->diffrec) > 0) {
 						$diffstr = addslashes(serialize($diffrec_full));
-                        $username = $app->db->quote($_SESSION["s"]["user"]["username"]);
-                        $dbidx = $this->formDef['db_table_idx'].":".$primary_id;
-                        // $action = ($action == 'INSERT')?'i':'u';
-						
+						$username = $app->db->quote($_SESSION["s"]["user"]["username"]);
+						$dbidx = $this->formDef['db_table_idx'].":".$primary_id;
+						// $action = ($action == 'INSERT')?'i':'u';
+
 						if($action == 'INSERT') $action = 'i';
 						if($action == 'UPDATE') $action = 'u';
 						if($action == 'DELETE') $action = 'd';
-                        $sql = "INSERT INTO sys_datalog (dbtable,dbidx,server_id,action,tstamp,user,data) VALUES ('".$this->formDef['db_table']."','$dbidx','$server_id','$action','".time()."','$username','$diffstr')";
+						$sql = "INSERT INTO sys_datalog (dbtable,dbidx,server_id,action,tstamp,user,data) VALUES ('".$this->formDef['db_table']."','$dbidx','$server_id','$action','".time()."','$username','$diffstr')";
 						$app->db->query($sql);
-                }
+				}
 
-                return true;
+				return true;
 				*/
 
-        }
+		}
 
-        function getAuthSQL($perm, $table = '') {
+		function getAuthSQL($perm, $table = '') {
 				if($_SESSION["s"]["user"]["typ"] == 'admin') {
 					return '1';
 				} else {
 					if ($table != ''){
 						$table = ' ' . $table . '.';
 					}
-                	$groups = ( $_SESSION["s"]["user"]["groups"] ) ? $_SESSION["s"]["user"]["groups"] : 0;
+					$groups = ( $_SESSION["s"]["user"]["groups"] ) ? $_SESSION["s"]["user"]["groups"] : 0;
 					$sql = '(';
-                	$sql .= "(" . $table . "sys_userid = ".$_SESSION["s"]["user"]["userid"]." AND " . $table . "sys_perm_user like '%$perm%') OR  ";
-                	$sql .= "(" . $table . "sys_groupid IN (".$groups.") AND " . $table ."sys_perm_group like '%$perm%') OR ";
-                	$sql .= $table . "sys_perm_other like '%$perm%'";
-                	$sql .= ')';
+					$sql .= "(" . $table . "sys_userid = ".$_SESSION["s"]["user"]["userid"]." AND " . $table . "sys_perm_user like '%$perm%') OR  ";
+					$sql .= "(" . $table . "sys_groupid IN (".$groups.") AND " . $table ."sys_perm_group like '%$perm%') OR ";
+					$sql .= $table . "sys_perm_other like '%$perm%'";
+					$sql .= ')';
 
-                	return $sql;
+					return $sql;
 				}
-        }
+		}
 
-        /*
-        This function checks if a user has the parmissions $perm for the data record with the ID $record_id
-        If record_id = 0, the the permissions are tested against the defaults of the form file.
-        */
-        function checkPerm($record_id,$perm) {
-                global $app;
+		/*
+		This function checks if a user has the parmissions $perm for the data record with the ID $record_id
+		If record_id = 0, the the permissions are tested against the defaults of the form file.
+		*/
+		function checkPerm($record_id,$perm) {
+				global $app;
 
-                if($record_id > 0) {
-                        // Add backticks for incomplete table names.
-                        if(stristr($this->formDef['db_table'],'.')) {
-                                $escape = '';
-                        } else {
-                                $escape = '`';
-                        }
+				if($record_id > 0) {
+						// Add backticks for incomplete table names.
+						if(stristr($this->formDef['db_table'],'.')) {
+								$escape = '';
+						} else {
+								$escape = '`';
+						}
 
-                        $sql = "SELECT ".$this->formDef['db_table_idx']." FROM ".$escape.$this->formDef['db_table'].$escape." WHERE ".$this->formDef['db_table_idx']." = ".$record_id." AND ".$this->getAuthSQL($perm);
-                        if($record = $app->db->queryOneRecord($sql)) {
-                                return true;
-                        } else {
-                                return false;
-                        }
-                } else {
-                        $result = false;
-                        if(@$this->formDef["auth_preset"]["userid"] == $_SESSION["s"]["user"]["userid"] && stristr($perm,$this->formDef["auth_preset"]["perm_user"])) $result = true;
-                        if(@$this->formDef["auth_preset"]["groupid"] == $_SESSION["s"]["user"]["groupid"] && stristr($perm,$this->formDef["auth_preset"]["perm_group"])) $result = true;
-                        if(@stristr($this->formDef["auth_preset"]["perm_other"],$perm)) $result = true;
+						$sql = "SELECT ".$this->formDef['db_table_idx']." FROM ".$escape.$this->formDef['db_table'].$escape." WHERE ".$this->formDef['db_table_idx']." = ".$record_id." AND ".$this->getAuthSQL($perm);
+						if($record = $app->db->queryOneRecord($sql)) {
+								return true;
+						} else {
+								return false;
+						}
+				} else {
+						$result = false;
+						if(@$this->formDef["auth_preset"]["userid"] == $_SESSION["s"]["user"]["userid"] && stristr($perm,$this->formDef["auth_preset"]["perm_user"])) $result = true;
+						if(@$this->formDef["auth_preset"]["groupid"] == $_SESSION["s"]["user"]["groupid"] && stristr($perm,$this->formDef["auth_preset"]["perm_group"])) $result = true;
+						if(@stristr($this->formDef["auth_preset"]["perm_other"],$perm)) $result = true;
 
-                        // if preset == 0, everyone can insert a record of this type
-                        if($this->formDef["auth_preset"]["userid"] == 0 AND $this->formDef["auth_preset"]["groupid"] == 0 AND (@stristr($this->formDef["auth_preset"]["perm_user"],$perm) OR @stristr($this->formDef["auth_preset"]["perm_group"],$perm))) $result = true;
+						// if preset == 0, everyone can insert a record of this type
+						if($this->formDef["auth_preset"]["userid"] == 0 AND $this->formDef["auth_preset"]["groupid"] == 0 AND (@stristr($this->formDef["auth_preset"]["perm_user"],$perm) OR @stristr($this->formDef["auth_preset"]["perm_group"],$perm))) $result = true;
 
-                        return $result;
+						return $result;
 
-                }
+				}
 
-        }
+		}
 
-        function getNextTab() {
-                // Which tab is shown
-                if($this->errorMessage == '') {
-                    // If there is no error
-                    if(isset($_REQUEST["next_tab"]) && $_REQUEST["next_tab"] != '') {
-                                // If the next tab is known
-                                $active_tab = $_REQUEST["next_tab"];
-                    } else {
-                        // else use the default tab
-                        $active_tab = $this->formDef['tab_default'];
-                    }
-                } else {
-                    // Show the same tab again in case of an error
-                    $active_tab = $_SESSION["s"]["form"]["tab"];
-                }
+		function getNextTab() {
+				// Which tab is shown
+				if($this->errorMessage == '') {
+					// If there is no error
+					if(isset($_REQUEST["next_tab"]) && $_REQUEST["next_tab"] != '') {
+								// If the next tab is known
+								$active_tab = $_REQUEST["next_tab"];
+					} else {
+						// else use the default tab
+						$active_tab = $this->formDef['tab_default'];
+					}
+				} else {
+					// Show the same tab again in case of an error
+					$active_tab = $_SESSION["s"]["form"]["tab"];
+				}
 
-                return $active_tab;
-        }
+				return $active_tab;
+		}
 
-        function getCurrentTab() {
-                return $_SESSION["s"]["form"]["tab"];
-        }
-		
+		function getCurrentTab() {
+				return $_SESSION["s"]["form"]["tab"];
+		}
+
 		function isReadonlyTab($tab, $primary_id) {
 			global $app, $conf;
-			
+
 			// Add backticks for incomplete table names.
-            if(stristr($this->formDef['db_table'],'.')) {
-                $escape = '';
-            } else {
-                $escape = '`';
-            }
-			
+			if(stristr($this->formDef['db_table'],'.')) {
+				$escape = '';
+			} else {
+				$escape = '`';
+			}
+
 			$sql = "SELECT sys_userid FROM ".$escape.$this->formDef['db_table'].$escape." WHERE ".$this->formDef['db_table_idx']." = ".$primary_id;
-            $record = $app->db->queryOneRecord($sql);
-			
+			$record = $app->db->queryOneRecord($sql);
+
 			// return true if the readonly flag of the form is set and the current loggedin user is not the owner of the record.
 			if(isset($this->formDef['tabs'][$tab]['readonly']) && $this->formDef['tabs'][$tab]['readonly'] == true && $record['sys_userid'] != $_SESSION["s"]["user"]["userid"]) {
 				return true;
 			} else {
 				return false;
 			}
-        }
-		
-		
+		}
+
+
 		// translation function for forms, tries the form wordbook first and if this fails, it tries the global wordbook
 		function lng($msg) {
 			global $app,$conf;
-			
+
 			if(isset($this->wordbook[$msg])) {
 				return $this->wordbook[$msg];
 			} else {
 				return $app->lng($msg);
 			}
-			
+
 		}
-		
+
 		function checkClientLimit($limit_name,$sql_where = '') {
 			global $app;
-			
+
 			$check_passed = true;
 			$limit_name = $app->db->quote($limit_name);
 			if($limit_name == '') $app->error('Limit name missing in function checkClientLimit.');
-			
+
 			// Get the limits of the client that is currently logged in
 			$client_group_id = $_SESSION["s"]["user"]["default_group"];
 			$client = $app->db->queryOneRecord("SELECT $limit_name as number, parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
-			
+
 			// Check if the user may add another item
 			if($client["number"] >= 0) {
 				$sql = "SELECT count(".$this->formDef['db_table_idx'].") as number FROM ".$this->formDef['db_table']." WHERE ".$this->getAuthSQL('u');
@@ -1462,33 +1462,33 @@
 				$tmp = $app->db->queryOneRecord($sql);
 				if($tmp["number"] >= $client["number"]) $check_passed = false;
 			}
-			
+
 			return $check_passed;
 		}
-		
+
 		function checkResellerLimit($limit_name,$sql_where = '') {
 			global $app;
-			
+
 			$check_passed = true;
 			$limit_name = $app->db->quote($limit_name);
 			if($limit_name == '') $app->error('Limit name missing in function checkClientLimit.');
-			
+
 			// Get the limits of the client that is currently logged in
 			$client_group_id = $_SESSION["s"]["user"]["default_group"];
 			$client = $app->db->queryOneRecord("SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
-			
+
 			//* If the client belongs to a reseller, we will check against the reseller Limit too
 			if($client['parent_client_id'] != 0) {
-				
+
 				//* first we need to know the groups of this reseller
 				$tmp = $app->db->queryOneRecord("SELECT userid, groups FROM sys_user WHERE client_id = ".$client['parent_client_id']);
 				$reseller_groups = $tmp["groups"];
 				$reseller_userid = $tmp["userid"];
-				
+
 				// Get the limits of the reseller of the logged in client
 				$client_group_id = $_SESSION["s"]["user"]["default_group"];
 				$reseller = $app->db->queryOneRecord("SELECT $limit_name as number FROM client WHERE client_id = ".$client['parent_client_id']);
-			
+
 				// Check if the user may add another item
 				if($reseller["number"] >= 0) {
 					$sql = "SELECT count(".$this->formDef['db_table_idx'].") as number FROM ".$this->formDef['db_table']." WHERE (sys_groupid IN (".$reseller_groups.") or sys_userid = ".$reseller_userid.")";
@@ -1497,13 +1497,13 @@
 					if($tmp["number"] >= $reseller["number"]) $check_passed = false;
 				}
 			}
-			
+
 			return $check_passed;
 		}
-		
+
 		//* get the difference record of two arrays
 		function getDiffRecord($record_old,$record_new) {
-			
+
 			if(is_array($record_new) && count($record_new) > 0) {
 			foreach($record_new as $key => $val) {
 				if(@$record_old[$key] != $val) {
@@ -1522,17 +1522,17 @@
 					}
 				}
 			return $diffrec;
-		
+
 		}
-		
+
 		/**
 		 * Generate HTML for DATETIME fields.
-		 * 
+		 *
 		 * @access private
 		 * @param string $form_element Name of the form element.
 		 * @param string $default_value Selected value for fields.
 		 * @param bool $display_secons Include seconds selection.
-		 * @return string HTML	
+		 * @return string HTML
 		 */
 		function _getDateTimeHTML($form_element, $default_value, $display_seconds=false)
 		{
@@ -1540,54 +1540,54 @@
 			$_showdate = ($_datetime === false) ? false : true;
 
 			$dselect = array('day','month','year','hour','minute');
-            if ($display_seconds === true) {
+			if ($display_seconds === true) {
 			 	$dselect[] = 'second';
 			}
-			 
+
 			$out = '';
-			 
+
 			foreach ($dselect as $dt_element)
 			{
 			 	$dt_options = array();
 			 	$dt_space = 1;
-			 	
+
 			 	switch ($dt_element) {
 			 		case 'day':
 					 	for ($i = 1; $i <= 31; $i++) {
-				            $dt_options[] = array('name' =>  sprintf('%02d', $i),
-				            					  'value' => sprintf('%d', $i));
-				        }
-				        $selected_value = date('d', $_datetime);
+							$dt_options[] = array('name' =>  sprintf('%02d', $i),
+												  'value' => sprintf('%d', $i));
+						}
+						$selected_value = date('d', $_datetime);
 			 			break;
-			 			
+
 			 		case 'month':
 				 		for ($i = 1; $i <= 12; $i++) {
-				            $dt_options[] = array('name' => strftime('%b', mktime(0, 0, 0, $i, 1, 2000)),
-				            					  'value' => strftime('%m', mktime(0, 0, 0, $i, 1, 2000)));
-				        }
-				        $selected_value = date('n', $_datetime);
+							$dt_options[] = array('name' => strftime('%b', mktime(0, 0, 0, $i, 1, 2000)),
+												  'value' => strftime('%m', mktime(0, 0, 0, $i, 1, 2000)));
+						}
+						$selected_value = date('n', $_datetime);
 			 			break;
-			 			
+
 			 		case 'year':
 					 	$start_year = strftime("%Y");
 						$years = range((int)$start_year, (int)($start_year+3));
-				        
-				        foreach ($years as $year) {
-				        	$dt_options[] = array('name' => $year,
-				            					 'value' => $year);
-				        }
-				        $selected_value = date('Y', $_datetime);
-				        $dt_space = 2;
+
+						foreach ($years as $year) {
+							$dt_options[] = array('name' => $year,
+												 'value' => $year);
+						}
+						$selected_value = date('Y', $_datetime);
+						$dt_space = 2;
 			 			break;
-			 			
+
 			 		case 'hour':
 			 			foreach(range(0, 23) as $hour) {
 			 				$dt_options[] = array('name' =>  sprintf('%02d', $hour),
-            			    					  'value' => sprintf('%d', $hour));
+												  'value' => sprintf('%d', $hour));
 			 			}
 			 			$selected_value = date('G', $_datetime);
 			 			break;
-			 			
+
 			 		case 'minute':
 			 			foreach(range(0, 59) as $minute) {
 			 				if (($minute % 5) == 0) {
@@ -1597,23 +1597,23 @@
 			 			}
 			 			$selected_value = (int)floor(date('i', $_datetime));
 			 			break;
-			 			
-			 		case 'second':	
+
+			 		case 'second':
 			 			foreach(range(0, 59) as $second) {
 			 				$dt_options[] = array('name' =>  sprintf('%02d', $second),
-							      				  'value' => sprintf('%d', $second));
+								  				  'value' => sprintf('%d', $second));
 			 			}
 			 			$selected_value = (int)floor(date('s', $_datetime));
 			 			break;
 			 	}
-					 	
+
 				$out .= "<select name=\"".$form_element."[$dt_element]\" id=\"".$form_element."_$dt_element\" class=\"selectInput\" style=\"width: auto; float: none;\">";
 				if (!$_showdate) {
 					$out .= "<option value=\"-\" selected=\"selected\">--</option>" . PHP_EOL;
 				} else {
 					$out .= "<option value=\"-\">--</option>" . PHP_EOL;
 				}
-				 
+
 				foreach ($dt_options as $dt_opt) {
 					if ( $_showdate && ($selected_value == $dt_opt['value']) ) {
 						$out .= "<option value=\"{$dt_opt['value']}\" selected=\"selected\">{$dt_opt['name']}</option>" . PHP_EOL;
@@ -1621,10 +1621,10 @@
 						$out .= "<option value=\"{$dt_opt['value']}\">{$dt_opt['name']}</option>" . PHP_EOL;
 					}
 				}
-												        
+
 				$out .= '</select>' . str_repeat('&nbsp;', $dt_space);
 			}
-			
+
 			return $out;
 		}
 }
diff --git a/interface/lib/classes/tools_monitor.inc.php b/interface/lib/classes/tools_monitor.inc.php
index 121ab93..42defa0 100644
--- a/interface/lib/classes/tools_monitor.inc.php
+++ b/interface/lib/classes/tools_monitor.inc.php
@@ -453,6 +453,40 @@
         return $html;
     }
 
+    function showMongoDB() {
+        global $app;
+
+        /* fetch the Data from the DB */
+        $record = $app->db->queryOneRecord("SELECT data, state FROM monitor_data WHERE type = 'log_mongodb' and server_id = " . $_SESSION['monitor']['server_id'] . " order by created desc");
+
+        if(isset($record['data'])) {
+            $html =
+                    '<div class="systemmonitor-state state-'.$record['state'].'">
+                <div class="systemmonitor-content icons32 ico-'.$record['state'].'">';
+
+            /*
+             * First, we have to detect, if there is any monitoring-data.
+             * If not (because mongodb is not installed) show this.
+            */
+            $data = unserialize($record['data']);
+            if ($data == '') {
+                $html .= '<p>'.
+                        'MongoDB is not installed at this server.<br />' .
+                        'See more (for debian) <a href="http://www.howtoforge.com/fail2ban_debian_etch" target="htf">here...</a>'.
+                        '</p>';
+            }
+            else {
+                $html .= nl2br($data);
+            }
+            $html .= '</div></div>';
+
+        } else {
+            $html = '<p>There is no data available at the moment.</p>';
+        }
+
+        return $html;
+    }
+
     function showIPTables() {
         global $app;
         $record = $app->db->queryOneRecord("SELECT data, state FROM monitor_data WHERE type = 'iptables_rules' and server_id = " . $_SESSION['monitor']['server_id'] . " order by created desc");
diff --git a/interface/lib/shelluser_blacklist b/interface/lib/shelluser_blacklist
index c49d825..4913b64 100644
--- a/interface/lib/shelluser_blacklist
+++ b/interface/lib/shelluser_blacklist
@@ -31,4 +31,5 @@
 getmail
 ispconfig
 courier
-dovecot
\ No newline at end of file
+dovecot
+mongodb
diff --git a/interface/web/admin/form/server_config.tform.php b/interface/web/admin/form/server_config.tform.php
index c83075f..0bc490f 100644
--- a/interface/web/admin/form/server_config.tform.php
+++ b/interface/web/admin/form/server_config.tform.php
@@ -89,9 +89,9 @@
 		'v6_prefix' => array(
 			'datatype' => 'VARCHAR',
 			'formtype' => 'TEXT',
-                        'validators' => array(0 => array('type' => 'ISV6PREFIX',
-                                        'errmsg' => 'v6_prefix_wrong'),
-                        ),
+						'validators' => array(0 => array('type' => 'ISV6PREFIX',
+										'errmsg' => 'v6_prefix_wrong'),
+						),
 		'default' => ''
 		),
 		'gateway' => array(
@@ -117,13 +117,13 @@
 			'datatype' => 'VARCHAR',
 			'formtype' => 'TEXT',
 			'default' => 'server1.domain.tld',
-            'filters'   => array( 0 => array( 'event' => 'SAVE',
-                                              'type' => 'IDNTOASCII'),
-                                  1 => array( 'event' => 'SHOW',
-                                              'type' => 'IDNTOUTF8'),
-                                  2 => array( 'event' => 'SAVE',
-                                              'type' => 'TOLOWER')
-                                ),
+			'filters'   => array( 0 => array( 'event' => 'SAVE',
+											  'type' => 'IDNTOASCII'),
+								  1 => array( 'event' => 'SHOW',
+											  'type' => 'IDNTOUTF8'),
+								  2 => array( 'event' => 'SAVE',
+											  'type' => 'TOLOWER')
+								),
 			'validators' => array(0 => array('type' => 'NOTEMPTY',
 					'errmsg' => 'hostname_error_empty'),
 			),
@@ -182,9 +182,9 @@
 			'formtype' => 'TEXT',
 			'default' => '',
 			'validators'	=> array ( 0 => array (	'type'	=> 'REGEX',
-                                                                'regex' => '/^[0-9a-zA-Z\:\/\-\.\[\]]{0,255}$/',
-                                                                'errmsg'=> 'monit_url_error_regex'),
-                                                ),
+																'regex' => '/^[0-9a-zA-Z\:\/\-\.\[\]]{0,255}$/',
+																'errmsg'=> 'monit_url_error_regex'),
+												),
 			'value' => '',
 			'width' => '40',
 			'maxlength' => '255'
@@ -210,9 +210,9 @@
 			'formtype' => 'TEXT',
 			'default' => '',
 			'validators'	=> array ( 0 => array (	'type'	=> 'REGEX',
-                                                                'regex' => '/^[0-9a-zA-Z\:\/\-\.\[\]]{0,255}$/',
-                                                                'errmsg'=> 'munin_url_error_regex'),
-                                                ),
+																'regex' => '/^[0-9a-zA-Z\:\/\-\.\[\]]{0,255}$/',
+																'errmsg'=> 'munin_url_error_regex'),
+												),
 			'value' => '',
 			'width' => '40',
 			'maxlength' => '255'
@@ -275,19 +275,19 @@
 			'width' => '40',
 			'maxlength' => '255'
 		),
-                'dkim_path' => array(
-                        'datatype' => 'VARCHAR',
-                        'formtype' => 'TEXT',
-                        'default' => '/var/db/dkim',
-                        'validators'    => array (  0 => array ('type'  => 'CUSTOM',
-                                                                'class' => 'validate_dkim',
-                                                                'function' => 'check_dkim_path',
-                                                                'errmsg'=> 'dkim_path_error'),
-                                                 ),
-                        'value' => '',
-                        'width' => '40',
-                        'maxlength' => '255'
-                ),
+				'dkim_path' => array(
+						'datatype' => 'VARCHAR',
+						'formtype' => 'TEXT',
+						'default' => '/var/db/dkim',
+						'validators'    => array (  0 => array ('type'  => 'CUSTOM',
+																'class' => 'validate_dkim',
+																'function' => 'check_dkim_path',
+																'errmsg'=> 'dkim_path_error'),
+												 ),
+						'value' => '',
+						'width' => '40',
+						'maxlength' => '255'
+				),
 		'pop3_imap_daemon' => array(
 			'datatype' => 'VARCHAR',
 			'formtype' => 'SELECT',
@@ -419,8 +419,8 @@
 			'formtype' => 'TEXT',
 			'default' => '7',
 			'value' => '',
-            'width' => '20',
-            'maxlength' => '255'
+			'width' => '20',
+			'maxlength' => '255'
 		),
 		'overquota_notify_onok' => array(
 			'datatype' => 'VARCHAR',
@@ -659,8 +659,8 @@
 			'formtype' => 'TEXT',
 			'default' => '7',
 			'value' => '',
-            'width' => '20',
-            'maxlength' => '255'
+			'width' => '20',
+			'maxlength' => '255'
 		),
 		'overquota_notify_onok' => array(
 			'datatype' => 'VARCHAR',
@@ -1306,6 +1306,12 @@
 			'default' => 'n',
 			'value' => array(0 => 'n', 1 => 'y')
 		),
+		'do_not_try_rescue_mongodb' => array(
+			'datatype' => 'VARCHAR',
+			'formtype' => 'CHECKBOX',
+			'default' => 'n',
+			'value' => array(0 => 'n', 1 => 'y')
+		),
 		'do_not_try_rescue_mysql' => array(
 			'datatype' => 'VARCHAR',
 			'formtype' => 'CHECKBOX',
diff --git a/interface/web/admin/lib/lang/de_server_config.lng b/interface/web/admin/lib/lang/de_server_config.lng
index b6f1051..acb6b3d 100644
--- a/interface/web/admin/lib/lang/de_server_config.lng
+++ b/interface/web/admin/lib/lang/de_server_config.lng
@@ -146,6 +146,7 @@
 $wb['fastcgi_config_syntax_txt'] = 'FastCGI Konfigurations Syntax';
 $wb['try_rescue_txt'] = 'Aktiviere Service Monitoring und Neustart bei Unerreichbarkeit';
 $wb['do_not_try_rescue_httpd_txt'] = 'Deaktiviere HTTPD Monitoring';
+$wb['do_not_try_rescue_mongodb_txt'] = 'Deaktiviere MongoDB Monitoring';
 $wb['do_not_try_rescue_mysql_txt'] = 'Deaktiviere MySQL Monitoring';
 $wb['do_not_try_rescue_mail_txt'] = 'Deaktiviere E-Mail Monitoring';
 $wb['rescue_description_txt'] = '<b>Information:</b> Falls Sie MySQL stoppen möchten, wählen Sie die Funktion \'Deaktiviere MySQL Monitoring\' und warten Sie 2 bis 3 Minuten. Wenn Sie nicht 2 bis 3 Miunten warten wird ISPConfig versuchen MySQL wieder zu starten.';
diff --git a/interface/web/admin/lib/lang/en_server_config.lng b/interface/web/admin/lib/lang/en_server_config.lng
index c4abee8..1f1ad0d 100644
--- a/interface/web/admin/lib/lang/en_server_config.lng
+++ b/interface/web/admin/lib/lang/en_server_config.lng
@@ -151,6 +151,7 @@
 $wb["php_fpm_socket_dir_error_empty"] = 'PHP-FPM socket directory is empty.';
 $wb["try_rescue_txt"] = 'Enable service monitoring and restart on failure';
 $wb["do_not_try_rescue_httpd_txt"] = 'Disable HTTPD monitoring';
+$wb["do_not_try_rescue_mongodb_txt"] = 'Disable MongoDB monitoring';
 $wb["do_not_try_rescue_mysql_txt"] = 'Disable MySQL monitoring';
 $wb["do_not_try_rescue_mail_txt"] = 'Disable Email monitoring';
 $wb["rescue_description_txt"] = '<b>Information:</b> If you want to shut down mysql you have to select the "Disable MySQL monitor" checkbox and then wait 2-3 minutes.<br>If you do not wait 2-3 minutes, rescue will try to restart mysql!';
@@ -190,4 +191,4 @@
 $wb['munin_password_txt'] = 'Munin Password';
 $wb['munin_url_error_regex'] = 'Invalid Munin URL';
 $wb['munin_url_note_txt'] = 'Placeholder:';
-?>
+?>
diff --git a/interface/web/admin/templates/server_config_rescue_edit.htm b/interface/web/admin/templates/server_config_rescue_edit.htm
index 778225b..28b5cb4 100644
--- a/interface/web/admin/templates/server_config_rescue_edit.htm
+++ b/interface/web/admin/templates/server_config_rescue_edit.htm
@@ -18,6 +18,12 @@
                 </div>
             </div>
             <div class="ctrlHolder">
+                <p class="label" style="width:300px">{tmpl_var name='do_not_try_rescue_mongodb_txt'}</p>
+                <div class="multiField" style="width:100px">
+                    {tmpl_var name='do_not_try_rescue_mongodb'}
+                </div>
+            </div>
+            <div class="ctrlHolder">
                 <p class="label" style="width:300px">{tmpl_var name='do_not_try_rescue_mysql_txt'}</p>
                 <div class="multiField" style="width:100px">
                     {tmpl_var name='do_not_try_rescue_mysql'}
@@ -30,15 +36,15 @@
                 </div>
             </div>
         </fieldset>
-            
+
         <tmpl_var name="rescue_description_txt">
-            
+
             <input type="hidden" name="id" value="{tmpl_var name='id'}">
-                
+
             <div class="buttonHolder buttons">
                 <button class="positive iconstxt icoPositive" type="button" value="{tmpl_var name='btn_save_txt'}" onclick="submitForm('pageForm','admin/server_config_edit.php');"><span>{tmpl_var name='btn_save_txt'}</span></button>
                 <button class="negative iconstxt icoNegative" type="button" value="{tmpl_var name='btn_cancel_txt'}" onclick="loadContent('admin/server_config_list.php');"><span>{tmpl_var name='btn_cancel_txt'}</span></button>
             </div>
     </div>
-  
-</div>
\ No newline at end of file
+
+</div>
diff --git a/interface/web/monitor/lib/lang/de.lng b/interface/web/monitor/lib/lang/de.lng
index cf9621f..a46050e 100644
--- a/interface/web/monitor/lib/lang/de.lng
+++ b/interface/web/monitor/lib/lang/de.lng
@@ -122,6 +122,7 @@
 $wb['monitor_services_pop_txt'] = 'POP3 Server:';
 $wb['monitor_services_imap_txt'] = 'IMAP Server:';
 $wb['monitor_services_mydns_txt'] = 'DNS Server:';
+$wb['monitor_services_mongodb_txt'] = 'MongoDB Server:';
 $wb['monitor_services_mysql_txt'] = 'MySQL Server:';
 $wb['monitor_settings_datafromdate_txt'] = 'Daten vom: ';
 $wb['monitor_settings_datetimeformat_txt'] = 'd.m.Y H:i';
@@ -134,6 +135,7 @@
 $wb['monitor_title_rkhunterlog_txt'] = 'RKHunter Protokoll';
 $wb['monitor_updates_nosupport_txt'] = 'Ihre Distribution wird für die Überwachung nicht unterstützt';
 $wb['monitor_title_fail2ban_txt'] = 'Fail2Ban Protokoll';
+$wb['monitor_title_mongodb_txt'] = 'MongoDB Protokoll';
 $wb['monitor_nosupportedraid1_txt'] = 'At the moment, we support mdadm or mpt-status for monitoring the RAID.<br>We cant find any of them at your server.<br><br>This means we can not support your RAID yet.';
 $wb['monitor_serverstate_beancounterok_txt'] = 'The beancounter is ok';
 $wb['monitor_serverstate_beancounterinfo_txt'] = 'There are vew failure in the beancounter';
@@ -144,6 +146,7 @@
 $wb['monitor_beancounter_nosupport_txt'] = 'This server is not a OpenVz VE and has no beancounter information';
 $wb['monitor_title_iptables_txt'] = 'IPTables Regeln';
 $wb['Show fail2ban-Log'] = 'Fail2ban Protokoll anzeigen';
+$wb['Show MongoDB-Log'] = 'MongoDB Protokoll anzeigen';
 $wb['Show IPTables'] = 'IPTables anzeigen';
 $wb['Show OpenVz VE BeanCounter'] = 'OpenVz VE BeanCounter anzeigen';
 $wb['Show Monit'] = 'Monit anzeigen';
diff --git a/interface/web/monitor/lib/lang/en.lng b/interface/web/monitor/lib/lang/en.lng
index 20cf1fb..ec5ca73 100644
--- a/interface/web/monitor/lib/lang/en.lng
+++ b/interface/web/monitor/lib/lang/en.lng
@@ -46,6 +46,7 @@
 $wb['Show RKHunter-Log'] = 'Show RKHunter-Log';
 $wb['Show Jobqueue'] = 'Show Jobqueue';
 $wb['Show fail2ban-Log'] = 'Show fail2ban-Log';
+$wb['Show MongoDB-Log'] = 'Show MongoDB-Log';
 $wb['Show IPTables'] = 'Show IPTables';
 $wb['Show OpenVz VE BeanCounter'] = 'Show OpenVz VE BeanCounter';
 $wb['monitor_general_serverstate_txt'] = 'Server State';
@@ -131,6 +132,7 @@
 $wb['monitor_services_pop_txt'] = 'POP3-Server:';
 $wb['monitor_services_imap_txt'] = 'IMAP-Server:';
 $wb['monitor_services_mydns_txt'] = 'DNS-Server:';
+$wb['monitor_services_mongodb_txt'] = 'MongoDB-Server:';
 $wb['monitor_services_mysql_txt'] = 'mySQL-Server:';
 $wb['monitor_settings_datafromdate_txt'] = 'Data from: ';
 $wb['monitor_settings_datetimeformat_txt'] = 'Y-m-d H:i';
@@ -142,6 +144,7 @@
 $wb['monitor_title_raidstate_txt'] = 'RAID Status';
 $wb['monitor_title_rkhunterlog_txt'] = 'RKHunter Log';
 $wb['monitor_title_fail2ban_txt'] = 'Fail2Ban Log';
+$wb['monitor_title_mongodb_txt'] = 'MongoDB Log';
 $wb['monitor_title_iptables_txt'] = 'IPTables Rules';
 $wb['monitor_title_beancounter_txt'] = 'OpenVz VE BeanCounter';
 $wb['monitor_updates_nosupport_txt'] = 'Your distribution is not supported for this monitoring';
diff --git a/interface/web/monitor/lib/module.conf.php b/interface/web/monitor/lib/module.conf.php
index 1d4e5e1..c019b84 100644
--- a/interface/web/monitor/lib/module.conf.php
+++ b/interface/web/monitor/lib/module.conf.php
@@ -190,6 +190,11 @@
                   'link'	=> 'monitor/show_data.php?type=fail2ban',
                   'html_id' => 'fai2ban');
 
+$items[] = array( 'title' 	=> "Show MongoDB-Log",
+                  'target' 	=> 'content',
+                  'link'	=> 'monitor/show_data.php?type=mongodb',
+                  'html_id' => 'mongodb');
+
 $items[] = array( 'title' 	=> "Show IPTables",
                   'target' 	=> 'content',
                   'link'	=> 'monitor/show_data.php?type=iptables',
@@ -198,4 +203,4 @@
 $module["nav"][] = array(	'title'	=> 'Logfiles',
                             'open' 	=> 1,
                             'items'	=> $items);
-?>
\ No newline at end of file
+?>
diff --git a/interface/web/monitor/show_data.php b/interface/web/monitor/show_data.php
index 1cd4baf..92c66a4 100644
--- a/interface/web/monitor/show_data.php
+++ b/interface/web/monitor/show_data.php
@@ -124,6 +124,13 @@
         $title = $app->lng("monitor_title_fail2ban_txt") . ' (' . $monTransSrv . ' : ' . $_SESSION['monitor']['server_name'] . ')';
         $description = '';
         break;
+    case 'mongodb':
+        $template = 'templates/show_data.htm';
+        $output .= $app->tools_monitor->showMongoDB();
+        $time = $app->tools_monitor->getDataTime('log_mongodb');
+        $title = $app->lng("monitor_title_mongodb_txt") . ' (' . $monTransSrv . ' : ' . $_SESSION['monitor']['server_name'] . ')';
+        $description = '';
+        break;
     case 'iptables':
         $template = 'templates/show_data.htm';
         $output .= $app->tools_monitor->showIPTables();
diff --git a/interface/web/sites/database_user_edit.php b/interface/web/sites/database_user_edit.php
index 1b71196..4f6979f 100644
--- a/interface/web/sites/database_user_edit.php
+++ b/interface/web/sites/database_user_edit.php
@@ -57,17 +57,17 @@
 		 * If the names are restricted -> remove the restriction, so that the
 		 * data can be edited
 		 */
-		
+
 		//* Get the database user prefix
 		$app->uses('getconf,tools_sites');
 		$global_config = $app->getconf->get_global_config('sites');
 		$dbuser_prefix = $app->tools_sites->replacePrefix($global_config['dbuser_prefix'], $this->dataRecord);
-		
+
         if ($_SESSION["s"]["user"]["typ"] != 'admin' && $app->auth->has_clients($_SESSION['s']['user']['userid'])) {
 			// Get the limits of the client
 			$client_group_id = $_SESSION["s"]["user"]["default_group"];
 			$client = $app->db->queryOneRecord("SELECT client.company_name, client.contact_name, client.client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
-            
+
             // Fill the client select field
             $sql = "SELECT sys_group.groupid, sys_group.name, CONCAT(IF(client.company_name != '', CONCAT(client.company_name, ' :: '), ''), client.contact_name, ' (', client.username, IF(client.customer_no != '', CONCAT(', ', client.customer_no), ''), ')') as contactname FROM sys_group, client WHERE sys_group.client_id = client.client_id AND client.parent_client_id = ".$client['client_id']." ORDER BY sys_group.name";
             $records = $app->db->queryAllRecords($sql);
@@ -96,24 +96,24 @@
 			}
 			$app->tpl->setVar("client_group_id",$client_select);
         }
-        
-        
+
+
 		if ($this->dataRecord['database_user'] != ""){
 			/* REMOVE the restriction */
 			$app->tpl->setVar("database_user", $app->tools_sites->removePrefix($this->dataRecord['database_user'], $this->dataRecord['database_user_prefix'], $dbuser_prefix));
 		}
-		
-    
+
+
 		$app->tpl->setVar("database_user_prefix", $app->tools_sites->getPrefix($this->dataRecord['database_user_prefix'], $dbuser_prefix, $global_config['dbuser_prefix']));
-		
+
 		parent::onShowEnd();
 	}
-    
+
     function onSubmit() {
         global $app;
-        
+
         if($_SESSION['s']['user']['typ'] != 'admin' && !$app->auth->has_clients($_SESSION['s']['user']['userid'])) unset($this->dataRecord["client_group_id"]);
-        
+
         parent::onSubmit();
     }
 
@@ -126,35 +126,40 @@
 		$dbuser_prefix = $app->tools_sites->replacePrefix($global_config['dbuser_prefix'], $this->dataRecord);
 
         $this->oldDataRecord = $app->db->queryOneRecord("SELECT * FROM web_database_user WHERE database_user_id = '".$this->id."'");
-        
+
         $dbuser_prefix = $app->tools_sites->getPrefix($this->oldDataRecord['database_user_prefix'], $dbuser_prefix);
         $this->dataRecord['database_user_prefix'] = $dbuser_prefix;
-        
+
 		//* Database username shall not be empty
 		if($this->dataRecord['database_user'] == '') $app->tform->errorMessage .= $app->tform->wordbook["database_user_error_empty"].'<br />';
 
 		if(strlen($dbuser_prefix . $this->dataRecord['database_user']) > 16) $app->tform->errorMessage .= str_replace('{user}',$dbuser_prefix . $this->dataRecord['database_user'],$app->tform->wordbook["database_user_error_len"]).'<br />';
-		
+
 		//* Check database user against blacklist
 		$dbuser_blacklist = array($conf['db_user'],'mysql','root');
 		if(in_array($dbuser_prefix . $this->dataRecord['database_user'],$dbuser_blacklist)) {
 			$app->tform->errorMessage .= $app->lng('Database user not allowed.').'<br />';
 		}
-		
+
 		if ($app->tform->errorMessage == ''){
 			/* restrict the names if there is no error */
             /* crop user and db names if they are too long -> mysql: user: 16 chars / db: 64 chars */
 			$this->dataRecord['database_user'] = substr($dbuser_prefix . $this->dataRecord['database_user'], 0, 16);
 		}
-		
+
+		/* prepare password for MongoDB */
+		// TODO: this still doens't work as when only the username changes we have no database_password.
+		// taking the one from oldData doesn't work as it's encrypted...shit!
+		$this->dataRecord['database_password_mongo'] = $this->dataRecord['database_user'].":mongo:".$this->dataRecord['database_password'];
+
         $this->dataRecord['server_id'] = 0; // we need this on all servers
-        
+
 		parent::onBeforeUpdate();
 	}
 
 	function onBeforeInsert() {
 		global $app, $conf, $interfaceConf;
-		
+
 		//* Database username shall not be empty
 		if($this->dataRecord['database_user'] == '') $app->tform->errorMessage .= $app->tform->wordbook["database_user_error_empty"].'<br />';
 
@@ -162,11 +167,11 @@
 		$app->uses('getconf,tools_sites');
 		$global_config = $app->getconf->get_global_config('sites');
 		$dbuser_prefix = $app->tools_sites->replacePrefix($global_config['dbuser_prefix'], $this->dataRecord);
-		
+
         $this->dataRecord['database_user_prefix'] = $dbuser_prefix;
-        
+
 		if(strlen($dbuser_prefix . $this->dataRecord['database_user']) > 16) $app->tform->errorMessage .= str_replace('{user}',$dbuser_prefix . $this->dataRecord['database_user'],$app->tform->wordbook["database_user_error_len"]).'<br />';
-		
+
 		//* Check database user against blacklist
 		$dbuser_blacklist = array($conf['db_user'],'mysql','root');
 		if(is_array($dbuser_blacklist) && in_array($dbuser_prefix . $this->dataRecord['database_user'],$dbuser_blacklist)) {
@@ -178,15 +183,18 @@
 		if ($app->tform->errorMessage == ''){
 			$this->dataRecord['database_user'] = substr($dbuser_prefix . $this->dataRecord['database_user'], 0, 16);
 		}
-		
-        $this->dataRecord['server_id'] = 0; // we need this on all servers
-        
+
+		$this->dataRecord['server_id'] = 0; // we need this on all servers
+
+		/* prepare password for MongoDB */
+		$this->dataRecord['database_password_mongo'] = $this->dataRecord['database_user'].":mongo:".$this->dataRecord['database_password'];
+
 		parent::onBeforeInsert();
 	}
 
 	function onAfterInsert() {
 		global $app, $conf;
-		
+
 		if($_SESSION["s"]["user"]["typ"] == 'admin' && isset($this->dataRecord["client_group_id"])) {
 			$client_group_id = $app->functions->intval($this->dataRecord["client_group_id"]);
 			$app->db->query("UPDATE web_database_user SET sys_groupid = $client_group_id, sys_perm_group = 'riud' WHERE database_user_id = ".$this->id);
@@ -208,9 +216,9 @@
 			$client_group_id = $app->functions->intval($this->dataRecord["client_group_id"]);
 			$app->db->query("UPDATE web_database_user SET sys_groupid = $client_group_id, sys_perm_group = 'riud' WHERE database_user_id = ".$this->id);
 		}
-		
+
 		/*$password = $app->db->queryOneRecord("SELECT database_password FROM web_database_user WHERE database_user_id = ".$this->id);
-        
+
         $records = $app->db->queryAllRecords("SELECT DISTINCT server_id FROM web_database WHERE database_user_id = '".$app->functions->intval($this->id)."' UNION SELECT DISTINCT server_id FROM web_database WHERE database_ro_user_id = '".$app->functions->intval($this->id)."'");
         foreach($records as $rec) {
             $new_rec = $this->dataRecord;
diff --git a/interface/web/sites/form/database.tform.php b/interface/web/sites/form/database.tform.php
index e390f72..4cbfa12 100644
--- a/interface/web/sites/form/database.tform.php
+++ b/interface/web/sites/form/database.tform.php
@@ -29,7 +29,7 @@
 	Hint:
 	The ID field of the database table is not part of the datafield definition.
 	The ID field must be always auto incement (int or bigint).
-	
+
 	Search:
 	- searchable = 1 or searchable = 2 include the field in the search
 	- searchable = 1: this field will be the title of the search result
@@ -89,7 +89,10 @@
 			'datatype'	=> 'VARCHAR',
 			'formtype'	=> 'SELECT',
 			'default'	=> 'y',
-			'value'		=> array('mysql' => 'MySQL')
+			'value'		=> array(
+			                  'mongo' => 'MongoDB',
+			                  'mysql' => 'MySQL'
+			               )
 		),
 		'database_name' => array (
 			'datatype'	=> 'VARCHAR',
@@ -174,4 +177,4 @@
 );
 
 
-?>
\ No newline at end of file
+?>
diff --git a/interface/web/sites/form/database_user.tform.php b/interface/web/sites/form/database_user.tform.php
index fa2b2d3..d2a2def 100644
--- a/interface/web/sites/form/database_user.tform.php
+++ b/interface/web/sites/form/database_user.tform.php
@@ -29,7 +29,7 @@
 	Hint:
 	The ID field of the database table is not part of the datafield definition.
 	The ID field must be always auto incement (int or bigint).
-	
+
 	Search:
 	- searchable = 1 or searchable = 2 include the field in the search
 	- searchable = 1: this field will be the title of the search result
@@ -108,6 +108,14 @@
 			'width'		=> '30',
 			'maxlength'	=> '255'
 		),
+		'database_password_mongo' => array (
+			'datatype'	=> 'VARCHAR',
+			'formtype'	=> 'PASSWORD',
+			'default'	=> '',
+			'value'		=> '',
+			'width'		=> '30',
+			'maxlength'	=> '255'
+		),
 	##################################
 	# ENDE Datatable fields
 	##################################
diff --git a/interface/web/sites/lib/lang/de_database_admin_list.lng b/interface/web/sites/lib/lang/de_database_admin_list.lng
index 3f7542a..3b11b2c 100644
--- a/interface/web/sites/lib/lang/de_database_admin_list.lng
+++ b/interface/web/sites/lib/lang/de_database_admin_list.lng
@@ -2,6 +2,7 @@
 $wb['list_head_txt'] = 'Datenbank';
 $wb['active_txt'] = 'Aktiv';
 $wb['remote_access_txt'] = 'Remotezugriff';
+$wb['type_txt'] = 'Typ';
 $wb['server_id_txt'] = 'Server';
 $wb['database_user_txt'] = 'Datenbank Benutzer';
 $wb['database_name_txt'] = 'Datenbankname';
diff --git a/interface/web/sites/lib/lang/de_database_list.lng b/interface/web/sites/lib/lang/de_database_list.lng
index bae444c..89caea3 100644
--- a/interface/web/sites/lib/lang/de_database_list.lng
+++ b/interface/web/sites/lib/lang/de_database_list.lng
@@ -2,6 +2,7 @@
 $wb['list_head_txt'] = 'Datenbank';
 $wb['active_txt'] = 'Aktiv';
 $wb['remote_access_txt'] = 'Remotezugriff';
+$wb['type_txt'] = 'Typ';
 $wb['server_id_txt'] = 'Server';
 $wb['database_name_txt'] = 'Datenbankname';
 $wb['add_new_record_txt'] = 'Neue Datenbank hinzufügen';
diff --git a/interface/web/sites/lib/lang/de_web_backup_list.lng b/interface/web/sites/lib/lang/de_web_backup_list.lng
index 4cc06d8..499fb4f 100644
--- a/interface/web/sites/lib/lang/de_web_backup_list.lng
+++ b/interface/web/sites/lib/lang/de_web_backup_list.lng
@@ -10,6 +10,7 @@
 $wb['restore_confirm_txt'] = 'Die Wiederherstellung wird existierende Dateien in Ihrer Website überschreiben. Möchten Sie dieses Backup wirklich zurückspielen?';
 $wb['download_pending_txt'] = 'Es liegt bereits ein Backup Download Job an.';
 $wb['restore_pending_txt'] = 'Es liegt bereits ein Backup Wiederherstellungs Job an.';
+$wb['backup_type_mongodb'] = 'MongoDB Datenbank';
 $wb['backup_type_mysql'] = 'MySQL Datenbank';
 $wb['backup_type_web'] = 'Webseiten Dateien';
 ?>
diff --git a/interface/web/sites/lib/lang/en_database_admin_list.lng b/interface/web/sites/lib/lang/en_database_admin_list.lng
index a49adcd..5d0ad7a 100644
--- a/interface/web/sites/lib/lang/en_database_admin_list.lng
+++ b/interface/web/sites/lib/lang/en_database_admin_list.lng
@@ -2,9 +2,10 @@
 $wb["list_head_txt"] = 'Database';
 $wb["active_txt"] = 'Active';
 $wb["remote_access_txt"] = 'Remote Access';
+$wb['type_txt'] = 'Type';
 $wb["server_id_txt"] = 'Server';
 $wb["database_user_txt"] = 'Database user';
 $wb["database_name_txt"] = 'Database name';
 $wb["add_new_record_txt"] = 'Add new Database';
 $wb["sys_groupid_txt"] = 'Client';
-?>
\ No newline at end of file
+?>
diff --git a/interface/web/sites/lib/lang/en_database_list.lng b/interface/web/sites/lib/lang/en_database_list.lng
index ff599d2..0a8d6ff 100644
--- a/interface/web/sites/lib/lang/en_database_list.lng
+++ b/interface/web/sites/lib/lang/en_database_list.lng
@@ -2,8 +2,9 @@
 $wb["list_head_txt"] = 'Database';
 $wb["active_txt"] = 'Active';
 $wb["remote_access_txt"] = 'Remote Access';
+$wb['type_txt'] = 'Type';
 $wb["server_id_txt"] = 'Server';
 $wb["database_user_txt"] = 'Database user';
 $wb["database_name_txt"] = 'Database name';
 $wb["add_new_record_txt"] = 'Add new Database';
-?>
\ No newline at end of file
+?>
diff --git a/interface/web/sites/lib/lang/en_web_backup_list.lng b/interface/web/sites/lib/lang/en_web_backup_list.lng
index 2b65944..aea21f8 100644
--- a/interface/web/sites/lib/lang/en_web_backup_list.lng
+++ b/interface/web/sites/lib/lang/en_web_backup_list.lng
@@ -11,7 +11,8 @@
 $wb['restore_confirm_txt'] = 'Restoring will overwrite existing files in your website. Do you really want to restore this backup?';
 $wb['download_pending_txt'] = 'There is already a pending backup download job.';
 $wb['restore_pending_txt'] = 'There is already a pending backup restore job.';
-$wb['backup_type_mysql'] = 'MySQL Database';
-$wb['backup_type_web'] = 'Website files';
-
-?>
+$wb['backup_type_mongodb'] = 'MongoDB Database';
+$wb['backup_type_mysql'] = 'MySQL Database';
+$wb['backup_type_web'] = 'Website files';
+
+?>
diff --git a/interface/web/sites/list/database.list.php b/interface/web/sites/list/database.list.php
index cbb51a8..f512bef 100644
--- a/interface/web/sites/list/database.list.php
+++ b/interface/web/sites/list/database.list.php
@@ -70,6 +70,19 @@
 							'width'		=> "",
 							'value'		=> array('y' => "<div id=\"ir-Yes\" class=\"swap\"><span>Yes</span></div>",'n' => "<div class=\"swap\" id=\"ir-No\"><span>No</span></div>"));
 
+$liste["item"][] = array(	'field'		=> "type",
+							'datatype'	=> "VARCHAR",
+							'formtype'	=> "SELECT",
+							'op'		=> "=",
+							'prefix'	=> "",
+							'suffix'	=> "",
+							'width'		=> "",
+							'value'		=> array(
+							                  'mongo' => "MongoDB",
+							                  'mysql' => "MySQL"
+							               )
+						);
+
 if($_SESSION['s']['user']['typ'] == 'admin') {
 $liste["item"][] = array(	'field'		=> "sys_groupid",
 							'datatype'	=> "INTEGER",
@@ -123,4 +136,4 @@
                             'width'        => "",
                             'value'        => "");
 
-?>
\ No newline at end of file
+?>
diff --git a/interface/web/sites/templates/database_admin_list.htm b/interface/web/sites/templates/database_admin_list.htm
index e44616c..2f96738 100644
--- a/interface/web/sites/templates/database_admin_list.htm
+++ b/interface/web/sites/templates/database_admin_list.htm
@@ -19,6 +19,7 @@
                     <tr class="caption">
                         <th class="tbl_col_active" scope="col"><tmpl_var name="active_txt"></th>
                         <th class="tbl_col_remote_access" scope="col"><tmpl_var name="remote_access_txt"></th>
+                        <th class="tbl_col_type" scope="col"><tmpl_var name="type_txt"></th>
                         <th class="tbl_col_sys_groupid" scope="col"><tmpl_var name="sys_groupid_txt"></th>
                         <th class="tbl_col_server_id" scope="col"><tmpl_var name="server_id_txt"></th>
                         <th class="tbl_col_database_user_id" scope="col"><tmpl_var name="database_user_txt"></th>
@@ -28,6 +29,7 @@
                     <tr class="filter">
                         <td class="tbl_col_active"><select name="search_active">{tmpl_var name='search_active'}</select></td>
                         <td class="tbl_col_remote_access"><select name="search_remote_access">{tmpl_var name='search_remote_access'}</select></td>
+                        <td class="tbl_col_type"><select name="search_type">{tmpl_var name='search_type'}</select></td>
                         <td class="tbl_col_sys_groupid"><select name="search_sys_groupid">{tmpl_var name='search_sys_groupid'}</select></td>
                         <td class="tbl_col_server_id"><select name="search_server_id">{tmpl_var name='search_server_id'}</select></td>
                         <td class="tbl_col_database_user"><select name="search_database_user_id">{tmpl_var name='search_database_user_id'}</select></td>
@@ -42,6 +44,7 @@
                         <tr class="tbl_row_<tmpl_if name='__EVEN__'}even<tmpl_else>uneven</tmpl_if>">
                             <td class="tbl_col_active"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="active"}</a></td>
                             <td class="tbl_col_remote_access"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="remote_access"}</a></td>
+                            <td class="tbl_col_type"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="type"}</a></td>
                             <td class="tbl_col_sys_groupid"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="sys_groupid"}</a></td>
                             <td class="tbl_col_server_id"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="server_id"}</a></td>
                             <td class="tbl_col_database_user"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="database_user_id"}</a></td>
@@ -51,23 +54,23 @@
                                     <a class="button icons16 icoDbAdmin" href="sites/database_phpmyadmin.php?id={tmpl_var name='id'}" target="phpmyadmin"><span>{tmpl_var name='admin_txt'}</span></a>
                                 </tmpl_if>
                                 <a class="button icons16 icoEdit" href="javascript: loadContent('sites/database_edit.php?id={tmpl_var name='id'}');"><span>{tmpl_var name='edit_txt'}</span></a>
-                                <a class="button icons16 icoDelete" href="javascript: del_record('sites/database_del.php?id={tmpl_var name='id'}&phpsessid={tmpl_var name='phpsessid'}','{tmpl_var name='delete_confirmation'}');"><span>{tmpl_var name='delete_txt'}</span></a>
+                                <a class="button icons16 icoDelete" href="javascript: del_record('sites/database_del.php?id={tmpl_var name='id'}&amp;phpsessid={tmpl_var name='phpsessid'}','{tmpl_var name='delete_confirmation'}');"><span>{tmpl_var name='delete_txt'}</span></a>
                             </td>
                         </tr>
                     </tmpl_loop>
                     <tmpl_unless name="records">
                         <tr class="tbl_row_noresults tbl_row_<tmpl_if name='__EVEN__'}even<tmpl_else>uneven</tmpl_if>">
-                            <td colspan="7">{tmpl_var name='globalsearch_noresults_text_txt'}</td>
+                            <td colspan="8">{tmpl_var name='globalsearch_noresults_text_txt'}</td>
                         </tr>
                     </tmpl_unless>
                 </tbody>
                 <tfoot>
                     <tr>
-                        <td class="tbl_footer tbl_paging" colspan="7"><tmpl_var name="paging"></td>
+                        <td class="tbl_footer tbl_paging" colspan="8"><tmpl_var name="paging"></td>
                     </tr>
                 </tfoot>
             </table>
         </fieldset>
     </div>
 
-</div>
\ No newline at end of file
+</div>
diff --git a/interface/web/sites/templates/database_list.htm b/interface/web/sites/templates/database_list.htm
index 0e80212..888f3ba 100644
--- a/interface/web/sites/templates/database_list.htm
+++ b/interface/web/sites/templates/database_list.htm
@@ -36,6 +36,7 @@
                     <tr class="caption">
                         <th class="tbl_col_active" scope="col"><tmpl_var name="active_txt"></th>
                         <th class="tbl_col_remote_access" scope="col"><tmpl_var name="remote_access_txt"></th>
+                        <th class="tbl_col_type" scope="col"><tmpl_var name="type_txt"></th>
                         <th class="tbl_col_server_id" scope="col"><tmpl_var name="server_id_txt"></th>
                         <th class="tbl_col_database_user_id" scope="col"><tmpl_var name="database_user_txt"></th>
                         <th class="tbl_col_database_name" scope="col"><tmpl_var name="database_name_txt"></th>
@@ -44,6 +45,7 @@
                     <tr class="filter">
                         <td class="tbl_col_active"><select name="search_active">{tmpl_var name='search_active'}</select></td>
                         <td class="tbl_col_remote_access"><select name="search_remote_access">{tmpl_var name='search_remote_access'}</select></td>
+                        <td class="tbl_col_type"><select name="search_type">{tmpl_var name='search_type'}</select></td>
                         <td class="tbl_col_server_id"><select name="search_server_id">{tmpl_var name='search_server_id'}</select></td>
                         <td class="tbl_col_database_user_id"><select name="search_database_user_id">{tmpl_var name='search_database_user_id'}</select></td>
                         <td class="tbl_col_database_name"><input type="text" name="search_database_name" value="{tmpl_var name='search_database_name'}"/></td>
@@ -57,6 +59,7 @@
                         <tr class="tbl_row_<tmpl_if name='__EVEN__'}even<tmpl_else>uneven</tmpl_if>">
                             <td class="tbl_col_active"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="active"}</a></td>
                             <td class="tbl_col_remote_access"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="remote_access"}</a></td>
+                            <td class="tbl_col_type"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="type"}</a></td>
                             <td class="tbl_col_server_id"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="server_id"}</a></td>
                             <td class="tbl_col_database_user"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="database_user_id"}</a></td>
                             <td class="tbl_col_database_name"><a href="#" onclick="loadContent('sites/database_edit.php?id={tmpl_var name='id'}');">{tmpl_var name="database_name"}</a></td>
@@ -65,23 +68,23 @@
                                     <a class="button icons16 icoDbAdmin" href="sites/database_phpmyadmin.php?id={tmpl_var name='id'}" target="phpmyadmin"><span>{tmpl_var name='admin_txt'}</span></a>
                                 </tmpl_if>
                                 <a class="button icons16 icoEdit" href="javascript: loadContent('sites/database_edit.php?id={tmpl_var name='id'}');"><span>{tmpl_var name='edit_txt'}</span></a>
-                                <a class="button icons16 icoDelete" href="javascript: del_record('sites/database_del.php?id={tmpl_var name='id'}&phpsessid={tmpl_var name='phpsessid'}','{tmpl_var name='delete_confirmation'}');"><span>{tmpl_var name='delete_txt'}</span></a>
+                                <a class="button icons16 icoDelete" href="javascript: del_record('sites/database_del.php?id={tmpl_var name='id'}&amp;phpsessid={tmpl_var name='phpsessid'}','{tmpl_var name='delete_confirmation'}');"><span>{tmpl_var name='delete_txt'}</span></a>
                             </td>
                         </tr>
                     </tmpl_loop>
                     <tmpl_unless name="records">
                         <tr class="tbl_row_noresults tbl_row_<tmpl_if name='__EVEN__'}even<tmpl_else>uneven</tmpl_if>">
-                            <td colspan="6">{tmpl_var name='globalsearch_noresults_text_txt'}</td>
+                            <td colspan="7">{tmpl_var name='globalsearch_noresults_text_txt'}</td>
                         </tr>
                     </tmpl_unless>
                 </tbody>
                 <tfoot>
                     <tr>
-                        <td class="tbl_footer tbl_paging" colspan="6"><tmpl_var name="paging"></td>
+                        <td class="tbl_footer tbl_paging" colspan="7"><tmpl_var name="paging"></td>
                     </tr>
                 </tfoot>
             </table>
         </fieldset>
     </div>
 
-</div>
\ No newline at end of file
+</div>
diff --git a/server/cron_daily.php b/server/cron_daily.php
index 9d7ca00..21d8f84 100644
--- a/server/cron_daily.php
+++ b/server/cron_daily.php
@@ -54,7 +54,7 @@
 foreach($records as $rec) {
 	if(@is_file($rec['maildir'].'/ispconfig_mailsize')) {
         $parse_mail_log = false;
-        
+
 		// rename file
 		rename($rec['maildir'].'/ispconfig_mailsize',$rec['maildir'].'/ispconfig_mailsize_save');
 
@@ -92,15 +92,15 @@
     $mailbox_traffic = array();
     $mail_boxes = array();
     $mail_rewrites = array(); // we need to read all mail aliases and forwards because the address in amavis is not always the mailbox address
-    
+
     function parse_mail_log_line($line) {
         //Oct 31 17:35:48 mx01 amavis[32014]: (32014-05) Passed CLEAN, [IPv6:xxxxx] [IPv6:xxxxx] <xxx@yyyy> -> <aaaa@bbbb>, Message-ID: <xxxx@yyyyy>, mail_id: xxxxxx, Hits: -1.89, size: 1591, queued_as: xxxxxxx, 946 ms
-        
+
         if(preg_match('/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+[^ ]+\s+amavis.* <([^>]+)>\s+->\s+((<[^>]+>,)+) .*Message-ID:\s+<([^>]+)>.* size:\s+(\d+),.*$/', $line, $matches) == false) return false;
-        
+
         $timestamp = strtotime($matches[1]);
         if(!$timestamp) return false;
-        
+
         $to = array();
         $recipients = explode(',', $matches[3]);
         foreach($recipients as $recipient) {
@@ -108,15 +108,15 @@
             if(!$recipient || $recipient == $matches[2]) continue;
             $to[] = $recipient;
         }
-        
+
         return array('line' => $line, 'timestamp' => $timestamp, 'size' => $matches[6], 'from' => $matches[2], 'to' => $to, 'message-id' => $matches[5]);
     }
 
     function add_mailbox_traffic(&$traffic_array, $address, $traffic) {
         global $mail_boxes, $mail_rewrites;
-        
+
         $address = strtolower($address);
-        
+
         if(in_array($address, $mail_boxes) == true) {
             if(!isset($traffic_array[$address])) $traffic_array[$address] = 0;
             $traffic_array[$address] += $traffic;
@@ -146,17 +146,17 @@
             }
         }
     }
-    
+
     $state_file = dirname(__FILE__) . '/mail_log_parser.state';
     $prev_line = false;
     $last_line = false;
     $cur_line = false;
-    
+
     if(file_exists($state_file)) {
         $prev_line = parse_mail_log_line(trim(file_get_contents($state_file)));
         //if($prev_line) echo "continuing from previous run, log position: " . $prev_line['message-id'] . " at " . strftime('%d.%m.%Y %H:%M:%S', $prev_line['timestamp']) . "\n";
     }
-    
+
     if(file_exists('/var/log/mail.log')) {
         $fp = fopen('/var/log/mail.log', 'r');
         //echo "Parsing mail.log...\n";
@@ -166,7 +166,7 @@
             //if($l % 1000 == 0) echo "\rline $l";
             $cur_line = parse_mail_log_line($line);
             if(!$cur_line) continue;
-            
+
             if($prev_line) {
                 // check if this line has to be processed
                 if($cur_line['timestamp'] < $prev_line['timestamp']) {
@@ -178,7 +178,7 @@
                     continue;
                 }
             }
-            
+
             add_mailbox_traffic($mailbox_traffic, $cur_line['from'], $cur_line['size']);
             foreach($cur_line['to'] as $to) {
                 add_mailbox_traffic($mailbox_traffic, $to, $cur_line['size']);
@@ -188,7 +188,7 @@
         fclose($fp);
         //echo "\n";
     }
-    
+
     if($parse_mail_log == true && file_exists('/var/log/mail.log.1')) {
         $fp = fopen('/var/log/mail.log.1', 'r');
         //echo "Parsing mail.log.1...\n";
@@ -198,7 +198,7 @@
             //if($l % 1000 == 0) echo "\rline $l";
             $cur_line = parse_mail_log_line($line);
             if(!$cur_line) continue;
-            
+
             if($prev_line) {
                 // check if this line has to be processed
                 if($cur_line['timestamp'] < $prev_line['timestamp']) continue; // already processed
@@ -207,7 +207,7 @@
                     continue;
                 }
             }
-            
+
             add_mailbox_traffic($mailbox_traffic, $cur_line['from'], $cur_line['size']);
             foreach($cur_line['to'] as $to) {
                 add_mailbox_traffic($mailbox_traffic, $to, $cur_line['size']);
@@ -218,7 +218,7 @@
     }
     unset($mail_rewrites);
     unset($mail_boxes);
-    
+
     // Save the traffic stats in the sql database
     $tstamp = date('Y-m');
     $sql = "SELECT mailuser_id,email FROM mail_user WHERE server_id = ".$conf['server_id'];
@@ -238,7 +238,7 @@
             //echo $sql;
         }
     }
-    
+
     unset($mailbox_traffic);
     if($last_line) file_put_contents($state_file, $last_line);
 }
@@ -278,7 +278,7 @@
 foreach($records as $rec) {
 	//$yesterday = date('Ymd',time() - 86400);
 	$yesterday = date('Ymd',strtotime("-1 day", time()));
-	
+
     $log_folder = 'log';
     if($rec['type'] == 'vhostsubdomain') {
         $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = '.intval($rec['parent_domain_id']));
@@ -330,7 +330,7 @@
 foreach($records as $rec) {
 	//$yesterday = date('Ymd',time() - 86400);
 	$yesterday = date('Ymd',strtotime("-1 day", time()));
-	
+
     $log_folder = 'log';
     if($rec['type'] == 'vhostsubdomain') {
         $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = '.intval($rec['parent_domain_id']));
@@ -452,7 +452,7 @@
 
 	//* create traffic statistics based on yesterdays access log file
 	$yesterday = date('Ymd',time() - 86400);
-	
+
     $log_folder = 'log';
     if($rec['type'] == 'vhostsubdomain') {
         $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = '.intval($rec['parent_domain_id']));
@@ -461,7 +461,7 @@
         $log_folder .= '/' . $subdomain_host;
         unset($tmp);
     }
-    
+
     $logfile = $rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log';
 	$total_bytes = 0;
 
@@ -646,10 +646,10 @@
 #########
 function send_notification_email($template, $placeholders, $recipients) {
     global $conf;
-    
+
     if(!is_array($recipients) || count($recipients) < 1) return false;
     if(!is_array($placeholders)) $placeholders = array();
-    
+
     if(file_exists($conf['rootpath'].'/conf-custom/mail/' . $template . '_'.$conf['language'].'.txt')) {
         $lines = file($conf['rootpath'].'/conf-custom/mail/' . $template . '_'.$conf['language'].'.txt');
     } elseif(file_exists($conf['rootpath'].'/conf-custom/mail/' . $template . '_en.txt')) {
@@ -659,7 +659,7 @@
     } else {
         $lines = file($conf['rootpath'].'/conf/mail/' . $template . '_en.txt');
     }
-    
+
     //* get mail headers, subject and body
     $mailHeaders = '';
     $mailBody = '';
@@ -680,12 +680,12 @@
         }
     }
     $mailBody = trim($mailBody);
-    
+
     //* Replace placeholders
     $mailHeaders = strtr($mailHeaders, $placeholders);
     $mailSubject = strtr($mailSubject, $placeholders);
     $mailBody = strtr($mailBody, $placeholders);
-    
+
     for($r = 0; $r < count($recipients); $r++) {
         mail($recipients[$r], $mailSubject, $mailBody, $mailHeaders);
     }
@@ -694,7 +694,7 @@
     unset($mailHeaders);
     unset($mailBody);
     unset($lines);
-    
+
     return true;
 }
 
@@ -706,7 +706,7 @@
 if ($app->dbmaster == $app->db) {
 
 	$global_config = $app->getconf->get_global_config('mail');
-	
+
 	$current_month = date('Y-m');
 
 	//* Check website traffic quota
@@ -739,19 +739,19 @@
 			if($web_traffic_quota > 0 && $web_traffic > $web_traffic_quota) {
 				$app->dbmaster->datalogUpdate('web_domain', "traffic_quota_lock = 'y',active = 'n'", 'domain_id', $rec['domain_id']);
 				$app->log('Traffic quota for '.$rec['domain'].' exceeded. Disabling website.',LOGLEVEL_DEBUG);
-				
+
 				//* Send traffic notifications
 				if($rec['traffic_quota_lock'] != 'y' && ($web_config['overtraffic_notify_admin'] == 'y' || $web_config['overtraffic_notify_client'] == 'y')) {
-                    
-                    $placeholders = array('{domain}' => $rec['domain'],
-                                          '{admin_mail}' => $global_config['admin_mail']);
-                    
+
+					$placeholders = array('{domain}' => $rec['domain'],
+										  '{admin_mail}' => $global_config['admin_mail']);
+
 					$recipients = array();
-                    //* send email to admin
+					//* send email to admin
 					if($global_config['admin_mail'] != '' && $web_config['overtraffic_notify_admin'] == 'y') {
 						$recipients[] = $global_config['admin_mail'];
 					}
-					
+
 					//* Send email to client
 					if($web_config['overtraffic_notify_client'] == 'y') {
 						$client_group_id = $rec["sys_groupid"];
@@ -760,11 +760,10 @@
 							$recipients[] = $client['email'];
 						}
 					}
-                    
-                    send_notification_email('web_traffic_notification', $placeholders, $recipients);
+
+					send_notification_email('web_traffic_notification', $placeholders, $recipients);
 				}
-				
-				
+
 			} else {
 				//* unlock the website, if traffic is lower then quota
 				if($rec['traffic_quota_lock'] == 'y') {
@@ -791,7 +790,7 @@
 	$sql = "SELECT domain_id,sys_groupid,domain,system_user,last_quota_notification,DATEDIFF(CURDATE(), last_quota_notification) as `notified_before` FROM web_domain WHERE (type = 'vhost' OR type = 'vhostsubdomain')";
 	$records = $app->db->queryAllRecords($sql);
 	if(is_array($records) && !empty($records)) {
-	
+
 		$tmp_rec =  $app->db->queryAllRecords("SELECT data from monitor_data WHERE type = 'harddisk_quota' ORDER BY created DESC");
 		$monitor_data = array();
 		if(is_array($tmp_rec)) {
@@ -799,18 +798,18 @@
 				$monitor_data = array_merge_recursive($monitor_data,unserialize($app->db->unquote($tmp_mon['data'])));
 			}
 		}
-		
+
 		foreach($records as $rec) {
 
 			//$web_hd_quota = $rec['hd_quota'];
 			$domain = $rec['domain'];
-			
+
 			$username = $rec['system_user'];
 			$rec['used'] = $monitor_data['user'][$username]['used'];
 			$rec['soft'] = $monitor_data['user'][$username]['soft'];
 			$rec['hard'] = $monitor_data['user'][$username]['hard'];
 			$rec['files'] = $monitor_data['user'][$username]['files'];
-				
+
 			if (!is_numeric($rec['used'])){
 				if ($rec['used'][0] > $rec['used'][1]){
 					$rec['used'] = $rec['used'][0];
@@ -821,22 +820,22 @@
 			if (!is_numeric($rec['soft'])) $rec['soft']=$rec['soft'][1];
 			if (!is_numeric($rec['hard'])) $rec['hard']=$rec['hard'][1];
 			if (!is_numeric($rec['files'])) $rec['files']=$rec['files'][1];
-				
+
 			// used space ratio
 			if($rec['soft'] > 0){
 				$used_ratio = $rec['used']/$rec['soft'];
 			} else {
 				$used_ratio = 0;
 			}
-			
+
 			$rec['ratio'] = number_format($used_ratio * 100, 2, '.', '').'%';
-		
+
 			if($rec['used'] > 1024) {
 				$rec['used'] = round($rec['used'] / 1024,2).' MB';
 			} else {
 				if ($rec['used'] != '') $rec['used'] .= ' KB';
 			}
-		
+
 			if($rec['soft'] > 1024) {
 				$rec['soft'] = round($rec['soft'] / 1024,2).' MB';
 			} elseif($rec['soft'] == 0){
@@ -844,7 +843,7 @@
 			} else {
 				$rec['soft'] .= ' KB';
 			}
-		
+
 			if($rec['hard'] > 1024) {
 				$rec['hard'] = round($rec['hard'] / 1024,2).' MB';
 			} elseif($rec['hard'] == 0){
@@ -852,12 +851,12 @@
 			} else {
 				$rec['hard'] .= ' KB';
 			}
-			
+
 			// send notifications only if 90% or more of the quota are used
 			if($used_ratio < 0.9) {
                 // reset notification date
                 if($rec['last_quota_notification']) $app->dbmaster->datalogUpdate('web_domain', "last_quota_notification = NULL", 'domain_id', $rec['domain_id']);
-                
+
                 // send notification - everything ok again
                 if($rec['last_quota_notification'] && $web_config['overquota_notify_onok'] == 'y' && ($web_config['overquota_notify_admin'] == 'y' || $web_config['overquota_notify_client'] == 'y')) {
                     $placeholders = array('{domain}' => $rec['domain'],
@@ -868,12 +867,12 @@
                                           '{ratio}' => $rec['ratio']);
 
                     $recipients = array();
-                    
+
                     //* send email to admin
                     if($global_config['admin_mail'] != '' && $web_config['overquota_notify_admin'] == 'y') {
                         $recipients[] = $global_config['admin_mail'];
                     }
-                    
+
                     //* Send email to client
                     if($web_config['overquota_notify_client'] == 'y') {
                         $client_group_id = $rec["sys_groupid"];
@@ -884,19 +883,19 @@
                     }
                     send_notification_email('web_quota_ok_notification', $placeholders, $recipients);
                 }
-                
+
                 continue;
             }
-            
+
             // could a notification be sent?
             $send_notification = false;
             if(!$rec['last_quota_notification']) $send_notification = true; // not yet notified
             elseif($web_config['overquota_notify_freq'] > 0 && $rec['notified_before'] >= $web_config['overquota_notify_freq']) $send_notification = true;
-            
+
 			//* Send quota notifications
 			if(($web_config['overquota_notify_admin'] == 'y' || $web_config['overquota_notify_client'] == 'y') && $send_notification == true) {
 				$app->dbmaster->datalogUpdate('web_domain', "last_quota_notification = CURDATE()", 'domain_id', $rec['domain_id']);
-                
+
                 $placeholders = array('{domain}' => $rec['domain'],
                                       '{admin_mail}' => $global_config['admin_mail'],
                                       '{used}' => $rec['used'],
@@ -905,12 +904,12 @@
                                       '{ratio}' => $rec['ratio']);
 
                 $recipients = array();
-                
+
                 //* send email to admin
                 if($global_config['admin_mail'] != '' && $web_config['overquota_notify_admin'] == 'y') {
                     $recipients[] = $global_config['admin_mail'];
                 }
-                
+
                 //* Send email to client
                 if($web_config['overquota_notify_client'] == 'y') {
                     $client_group_id = $rec["sys_groupid"];
@@ -939,7 +938,7 @@
 	$sql = "SELECT mailuser_id,sys_groupid,email,name,quota,last_quota_notification,DATEDIFF(CURDATE(), last_quota_notification) as `notified_before` FROM mail_user";
 	$records = $app->db->queryAllRecords($sql);
 	if(is_array($records) && !empty($records)) {
-	
+
 		$tmp_rec =  $app->db->queryAllRecords("SELECT data from monitor_data WHERE type = 'email_quota' ORDER BY created DESC");
 		$monitor_data = array();
 		if(is_array($tmp_rec)) {
@@ -953,24 +952,24 @@
 				}
 			}
 		}
-		
+
 		foreach($records as $rec) {
 
 			$email = $rec['email'];
-		
+
 			$rec['used'] = isset($monitor_data[$email]['used']) ? $monitor_data[$email]['used'] : array(1 => 0);
-		
+
 			if (!is_numeric($rec['used'])) $rec['used']=$rec['used'][1];
-				
+
 			// used space ratio
 			if($rec['quota'] > 0){
 				$used_ratio = $rec['used']/$rec['quota'];
 			} else {
 				$used_ratio = 0;
 			}
-			
+
 			$rec['ratio'] = number_format($used_ratio * 100, 2, '.', '').'%';
-			
+
 			if($rec['quota'] > 0){
 				$rec['quota'] = round($rec['quota'] / 1048576,4).' MB';
 			} else {
@@ -981,8 +980,8 @@
 				$rec['used'] = round($rec['used'] / 1024,4).' KB';
 			} else {
 				$rec['used'] = round($rec['used'] / 1048576,4).' MB';
-			} 
-			
+			}
+
 			// send notifications only if 90% or more of the quota are used
 			if($used_ratio < 0.9) {
                 // reset notification date
@@ -996,13 +995,13 @@
                               '{name}' => $rec['name'],
                               '{quota}' => $rec['quota'],
                               '{ratio}' => $rec['ratio']);
-        
+
                     $recipients = array();
                     //* send email to admin
                     if($global_config['admin_mail'] != '' && $mail_config['overquota_notify_admin'] == 'y') {
                         $recipients[] = $global_config['admin_mail'];
                     }
-                    
+
                     //* Send email to client
                     if($mail_config['overquota_notify_client'] == 'y') {
                         $client_group_id = $rec["sys_groupid"];
@@ -1011,35 +1010,35 @@
                             $recipients[] = $client['email'];
                         }
                     }
-                    
+
                     send_notification_email('mail_quota_ok_notification', $placeholders, $recipients);
                 }
 
                 continue;
             }
-				
+
 			//* Send quota notifications
             // could a notification be sent?
             $send_notification = false;
             if(!$rec['last_quota_notification']) $send_notification = true; // not yet notified
             elseif($mail_config['overquota_notify_freq'] > 0 && $rec['notified_before'] >= $mail_config['overquota_notify_freq']) $send_notification = true;
-            
+
             if(($mail_config['overquota_notify_admin'] == 'y' || $mail_config['overquota_notify_client'] == 'y') && $send_notification == true) {
 				$app->dbmaster->datalogUpdate('mail_user', "last_quota_notification = CURDATE()", 'mailuser_id', $rec['mailuser_id']);
-                
+
                 $placeholders = array('{email}' => $rec['email'],
                           '{admin_mail}' => $global_config['admin_mail'],
                           '{used}' => $rec['used'],
                           '{name}' => $rec['name'],
                           '{quota}' => $rec['quota'],
                           '{ratio}' => $rec['ratio']);
-    
+
                 $recipients = array();
                 //* send email to admin
                 if($global_config['admin_mail'] != '' && $mail_config['overquota_notify_admin'] == 'y') {
                     $recipients[] = $global_config['admin_mail'];
                 }
-                
+
                 //* Send email to client
                 if($mail_config['overquota_notify_client'] == 'y') {
                     $client_group_id = $rec["sys_groupid"];
@@ -1048,9 +1047,9 @@
                         $recipients[] = $client['email'];
                     }
                 }
-                
+
                 send_notification_email('mail_quota_notification', $placeholders, $recipients);
-			}	
+			}
 		}
 	}
 }
@@ -1081,7 +1080,7 @@
 #######################################################################################################
 function formatBytes($size, $precision = 2) {
 	$base=log($size)/log(1024);
-	$suffixes=array('','k','M','G','T');   
+	$suffixes=array('','k','M','G','T');
     	return round(pow(1024,$base-floor($base)),$precision).$suffixes[floor($base)];
 }
 
@@ -1153,7 +1152,7 @@
 				} else {
 					if(is_file($web_backup_dir.'/'.$web_backup_file)) unlink($web_backup_dir.'/'.$web_backup_file);
 				}
-				
+
 				//* Remove old backups
 				$backup_copies = intval($rec['backup_copies']);
 
@@ -1187,7 +1186,7 @@
 				//* Remove backupdir symlink and create as directory instead
 				$app->uses('system');
 				$app->system->web_folder_protection($web_path,false);
-				
+
 				if(is_link($web_path.'/backup')) {
 					unlink($web_path.'/backup');
 				}
@@ -1196,7 +1195,7 @@
 					chown($web_path.'/backup', $rec['system_user']);
 					chgrp($web_path.'/backup', $rec['system_group']);
 				}
-				
+
 				$app->system->web_folder_protection($web_path,true);
 
 			}
@@ -1232,33 +1231,72 @@
 				chown($db_backup_dir, 'root');
 				chgrp($db_backup_dir, 'root');
 
-				//* Do the mysql database backup with mysqldump
+				//* Do the mysql database backup with mysqldump or mongodump
 				$db_id = $rec['database_id'];
 				$db_name = $rec['database_name'];
-				$db_backup_file = 'db_'.$db_name.'_'.date('Y-m-d_H-i').'.sql';
-				$command = "mysqldump -h '".escapeshellcmd($clientdb_host)."' -u '".escapeshellcmd($clientdb_user)."' -p'".escapeshellcmd($clientdb_password)."' -c --add-drop-table --create-options --quick --result-file='".$db_backup_dir.'/'.$db_backup_file."' '".$db_name."'";
-				exec($command, $tmp_output, $retval);
 
-				//* Compress the backup with gzip
-				if($retval == 0) exec("gzip -c '".escapeshellcmd($db_backup_dir.'/'.$db_backup_file)."' > '".escapeshellcmd($db_backup_dir.'/'.$db_backup_file).".gz'", $tmp_output, $retval);
-				
-				if($retval == 0){
-					chmod($db_backup_dir.'/'.$db_backup_file.'.gz', 0750);
-					chown($db_backup_dir.'/'.$db_backup_file.'.gz', fileowner($db_backup_dir));
-					chgrp($db_backup_dir.'/'.$db_backup_file.'.gz', filegroup($db_backup_dir));
+				if ($rec['type'] == 'mysql') {
+					$db_backup_file = 'db_'.$db_name.'_'.date('Y-m-d_H-i').'.sql';
+					$command = "mysqldump -h '".escapeshellcmd($clientdb_host)."' -u '".escapeshellcmd($clientdb_user)."' -p'".escapeshellcmd($clientdb_password)."' -c --add-drop-table --create-options --quick --result-file='".$db_backup_dir.'/'.$db_backup_file."' '".$db_name."'";
+					exec($command, $tmp_output, $retval);
 
-					//* Insert web backup record in database
-					//$insert_data = "(server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",$web_id,'mysql','sqlgz',".time().",'".$app->db->quote($db_backup_file).".gz')";
-					//$app->dbmaster->datalogInsert('web_backup', $insert_data, 'backup_id');
-					$sql = "INSERT INTO web_backup (server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",$web_id,'mysql','sqlgz',".time().",'".$app->db->quote($db_backup_file).".gz')";
-					$app->db->query($sql);
-					if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
+					//* Compress the backup with gzip
+					if($retval == 0) exec("gzip -c '".escapeshellcmd($db_backup_dir.'/'.$db_backup_file)."' > '".escapeshellcmd($db_backup_dir.'/'.$db_backup_file).".gz'", $tmp_output, $retval);
 
-				} else {
-					if(is_file($db_backup_dir.'/'.$db_backup_file.'.gz')) unlink($db_backup_dir.'/'.$db_backup_file.'.gz');
+					if($retval == 0){
+						chmod($db_backup_dir.'/'.$db_backup_file.'.gz', 0750);
+						chown($db_backup_dir.'/'.$db_backup_file.'.gz', fileowner($db_backup_dir));
+						chgrp($db_backup_dir.'/'.$db_backup_file.'.gz', filegroup($db_backup_dir));
+
+						//* Insert web backup record in database
+						//$insert_data = "(server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",$web_id,'mysql','sqlgz',".time().",'".$app->db->quote($db_backup_file).".gz')";
+						//$app->dbmaster->datalogInsert('web_backup', $insert_data, 'backup_id');
+						$sql = "INSERT INTO web_backup (server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",$web_id,'mysql','sqlgz',".time().",'".$app->db->quote($db_backup_file).".gz')";
+						$app->db->query($sql);
+						if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
+
+					} else {
+						if(is_file($db_backup_dir.'/'.$db_backup_file.'.gz')) unlink($db_backup_dir.'/'.$db_backup_file.'.gz');
+					}
+					//* Remove the uncompressed file
+					if(is_file($db_backup_dir.'/'.$db_backup_file)) unlink($db_backup_dir.'/'.$db_backup_file);
+				} else if ($rec['type'] == 'mongo') {
+					$db_backup_file = 'db_'.$db_name.'_'.date('Y-m-d_H-i');
+
+					try {
+						$connection = new MongoClient("mongodb://root:123456@127.0.0.1:27017/admin");
+						$db = $connection->selectDB($db_name);
+						// exclude not supported by mongodump, only get user collections
+						$collections = $db->getCollectionNames(false);
+
+						foreach ($collections as $collection) {
+							// mongodump -h 127.0.0.1 --port 27017 -u root -p 123456 --authenticationDatabase admin -d <db> -c <table> -o /tmp/test
+							$command = "mongodump -h 127.0.0.1 --port 27017 -u root -p 123456 --authenticationDatabase admin -d ".escapeshellcmd($db_name)." -c ".escapeshellcmd($collection)." -o ".escapeshellcmd($db_backup_dir.'/'.$db_backup_file);
+							exec($command);
+						}
+
+						if (is_dir(escapeshellcmd($db_backup_dir.'/'.$db_backup_file))) {
+							//* Compress the backup with gzip
+							exec("cd ".escapeshellcmd($db_backup_dir)." && tar -pczf ".escapeshellcmd($db_backup_dir.'/'.$db_backup_file).".tar.gz ".escapeshellcmd($db_backup_file));
+							chmod($db_backup_dir.'/'.$db_backup_file.'.tar.gz', 0750);
+							chown($db_backup_dir.'/'.$db_backup_file.'.tar.gz', fileowner($db_backup_dir));
+							chgrp($db_backup_dir.'/'.$db_backup_file.'.tar.gz', filegroup($db_backup_dir));
+
+							//* Insert web backup record in database
+							$sql = "INSERT INTO web_backup (server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",$web_id,'mongodb','rootgz',".time().",'".$app->db->quote($db_backup_file).".tar.gz')";
+							$app->db->query($sql);
+
+							if ($app->db->dbHost != $app->dbmaster->dbHost) {
+								$app->dbmaster->query($sql);
+							}
+
+							//* Remove the uncompressed file
+							exec("rm -rf ".escapeshellcmd($db_backup_dir.'/'.$db_backup_file));
+						}
+					} catch (MongoConnnectionException $e) {
+						// connecting to MongoDB failed - cannot create backup
+					}
 				}
-				//* Remove the uncompressed file
-				if(is_file($db_backup_dir.'/'.$db_backup_file)) unlink($db_backup_dir.'/'.$db_backup_file);
 
 				//* Remove old backups
 				$backup_copies = intval($rec['backup_copies']);
@@ -1266,13 +1304,13 @@
 				$dir_handle = dir($db_backup_dir);
 				$files = array();
 				while (false !== ($entry = $dir_handle->read())) {
-					if($entry != '.' && $entry != '..' && preg_match('/^db_(.*?)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.sql.gz$/', $entry, $matches) && is_file($db_backup_dir.'/'.$entry)) {
+					if($entry != '.' && $entry != '..' && (preg_match('/^db_(.*?)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.sql.gz$/', $entry, $matches) || preg_match('/^db_(.*?)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.tar.gz$/', $entry, $matches)) && is_file($db_backup_dir.'/'.$entry)) {
                         if(array_key_exists($matches[1], $files) == false) $files[$matches[1]] = array();
 						$files[$matches[1]][] = $entry;
 					}
 				}
 				$dir_handle->close();
-                
+
                 reset($files);
                 foreach($files as $db_name => $filelist) {
                     rsort($filelist);
diff --git a/server/lib/classes/monitor_tools.inc.php b/server/lib/classes/monitor_tools.inc.php
index 9ce9556..6b93e1e 100644
--- a/server/lib/classes/monitor_tools.inc.php
+++ b/server/lib/classes/monitor_tools.inc.php
@@ -755,6 +755,13 @@
 				$data['mysqlserver'] = 0;
 				$state = 'error'; // because service is down
 			}
+
+			if ($this->_checkTcp('localhost', 27017)) {
+				$data['mongodbserver'] = 1;
+			} else {
+				$data['mongodbserver'] = 0;
+				$state = 'error'; // because service is down
+			}
 		}
 
 		/*
@@ -1299,6 +1306,51 @@
 		return $res;
 	}
 
+	public function monitorMongoDB() {
+		global $conf;
+
+		/* the id of the server as int */
+		$server_id = intval($conf['server_id']);
+
+		/** The type of the data */
+		$type = 'log_mongodb';
+
+		/* This monitoring is only available if MongoDB is installed */
+		system('which mongod', $retval); // Debian, Ubuntu, Fedora
+		if ($retval !== 0)
+			system('which mongod', $retval); // CentOS
+		if ($retval === 0) {
+			/*  Get the data of the log */
+			$data = $this->_getLogData($type);
+
+			/*
+			 * At this moment, there is no state (maybe later)
+			 */
+			$state = 'no_state';
+		} else {
+			/*
+			 * MongoDB is not installed, so there is no data and no state
+			 *
+			 * no_state, NOT unknown, because "unknown" is shown as state
+			 * inside the GUI. no_state is hidden.
+			 *
+			 * We have to write NO DATA inside the DB, because the GUI
+			 * could not know, if there is any dat, or not...
+			 */
+			$state = 'no_state';
+			$data = '';
+		}
+
+		/*
+		 * Return the Result
+		 */
+		$res['server_id'] = $server_id;
+		$res['type'] = $type;
+		$res['data'] = $data;
+		$res['state'] = $state;
+		return $res;
+	}
+
 	public function monitorIPTables() {
 				global $conf;
 
@@ -1745,6 +1797,9 @@
 					$logfile = '/var/log/fail2ban.log';
 				}
 				break;
+			case 'log_mongodb':
+					$logfile = '/var/log/mongodb/mongodb.log';
+				break;
 			case 'log_ispconfig':
 				if ($dist == 'debian') {
 					$logfile = $conf['ispconfig_log_dir'] . '/ispconfig.log';
@@ -1926,4 +1981,4 @@
 
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/server/mods-available/monitor_core_module.inc.php b/server/mods-available/monitor_core_module.inc.php
index 2e66d64..88e994d 100644
--- a/server/mods-available/monitor_core_module.inc.php
+++ b/server/mods-available/monitor_core_module.inc.php
@@ -89,7 +89,7 @@
 		$this->_tools = new monitor_tools();
 
 		/*
-		 * Calls the single Monitoring steps 
+		 * Calls the single Monitoring steps
 		 */
 		$this->_monitorEmailQuota();
 		$this->_monitorHDQuota();
@@ -117,6 +117,7 @@
 		$this->_monitorRaid();
 		$this->_monitorRkHunter();
 		$this->_monitorFail2ban();
+		$this->_monitorMongoDB();
 		$this->_monitorIPTables();
 		$this->_monitorSysLog();
 	}
@@ -129,12 +130,12 @@
 		 */
 		$min = @date('i', $this->_run_time);
 		if ($min % 15 != 0) return;
-		
+
 		$app->uses('getconf');
 		$mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
 		if($mail_config['mailbox_quota_stats'] == 'n') return;
-		
-		
+
+
 		/*
          * First we get the Monitoring-data from the tools
          */
@@ -422,7 +423,7 @@
 		 * First we get the Monitoring-data from the tools
 		 */
 		$res = $this->_tools->monitorSystemUpdate();
-		
+
 		//* Ensure that output is encoded so that it does not break the serialize
 		//$res['data']['output'] = htmlentities($res['data']['output']);
 		$res['data']['output'] = htmlentities($res['data']['output'],ENT_QUOTES,'UTF-8');
@@ -536,6 +537,31 @@
          * First we get the Monitoring-data from the tools
          */
         $res = $this->_tools->monitorFail2ban();
+
+        /*
+         * Insert the data into the database
+         */
+        $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+                'VALUES (' .
+                $res['server_id'] . ', ' .
+                "'" . $app->dbmaster->quote($res['type']) . "', " .
+                'UNIX_TIMESTAMP(), ' .
+                "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+                "'" . $res['state'] . "'" .
+                ')';
+        $app->dbmaster->query($sql);
+
+        /* The new data is written, now we can delete the old one */
+        $this->_delOldRecords($res['type'], $res['server_id']);
+    }
+
+	private function _monitorMongoDB() {
+	global $app;
+
+        /*
+         * First we get the Monitoring-data from the tools
+         */
+        $res = $this->_tools->monitorMongoDB();
 
         /*
          * Insert the data into the database
@@ -712,7 +738,7 @@
 		 * First we get the Monitoring-data from the tools
 		 */
 		$res = $this->_tools->monitorISPCCronLog();
-		
+
 		//* Ensure that output is encoded so that it does not break the serialize
 		if(is_array($res) && isset($res['data'])) $res['data'] = htmlentities($res['data']);
 
@@ -820,10 +846,10 @@
 		// $now = time();
 		// $old = $now - (4 * 60); // 4 minutes
 		$old = 'UNIX_TIMESTAMP() - 240';
-		
+
 		/*
 		 * ATTENTION if i do NOT pay attention of the server id, i delete all data (of the type)
-		 * of ALL servers. This means, if i have a multiserver-environment and a server has a 
+		 * of ALL servers. This means, if i have a multiserver-environment and a server has a
 		 * time not synced with the others (for example, all server has 11:00 and ONE server has
 		 * 10:45) then the actual data of this server (with the time-stamp 10:45) get lost
 		 * even though it is the NEWEST data of this server. To avoid this i HAVE to include
@@ -841,4 +867,4 @@
 
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/server/mods-available/rescue_core_module.inc.php b/server/mods-available/rescue_core_module.inc.php
index 49012d5..050d32f 100644
--- a/server/mods-available/rescue_core_module.inc.php
+++ b/server/mods-available/rescue_core_module.inc.php
@@ -35,7 +35,7 @@
 	/* No actions at this time. maybe later... */
 	var $actions_available = array();
 	/**
-	 * The monitoring-Data of this module. 
+	 * The monitoring-Data of this module.
 	 * [0] are the actual data, [1] are the data 1 minnute ago [2] are teh data 2 minuntes...
 	 */
 	private $_monitoringData = array();
@@ -73,7 +73,7 @@
 		 * do nothing, if the rescue-system is not enabled
 		 */
 		global $conf;
-		if ((!isset($conf['serverconfig']['rescue']['try_rescue'])) || 
+		if ((!isset($conf['serverconfig']['rescue']['try_rescue'])) ||
 				((isset($conf['serverconfig']['rescue']['try_rescue'])) && ($conf['serverconfig']['rescue']['try_rescue'] !='y'))){
 			return;
 		}
@@ -87,17 +87,22 @@
 		 * Next we get the rescue data needed for rescuing the system
 		 */
 		$this->_rescueData = $this->_getRescueData();
-		
+
+		/*
+		 * rescue MongoDB if needed
+		 */
+		$this->_rescueMongoDB();
+
 		/*
 		 * rescue mysql if needed (maybe httpd depends on mysql, so try this first!)
 		 */
 		$this->_rescueMySql();
-		
+
 		/*
 		 * rescue httpd if needed
 		 */
 		$this->_rescueHttpd();
-		
+
 		/*
 		 * The last step is to save the rescue-data
 		 */
@@ -112,12 +117,12 @@
 	 */
 	private function _getMonitoringData() {
 		global $app;
-		
+
 		$dataFilename = dirname(__FILE__) . "/../temp/rescue_module_monitoringdata.ser.txt";
-		
+
 		/*
 		 * If the file containing the data is too old (older than 5 minutes) it is better to
-		 * delete it, because it could be, that the server was down for some times and so the data 
+		 * delete it, because it could be, that the server was down for some times and so the data
 		 * are outdated
 		 */
 		if (file_exists($dataFilename) && (filemtime($dataFilename) < (time() - 5 * 60))) {
@@ -132,7 +137,7 @@
 		} else {
 			$data = array();
 		}
-		
+
 		/*
 		 * $temp[0] was the data of the last monitoring (means 1 minute ago), $temp[1] is the data
 		 * 2 minutes ago and so on. Now we have make place for the newest data...
@@ -144,32 +149,32 @@
 		for ($i = $max; $i > 0; $i--){
 			$data[$i] = $data[$i -1];
 		}
-		
+
 		/*
 		 * we need the monitoring tools
 		 */
 		$app->load('monitor_tools');
 		$tools = new monitor_tools();
-		
+
 		/*
 		 * Call the needed Monitoring-step and get the data
 		 */
 		$tmp[0] = $tools->monitorServices();
-		
+
 		/* Add the data at the FIRST position of the history */
 		$data[0] = $tmp;
-		
+
 		/*
 		 * We have the newest monitoring data. Save it!
 		 * (and protect it, because there may be sensible data in it)
 		 */
 		file_put_contents($dataFilename, serialize($data));
 		chmod($dataFilename, 0600);
-						
+
 		/* Thats it */
 		return $data;
 	}
-	
+
 	/**
 	 * This gets the rescue-Data, needed for rescuing the system.
 	 * Because we can not be 100% sure, that the mysql-DB is up and running, so we use the
@@ -181,7 +186,7 @@
 
 		/*
 		 * If the file containing the data is too old (older than 5 minutes) it is better to
-		 * delete it, because it could be, that the server was down for some times and so the data 
+		 * delete it, because it could be, that the server was down for some times and so the data
 		 * are outdated
 		 */
 		if (file_exists($dataFilename) && (filemtime($dataFilename) < (time() - 5 * 60))) {
@@ -196,7 +201,7 @@
 		} else {
 			$data = array();
 		}
-		
+
 		/* Thats it */
 		return $data;
 	}
@@ -222,14 +227,14 @@
 	 */
 	private function _rescueHttpd(){
 		global $app, $conf;
-		
+
 		/*
 		 * do nothing, if it is not allowed to rescue httpd
 		 */
 		if ((isset($conf['serverconfig']['rescue']['do_not_try_rescue_httpd']) && ($conf['serverconfig']['rescue']['do_not_try_rescue_httpd']) == 'y')){
 			return;
 		}
-		
+
 		/*
 		 * if the service is up and running, or the service is not installed there is nothing to do...
 		 */
@@ -238,42 +243,42 @@
 			$this->_rescueData['webserver']['try_counter'] = 0;
 			return;
 		}
-		
+
 		/*
 		 * OK, the service is installed and down.
 		 * Maybe this is because of a restart of the service by the admin.
 		 * This means, we check the data 1 minute ago
 		 */
-		if ((!isset($this->_monitoringData[1][0]['data']['webserver'])) || 
+		if ((!isset($this->_monitoringData[1][0]['data']['webserver'])) ||
 				((isset($this->_monitoringData[1][0]['data']['webserver'])) && ($this->_monitoringData[1][0]['data']['webserver'] != 0))){
-			/* 
-			 * We do NOT have this data or we have this data, but the webserver was not down 1 minute ago. 
-			 * This means, it could be, that the admin is restarting the server. 
+			/*
+			 * We do NOT have this data or we have this data, but the webserver was not down 1 minute ago.
+			 * This means, it could be, that the admin is restarting the server.
 			 * We wait one more minute...
 			 */
 			return;
 		}
-		
+
 		/*#####
 		 * The service is down and it was down 1 minute ago.
 		 * We try to rescue it
 		 *#####*/
-		
+
 		/* Get the try counter */
 		$tryCount = (!isset($this->_rescueData['webserver']['try_counter']))? 1 : $this->_rescueData['webserver']['try_counter'] + 1;
-		
+
 		/* Set the new try counter */
 		$this->_rescueData['webserver']['try_counter'] = $tryCount;
-		
+
 		/* if 5 times will not work, we have to give up... */
 		if ($tryCount > 5){
 			$app->log('httpd is down! Rescue will not help!', LOGLEVEL_ERROR);
 			return;
 		}
-		
-		
+
+
 		$app->log('httpd is down! Try rescue httpd (try:' . $tryCount . ')...', LOGLEVEL_WARN);
-		
+
 		if($conf['serverconfig']['web']['server_type'] == 'nginx'){
 			$daemon = 'nginx';
 		} else {
@@ -285,23 +290,89 @@
 				$daemon = 'apache2';
 			}
 		}
-		
+
 		$this->_rescueDaemon($daemon);
 	}
-	
+
+	/**
+	 * restarts MongoDB, if needed
+	 */
+	private function _rescueMongoDB(){
+		global $app, $conf;
+
+		/*
+		 * do nothing, if it is not allowed to rescue mysql
+		 */
+		if ((isset($conf['serverconfig']['rescue']['do_not_try_rescue_mongodb']) && ($conf['serverconfig']['rescue']['do_not_try_rescue_mongodb']) == 'y')){
+			return;
+		}
+
+		/*
+		 * if the service is up and running, or the service is not installed there is nothing to do...
+		 */
+		if ($this->_monitoringData[0][0]['data']['mongodbserver'] != 0){
+			/* Clear the try counter, because we do not have to try to rescue the service */
+			$this->_rescueData['mongodbserver']['try_counter'] = 0;
+			return;
+		}
+
+		/*
+		 * OK, the service is installed and down.
+		 * Maybe this is because of a restart of the service by the admin.
+		 * This means, we check the data 1 minute ago
+		 */
+		if ((!isset($this->_monitoringData[1][0]['data']['mongodbserver'])) ||
+				((isset($this->_monitoringData[1][0]['data']['mongodbserver'])) && ($this->_monitoringData[1][0]['data']['mongodbserver'] != 0))){
+			/*
+			 * We do NOT have this data or we have this data, but the webserver was not down 1 minute ago.
+			 * This means, it could be, that the admin is restarting the server.
+			 * We wait one more minute...
+			 */
+			return;
+		}
+
+		/*#####
+		 * The service is down and it was down 1 minute ago.
+		 * We try to rescue it
+		 *#####*/
+
+		/* Get the try counter */
+		$tryCount = (!isset($this->_rescueData['mongodbserver']['try_counter']))? 1 : $this->_rescueData['mongodbserver']['try_counter'] + 1;
+
+		/* Set the new try counter */
+		$this->_rescueData['mongodbserver']['try_counter'] = $tryCount;
+
+		/* if 5 times will not work, we have to give up... */
+		if ($tryCount > 5){
+			$app->log('MongoDB is down! Rescue will not help!', LOGLEVEL_ERROR);
+			return;
+		}
+
+
+		$app->log('MongoDB is down! Try rescue MongoDB (try:' . $tryCount . ')...', LOGLEVEL_WARN);
+
+		if(is_file($conf['init_scripts'] . '/' . 'mongodb')) {
+			$daemon = 'mongodb';
+		} else {
+			$daemon = 'mongodb';
+		}
+
+		$this->_rescueDaemon($daemon);
+	}
+
 	/**
 	 * restarts mysql, if needed
 	 */
 	private function _rescueMySql(){
 		global $app, $conf;
-		
+
 		/*
 		 * do nothing, if it is not allowed to rescue mysql
 		 */
 		if ((isset($conf['serverconfig']['rescue']['do_not_try_rescue_mysql']) && ($conf['serverconfig']['rescue']['do_not_try_rescue_mysql']) == 'y')){
 			return;
 		}
-		
+
 		/*
 		 * if the service is up and running, or the service is not installed there is nothing to do...
 		 */
@@ -310,40 +381,40 @@
 			$this->_rescueData['mysqlserver']['try_counter'] = 0;
 			return;
 		}
-		
+
 		/*
 		 * OK, the service is installed and down.
 		 * Maybe this is because of a restart of the service by the admin.
 		 * This means, we check the data 1 minute ago
 		 */
-		if ((!isset($this->_monitoringData[1][0]['data']['mysqlserver'])) || 
+		if ((!isset($this->_monitoringData[1][0]['data']['mysqlserver'])) ||
 				((isset($this->_monitoringData[1][0]['data']['mysqlserver'])) && ($this->_monitoringData[1][0]['data']['mysqlserver'] != 0))){
-			/* 
-			 * We do NOT have this data or we have this data, but the webserver was not down 1 minute ago. 
-			 * This means, it could be, that the admin is restarting the server. 
+			/*
+			 * We do NOT have this data or we have this data, but the webserver was not down 1 minute ago.
+			 * This means, it could be, that the admin is restarting the server.
 			 * We wait one more minute...
 			 */
 			return;
 		}
-		
+
 		/*#####
 		 * The service is down and it was down 1 minute ago.
 		 * We try to rescue it
 		 *#####*/
-		
+
 		/* Get the try counter */
 		$tryCount = (!isset($this->_rescueData['mysqlserver']['try_counter']))? 1 : $this->_rescueData['mysqlserver']['try_counter'] + 1;
-		
+
 		/* Set the new try counter */
 		$this->_rescueData['mysqlserver']['try_counter'] = $tryCount;
-		
+
 		/* if 5 times will not work, we have to give up... */
 		if ($tryCount > 5){
 			$app->log('MySQL is down! Rescue will not help!', LOGLEVEL_ERROR);
 			return;
 		}
-		
-		
+
+
 		$app->log('MySQL is down! Try rescue mysql (try:' . $tryCount . ')...', LOGLEVEL_WARN);
 
 		if(is_file($conf['init_scripts'] . '/' . 'mysqld')) {
@@ -351,23 +422,23 @@
 		} else {
 			$daemon = 'mysql';
 		}
-		
+
 		$this->_rescueDaemon($daemon);
 	}
 
 	/**
 	 * Tries to stop and then restart the daemon
-	 * 
+	 *
 	 * @param type $daemon the name of the daemon
 	 */
 	private function _rescueDaemon($daemon){
 		global $conf;
-		
+
 		// if you need to find all restarts search for "['init_scripts']"
 		/*
 		 * First we stop the running service "normally"
 		 */
-		
+
 		/*
 		 * ATTENTION!
 		 * The service hangs. this means it could be, that "stop" will hang also.
@@ -375,13 +446,13 @@
 		 * of the service
 		 */
 		exec($conf['init_scripts'] . '/' . $daemon . ' stop && (sleep 3; kill $!; sleep 2; kill -9 $!) &> /dev/null');
-		
+
 		/*
 		 * OK, we tryed to stop it normally, maybe this worked maybe not. So we have to look
 		 * if the service is already running or not. If so, we have to kill them hard
 		 */
 		exec("kill -9 `ps -A | grep " . $daemon . "| grep -v grep | awk '{print $1}'` &> /dev/null");
-		
+
 		/*
 		 * There are no more zombies left. Lets start the service..
 		 */
diff --git a/server/plugins-available/backup_plugin.inc.php b/server/plugins-available/backup_plugin.inc.php
index 78be959..bc91a91 100644
--- a/server/plugins-available/backup_plugin.inc.php
+++ b/server/plugins-available/backup_plugin.inc.php
@@ -29,48 +29,48 @@
 */
 
 class backup_plugin {
-	
+
 	var $plugin_name = 'backup_plugin';
 	var $class_name  = 'backup_plugin';
-	
+
 	//* This function is called during ispconfig installation to determine
 	//  if a symlink shall be created for this plugin.
 	public function onInstall() {
 		global $conf;
-		
+
 		return true;
-		
+
 	}
-	
-		
+
+
 	/*
 	 	This function is called when the plugin is loaded
 	*/
-	
+
 	public function onLoad() {
 		global $app;
-		
+
 		//* Register for actions
 		$app->plugins->registerAction('backup_download',$this->plugin_name,'backup_action');
 		$app->plugins->registerAction('backup_restore',$this->plugin_name,'backup_action');
-		
+
 	}
-	
+
 	//* Do a backup action
 	public function backup_action($action_name,$data) {
 		global $app,$conf;
-		
+
 		$backup_id = intval($data);
 		$backup = $app->dbmaster->queryOneRecord("SELECT * FROM web_backup WHERE backup_id = $backup_id");
-		
+
 		if(is_array($backup)) {
-		
+
 			$app->uses('ini_parser,file,getconf');
-			
+
 			$web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$backup['parent_domain_id']);
 			$server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
 			$backup_dir = $server_config['backup_dir'].'/web'.$web['domain_id'];
-			
+
 			//* Make backup available for download
 			if($action_name == 'backup_download') {
 				//* Copy the backup file to the backup folder of the website
@@ -80,12 +80,38 @@
 					$app->log('cp '.$backup_dir.'/'.$backup['filename'].' '.$web['document_root'].'/backup/'.$backup['filename'],LOGLEVEL_DEBUG);
 				}
 			}
-			
+
+			//* Restore a MongoDB backup
+			if($action_name == 'backup_restore' && $backup['backup_type'] == 'mongodb') {
+				if(file_exists($backup_dir.'/'.$backup['filename'])) {
+					//$parts = explode('_',$backup['filename']);
+					//$db_name = $parts[1];
+					preg_match('@^db_(.+)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.tar\.gz$@', $backup['filename'], $matches);
+					$db_name = $matches[1];
+
+					// extract tar.gz archive
+					$dump_directory = str_replace(".tar.gz", "", $backup['filename']);
+					$extracted = "/usr/local/ispconfig/server/temp";
+					exec("tar -xzvf ".escapeshellarg($backup_dir.'/'.$backup['filename'])." --directory=".escapeshellarg($extracted));
+					$restore_directory = $extracted."/".$dump_directory."/".$db_name;
+
+					// mongorestore -h 127.0.0.1 -u root -p 123456 --authenticationDatabase admin -d c1debug --drop ./toRestore
+					$command = "mongorestore -h 127.0.0.1 --port 27017 -u root -p 123456 --authenticationDatabase admin -d ".$db_name." --drop ".escapeshellarg($restore_directory);
+					exec($command);
+					exec("rm -rf ".escapeshellarg($extracted."/".$dump_directory));
+				}
+
+				unset($clientdb_host);
+				unset($clientdb_user);
+				unset($clientdb_password);
+				$app->log('Restored MongoDB backup '.$backup_dir.'/'.$backup['filename'],LOGLEVEL_DEBUG);
+			}
+
 			//* Restore a mysql backup
 			if($action_name == 'backup_restore' && $backup['backup_type'] == 'mysql') {
 				//* Load sql dump into db
 				include('lib/mysql_clientdb.conf');
-				
+
 				if(file_exists($backup_dir.'/'.$backup['filename'])) {
 					//$parts = explode('_',$backup['filename']);
 					//$db_name = $parts[1];
@@ -99,7 +125,7 @@
 				unset($clientdb_password);
 				$app->log('Restored MySQL backup '.$backup_dir.'/'.$backup['filename'],LOGLEVEL_DEBUG);
 			}
-			
+
 			//* Restore a web backup
 			if($action_name == 'backup_restore' && $backup['backup_type'] == 'web') {
 				if($backup['backup_mode'] == 'userzip') {
@@ -123,11 +149,11 @@
 					}
 				}
 			}
-			
+
 		} else {
 			$app->log('No backup with ID '.$backup_id.' found.',LOGLEVEL_DEBUG);
 		}
-		
+
 		return 'ok';
 	}
 
diff --git a/server/plugins-available/mongo_clientdb_plugin.inc.php b/server/plugins-available/mongo_clientdb_plugin.inc.php
new file mode 100644
index 0000000..545fe9e
--- /dev/null
+++ b/server/plugins-available/mongo_clientdb_plugin.inc.php
@@ -0,0 +1,820 @@
+<?php
+
+/*
+Copyright (c) 2007, Till Brehm, projektfarm Gmbh
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of ISPConfig nor the names of its contributors
+      may be used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * The MongoDB client plugin is used by ISPConfig to control the management of MongoDB.
+ * If handles everything from creating DBs/Users, update them or delete them.
+ */
+class mongo_clientdb_plugin {
+
+	/**
+	 * ISPConfig internal identifiers.
+	 */
+	var $plugin_name = 'mongo_clientdb_plugin';
+	var $class_name  = 'mongo_clientdb_plugin';
+
+
+	/**
+	 * This function is called during ISPConfig installation.
+	 * It determines if a symlink shall be created for this plugin.
+	 *
+	 * @return bool true if symlink should be created
+	 */
+	function onInstall() {
+		global $conf;
+
+		return (bool) $conf['services']['db'];
+	}
+
+	/**
+	 * This function is called when the plugin is loaded.
+	 * Each plugin/module needs to register itself to ISPConfig events from which
+	 * it want to receive changes/get notified.
+	 *
+	 * Since this is a MongoDB plugin we are interested in DB changes and everything related
+	 * to it, like users.
+	 */
+	function onLoad() {
+		global $app;
+
+		//* Databases
+		$app->plugins->registerEvent('database_insert',$this->plugin_name,'db_insert');
+		$app->plugins->registerEvent('database_update',$this->plugin_name,'db_update');
+		$app->plugins->registerEvent('database_delete',$this->plugin_name,'db_delete');
+
+		//* Database users
+		$app->plugins->registerEvent('database_user_insert',$this->plugin_name,'db_user_insert');
+		$app->plugins->registerEvent('database_user_update',$this->plugin_name,'db_user_update');
+		$app->plugins->registerEvent('database_user_delete',$this->plugin_name,'db_user_delete');
+	}
+
+
+	/**
+	 * MongoDB
+	 * ------------------------------------------------------------------------
+	 * The following needs to be done before using this plugin:
+	 * - 1. install MongoDB server from 10gen sources (or another one with >= 2.4)
+	 * - 2. install php5-dev package (apt-get install php5-dev)
+	 * - 3. install mongo PECL extension (pecl install mongo)
+	 * - 4. enable mongo (echo "extension=mongo.so" > /etc/php5/mods-available/mongo.ini && php5enmod mongo)
+	 * - 5. create administrative user manager in Mongo (mongo -> use admin -> db.addUser({user: "root", pwd: "123456", roles: [ "userAdminAnyDatabase", "readWriteAnyDatabase", "dbAdminAnyDatabase", "clusterAdmin" ]}))
+	 * - 6. enable auth for Mongo (nano /etc/mongodb.conf -> auth = true)
+	 * - 7. restart MongoDB (service mongodb restart)
+	 *
+	 * Unlike MySQL, MongoDB manages users per database.
+	 * Therefor we cannot use one user for multiple databases. Instead, we have to add him each time via the admin user.
+	 */
+
+	/**
+	 * Stores the MongoDB connection.
+	 * @var object
+	 */
+	private $_connection = null;
+
+	/**
+	 * Stores the MongoDB admin user.
+	 * @var string
+	 */
+	const USER = "root";
+
+	/**
+	 * Stores the MongoDB admin password.
+	 * @var string
+	 */
+	const PW = "123456";
+
+	/**
+	 * Stores the MongoDB host address.
+	 * @var string
+	 */
+	const HOST = "127.0.0.1";
+
+	/**
+	 * Stores the MongoDB port.
+	 * @var int
+	 */
+	const PORT = 27017;
+
+	/**
+	 * Adds the user to given database.
+	 * If no connection exists, the user already exists or the database doesn't exist,
+	 * null is returned.
+	 *
+	 * @param string $db the database to use
+	 * @param array $user the user to add
+	 * @return bool true if user added
+	 */
+	private function addUser($db, $user) {
+		if ($this->isConnected() && !$this->userExists($db, $user)) {
+			$roles = "";
+
+			foreach ($user['roles'] as $index => $role) {
+				$roles .= "\"".$role."\"";
+
+				if ($index !== count($user['roles']) - 1) {
+					$roles .= ", ";
+				}
+			}
+
+			return $this->exec($db, "db.system.users.insert({ user: \"".$user['username']."\", pwd: \"".$user['password']."\", roles: [ ".$roles." ] })");
+			//return $this->exec($db, "db.addUser({ user: \"".$user['username']."\", pwd: \"".$user['password']."\", roles: [ ".$roles." ] })");
+		}
+
+		return null;
+	}
+
+	/**
+	 * Changes the users password in given DB.
+	 * If no connection exists, the user doesn't exist or the DB doesn't exist,
+	 * null is returned.
+	 *
+	 * @param string $db the database name
+	 * @param string $user the user to change
+	 * @param string $password the new password
+	 * @return bool true if password changes
+	 */
+	private function changePassword($db, $user, $password) {
+		if ($this->isConnected() && $this->dbExists($db) && $this->userExists($db, $user)) {
+			$old_user = $this->getUser($db, $user);
+
+			if ($this->dropUser($user, $db)) {
+				return $this->addUser($db, array(
+					'username' => $user,
+					'password' => $password,
+					'roles' => $old_user['roles']
+				));
+			}
+
+			return false;
+		}
+
+		return null;
+	}
+
+	/**
+	 * Connects to the server and authentificates.
+	 * If the authentificaten goes wrong or another error encounters,
+	 * false is returned.
+	 * If we already have an open connection we try to disconnect and connect again.
+	 * If this fails, false is returned.
+	 *
+	 * @return object $connection the MongoDB connection
+	 */
+	private function connect() {
+		try {
+			if ($this->isConnected() && !$this->disconnect()) {
+				return false;
+			}
+
+			$this->_connection = new MongoClient("mongodb://".self::USER.":".self::PW."@".self::HOST.":".self::PORT."/admin");
+
+			return $this->_connection;
+		} catch (MongoConnnectionException $e) {
+			$app->log('Unable to connect to MongoDB: '.$e, LOGLEVEL_ERROR);
+			$this->_connection = null;
+
+			return false;
+		}
+	}
+
+	/**
+	 * Checks if the database exists.
+	 * If no connection exists,
+	 * null is returned.
+	 *
+	 * @param string $db the database name
+	 * @return bool true if exists
+	 */
+	private function dbExists($db) {
+		if ($this->isConnected()) {
+			return in_array($db, $this->getDBs());
+		}
+
+		return null;
+	}
+
+	/**
+	 * Closes the MongoDB connection.
+	 * If no connection exists and nothing is done,
+	 * null is returned.
+	 *
+	 * @return bool true if closed
+	 */
+	private function disconnect() {
+		if ($this->isConnected()) {
+			$status = $this->_connection->close();
+
+			if ($status) {
+				$this->_connection = null;
+			}
+
+			return $status;
+		}
+
+		return null;
+	}
+
+	/**
+	 * Drops the given database.
+	 * If no connection exists or the database doesn't exist,
+	 * null is returned.
+	 *
+	 * @param string $db the database's to drop name
+	 */
+	private function dropDB($db) {
+		if ($this->isConnected() && $this->dbExists($db)) {
+			return (bool) $this->_connection->dropDB($db)['ok'];
+		}
+
+		return null;
+	}
+
+	/**
+	 * Drops the given user from database.
+	 * If no DB is defined, the user is dropped from all databases.
+	 * If there's an error when dropping the user from all DBs, an array containing the
+	 * names of the failed DBs is returned.
+	 * If no connection exists, the database doesn't exist or the user is not in DB,
+	 * null is returned.
+	 *
+	 * @param string $user the user to drop
+	 * @param string $db the database name
+	 * @return bool true if dropped
+	 */
+	private function dropUser($user, $db = null) {
+		if ($this->isConnected()) {
+			if ($db !== null && $this->dbExists($db) && $this->userExists($db, $user)) {
+				return $this->exec($db, "db.removeUser(\"".$user."\")");
+			} else {
+				$dbs = $this->getDBs();
+
+				if ((bool) $dbs) {
+					$failures = array();
+
+					foreach ($dbs as $db) {
+						$exists = $this->userExists($db, $user);
+
+						if ($exists) {
+							if (!$this->dropUser($user, $db)) {
+								$failures[] = $db;
+							}
+						}
+					}
+				}
+
+				return (bool) $failures ? $failures : true;
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * Executed the command on the MongoDB server.
+	 * If no connection exists and thus nothing can be done,
+	 * null is returned.
+	 *
+	 * @param string $db the database to query
+	 * @param string $query the command to execute
+	 * @return array the result of the query
+	 */
+	private function exec($db, $query) {
+		if ($this->isConnected()) {
+			$db = $this->selectDB($db);
+			$result = $db->execute($query);
+
+			if ((bool) $result['ok']) {
+				return $result;
+			}
+
+			return false;
+		}
+
+		return null;
+	}
+
+	/**
+	 * Checks if the connection exists.
+	 *
+	 * @return true if connected
+	 */
+	private function isConnected() {
+		return $this->_connection !== null;
+	}
+
+	/**
+	 * Generates a MongoDB compatible password.
+	 *
+	 * @param string $user the username
+	 * @param string $password the user password
+	 * @return string the MD5 string
+	 */
+	private function generatePassword($user, $password) {
+		return md5($user.":mongo:".$password);
+	}
+
+	/**
+	 * Returns the databases found on connection.
+	 * If no connection exists and therefor no DBs can be found,
+	 * null is returned.
+	 *
+	 * @return array $names the databases's name
+	 */
+	private function getDBs() {
+		if ($this->isConnected()) {
+			$dbs = $this->_connection->listDBs();
+
+			if ((bool) $dbs && isset($dbs['databases'])) {
+				$names = array();
+
+				foreach ($dbs['databases'] as $db) {
+					$names[] = $db['name'];
+				}
+
+				return $names;
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * Returns the user entry for given database.
+	 * If no connection exists, the database doesn't exist or the user doesn't exist
+	 * null is returned.
+	 *
+	 * @param string $db the database name
+	 * @param string $user the user to return
+	 * @return array $user the user in DB
+	 */
+	private function getUser($db, $user) {
+		if ($this->isConnected() && $this->dbExists($db) && $this->userExists($db, $user)) {
+			$result = $this->selectDB($db)->selectCollection("system.users")->find(array( 'user' => $user ));
+
+			// ugly fix to return user
+			foreach ($result as $user) {
+				return $user;
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * Returns the users for given database.
+	 * If no connection exists or the database doesn't exist,
+	 * null is returned.
+	 *
+	 * @param string $db the database name
+	 * @return array $users the users in DB
+	 */
+	private function getUsers($db) {
+		if ($this->isConnected() && $this->dbExists($db)) {
+			$result = $this->selectDB($db)->selectCollection("system.users")->find();
+
+			$users = array();
+
+			foreach ($result as $record) {
+				$users[] = $record['user'];
+			}
+
+			return $users;
+		}
+
+		return null;
+	}
+
+	/**
+	 * Checks if the given user exists in given database.
+	 * If no connection exists or the given database doesn't exist
+	 * null is returned.
+	 *
+	 * @param string $db the database name
+	 * @param string $user the user to check
+	 * @return bool true if user exists
+	 */
+	private function userExists($db, $user) {
+		if ($this->isConnected() && $this->dbExists($db)) {
+			$users = $this->getUsers($db);
+
+			return in_array($user, $users);
+		}
+
+		return null;
+	}
+
+	/**
+	 * Renames the MongoDB database to provided name.
+	 * If no connection exists, the source DB doesn't exist or the target DB already exists,
+	 * null is returned.
+	 *
+	 * @param string $old_name the old database name
+	 * @param string $new_name the new database name
+	 * @return bool true if renamed
+	 */
+	private function renameDB($old_name, $new_name) {
+		if ($this->isConnected() && $this->dbExists($old_name) && !$this->dbExists($new_name)) {
+			if ($this->exec($old_name, "db.copyDatabase(\"".$old_name."\", \"".$new_name."\", \"".self::HOST."\", \"".self::USER."\", \"".self::PW."\")")) {
+				$this->dropDB($old_name);
+
+				return true;
+			}
+
+			return false;
+		}
+
+		return null;
+	}
+
+	/**
+	 * Switched the selected database.
+	 * MongoDB acts on a per-DB level (user management) and we always need to
+	 * ensure we have the right DB selected.
+	 * If no connection exists and thus nothing is done,
+	 * null is returned.
+	 *
+	 * @param string $db the database to use
+	 * @return object the MongoDB database object
+	 */
+	private function selectDB($db) {
+		if ($this->isConnected()) {
+			return $this->_connection->selectDB($db);
+		}
+
+		return null;
+	}
+
+
+	/**
+	 * This function is called when a DB is created from within the ISPConfig3 interface.
+	 * We need to create the DB and allow all users to connect to it that are choosen.
+	 * Since MongoDB doesn't create a DB before any data is stored in it, it's important
+	 * to store the users so it contains data -> is created.
+	 *
+	 * @param string $event_name the name of the event (insert, update, delete)
+	 * @param array $data the event data (old and new)
+	 * @return only if something is wrong
+	 */
+	function db_insert($event_name, $data) {
+		global $app, $conf;
+
+		// beside checking for MongoDB we also check if the DB is active because only then we add users
+		// -> MongoDB needs users to create the DB
+		if ($data['new']['type'] == 'mongo' && $data['new']['active'] == 'y') {
+			if ($this->connect() === false) {
+				$app->log("Unable to connect to MongoDB: Connecting using connect() failed.", LOGLEVEL_ERROR);
+				return;
+			}
+
+			$db_user = $app->db->queryOneRecord("SELECT `database_user`, `database_password_mongo` FROM `web_database_user` WHERE `database_user_id` = '" . intval($data['new']['database_user_id']) . "'");
+			$db_ro_user = $app->db->queryOneRecord("SELECT `database_user`, `database_password_mongo` FROM `web_database_user` WHERE `database_user_id` = '" . intval($data['new']['database_ro_user_id']) . "'");
+
+			$user = $db_user['database_user'];
+			$password = $db_user['database_password_mongo'];
+
+			$ro_user = $db_ro_user['database_user'];
+			$ro_password = $db_ro_user['database_password_mongo'];
+
+			$db = $data['new']['database_name'];
+
+			if ((bool) $db_user) {
+			    if ($user == 'root') {
+				$app->log("User root not allowed for client databases", LOGLEVEL_WARNING);
+			    } else {
+				if (!$this->addUser($db, array(
+					'username' => $user,
+					'password' => $password,
+					'roles' => array(
+						"readWrite",
+						"dbAdmin"
+					)
+				))) {
+					$app->log("Error while adding user: ".$user." to DB: ".$db, LOGLEVEL_WARNING);
+				}
+			    }
+			}
+
+			if ($db_ro_user && $data['new']['database_user_id'] != $data['new']['database_ro_user_id']) {
+			    if ($user == 'root') {
+				$app->log("User root not allowed for client databases", LOGLEVEL_WARNING);
+			    } else {
+				if (!$this->addUser($db, array(
+					'username' => $ro_user,
+					'password' => $ro_password,
+					'roles' => array(
+						"read"
+					)
+				))) {
+					$app->log("Error while adding read-only user: ".$user." to DB: ".$db, LOGLEVEL_WARNING);
+				}
+			    }
+			}
+
+			$this->disconnect();
+		}
+	}
+
+	/**
+	 * This function is called when a DB is updated from within the ISPConfig interface.
+	 * Updating the DB needs a lot of changes. First, we need to recheck all users that
+	 * have permissions to access the DB. Maybe we also need to rename the DB and change
+	 * it's type (MySQL, MongoDB etc.)...hard work here :)
+	 *
+	 * @param string $event_name the name of the event (insert, update, delete)
+	 * @param array $data the event data (old and new)
+	 * @return only if something is wrong
+	 */
+	function db_update($event_name,$data) {
+		global $app, $conf;
+
+		if ($data['old']['active'] == 'n' && $data['new']['active'] == 'n') {
+			return;
+		}
+
+		// currently switching from MongoDB <-> MySQL isn't supported
+		if ($data['old']['type'] == 'mongo' && $data['new']['type'] == 'mongo') {
+			if ($this->connect() === false) {
+				$app->log("Unable to connect to MongoDB: Connecting using connect() failed.", LOGLEVEL_ERROR);
+				return;
+			}
+
+			$db_user = $app->db->queryOneRecord("SELECT `database_user`, `database_password_mongo` FROM `web_database_user` WHERE `database_user_id` = '" . intval($data['new']['database_user_id']) . "'");
+			$db_ro_user = $app->db->queryOneRecord("SELECT `database_user`, `database_password_mongo` FROM `web_database_user` WHERE `database_user_id` = '" . intval($data['new']['database_ro_user_id']) . "'");
+
+			$user = $db_user['database_user'];
+			$password = $db_user['database_password_mongo'];
+
+			$ro_user = $db_ro_user['database_user'];
+			$ro_password = $db_ro_user['database_password_mongo'];
+
+			$db = $data['new']['database_name'];
+
+			// create the database user if database was disabled before
+			if ($data['new']['active'] == 'y' && $data['old']['active'] == 'n') {
+				// since MongoDB creates DBs on-the-fly we can use the db_insert method which takes care of adding
+				// users to a given DB
+				$this->db_insert($event_name, $data);
+			} else if ($data['new']['active'] == 'n' && $data['old']['active'] == 'y') {
+				$users = $this->getUsers($db);
+
+				if ((bool) $users) {
+					foreach ($users as $user) {
+						$this->dropUser($user, $db);
+					}
+				}
+			} else {
+				// selected user has changed -> drop old one
+				if ($data['new']['database_user_id'] != $data['old']['database_user_id']) {
+					$old_db_user = $app->db->queryOneRecord("SELECT `database_user`, `database_password_mongo` FROM `web_database_user` WHERE `database_user_id` = '" . intval($data['old']['database_user_id']) . "'");
+
+					if ((bool) $old_db_user) {
+						if ($old_db_user['database_user'] == 'root') {
+							$app->log("User root not allowed for client databases", LOGLEVEL_WARNING);
+						} else {
+							$this->dropUser($old_db_user['database_user'], $db);
+						}
+					}
+				}
+
+				// selected read-only user has changed -> drop old one
+				if ($data['new']['database_ro_user_id'] != $data['old']['database_ro_user_id']) {
+					$old_db_user = $app->db->queryOneRecord("SELECT `database_user`, `database_password_mongo` FROM `web_database_user` WHERE `database_user_id` = '" . intval($data['old']['database_ro_user_id']) . "'");
+
+					if ((bool) $old_db_user) {
+						if ($old_db_user['database_user'] == 'root') {
+							$app->log("User root not allowed for client databases",LOGLEVEL_WARNING);
+						} else {
+							$this->dropUser($old_db_user['database_user'], $db);
+						}
+					}
+				}
+
+				// selected user has changed -> add new one
+				if ($data['new']['database_user_id'] != $data['old']['database_user_id']) {
+					if ((bool) $db_user) {
+						if ($user == 'root') {
+							$app->log("User root not allowed for client databases", LOGLEVEL_WARNING);
+						} else {
+							$this->addUser($db, array(
+								'username' => $user,
+								'password' => $password,
+								'roles' => array(
+									"readWrite",
+									"dbAdmin"
+								)
+							));
+						}
+					}
+				}
+
+				// selected read-only user has changed -> add new one
+				if ($data['new']['database_ro_user_id'] != $data['old']['database_ro_user_iduser_id']) {
+					if ((bool) $db_ro_user && $data['new']['database_user_id'] != $data['new']['database_ro_user_id']) {
+						if ($ro_user == 'root') {
+							$app->log("User root not allowed for client databases", LOGLEVEL_WARNING);
+						} else {
+							$this->addUser($db, array(
+								'username' => $ro_user,
+								'password' => $ro_password,
+								'roles' => array(
+									"read"
+								)
+							));
+						}
+					}
+				}
+
+				// renamed?
+				/*
+				if ($data['old']['database_name'] != $data['new']['database_name']) {
+					$old_name = $data['old']['database_name'];
+					$new_name = $data['new']['database_name'];
+
+					if ($this->renameDB($oldName, $newName)) {
+						$app->log("Renamed MongoDB database: ".$old_name." -> ".$new_name, LOGLEVEL_DEBUG);
+					} else {
+						$app->log("Renaming MongoDB database failed: ".$old_name." -> ".$new_name, LOGLEVEL_WARNING);
+					}
+				}
+				*/
+			}
+
+			// switching from MySQL <-> Mongo isn't supported
+			// no idea what we should do here...would be best to permit in interface?
+
+			// remote access isn't supported by MongoDB (limiting to IP),
+			// we therefor don't listen for it's changes
+		}
+
+		$this->disconnect();
+	}
+
+	/**
+	 * This function is called when a DB is deleted from within the ISPConfig interface.
+	 * All we need to do is to delete the database.
+	 *
+	 * @param string $event_name the name of the event (insert, update, delete)
+	 * @param array $data the event data (old and new)
+	 * @return only if something is wrong
+	 */
+	function db_delete($event_name,$data) {
+		global $app, $conf;
+
+		if ($data['old']['type'] == 'mongo') {
+			if ($this->connect() === false) {
+				$app->log("Unable to connect to MongoDB: Connecting using connect() failed.", LOGLEVEL_ERROR);
+				return;
+			}
+
+			$db_to_drop = $data['old']['database_name'];
+
+			if ($this->dropDB($db_to_drop)) {
+				$app->log("Dropping MongoDB database: ".$db_to_drop, LOGLEVEL_DEBUG);
+			} else {
+				$app->log("Error while dropping MongoDB database: ".$db_to_drop, LOGLEVEL_WARNING);
+			}
+
+			$this->disconnect();
+		}
+	}
+
+
+	/**
+	 * This function is called when a user is inserted from within the ISPConfig interface.
+	 * Since users are separated from databases we don't do anything here.
+	 * As soon as an user is associated to a DB, we add him there.
+	 *
+	 * @param string $event_name the name of the event (insert, update, delete)
+	 * @param array $data the event data (old and new)
+	 */
+	function db_user_insert($event_name,$data) {}
+
+	/**
+	 * This function is called when a user is updated from within the ISPConfig interface.
+	 * The only thing we need to listen for here are password changes.
+	 * We than need to change those in all databases the user uses.
+	 *
+	 * @param string $event_name the name of the event (insert, update, delete)
+	 * @param array $data the event data (old and new)
+	 * @return only if something is wrong
+	 */
+	function db_user_update($event_name,$data) {
+		global $app, $conf;
+
+		if ($data['old']['database_user'] == $data['new']['database_user']
+		    && ($data['old']['database_password'] == $data['new']['database_password']
+		    || $data['new']['database_password'] == '')) {
+		    return;
+		}
+
+		if ($this->connect() === false) {
+			$app->log("Unable to connect to MongoDB: Connecting using connect() failed.", LOGLEVEL_ERROR);
+			return;
+		}
+
+		if ($data['old']['database_user'] != $data['new']['database_user']) {
+			// username has changed
+			$dbs = $this->getDBs();
+
+			if ((bool) $dbs) {
+				foreach ($dbs as $db) {
+					if ($this->userExists($db, $data['old']['database_user'])) {
+						if (!$this->userExists($db, $data['new']['database_user'])) {
+							$user = $this->getUser($db, $data['old']['database_user']);
+
+							if ($this->dropUser($data['old']['database_user'], $db)) {
+								if ($this->addUser($db, array(
+									'username' => $data['new']['database_user'],
+									'password' => md5($data['new']['database_password_mongo']),
+									'roles' => $user['roles']
+								))) {
+									$app->log("Created user: ".$data['new']['database_user']." in DB: ".$db, LOGLEVEL_DEBUG);
+								} else {
+									$app->log("Couldn't create user: ".$data['new']['database_user']." in DB: ".$db, LOGLEVEL_WARNING);
+								}
+							} else {
+								$app->log("Couldn't drop user: ".$data['old']['database_user']." in DB: ".$db, LOGLEVEL_WARNING);
+							}
+						} else {
+							$app->log("User: ".$data['new']['database_user']." already exists in DB: ".$db, LOGLEVEL_WARNING);
+						}
+					}
+				}
+			}
+		}
+
+		if ($data['old']['database_password'] != $data['new']['database_password']
+			|| $data['old']['database_user'] != $data['new']['database_user']) {
+			// password only has changed
+			$dbs = $this->getDBs();
+
+			if ((bool) $dbs) {
+				foreach ($dbs as $db) {
+					if ($this->userExists($db, $data['new']['database_user'])) {
+						if ($this->changePassword($db, $data['new']['database_user'], md5($data['new']['database_password_mongo']))) {
+							$app->log("Changed user's: ".$data['new']['database_user']." password in DB: ".$db, LOGLEVEL_DEBUG);
+						} else {
+							$app->log("Couldn't change user's: ".$data['new']['database_user']." password in DB: ".$db, LOGLEVEL_WARNING);
+						}
+					}
+				}
+			}
+		}
+
+		$this->disconnect();
+	}
+
+	/**
+	 * This function is called when a user is deleted from within the ISPConfig interface.
+	 * Since MongoDB uses per-DB user management, we have to find every database where the user is
+	 * activated and delete him there.
+	 *
+	 * @param string $event_name the name of the event (insert, update, delete)
+	 * @param array $data the event data (old and new)
+	 * @return only if something is wrong
+	 */
+	function db_user_delete($event_name, $data) {
+		global $app, $conf;
+
+		if ($this->connect() === false) {
+			$app->log("Unable to connect to MongoDB: Connecting using connect() failed.", LOGLEVEL_ERROR);
+			return;
+		}
+
+		if ($this->dropUser($data['old']['database_user']) === true) {
+			$app->log("Dropped MongoDB user: ".$data['old']['database_user'], LOGLEVEL_DEBUG);
+		} else {
+			$app->log("Error while dropping MongoDB user: ".$data['old']['database_user'], LOGLEVEL_WARNING);
+		}
+
+		$this->disconnect();
+	}
+
+}

--
Gitblit v1.9.1