From 1fa8f425b71db332a03ceef2d1e165083d0ba241 Mon Sep 17 00:00:00 2001
From: Falko Timme <ft@falkotimme.com>
Date: Fri, 5 Dec 2014 23:50:34 +0100
Subject: [PATCH] - Directive snippets can now be made available to clients;
 clients can select an available directive snippet for a website - the
 appropriate snippet will then be written to the vhost configuration file.
 This is useful for example on nginx where clients have no access to the
 Options tab of a website.

---
 install/sql/incremental/upd_0079.sql          |  2 +
 install/sql/ispconfig3.sql                    |  2 +
 .../classes/plugin_directive_snippets.inc.php | 72 +++++++++++++++++++
 .../admin/form/directive_snippets.tform.php   |  6 ++
 .../admin/lib/lang/de_directive_snippets.lng  |  1 +
 .../admin/lib/lang/en_directive_snippets.lng  |  1 +
 .../templates/directive_snippets_edit.htm     | 17 +++++
 interface/web/sites/ajax_get_json.php         | 11 +++
 .../web/sites/form/web_vhost_domain.tform.php |  8 ++-
 .../lib/lang/de_web_directive_snippets.lng    |  3 +
 .../lib/lang/en_web_directive_snippets.lng    |  3 +
 .../templates/web_directive_snippets.htm      | 14 ++++
 .../sites/templates/web_vhost_domain_edit.htm | 23 +++++-
 interface/web/sites/web_vhost_domain_edit.php |  2 +-
 .../plugins-available/apache2_plugin.inc.php  |  6 ++
 server/plugins-available/nginx_plugin.inc.php | 11 ++-
 16 files changed, 177 insertions(+), 5 deletions(-)
 create mode 100644 install/sql/incremental/upd_0079.sql
 create mode 100644 interface/lib/classes/plugin_directive_snippets.inc.php
 create mode 100644 interface/web/sites/lib/lang/de_web_directive_snippets.lng
 create mode 100644 interface/web/sites/lib/lang/en_web_directive_snippets.lng
 create mode 100644 interface/web/sites/templates/web_directive_snippets.htm

