update.lib.php 18.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
<?php
/*
Copyright (c) 2007-2010, 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.
*/

30 31
//* Installer patch stub class
class installer_patch_update {
32 33 34 35 36 37
	protected function onBeforeSQL() {
	}

	protected function onAfterSQL() {
	}

38 39 40
}

//* DB dump function
41 42 43 44 45 46
function prepareDBDump() {
	global $conf;

	//** load the pre update sql script do perform modifications on the database before the database is dumped
	if(is_file(ISPC_INSTALL_ROOT."/install/sql/pre_update.sql")) {
		if($conf['mysql']['admin_password'] == '') {
47
			caselog("mysql --default-character-set=".escapeshellarg($conf['mysql']['charset'])." -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." ".escapeshellarg($conf['mysql']['database'])." < '".ISPC_INSTALL_ROOT."/install/sql/pre_update.sql' &> /dev/null", __FILE__, __LINE__, 'read in ispconfig3.sql', 'could not read in ispconfig3.sql');
48
		} else {
49
			caselog("mysql --default-character-set=".escapeshellarg($conf['mysql']['charset'])." -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." -p".escapeshellarg($conf['mysql']['admin_password'])." ".escapeshellarg($conf['mysql']['database'])." < '".ISPC_INSTALL_ROOT."/install/sql/pre_update.sql' &> /dev/null", __FILE__, __LINE__, 'read in ispconfig3.sql', 'could not read in ispconfig3.sql');
50 51 52 53 54 55
		}
	}

	//** export the current database data
	if( !empty($conf["mysql"]["admin_password"]) ) {

56
		system("mysqldump -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." -p".escapeshellarg($conf['mysql']['admin_password'])." -c -t --add-drop-table --create-options --quick --result-file=existing_db.sql ".$conf['mysql']['database']);
57 58 59
	}
	else {

60
		system("mysqldump -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." -c -t --add-drop-table --create-options --quick --result-file=existing_db.sql ".$conf['mysql']['database']);
61 62 63 64 65 66 67 68 69
	}

	/*
	 * If we have a server with nothing in it except VE's then the database of thie server is empty.
	 * so the following line will no longer work!
	 */
	//if(filesize('existing_db.sql') < 30000) die('Possible problem with dumping the database. We will stop here. Please check the file existing_db.sql');

	// create a backup copy of the ispconfig database in the root folder
70 71 72 73 74
	if(isset($conf['backup_path'])) {
		$backup_db_name = $conf['backup_path'].'/ispconfig_db_backup.sql';
	} else {
		$backup_db_name = '/root/ispconfig_db_backup_'.@date('Y-m-d_H-i').'.sql';
	}
75
	copy('existing_db.sql', $backup_db_name);
76 77 78 79 80 81
	chmod($backup_db_name, 0700);
	chown($backup_db_name, 'root');
	chgrp($backup_db_name, 'root');

	if ($conf['powerdns']['installed']) {
		//** export the current PowerDNS database data
82 83 84 85 86
		if( !empty($conf["mysql"]["admin_password"]) ) {
			system("mysqldump -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." -p".escapeshellarg($conf['mysql']['admin_password'])." -c -t --add-drop-table --create-options --quick --result-file=existing_powerdns_db.sql ".$conf['powerdns']['database']);
		} else {
			system("mysqldump -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." -c -t --add-drop-table --create-options --quick --result-file=existing_powerdns_db.sql ".$conf['powerdns']['database']);
		}
87 88 89

		// create a backup copy of the PowerDNS database in the root folder
		$backup_db_name = '/root/ispconfig_powerdns_db_backup_'.@date('Y-m-d_h-i').'.sql';
90
		copy('existing_powerdns_db.sql', $backup_db_name);
91
		chmod($backup_db_name, 0700);
92 93
		chown($backup_db_name, 'root');
		chgrp($backup_db_name, 'root');
94 95 96 97 98 99 100 101 102 103
	}
}

function checkDbHealth() {
	global $conf;

	//* Array containing non OK tables (can be repaired, crashed, corrupt)
	$notok = array();

	echo "Checking ISPConfig database .. ";
104
	exec("mysqlcheck -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." -p".escapeshellarg($conf['mysql']['admin_password'])." -r ".escapeshellarg($conf["mysql"]["database"]), $result);
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
	for( $i=0; $i<sizeof($result);$i++) {
		if ( substr($result[$i], -2) != "OK" ) {
			$notok[] = $result[$i];
		}
	}

	if ( sizeof($notok) > 0 ) {
		echo "\nSome tables where not 'OK'. Please check the list below.\n\n";
		foreach ($notok as $key => $value) {
			echo "$value\n";
		}
		echo "\nPress enter to continue or CTRL-C to cancel the installation ..";
		sread();
	}
	else
120
		echo "OK\n";
121 122 123 124 125 126 127 128 129 130
}

function updateDbAndIni() {
	global $inst, $conf;

	//* Update $conf array with values from the server.ini that shall be preserved
	$tmp = $inst->db->queryOneRecord("SELECT * FROM ".$conf["mysql"]["database"].".server WHERE server_id = ".$conf['server_id']);
	$ini_array = ini_to_array(stripslashes($tmp['config']));
	$current_db_version = (isset($tmp['dbversion']))?intval($tmp['dbversion']):0;

131
	if(!is_array($ini_array) or count($ini_array) == 0) die('Unable to read server configuration from database.');
132 133 134 135 136 137 138 139 140

	$conf['services']['mail'] = ($tmp['mail_server'] == 1)?true:false;
	$conf['services']['web'] = ($tmp['web_server'] == 1)?true:false;
	$conf['services']['dns'] = ($tmp['dns_server'] == 1)?true:false;
	$conf['services']['file'] = ($tmp['file_server'] == 1)?true:false;
	$conf['services']['db'] = ($tmp['db_server'] == 1)?true:false;
	$conf['services']['vserver'] = ($tmp['vserver_server'] == 1)?true:false;
	$conf['services']['proxy'] = (isset($tmp['proxy_server']) && $tmp['proxy_server'] == 1)?true:false;
	$conf['services']['firewall'] = (isset($tmp['firewall_server']) && $tmp['firewall_server'] == 1)?true:false;
141

142
	$conf['postfix']['vmail_mailbox_base'] = $ini_array['mail']['homedir_path'];
143

tbrehm's avatar
tbrehm committed
144
	if(isset($ini_array['web']['server_type']) && $ini_array['web']['server_type'] != ''){
145 146 147 148 149 150 151 152 153 154
		$conf['webserver']['server_type'] = $ini_array['web']['server_type'];
		if($conf['webserver']['server_type'] == 'nginx'){
			$conf['apache']['installed'] = false;
		} else {
			$conf['nginx']['installed'] = false;
		}
	} else {
		$conf['webserver']['server_type'] = 'apache';
		$conf['nginx']['installed'] = false;
	}
155

156
	//* Do incremental DB updates only on installed ISPConfig versions > 3.0.3
157 158
	if(compare_ispconfig_version('3.0.3', ISPC_APP_VERSION) >= 0) {

159
		swriteln($inst->lng('Starting incremental database update.'));
160 161

		//* get the version of the db schema from the server table
162 163 164
		$found = true;
		while($found == true) {
			$next_db_version = intval($current_db_version + 1);
165 166
			$sql_patch_filename = realpath(dirname(__FILE__).'/../').'/sql/incremental/upd_'.str_pad($next_db_version, 4, '0', STR_PAD_LEFT).'.sql';
			$php_patch_filename = realpath(dirname(__FILE__).'/../').'/patches/upd_'.str_pad($next_db_version, 4, '0', STR_PAD_LEFT).'.php';
167

168
			if(is_file($sql_patch_filename)) {
169

170 171 172
				//* Load php patch file and instantiate object
				if(is_file($php_patch_filename)) {
					$php_patch_class_name = 'upd_'.str_pad($next_db_version, 4, '0', STR_PAD_LEFT);
173
					include_once $php_patch_filename;
174 175 176 177 178 179
					if(class_exists($php_patch_class_name)) {
						$php_patch = new $php_patch_class_name;
					} else {
						swriteln($inst->lng('WARNING: PHP patch file').': '.$php_patch_filename.' '.$inst->lng('contains errors.'));
					}
				}
180

181 182 183 184 185
				//* Exec onBeforeSQL function
				if(isset($php_patch) && is_object($php_patch)) {
					$php_patch->onBeforeSQL();
					swriteln($inst->lng('Executing PHP patch file').': '.$php_patch_filename);
				}
186

187 188
				//* Load patch file into database
				if( !empty($conf["mysql"]["admin_password"]) ) {
189
					system("mysql --default-character-set=".escapeshellarg($conf['mysql']['charset'])." --force -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." -p".escapeshellarg($conf['mysql']['admin_password'])." ".escapeshellarg($conf['mysql']['database'])." < ".$sql_patch_filename);
190
				} else {
191 192 193
					system("mysql --default-character-set=".escapeshellarg($conf['mysql']['charset'])." --force -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." ".escapeshellarg($conf['mysql']['database'])." < ".$sql_patch_filename);
				}
				swriteln($inst->lng('Loading SQL patch file').': '.$sql_patch_filename);
194

195 196 197
				//* Exec onAfterSQL function
				if(isset($php_patch) && is_object($php_patch)) {
					$php_patch->onAfterSQL();
198
				}
199

200
				$current_db_version = $next_db_version;
201
				if(isset($php_patch)) unset($php_patch);
202 203 204 205
			} else {
				$found = false;
			}
		}
206

207 208
		//* update the database version in server table
		$inst->db->query("UPDATE ".$conf["mysql"]["database"].".server SET dbversion = '".$current_db_version."' WHERE server_id = ".$conf['server_id']);
209
		if($inst->db->dbHost != $inst->dbmaster->dbHost) $inst->dbmaster->query("UPDATE ".$conf["mysql"]["master_database"].".server SET dbversion = '".$current_db_version."' WHERE server_id = ".$conf['server_id']);
210 211 212


		//* If ISPConfig Version < 3.0.3, we will do a full db update
213
	} else {
214

215
		swriteln($inst->lng('Starting full database update.'));
216

217 218
		//** Delete the old database
		if( !$inst->db->query('DROP DATABASE IF EXISTS '.$conf['mysql']['database']) ) {
219
			$inst->error('Unable to drop MySQL database: '.$conf['mysql']['database'].'.');
220 221 222 223 224 225 226 227 228 229 230 231 232 233
		}

		//** Create the mysql database
		$inst->configure_database();

		//** empty all databases
		$db_tables = $inst->db->getTables();

		foreach($db_tables as $table) {
			$inst->db->query("TRUNCATE $table");
		}

		//** load old data back into database
		if( !empty($conf["mysql"]["admin_password"]) ) {
234
			system("mysql --default-character-set=".escapeshellarg($conf['mysql']['charset'])." --force -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." -p".escapeshellarg($conf['mysql']['admin_password'])." ".escapeshellarg($conf['mysql']['database'])." < existing_db.sql");
235
		} else {
236
			system("mysql --default-character-set=".escapeshellarg($conf['mysql']['charset'])." --force -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." ".escapeshellarg($conf['mysql']['database'])." < existing_db.sql");
237
		}
238

239 240 241 242 243 244 245 246 247 248 249
		//** Get the database version number based on the patchfile
		$found = true;
		while($found == true) {
			$next_db_version = intval($current_db_version + 1);
			$patch_filename = realpath(dirname(__FILE__).'/../').'/sql/incremental/upd_'.str_pad($next_db_version, 4, '0', STR_PAD_LEFT).'.sql';
			if(is_file($patch_filename)) {
				$current_db_version = $next_db_version;
			} else {
				$found = false;
			}
		}
250

251 252
		//* update the database version in server table
		$inst->db->query("UPDATE ".$conf["mysql"]["database"].".server SET dbversion = '".$current_db_version."' WHERE server_id = ".$conf['server_id']);
253
		if($inst->db->dbHost != $inst->dbmaster->dbHost) $inst->dbmaster->query("UPDATE ".$conf["mysql"]["master_database"].".server SET dbversion = '".$current_db_version."' WHERE server_id = ".$conf['server_id']);
254 255

		if ($conf['powerdns']['installed']) {
256

257 258
			swriteln($inst->lng('Starting full PowerDNS database update.'));

259 260
			//** Delete the old PowerDNS database
			if( !$inst->db->query('DROP DATABASE IF EXISTS '.$conf['powerdns']['database']) ) {
261
				$inst->error('Unable to drop MySQL database: '.$conf['powerdns']['database'].'.');
262
			}
263

264 265
			//** Create the mysql database
			$inst->configure_powerdns();
266

267 268 269 270 271 272
			//** load old data back into the PowerDNS database
			if( !empty($conf["mysql"]["admin_password"]) ) {
				system("mysql --default-character-set=".escapeshellarg($conf['mysql']['charset'])." --force -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." -p".escapeshellarg($conf['mysql']['admin_password'])." ".escapeshellarg($conf['powerdns']['database'])." < existing_powerdns_db.sql");
			} else {
				system("mysql --default-character-set=".escapeshellarg($conf['mysql']['charset'])." --force -h ".escapeshellarg($conf['mysql']['host'])." -u ".escapeshellarg($conf['mysql']['admin_user'])." ".escapeshellarg($conf['powerdns']['database'])." < existing_powerdns_db.sql");
			}
273 274 275 276 277
		}
	}


	//** Update server ini
278
	$tmp_server_rec = $inst->db->queryOneRecord("SELECT config FROM ".$conf["mysql"]["database"].".server WHERE server_id = ".$conf['server_id']);
279 280 281
	$old_ini_array = ini_to_array(stripslashes($tmp_server_rec['config']));
	unset($tmp_server_rec);
	$tpl_ini_array = ini_to_array(rf('tpl/server.ini.master'));
282

283 284 285 286 287
	//* Update further distribution specific parameters for server config here
	//* HINT: Every line added here has to be added in installer_base.lib.php too!!
	$tpl_ini_array['jailkit']['jailkit_chroot_app_programs'] = $conf['jailkit']['jailkit_chroot_app_programs'];
	$tpl_ini_array['fastcgi']['fastcgi_phpini_path'] = $conf['fastcgi']['fastcgi_phpini_path'];
	$tpl_ini_array['fastcgi']['fastcgi_starter_path'] = $conf['fastcgi']['fastcgi_starter_path'];
288
	$tpl_ini_array['fastcgi']['fastcgi_bin'] = $conf['fastcgi']['fastcgi_bin'];
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
	$tpl_ini_array['server']['hostname'] = $conf['hostname'];
	$tpl_ini_array['server']['ip_address'] = @gethostbyname($conf['hostname']);
	$tpl_ini_array['web']['website_basedir'] = $conf['web']['website_basedir'];
	$tpl_ini_array['web']['website_path'] = $conf['web']['website_path'];
	$tpl_ini_array['web']['website_symlinks'] = $conf['web']['website_symlinks'];
	$tpl_ini_array['cron']['crontab_dir'] = $conf['cron']['crontab_dir'];
	$tpl_ini_array['web']['security_level'] = 20;
	$tpl_ini_array['web']['user'] = $conf['apache']['user'];
	$tpl_ini_array['web']['group'] = $conf['apache']['group'];
	$tpl_ini_array['web']['php_ini_path_apache'] = $conf['apache']['php_ini_path_apache'];
	$tpl_ini_array['web']['php_ini_path_cgi'] = $conf['apache']['php_ini_path_cgi'];
	$tpl_ini_array['mail']['pop3_imap_daemon'] = ($conf['dovecot']['installed'] == true)?'dovecot':'courier';
	$tpl_ini_array['mail']['mail_filter_syntax'] = ($conf['dovecot']['installed'] == true)?'sieve':'maildrop';
	$tpl_ini_array['dns']['bind_user'] = $conf['bind']['bind_user'];
	$tpl_ini_array['dns']['bind_group'] = $conf['bind']['bind_group'];
	$tpl_ini_array['dns']['bind_zonefiles_dir'] = $conf['bind']['bind_zonefiles_dir'];
	$tpl_ini_array['dns']['named_conf_path'] = $conf['bind']['named_conf_path'];
	$tpl_ini_array['dns']['named_conf_local_path'] = $conf['bind']['named_conf_local_path'];
307

308 309 310 311 312 313 314 315 316 317
	$tpl_ini_array['web']['nginx_vhost_conf_dir'] = $conf['nginx']['vhost_conf_dir'];
	$tpl_ini_array['web']['nginx_vhost_conf_enabled_dir'] = $conf['nginx']['vhost_conf_enabled_dir'];
	$tpl_ini_array['web']['nginx_user'] = $conf['nginx']['user'];
	$tpl_ini_array['web']['nginx_group'] = $conf['nginx']['group'];
	$tpl_ini_array['web']['nginx_cgi_socket'] = $conf['nginx']['cgi_socket'];
	$tpl_ini_array['web']['php_fpm_init_script'] = $conf['nginx']['php_fpm_init_script'];
	$tpl_ini_array['web']['php_fpm_ini_path'] = $conf['nginx']['php_fpm_ini_path'];
	$tpl_ini_array['web']['php_fpm_pool_dir'] = $conf['nginx']['php_fpm_pool_dir'];
	$tpl_ini_array['web']['php_fpm_start_port'] = $conf['nginx']['php_fpm_start_port'];
	$tpl_ini_array['web']['php_fpm_socket_dir'] = $conf['nginx']['php_fpm_socket_dir'];
318

319 320 321 322
	if ($conf['nginx']['installed'] == true) {
		$tpl_ini_array['web']['server_type'] = 'nginx';
		$tpl_ini_array['global']['webserver'] = 'nginx';
	}
323

324
	//* update the new template with the old values
325 326 327 328 329 330 331 332 333
	if(is_array($old_ini_array)) {
		foreach($old_ini_array as $tmp_section_name => $tmp_section_content) {
			foreach($tmp_section_content as $tmp_var_name => $tmp_var_content) {
				$tpl_ini_array[$tmp_section_name][$tmp_var_name] = $tmp_var_content;
			}
		}
	}

	$new_ini = array_to_ini($tpl_ini_array);
334
	$sql = "UPDATE ".$conf["mysql"]["database"].".server SET config = '".mysql_real_escape_string($new_ini)."' WHERE server_id = ".$conf['server_id'];
tbrehm's avatar
tbrehm committed
335
	$inst->db->query($sql);
336

337 338 339 340
	if($inst->db->dbHost != $inst->dbmaster->dbHost) {
		$sql = "UPDATE ".$conf["mysql"]["master_database"].".server SET config = '".mysql_real_escape_string($new_ini)."' WHERE server_id = ".$conf['server_id'];
		$inst->dbmaster->query($sql);
	}
341 342 343 344 345 346
	unset($old_ini_array);
	unset($tpl_ini_array);
	unset($new_ini);


	//** Update system ini
347
	$tmp_server_rec = $inst->db->queryOneRecord("SELECT config FROM ".$conf["mysql"]["database"].".sys_ini WHERE sysini_id = 1");
348 349 350 351 352 353 354 355 356 357 358 359 360 361
	$old_ini_array = ini_to_array(stripslashes($tmp_server_rec['config']));
	unset($tmp_server_rec);
	$tpl_ini_array = ini_to_array(rf('tpl/system.ini.master'));

	// update the new template with the old values
	if(is_array($old_ini_array)) {
		foreach($old_ini_array as $tmp_section_name => $tmp_section_content) {
			foreach($tmp_section_content as $tmp_var_name => $tmp_var_content) {
				$tpl_ini_array[$tmp_section_name][$tmp_var_name] = $tmp_var_content;
			}
		}
	}

	$new_ini = array_to_ini($tpl_ini_array);
362
	$tmp = $inst->db->queryOneRecord('SELECT count(sysini_id) as number FROM '.$conf["mysql"]["database"].'.sys_ini WHERE 1');
363
	if($tmp['number'] == 0) {
364
		$inst->db->query("INSERT INTO ".$conf["mysql"]["database"].".sys_ini (sysini_id, config) VALUES (1,'".mysql_real_escape_string($new_ini)."')");
365
	} else {
366
		$inst->db->query("UPDATE ".$conf["mysql"]["database"].".sys_ini SET config = '".mysql_real_escape_string($new_ini)."' WHERE sysini_id = 1");
367 368 369 370 371 372
	}
	unset($old_ini_array);
	unset($tpl_ini_array);
	unset($new_ini);
}

373 374


375
?>