From 6a001aa768d5a7b9a9a5a638be84cee16df6afe0 Mon Sep 17 00:00:00 2001
From: Till Brehm <tbrehm@ispconfig.org>
Date: Fri, 09 May 2014 09:23:50 -0400
Subject: [PATCH] Merge branch 'stable-3.0.5' of git.ispconfig.org:ispconfig/ispconfig3 into stable-3.0.5

---
 server/conf/vhost.conf.master                             |    4 
 install/lib/installer_base.lib.php                        |    2 
 interface/web/admin/templates/directive_snippets_edit.htm |    2 
 interface/web/index.php                                   |   16 +
 server/plugins-available/shelluser_jailkit_plugin.inc.php |  125 ++++++++-----
 interface/web/themes/default/templates/main.tpl.htm       |    3 
 interface/lib/classes/validate_password.inc.php           |   10 +
 interface/web/admin/lib/lang/de_system_config.lng         |    2 
 interface/lib/classes/ispconfig_request.inc.php           |  263 +++++++++++++++++++++++++++++
 interface/web/js/scrigo.js.php                            |  101 ++++++++---
 10 files changed, 444 insertions(+), 84 deletions(-)

diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php
index cd5b01b..7d6348b 100644
--- a/install/lib/installer_base.lib.php
+++ b/install/lib/installer_base.lib.php
@@ -690,7 +690,7 @@
 		if(!is_user($cf['vmail_username'])) caselog("$command &> /dev/null", __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
 
 		//* These postconf commands will be executed on installation and update
-		$server_ini_rec = $this->db->queryOneRecord("SELECT config FROM server WHERE server_id = ".$conf['server_id']);
+		$server_ini_rec = $this->db->queryOneRecord("SELECT config FROM `" . $this->db->quote($conf["mysql"]["database"]) . "`.`server` WHERE server_id = ".$conf['server_id']);
 		$server_ini_array = ini_to_array(stripslashes($server_ini_rec['config']));
 		unset($server_ini_rec);
 
diff --git a/interface/lib/classes/ispconfig_request.inc.php b/interface/lib/classes/ispconfig_request.inc.php
new file mode 100644
index 0000000..b29ae23
--- /dev/null
+++ b/interface/lib/classes/ispconfig_request.inc.php
@@ -0,0 +1,263 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+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 purpose of this library is to provide some general functions.
+//* This class is loaded automatically by the ispconfig framework.
+
+abstract class ISPConfigRequest {
+	/**
+	 * Get header data and contents from an url
+	 *
+	 * Calls an url and returns an array containing the http header and the page content
+	 *
+	 * @access public
+	 * @param string $url the url to call
+	 * @param string $store_in the file to store the data in instead of returning them
+	 * @return array The array with header data at index 0 and page content at index 1, returns boolean false on error. If $store_in is set only the headers are returned
+	 */
+
+
+	public static function get_with_headers($url, $store_in = null, $follow_redirects = false, $user_agent = false) {
+		if($follow_redirects === true) $follow_redirects = 5;
+		elseif($follow_redirects !== false) $follow_redirects--;
+
+		if(!$user_agent) $user_agent = 'pxFW GET proxy';
+
+		$url_info = parse_url($url);
+		if(isset($url_info['scheme']) && $url_info['scheme'] == 'https') {
+			$port = isset($url_info['port']) ? $url_info['port'] : 443;
+			//@$fp = stream_socket_client('ssl://' . $url_info['host'] . ':' . $port, $errno, $errstr, 10, STREAM_CLIENT_CONNECT, stream_context_create(array('ssl' => array('ciphers' => 'ALL:!AES:!3DES:!RC4:@STRENGTH'))));
+			@$fp = fsockopen('sslv3://' . $url_info['host'], $port, $errno, $errstr, 10);
+		} else {
+			$port = isset($url_info['port']) ? $url_info['port'] : 80;
+			@$fp = fsockopen($url_info['host'], $port, $errno, $errstr, 10);
+		}
+
+		if($store_in) {
+			$outfp = fopen($store_in, 'w');
+			if(!$outfp) return false;
+		}
+		if($fp) {
+			stream_set_timeout($fp, 10);
+			$head = 'GET ' . (isset($url_info['path']) ? $url_info['path'] : '/') . (isset($url_info['query']) ? '?' . $url_info['query'] : '');
+			$head .= " HTTP/1.0\r\nHost: " . (isset($url_info['host']) ? $url_info['host'] : '') . "\r\n";
+			$head .= "User-Agent: " . $user_agent . "\r\n";
+			if(isset($url_info['user'])) {
+				if(!array_key_exists('pass', $url_info)) $url_info['pass'] = '';
+				$head .= "Authorization: basic " . base64_encode($url_info['user'] . ':' . $url_info['pass']) . "\r\n";
+			}
+			$head .= "Connection: Close\r\n";
+			$head .= "Accept: */*\r\n\r\n";
+
+			$data = '';
+			$eoheader = false;
+			fputs($fp, $head);
+			while(!feof($fp)) {
+				if($header = fgets($fp, 1024)) {
+					if($eoheader == true) {
+						if($store_in) fputs($outfp, $header);
+						else $data .= $header;
+						continue;
+					}
+
+					if ($header == "\r\n") {
+						$eoheader = true;
+						continue;
+					} else {
+						$header = trim($header);
+					}
+					$sc_pos = strpos($header, ':');
+					if($sc_pos === false) {
+						$headers['status'] = $header;
+						$headers['http_code'] = intval(preg_replace('/^HTTP\/\d+\.\d+\s+(\d+)\s+.*$/', '$1', $header));
+					} else {
+						$label = substr($header, 0, $sc_pos);
+						$value = substr($header, $sc_pos + 1);
+						$headers[strtolower($label)] = trim($value);
+					}
+				}
+			}
+			fclose($fp);
+			if(isset($headers['http_code']) && isset($headers['location']) && ($headers['http_code'] == 301 || $headers['http_code'] == 302) && $follow_redirects > 0) {
+				if($store_in) fclose($outfp);
+				return $self::get_with_headers($headers['location'], $store_in, $follow_redirects);
+			}
+			if($store_in) {
+				fclose($outfp);
+
+				$code = intval(preg_replace('/^HTTP\/\d+\.\d+\s+(\d+)\s+.*$/', '$1', $headers['status']));
+				if($code != 200) {
+					return false;
+				}
+				return $headers;
+			} else {
+				return array($headers, $data);
+			}
+		} else {
+			if($store_in) {
+				fclose($outfp);
+				@unlink($store_in);
+			}
+			return false;
+		}
+	}
+
+	/**
+	 * Gets the content of an url
+	 *
+	 * Checks for the php function file_get_contents and uses an alternative if not found
+	 *
+	 * @access public
+	 * @param string $url url to get
+	 * @return string url data including headers
+	 * @see file_get_contents
+	 */
+	public static function get($url) {
+		if(function_exists('file_get_contents')) return file_get_contents($url);
+
+		$fp = fopen($url, 'r');
+		$data = '';
+		while(!feof($fp)) {
+			$data .= fgets($fp, 8192);
+		}
+		fclose($fp);
+
+		return $data;
+	}
+
+
+	/**
+	 * Make a post request and get data
+	 *
+	 * Calls an url with a post request and returns the data - and optionally the header content
+	 *
+	 * @access public
+	 * @param string $url the url to call
+	 * @param string $data the post data to send
+	 * @param bool $get_headers if true, the function will return an array like PXUrl::get_with_headers(), otherwise the content is returned as a string
+	 * @return mixed Content data as string or - if get_headers is true - the array with header data at index 0 and page content at index 1
+	 * @see get_url_and_headers
+	 */
+	public static function post($url, $data, $get_headers = false, $user_agent = false) {
+		$url_info = parse_url($url);
+		if((isset($url_info['scheme']) && $url_info['scheme'] == 'https') || $url_info['port'] == 443) {
+			$port = (!isset($url_info['port']) || !$url_info['port'] || $url_info['port'] == 443 || $url_info['port'] == 80) ? 443 : $url_info['port'];
+			//@$fp = stream_socket_client('ssl://' . $url_info['host'] . ':' . $port, $errno, $errstr, 10, STREAM_CLIENT_CONNECT, stream_context_create(array('ssl' => array('ciphers' => 'ALL:!AES:!3DES:!RC4:@STRENGTH'))));
+			@$fp = fsockopen('sslv3://' . $url_info['host'], $port, $errno, $errstr, 10);
+		} else {
+			$port = isset($url_info['port']) ? $url_info['port'] : 80;
+			@$fp = fsockopen($url_info['host'], $port, $errno, $errstr, 10);
+		}
+
+		if(!$fp) return '';
+
+		if(!$user_agent) $user_agent = 'pxFW GET proxy';
+
+		$header = 'POST ' . (isset($url_info['path']) ? $url_info['path'] : '/') . (isset($url_info['query']) ? '?' . @$url_info['query'] : '') . " HTTP/1.1\r\n";
+		$header .= "Host: " . @$url_info['host'] . "\r\n";
+		$header .= "User-Agent: " . $user_agent . "\r\n";
+		if(isset($url_info['user'])) {
+			if(!array_key_exists('pass', $url_info)) $url_info['pass'] = '';
+			$header .= "Authorization: basic " . base64_encode($url_info['user'] . ':' . $url_info['pass']) . "\r\n";
+		}
+		$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
+		$header .= "Content-Length: " . strlen($data) . "\r\n";
+		$header .= "Connection: close\r\n\r\n";
+		$header .= $data . "\r\n\r\n";
+
+		fwrite($fp, $header);
+
+		$response = '';
+		$eoheader = false;
+		$header = '';
+		$tmpdata = '';
+		$chunked = false;
+		$chunklen = 0;
+
+		while(!feof($fp)) {
+			if($header = @fgets($fp, 1024)) {
+				if($eoheader == true) {
+					$response .= $header;
+					continue;
+				}
+
+				if ($header == "\r\n") {
+					$eoheader = true;
+					continue;
+				} else {
+					$tmpdata .= $header;
+					if(preg_match('/Transfer-Encoding:\s+chunked/i', $tmpdata)) $chunked = true;
+				}
+			}
+		}
+		//var_dump($response, $chunked, $header);
+		if($chunked == true) {
+			$lines = explode("\n", $response);
+			$response = '';
+			$chunklen = 0;
+			foreach($lines as $line) {
+				$line .= "\n";
+				if($chunklen <= 0) {
+					if(preg_match('/^([0-9a-f]+)\s*$/is', $line, $matches)) {
+						$chunklen = hexdec($matches[1]);
+					}
+					continue;
+				}
+
+				if(strlen($line) > $chunklen) {
+					//echo "Warnung: " . strlen($line) . " > " . $chunklen . "\n";
+					$line = substr($line, 0, $chunklen);
+				}
+				$response .= $line;
+				$chunklen -= strlen($line);
+			}
+
+			$start = strpos($response, '<?xml');
+			$end = strrpos($response, '>');
+			if($start !== false && $end !== false) $response = substr($response, $start, $end - $start + 1);
+		}
+
+		fclose($fp);
+
+		if($get_headers == true) {
+			$tmpheaders = explode("\n", $tmpdata);
+			$headers = array();
+			foreach($tmpheaders as $cur) {
+				if(preg_match('/^(\w+)\:\s*(.*)$/is', $cur, $matches)) {
+					$headers["$matches[1]"] = trim($matches[2]);
+				}
+			}
+			return array($headers, $response);
+		} else return $response;
+	}
+
+}
+
+?>
diff --git a/interface/lib/classes/validate_password.inc.php b/interface/lib/classes/validate_password.inc.php
index 543a90e..998c37c 100644
--- a/interface/lib/classes/validate_password.inc.php
+++ b/interface/lib/classes/validate_password.inc.php
@@ -38,19 +38,27 @@
 			return 1;
 		}
 
