From 4c2c363036bbf1093cd0f732a23a05795e16aa06 Mon Sep 17 00:00:00 2001
From: bmarlon <bmarlon@ispconfig3>
Date: Thu, 28 Apr 2011 10:03:16 +0000
Subject: [PATCH] * Changed "aptitude upgrade -y" to "aptitude safe-upgrade -y"
 since upgrade is deprecated. + Added DNS-import, not finished. Needs
 language-variables and better way to parse SOA-record and possibly some
 cleaning.

---
 interface/web/dns/dns_import.php              | 321 +++++++++++++++
 interface/web/dns/lib/module.conf.php         |   5 +
 interface/web/dns/templates/dns_import.htm    |  52 +++
 interface/web/dns/templates/dns_soa_list.htm  |   3 +
 .../remoteaction_core_module.inc.php          | 388 +++++++++---------
 5 files changed, 575 insertions(+), 194 deletions(-)
 create mode 100644 interface/web/dns/dns_import.php
 create mode 100644 interface/web/dns/templates/dns_import.htm

diff --git a/interface/web/dns/dns_import.php b/interface/web/dns/dns_import.php
new file mode 100644
index 000000000..861c9c833
--- /dev/null
+++ b/interface/web/dns/dns_import.php
@@ -0,0 +1,321 @@
+<?php
+
+/*
+Copyright (c) 2008, Till Brehm, projektfarm Gmbh
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of ISPConfig nor the names of its contributors
+      may be used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once('../../lib/config.inc.php');
+require_once('../../lib/app.inc.php');
+
+//* Check permissions for module
+$app->auth->check_module_permissions('dns');
+
+
+// Loading the template
+$app->uses('tpl,validate_dns');
+$app->tpl->newTemplate("form.tpl.htm");
+$app->tpl->setInclude('content_tpl','templates/dns_import.htm');
+$app->load_language_file('/web/dns/lib/lang/'.$_SESSION['s']['language'].'_dns_wizard.lng');
+
+// import variables
+$template_id = (isset($_POST['template_id']))?intval($_POST['template_id']):0;
+$sys_groupid = (isset($_POST['client_group_id']))?intval($_POST['client_group_id']):0;
+$domain = (isset($_POST['domain'])&&!empty($_POST['domain']))?$_POST['domain']:NULL;
+
+// get the correct server_id
+if($_SESSION['s']['user']['typ'] == 'admin') {
+	$server_id = (isset($_POST['server_id']))?intval($_POST['server_id']):1;
+} else {
+	$client_group_id = $_SESSION["s"]["user"]["default_group"];
+	$client = $app->db->queryOneRecord("SELECT default_dnsserver FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+	$server_id = $client["default_dnsserver"];
+}
+
+
+// Load the templates
+$records = $app->db->queryAllRecords("SELECT * FROM dns_template WHERE visible = 'Y'");
+$template_id_option = '';
+$n = 0;
+foreach($records as $rec){
+	$checked = ($rec['template_id'] == $template_id)?' SELECTED':'';
+	$template_id_option .= '<option value="'.$rec['template_id'].'"'.$checked.'>'.$rec['name'].'</option>';
+	if($n == 0 && $template_id == 0) $template_id = $rec['template_id'];
+	$n++;
+}
+unset($n);
+$app->tpl->setVar("template_id_option",$template_id_option);
+
+// If the user is administrator
+if($_SESSION['s']['user']['typ'] == 'admin') {
+	
+	// Load the list of servers
+	$records = $app->db->queryAllRecords("SELECT server_id, server_name FROM server WHERE mirror_server_id = 0 AND dns_server = 1 ORDER BY server_name");
+	$server_id_option = '';
+	foreach($records as $rec){
+		$checked = ($rec['server_id'] == $server_id)?' SELECTED':'';
+		$server_id_option .= '<option value="'.$rec['server_id'].'"'.$checked.'>'.$rec['server_name'].'</option>';
+	}
+	$app->tpl->setVar("server_id",$server_id_option);
+	
+	// load the list of clients
+	$sql = "SELECT groupid, name FROM sys_group WHERE client_id > 0 ORDER BY name";
+	$clients = $app->db->queryAllRecords($sql);
+	$client_select = '';
+	if($_SESSION["s"]["user"]["typ"] == 'admin') $client_select .= "<option value='0'></option>";
+	if(is_array($clients)) {
+		foreach( $clients as $client) {
+			$selected = ($client["groupid"] == $sys_groupid)?'SELECTED':'';
+			$client_select .= "<option value='$client[groupid]' $selected>$client[name]</option>\r\n";
+		}
+	}
+
+	$app->tpl->setVar("client_group_id",$client_select);
+}
+
+if ($_SESSION["s"]["user"]["typ"] != 'admin' && $app->auth->has_clients($_SESSION['s']['user']['userid'])) {
+	
+	// Get the limits of the client
+	$client_group_id = $_SESSION["s"]["user"]["default_group"];
+	$client = $app->db->queryOneRecord("SELECT client.client_id, contact_name FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+
+	
+	// load the list of clients
+	$sql = "SELECT groupid, name FROM sys_group, client WHERE sys_group.client_id = client.client_id AND client.parent_client_id = ".$client['client_id'];
+	$clients = $app->db->queryAllRecords($sql);
+	$tmp = $app->db->queryOneRecord("SELECT groupid FROM sys_group WHERE client_id = ".$client['client_id']);
+	$client_select = '<option value="'.$tmp['groupid'].'">'.$client['contact_name'].'</option>';
+	if(is_array($clients)) {
+		foreach( $clients as $client) {
+			$selected = ($client["groupid"] == $sys_groupid)?'SELECTED':'';
+			$client_select .= "<option value='$client[groupid]' $selected>$client[name]</option>\r\n";
+		}
+	}
+
+	$app->tpl->setVar("client_group_id",$client_select);
+}
+
+// Import the zone-file
+//if(1=="1")
+if(isset($_FILES['file']['name']) && is_uploaded_file($_FILES['file']['tmp_name']))
+{
+	$sql = "SELECT server_name FROM `server` WHERE server_id=".intval($server_id)." OR mirror_server_id=".intval($server_id)." ORDER BY server_name ASC";
+	$servers = $app->db->queryAllRecords($sql);
+	for ($i=0;$i<count($servers);$i++)
+	{
+		if (substr($servers[$i]['server_name'],strlen($servers[$i]['server_name'])-1) != ".")
+		{
+			$servers[$i]['server_name'] .= ".";
+		}
+	}
+	$lines = file($_FILES['file']['tmp_name']);
+	//$lines = file("apriqot.se.txt");
+	$name = str_replace("txt","",$_FILES['file']['name']);
+	$name = str_replace("zone","",$name);
+	if ($domain !== NULL)
+	{
+		$name = $domain;
+		if (substr($name,strlen($name)-1) != ".")
+		{
+			$name .= ".";
+		}
+	}
+	$i = 0;
+	$r = 0;
+	$s = 0;
+	$dns_rr = array();
+	foreach ($lines as $line)
+	{
+		if (substr($line,0,1)!=';'&&substr($line,0,1)!='$')
+		{
+			$line = str_replace("\n",NULL,$line);
+			$i++;
+
+			// TODO - Find a better way to parse the SOA record. Lazy checking.
+			if ($i <= 7)
+			{
+				if ($i > 1)
+				{
+					$s++;
+					$line = str_replace("\t",NULL,$line);
+					if (!empty($line))
+					{
+						print(strpos(";",$line));
+						$line = substr($line,0,strpos($line,";"));
+						if ($s == 1)
+							$soa['serial'] = $line;
+						else if ($s == 2)
+							$soa['refresh'] = $line;
+						else if ($s == 3)
+							$soa['retry'] = $line;
+						else if ($s == 4)
+							$soa['expire'] = $line;
+						else if ($s == 5)
+							$soa['ttl'] = $line;
+
+					}
+				}
+				else
+				{
+					$line = str_replace("\t",",",$line);
+					$recs = explode(",",$line);
+
+					foreach ($recs as $key => $rec)
+					{
+						$rec = trim($rec);
+						//name	type	data	aux	ttl	active
+						if ($key == 0)
+						{
+							if ($rec == '@' || $rec == "")
+							{
+								$rec = $name;
+							}
+
+							$soa['name'] = $rec;
+						}
+
+						if ($key != 0 && strtolower($rec) == 'soa')
+						{
+							$typekeys[$s] = $key;
+						}
+						else if ($key > $typekey[$r])
+						{
+							if ($rec != ""&&$rec != "(")
+							{
+								$rec = explode(" ",$rec);
+
+								$soa['ns'] = $servers[0]['server_name'];
+								$soa['mbox'] = $rec[1];
+							}
+						}
+					}
+				}
+			}
+			else
+			{
+				$line = str_replace("\n","",trim($line));
+
+				if (!empty($line))
+				{
+
+					preg_match_all('/(.*?)\s*IN\s*(A|CNAME|MX|TXT|NS|AAAA)\s*(.*)/',$line, $recs);
+
+					if ($recs[1][0] == '@' || trim($recs[1][0]) == "")
+					{
+						$recs[1][0] = $name;
+					}
+					$dns_rr[$r]['name'] = $recs[1][0];
+					$dns_rr[$r]['type'] = $recs[2][0];
+					if (strtolower($dns_rr[$r]['type'])=='mx')
+					{
+						$recs[3][0] = str_replace(" ","\t",$recs[3][0]);
+						$mx[$r] = explode("\t",$recs[3][0]);
+						for ($m=1;$m<count($mx[$r]);$m++)
+						{
+							if (!empty($mx[$r][$m]))
+								$dns_rr[$r]['data'] = $mx[$r][$m];
+						}
+						
+						$dns_rr[$r]['aux'] = $mx[$r][0];
+					}
+					else if (strtolower($dns_rr[$r]['type'])=='txt')
+					{
+						$dns_rr[$r]['data'] = substr($recs[3][0],1,(strlen($recs[3][0])-2));
+					}
+					else
+					{
+						$dns_rr[$r]['data'] = $recs[3][0];
+					}
+
+					if (strtolower($dns_rr[$r]['type'])=='ns' && strtolower($dns_rr[$r]['name'])==$name)
+					{
+						unset($dns_rr[$r]);
+					}
+
+					$r++;
+				}
+			}
+
+		}
+	}
+
+	foreach ($servers as $server)
+	{
+		$dns_rr[$r]['name']=$name;
+		$dns_rr[$r]['type']='NS';
+		$dns_rr[$r]['data'] = $server['server_name'];
+		$dns_rr[$r]['aux'] = 0;
+
+		$r++;
+	}
+					print('<pre>');
+					print_r($dns_rr);
+					print('</pre>');
+	// Insert the soa record
+	$sys_userid = $_SESSION['s']['user']['userid'];
+	$origin = $app->db->quote($soa['name']);
+	$ns = $app->db->quote($soa['ns']);
+	$mbox = $app->db->quote($soa['mbox']);
+	$refresh = $app->db->quote($soa['refresh']);
+	$retry = $app->db->quote($soa['retry']);
+	$expire = $app->db->quote($soa['expire']);
+	$minimum = $app->db->quote($soa['ttl']);
+	$ttl = $app->db->quote($soa['ttl']);
+	$xfer = $app->db->quote('');
+	$serial = $app->db->quote(intval($soa['serial'])+1);
+	
+	$insert_data = "(`sys_userid`, `sys_groupid`, `sys_perm_user`, `sys_perm_group`, `sys_perm_other`, `server_id`, `origin`, `ns`, `mbox`, `serial`, `refresh`, `retry`, `expire`, `minimum`, `ttl`, `active`, `xfer`) VALUES
+	('$sys_userid', '$sys_groupid', 'riud', 'riud', '', '$server_id', '$origin', '$ns', '$mbox', '$serial', '$refresh', '$retry', '$expire', '$minimum', '$ttl', 'Y', '$xfer')";
+	$dns_soa_id = $app->db->datalogInsert('dns_soa', $insert_data, 'id');
+	
+	// Insert the dns_rr records
+	if(is_array($dns_rr) && $dns_soa_id > 0)
+	{
+		foreach($dns_rr as $rr)
+		{
+			$insert_data = "(`sys_userid`, `sys_groupid`, `sys_perm_user`, `sys_perm_group`, `sys_perm_other`, `server_id`, `zone`, `name`, `type`, `data`, `aux`, `ttl`, `active`) VALUES
+			('$sys_userid', '$sys_groupid', 'riud', 'riud', '', '$server_id', '$dns_soa_id', '$rr[name]', '$rr[type]', '$rr[data]', '$rr[aux]', '$rr[ttl]', 'Y')";
+			$dns_rr_id = $app->db->datalogInsert('dns_rr', $insert_data, 'id');
+		}
+	}
+	
+	header('Location: /dns/dns_soa_edit.php?id='.$dns_soa_id);
+}
+
+$app->tpl->setVar('msg',$msg);
+$app->tpl->setVar('error',$error);
+
+$app->tpl->setVar("title",'Import Zone Files');
+
+$lng_file = 'lib/lang/'.$_SESSION['s']['language'].'_dns_wizard.lng';
+include($lng_file);
+$app->tpl->setVar($wb);
+
+$app->tpl_defaults();
+$app->tpl->pparse();
+
+
+?>
\ No newline at end of file
diff --git a/interface/web/dns/lib/module.conf.php b/interface/web/dns/lib/module.conf.php
index 8018e9808..1af3a893d 100644
--- a/interface/web/dns/lib/module.conf.php
+++ b/interface/web/dns/lib/module.conf.php
@@ -12,6 +12,11 @@ $items[] = array( 'title' 	=> "Add DNS Zone",
 				  'link'	=> 'dns/dns_wizard.php',
 				  'html_id' => 'dns_wizard');
 
+$items[] = array( 'title' 	=> "Import Zone File",
+				  'target' 	=> 'content',
+				  'link'	=> 'dns/dns_import.php',
+				  'html_id' => 'dns_import');
+
 if($_SESSION["s"]["user"]["typ"] == 'admin') {
   $items[] = array( 	'title' 	=> "Templates",
 				  'target' 	=> 'content',
diff --git a/interface/web/dns/templates/dns_import.htm b/interface/web/dns/templates/dns_import.htm
new file mode 100644
index 000000000..a8e235137
--- /dev/null
+++ b/interface/web/dns/templates/dns_import.htm
@@ -0,0 +1,52 @@
+<h2><tmpl_var name="list_head_txt"></h2>
+<p><tmpl_var name="list_desc_txt"></p>
+
+<tmpl_if name="error">
+	<div id="errorMsg"><h3>ERROR</h3><ol><tmpl_var name="error"></ol></div>
+</tmpl_if>
+
+<div class="panel panel_dns_wizard">
+
+  <div class="pnl_formsarea">
+        <fieldset class="inlineLabels"><legend>Zone File Import</legend>
+      <tmpl_if name="is_admin">
+      <div class="ctrlHolder">
+      	<label for="server_id">{tmpl_var name='server_id_txt'}</label>
+        <select name="server_id" id="server_id" class="selectInput">
+					{tmpl_var name='server_id'}
+				</select>
+      </div>
+      <div class="ctrlHolder">
+      	<label for="client_group_id">{tmpl_var name='client_txt'}</label>
+        <select name="client_group_id" id="client_group_id" class="selectInput">
+					{tmpl_var name='client_group_id'}
+				</select>
+      </div>
+      </tmpl_if>
+	      <div class="ctrlHolder">
+	      	<label for="domain">{tmpl_var name='domain_txt'}. Can be left empty if domain name is in the filename or the zone-file content.</label>
+	        <input name="domain" id="domain" value="{tmpl_var name='domain'}" size="30" maxlength="255" type="text" class="textInput" />
+				</div>
+
+      <div class="ctrlHolder" style="margin-left:0px;left:0px;padding-left:0px;">
+	      <input name="file" id="file" size="30" type="file" class="fileUpload" />
+      </div>
+
+	<tmpl_if name="msg">
+	<div id="OKMsg"><p><tmpl_var name="msg"></p></div>
+  </tmpl_if>
+  <tmpl_if name="error">
+	<div id="errorMsg"><h3>ERROR</h3><ol><tmpl_var name="error"></ol></div>
+  </tmpl_if>
+
+    <input type="hidden" name="id" value="{tmpl_var name='id'}">
+
+    <div class="buttonHolder buttons">
+      <button class="positive iconstxt icoPositive" type="button" value="{tmpl_var name='btn_save_txt'}" onClick="submitUploadForm('pageForm','dns/dns_import.php');"><span>{tmpl_var name='btn_save_txt'}</span></button>
+      <button class="negative iconstxt icoNegative" type="button" value="{tmpl_var name='btn_cancel_txt'}" onClick="loadContent('dns/dns_soa_list.php');"><span>{tmpl_var name='btn_cancel_txt'}</span></button>
+    </div>
+
+	</fieldset>
+  </div>
+  
+</div>
diff --git a/interface/web/dns/templates/dns_soa_list.htm b/interface/web/dns/templates/dns_soa_list.htm
index 4ed162a3d..13be4f776 100644
--- a/interface/web/dns/templates/dns_soa_list.htm
+++ b/interface/web/dns/templates/dns_soa_list.htm
@@ -12,6 +12,9 @@
         <button class="iconstxt icoAdd" type="button" onClick="loadContent('dns/dns_soa_edit.php');">
           <span>{tmpl_var name="add_new_record_txt"}</span>
         </button>
+        <button class="iconstxt icoAdd" type="button" onClick="loadContent('dns/dns_import.php');">
+          <span>Import Zone File</span>
+        </button>
       </div>
     </fieldset>
   </div>
diff --git a/server/mods-available/remoteaction_core_module.inc.php b/server/mods-available/remoteaction_core_module.inc.php
index ebdd404cd..b112e8c54 100644
--- a/server/mods-available/remoteaction_core_module.inc.php
+++ b/server/mods-available/remoteaction_core_module.inc.php
@@ -1,141 +1,141 @@
-<?php
-/*
-Copyright (c) 2007-2010, Till Brehm, projektfarm Gmbh and Oliver Vogel www.muv.com
-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.
-*/
-
-class remoteaction_core_module {
-	var $module_name = 'remoteaction_core_module';
-	var $class_name = 'remoteaction_core_module';
-	/* No actions at this time. maybe later... */
-	var $actions_available = array();
-	//* This function is called during ispconfig installation to determine
-	//  if a symlink shall be created for this plugin.
-	function onInstall() {
-		return true;
-	}
-
-	/*
-        This function is called when the module is loaded
-	*/
-	function onLoad() {
-		/*
-       	 * Check for actions to execute
-		*/
-		$this->_execActions();
-	}
-
-	/*
-     This function is called when a change in one of the registered tables is detected.
-     The function then raises the events for the plugins.
-	*/
-	function process($tablename, $action, $data) {
-		// not needed
-	} // end function
-
-	private function _actionDone($id, $state) {
-		/*
-		 * First set the state
-		 */
-		global $app;
-		$sql = "UPDATE sys_remoteaction " .
-				"SET action_state = '" . $app->dbmaster->quote($state) . "' " .
-				"WHERE action_id = " . intval($id);
-		$app->dbmaster->query($sql);
-
-		/*
-		 * Then save the maxid for the next time...
-		 */
-		$fp = fopen(dirname(__FILE__) .  "/../lib/remote_action.inc.php", 'wb');
-		$content = '<?php' . "\n" . '$maxid_remote_action = ' . $id . ';' . "\n?>";
-		fwrite($fp, $content);
-		fclose($fp);
-	}
-
-
-	/**
-	 * This method searches for scheduled actions and exec then
-	 */
-	private function _execActions() {
-		global $app;
-		global $conf;
-
-		/* the id of the server as int */
-		$server_id = intval($conf["server_id"]);
-
-		/*
-		 * First we (till and i, oliver) thought, it was enough to write
-		 * "select from where action_status = 'pending'" and then execute this actions.
-		 * But it is not!
-		 * If a hacker can hack into a server, she can change the valus of action_status
-		 * and so re-exec a action, executed some days bevore. So she can (for example)
-		 * stop a service, a admin stopped some days before! To avoid this, we ignore
-		 * the status (it is only for the interface to show) and use our own maxid
-		*/
-		include_once (dirname(__FILE__) .  "/../lib/remote_action.inc.php");
-
-		/*
-		 * Get all actions this server should execute
-		*/
-		$sql = "SELECT action_id, action_type, action_param " .
-				"FROM sys_remoteaction " .
-				"WHERE server_id = " . $server_id . " ".
-				" AND  action_id > " . intval($maxid_remote_action) . " ".
-				"ORDER BY action_id";
-		$actions = $app->dbmaster->queryAllRecords($sql);
-
-		/*
-		 * process all actions
-		*/
-		if(is_array($actions)) {
-			foreach ($actions as $action) {
-				if ($action['action_type'] == 'os_update') {
-					/* do the update */
-					$this->_doOsUpdate($action);
-					/* this action takes so much time,
-					* we stop executing the actions not to waste more time */
-					return;
-				}
-				if ($action['action_type'] == 'ispc_update') {
-					/* do the update */
-					$this->_doIspCUpdate($action);
-					/* this action takes so much time,
-					* we stop executing the actions not to waste more time */
-					return;
-				}
-			}
-		}
-	}
-
-	private function _doOsUpdate($action) {
-		/*
-		 * Do the update
-		 */
+<?php
+/*
+Copyright (c) 2007-2010, Till Brehm, projektfarm Gmbh and Oliver Vogel www.muv.com
+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.
+*/
+
+class remoteaction_core_module {
+	var $module_name = 'remoteaction_core_module';
+	var $class_name = 'remoteaction_core_module';
+	/* No actions at this time. maybe later... */
+	var $actions_available = array();
+	//* This function is called during ispconfig installation to determine
+	//  if a symlink shall be created for this plugin.
+	function onInstall() {
+		return true;
+	}
+
+	/*
+        This function is called when the module is loaded
+	*/
+	function onLoad() {
+		/*
+       	 * Check for actions to execute
+		*/
+		$this->_execActions();
+	}
+
+	/*
+     This function is called when a change in one of the registered tables is detected.
+     The function then raises the events for the plugins.
+	*/
+	function process($tablename, $action, $data) {
+		// not needed
+	} // end function
+
+	private function _actionDone($id, $state) {
+		/*
+		 * First set the state
+		 */
+		global $app;
+		$sql = "UPDATE sys_remoteaction " .
+				"SET action_state = '" . $app->dbmaster->quote($state) . "' " .
+				"WHERE action_id = " . intval($id);
+		$app->dbmaster->query($sql);
+
+		/*
+		 * Then save the maxid for the next time...
+		 */
+		$fp = fopen(dirname(__FILE__) .  "/../lib/remote_action.inc.php", 'wb');
+		$content = '<?php' . "\n" . '$maxid_remote_action = ' . $id . ';' . "\n?>";
+		fwrite($fp, $content);
+		fclose($fp);
+	}
+
+
+	/**
+	 * This method searches for scheduled actions and exec then
+	 */
+	private function _execActions() {
+		global $app;
+		global $conf;
+
+		/* the id of the server as int */
+		$server_id = intval($conf["server_id"]);
+
+		/*
+		 * First we (till and i, oliver) thought, it was enough to write
+		 * "select from where action_status = 'pending'" and then execute this actions.
+		 * But it is not!
+		 * If a hacker can hack into a server, she can change the valus of action_status
+		 * and so re-exec a action, executed some days bevore. So she can (for example)
+		 * stop a service, a admin stopped some days before! To avoid this, we ignore
+		 * the status (it is only for the interface to show) and use our own maxid
+		*/
+		include_once (dirname(__FILE__) .  "/../lib/remote_action.inc.php");
+
+		/*
+		 * Get all actions this server should execute
+		*/
+		$sql = "SELECT action_id, action_type, action_param " .
+				"FROM sys_remoteaction " .
+				"WHERE server_id = " . $server_id . " ".
+				" AND  action_id > " . intval($maxid_remote_action) . " ".
+				"ORDER BY action_id";
+		$actions = $app->dbmaster->queryAllRecords($sql);
+
+		/*
+		 * process all actions
+		*/
+		if(is_array($actions)) {
+			foreach ($actions as $action) {
+				if ($action['action_type'] == 'os_update') {
+					/* do the update */
+					$this->_doOsUpdate($action);
+					/* this action takes so much time,
+					* we stop executing the actions not to waste more time */
+					return;
+				}
+				if ($action['action_type'] == 'ispc_update') {
+					/* do the update */
+					$this->_doIspCUpdate($action);
+					/* this action takes so much time,
+					* we stop executing the actions not to waste more time */
+					return;
+				}
+			}
+		}
+	}
+
+	private function _doOsUpdate($action) {
+		/*
+		 * Do the update
+		 */
 		exec("aptitude update");
-		exec("aptitude upgrade -y");
+		exec("aptitude safe-upgrade -y");
 
 		//TODO : change this when distribution information has been integrated into server record
 		if(file_exists('/etc/gentoo-release')) {
@@ -147,61 +147,61 @@ class remoteaction_core_module {
 		}
 		
 		/*
-		 * All well done!
-		 */
-		$this->_actionDone($action['action_id'], 'ok');
-	}
-
-	private function _doIspCUpdate($action) {
-		
-		// Ensure that this code is not executed twice as this would cause a loop in case of a failure
-		$this->_actionDone($action['action_id'], 'ok');
-		
-		/*
-		 * Get the version-number of the newest version 
-		 */
-		$new_version = @file_get_contents('http://www.ispconfig.org/downloads/ispconfig3_version.txt');
-		$new_version = trim($new_version);
-
-		/*
-		 * Do the update
-		 */
-
-		/* jump into the temporary dir */
-		$oldDir = getcwd();
-		chdir("/tmp");
-
-		/* delete the old files (if there are any...) */
-		exec("rm /tmp/ISPConfig-" . $new_version . ".tar.gz");
-		exec("rm /tmp/ispconfig3_install -R");
-		
-		/* get the newest version */
-		exec("wget http://www.ispconfig.org/downloads/ISPConfig-" . $new_version . ".tar.gz");
-		
-		/* extract the files */
-		exec("tar xvfz ISPConfig-" . $new_version . ".tar.gz");
-
-		/*
-		 * Initialize the automated update
-		 * (the update is then done next start of server.sh
-		 */
-		chdir("/tmp/ispconfig3_install/install");
-		exec("touch autoupdate");
-		
-		/*
-		 * do some clean-up
-		 */
-		exec("rm /tmp/ISPConfig-" . $new_version . ".tar.gz");
-
-		/*
-		 * go back to the "old path"
-		 */
-		chdir($oldDir);
-
-		/*
-		 * All well done!
-		 */
-		//$this->_actionDone($action['action_id'], 'ok');
-	}
-}
+		 * All well done!
+		 */
+		$this->_actionDone($action['action_id'], 'ok');
+	}
+
+	private function _doIspCUpdate($action) {
+		
+		// Ensure that this code is not executed twice as this would cause a loop in case of a failure
+		$this->_actionDone($action['action_id'], 'ok');
+		
+		/*
+		 * Get the version-number of the newest version 
+		 */
+		$new_version = @file_get_contents('http://www.ispconfig.org/downloads/ispconfig3_version.txt');
+		$new_version = trim($new_version);
+
+		/*
+		 * Do the update
+		 */
+
+		/* jump into the temporary dir */
+		$oldDir = getcwd();
+		chdir("/tmp");
+
+		/* delete the old files (if there are any...) */
+		exec("rm /tmp/ISPConfig-" . $new_version . ".tar.gz");
+		exec("rm /tmp/ispconfig3_install -R");
+		
+		/* get the newest version */
+		exec("wget http://www.ispconfig.org/downloads/ISPConfig-" . $new_version . ".tar.gz");
+		
+		/* extract the files */
+		exec("tar xvfz ISPConfig-" . $new_version . ".tar.gz");
+
+		/*
+		 * Initialize the automated update
+		 * (the update is then done next start of server.sh
+		 */
+		chdir("/tmp/ispconfig3_install/install");
+		exec("touch autoupdate");
+		
+		/*
+		 * do some clean-up
+		 */
+		exec("rm /tmp/ISPConfig-" . $new_version . ".tar.gz");
+
+		/*
+		 * go back to the "old path"
+		 */
+		chdir($oldDir);
+
+		/*
+		 * All well done!
+		 */
+		//$this->_actionDone($action['action_id'], 'ok');
+	}
+}
 ?>
\ No newline at end of file
-- 
GitLab