From d87f76019fc231ec20d95126a7fee0487e7be5f0 Mon Sep 17 00:00:00 2001
From: tbrehm <t.brehm@ispconfig.org>
Date: Tue, 14 Aug 2012 10:56:20 -0400
Subject: [PATCH] - Added new web folder named private to web folder layout. The folder is intended to store data that shall not be visible in the web directory, it is owned by the user of the web. - Changed ownership of web root directory to root user in all security modes to prevent symlink attacks. - Apache log files are now owned by user root. - Improved functions in system library.

---
 server/plugins-available/nginx_plugin.inc.php |  657 +++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 539 insertions(+), 118 deletions(-)

diff --git a/server/plugins-available/nginx_plugin.inc.php b/server/plugins-available/nginx_plugin.inc.php
index b4ba1b7..9d444f5 100644
--- a/server/plugins-available/nginx_plugin.inc.php
+++ b/server/plugins-available/nginx_plugin.inc.php
@@ -41,7 +41,7 @@
 	function onInstall() {
 		global $conf;
 
-		if($conf['services']['web'] == true) {
+		if($conf['services']['web'] == true && !@is_link('/usr/local/ispconfig/server/plugins-enabled/apache2_plugin.inc.php')) {
 			return true;
 		} else {
 			return false;
@@ -168,7 +168,7 @@
 					$app->log("Creating CA-signed SSL Cert for: $domain",LOGLEVEL_DEBUG);
 					if (filesize($crt_file)==0 || !file_exists($crt_file)) $app->log("CA-Certificate signing failed.  openssl ca -out $crt_file -config ".$web_config['CA_path']."/openssl.cnf -passin pass:".$web_config['CA_pass']." -in $csr_file",LOGLEVEL_ERROR);
 				};
-				if (filesize($crt_file)==0 || !file_exists($crt_file)){
+				if (@filesize($crt_file)==0 || !file_exists($crt_file)){
 					exec("openssl req -x509 -passin pass:$ssl_password -passout pass:$ssl_password -key $key_file -in $csr_file -out $crt_file -days $ssl_days -config $config_file ");
 					$app->log("Creating self-signed SSL Cert for: $domain",LOGLEVEL_DEBUG);
 				};
@@ -191,14 +191,24 @@
 		//* Save a SSL certificate to disk
 		if($data["new"]["ssl_action"] == 'save') {
 			$ssl_dir = $data["new"]["document_root"]."/ssl";
-			$domain = $data["new"]["ssl_domain"];
+			$domain = ($data["new"]["ssl_domain"] != '')?$data["new"]["ssl_domain"]:$data["new"]["domain"];
 			$csr_file = $ssl_dir.'/'.$domain.".csr";
 			$crt_file = $ssl_dir.'/'.$domain.".crt";
 			//$bundle_file = $ssl_dir.'/'.$domain.".bundle";
 			if(trim($data["new"]["ssl_request"]) != '') file_put_contents($csr_file,$data["new"]["ssl_request"]);
 			if(trim($data["new"]["ssl_cert"]) != '') file_put_contents($crt_file,$data["new"]["ssl_cert"]);
 			// for nginx, bundle files have to be appended to the certificate file
-			if(trim($data["new"]["ssl_bundle"]) != '') file_put_contents($crt_file,$data["new"]["ssl_bundle"], FILE_APPEND);
+			if(trim($data["new"]["ssl_bundle"]) != ''){				
+				if(file_exists($crt_file)){
+					$crt_file_contents = trim(file_get_contents($crt_file));
+				} else {
+					$crt_file_contents = '';
+				}
+				if($crt_file_contents != '') $crt_file_contents .= "\n";
+				$crt_file_contents .= $data["new"]["ssl_bundle"];
+				file_put_contents($crt_file,$app->file->unix_nl($crt_file_contents));
+				unset($crt_file_contents);
+			}
 			/* Update the DB of the (local) Server */
 			$app->db->query("UPDATE web_domain SET ssl_action = '' WHERE domain = '".$data['new']['domain']."'");
 			/* Update also the master-DB of the Server-Farm */
@@ -209,7 +219,7 @@
 		//* Delete a SSL certificate
 		if($data['new']['ssl_action'] == 'del') {
 			$ssl_dir = $data['new']['document_root'].'/ssl';
-			$domain = $data['new']['ssl_domain'];
+			$domain = ($data["new"]["ssl_domain"] != '')?$data["new"]["ssl_domain"]:$data["new"]["domain"];
 			$csr_file = $ssl_dir.'/'.$domain.'.csr';
 			$crt_file = $ssl_dir.'/'.$domain.'.crt';
 			//$bundle_file = $ssl_dir.'/'.$domain.'.bundle';
@@ -230,7 +240,6 @@
 			$app->log('Deleting SSL Cert for: '.$domain,LOGLEVEL_DEBUG);
 		}
 
-
 	}
 
 
@@ -247,7 +256,13 @@
 
 	function update($event_name,$data) {
 		global $app, $conf;
-
+		
+		//* Check if the apache plugin is enabled
+		if(@is_link('/usr/local/ispconfig/server/plugins-enabled/apache2_plugin.inc.php')) {
+			$app->log('The nginx plugin can not be used together with the apache2 plugin..',LOGLEVEL_WARN);
+			return 0;
+		}
+		
 		if($this->action != 'insert') $this->action = 'update';
 
 		if($data['new']['type'] != 'vhost' && $data['new']['parent_domain_id'] > 0) {
@@ -324,8 +339,14 @@
 			$tmp_docroot = explode('/',$data['old']['document_root']);
 			unset($tmp_docroot[count($tmp_docroot)-1]);
 			$old_dir = implode('/',$tmp_docroot);
-
-			exec('rm -rf '.$data['new']['document_root']);
+			
+			//* Check if there is already some data in the new docroot and rename it as we need a clean path to move the existing site to the new path
+			if(@is_dir($data['new']['document_root'])) {
+				rename($data['new']['document_root'],$data['new']['document_root'].'_bak_'.date('Y_m_d'));
+				$app->log('Renaming existing directory in new docroot location. mv '.$data['new']['document_root'].' '.$data['new']['document_root'].'_bak_'.date('Y_m_d'),LOGLEVEL_DEBUG);
+			}
+			
+			//* Create new base directory, if it does not exist yet
 			if(!is_dir($new_dir)) exec('mkdir -p '.$new_dir);
 			exec('mv '.$data['old']['document_root'].' '.$new_dir);
 			$app->log('Moving site to new document root: mv '.$data['old']['document_root'].' '.$new_dir,LOGLEVEL_DEBUG);
@@ -503,18 +524,42 @@
 
 		// Create group and user, if not exist
 		$app->uses('system');
+		
+		if($web_config['connect_userid_to_webid'] == 'y') {
+			//* Calculate the uid and gid
+			$connect_userid_to_webid_start = ($web_config['connect_userid_to_webid_start'] < 1000)?1000:intval($web_config['connect_userid_to_webid_start']);
+			$fixed_uid_gid = intval($connect_userid_to_webid_start + $data['new']['domain_id']);
+			$fixed_uid_param = '--uid '.$fixed_uid_gid;
+			$fixed_gid_param = '--gid '.$fixed_uid_gid;
+			
+			//* Check if a ispconfigend user and group exists and create them
+			if(!$app->system->is_group('ispconfigend')) {
+				exec('groupadd --gid '.($connect_userid_to_webid_start + 10000).' ispconfigend');
+			}
+			if(!$app->system->is_user('ispconfigend')) {
+				exec('useradd -g ispconfigend -d /usr/local/ispconfig --uid '.($connect_userid_to_webid_start + 10000).' ispconfigend');
+			}
+		} else {
+			$fixed_uid_param = '';
+			$fixed_gid_param = '';
+		}
 
 		$groupname = escapeshellcmd($data['new']['system_group']);
 		if($data['new']['system_group'] != '' && !$app->system->is_group($data['new']['system_group'])) {
-			exec('groupadd '.$groupname);
+			exec('groupadd '.$fixed_gid_param.' '.$groupname);
 			if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' groupadd '.$groupname);
 			$app->log('Adding the group: '.$groupname,LOGLEVEL_DEBUG);
 		}
 
 		$username = escapeshellcmd($data['new']['system_user']);
 		if($data['new']['system_user'] != '' && !$app->system->is_user($data['new']['system_user'])) {
-			exec('useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname -G sshusers $username -s /bin/false");
-			if($apache_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname -G sshusers $username -s /bin/false");
+			if($web_config['add_web_users_to_sshusers_group'] == 'y') {
+				exec('useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param -G sshusers $username -s /bin/false");
+				if($nginx_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param -G sshusers $username -s /bin/false");
+			} else {
+				exec('useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param $username -s /bin/false");
+				if($nginx_chrooted) $this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' useradd -d '.escapeshellcmd($data['new']['document_root'])." -g $groupname $fixed_uid_param $username -s /bin/false");
+			}
 			$app->log('Adding the user: '.$username,LOGLEVEL_DEBUG);
 		}
 
@@ -532,74 +577,91 @@
 
 		if($this->action == 'insert' || $data["new"]["system_user"] != $data["old"]["system_user"]) {
 			// Chown and chmod the directories below the document root
-			$this->_exec('chown -R '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']));
+			$this->_exec('chown -R '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']).'/web');
 			// The document root itself has to be owned by root in normal level and by the web owner in security level 20
 			if($web_config['security_level'] == 20) {
-				$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']));
+				$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']).'/web');
 			} else {
-				$this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root']));
+				$this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root']).'/web');
 			}
 		}
-
-
-
+		
 		//* If the security level is set to high
-		if($web_config['security_level'] == 20) {
+		if(($this->action == 'insert' && $data['new']['type'] == 'vhost') or ($web_config['set_folder_permissions_on_update'] == 'y' && $data['new']['type'] == 'vhost')) {
+			if($web_config['security_level'] == 20) {
 
-			$this->_exec('chmod 751 '.escapeshellcmd($data['new']['document_root']));
-			$this->_exec('chmod 751 '.escapeshellcmd($data['new']['document_root']).'/*');
-			$this->_exec('chmod 710 '.escapeshellcmd($data['new']['document_root'].'/web'));
+				$this->_exec('chmod 751 '.escapeshellcmd($data['new']['document_root']));
+				$this->_exec('chmod 751 '.escapeshellcmd($data['new']['document_root']).'/*');
+				$this->_exec('chmod 710 '.escapeshellcmd($data['new']['document_root'].'/web'));
 
-			// make tmp directory writable for nginx and the website users
-			$this->_exec('chmod 777 '.escapeshellcmd($data['new']['document_root'].'/tmp'));
+				// make tmp directory writable for nginx and the website users
+				$this->_exec('chmod 777 '.escapeshellcmd($data['new']['document_root'].'/tmp'));
 			
-			// Set Log symlink to 755 to make the logs accessible by the FTP user
-			$this->_exec("chmod 755 ".escapeshellcmd($data["new"]["document_root"])."/log");
+				// Set Log symlink to 755 to make the logs accessible by the FTP user
+				$this->_exec("chmod 755 ".escapeshellcmd($data["new"]["document_root"])."/log");
 
-			$command = 'usermod';
-			$command .= ' --groups sshusers';
-			$command .= ' '.escapeshellcmd($data['new']['system_user']);
-			$this->_exec($command);
+				if($web_config['add_web_users_to_sshusers_group'] == 'y') {
+					$command = 'usermod';
+					$command .= ' --groups sshusers';
+					$command .= ' '.escapeshellcmd($data['new']['system_user']);
+					$this->_exec($command);
+				}
 
-			//* if we have a chrooted nginx environment
-			if($nginx_chrooted) {
-				$this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
+				//* if we have a chrooted nginx environment
+				if($nginx_chrooted) {
+					$this->_exec('chroot '.escapeshellcmd($web_config['website_basedir']).' '.$command);
 
-				//* add the nginx user to the client group in the chroot environment
-				$tmp_groupfile = $app->system->server_conf['group_datei'];
-				$app->system->server_conf['group_datei'] = $web_config['website_basedir'].'/etc/group';
-				$app->system->add_user_to_group($groupname, escapeshellcmd($web_config['user']));
-				$app->system->server_conf['group_datei'] = $tmp_groupfile;
-				unset($tmp_groupfile);
-			}
+					//* add the nginx user to the client group in the chroot environment
+					$tmp_groupfile = $app->system->server_conf['group_datei'];
+					$app->system->server_conf['group_datei'] = $web_config['website_basedir'].'/etc/group';
+					$app->system->add_user_to_group($groupname, escapeshellcmd($web_config['user']));
+					$app->system->server_conf['group_datei'] = $tmp_groupfile;
+					unset($tmp_groupfile);
+				}
 
-			//* add the nginx user to the client group
-			$app->system->add_user_to_group($groupname, escapeshellcmd($web_config['nginx_user']));
+				//* add the nginx user to the client group
+				$app->system->add_user_to_group($groupname, escapeshellcmd($web_config['nginx_user']));
+				
+				//* Chown all default directories
+				$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']));
+				$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/cgi-bin'));
+				$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/log'));
+				$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/ssl'));
+				$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/tmp'));
+				$this->_exec('chown -R '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/web'));
 
-			$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root']));
+				/*
+				* Workaround for jailkit: If jailkit is enabled for the site, the 
+				* website root has to be owned by the root user and we have to chmod it to 755 then
+				*/
 
-			/*
-			* Workaround for jailkit: If jailkit is enabled for the site, the 
-			* website root has to be owned by the root user and we have to chmod it to 755 then
-			*/
+				//* Check if there is a jailkit user for this site
+				$tmp = $app->db->queryOneRecord('SELECT count(shell_user_id) as number FROM shell_user WHERE parent_domain_id = '.$data['new']['domain_id']." AND chroot = 'jailkit'");
+				if($tmp['number'] > 0) {
+					$this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root']));
+					$this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root']));
+				}
+				unset($tmp);
 
-			//* Check if there is a jailkit user for this site
-			$tmp = $app->db->queryOneRecord('SELECT count(shell_user_id) as number FROM shell_user WHERE parent_domain_id = '.$data['new']['domain_id']." AND chroot = 'jailkit'");
-			if($tmp['number'] > 0) {
+				// If the security Level is set to medium
+			} else {
+
 				$this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root']));
+				$this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root'].'/cgi-bin'));
+				$this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root'].'/log'));
+				$this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root'].'/ssl'));
+				$this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root'].'/web'));
+				
+				// make temp directory writable for nginx and the website users
+				$this->_exec('chmod 777 '.escapeshellcmd($data['new']['document_root'].'/tmp'));
+				
 				$this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root']));
+				$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/cgi-bin'));
+				$this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root'].'/log'));
+				$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/tmp'));
+				$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/ssl'));
+				$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/web'));
 			}
-			unset($tmp);
-
-			// If the security Level is set to medium
-		} else {
-
-			$this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root']));
-			$this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root'].'/*'));
-			$this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root']));
-
-			// make temp directory writable for nginx and the website users
-			$this->_exec('chmod 777 '.escapeshellcmd($data['new']['document_root'].'/tmp'));
 		}
 
 		// Change the ownership of the error log to the owner of the website
@@ -650,7 +712,39 @@
 		if($data['new']['ipv6_address'] != '') $tpl->setVar('ipv6_enabled', 1);
 		
 		// PHP-FPM
-		$pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
+		// Support for multiple PHP versions
+		/*
+		if(trim($data['new']['fastcgi_php_version']) != ''){
+			$default_php_fpm = false;
+			list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['new']['fastcgi_php_version']));
+			if(substr($custom_php_fpm_ini_dir,-1) != '/') $custom_php_fpm_ini_dir .= '/';
+		} else {
+			$default_php_fpm = true;
+		}
+		*/
+		if($data['new']['php'] != 'no'){
+			if(trim($data['new']['fastcgi_php_version']) != ''){
+				$default_php_fpm = false;
+				list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['new']['fastcgi_php_version']));
+				if(substr($custom_php_fpm_ini_dir,-1) != '/') $custom_php_fpm_ini_dir .= '/';
+			} else {
+				$default_php_fpm = true;
+			}
+		} else {
+			if(trim($data['old']['fastcgi_php_version']) != '' && $data['old']['php'] != 'no'){
+				$default_php_fpm = false;
+				list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['old']['fastcgi_php_version']));
+				if(substr($custom_php_fpm_ini_dir,-1) != '/') $custom_php_fpm_ini_dir .= '/';
+			} else {
+				$default_php_fpm = true;
+			}
+		}
+		
+		if($default_php_fpm){
+			$pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
+		} else {
+			$pool_dir = $custom_php_fpm_pool_dir;
+		}
 		if(substr($pool_dir,-1) != '/') $pool_dir .= '/';
 		$pool_name = 'web'.$data['new']['domain_id'];
 		$socket_dir = escapeshellcmd($web_config['php_fpm_socket_dir']);
@@ -668,6 +762,9 @@
 		$fpm_socket = $socket_dir.$pool_name.'.sock';
 		$tpl->setVar('fpm_socket', $fpm_socket);
 		$vhost_data['fpm_port'] = $web_config['php_fpm_start_port'] + $data['new']['domain_id'] - 1;
+		
+		// backwards compatibility; since ISPConfig 3.0.5, the PHP mode for nginx is called 'php-fpm' instead of 'fast-cgi'. The following line makes sure that old web sites that have 'fast-cgi' in the database still get PHP-FPM support.
+		if($vhost_data['php'] == 'fast-cgi') $vhost_data['php'] = 'php-fpm';
 		
 		// Custom nginx directives
 		$final_nginx_directives = array();
@@ -716,9 +813,10 @@
 
 		// Rewrite rules
 		$rewrite_rules = array();
-		if($data['new']['redirect_type'] != '') {
+		if($data['new']['redirect_type'] != '' && $data['new']['redirect_path'] != '') {
 			if(substr($data['new']['redirect_path'],-1) != '/') $data['new']['redirect_path'] .= '/';
 			if(substr($data['new']['redirect_path'],0,8) == '[scheme]') $data['new']['redirect_path'] = '$scheme'.substr($data['new']['redirect_path'],8);
+			
 			/* Disabled path extension
 			if($data['new']['redirect_type'] == 'no' && substr($data['new']['redirect_path'],0,4) != 'http') {
 				$data['new']['redirect_path'] = $data['new']['document_root'].'/web'.realpath($data['new']['redirect_path']).'/';
@@ -727,22 +825,91 @@
 
 			switch($data['new']['subdomain']) {
 				case 'www':
+					if(substr($data['new']['redirect_path'],0,1) == '/'){ // relative path
+						$rewrite_exclude = '(?!'.substr($data['new']['redirect_path'],0,-1).')';
+					} else { // URL - check if URL is local
+						$tmp_redirect_path = $data['new']['redirect_path'];
+						if(substr($tmp_redirect_path,0,7) == '$scheme') $tmp_redirect_path = 'http'.substr($tmp_redirect_path,7);
+						$tmp_redirect_path_parts = parse_url($tmp_redirect_path);
+						if($tmp_redirect_path_parts['host'] == $data['new']['domain'] && ($tmp_redirect_path_parts['port'] == '80' || $tmp_redirect_path_parts['port'] == '443' || !isset($tmp_redirect_path_parts['port']))){
+							if(substr($tmp_redirect_path_parts['path'],-1) == '/') $tmp_redirect_path_parts['path'] = substr($tmp_redirect_path_parts['path'],0,-1);
+							if(substr($tmp_redirect_path_parts['path'],0,1) != '/') $tmp_redirect_path_parts['path'] = '/'.$tmp_redirect_path_parts['path'];
+							$rewrite_exclude = '(?!'.$tmp_redirect_path_parts['path'].')';
+						} else {
+							$rewrite_exclude = '(.?)';
+						}
+						unset($tmp_redirect_path);
+						unset($tmp_redirect_path_parts);
+					}
 					$rewrite_rules[] = array(	'rewrite_domain' 	=> '^'.$data['new']['domain'],
 					'rewrite_type' 		=> ($data['new']['redirect_type'] == 'no')?'':$data['new']['redirect_type'],
-					'rewrite_target' 	=> $data['new']['redirect_path']);
+					'rewrite_target' 	=> $data['new']['redirect_path'],
+					'rewrite_exclude'	=> $rewrite_exclude);
+					
+					if(substr($data['new']['redirect_path'],0,1) == '/'){ // relative path
+						$rewrite_exclude = '(?!'.substr($data['new']['redirect_path'],0,-1).')';
+					} else { // URL - check if URL is local
+						$tmp_redirect_path = $data['new']['redirect_path'];
+						if(substr($tmp_redirect_path,0,7) == '$scheme') $tmp_redirect_path = 'http'.substr($tmp_redirect_path,7);
+						$tmp_redirect_path_parts = parse_url($tmp_redirect_path);
+						if($tmp_redirect_path_parts['host'] == 'www.'.$data['new']['domain'] && ($tmp_redirect_path_parts['port'] == '80' || $tmp_redirect_path_parts['port'] == '443' || !isset($tmp_redirect_path_parts['port']))){
+							if(substr($tmp_redirect_path_parts['path'],-1) == '/') $tmp_redirect_path_parts['path'] = substr($tmp_redirect_path_parts['path'],0,-1);
+							if(substr($tmp_redirect_path_parts['path'],0,1) != '/') $tmp_redirect_path_parts['path'] = '/'.$tmp_redirect_path_parts['path'];
+							$rewrite_exclude = '(?!'.$tmp_redirect_path_parts['path'].')';
+						} else {
+							$rewrite_exclude = '(.?)';
+						}
+						unset($tmp_redirect_path);
+						unset($tmp_redirect_path_parts);
+					}
 					$rewrite_rules[] = array(	'rewrite_domain' 	=> '^www.'.$data['new']['domain'],
 							'rewrite_type' 		=> ($data['new']['redirect_type'] == 'no')?'':$data['new']['redirect_type'],
-							'rewrite_target' 	=> $data['new']['redirect_path']);
+							'rewrite_target' 	=> $data['new']['redirect_path'],
+							'rewrite_exclude'	=> $rewrite_exclude);
 					break;
 				case '*':
+					if(substr($data['new']['redirect_path'],0,1) == '/'){ // relative path
+						$rewrite_exclude = '(?!'.substr($data['new']['redirect_path'],0,-1).')';
+					} else { // URL - check if URL is local
+						$tmp_redirect_path = $data['new']['redirect_path'];
+						if(substr($tmp_redirect_path,0,7) == '$scheme') $tmp_redirect_path = 'http'.substr($tmp_redirect_path,7);
+						$tmp_redirect_path_parts = parse_url($tmp_redirect_path);
+						if(substr($tmp_redirect_path_parts['host'],-strlen($data['new']['domain'])) == $data['new']['domain'] && ($tmp_redirect_path_parts['port'] == '80' || $tmp_redirect_path_parts['port'] == '443' || !isset($tmp_redirect_path_parts['port']))){
+							if(substr($tmp_redirect_path_parts['path'],-1) == '/') $tmp_redirect_path_parts['path'] = substr($tmp_redirect_path_parts['path'],0,-1);
+							if(substr($tmp_redirect_path_parts['path'],0,1) != '/') $tmp_redirect_path_parts['path'] = '/'.$tmp_redirect_path_parts['path'];
+							$rewrite_exclude = '(?!'.$tmp_redirect_path_parts['path'].')';
+						} else {
+							$rewrite_exclude = '(.?)';
+						}
+						unset($tmp_redirect_path);
+						unset($tmp_redirect_path_parts);
+					}
 					$rewrite_rules[] = array(	'rewrite_domain' 	=> $data['new']['domain'],
 						'rewrite_type' 		=> ($data['new']['redirect_type'] == 'no')?'':$data['new']['redirect_type'],
-						'rewrite_target' 	=> $data['new']['redirect_path']);
+						'rewrite_target' 	=> $data['new']['redirect_path'],
+						'rewrite_exclude'	=> $rewrite_exclude);
 					break;
 				default:
+					if(substr($data['new']['redirect_path'],0,1) == '/'){ // relative path
+						$rewrite_exclude = '(?!'.substr($data['new']['redirect_path'],0,-1).')';
+					} else { // URL - check if URL is local
+						$tmp_redirect_path = $data['new']['redirect_path'];
+						if(substr($tmp_redirect_path,0,7) == '$scheme') $tmp_redirect_path = 'http'.substr($tmp_redirect_path,7);
+						$tmp_redirect_path_parts = parse_url($tmp_redirect_path);
+						if($tmp_redirect_path_parts['host'] == $data['new']['domain'] && ($tmp_redirect_path_parts['port'] == '80' || $tmp_redirect_path_parts['port'] == '443' || !isset($tmp_redirect_path_parts['port']))){
+							if(substr($tmp_redirect_path_parts['path'],-1) == '/') $tmp_redirect_path_parts['path'] = substr($tmp_redirect_path_parts['path'],0,-1);
+							if(substr($tmp_redirect_path_parts['path'],0,1) != '/') $tmp_redirect_path_parts['path'] = '/'.$tmp_redirect_path_parts['path'];
+							$rewrite_exclude = '(?!'.$tmp_redirect_path_parts['path'].')';
+						} else {
+							$rewrite_exclude = '(.?)';
+						}
+						unset($tmp_redirect_path);
+						unset($tmp_redirect_path_parts);
+					}
 					$rewrite_rules[] = array(	'rewrite_domain' 	=> '^'.$data['new']['domain'],
 					'rewrite_type' 		=> ($data['new']['redirect_type'] == 'no')?'':$data['new']['redirect_type'],
-					'rewrite_target' 	=> $data['new']['redirect_path']);
+					'rewrite_target' 	=> $data['new']['redirect_path'],
+					'rewrite_exclude'	=> $rewrite_exclude);
 			}
 		}
 
@@ -751,30 +918,30 @@
 		$server_alias = array();
 		switch($data['new']['subdomain']) {
 			case 'www':
-				$server_alias[] .= 'www.'.$data['new']['domain'].' ';
+				$server_alias[] = 'www.'.$data['new']['domain'].' ';
 				break;
 			case '*':
-				$server_alias[] .= '*.'.$data['new']['domain'].' ';
+				$server_alias[] = '*.'.$data['new']['domain'].' ';
 				break;
 		}
 		if(is_array($aliases)) {
 			foreach($aliases as $alias) {
 				switch($alias['subdomain']) {
 					case 'www':
-						$server_alias[] .= 'www.'.$alias['domain'].' '.$alias['domain'].' ';
+						$server_alias[] = 'www.'.$alias['domain'].' '.$alias['domain'].' ';
 						break;
 					case '*':
-						$server_alias[] .= '*.'.$alias['domain'].' '.$alias['domain'].' ';
+						$server_alias[] = '*.'.$alias['domain'].' '.$alias['domain'].' ';
 						break;
 					default:
-						$server_alias[] .= $alias['domain'].' ';
+						$server_alias[] = $alias['domain'].' ';
 						break;
 				}
 				$app->log('Add server alias: '.$alias['domain'],LOGLEVEL_DEBUG);
 				// Rewriting
-				if($alias['redirect_type'] != '') {
+				if($alias['redirect_type'] != '' && $alias['redirect_path'] != '') {
 					if(substr($alias['redirect_path'],-1) != '/') $alias['redirect_path'] .= '/';
-					if(substr($alias['redirect_path'],0,8) == '[scheme]') $alias['redirect_path'] = '$scheme'.substr($alias['redirect_path'],8);
+					if(substr($alias['redirect_path'],0,8) == '[scheme]') $alias['redirect_path'] = '$scheme'.substr($alias['redirect_path'],8);	
 					
 					/* Disabled the path extension
 					if($data['new']['redirect_type'] == 'no' && substr($data['new']['redirect_path'],0,4) != 'http') {
@@ -784,22 +951,91 @@
 					
 					switch($alias['subdomain']) {
 						case 'www':
+							if(substr($alias['redirect_path'],0,1) == '/'){ // relative path
+								$rewrite_exclude = '(?!'.substr($alias['redirect_path'],0,-1).')';
+							} else { // URL - check if URL is local
+								$tmp_redirect_path = $alias['redirect_path'];
+								if(substr($tmp_redirect_path,0,7) == '$scheme') $tmp_redirect_path = 'http'.substr($tmp_redirect_path,7);
+								$tmp_redirect_path_parts = parse_url($tmp_redirect_path);
+								if($tmp_redirect_path_parts['host'] == $alias['domain'] && ($tmp_redirect_path_parts['port'] == '80' || $tmp_redirect_path_parts['port'] == '443' || !isset($tmp_redirect_path_parts['port']))){
+									if(substr($tmp_redirect_path_parts['path'],-1) == '/') $tmp_redirect_path_parts['path'] = substr($tmp_redirect_path_parts['path'],0,-1);
+									if(substr($tmp_redirect_path_parts['path'],0,1) != '/') $tmp_redirect_path_parts['path'] = '/'.$tmp_redirect_path_parts['path'];
+									$rewrite_exclude = '(?!'.$tmp_redirect_path_parts['path'].')';
+								} else {
+									$rewrite_exclude = '(.?)';
+								}
+								unset($tmp_redirect_path);
+								unset($tmp_redirect_path_parts);
+							}
 							$rewrite_rules[] = array(	'rewrite_domain' 	=> '^'.$alias['domain'],
 								'rewrite_type' 		=> ($alias['redirect_type'] == 'no')?'':$alias['redirect_type'],
-								'rewrite_target' 	=> $alias['redirect_path']);
+								'rewrite_target' 	=> $alias['redirect_path'],
+								'rewrite_exclude'	=> $rewrite_exclude);
+								
+							if(substr($alias['redirect_path'],0,1) == '/'){ // relative path
+								$rewrite_exclude = '(?!'.substr($alias['redirect_path'],0,-1).')';
+							} else { // URL - check if URL is local
+								$tmp_redirect_path = $alias['redirect_path'];
+								if(substr($tmp_redirect_path,0,7) == '$scheme') $tmp_redirect_path = 'http'.substr($tmp_redirect_path,7);
+								$tmp_redirect_path_parts = parse_url($tmp_redirect_path);
+								if($tmp_redirect_path_parts['host'] == 'www.'.$alias['domain'] && ($tmp_redirect_path_parts['port'] == '80' || $tmp_redirect_path_parts['port'] == '443' || !isset($tmp_redirect_path_parts['port']))){
+									if(substr($tmp_redirect_path_parts['path'],-1) == '/') $tmp_redirect_path_parts['path'] = substr($tmp_redirect_path_parts['path'],0,-1);
+									if(substr($tmp_redirect_path_parts['path'],0,1) != '/') $tmp_redirect_path_parts['path'] = '/'.$tmp_redirect_path_parts['path'];
+									$rewrite_exclude = '(?!'.$tmp_redirect_path_parts['path'].')';
+								} else {
+									$rewrite_exclude = '(.?)';
+								}
+								unset($tmp_redirect_path);
+								unset($tmp_redirect_path_parts);
+							}
 							$rewrite_rules[] = array(	'rewrite_domain' 	=> '^www.'.$alias['domain'],
 									'rewrite_type' 		=> ($alias['redirect_type'] == 'no')?'':$alias['redirect_type'],
-									'rewrite_target' 	=> $alias['redirect_path']);
+									'rewrite_target' 	=> $alias['redirect_path'],
+									'rewrite_exclude'	=> $rewrite_exclude);
 							break;
 						case '*':
+							if(substr($alias['redirect_path'],0,1) == '/'){ // relative path
+								$rewrite_exclude = '(?!'.substr($alias['redirect_path'],0,-1).')';
+							} else { // URL - check if URL is local
+								$tmp_redirect_path = $alias['redirect_path'];
+								if(substr($tmp_redirect_path,0,7) == '$scheme') $tmp_redirect_path = 'http'.substr($tmp_redirect_path,7);
+								$tmp_redirect_path_parts = parse_url($tmp_redirect_path);
+								if(substr($tmp_redirect_path_parts['host'],-strlen($alias['domain'])) == $alias['domain'] && ($tmp_redirect_path_parts['port'] == '80' || $tmp_redirect_path_parts['port'] == '443' || !isset($tmp_redirect_path_parts['port']))){
+									if(substr($tmp_redirect_path_parts['path'],-1) == '/') $tmp_redirect_path_parts['path'] = substr($tmp_redirect_path_parts['path'],0,-1);
+									if(substr($tmp_redirect_path_parts['path'],0,1) != '/') $tmp_redirect_path_parts['path'] = '/'.$tmp_redirect_path_parts['path'];
+									$rewrite_exclude = '(?!'.$tmp_redirect_path_parts['path'].')';
+								} else {
+									$rewrite_exclude = '(.?)';
+								}
+								unset($tmp_redirect_path);
+								unset($tmp_redirect_path_parts);
+							}
 							$rewrite_rules[] = array(	'rewrite_domain' 	=> $alias['domain'],
 								'rewrite_type' 		=> ($alias['redirect_type'] == 'no')?'':$alias['redirect_type'],
-								'rewrite_target' 	=> $alias['redirect_path']);
+								'rewrite_target' 	=> $alias['redirect_path'],
+								'rewrite_exclude'	=> $rewrite_exclude);
 							break;
 						default:
+							if(substr($alias['redirect_path'],0,1) == '/'){ // relative path
+								$rewrite_exclude = '(?!'.substr($alias['redirect_path'],0,-1).')';
+							} else { // URL - check if URL is local
+								$tmp_redirect_path = $alias['redirect_path'];
+								if(substr($tmp_redirect_path,0,7) == '$scheme') $tmp_redirect_path = 'http'.substr($tmp_redirect_path,7);
+								$tmp_redirect_path_parts = parse_url($tmp_redirect_path);
+								if($tmp_redirect_path_parts['host'] == $alias['domain'] && ($tmp_redirect_path_parts['port'] == '80' || $tmp_redirect_path_parts['port'] == '443' || !isset($tmp_redirect_path_parts['port']))){
+									if(substr($tmp_redirect_path_parts['path'],-1) == '/') $tmp_redirect_path_parts['path'] = substr($tmp_redirect_path_parts['path'],0,-1);
+									if(substr($tmp_redirect_path_parts['path'],0,1) != '/') $tmp_redirect_path_parts['path'] = '/'.$tmp_redirect_path_parts['path'];
+									$rewrite_exclude = '(?!'.$tmp_redirect_path_parts['path'].')';
+								} else {
+									$rewrite_exclude = '(.?)';
+								}
+								unset($tmp_redirect_path);
+								unset($tmp_redirect_path_parts);
+							}
 							$rewrite_rules[] = array(	'rewrite_domain' 	=> '^'.$alias['domain'],
 							'rewrite_type' 		=> ($alias['redirect_type'] == 'no')?'':$alias['redirect_type'],
-							'rewrite_target' 	=> $alias['redirect_path']);
+							'rewrite_target' 	=> $alias['redirect_path'],
+							'rewrite_exclude'	=> $rewrite_exclude);
 					}
 				}
 			}
@@ -836,7 +1072,7 @@
 		if(file_exists($vhost_file)) copy($vhost_file,$vhost_file.'~');
 		
 		//* Write vhost file
-		file_put_contents($vhost_file,$tpl->grab());
+		file_put_contents($vhost_file,$this->nginx_merge_locations($tpl->grab()));
 		$app->log('Writing the vhost file: '.$vhost_file,LOGLEVEL_DEBUG);
 		unset($tpl);
 
@@ -882,6 +1118,11 @@
 				unlink($vhost_symlink);
 				$app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
 			}
+			$vhost_symlink = escapeshellcmd($web_config['nginx_vhost_conf_enabled_dir'].'/'.$data['old']['domain'].'.vhost');
+			if(is_link($vhost_symlink)) {
+				unlink($vhost_symlink);
+				$app->log('Removing symlink: '.$vhost_symlink.'->'.$vhost_file,LOGLEVEL_DEBUG);
+			}
 			$vhost_file = escapeshellcmd($web_config['nginx_vhost_conf_dir'].'/'.$data['old']['domain'].'.vhost');
 			unlink($vhost_file);
 			$app->log('Removing file: '.$vhost_file,LOGLEVEL_DEBUG);
@@ -920,7 +1161,13 @@
 			if($nginx_online_status_before_restart && !$nginx_online_status_after_restart) {
 				$app->log('nginx did not restart after the configuration change for website '.$data['new']['domain'].' Reverting the configuration. Saved non-working config as '.$vhost_file.'.err',LOGLEVEL_WARN);
 				copy($vhost_file,$vhost_file.'.err');
-				copy($vhost_file.'~',$vhost_file);
+				if(is_file($vhost_file.'~')) {
+					//* Copy back the last backup file
+					copy($vhost_file.'~',$vhost_file);
+				} else {
+					//* There is no backup file, so we create a empty vhost file with a warning message inside
+					file_put_contents($vhost_file,"# nginx did not start after modifying this vhost file.\n# Please check file $vhost_file.err for syntax errors.");
+				}
 				$app->services->restartService('httpd','restart');
 			}
 		} else {
@@ -1001,6 +1248,11 @@
 					exec('rm -rf '.$fastcgi_starter_path);
 				}
 			}
+			
+			// remove PHP-FPM pool
+			if ($data['old']['php'] == 'php-fpm') {
+				$this->php_fpm_pool_delete($data,$web_config);
+			}
 
 			//remove the php cgi starter script if available
 			if ($data['old']['php'] == 'cgi') {
@@ -1058,27 +1310,7 @@
 
 	//* This function is called when a IP on the server is inserted, updated or deleted
 	function server_ip($event_name,$data) {
-		global $app, $conf;
-
-		// load the server configuration options
-		$app->uses('getconf');
-		$web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
-
-		$app->load('tpl');
-
-		$tpl = new tpl();
-		$tpl->newTemplate('apache_ispconfig.conf.master');
-		$records = $app->db->queryAllRecords('SELECT * FROM server_ip WHERE server_id = '.$conf['server_id']." AND virtualhost = 'y'");
-
-		if(count($records) > 0) {
-			$tpl->setLoop('ip_adresses',$records);
-		}
-
-		$vhost_file = escapeshellcmd($web_config['nginx_vhost_conf_dir'].'/ispconfig.conf');
-		file_put_contents($vhost_file,$tpl->grab());
-		$app->log('Writing the conf file: '.$vhost_file,LOGLEVEL_DEBUG);
-		unset($tpl);
-
+		return;
 	}
 	
 	//* Create or update the .htaccess folder protection
@@ -1114,12 +1346,18 @@
 		}
 		
 		//* Create the folder path, if it does not exist
-		if(!is_dir($folder_path)) exec('mkdir -p '.$folder_path);
+		if(!is_dir($folder_path)) {
+			exec('mkdir -p '.$folder_path);
+			chown($folder_path,$website['system_user']);
+			chgrp($folder_path,$website['system_group']);
+		}
 		
 		//* Create empty .htpasswd file, if it does not exist
 		if(!is_file($folder_path.'.htpasswd')) {
 			touch($folder_path.'.htpasswd');
 			chmod($folder_path.'.htpasswd',0755);
+			chown($folder_path.'.htpasswd',$website['system_user']);
+			chgrp($folder_path.'.htpasswd',$website['system_group']);
 			$app->log('Created file'.$folder_path.'.htpasswd',LOGLEVEL_DEBUG);
 		}
 		
@@ -1291,6 +1529,7 @@
 		
 		$awstats_conf_dir = $web_config['awstats_conf_dir'];
 		
+		if(!is_dir($data['new']['document_root']."/web/stats/")) mkdir($data['new']['document_root']."/web/stats");
 		if(!@is_file($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf') || ($data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain'])) {
 			if ( @is_file($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf') ) {
 				unlink($awstats_conf_dir.'/awstats.'.$data['old']['domain'].'.conf');
@@ -1305,6 +1544,9 @@
 			file_put_contents($awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf',$content);
 			$app->log('Created AWStats config file: '.$awstats_conf_dir.'/awstats.'.$data['new']['domain'].'.conf',LOGLEVEL_DEBUG);
 		}
+		
+		if(is_file($data['new']['document_root']."/web/stats/index.html")) unlink($data['new']['document_root']."/web/stats/index.html");
+		copy("/usr/local/ispconfig/server/conf/awstats_index.php.master",$data['new']['document_root']."/web/stats/index.php");
 	}
 	
 	//* Delete the awstats configuration file
@@ -1322,20 +1564,50 @@
 	//* Update the PHP-FPM pool configuration file
 	private function php_fpm_pool_update ($data,$web_config,$pool_dir,$pool_name,$socket_dir) {
 		global $app, $conf;
-		//$reload = false;
+		/*
+		if(trim($data['new']['fastcgi_php_version']) != ''){
+			$default_php_fpm = false;
+			list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['new']['fastcgi_php_version']));
+			if(substr($custom_php_fpm_ini_dir,-1) != '/') $custom_php_fpm_ini_dir .= '/';
+		} else {
+			$default_php_fpm = true;
+		}
+		*/
+		if($data['new']['php'] != 'no'){
+			if(trim($data['new']['fastcgi_php_version']) != ''){
+				$default_php_fpm = false;
+				list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['new']['fastcgi_php_version']));
+				if(substr($custom_php_fpm_ini_dir,-1) != '/') $custom_php_fpm_ini_dir .= '/';
+			} else {
+				$default_php_fpm = true;
+			}
+		} else {
+			if(trim($data['old']['fastcgi_php_version']) != '' && $data['old']['php'] != 'no'){
+				$default_php_fpm = false;
+				list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['old']['fastcgi_php_version']));
+				if(substr($custom_php_fpm_ini_dir,-1) != '/') $custom_php_fpm_ini_dir .= '/';
+			} else {
+				$default_php_fpm = true;
+			}
+		}
+		
+		$app->uses("getconf");
+		$web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
 		
 		if($data['new']['php'] == 'no'){
 			if(@is_file($pool_dir.$pool_name.'.conf')){
 				unlink($pool_dir.$pool_name.'.conf');
-				//$reload = true;
 			}
-			//if($reload == true) $app->services->restartService('php-fpm','reload');
+			if($data['old']['php'] != 'no'){
+				if(!$default_php_fpm){
+					$app->services->restartService('php-fpm','reload:'.$custom_php_fpm_init_script);
+				} else {
+					$app->services->restartService('php-fpm','reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
+				}
+			}
 			return;
 		}
-			
-		$app->uses("getconf");
-		$web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
-			
+				
 		$app->load('tpl');
 		$tpl = new tpl();
 		$tpl->newTemplate('php_fpm_pool.conf.master');
@@ -1358,10 +1630,13 @@
 		$tpl->setVar('fpm_port', $web_config['php_fpm_start_port'] + $data['new']['domain_id'] - 1);
 		$tpl->setVar('fpm_user', $data['new']['system_user']);
 		$tpl->setVar('fpm_group', $data['new']['system_group']);
+		$tpl->setVar('pm', $data['new']['pm']);
 		$tpl->setVar('pm_max_children', $data['new']['pm_max_children']);
 		$tpl->setVar('pm_start_servers', $data['new']['pm_start_servers']);
 		$tpl->setVar('pm_min_spare_servers', $data['new']['pm_min_spare_servers']);
 		$tpl->setVar('pm_max_spare_servers', $data['new']['pm_max_spare_servers']);
+		$tpl->setVar('pm_process_idle_timeout', $data['new']['pm_process_idle_timeout']);
+		$tpl->setVar('pm_max_requests', $data['new']['pm_max_requests']);
 		$tpl->setVar('document_root', $data['new']['document_root']);
 		$tpl->setVar('security_level',$web_config['security_level']);
 		$php_open_basedir = ($data['new']['php_open_basedir'] == '')?escapeshellcmd($data['new']['document_root']):escapeshellcmd($data['new']['php_open_basedir']);
@@ -1387,12 +1662,12 @@
 							$value = escapeshellcmd(trim($value));
 							$key = escapeshellcmd(trim($key));
 							switch (strtolower($value)) {
-								case 'on':
-								case 'off':
-								case '1':
 								case '0':
 									// PHP-FPM might complain about invalid boolean value if you use 0
 									$value = 'off';
+								case '1':
+								case 'on':
+								case 'off':
 								case 'true':
 								case 'false':
 								case 'yes':
@@ -1412,24 +1687,170 @@
 		file_put_contents($pool_dir.$pool_name.'.conf',$tpl->grab());
 		$app->log('Writing the PHP-FPM config file: '.$pool_dir.$pool_name.'.conf',LOGLEVEL_DEBUG);
 		unset($tpl);
-		//$reload = true;
-
-		//if($reload == true) $app->services->restartService('php-fpm','reload');
+		
+		// delete pool in all other PHP versions
+		$default_pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
+		if(substr($default_pool_dir,-1) != '/') $default_pool_dir .= '/';
+		if($default_pool_dir != $pool_dir){
+			if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
+					unlink($default_pool_dir.$pool_name.'.conf');
+					$app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf',LOGLEVEL_DEBUG);
+					$app->services->restartService('php-fpm','reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
+			}
+		}
+		$php_versions = $app->db->queryAllRecords("SELECT * FROM server_php WHERE php_fpm_init_script != '' AND php_fpm_ini_dir != '' AND php_fpm_pool_dir != '' AND server_id = ".$conf["server_id"]);
+		if(is_array($php_versions) && !empty($php_versions)){
+			foreach($php_versions as $php_version){
+				if(substr($php_version['php_fpm_pool_dir'],-1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
+				if($php_version['php_fpm_pool_dir'] != $pool_dir){
+					if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
+						unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
+						$app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf',LOGLEVEL_DEBUG);
+						$app->services->restartService('php-fpm','reload:'.$php_version['php_fpm_init_script']);
+					}
+				}
+			}
+		}
+		// Reload current PHP-FPM after all others
+		sleep(1);
+		if(!$default_php_fpm){
+			$app->services->restartService('php-fpm','reload:'.$custom_php_fpm_init_script);
+		} else {
+			$app->services->restartService('php-fpm','reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
+		}
 	}
 	
 	//* Delete the PHP-FPM pool configuration file
 	private function php_fpm_pool_delete ($data,$web_config) {
-		global $app;
+		global $app, $conf;
 		
-		$pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
+		if(trim($data['old']['fastcgi_php_version']) != '' && $data['old']['php'] != 'no'){
+			$default_php_fpm = false;
+			list($custom_php_fpm_name, $custom_php_fpm_init_script, $custom_php_fpm_ini_dir, $custom_php_fpm_pool_dir) = explode(':', trim($data['old']['fastcgi_php_version']));
+			if(substr($custom_php_fpm_ini_dir,-1) != '/') $custom_php_fpm_ini_dir .= '/';
+		} else {
+			$default_php_fpm = true;
+		}
+		
+		if($default_php_fpm){
+			$pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
+		} else {
+			$pool_dir = $custom_php_fpm_pool_dir;
+		}
+		
 		if(substr($pool_dir,-1) != '/') $pool_dir .= '/';
 		$pool_name = 'web'.$data['old']['domain_id'];
 		
 		if ( @is_file($pool_dir.$pool_name.'.conf') ) {
 			unlink($pool_dir.$pool_name.'.conf');
 			$app->log('Removed PHP-FPM config file: '.$pool_dir.$pool_name.'.conf',LOGLEVEL_DEBUG);
-			//$app->services->restartService('php-fpm','reload');
 		}
+		
+		// delete pool in all other PHP versions
+		$default_pool_dir = escapeshellcmd($web_config['php_fpm_pool_dir']);
+		if(substr($default_pool_dir,-1) != '/') $default_pool_dir .= '/';
+		if($default_pool_dir != $pool_dir){
+			if ( @is_file($default_pool_dir.$pool_name.'.conf') ) {
+					unlink($default_pool_dir.$pool_name.'.conf');
+					$app->log('Removed PHP-FPM config file: '.$default_pool_dir.$pool_name.'.conf',LOGLEVEL_DEBUG);
+					$app->services->restartService('php-fpm','reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
+			}
+		}	
+		$php_versions = $app->db->queryAllRecords("SELECT * FROM server_php WHERE php_fpm_init_script != '' AND php_fpm_ini_dir != '' AND php_fpm_pool_dir != '' AND server_id = ".$data['old']['server_id']);
+		if(is_array($php_versions) && !empty($php_versions)){
+			foreach($php_versions as $php_version){
+				if(substr($php_version['php_fpm_pool_dir'],-1) != '/') $php_version['php_fpm_pool_dir'] .= '/';
+				if($php_version['php_fpm_pool_dir'] != $pool_dir){
+					if ( @is_file($php_version['php_fpm_pool_dir'].$pool_name.'.conf') ) {
+						unlink($php_version['php_fpm_pool_dir'].$pool_name.'.conf');
+						$app->log('Removed PHP-FPM config file: '.$php_version['php_fpm_pool_dir'].$pool_name.'.conf',LOGLEVEL_DEBUG);
+						$app->services->restartService('php-fpm','reload:'.$php_version['php_fpm_init_script']);
+					}
+				}
+			}
+		}
+		
+		// Reload current PHP-FPM after all others
+		sleep(1);
+		if(!$default_php_fpm){
+			$app->services->restartService('php-fpm','reload:'.$custom_php_fpm_init_script);
+		} else {
+			$app->services->restartService('php-fpm','reload:'.$conf['init_scripts'].'/'.$web_config['php_fpm_init_script']);
+		}
+	}
+	
+	private function nginx_merge_locations($vhost_conf){
+
+		$lines = explode("\n", $vhost_conf);
+		
+		if(is_array($lines) && !empty($lines)){
+		
+			$locations = array();
+			$islocation = false;
+			$linecount = sizeof($lines);
+
+			for($i=0;$i<$linecount;$i++){
+				$l = trim($lines[$i]);
+				if(substr($l, 0, 8) == 'location' && !$islocation){
+				
+					$islocation = true;
+					$level = 0;
+					
+					// Remove unnecessary whitespace
+					$l = preg_replace('/\s\s+/', ' ', $l);
+					
+					$loc_parts = explode(' ', $l);
+					// see http://wiki.nginx.org/HttpCoreModule#location
+					if($loc_parts[1] == '=' || $loc_parts[1] == '~' || $loc_parts[1] == '~*' || $loc_parts[1] == '^~'){
+						$location = $loc_parts[1].' '.$loc_parts[2];
+					} else {
+						$location = $loc_parts[1];
+					}
+					unset($loc_parts);
+					
+					if(!isset($locations[$location]['action'])) $locations[$location]['action'] = 'replace';
+					if(substr($l, -9) == '##merge##'){
+						$locations[$location]['action'] = 'merge';
+					}
+					
+					if(!isset($locations[$location]['open_tag'])) $locations[$location]['open_tag'] = '        location '.$location.' {';
+					if(!isset($locations[$location]['location']) || $locations[$location]['action'] == 'replace') $locations[$location]['location'] = '';
+					if(!isset($locations[$location]['end_tag'])) $locations[$location]['end_tag'] = '        }';
+					if(!isset($locations[$location]['start_line'])) $locations[$location]['start_line'] = $i;
+
+					unset($lines[$i]);
+					
+				} else {
+				
+					if($islocation){
+						if(strpos($l, '{') !== false){
+							$level += 1;
+						}
+						if(strpos($l, '}') !== false && $level > 0){
+							$level -= 1;
+							$locations[$location]['location'] .= $lines[$i]."\n";
+						} elseif(strpos($l, '}') !== false && $level == 0){
+							$islocation = false;
+						} else {
+							$locations[$location]['location'] .= $lines[$i]."\n";
+						}
+						unset($lines[$i]);
+					}
+					
+				}
+			}
+			
+			if(is_array($locations) && !empty($locations)){
+				foreach($locations as $key => $val){
+					$new_location = $val['open_tag']."\n".$val['location'].$val['end_tag'];
+					$lines[$val['start_line']] = $new_location;
+				}
+			}
+			ksort($lines);
+			$vhost_conf = implode("\n", $lines);
+		}
+		
+		return $vhost_conf;
 	}
 	
 	function client_delete($event_name,$data) {

--
Gitblit v1.9.1