+		$different = 0;
+		if (preg_match('/[abcdefghijklnmopqrstuvwxyz]/', $password)) {
+			$different += 1;
+		}
+
 		if (preg_match('/[ABCDEFGHIJKLNMOPQRSTUVWXYZ]/', $password)) {
 			$points += 1;
+			$different += 1;
 		}
 
 		if (preg_match('/[0123456789]/', $password)) {
 			$points += 1;
+			$different += 1;
 		}
 
 		if (preg_match('/[`~!@#$%^&*()_+|\\=-[]}{\';:\/?.>,<" ]/', $password)) {
 			$points += 1;
+			$different += 1;
 		}
 
-		if ($points == 0) {
+		if ($points == 0 || $different < 3) {
 			if ($length >= 5 && $length <= 6) {
 				return 1;
 			} else if ($length >= 7 && $length <= 8) {
diff --git a/interface/web/admin/lib/lang/de_system_config.lng b/interface/web/admin/lib/lang/de_system_config.lng
index 272d312..ab73983 100644
--- a/interface/web/admin/lib/lang/de_system_config.lng
+++ b/interface/web/admin/lib/lang/de_system_config.lng
@@ -64,7 +64,7 @@
 $wb['customer_no_start_txt'] = 'Kundennummer Startwert';
 $wb['customer_no_counter_txt'] = 'Kundennummer Zähler';
 $wb['session_timeout_txt'] = 'Session-Timeout (Minuten)';
-$wb['session_allow_endless_txt'] = '\\"Eingeloggt bleiben\\" aktivieren';
+$wb['session_allow_endless_txt'] = '&quot;Eingeloggt bleiben&quot; aktivieren';
 $wb['No'] = 'Nein';
 $wb['min_password_length_txt'] = 'Minimale Passwortlänge';
 $wb['min_password_strength_txt'] = 'Minimale Passwortstärke';
diff --git a/interface/web/admin/templates/directive_snippets_edit.htm b/interface/web/admin/templates/directive_snippets_edit.htm
index 6522eb1..7a17cb6 100644
--- a/interface/web/admin/templates/directive_snippets_edit.htm
+++ b/interface/web/admin/templates/directive_snippets_edit.htm
@@ -17,7 +17,7 @@
             </div>
 			<div class="ctrlHolder">
                 <label for="snippet">{tmpl_var name='snippet_txt'}</label>
-                <textarea name="snippet" id="snippet" rows='10' cols='50' style="width:400px;">{tmpl_var name='snippet'}</textarea><div class="nginx"> &nbsp; {tmpl_var name='variables_txt'}: <a href="javascript:void(0);" class="addPlaceholder">{DOCROOT}</a>, <a href="javascript:void(0);" class="addPlaceholder">{FASTCGIPASS}</a></div>
+                <textarea name="snippet" id="snippet" rows='10' cols='50' style="width:400px;">{tmpl_var name='snippet'}</textarea><span class="nginx"> &nbsp; {tmpl_var name='variables_txt'}: </span><a href="javascript:void(0);" class="addPlaceholder nginx">{DOCROOT}</a><span class="nginx">, </span><a href="javascript:void(0);" class="addPlaceholder nginx">{FASTCGIPASS}</a>
             </div>
             <div class="ctrlHolder">
                 <p class="label">{tmpl_var name='active_txt'}</p>
diff --git a/interface/web/index.php b/interface/web/index.php
index c6f0ff3..80eab11 100644
--- a/interface/web/index.php
+++ b/interface/web/index.php
@@ -60,6 +60,22 @@
 	unset($_SESSION['show_error_msg']);
 }
 
+// read js.d files
+$js_d = ISPC_WEB_PATH . '/js/js.d';
+$js_d_files = array();
+if(@is_dir($js_d)) {
+	$dir = opendir($js_d);
+	while($file = readdir($dir)) {
+		$filename = $js_d . '/' . $file;
+		if($file === '.' || $file === '..' || !is_file($filename)) continue;
+		if(substr($file, -3) !== '.js') continue;
+		$js_d_files[] = array('file' => $file);
+	}
+	closedir($dir);
+}
+
+if (!empty($js_d_files)) $app->tpl->setLoop('js_d_includes', $js_d_files);
+unset($js_d_files);
 
 $app->tpl_defaults();
 $app->tpl->pparse();
diff --git a/interface/web/js/scrigo.js.php b/interface/web/js/scrigo.js.php
index 7d15e30..4e51cd5 100644
--- a/interface/web/js/scrigo.js.php
+++ b/interface/web/js/scrigo.js.php
@@ -18,6 +18,7 @@
 var indicatorPaddingH = -1;
 var indicatorPaddingW = -1;
 var indicatorCompleted = false;
+var registeredHooks = new Array();
 redirect = '';
 
 function reportError(request) {
@@ -26,6 +27,20 @@
 	   ajax request worked. */
 
 	/*alert(request);*/
+}
+
+function registerHook(name, callback) {
+    if(!registeredHooks[name]) registeredHooks[name] = new Array();
+    var newindex = registeredHooks[name].length;
+    registeredHooks[name][newindex] = callback;
+}
+
+function callHook(name, params) {
+    if(!registeredHooks[name]) return;
+    for(var i = 0; i < registeredHooks[name].length; i++) {
+        var callback = registeredHooks[name][i];
+        callback(name, params);
+    }
 }
 
 function resetFormChanged() {
@@ -73,7 +88,9 @@
     }
 }
 
-function onAfterContentLoad() {
+function onAfterContentLoad(url, data) {
+    if(!data) data = '';
+    else data = '&' + data;
 <?php
 if($server_config_array['misc']['use_combobox'] == 'y'){
 ?>
@@ -81,6 +98,7 @@
 <?php
 }
 ?>
+    callHook('onAfterContentLoad', {'url': url, 'data': data });
 }
 
 function loadContentRefresh(pagename) {
@@ -96,7 +114,7 @@
 											success: function(data, textStatus, jqXHR) {
                                                 hideLoadIndicator();
 												jQuery('#pageContent').html(jqXHR.responseText);
-                                                onAfterContentLoad();
+                                                onAfterContentLoad(pagename, "refresh="+document.getElementById('refreshinterval').value);
                                                 pageFormChanged = false;
 											},
 											error: function() {
@@ -175,7 +193,7 @@
 													document.location.href = 'index.php';
 												} else {
 													jQuery('#pageContent').html(jqXHR.responseText);
-                                                    onAfterContentLoad();
+                                                    onAfterContentLoad('content.php', jQuery('#'+formname).serialize());
                                                     pageFormChanged = false;
 												}
 												loadMenus();
@@ -213,7 +231,7 @@
 													//window.setTimeout('loadContent(redirect)', 1000);
 												} else {
 													jQuery('#pageContent').html(jqXHR.responseText);
-                                                    onAfterContentLoad();
+                                                    onAfterContentLoad(target, jQuery('#'+formname).serialize());
                                                     pageFormChanged = false;
 												}
                                                 hideLoadIndicator();
@@ -252,7 +270,7 @@
 													//window.setTimeout('loadContent(redirect)', 1000);
 												} else {
 													jQuery('#pageContent').html(jqXHR.responseText);
-                                                    onAfterContentLoad();
+                                                    onAfterContentLoad(target, jQuery('#'+formname).serialize());
                                                     pageFormChanged = false;
 												}
                                                 hideLoadIndicator();
@@ -330,7 +348,7 @@
 													//jQuery.each(reponseScript, function(idx, val) { eval(val.text); } );
 
 													jQuery('#pageContent').html(jqXHR.responseText);
-                                                    onAfterContentLoad();
+                                                    onAfterContentLoad(pagename, (params ? params : null));
                                                     pageFormChanged = false;
 												}
                                                 hideLoadIndicator();