diff --git a/install/sql/incremental/upd_0079.sql b/install/sql/incremental/upd_0079.sql
new file mode 100644
index 0000000000..5dd0152753
--- /dev/null
+++ b/install/sql/incremental/upd_0079.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `directive_snippets` ADD `customer_viewable` ENUM('n','y') NOT NULL DEFAULT 'n' AFTER `snippet`;
+ALTER TABLE `web_domain` ADD `directive_snippets_id` int(11) unsigned NOT NULL default '0';
\ No newline at end of file
diff --git a/install/sql/ispconfig3.sql b/install/sql/ispconfig3.sql
index 3f65bfe32d..6af74fb984 100644
--- a/install/sql/ispconfig3.sql
+++ b/install/sql/ispconfig3.sql
@@ -429,6 +429,7 @@ CREATE TABLE IF NOT EXISTS `directive_snippets` (
   `name` varchar(255) DEFAULT NULL,
   `type` varchar(255) DEFAULT NULL,
   `snippet` mediumtext,
+  `customer_viewable` ENUM('n','y') NOT NULL DEFAULT 'n',
   `active` enum('n','y') NOT NULL DEFAULT 'y',
   PRIMARY KEY (`directive_snippets_id`)
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
@@ -1880,6 +1881,7 @@ CREATE TABLE `web_domain` (
   `rewrite_rules` mediumtext,
   `added_date` date NOT NULL DEFAULT '0000-00-00',
   `added_by` varchar(255) DEFAULT NULL,
+  `directive_snippets_id` int(11) unsigned NOT NULL default '0',
   PRIMARY KEY  (`domain_id`),
   UNIQUE KEY `serverdomain` (  `server_id` , `ip_address`,  `domain` )
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
diff --git a/interface/lib/classes/plugin_directive_snippets.inc.php b/interface/lib/classes/plugin_directive_snippets.inc.php
new file mode 100644
index 0000000000..dbc7d4887d
--- /dev/null
+++ b/interface/lib/classes/plugin_directive_snippets.inc.php
@@ -0,0 +1,72 @@
+<?php
+
+
+class plugin_directive_snippets extends plugin_base
+{
+	var $module;
+	var $form;
+	var $tab;
+	var $record_id;
+	var $formdef;
+	var $options;
+
+	public function onShow()
+	{
+		global $app;
+
+		$listTpl = new tpl;
+		$listTpl->newTemplate('templates/web_directive_snippets.htm');
+
+		//* Loading language file
+		$lng_file = "lib/lang/".$_SESSION["s"]["language"]."_web_directive_snippets.lng";
+
+		include $lng_file;
+		$listTpl->setVar($wb);
+
+		$message = '';
+		$error   = '';
+
+		$server_type = $app->getconf->get_server_config($this->form->dataRecord['server_id'], 'web');
+		$server_type = $server_type['server_type'];
+		$records = $app->db->queryAllRecords("SELECT directive_snippets_id, name FROM directive_snippets WHERE customer_viewable = 'y' AND type = ? ORDER BY name ASC", $server_type);
+
+		for ($i = 0, $c = count($records); $i < $c; $i++)
+		{
+			$records[$i]['is_selected'] = false;
+
+			if ($this->form->dataRecord['directive_snippets_id'] === $records[$i]['directive_snippets_id'])
+				$records[$i]['is_selected'] = true;
+		}
+
+		$listTpl->setLoop('records', $records);
+
+		$list_name = 'directive_snippets_list';
+		$_SESSION["s"]["list"][$list_name]["parent_id"] = $this->form->id;
+		$_SESSION["s"]["list"][$list_name]["parent_name"] = $app->tform->formDef["name"];
+		$_SESSION["s"]["list"][$list_name]["parent_tab"] = $_SESSION["s"]["form"]["tab"];
+		$_SESSION["s"]["list"][$list_name]["parent_script"] = $app->tform->formDef["action"];
+		$_SESSION["s"]["form"]["return_to"] = $list_name;
+
+		return $listTpl->grab();
+	}
+	
+	public function onUpdate()
+	{
+		global $app, $conf;
+
+		if (isset($this->form->dataRecord['directive_snippets_id']) && $this->form->oldDataRecord['directive_snippets_id'] !== $this->form->dataRecord['directive_snippets_id']) {
+			$app->db->query('UPDATE web_domain SET directive_snippets_id = ? WHERE domain_id = ?', $this->form->dataRecord['directive_snippets_id'], $this->form->id);
+		}
+	}
+
+	public function onInsert()
+	{
+		global $app, $conf;
+
+		if (isset($this->form->dataRecord['directive_snippets_id'])) {
+			$app->db->query('UPDATE web_domain SET directive_snippets_id = ? WHERE domain_id = ?', $this->form->dataRecord['directive_snippets_id'], $this->form->id);
+		}
+	}
+
+}
+?>
\ No newline at end of file
diff --git a/interface/web/admin/form/directive_snippets.tform.php b/interface/web/admin/form/directive_snippets.tform.php
index 2af05af6c3..8db725b95f 100644
--- a/interface/web/admin/form/directive_snippets.tform.php
+++ b/interface/web/admin/form/directive_snippets.tform.php
@@ -93,6 +93,12 @@ $form["tabs"]['directive_snippets'] = array (
 			'maxlength' => '255',
 			'searchable' => 2
 		),
+		'customer_viewable' => array (
+			'datatype' => 'VARCHAR',
+			'formtype' => 'CHECKBOX',
+			'default' => 'n',
+			'value'  => array(0 => 'n', 1 => 'y')
+		),
 		'active' => array (
 			'datatype' => 'VARCHAR',
 			'formtype' => 'CHECKBOX',
diff --git a/interface/web/admin/lib/lang/de_directive_snippets.lng b/interface/web/admin/lib/lang/de_directive_snippets.lng
index 18ce2d51b2..83a6b3c5f7 100644
--- a/interface/web/admin/lib/lang/de_directive_snippets.lng
+++ b/interface/web/admin/lib/lang/de_directive_snippets.lng
@@ -7,4 +7,5 @@ $wb['active_txt'] = 'Aktiv';
 $wb['directive_snippets_name_empty'] = 'Bitte geben Sie einen Namen für den Schnipsel an.';
 $wb['directive_snippets_name_error_unique'] = 'Es existiert schon ein Direktiven-Schnipsel mit diesem Namen.';
 $wb['variables_txt'] = 'Variablen';
+$wb['customer_viewable_txt'] = 'Sichtbar für Kunden';
 ?>
diff --git a/interface/web/admin/lib/lang/en_directive_snippets.lng b/interface/web/admin/lib/lang/en_directive_snippets.lng
index 9d9b0ae8ee..e8733cd948 100644
--- a/interface/web/admin/lib/lang/en_directive_snippets.lng
+++ b/interface/web/admin/lib/lang/en_directive_snippets.lng
@@ -7,4 +7,5 @@ $wb["active_txt"] = 'Active';
 $wb["directive_snippets_name_empty"] = 'Please specify a name for the snippet.';
 $wb["directive_snippets_name_error_unique"] = 'There is already a directive snippet with this name.';
 $wb['variables_txt'] = 'Variables';
+$wb['customer_viewable_txt'] = 'Customer viewable';
 ?>
\ No newline at end of file
diff --git a/interface/web/admin/templates/directive_snippets_edit.htm b/interface/web/admin/templates/directive_snippets_edit.htm
index 7a17cb679e..ca5cb9651c 100644
--- a/interface/web/admin/templates/directive_snippets_edit.htm
+++ b/interface/web/admin/templates/directive_snippets_edit.htm
@@ -18,6 +18,12 @@
 			<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><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='customer_viewable_txt'}</p>
+                <div class="multiField">
+                    {tmpl_var name='customer_viewable'}
+                </div>
             </div>
             <div class="ctrlHolder">
                 <p class="label">{tmpl_var name='active_txt'}</p>
@@ -43,8 +49,19 @@
     } else {
         jQuery('.nginx:visible').hide();
     }
+	
+	if (jQuery('#type').val() != 'nginx' && jQuery('#type').val() != 'apache') {
+		jQuery('#customer_viewable').closest('div.ctrlHolder:visible').hide();
+	}else {
+		jQuery('#customer_viewable').closest('div.ctrlHolder:hidden').show();
+	}
     
     jQuery('#type').change(function(){
+		if (jQuery(this).val() != 'nginx' && jQuery(this).val() != 'apache') {
+			jQuery('#customer_viewable').closest('div.ctrlHolder:visible').hide();
+		} else {
+			jQuery('#customer_viewable').closest('div.ctrlHolder:hidden').show();
+		}
         if(jQuery(this).val() == 'nginx'){
             jQuery('.nginx:hidden').show();
         } else {
diff --git a/interface/web/sites/ajax_get_json.php b/interface/web/sites/ajax_get_json.php
index ddf7d8550b..fb2f1c093f 100644
--- a/interface/web/sites/ajax_get_json.php
+++ b/interface/web/sites/ajax_get_json.php
@@ -190,6 +190,17 @@ if($type == 'get_use_loadindicator'){
 	$json .= '"}';
 }
 
+if ($type == 'getdirectivesnippet') {
+	$server_type = 'apache';
+	$web_config = $app->getconf->get_server_config($server_id, 'web');
+	if (!empty($web_config['server_type']))
+		$server_type = $web_config['server_type'];
+
+	$snippets = $app->db->queryAllRecords("SELECT directive_snippets_id, name FROM directive_snippets WHERE customer_viewable = 'y' AND type = ? ORDER BY name ASC", $server_type);
+
+	$json = json_encode($snippets);
+}
+
 //}
 
 header('Content-type: application/json');
diff --git a/interface/web/sites/form/web_vhost_domain.tform.php b/interface/web/sites/form/web_vhost_domain.tform.php
index 7d50b97478..4d6b161db4 100644
--- a/interface/web/sites/form/web_vhost_domain.tform.php
+++ b/interface/web/sites/form/web_vhost_domain.tform.php
@@ -282,7 +282,13 @@ $form["tabs"]['domain'] = array (
 		//#################################
 		// ENDE Datatable fields
 		//#################################
-	)
+	),
+	'plugins' => array (
+		// needs serverId for web.server_type
+		'directive_snippets_id' => array (
+			'class' => 'plugin_directive_snippets'
+		),
+ 	)
 );
 
 // add type-specific field attributes
diff --git a/interface/web/sites/lib/lang/de_web_directive_snippets.lng b/interface/web/sites/lib/lang/de_web_directive_snippets.lng
new file mode 100644
index 0000000000..b6d898496e
--- /dev/null
+++ b/interface/web/sites/lib/lang/de_web_directive_snippets.lng
@@ -0,0 +1,3 @@
+<?php
+$wb['directive_snippets_id_txt'] = 'Gewünschte Konfiguration';
+?>
\ No newline at end of file
diff --git a/interface/web/sites/lib/lang/en_web_directive_snippets.lng b/interface/web/sites/lib/lang/en_web_directive_snippets.lng
new file mode 100644
index 0000000000..05a004f654
--- /dev/null
+++ b/interface/web/sites/lib/lang/en_web_directive_snippets.lng
@@ -0,0 +1,3 @@
+<?php
+$wb['directive_snippets_id_txt'] = 'Desired configuration';
+?>
\ No newline at end of file
diff --git a/interface/web/sites/templates/web_directive_snippets.htm b/interface/web/sites/templates/web_directive_snippets.htm
new file mode 100644
index 0000000000..664a07fd58
--- /dev/null
+++ b/interface/web/sites/templates/web_directive_snippets.htm
@@ -0,0 +1,14 @@
+<div class="ctrlHolder">
+	<label for="directive_snippets_id">
+		{tmpl_var name='directive_snippets_id_txt'}
+	</label>
+
+	<select name="directive_snippets_id" id="directive_snippets_id" class="selectInput formLengthHalf">
+		<option value="0"></option>
+		<tmpl_loop name="records">
+		<option {tmpl_if name='is_selected' op='==' value='true'}selected="selected" {/tmpl_if}value="{tmpl_var name='directive_snippets_id'}">
+			{tmpl_var name='name'}
+		</option>
+		</tmpl_loop>
+	</select>
+</div>
\ No newline at end of file
diff --git a/interface/web/sites/templates/web_vhost_domain_edit.htm b/interface/web/sites/templates/web_vhost_domain_edit.htm
index 0e0897a5cc..6548e82748 100644
--- a/interface/web/sites/templates/web_vhost_domain_edit.htm
+++ b/interface/web/sites/templates/web_vhost_domain_edit.htm
@@ -219,6 +219,7 @@
                     {tmpl_var name='fastcgi_php_version'}
                 </select>
             </div>
+			{tmpl_var name="directive_snippets_id"}
             <div class="ctrlHolder">
                 <p class="label">{tmpl_var name='active_txt'}</p>
                 <div class="multiField">
@@ -249,6 +250,7 @@
             adjustForm();
             reloadWebIP();
             reloadFastcgiPHPVersions();
+			reloadDirectiveSnippets();
         });
     }
     adjustForm(true);
