From 93f24e172a9fae36cc6fb27ffee4029b265a8f77 Mon Sep 17 00:00:00 2001
From: ftimme <ft@falkotimme.com>
Date: Tue, 03 Apr 2012 11:55:49 -0400
Subject: [PATCH] - Fixed FS#2139.

---
 server/plugins-available/nginx_plugin.inc.php |  243 +++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 228 insertions(+), 15 deletions(-)

diff --git a/server/plugins-available/nginx_plugin.inc.php b/server/plugins-available/nginx_plugin.inc.php
index 42d6120..0f3b034 100644
--- a/server/plugins-available/nginx_plugin.inc.php
+++ b/server/plugins-available/nginx_plugin.inc.php
@@ -794,6 +794,7 @@
 		if($data['new']['redirect_type'] != '') {
 			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']).'/';
@@ -802,22 +803,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);
 			}
 		}
 
@@ -826,30 +896,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(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') {
@@ -859,22 +929,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);
 					}
 				}
 			}
@@ -911,7 +1050,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);
 
@@ -1600,6 +1739,80 @@
 		}
 	}
 	
+	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) {
 		global $app, $conf;
 		

--
Gitblit v1.9.1