@@ -357,7 +375,7 @@
 													loadContent(parts[1]);
 												} else {
 													jQuery('#pageContent').html(jqXHR.responseText);
-                                                    onAfterContentLoad();
+                                                    onAfterContentLoad('content.php', "s_mod=login&s_pg=index");
                                                     pageFormChanged = false;
 												}
                                                 hideLoadIndicator();
@@ -561,6 +579,8 @@
 pass_message['color'] = "green";
 pass_messages[5] = pass_message;
 
+var special_chars = "`~!@#$%^&*()_+|\=-[]}{';:/?.>,<\" ";
+
 function pass_check(password) {
 	var length = password.length;
 	var points = 0;
@@ -573,20 +593,29 @@
 		pass_result(1);
 		return;
 	}
-
+	
+	var different = 0;
+	
+	if (pass_contains(password, "abcdefghijklnmopqrstuvwxyz")) {
+		different += 1;
+	}
+	
 	if (pass_contains(password, "ABCDEFGHIJKLNMOPQRSTUVWXYZ")) {
 		points += 1;
+		different += 1;
 	}
 
 	if (pass_contains(password, "0123456789")) {
 		points += 1;
+		different += 1;
 	}
 
-	if (pass_contains(password, "`~!@#$%^&*()_+|\=-[]}{';:/?.>,<\" ")) {
+	if (pass_contains(password, special_chars)) {
 		points += 1;
+		different += 1;
 	}
 
-	if (points == 0) {
+	if (points == 0 || different < 3) {
 		if (length >= 5 && length <=6) {
 			pass_result(1);
 		} else if (length >= 7 && length <=8) {
@@ -724,27 +753,45 @@
     return rv;
 }
 
-function password(minLength, special){
-	var iteration = 0;
-	var password = "";
-	var randomNumber;
+function password(minLength, special, num_special){
 	minLength = minLength || 10;
+	if(minLength < 8) minLength = 8;
 	var maxLength = minLength + 5;
 	var length = getRandomInt(minLength, maxLength);
-	if(special == undefined){
-		var special = false;
+	
+	var alphachars = "abcdefghijklmnopqrstuvwxyz";
+	var upperchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    var numchars = "1234567890";
+    var specialchars = "!@#_";
+	
+	if(num_special == undefined) num_special = 0;
+	if(special != undefined && special == true) {
+		num_special = Math.floor(Math.random() * (length / 4)) + 1;
 	}
-	while(iteration < length){
-		randomNumber = (Math.floor((Math.random() * 100)) % 94) + 33;
-		if(!special){
-			if ((randomNumber >=33) && (randomNumber <=47)) { continue; }
-			if ((randomNumber >=58) && (randomNumber <=64)) { continue; }
-			if ((randomNumber >=91) && (randomNumber <=96)) { continue; }
-			if ((randomNumber >=123) && (randomNumber <=126)) { continue; }
-		}
-		iteration++;
-		password += String.fromCharCode(randomNumber);
+	var numericlen = getRandomInt(1, 2);
+	var alphalen = length - num_special - numericlen;
+	var upperlen = Math.floor(alphalen / 2);
+	alphalen = alphalen - upperlen;
+	var password = "";
+	
+	for(i = 0; i < alphalen; i++) {
+		password += alphachars.charAt(Math.floor(Math.random() * alphachars.length));
 	}
+	
+	for(i = 0; i < upperlen; i++) {
+		password += upperchars.charAt(Math.floor(Math.random() * upperchars.length));
+	}
+	
+	for(i = 0; i < num_special; i++) {
+		password += specialchars.charAt(Math.floor(Math.random() * specialchars.length));
+	}
+	
+	for(i = 0; i < numericlen; i++) {
+		password += numchars.charAt(Math.floor(Math.random() * numchars.length));
+	}
+	
+	password = password.split('').sort(function() { return 0.5 - Math.random(); }).join('');
+	
 	return password;
 }
 
@@ -760,7 +807,7 @@
 	var newPWField = oldPWField.clone();
 	newPWField.attr('type', 'text').attr('id', 'tmp'+passwordFieldID).insertBefore(oldPWField);
 	oldPWField.remove();
-	var pword = password(<?php echo $min_password_length ?>, false);
+	var pword = password(<?php echo $min_password_length; ?>, false, 1);
 	jQuery('#'+repeatPasswordFieldID).val(pword);
 	newPWField.attr('id', passwordFieldID).val(pword).trigger('keyup');
 }
diff --git a/interface/web/themes/default/templates/main.tpl.htm b/interface/web/themes/default/templates/main.tpl.htm
index fd38222..9146291 100644
--- a/interface/web/themes/default/templates/main.tpl.htm
+++ b/interface/web/themes/default/templates/main.tpl.htm
@@ -18,6 +18,9 @@
         <script type="text/javascript" src="js/uni-form/uni-form.jquery.js"></script>
         <script type="text/javascript" src="js/jquery.ispconfigsearch.js"></script>
         <script type="text/javascript" src="js/jquery.tipsy.js"></script>
+        <tmpl_loop name="js_d_includes">
+            <script type="text/javascript" src="js/js.d/<tmpl_var name='file'>"></script>
+        </tmpl_loop>
         <script language="JavaScript" type="text/javascript">
             jQuery(document).ready(function() {
                 loadInitContent();
diff --git a/server/conf/vhost.conf.master b/server/conf/vhost.conf.master
index f78efe5..5a110cc 100644
--- a/server/conf/vhost.conf.master
+++ b/server/conf/vhost.conf.master
@@ -335,7 +335,9 @@
 		RewriteCond %{REQUEST_URI} !^/php5-fcgi/
 		RewriteCond %{REQUEST_URI} !^<tmpl_var name='rewrite_target'>
 </tmpl_if>
-		RewriteRule   ^/(.*)$ <tmpl_var name='rewrite_target'><tmpl_if name="rewrite_add_path" op="==" value="y">$1</tmpl_if>  <tmpl_var name='rewrite_type'>
+		
+		RewriteRule   ^/(.*)$ <tmpl_var name='rewrite_target'><tmpl_if name="rewrite_add_path" op="==" value="y">$1</tmpl_if>  <tmpl_if name='rewrite_type' value=''><tmpl_if name="rewrite_is_url" op="==" value="n">[PT]</tmpl_if></tmpl_else><tmpl_var name='rewrite_type'></tmpl_if>
+	
 </tmpl_loop>
 </tmpl_if>
 
diff --git a/server/plugins-available/shelluser_jailkit_plugin.inc.php b/server/plugins-available/shelluser_jailkit_plugin.inc.php
index 9816b70..90ed677 100755
--- a/server/plugins-available/shelluser_jailkit_plugin.inc.php
+++ b/server/plugins-available/shelluser_jailkit_plugin.inc.php
@@ -33,6 +33,7 @@
 	//* $plugin_name and $class_name have to be the same then the name of this class
 	var $plugin_name = 'shelluser_jailkit_plugin';
 	var $class_name = 'shelluser_jailkit_plugin';
+	var $min_uid = 499;
 
 	//* This function is called during ispconfig installation to determine
 	//  if a symlink shall be created for this plugin.
@@ -73,50 +74,60 @@
 		$app->uses('system');
 		$web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$data['new']['parent_domain_id']);
 
-		if($app->system->is_user($data['new']['username'])) {
+		if($app->system->is_user($data['new']['puser'])) {
+			// Get the UID of the parent user
+			$uid = intval($app->system->getuid($data['new']['puser']));
+			if($uid > $this->min_uid) {
+			
+				if($app->system->is_user($data['new']['username'])) {
 
-			/**
-			 * Setup Jailkit Chroot System If Enabled
-			 */
+					/**
+					* Setup Jailkit Chroot System If Enabled
+					*/
+
+					if ($data['new']['chroot'] == "jailkit")
+					{
 
 
-			if ($data['new']['chroot'] == "jailkit")
-			{
+						// load the server configuration options
+						$app->uses("getconf");
+						$this->data = $data;
+						$this->app = $app;
+						$this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
 
+						$this->_update_website_security_level();
 
-				// load the server configuration options
-				$app->uses("getconf");
-				$this->data = $data;
-				$this->app = $app;
-				$this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
+						$app->system->web_folder_protection($web['document_root'], false);
 
-				$this->_update_website_security_level();
+						$this->_setup_jailkit_chroot();
 
-				$app->system->web_folder_protection($web['document_root'], false);
+						$this->_add_jailkit_user();
 
-				$this->_setup_jailkit_chroot();
+						//* call the ssh-rsa update function
+						$this->_setup_ssh_rsa();
 
-				$this->_add_jailkit_user();
+						//$command .= 'usermod -s /usr/sbin/jk_chrootsh -U '.escapeshellcmd($data['new']['username']);
+						//exec($command);
+						$app->system->usermod($data['new']['username'], 0, 0, '', '/usr/sbin/jk_chrootsh', '', '');
 
-				//* call the ssh-rsa update function
-				$this->_setup_ssh_rsa();
+						//* Unlock user
+						$command = 'usermod -U '.escapeshellcmd($data['new']['username']).' 2>/dev/null';
+						exec($command);
 
-				//$command .= 'usermod -s /usr/sbin/jk_chrootsh -U '.escapeshellcmd($data['new']['username']);
-				//exec($command);
-				$app->system->usermod($data['new']['username'], 0, 0, '', '/usr/sbin/jk_chrootsh', '', '');
+						$this->_update_website_security_level();
+						$app->system->web_folder_protection($web['document_root'], true);
+					}
 
-				//* Unlock user
-				$command = 'usermod -U '.escapeshellcmd($data['new']['username']).' 2>/dev/null';
-				exec($command);
+					$app->log("Jailkit Plugin -> insert username:".$data['new']['username'], LOGLEVEL_DEBUG);
 
-				$this->_update_website_security_level();
-				$app->system->web_folder_protection($web['document_root'], true);
+				} else {
+					$app->log("Jailkit Plugin -> insert username:".$data['new']['username']." skipped, the user does not exist.", LOGLEVEL_WARN);
+				}
+			} else {
+				$app->log("UID = $uid for shelluser:".$data['new']['username']." not allowed.", LOGLEVEL_ERROR);
 			}
-
-			$app->log("Jailkit Plugin -> insert username:".$data['new']['username'], LOGLEVEL_DEBUG);
-
 		} else {
-			$app->log("Jailkit Plugin -> insert username:".$data['new']['username']." skipped, the user does not exist.", LOGLEVEL_WARN);
+			$app->log("Skipping insertion of user:".$data['new']['username'].", parent user ".$data['new']['puser']." does not exist.", LOGLEVEL_WARN);
 		}
 
 	}
@@ -128,41 +139,51 @@
 		$app->uses('system');
 		$web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$data['new']['parent_domain_id']);
 
-		if($app->system->is_user($data['new']['username'])) {
+		if($app->system->is_user($data['new']['puser'])) {
+			// Get the UID of the parent user
+			$uid = intval($app->system->getuid($data['new']['puser']));
+			if($uid > $this->min_uid) {
+			
+			
+				if($app->system->is_user($data['new']['username'])) {
 
+					/**
+					* Setup Jailkit Chroot System If Enabled
+					*/
+					if ($data['new']['chroot'] == "jailkit")
+					{
 
+						// load the server configuration options
+						$app->uses("getconf");
+						$this->data = $data;
+						$this->app = $app;
+						$this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
 
-			/**
-			 * Setup Jailkit Chroot System If Enabled
-			 */
-			if ($data['new']['chroot'] == "jailkit")
-			{
+						$this->_update_website_security_level();
 
-				// load the server configuration options
-				$app->uses("getconf");
-				$this->data = $data;
-				$this->app = $app;
-				$this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
+						$app->system->web_folder_protection($web['document_root'], false);
 
-				$this->_update_website_security_level();
+						$this->_setup_jailkit_chroot();
+						$this->_add_jailkit_user();
 
-				$app->system->web_folder_protection($web['document_root'], false);
+						//* call the ssh-rsa update function
+						$this->_setup_ssh_rsa();
 
-				$this->_setup_jailkit_chroot();
-				$this->_add_jailkit_user();
+						$this->_update_website_security_level();
 
-				//* call the ssh-rsa update function
-				$this->_setup_ssh_rsa();
+						$app->system->web_folder_protection($web['document_root'], true);
+					}
 
-				$this->_update_website_security_level();
+					$app->log("Jailkit Plugin -> update username:".$data['new']['username'], LOGLEVEL_DEBUG);
 
-				$app->system->web_folder_protection($web['document_root'], true);
+				} else {
+					$app->log("Jailkit Plugin -> update username:".$data['new']['username']." skipped, the user does not exist.", LOGLEVEL_WARN);
+				}
+			} else {
+				$app->log("UID = $uid for shelluser:".$data['new']['username']." not allowed.", LOGLEVEL_ERROR);
 			}
-
-			$app->log("Jailkit Plugin -> update username:".$data['new']['username'], LOGLEVEL_DEBUG);
-
 		} else {
-			$app->log("Jailkit Plugin -> update username:".$data['new']['username']." skipped, the user does not exist.", LOGLEVEL_WARN);
+			$app->log("Skipping update for user:".$data['new']['username'].", parent user ".$data['new']['puser']." does not exist.", LOGLEVEL_WARN);
 		}
 
 	}

--
Gitblit v1.9.1