forked from extern/egroupware
new command objects to install an instance: create database, ldap structur, create/edit header (used by setup-cli too)
This commit is contained in:
parent
6a91f65335
commit
b96ebc16fc
@ -15,6 +15,13 @@
|
||||
*/
|
||||
abstract class setup_cmd extends admin_cmd
|
||||
{
|
||||
/**
|
||||
* Defaults set for empty options while running the command
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $set_defaults = array();
|
||||
|
||||
/**
|
||||
* Should be called by every command usually requiring header admin rights
|
||||
*
|
||||
@ -65,4 +72,30 @@ abstract class setup_cmd extends admin_cmd
|
||||
//echo "header_secret='$secret' = md5('$this->uid'.'$header_admin_user'.'$header_admin_password')\n";
|
||||
return $secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore our db connection
|
||||
*
|
||||
*/
|
||||
static protected function restore_db()
|
||||
{
|
||||
$GLOBALS['egw']->db->disconnect();
|
||||
$GLOBALS['egw']->db->connect();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Saving the object to the database, reimplemented to not do it in setup context
|
||||
*
|
||||
* @param boolean $set_modifier=true set the current user as modifier or 0 (= run by the system)
|
||||
* @return boolean true on success, false otherwise
|
||||
*/
|
||||
function save($set_modifier=true)
|
||||
{
|
||||
if (is_object($GLOBALS['egw']->db))
|
||||
{
|
||||
return parent::save($set_modifier);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
232
setup/inc/class.setup_cmd_database.inc.php
Normal file
232
setup/inc/class.setup_cmd_database.inc.php
Normal file
@ -0,0 +1,232 @@
|
||||
<?php
|
||||
/**
|
||||
* eGgroupWare setup - test or create the database
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @package setup
|
||||
* @copyright (c) 2007 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* setup command: test or create the database
|
||||
*/
|
||||
class setup_cmd_database extends setup_cmd
|
||||
{
|
||||
/**
|
||||
* Instance of egw_db to connect or create the db
|
||||
*
|
||||
* @var egw_db
|
||||
*/
|
||||
private $test_db;
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param string/array $domain domain-name to customize the defaults or array with all parameters
|
||||
* @param string $db_type db-type (mysql, pgsql, ...)
|
||||
* @param string $db_host=null
|
||||
* @param string $db_port=null
|
||||
* @param string $db_name=null
|
||||
* @param string $db_user=null
|
||||
* @param string $db_pass=null
|
||||
* @param string $db_root=null
|
||||
* @param string $db_root_pw=null
|
||||
* @param string $sub_command='create_db' 'create_db', 'test_db', 'test_db_root'
|
||||
*/
|
||||
function __construct($domain,$db_type=null,$db_host=null,$db_port=null,$db_name=null,$db_user=null,$db_pass=null,
|
||||
$db_root=null,$db_root_pw=null,$sub_command='create_db')
|
||||
{
|
||||
if (!is_array($domain))
|
||||
{
|
||||
$data = array(
|
||||
'domain' => $domain,
|
||||
'db_type' => $db_type,
|
||||
'db_host' => $db_host,
|
||||
'db_port' => $db_port,
|
||||
'db_name' => $db_name,
|
||||
'db_user' => $db_user,
|
||||
'db_pass' => $db_pass,
|
||||
'db_root' => $db_root,
|
||||
'db_root_pw' => $db_root_pw,
|
||||
'sub_command' => $sub_command
|
||||
);
|
||||
}
|
||||
//echo __CLASS__.'::__construct()'; _debug_array($domain);
|
||||
admin_cmd::__construct($domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* test or create database
|
||||
*
|
||||
* @param boolean $check_only=false only run the checks (and throw the exceptions), but not the command itself
|
||||
* @return string serialized $GLOBALS defined in the header.inc.php
|
||||
* @throws Exception(lang('Wrong credentials to access the header.inc.php file!'),2);
|
||||
* @throws Exception('header.inc.php not found!');
|
||||
*/
|
||||
protected function exec($check_only=false)
|
||||
{
|
||||
if (!empty($this->domain) && !preg_match('/^([a-z0-9_-]+\.)*[a-z0-9]+/i',$this->domain))
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang("'%1' is no valid domain name!",$this->domain));
|
||||
}
|
||||
if ($this->remote_id && $check_only) return true; // further checks can only done locally
|
||||
|
||||
$this->_merge_defaults();
|
||||
//_debug_array($this->as_array());
|
||||
|
||||
try {
|
||||
switch($this->sub_command)
|
||||
{
|
||||
case 'test_db_root':
|
||||
$msg = $this->connect($this->db_root,$this->db_root_pw,$this->db_meta);
|
||||
break;
|
||||
case 'test_db':
|
||||
$msg = $this->connect();
|
||||
break;
|
||||
case 'create_db':
|
||||
default:
|
||||
$msg = $this->create();
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// we catch the exception to properly restore the db
|
||||
}
|
||||
$this->restore_db();
|
||||
|
||||
if ($e)
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to database
|
||||
*
|
||||
* @param string $user=null default $this->db_user
|
||||
* @param string $pass=null default $this->db_pass
|
||||
* @param string $name=null default $this->db_name
|
||||
* @throws egw_exception_wrong_userinput Can not connect to database ...
|
||||
*/
|
||||
private function connect($user=null,$pass=null,$name=null)
|
||||
{
|
||||
if (is_null($user)) $user = $this->db_user;
|
||||
if (is_null($pass)) $pass = $this->db_name;
|
||||
if (is_null($name)) $name = $this->db_name;
|
||||
|
||||
$this->test_db = new egw_db();
|
||||
|
||||
$error_rep = error_reporting();
|
||||
error_reporting($error_rep & ~E_WARNING); // switch warnings of, in case they are on
|
||||
try {
|
||||
$this->test_db->connect($name,$this->db_host,$this->db_port,$user,$pass,$this->db_type);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// just give a nicer error, after switching error_reporting on again
|
||||
}
|
||||
error_reporting($error_rep);
|
||||
|
||||
if ($e)
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang('Can not connect to %1 database %2 on host %3 using user %4!',
|
||||
$this->db_type,$name,$this->db_host.($this->db_port?':'.$this->db_port:''),$user).' ('.$e->getMessage().')');
|
||||
}
|
||||
return lang('Successful connected to %1 database %2 on %3 using user %4.',
|
||||
$this->db_type,$name,$this->db_host.($this->db_port?':'.$this->db_port:''),$user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and if does not yet exist create the new database and user
|
||||
*
|
||||
* The check will fail if the database exists, but already contains tables
|
||||
*
|
||||
* @return string with success message
|
||||
* @throws egw_exception_wrong_userinput
|
||||
*/
|
||||
private function create()
|
||||
{
|
||||
try {
|
||||
$msg = $this->connect();
|
||||
}
|
||||
catch (egw_exception_wrong_userinput $e) {
|
||||
// db or user not working --> connect as root and create it
|
||||
if (!$this->test_db->create_database($this->db_root,$this->db_root_pw,$this->db_charset))
|
||||
{
|
||||
// try connect as root to check if that's the problem
|
||||
$this->connect($this->db_root,$this->db_root_pw,$this->db_meta);
|
||||
// if not give general error
|
||||
throw new egw_exception_wrong_userinput(lang('Can not create %1 database %2 on %3 for user %4!',
|
||||
$this->db_type,$this->db_name,$this->db_host.($this->db_port?':'.$this->db_port:''),$this->db_user));
|
||||
}
|
||||
$msg = lang('Successful connected to %1 on %3 and created database %2 for user %4.',
|
||||
$this->db_type,$this->db_name,$this->db_host.($this->db_port?':'.$this->db_port:''),$this->db_user);
|
||||
}
|
||||
// check if it already contains tables
|
||||
if (($tables = $this->test_db->table_names()))
|
||||
{
|
||||
foreach($tables as &$table)
|
||||
{
|
||||
$table = $table['table_name'];
|
||||
}
|
||||
throw new egw_exception_wrong_userinput(lang('%1 database %2 on %3 already contains the following tables:',
|
||||
$this->db_type,$this->db_name,$this->db_host.($this->db_port?':'.$this->db_port:'')).' '.
|
||||
implode(', ',$tables));
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default database settings for a given domain
|
||||
*
|
||||
* @param string $db_type='mysql'
|
||||
* @return array
|
||||
*/
|
||||
static function defaults($db_type='mysql')
|
||||
{
|
||||
switch($db_type)
|
||||
{
|
||||
case 'mysql':
|
||||
default:
|
||||
$db_type = $meta_db = 'mysql';
|
||||
break;
|
||||
case 'pgsql':
|
||||
$meta_db = 'template1';
|
||||
break;
|
||||
}
|
||||
return array(
|
||||
'db_type' => $db_type,
|
||||
'db_host' => 'localhost',
|
||||
'db_port' => 3306,
|
||||
'db_name' => 'egw_$domain',
|
||||
'db_user' => 'egw_$domain',
|
||||
'db_pass' => md5(microtime(true).$domain.session_id()),
|
||||
'db_root' => 'root',
|
||||
'db_root_pw' => '', // not really a default
|
||||
'db_meta' => $meta_db,
|
||||
'db_charset' => 'utf-8',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the default into the current properties, if they are empty or contain placeholders
|
||||
*/
|
||||
private function _merge_defaults()
|
||||
{
|
||||
foreach(self::defaults($this->domain) as $name => $default)
|
||||
{
|
||||
if (!$this->$name)
|
||||
{
|
||||
//echo "<p>setting $name='{$this->$name}' to it's default='$default'</p>\n";
|
||||
$this->set_defaults[$name] = $this->$name = $default;
|
||||
}
|
||||
if (strpos($this->$name,'$domain'))
|
||||
{
|
||||
$this->$name = str_replace(array('$domain','.','-'),array($this->domain,'_','_'),$this->$name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
338
setup/inc/class.setup_cmd_header.inc.php
Normal file
338
setup/inc/class.setup_cmd_header.inc.php
Normal file
@ -0,0 +1,338 @@
|
||||
<?php
|
||||
/**
|
||||
* eGgroupWare setup - create or update the header.inc.php
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @package setup
|
||||
* @copyright (c) 2007 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* setup command: create or update the header.inc.php
|
||||
*
|
||||
* @ToDo: incorporate setup_header here
|
||||
*/
|
||||
class setup_cmd_header extends setup_cmd
|
||||
{
|
||||
/**
|
||||
* Instance of setup's header object
|
||||
*
|
||||
* @var setup_header
|
||||
*/
|
||||
private $setup_header;
|
||||
/**
|
||||
* Full path of the header.inc.php
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $header_path;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string/array $sub_command='create' 'create','edit','delete'(-domain) or array with all arguments
|
||||
* @param array $arguments=null comand line arguments
|
||||
*/
|
||||
function __construct($sub_command='create',$arguments=null)
|
||||
{
|
||||
if (!is_array($sub_command))
|
||||
{
|
||||
$sub_command = array(
|
||||
'sub_command' => $sub_command,
|
||||
'arguments' => $arguments,
|
||||
);
|
||||
}
|
||||
//echo __CLASS__.'::__construct()'; _debug_array($domain);
|
||||
admin_cmd::__construct($sub_command);
|
||||
|
||||
// header is 2 levels lower then this command in setup/inc
|
||||
$this->header_path = realpath(dirname(__FILE__).'/../../header.inc.php');
|
||||
|
||||
$this->setup_header =& new setup_header();
|
||||
}
|
||||
|
||||
/**
|
||||
* test or create database
|
||||
*
|
||||
* @param boolean $check_only=false only run the checks (and throw the exceptions), but not the command itself
|
||||
* @return string serialized $GLOBALS defined in the header.inc.php
|
||||
* @throws Exception(lang('Wrong credentials to access the header.inc.php file!'),2);
|
||||
* @throws Exception('header.inc.php not found!');
|
||||
*/
|
||||
protected function exec($check_only=false)
|
||||
{
|
||||
if ($check_only && $this->remote_id)
|
||||
{
|
||||
return true; // can only check locally
|
||||
}
|
||||
if (!file_exists($this->header_path))
|
||||
{
|
||||
if ($this->sub_command != 'create')
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang('eGroupWare configuration file (header.inc.php) does NOT exist.')."\n".lang('Use --create-header to create the configuration file (--usage gives more options).'),1);
|
||||
}
|
||||
$this->setup_header->defaults(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->sub_command == 'create')
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(
|
||||
lang('eGroupWare configuration file header.inc.php already exists, you need to use --edit-header or delete it first!'),20);
|
||||
}
|
||||
|
||||
// check header-admin-user and -password (only if a password is set!)
|
||||
if ($GLOBALS['egw_info']['server']['header_admin_password'])
|
||||
{
|
||||
if (!is_object($GLOBALS['egw_setup']))
|
||||
{
|
||||
$GLOBALS['egw_setup'] = new setup();
|
||||
}
|
||||
if ($this->arguments)
|
||||
{
|
||||
list($this->header_admin_password,$this->header_admin_user) = explode(',',$this->arguments[1]);
|
||||
}
|
||||
if (!$GLOBALS['egw_setup']->check_auth($this->header_admin_user,$this->header_admin_password,
|
||||
$GLOBALS['egw_info']['server']['header_admin_user'],
|
||||
$GLOBALS['egw_info']['server']['header_admin_password']))
|
||||
{
|
||||
throw new egw_exception_no_permission(lang('Access denied: wrong username or password for manage-header !!!'),21);
|
||||
}
|
||||
}
|
||||
$GLOBALS['egw_info']['server']['server_root'] = EGW_SERVER_ROOT;
|
||||
$GLOBALS['egw_info']['server']['include_root'] = EGW_INCLUDE_ROOT;
|
||||
|
||||
if (!isset($GLOBALS['egw_domain']))
|
||||
{
|
||||
// we run inside eGW, not setup --> read egw_domain array from the header via the showheader cmd
|
||||
$cmd = new setup_cmd_showheader();
|
||||
$header = $cmd->run();
|
||||
$GLOBALS['egw_domain'] = $header['egw_domain'];
|
||||
unset($cmd); unset($header);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->arguments) // we have command line arguments
|
||||
{
|
||||
$this->_parse_cli_arguments();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->_parse_properties();
|
||||
}
|
||||
if (($errors = $this->setup_header->validation_errors($GLOBALS['egw_info']['server']['server_root'],
|
||||
$GLOBALS['egw_info']['server']['include_root'])))
|
||||
{
|
||||
if ($this->arguments)
|
||||
{
|
||||
unset($GLOBALS['egw_info']['flags']);
|
||||
echo '$GLOBALS[egw_info] = '; print_r($GLOBALS['egw_info']);
|
||||
echo '$GLOBALS[egw_domain] = '; print_r($GLOBALS['egw_domain']);
|
||||
}
|
||||
throw new egw_exception_wrong_userinput(lang('Configuration errors:')."\n- ".implode("\n- ",$errors)."\n".lang("You need to fix the above errors, before the configuration file header.inc.php can be written!"),23);
|
||||
}
|
||||
if ($check_only)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
$header = $this->setup_header->generate($GLOBALS['egw_info'],$GLOBALS['egw_domain']);
|
||||
|
||||
if ($this->arguments)
|
||||
{
|
||||
echo $header; // for cli, we echo the header
|
||||
}
|
||||
if (file_exists($this->header_path) && is_writable($this->header_path) || is_writable(dirname($this->header_path)))
|
||||
{
|
||||
if (is_writable(dirname($this->header_path)) && file_exists($this->header_path)) unlink($this->header_path);
|
||||
if (($f = fopen($this->header_path,'wb')) && fwrite($f,$header))
|
||||
{
|
||||
fclose($f);
|
||||
return lang('header.inc.php successful written.');
|
||||
}
|
||||
}
|
||||
throw new egw_exception_no_permission(lang("Failed writing configuration file header.inc.php, check the permissions !!!"),24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Available options and allowed arguments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
static $options = array(
|
||||
'--create-header' => array(
|
||||
'header_admin_password' => 'egw_info/server/',
|
||||
'header_admin_user' => 'egw_info/server/',
|
||||
),
|
||||
'--edit-header' => array(
|
||||
'header_admin_password' => 'egw_info/server/',
|
||||
'header_admin_user' => 'egw_info/server/',
|
||||
'new_admin_password' => 'egw_info/server/header_admin_password',
|
||||
'new_admin_user' => 'egw_info/server/header_admin_user',
|
||||
),
|
||||
'--server-root' => 'egw_info/server/server_root',
|
||||
'--include-root' => 'egw_info/server/include_root',
|
||||
'--session-type' => array(
|
||||
'sessions_type' => array(
|
||||
'type' => 'egw_info/server/',
|
||||
'allowed' => array('php'=>'php4','php4'=>'php4','php-restore'=>'php4-restore','php4-restore'=>'php4-restore','db'=>'db'),
|
||||
),
|
||||
),
|
||||
'--limit-access' => 'egw_info/server/setup_acl', // name used in setup
|
||||
'--setup-acl' => 'egw_info/server/setup_acl', // alias to match the real name
|
||||
'--mcrypt' => array(
|
||||
'mcrypt_enabled' => array(
|
||||
'type' => 'egw_info/server/',
|
||||
'allowed' => array('on' => true,'off' => false),
|
||||
),
|
||||
'mcrypt_iv' => 'egw_info/server/',
|
||||
'mcrypt' => 'egw_info/versions/mcrypt',
|
||||
),
|
||||
'--domain-selectbox' => array(
|
||||
'show_domain_selectbox' => array(
|
||||
'type' => 'egw_info/server/',
|
||||
'allowed' => array('on' => true,'off' => false),
|
||||
),
|
||||
),
|
||||
'--db-persistent' => array(
|
||||
'db_persistent' => array(
|
||||
'type' => 'egw_info/server/',
|
||||
'allowed' => array('on' => true,'off' => false),
|
||||
),
|
||||
),
|
||||
'--domain' => array(
|
||||
'domain' => '@',
|
||||
'db_name' => 'egw_domain/@/',
|
||||
'db_user' => 'egw_domain/@/',
|
||||
'db_pass' => 'egw_domain/@/',
|
||||
'db_type' => 'egw_domain/@/',
|
||||
'db_host' => 'egw_domain/@/',
|
||||
'db_port' => 'egw_domain/@/',
|
||||
'config_user' => 'egw_domain/@/',
|
||||
'config_passwd' => 'egw_domain/@/',
|
||||
),
|
||||
'--delete-domain' => true,
|
||||
);
|
||||
|
||||
/**
|
||||
* Parses properties from this object
|
||||
*/
|
||||
private function _parse_properties()
|
||||
{
|
||||
foreach(self::$options as $arg => $option)
|
||||
{
|
||||
foreach(is_array($option) ? $option : array($option => $option) as $name => $data)
|
||||
{
|
||||
if (strpos($name,'/') !== false)
|
||||
{
|
||||
$name = array_pop($parts = explode('/',$name));
|
||||
}
|
||||
if (isset($this->$name))
|
||||
{
|
||||
$this->_parse_value($arg,$name,$data,$this->$name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses command line arguments in $this->arguments
|
||||
*/
|
||||
private function _parse_cli_arguments()
|
||||
{
|
||||
$arguments = $this->arguments;
|
||||
while(($arg = array_shift($arguments)))
|
||||
{
|
||||
$values = count($arguments) && substr($arguments[0],0,2) !== '--' ? array_shift($arguments) : 'on';
|
||||
|
||||
if ($arg == '--delete-domain')
|
||||
{
|
||||
if (!isset($GLOBALS['egw_domain'][$values]))
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang("Domain '%1' does NOT exist !!!",$values),92);
|
||||
}
|
||||
unset($GLOBALS['egw_domain'][$values]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset(self::$options[$arg]))
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang("Unknown option '%1' !!!",$arg),90);
|
||||
}
|
||||
|
||||
$option = self::$options[$arg];
|
||||
$values = !is_array($option) ? array($values) : explode(',',$values);
|
||||
if (!is_array($option)) $option = array($option => $option);
|
||||
$n = 0;
|
||||
foreach($option as $name => $data)
|
||||
{
|
||||
if ($n >= count($values)) break;
|
||||
|
||||
$this->_parse_value($arg,$name,$data,$values[$n++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a single value
|
||||
*
|
||||
* @param string $arg current cli argument processed
|
||||
* @param string $name name of the property
|
||||
* @param array/string $data string with type or array containing values for type, allowed
|
||||
* @param mixed $value value to set
|
||||
*/
|
||||
private function _parse_value($arg,$name,$data,$value)
|
||||
{
|
||||
static $domain;
|
||||
|
||||
if (!is_array($data)) $data = array('type' => $data);
|
||||
$type = $data['type'];
|
||||
|
||||
if (isset($data['allowed']))
|
||||
{
|
||||
if (!isset($data['allowed'][$value]))
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang("'%1' is not allowed as %2. arguments of option %3 !!!",$value,1+$n,$arg),91);
|
||||
}
|
||||
$value = $data['allowed'][$value];
|
||||
}
|
||||
if ($type == '@')
|
||||
{
|
||||
$domain = $arg == '--domain' && !$value ? 'default' : $value;
|
||||
if ($arg == '--domain' && (!isset($GLOBALS['egw_domain'][$domain]) || $this->sub_command == 'create'))
|
||||
{
|
||||
$GLOBALS['egw_domain'][$domain] = $this->setup_header->domain_defaults($GLOBALS['egw_info']['server']['header_admin_user'],$GLOBALS['egw_info']['server']['header_admin_password']);
|
||||
}
|
||||
}
|
||||
elseif ($value !== '')
|
||||
{
|
||||
self::_set_value($GLOBALS,str_replace('@',$domain,$type),$name,$value);
|
||||
if ($type == 'egw_info/server/server_root')
|
||||
{
|
||||
self::_set_value($GLOBALS,'egw_info/server/include_root',$name,$value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value in the given array $arr with (multidimensional) key $index[/$name]
|
||||
*
|
||||
* @param array &$arr
|
||||
* @param string $index multidimensional index written with / as separator, eg. egw_info/server/
|
||||
* @param string $name additional index to use if $index end with a slash
|
||||
* @param mixed $value value to set
|
||||
*/
|
||||
static private function _set_value(&$arr,$index,$name,$value)
|
||||
{
|
||||
if (substr($index,-1) == '/') $index .= $name;
|
||||
|
||||
$var =& $arr;
|
||||
foreach(explode('/',$index) as $name)
|
||||
{
|
||||
$var =& $var[$name];
|
||||
}
|
||||
$var = strpos($name,'passw') !== false ? md5($value) : $value;
|
||||
}
|
||||
}
|
277
setup/inc/class.setup_cmd_ldap.inc.php
Normal file
277
setup/inc/class.setup_cmd_ldap.inc.php
Normal file
@ -0,0 +1,277 @@
|
||||
<?php
|
||||
/**
|
||||
* eGgroupWare setup - test or create the ldap connection and hierarchy
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @package setup
|
||||
* @copyright (c) 2007 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* setup command: test or create the ldap connection and hierarchy
|
||||
*/
|
||||
class setup_cmd_ldap extends setup_cmd
|
||||
{
|
||||
/**
|
||||
* Instance of ldap object
|
||||
*
|
||||
* @var ldap
|
||||
*/
|
||||
private $test_ldap;
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param string/array $domain domain-name to customize the defaults or array with all parameters
|
||||
* @param string $ldap_type db-type (mysql, pgsql, ...)
|
||||
* @param string $ldap_host=null
|
||||
* @param string $ldap_suffix=null base of the whole ldap install, default "dc=local"
|
||||
* @param string $ldap_admin=null root-dn needed to create new entries in the suffix
|
||||
* @param string $ldap_admin_pw=null
|
||||
* @param string $ldap_base=null base of the instance, default "o=$domain,$suffix"
|
||||
* @param string $ldap_root=null root-dn used for the instance, default "cn=admin,$base"
|
||||
* @param string $ldap_root_pw=null
|
||||
* @param string $ldap_context=null ou for accounts, default "ou=accounts,$base"
|
||||
* @param string $ldap_search_filter=null search-filter for accounts, default "(uid=%user)"
|
||||
* @param string $ldap_context_group=null ou for groups, default "ou=groups,$base"
|
||||
* @param string $sub_command='create_ldap' 'create_ldap', 'test_ldap', 'test_ldap_root'
|
||||
*/
|
||||
function __construct($domain,$ldap_host=null,$ldap_suffix=null,$ldap_admin=null,$ldap_admin_pw=null,
|
||||
$ldap_base=null,$ldap_root=null,$ldap_root_pw=null,$ldap_context=null,$ldap_search_filter=null,
|
||||
$ldap_context_group=null,$sub_command='create_ldap')
|
||||
{
|
||||
if (!is_array($domain))
|
||||
{
|
||||
$data = array(
|
||||
'domain' => $domain,
|
||||
'ldap_host' => $ldap_host,
|
||||
'ldap_suffix' => $ldap_suffix,
|
||||
'ldap_admin' => $ldap_admin,
|
||||
'ldap_admin_pw' => $ldap_admin_pw,
|
||||
'ldap_base' => $ldap_base,
|
||||
'ldap_root' => $ldap_root,
|
||||
'ldap_root_pw' => $ldap_root_pw,
|
||||
'ldap_context' => $ldap_context,
|
||||
'ldap_search_filter' => $ldap_search_filter,
|
||||
'ldap_context_group' => $ldap_context_group,
|
||||
'sub_command' => $sub_command
|
||||
);
|
||||
}
|
||||
//echo __CLASS__.'::__construct()'; _debug_array($domain);
|
||||
admin_cmd::__construct($domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* test or create database
|
||||
*
|
||||
* @param boolean $check_only=false only run the checks (and throw the exceptions), but not the command itself
|
||||
* @return string serialized $GLOBALS defined in the header.inc.php
|
||||
* @throws Exception(lang('Wrong credentials to access the header.inc.php file!'),2);
|
||||
* @throws Exception('header.inc.php not found!');
|
||||
*/
|
||||
protected function exec($check_only=false)
|
||||
{
|
||||
if (!empty($this->domain) && !preg_match('/^([a-z0-9_-]+\.)*[a-z0-9]+/i',$this->domain))
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang("'%1' is no valid domain name!",$this->domain));
|
||||
}
|
||||
if ($this->remote_id && $check_only) return true; // further checks can only done locally
|
||||
|
||||
$this->_merge_defaults();
|
||||
//_debug_array($this->as_array());
|
||||
|
||||
try {
|
||||
switch($this->sub_command)
|
||||
{
|
||||
case 'test_ldap_root':
|
||||
$msg = $this->connect($this->ldap_admin,$this->ldap_admin_pw);
|
||||
break;
|
||||
case 'test_ldap':
|
||||
$msg = $this->connect();
|
||||
break;
|
||||
case 'create_ldap':
|
||||
default:
|
||||
$msg = $this->create();
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// we catch the exception to properly restore the db
|
||||
}
|
||||
$this->restore_db();
|
||||
|
||||
if ($e)
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to ldap server
|
||||
*
|
||||
* @param string $dn=null default $this->ldap_root
|
||||
* @param string $pw=null default $this->ldap_root_pw
|
||||
* @throws egw_exception_wrong_userinput Can not connect to ldap ...
|
||||
*/
|
||||
private function connect($dn=null,$pw=null)
|
||||
{
|
||||
if (is_null($dn)) $dn = $this->ldap_root;
|
||||
if (is_null($pw)) $pw = $this->ldap_root_pw;
|
||||
|
||||
if (!$pw) // ldap::ldapConnect use the current eGW's pw otherwise
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang('You need to specify a password!'));
|
||||
}
|
||||
$this->test_ldap = new ldap();
|
||||
|
||||
$error_rep = error_reporting();
|
||||
//error_reporting($error_rep & ~E_WARNING); // switch warnings of, in case they are on
|
||||
ob_start();
|
||||
$ds = $this->test_ldap->ldapConnect($this->ldap_host,$dn,$pw);
|
||||
ob_end_clean();
|
||||
error_reporting($error_rep);
|
||||
|
||||
if (!$ds)
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang('Can not connect to LDAP server on host %1 using DN %2!',
|
||||
$this->ldap_host,$dn).($this->test_ldap->ds ? ' ('.ldap_error($this->test_ldap->ds).')' : ''));
|
||||
}
|
||||
return lang('Successful connected to LDAP server on %1 using DN %2.',$this->ldap_host,$dn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and if does not yet exist create the new database and user
|
||||
*
|
||||
* The check will fail if the database exists, but already contains tables
|
||||
*
|
||||
* @return string with success message
|
||||
* @throws egw_exception_wrong_userinput
|
||||
*/
|
||||
private function create()
|
||||
{
|
||||
$this->connect($this->ldap_admin,$this->ldap_admin_pw);
|
||||
|
||||
foreach(array(
|
||||
$this->ldap_base => array(),
|
||||
$this->ldap_context => array(),
|
||||
$this->ldap_context_group => array(),
|
||||
$this->ldap_root => array('userPassword' => '{crypt}'.crypt($this->ldap_root_pw)),
|
||||
) as $dn => $extra)
|
||||
{
|
||||
if (!$this->_create_node($dn,$extra,$check_only) && $dn == $this->ldap_root)
|
||||
{
|
||||
// ldap_root already existed, lets check the pw is correct
|
||||
$this->connect();
|
||||
}
|
||||
}
|
||||
return lang('Successful connected to LDAP server on %1 and created required structur %2.',
|
||||
$this->ldap_host,$this->ldap_base);
|
||||
}
|
||||
|
||||
/**
|
||||
* array with objectclasses for the objects we can create
|
||||
*
|
||||
* @var array of name => objectClass pairs (or array with multiple)
|
||||
*/
|
||||
static $requiredObjectclasses = array(
|
||||
'o' => 'organization',
|
||||
'ou' => 'organizationalUnit',
|
||||
'cn' => array('namedObject','simpleSecurityObject'),
|
||||
'dc' => array('organization','dcObject'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Create a new node in the ldap tree
|
||||
*
|
||||
* @param string $dn dn to create, eg. "cn=admin,dc=local"
|
||||
* @param array $extra=array() extra attributes to set
|
||||
* @return boolean true if the node was create, false if it was already there
|
||||
* @throws egw_exception_wrong_userinput
|
||||
*/
|
||||
private function _create_node($dn,$extra=array())
|
||||
{
|
||||
//echo "<p>_create_node($dn,".print_r($extra,true).")</p>\n";
|
||||
// check if the node already exists and return if it does
|
||||
if (@ldap_read($this->test_ldap->ds,$dn,'objectClass=*'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
list($node,$base) = explode(',',$dn,2);
|
||||
|
||||
if (!@ldap_read($this->test_ldap->ds,$base,'objectClass=*'))
|
||||
{
|
||||
$this->_create_node($base); // create the base if it's not already there
|
||||
}
|
||||
// now we need to create the node itself
|
||||
list($name,$value) = explode('=',$node);
|
||||
|
||||
if (!isset(self::$requiredObjectclasses[$name]))
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang('Can not create DN %1!',$dn).' '.
|
||||
lang('Supported node types:').implode(', ',array_keys(self::$requiredObjectclasses)));
|
||||
}
|
||||
if ($name == 'dc') $extra['o'] = $value; // required by organisation
|
||||
|
||||
if (!@ldap_add($this->test_ldap->ds,$dn,$attr = array(
|
||||
$name => $value,
|
||||
'objectClass' => self::$requiredObjectclasses[$name],
|
||||
)+$extra))
|
||||
{
|
||||
throw new egw_exception_wrong_userinput(lang('Can not create DN %1!',$dn).
|
||||
' ('.ldap_error($this->test_ldap->ds).', attributes='.print_r($attr,true).')');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default database settings for a given domain
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static function defaults()
|
||||
{
|
||||
return array(
|
||||
'ldap_host' => 'localhost',
|
||||
'ldap_suffix' => 'dc=local',
|
||||
'ldap_admin' => 'cn=admin,$suffix',
|
||||
'ldap_admin_pw' => '',
|
||||
'ldap_base' => 'o=$domain,$suffix',
|
||||
'ldap_root' => 'cn=admin,$base',
|
||||
'ldap_root_pw' => md5(microtime(true).$domain.session_id()),
|
||||
'ldap_context' => 'ou=accounts,$base',
|
||||
'ldap_search_filter' => '(uid=%user)',
|
||||
'ldap_context_group' => 'ou=groups,$base',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the default into the current properties, if they are empty or contain placeholders
|
||||
*/
|
||||
private function _merge_defaults()
|
||||
{
|
||||
foreach(self::defaults($this->domain) as $name => $default)
|
||||
{
|
||||
if (!$this->$name)
|
||||
{
|
||||
//echo "<p>setting $name='{$this->$name}' to it's default='$default'</p>\n";
|
||||
$this->set_defaults[$name] = $this->$name = $default;
|
||||
}
|
||||
if (strpos($this->$name,'$') !== false)
|
||||
{
|
||||
$this->$name = str_replace(array(
|
||||
'$domain',
|
||||
'$suffix',
|
||||
'$base',
|
||||
),array(
|
||||
$this->domain,
|
||||
$this->ldap_suffix,
|
||||
$this->ldap_base,
|
||||
),$this->$name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -138,8 +138,7 @@ class setup_cmd_showheader extends setup_cmd
|
||||
$config['error'] = strip_tags($e->getMessage());
|
||||
}
|
||||
// restoring the db connection, seems to be necessary when we run via remote execution
|
||||
$GLOBALS['egw']->db->disconnect();
|
||||
$GLOBALS['egw']->db->connect();
|
||||
$this->restore_db();
|
||||
|
||||
error_reporting($err_rep);
|
||||
ob_end_clean();
|
||||
|
@ -637,22 +637,9 @@ function do_check($domain='',$stop=0)
|
||||
*/
|
||||
function do_header($create,&$arguments)
|
||||
{
|
||||
require_once('inc/class.setup_header.inc.php');
|
||||
$GLOBALS['egw_setup']->header =& new setup_header();
|
||||
|
||||
if (!file_exists('../header.inc.php'))
|
||||
{
|
||||
if (!$create) fail(1,lang('eGroupWare configuration file (header.inc.php) does NOT exist.')."\n".lang('Use --create-header to create the configuration file (--usage gives more options).'));
|
||||
|
||||
$GLOBALS['egw_setup']->header->defaults(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($create) fail(20,lang('eGroupWare configuration file header.inc.php already exists, you need to use --edit-header or delete it first!'));
|
||||
|
||||
// check header-admin-user and -password (only if a password is set!)
|
||||
if ($GLOBALS['egw_info']['server']['header_admin_password'])
|
||||
if (!$create)
|
||||
{
|
||||
// read password from enviroment or query it from user, if not given
|
||||
@list($password,$user) = $options = explode(',',@$arguments[0]);
|
||||
if (!$user) $user = 'admin';
|
||||
if (!$password && !($password = $_SERVER['EGW_CLI_PASSWORD']))
|
||||
@ -664,148 +651,19 @@ function do_header($create,&$arguments)
|
||||
$options[0] = $password;
|
||||
$options[1] = $user;
|
||||
$arguments[0] = implode(',',$options);
|
||||
|
||||
if (!$GLOBALS['egw_setup']->check_auth($user,$password,$GLOBALS['egw_info']['server']['header_admin_user'],
|
||||
$GLOBALS['egw_info']['server']['header_admin_password']))
|
||||
{
|
||||
fail(21,lang('Access denied: wrong username or password for manage-header !!!'));
|
||||
}
|
||||
}
|
||||
$GLOBALS['egw_info']['server']['server_root'] = EGW_SERVER_ROOT;
|
||||
$GLOBALS['egw_info']['server']['include_root'] = EGW_INCLUDE_ROOT;
|
||||
}
|
||||
|
||||
$options = array(
|
||||
'--create-header' => array(
|
||||
'header_admin_password' => 'egw_info/server/',
|
||||
'header_admin_user' => 'egw_info/server/',
|
||||
),
|
||||
'--edit-header' => array(
|
||||
'header_admin_password' => 'egw_info/server/',
|
||||
'header_admin_user' => 'egw_info/server/',
|
||||
'new_admin_password' => 'egw_info/server/header_admin_password',
|
||||
'new_admin_user' => 'egw_info/server/header_admin_user',
|
||||
),
|
||||
'--server-root' => 'egw_info/server/server_root',
|
||||
'--include-root' => 'egw_info/server/include_root',
|
||||
'--session-type' => array(
|
||||
'sessions_type' => array(
|
||||
'type' => 'egw_info/server/',
|
||||
'allowed' => array('php'=>'php4','php4'=>'php4','php-restore'=>'php4-restore','php4-restore'=>'php4-restore','db'=>'db'),
|
||||
),
|
||||
),
|
||||
'--limit-access' => 'egw_info/server/setup_acl', // name used in setup
|
||||
'--setup-acl' => 'egw_info/server/setup_acl', // alias to match the real name
|
||||
'--mcrypt' => array(
|
||||
'mcrypt_enabled' => array(
|
||||
'type' => 'egw_info/server/',
|
||||
'allowed' => array('on' => true,'off' => false),
|
||||
),
|
||||
'mcrypt_iv' => 'egw_info/server/',
|
||||
'mcrypt' => 'egw_info/versions/mcrypt',
|
||||
),
|
||||
'--domain-selectbox' => array(
|
||||
'show_domain_selectbox' => array(
|
||||
'type' => 'egw_info/server/',
|
||||
'allowed' => array('on' => true,'off' => false),
|
||||
),
|
||||
),
|
||||
'--db-persistent' => array(
|
||||
'db_persistent' => array(
|
||||
'type' => 'egw_info/server/',
|
||||
'allowed' => array('on' => true,'off' => false),
|
||||
),
|
||||
),
|
||||
'--domain' => array(
|
||||
'domain' => '@',
|
||||
'db_name' => 'egw_domain/@/',
|
||||
'db_user' => 'egw_domain/@/',
|
||||
'db_pass' => 'egw_domain/@/',
|
||||
'db_type' => 'egw_domain/@/',
|
||||
'db_host' => 'egw_domain/@/',
|
||||
'db_port' => 'egw_domain/@/',
|
||||
'config_user' => 'egw_domain/@/',
|
||||
'config_passwd' => 'egw_domain/@/',
|
||||
),
|
||||
'--delete-domain' => true,
|
||||
);
|
||||
array_unshift($arguments,$create ? '--create-header' : '--edit-header');
|
||||
while(($arg = array_shift($arguments)))
|
||||
{
|
||||
$values = count($arguments) && substr($arguments[0],0,2) !== '--' ? array_shift($arguments) : 'on';
|
||||
|
||||
if ($arg == '--delete-domain')
|
||||
{
|
||||
if (!isset($GLOBALS['egw_domain'][$values])) fail(92,lang("Domain '%1' does NOT exist !!!",$values));
|
||||
unset($GLOBALS['egw_domain'][$values]);
|
||||
continue;
|
||||
$cmd = new setup_cmd_header($create?'create':'edit',$arguments);
|
||||
try {
|
||||
$msg = $cmd->run();
|
||||
}
|
||||
|
||||
if (!isset($options[$arg])) fail(90,lang("Unknown option '%1' !!!",$arg));
|
||||
|
||||
$option = $options[$arg];
|
||||
$values = !is_array($option) ? array($values) : explode(',',$values);
|
||||
if (!is_array($option)) $option = array($option => $option);
|
||||
$n = 0;
|
||||
foreach($option as $name => $data)
|
||||
{
|
||||
if ($n >= count($values)) break;
|
||||
|
||||
if (!is_array($data)) $data = array('type' => $data);
|
||||
$type = $data['type'];
|
||||
|
||||
$value = $values[$n];
|
||||
if (isset($data['allowed']))
|
||||
{
|
||||
if (!isset($data['allowed'][$value]))
|
||||
{
|
||||
fail(91,lang("'%1' is not allowed as %2. arguments of option %3 !!!",$value,1+$n,$arg));
|
||||
catch(Exception $e) {
|
||||
fail($e->getCode(),$e->getMessage());
|
||||
}
|
||||
$value = $data['allowed'][$value];
|
||||
}
|
||||
if ($type == '@')
|
||||
{
|
||||
$remember = $arg == '--domain' && !$value ? 'default' : $value;
|
||||
if ($arg == '--domain' && (!isset($GLOBALS['egw_domain'][$remember]) || $create))
|
||||
{
|
||||
$GLOBALS['egw_domain'][$remember] = $GLOBALS['egw_setup']->header->domain_defaults($GLOBALS['egw_info']['server']['header_admin_user'],$GLOBALS['egw_info']['server']['header_admin_password']);
|
||||
}
|
||||
}
|
||||
elseif ($value !== '')
|
||||
{
|
||||
_set_value($GLOBALS,str_replace('@',$remember,$type),$name,$value);
|
||||
if ($name == 'egw_info/server/server_root')
|
||||
{
|
||||
_set_value($GLOBALS,'egw_info/server/include_root',$name,$value);
|
||||
}
|
||||
}
|
||||
++$n;
|
||||
}
|
||||
}
|
||||
if (($errors = $GLOBALS['egw_setup']->header->validation_errors($GLOBALS['egw_info']['server']['server_root'],$GLOBALS['egw_info']['server']['include_root'])))
|
||||
{
|
||||
unset($GLOBALS['egw_info']['flags']);
|
||||
echo '$GLOBALS[egw_info] = '; print_r($GLOBALS['egw_info']);
|
||||
echo '$GLOBALS[egw_domain] = '; print_r($GLOBALS['egw_domain']);
|
||||
echo "\n".lang('Configuration errors:')."\n- ".implode("\n- ",$errors)."\n";
|
||||
fail(23,lang("You need to fix the above errors, before the configuration file header.inc.php can be written!"));
|
||||
}
|
||||
$header = $GLOBALS['egw_setup']->header->generate($GLOBALS['egw_info'],$GLOBALS['egw_domain']);
|
||||
|
||||
echo $header;
|
||||
|
||||
if (file_exists('../header.inc.php') && is_writable('../header.inc.php') || is_writable('../'))
|
||||
{
|
||||
if (is_writable('../') && file_exists('../header.inc.php')) unlink('../header.inc.php');
|
||||
if (($f = fopen('../header.inc.php','wb')) && fwrite($f,$header))
|
||||
{
|
||||
fclose($f);
|
||||
echo "\n".lang('header.inc.php successful written.')."\n\n";
|
||||
echo "\n$msg\n\n";
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
fail(24,lang("Failed writing configuration file header.inc.php, check the permissions !!!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value in the given array $arr with (multidimensional) key $index[/$name]
|
||||
|
Loading…
Reference in New Issue
Block a user