Skip to content
class.ISPConfig.inc.php 8.74 KiB
Newer Older
<?php


if(function_exists('spl_autoload_register')) {
	spl_autoload_register('ISPConfig::autoload');
}

define('ISPC_WEBSERVER_NONE', 0);
define('ISPC_WEBSERVER_APACHE', 1);
define('ISPC_WEBSERVER_NGINX', 2);

/**
 * Main controller class
 *
 * @author croydon
 */
class ISPConfig {
	private static $is_cli_run = false;
	private static $cli_script = false;
	
	private static $autoload_files = array(
		'PXBashColor' => LIB_DIR . '/libbashcolor.inc.php'
	);
	
	public static $WEBSERVER = ISPC_WEBSERVER_APACHE;
	
	private static function init() {
		if(!isset($_GET)) {
			$_GET = array();
		}
		if(php_sapi_name() == 'cli') {
			self::$is_cli_run = true;
			
			$argc = 0;
			$argv = array();
			if(isset($_SERVER['argc'])) {
				$argc = $_SERVER['argc'];
			}
			if(isset($_SERVER['argv'])) {
				$argv = $_SERVER['argv'];
			}
			
			if(isset($argv[0])) {
				self::$cli_script = basename($argv[0]);
			}
			
			for($a = 1; $a < $argc; $a++) {
				if(substr($argv[$a], 0, 2) == '--') {
					$sArg = substr($argv[$a], 2);
					if(strpos($sArg, '=') !== false) {
						list($sKey, $sValue) = explode('=', $sArg);
					} else {
						$sKey = $sArg;
						$sValue = true;
					}
Marius Burkard's avatar
Marius Burkard committed
					$_GET[$sKey] = $sValue;
		if(!self::shallInstall('web')) {
			self::$WEBSERVER = ISPC_WEBSERVER_NONE;
		} elseif(isset($_GET['use-nginx']) && $_GET['use-nginx']) {
			self::$WEBSERVER = ISPC_WEBSERVER_NGINX;
		} else {
			self::$WEBSERVER = ISPC_WEBSERVER_APACHE;
		}
	private static function input() {
		$input = fgets(STDIN);
		return rtrim($input);
	}
	
	public static function ask($prompt) {
		print $prompt . ': ';
		return self::input();
	}
	
	/**
	 * @param string $class_name
	 * @throws ISPConfigClassException
	 */
	public static function autoload($class_name) {
		if(preg_match('/^\w+$/', $class_name) === false) {
			throw new ISPConfigClassException($class_name . ' is not a valid class name.');
		}
		
		$class_dir = LIB_DIR;
		if(preg_match('/Exception$/', $class_name)) {
			$class_dir .= '/exceptions';
		} elseif(preg_match('/Module$/', $class_name)) {
			$class_dir .= '/modules';
		} elseif(preg_match('/API$/', $class_name)) {
			$class_dir .= '/api';
		} elseif(preg_match('/OS$/', $class_name)) {
			$class_dir .= '/os';
		}
		
		$use_file = null;
		if(isset(self::$autoload_files[$class_name])) {
			$use_file = self::$autoload_files[$class_name];
		} elseif(file_exists($class_dir . '/class.' . $class_name . '.inc.php')) {
			$use_file = $class_dir . '/class.' . $class_name . '.inc.php';
		} elseif(file_exists($class_dir . '/class.' . strtolower($class_name) . '.inc.php')) {
			$use_file = $class_dir . '/class.' . strtolower($class_name) . '.inc.php';
		} elseif(preg_match('/^ISPConfig\w+Exception$/', $class_name)) {
			$use_file = LIB_DIR . '/exceptions/class.ISPConfigException.inc.php';
		} else {
			throw new ISPConfigClassException('No class file for ' . $class_name . ' found.');
		}

		if($class_name != 'ISPConfigLog') {
			ISPConfigLog::debug('Trying to autoload class file "' . $use_file . '" for class "' . $class_name . '"');
		}
		
		if(!file_exists($use_file)) {
			throw new ISPConfigClassException('File ' . $use_file . ' not found for class ' . $class_name . '.');
		}

		include_once $use_file;
		if(!class_exists($class_name)) {
			throw new ISPConfigClassException($class_name . ' not found in file ' . LIB_DIR . '/class.' . $class_name . '.inc.php.');
		}
	}
	
	/**
	 * @return boolean
	 */
	public static function isCLI() {
		return self::$is_cli_run;
	}
	
	/**
	 * @return string
	 */
	public static function getScriptName() {
		return self::$cli_script;
	}
	public static function shallInstall($what) {
		if(isset($_GET['no-'.$what]) && $_GET['no-'.$what]) {
			return false;
		} else {
			return true;
		}
	}
	
	public static function wantsInteractive() {
		if(isset($_GET['interactive']) && $_GET['interactive']) {
			return true;
		} else {
			return false;
		}
	}
	
	public static function wantsAmavis() {
		if(isset($_GET['use-amavis']) && $_GET['use-amavis']) {
			return true;
		} else {
			return false;
		}
	}
	
	public static function getISPConfigChannel() {
		if(isset($_GET['channel']) && $_GET['channel']) {
			return $_GET['channel'];
		} else {
			return 'stable';
		}
	}
	
	private static function printHelp() {
		$message = '

{FW}*
ISPConfig 3 Autoinstaller
{FW}*


Usage: ispc3-ai.sh [<argument>] [...]

This script automatically installs all needed packages for an ISPConfig 3 setup using the guidelines from the "Perfect Server Setup" howtos on www.howtoforge.com.

Possible arguments are:
	--help			->Show this help page
	--debug			->Enable verbose logging (logs each command with the exit code)
	--channel		->Choose the channel to use for ISPConfig. --channel=<stable|dev>
					->"stable" is the latest ISPConfig release available on www.ispconfig.org
					->"dev" is the latest stable-branch from the ISPConfig git repository: https://git.ispconfig.org/ispconfig/ispconfig3/tree/stable-3.1
					-> The dev channel might contain bugs and less-tested features and should only be used in production by very experienced users.
Marius Burkard's avatar
Marius Burkard committed
	--lang			->Use language for ISPConfig installation. Specify with --lang=en|de (only en (English) and de (German) supported currently).
	--interactive	->Don\'t install ISPConfig in non-interactive mode. This is needed if you want to use expert mode, e. g. to install a slave server that shall be integrated into an existing multiserver setup.
	--use-nginx		->Use nginx webserver instead of apache2
	--use-amavis	->Use amavis instead of rspamd for mail filtering
	--no-web		->Do not use ISPConfig on this server to manage webserver setting and don\'t install nginx/apache or pureftpd. This will also prevent installing an ISPConfig UI and implies --no-roundcube as well as --no-pma
	--no-mail		->Do not use ISPConfig on this server to manage mailserver settings. This will install postfix for sending system mails, but not dovecot and not configure any settings for ISPConfig mail. It implies --no-mailman.
	--no-dns		->Do not use ISPConfig on this server to manage DNS entries. Bind will be installed for local DNS caching / resolving only.
	--no-firewall	->Do not install ufw and tell ISPConfig to not manage firewall settings on this server.
	--no-roundcube	->Do not install roundcube webmail.
	--no-pma		->Do not install PHPMyAdmin on this server.
	--no-mailman	->Do not install Mailman mailing list manager.
	--i-know-what-i-am-doing
					->Prevent the autoinstaller to ask for confirmation before continuing to reconfigure the server.
';
		
		ISPConfigLog::print($message);
		exit;
	}

	/**
	 * @throws ISPConfigModuleException
	 */
	public static function run() {
		self::init();
		$valid_args = array(
			'help', 'debug', 'interactive',
			'use-nginx', 'use-amavis', 'channel', 'lang',
			'no-web', 'no-mail', 'no-dns', 'no-firewall', 'no-roundcube', 'no-pma', 'no-mailman',
			'i-know-what-i-am-doing'
		);
		
		reset($_GET);
		foreach($_GET as $key => $value) {
			if(!in_array($key, $valid_args, true)) {
				self::printHelp();
				exit;
			}
		}
		
		if(isset($_GET['help']) && $_GET['help']) {
			self::printHelp();
			exit;
		} elseif(isset($_GET['channel']) && !in_array($_GET['channel'], array('stable', 'dev'), true)) {
			self::printHelp();
			exit;
Marius Burkard's avatar
Marius Burkard committed
		} elseif(isset($_GET['lang']) && !in_array($_GET['lang'], array('de', 'en'), true)) {
			self::printHelp();
			exit;
		}
		
		if(!isset($_GET['i-know-what-i-am-doing']) || !$_GET['i-know-what-i-am-doing']) {
			print PXBashColor::getString('<lightred>WARNING!</lightred> This script will reconfigure your complete server!') . "\n";
			print 'It should be run on a freshly installed server and all current configuration that you have done will most likely be lost!' . "\n";
			$ok = ISPConfig::ask('Type \'yes\' if you really want to continue');
			if($ok !== 'yes') {
				print PXBashColor::getString('<lightred>ABORTED</lightred>') . "\n";
				exit;
			}
		}
		
Marius Burkard's avatar
Marius Burkard committed
		if(isset($_GET['debug']) && $_GET['debug']) {
			ISPConfigLog::setLogPriority(ISPConfigLog::PRIO_DEBUG);
		}
		
		// get operating system
		try {
			$os = ISPConfigBaseOS::getOSVersion();
			
			if(!self::wantsAmavis() && (!isset($_GET['channel']) || $_GET['channel'] !== 'dev')) {
				ISPConfigLog::info('<lightred>NOTE:</lightred> Installing ISPConfig stable with rspamd is not supported until 3.1.15 release (due to rspamd support). Please use --channel=dev to install stable-3.1 git development branch or --use-amavis to use amavis instead of rspamd.', true);
			ISPConfigLog::info('Starting perfect server setup for ' . $os['NAME'], true);
			$installer = ISPConfigBaseOS::getOSInstance();
Marius Burkard's avatar
Marius Burkard committed
			$installer->runPerfectSetup();
Marius Burkard's avatar
Marius Burkard committed
			ISPConfigLog::info('<lightred>Warning:</lightred> Please delete the log files in ' . LOG_DIR . '/setup-* once you don\'t need them anymore because they contain your passwords!', true);
		} catch(Exception $ex) {
			throw $ex;
		}
		
		exit;
	}
	
}