diff --git a/setup/inc/class.setup_cmd.inc.php b/setup/inc/class.setup_cmd.inc.php index a2851173ec..461ff40678 100644 --- a/setup/inc/class.setup_cmd.inc.php +++ b/setup/inc/class.setup_cmd.inc.php @@ -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; + } } diff --git a/setup/inc/class.setup_cmd_database.inc.php b/setup/inc/class.setup_cmd_database.inc.php new file mode 100644 index 0000000000..5ded88e526 --- /dev/null +++ b/setup/inc/class.setup_cmd_database.inc.php @@ -0,0 +1,232 @@ + + * @package setup + * @copyright (c) 2007 by Ralf Becker + * @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 "

setting $name='{$this->$name}' to it's default='$default'

\n"; + $this->set_defaults[$name] = $this->$name = $default; + } + if (strpos($this->$name,'$domain')) + { + $this->$name = str_replace(array('$domain','.','-'),array($this->domain,'_','_'),$this->$name); + } + } + } +} diff --git a/setup/inc/class.setup_cmd_header.inc.php b/setup/inc/class.setup_cmd_header.inc.php new file mode 100644 index 0000000000..dfe03655f9 --- /dev/null +++ b/setup/inc/class.setup_cmd_header.inc.php @@ -0,0 +1,338 @@ + + * @package setup + * @copyright (c) 2007 by Ralf Becker + * @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; + } +} diff --git a/setup/inc/class.setup_cmd_ldap.inc.php b/setup/inc/class.setup_cmd_ldap.inc.php new file mode 100644 index 0000000000..573f99b2d6 --- /dev/null +++ b/setup/inc/class.setup_cmd_ldap.inc.php @@ -0,0 +1,277 @@ + + * @package setup + * @copyright (c) 2007 by Ralf Becker + * @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 "

_create_node($dn,".print_r($extra,true).")

\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 "

setting $name='{$this->$name}' to it's default='$default'

\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); + } + } + } +} diff --git a/setup/inc/class.setup_cmd_showheader.inc.php b/setup/inc/class.setup_cmd_showheader.inc.php index 295f324e6f..47db733d0e 100644 --- a/setup/inc/class.setup_cmd_showheader.inc.php +++ b/setup/inc/class.setup_cmd_showheader.inc.php @@ -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(); diff --git a/setup/setup-cli.php b/setup/setup-cli.php index 0d48e0eff4..32014ac080 100755 --- a/setup/setup-cli.php +++ b/setup/setup-cli.php @@ -637,174 +637,32 @@ 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) { - 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']) - { - @list($password,$user) = $options = explode(',',@$arguments[0]); - if (!$user) $user = 'admin'; - if (!$password && !($password = $_SERVER['EGW_CLI_PASSWORD'])) - { - echo lang('Admin password to header manager').' '; - $password = trim(fgets($f = fopen('php://stdin','rb'))); - fclose($f); - } - $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; - } - - 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)); - } - $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)) + // 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'])) { + echo lang('Admin password to header manager').' '; + $password = trim(fgets($f = fopen('php://stdin','rb'))); fclose($f); - echo "\n".lang('header.inc.php successful written.')."\n\n"; - exit(0); } + $options[0] = $password; + $options[1] = $user; + $arguments[0] = implode(',',$options); } - fail(24,lang("Failed writing configuration file header.inc.php, check the permissions !!!")); + array_unshift($arguments,$create ? '--create-header' : '--edit-header'); + + $cmd = new setup_cmd_header($create?'create':'edit',$arguments); + try { + $msg = $cmd->run(); + } + catch(Exception $e) { + fail($e->getCode(),$e->getMessage()); + } + echo "\n$msg\n\n"; + exit(0); } /**