@@ -316,6 +318,23 @@
             }
         });
     }
+	
+	function reloadDirectiveSnippets() {
+        jQuery.getJSON('sites/ajax_get_json.php'+ '?' + Math.round(new Date().getTime()), {server_id : serverId, type : "getdirectivesnippet"}, function(data) {
+            var options = '<option value="0"></option>';
+			for (var i = 0, len = data.length; i < len; i++) {
+				var isSelected = '';
+
+				 if ($('#directive_snippets_id').val() == i + 1) {
+					 isSelected = 'selected="selected"';
+				 }
+
+				 options += '<option ' + isSelected + ' value="' + data[i]['directive_snippets_id'] + '">' + data[i]['name'] + '</option>';
+			}
+
+			$('#directive_snippets_id').html(options).change();
+		});
+	}
 		
     function reloadWebIP() {
         loadOptionInto('ip_address','sites/ajax_get_ip.php?ip_type=IPv4&server_id='+serverId+'&client_group_id='+clientGroupId);
@@ -340,9 +359,9 @@
     }
     
     <tmpl_if name="readonly_tab">
-        jQuery('div.panel_web_domain').find('fieldset').find('input,select,button').bind('click mousedown', function(e) { e.preventDefault(); }).focus(function() { $(this).blur(); });
+        jQuery('div.panel_web_domain').find('fieldset').find('input,select,button').not('#directive_snippets_id').bind('click mousedown', function(e) { e.preventDefault(); }).focus(function() { $(this).blur(); });
         jQuery('#dom-edit-submit').click(function() {
-               submitForm('pageForm','sites/web_vhost_domain_edit.php');
+			submitForm('pageForm','sites/web_vhost_domain_edit.php');
         });
     <tmpl_else>
         jQuery('#dom-edit-submit').click(function() {
diff --git a/interface/web/sites/web_vhost_domain_edit.php b/interface/web/sites/web_vhost_domain_edit.php
index e868ece7bd..8935713063 100644
--- a/interface/web/sites/web_vhost_domain_edit.php
+++ b/interface/web/sites/web_vhost_domain_edit.php
@@ -191,7 +191,7 @@ class page_action extends tform_actions {
 			if($app->functions->intval($this->dataRecord["server_id"]) > 0) {
 				// check if server is in client's servers or add it.
 				$chk_sid = explode(',', $client['web_servers']);
-				if(in_array($this->dataRecord["server_id"], $client['web_servers']) == false) {
+				if(in_array($this->dataRecord["server_id"], explode(',', $client['web_servers'])) == false) {
 					if($client['web_servers'] != '') $client['web_servers'] .= ',';
 					$client['web_servers'] .= $app->functions->intval($this->dataRecord["server_id"]);
 				}
diff --git a/server/plugins-available/apache2_plugin.inc.php b/server/plugins-available/apache2_plugin.inc.php
index 2bf4dfe3a9..ec98e849c8 100644
--- a/server/plugins-available/apache2_plugin.inc.php
+++ b/server/plugins-available/apache2_plugin.inc.php
@@ -1030,6 +1030,12 @@ class apache2_plugin {
 		$vhost_data['custom_php_ini_dir'] = escapeshellcmd($custom_php_ini_dir);
 
 		// Custom Apache directives
+		if(intval($data['new']['directive_snippets_id']) > 0){
+			$snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'apache' AND active = 'y' AND customer_viewable = 'y'", intval($data['new']['directive_snippets_id']));
+			if(isset($snippet['snippet'])){
+				$vhost_data['apache_directives'] = $snippet['snippet'];
+			}
+		}
 		// Make sure we only have Unix linebreaks
 		$vhost_data['apache_directives'] = str_replace("\r\n", "\n", $vhost_data['apache_directives']);
 		$vhost_data['apache_directives'] = str_replace("\r", "\n", $vhost_data['apache_directives']);
diff --git a/server/plugins-available/nginx_plugin.inc.php b/server/plugins-available/nginx_plugin.inc.php
index 57044eff43..c256ae18f6 100644
--- a/server/plugins-available/nginx_plugin.inc.php
+++ b/server/plugins-available/nginx_plugin.inc.php
@@ -1089,7 +1089,16 @@ class nginx_plugin {
 
 		// Custom nginx directives
 		$final_nginx_directives = array();
-		$nginx_directives = $data['new']['nginx_directives'];
+		if(intval($data['new']['directive_snippets_id']) > 0){
+			$snippet = $app->db->queryOneRecord("SELECT * FROM directive_snippets WHERE directive_snippets_id = ? AND type = 'nginx' AND active = 'y' AND customer_viewable = 'y'", intval($data['new']['directive_snippets_id']));
+			if(isset($snippet['snippet'])){
+				$nginx_directives = $snippet['snippet'];
+			} else {
+				$nginx_directives = $data['new']['nginx_directives'];
+			}
+		} else {
+			$nginx_directives = $data['new']['nginx_directives'];
+		}
 		// Make sure we only have Unix linebreaks
 		$nginx_directives = str_replace("\r\n", "\n", $nginx_directives);
 		$nginx_directives = str_replace("\r", "\n", $nginx_directives);
-- 
GitLab