Code

Updated setup again
[gosa.git] / gosa-core / setup / class_setupStep_Migrate.inc
1 <?php
3 /*
4    This code is part of GOsa (https://gosa.gonicus.de)
5    Copyright (C) 2007 Fabian Hickert
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
25 class Step_Migrate extends setup_step
26 {
27     var $header_image   = "images/setup/migrate.png";
28     var $checks         = array();
30     /* Create Acl attributes */
31     var $acl_create_dialog  = FALSE;
32     var $acl_create_selected= ""; // Currently selected element, that should receive admin rights 
33     var $acl_create_changes = ""; // Contains ldif information about changes 
34     var $acl_create_confirmed= FALSE;
36     /* Checks initialised ? */
37     var $checks_initialised = FALSE;
39     /* Root object classes */
40     var $rootOC_migrate_dialog = FALSE;
41     var $rootOC_details = array();
43     function Step_Migrate()
44     {
45         $this->update_strings(); 
46     }
48     function update_strings()
49     {
50         $this->s_title      = _("LDAP inspection");
51         $this->s_title_long = _("LDAP inspection");
52         $this->s_info       = _("Analyze your current LDAP for GOsa compatibility");
53     }
55     function initialize_checks()
56     {
57         $this->checks = array();
58         $this->checks['root']['TITLE']     = _("Checking for root object");
59         $this->checks['root']['STATUS']    = FALSE;
60         $this->checks['root']['STATUS_MSG']= "";
61         $this->checks['root']['ERROR_MSG'] = "";
62         $this->checkBase();
64         $this->checks['rootOC']['TITLE']     = _("Inspecting object classes in root object");
65         $this->checks['rootOC']['STATUS']    = FALSE;
66         $this->checks['rootOC']['STATUS_MSG']= "";
67         $this->checks['rootOC']['ERROR_MSG'] = "";
68         $this->checkBaseOC();
70         $this->checks['permissions']['TITLE']     = _("Checking permission for LDAP database");
71         $this->checks['permissions']['STATUS']    = FALSE;
72         $this->checks['permissions']['STATUS_MSG']= "";
73         $this->checks['permissions']['ERROR_MSG'] = "";
74         $this->check_ldap_permissions();
76         $this->migrate_users = array();
77         $this->checks['acls']['TITLE']     = _("Checking for super administrator");
78         $this->checks['acls']['STATUS']    = FALSE;
79         $this->checks['acls']['STATUS_MSG']= "";
80         $this->checks['acls']['ERROR_MSG'] = "";
81         $this->check_administrativeAccount();
82     }
85     /* Check ldap accessibility 
86      * Create and remove a dummy object, 
87      *  to ensure that we have the necessary permissions
88      */
89     function check_ldap_permissions()
90     {
91         /* Establish ldap connection */
92         $cv = $this->parent->captured_values;
93         $ldap_l = new LDAP($cv['admin'],
94                 $cv['password'],
95                 $cv['connection'],
96                 FALSE,
97                 $cv['tls']);
99         $ldap = new ldapMultiplexer($ldap_l);
101         /* Create dummy entry 
102          */
103         $name     = "GOsa_setup_text_entry_".session_id().rand(0,999999);
104         $dn       = "ou=".$name.",".$cv['base'];
105         $testEntry= array();
106         $testEntry['objectClass'][]= "top";
107         $testEntry['objectClass'][]= "organizationalUnit";
108         $testEntry['objectClass'][]= "gosaDepartment";
109         $testEntry['description']= "Created by GOsa setup, this object can be removed.";
110         $testEntry['ou']  = $name;
112         /* check if simple ldap cat will be successful 
113          */
114         $res = $ldap->cat($cv['base']);  
115         if(!$res){
116             $this->checks['permissions']['STATUS']    = FALSE;
117             $this->checks['permissions']['STATUS_MSG']= _("LDAP query failed");
118             $this->checks['permissions']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
119             return(false);
120         }
122         /* Try to create dummy object 
123          */ 
124         $ldap->cd ($dn);
125         $res = $ldap->add($testEntry);
126         $ldap->cat($dn);
127         if(!$ldap->count()){
128             new log("view","setup/".get_class($this),$dn,array(),$ldap->get_error());
130             $this->checks['permissions']['STATUS']    = FALSE;
131             $this->checks['permissions']['STATUS_MSG']= _("Failed");
132             $this->checks['permissions']['ERROR_MSG'] = 
133                 sprintf(_("The specified user '%s' does not have full access to your ldap database."),$cv['admin']);
134             return(false);
135         }
137         /* Try to remove created entry 
138          */
139         $res = $ldap->rmDir($dn);
140         $ldap->cat($dn);
141         if($ldap->count()){
142             new log("view","setup/".get_class($this),$dn,array(),$ldap->get_error());
143             $this->checks['permissions']['STATUS']    = FALSE;
144             $this->checks['permissions']['STATUS_MSG']= _("Failed");
145             $this->checks['permissions']['ERROR_MSG'] = 
146                 sprintf(_("The specified user '%s' does not have full access to your ldap database."),$cv['admin']);
147             return(false);
148         }
150         /* Create & remove of dummy object was successful */
151         $this->checks['permissions']['STATUS']    = TRUE;
152         $this->checks['permissions']['STATUS_MSG']= _("Ok");
153         $this->checks['permissions']['ERROR_MSG'] = "";
154         return(true);
155     } 
160     /* Check Acls if there is at least one object with acls defined 
161      */
162     function check_administrativeAccount()
163     {
164         /* Reset settings 
165          */ 
166         $GOsa_26_found = FALSE;
167         $this->migrate_users = array();
168         $this->acl_migrate_dialog = FALSE;
169         $this->migrate_acl_base_entry  = "";
171         /* Establish ldap connection */
172         $cv = $this->parent->captured_values;
173         $ldap_l = new LDAP($cv['admin'],
174                 $cv['password'],
175                 $cv['connection'],
176                 FALSE,
177                 $cv['tls']);
179         $ldap = new ldapMultiplexer($ldap_l);
180         $ldap->cd($cv['base']);
181         $res = $ldap->cat($cv['base']);
183         if(!$res){
184             $this->checks['acls']['STATUS']    = FALSE;
185             $this->checks['acls']['STATUS_MSG']= _("LDAP query failed");
186             $this->checks['acls']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
187         }else{
188             $GOsa_26_found = false; // GOsa 2.6 Account found
189             $GOsa_25_found = false; // GOsa 2.5 Account found, allow migration
191             $username = "";
192             $attrs = $ldap->fetch();
194             /* Collect a list of available GOsa users and groups 
195              */
196             $users = array();
197             $ldap->search("(&(objectClass=gosaAccount)(objectClass=person)".
198                     "(objectClass=inetOrgPerson)(objectClass=organizationalPerson))",array("uid","dn"));
199             while($user_attrs = $ldap->fetch()){
200                 $users[$user_attrs['dn']] = $user_attrs['uid'][0];
201                 $rusers[$user_attrs['uid'][0]] = $user_attrs['dn'];
202             }
203             $groups = array();
204             $ldap->search("objectClass=posixGroup",array("cn","dn"));
205             while($group_attrs = $ldap->fetch()){
206                 $groups[$group_attrs['dn']] = $group_attrs['cn'][0];
207             }
209             /* Check if a valid GOsa 2.6 admin exists 
210                -> gosaAclEntry for an existing and accessible user.
211              */
212             $valid_users = "";
213             $valid_groups = "";
214             if(isset($attrs['gosaAclEntry'])){
215                 $acls = $attrs['gosaAclEntry'];
216                 for($i = 0 ; $i < $acls['count'] ; $i++){
217                     $acl = $acls[$i];
218                     $tmp = explode(":",$acl);
220                     if($tmp[1] == "psub"){
221                         $members = explode(",",$tmp[2]);
222                         foreach($members as $member){
223                             $member = base64_decode($member);
224                             if(isset($users[$member])){
225                                 if(preg_match("/all\/all;cmdrw/i",$tmp[3])){
226                                     $valid_users .= $users[$member].", ";
227                                     $GOsa_26_found  = TRUE;
228                                 }
229                             }
230                             if(isset($groups[$member])){
231                                 if(preg_match("/all\/all;cmdrw/i",$tmp[3])){
232                                     $ldap->cat($member);
233                                     $group_attrs = $ldap->fetch();
234                                     $val_users = "";
235                                     if(isset($group_attrs['memberUid'])){
236                                         for($e = 0 ; $e < $group_attrs['memberUid']['count']; $e ++){
237                                             if(isset($rusers[$group_attrs['memberUid'][$e]])){
238                                                 $val_users .= $group_attrs['memberUid'][$e].", ";
239                                             }
240                                         }
241                                     }
242                                     if(!empty($val_users)){
243                                         $valid_groups .= $groups[$member]."(<i>".trim($val_users,", ")."</i>), ";
244                                         $GOsa_26_found  = TRUE;
245                                     }
246                                 }
247                             }
248                         }
249                     }elseif($tmp[1] == "role"){
251                         /* Check if acl owner is a valid GOsa user account */
252                         $ldap->cat(base64_decode($tmp[2]),array("gosaAclTemplate"));
253                         $ret = $ldap->fetch();
255                         if(isset($ret['gosaAclTemplate'])){
256                             $cnt = $ret['gosaAclTemplate']['count'];
257                             for($e = 0 ; $e < $cnt ; $e++){
259                                 $a_str = $ret['gosaAclTemplate'][$e];
260                                 if(preg_match("/^[0-9]*:psub:/",$a_str) && preg_match("/:all\/all;cmdrw$/",$a_str)){
262                                     $members = explode(",",$tmp[3]);
263                                     foreach($members as $member){
264                                         $member = base64_decode($member);
266                                         if(isset($users[$member])){
267                                             $valid_users .= $users[$member].", ";
268                                             $GOsa_26_found  = TRUE;
269                                         }
270                                         if(isset($groups[$member])){
271                                             $ldap->cat($member);
272                                             $group_attrs = $ldap->fetch();
273                                             $val_users = "";
274                                             if(isset($group_attrs['memberUid'])){
275                                                 for($e = 0 ; $e < $group_attrs['memberUid']['count']; $e ++){
276                                                     if(isset($rusers[$group_attrs['memberUid'][$e]])){
277                                                         $val_users .= $group_attrs['memberUid'][$e].", ";
278                                                     }
279                                                 }
280                                             }
281                                             if(!empty($val_users)){
282                                                 $valid_groups .= $groups[$member]."(<i>".trim($val_users,", ")."</i>), ";
283                                                 $GOsa_26_found  = TRUE;
284                                             }
285                                         }
286                                     }
287                                 }
288                             }
289                         }
290                     }
291                 }
292             }
294             /* Try to find an old GOsa 2.5 administrative account that may be migrated 
295              */
296             if(!$GOsa_26_found){
297                 $valid_users = "";
298                 $valid_groups = "";
299                 $ldap->cd($cv['base']);
300                 $ldap->search("(&(objectClass=posixGroup)(gosaSubtreeACL=:all)(memberUid=*))",array("memberUid","cn"));
301                 while($p_group = $ldap->fetch()){
302                     $val_users = "";
303                     for($e = 0 ; $e < $p_group['memberUid']['count'] ; $e ++ ){
304                         $user = $p_group['memberUid'][$e];
305                         if(isset($rusers[$user])){
306                             $val_users .= $user.", ";
307                         }  
308                     }
309                     if(!empty($val_users)){
310                         $valid_groups .= $groups[$p_group['dn']]."(<i>".trim($val_users,", ")."</i>), ";
311                         $GOsa_25_found  = TRUE;
312                     }
313                 }
314             }
317             /* Print out results 
318              */
319             if($GOsa_25_found){
320                 $str = "";
321                 if(!empty($valid_groups)){
322                     $str.= "<i>".sprintf(_("GOsa 2.5 administrative accounts found: %s"),trim($valid_groups,", "))."</i><br>";
323                 }
324                 $this->checks['acls']['STATUS']    = FALSE;
325                 $this->checks['acls']['STATUS_MSG']= _("Failed");
326                 $this->checks['acls']['ERROR_MSG'] = $str;
327                 $this->checks['acls']['ERROR_MSG'].= _("There is no valid GOsa 2.6 administrator account inside your LDAP.")."&nbsp;";
328                 $this->checks['acls']['ERROR_MSG'].= "<button type='submit' name='migrate_acls'>"._("Migrate")."</button>";
329                 $this->checks['acls']['ERROR_MSG'].= "<button type='submit' name='create_acls'>"._("Create")."</button>";
330             }elseif($GOsa_26_found){
331                 $str = "";
332                 if(!empty($valid_users)){
333                     $str.= "<b>"._("Users")."</b>:&nbsp;".trim($valid_users,", ")."<br>";
334                 }
335                 if(!empty($valid_groups)){
336                     $str.= "<b>"._("Groups")."</b>:&nbsp;".trim($valid_groups,", ")."<br>";
337                 }
338                 $this->checks['acls']['STATUS']    = TRUE;
339                 $this->checks['acls']['STATUS_MSG']= _("Ok");
340                 $this->checks['acls']['ERROR_MSG'] = $str;
341             }else{
342                 $this->checks['acls']['STATUS']    = FALSE;
343                 $this->checks['acls']['STATUS_MSG']= _("Failed");
344                 $this->checks['acls']['ERROR_MSG']= _("There is no GOsa administrator account inside your LDAP.")."&nbsp;";
345                 $this->checks['acls']['ERROR_MSG'].= "<button type='submit' name='create_acls'>"._("Create")."</button>";
346             }
347         }
349         // Reload base OC
350         $this->checkBaseOC();
351         return($GOsa_26_found);
352     }
356     function create_admin($only_ldif = FALSE)
357     {
358         /* Reset '' */
359         $this->acl_create_changes="";
361         /* Object that should receive admin acls */
362         $dn = $this->acl_create_selected;
364         /* Get collected configuration settings */
365         $cv = $this->parent->captured_values;
367         /* On first call check for rid/sid base */
368         $ldap_l = new LDAP($cv['admin'],
369                 $cv['password'],
370                 $cv['connection'],
371                 FALSE,
372                 $cv['tls']);
374         $ldap = new ldapMultiplexer($ldap_l);
376         /* Get current base attributes */
377         $ldap->cd($cv['base']);
378         $ldap->cat($cv['base'],array("dn","objectClass","gosaAclEntry"));
379         $attrs = $ldap->fetch();
381         /* Add acls for the selcted user to the base */
382         $attrs_new = array();
383         $attrs_new['objectClass'] = array("gosaACL");
385         for($i = 0; $i < $attrs['objectClass']['count']; $i ++){
386             if(!in_array_ics($attrs['objectClass'][$i],$attrs_new['objectClass'])){
387                 $attrs_new['objectClass'][] = $attrs['objectClass'][$i];
388             }
389         }
391         $acl = "0:psub:".base64_encode($dn).":all/all;cmdrw";    
392         $attrs_new['gosaAclEntry'][] = $acl;
393         if(isset($attrs['gosaAclEntry'])){
394             for($i = 0 ; $i < $attrs['gosaAclEntry']['count']; $i ++){
396                 $prio = preg_replace("/[:].*$/","",$attrs['gosaAclEntry'][$i]);
397                 $rest = preg_replace("/^[^:]/","",$attrs['gosaAclEntry'][$i]);
399                 $data = ($prio+1).$rest;
400                 $attrs_new['gosaAclEntry'][] = $data;
401             }
402         }
404         if($only_ldif){
405             $this->acl_create_changes ="\n".($ldap->fix($cv['base']))."\n";
406             $this->acl_create_changes.=$this->array_to_ldif($attrs)."\n";
407             $this->acl_create_changes.="\n".($ldap->fix($cv['base']))."\n";
408             $this->acl_create_changes.=$this->array_to_ldif($attrs_new);
409         }else{
411             $ldap->cd($cv['base']);
412             if(!$ldap->modify($attrs_new)){
413                 msg_dialog::display(_("Migration error"), sprintf(_("Cannot add ACL for user '%s':")."<br><br><i>%s</i>", LDAP::fix($dn), $ldap->get_error()), ERROR_DIALOG);
414                 return(FALSE);
415             }else{
416                 return(TRUE);
417             }
418         }
419     }
422     function create_admin_user()
423     {
424         $pw1 = $pw2 = "";
425         $uid = "";
427         /* On first call check for rid/sid base */
428         $cv = $this->parent->captured_values;
429         $ldap_l = new LDAP($cv['admin'],
430                 $cv['password'],
431                 $cv['connection'],
432                 FALSE,
433                 $cv['tls']);
435         $ldap = new ldapMultiplexer($ldap_l);
437         if(isset($_POST['new_user_uid'])){
438             $uid = $_POST['new_user_uid'];
439         }
440         if(isset($_POST['new_user_password'])){
441             $pw1 = $_POST['new_user_password'];
442         }
443         if(isset($_POST['new_user_password2'])){
444             $pw2 = $_POST['new_user_password2'];
445         }
448         $ldap->cd($cv['base']);
449         $ldap->search("(uid=".$uid.")");
450         if($ldap->count()){
451             msg_dialog::display(_("Input error"),msgPool::duplicated(_("Uid")), ERROR_DIALOG);
452             return false;
453         }
455         if(empty($pw1) || empty($pw2) | ($pw1 != $pw2)){
456             msg_dialog::display(_("Password error"), _("Provided passwords do not match!"), ERROR_DIALOG);
457             return false;
458         }
460         if(!tests::is_uid($uid) || empty($uid)){
461             msg_dialog::display(_("Input error"), _("Specify a valid user ID!"), ERROR_DIALOG);
462             return false;
463         }
466         /* Get current base attributes */
467         $ldap->cd($cv['base']);
469         $people_ou = "ou=people,"; // Thats the property default.
470         $dn = "cn=System Administrator-".$uid.",".$people_ou.$cv['base'];
472         $hash = $hash = passwordMethod::make_hash($pw2, 'crypt/md5');
474         $new_user=array();
475         $new_user['objectClass']= array("top","person","gosaAccount","organizationalPerson","inetOrgPerson");
476         $new_user['givenName']  = "System";
477         $new_user['sn']  = "Administrator";
478         $new_user['cn']  = "System Administrator-".$uid;
479         $new_user['uid'] = $uid;
480         $new_user['userPassword'] = $hash;
482         $ldap->cd($cv['base']);
484         $ldap->cat($dn,array("dn"));
485         if($ldap->count()){
486             msg_dialog::display(_("Error"), sprintf(_("Adding an administrative user failed: object '%s' already exists!"), LDAP::fix($dn)), ERROR_DIALOG);
487             return(FALSE);  
488         }
490         $ldap->create_missing_trees(preg_replace("/^[^,]+,/","",$dn));
491         $ldap->cd($dn);  
492         $res = $ldap->add($new_user);
493         $this->acl_create_selected = $dn;
494         $this->create_admin();
496         if(!$res){
497             msg_dialog::display(_("LDAP error"), $ldap->get_error(), ERROR_DIALOG);
498             return(FALSE);
499         }
501         $this->acl_create_dialog=FALSE;        
502         $this->check_administrativeAccount();
503         return(TRUE);
504     }
507     function execute()
508     {
509         /* Initialise checks if this is the first call */
510         if(!$this->checks_initialised || isset($_POST['reload'])){
511             $this->initialize_checks();
512             $this->checks_initialised = TRUE;
513         }
516         /*************
517          * Root object check  
518          *************/
520         if(isset($_POST['retry_root_create'])){
522             $state = $this->checks['root']['STATUS'];
523             $this->checkBase(FALSE);
524             if($state != $this->checks['root']['STATUS']){
525                 $this->initialize_checks();
526             }
527         }
529         /*************
530          * Root object class check  
531          *************/
533         if(isset($_POST['root_add_objectclasses'])){
534             $this->rootOC_migrate_dialog = TRUE;
535             $this->dialog = TRUE;
536         }
537         if(isset($_POST['rootOC_dialog_cancel'])){
538             $this->rootOC_migrate_dialog = FALSE;
539             $this->dialog = FALSE;
540         }
541         if(isset($_POST['rootOC_migrate_start'])){
542             if($this->checkBaseOC(FALSE)){
543                 $this->checkBaseOC(); // Update overview info
544                 $this->dialog = FALSE;
545                 $this->rootOC_migrate_dialog = FALSE;
546             }
547         }
548         if($this->rootOC_migrate_dialog){
549             $smarty = get_smarty();
550             $smarty->assign("details",$this->rootOC_details);
551             $smarty->assign("method","rootOC_migrate_dialog");
552             return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
553         }
555         /*************
556          * Administrative Account -- Migrate/Create 
557          *************/
559         if(isset($_POST['retry_acls'])){
560             $this->check_administrativeAccount();
561         }
563         /* Dialog handling */
564         if(isset($_POST['create_acls'])){
565             $this->acl_create_dialog = TRUE;
566             $this->dialog = TRUE;
567         }
569         if(isset($_POST['migrate_acls'])){
570             $this->acl_migrate_dialog = TRUE;
571             $this->dialog = TRUE;
572         }
574         if(isset($_POST['create_acls_cancel']) || isset($_POST['migrate_acls_cancel'])){
575             $this->acl_create_dialog = FALSE;
576             $this->acl_migrate_dialog = FALSE;
577             $this->dialog = FALSE;
578             $this->show_details = FALSE;
579         }
581         /* Account creation */
582         if(isset($_POST['create_acls_create'])){
583             $this->create_admin(TRUE);
584         }
586         if(isset($_POST['create_admin_user'])){
587             if($this->create_admin_user()){
588                 $this->dialog = FALSE;
589                 $this->show_details = FALSE;
590             }
591         }
593         /* Add admin acls for the selected users to the ldap base.
594          */
595         if($this->acl_migrate_dialog && isset($_POST['migrate_admin_user'])){
597             /* Update ldap and reload check infos 
598              */
599             $this->migrate_selected_admin_users();
600             $this->dialog = FALSE;
601             $this->acl_migrate_dialog = FALSE;
603         }elseif($this->acl_migrate_dialog){
605             /* Display admin migration dialog.
606              */
607             $this->migrate_users();
608             $smarty = get_smarty();
610             /* Do we have to display the changes
611              */
612             $details = isset($_POST['details']) && $_POST['details'];
613             if(isset($_POST['migrate_acls_show_changes'])){
614                 $details = TRUE;
615             }elseif(isset($_POST['migrate_acls_hide_changes'])){
616                 $details = FALSE;
617             }
619             $smarty->assign("migrate_acl_base_entry", $this->migrate_acl_base_entry);
620             $smarty->assign("details", $details);
621             $smarty->assign("method","migrate_acls");
622             $smarty->assign("migrateable_users",$this->migrate_users);
623             return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
624         }
626         if($this->acl_create_dialog){
627             $smarty = get_smarty();
628             $uid = "admin";
629             if(isset($_POST['new_user_uid'])){
630                 $uid = $_POST['new_user_uid'];
631             }
632             $smarty->assign("new_user_uid",$uid);
633             $smarty->assign("new_user_password",@$_POST['new_user_password']);
634             $smarty->assign("new_user_password2",@$_POST['new_user_password2']);
635             $smarty->assign("method","create_acls");
636             $smarty->assign("acl_create_selected",$this->acl_create_selected);
637             $smarty->assign("what_will_be_done_now",$this->acl_create_changes);
638             return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
639         }
642         $smarty = get_smarty();
643         $smarty->assign("checks",$this->checks);
644         $smarty->assign("method","default");
645         return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
646     }
649     function save_object()
650     {
651         $this->is_completed= TRUE;
654         /* Get "create acl" dialog posts */
655         if($this->acl_create_dialog){
657             if(isset($_POST['create_acls_create_abort'])){
658                 $this->acl_create_selected = "";
659             }
660         }
662     }
665     /* Check if the root object exists.
666      * If the parameter just_check is true, then just check if the 
667      *  root object is missing and update the info messages.
668      * If the Parameter is false, try to create a new root object.
669      */
670     function checkBase($just_check = TRUE)
671     {
672         /* Establish ldap connection */
673         $cv = $this->parent->captured_values;
674         $ldap_l = new LDAP($cv['admin'],
675                 $cv['password'],
676                 $cv['connection'],
677                 FALSE,
678                 $cv['tls']);
680         $ldap = new ldapMultiplexer($ldap_l);
682         /* Check if root object exists */
683         $ldap->cd($cv['base']);
684         $ldap->set_size_limit(1);
685         $res = $ldap->search("(objectClass=*)");
686         $ldap->set_size_limit(0);
687         $err = ldap_errno($ldap->cid); 
689         if( !$res || 
690                 $err == 0x20 ||  # LDAP_NO_SUCH_OBJECT
691                 $err == 0x40) {  # LDAP_NAMING_VIOLATION
693             /* Root object doesn't exists 
694              */
695             if($just_check){
696                 $this->checks['root']['STATUS']    = FALSE;
697                 $this->checks['root']['STATUS_MSG']= _("Failed");
698                 $this->checks['root']['ERROR_MSG'] =  _("The LDAP root object is missing. It is required to use your LDAP service.").'&nbsp;';
699                 $this->checks['root']['ERROR_MSG'].=  "<button type='submit' name='retry_root_create'>"._("Try to create root object")."</button>";
700                 return(FALSE);
701             }else{
703                 /* Add root object */ 
704                 $ldap->cd($cv['base']);
705                 $res = $ldap->create_missing_trees($cv['base']);
707                 /* If adding failed, tell the user */
708                 if(!$res){
709                     $this->checks['root']['STATUS']    = FALSE;
710                     $this->checks['root']['STATUS_MSG']= _("Failed");
711                     $this->checks['root']['ERROR_MSG'] = _("Root object couldn't be created, you should try it on your own.");
712                     $this->checks['root']['ERROR_MSG'].= "&nbsp;<button type='submit' name='retry_root_create'>"._("Try to create root object")."</button>";
713                     return($res);;
714                 }
715             }
716         }
718         /* Create & remove of dummy object was successful */
719         $this->checks['root']['STATUS']    = TRUE;
720         $this->checks['root']['STATUS_MSG']= _("Ok");
721     }
724     /* Check if the root object includes the required object classes, e.g. gosaDepartment is required for ACLs.
725      * If the parameter just_check is true, then just check for the OCs. 
726      * If the Parameter is false, try to add the required object classes.
727      */
728     function checkBaseOC($just_check = TRUE)
729     {
730         /* Establish ldap connection */
731         $cv = $this->parent->captured_values;
732         $ldap_l = new LDAP($cv['admin'],
733                 $cv['password'],
734                 $cv['connection'],
735                 FALSE,
736                 $cv['tls']);
738         $ldap = new ldapMultiplexer($ldap_l);
740         /* Check if root object exists */
741         $ldap->cd($cv['base']);
742         $ldap->cat($cv['base']);
743         if(!$ldap->count()){
744             $this->checks['rootOC']['STATUS']    = FALSE;
745             $this->checks['rootOC']['STATUS_MSG']= _("LDAP query failed");
746             $this->checks['rootOC']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
747             return;
748         }
750         $attrs = $ldap->fetch();
752         /* Root object doesn't exists 
753          */
754         if(!in_array("gosaDepartment",$attrs['objectClass'])){
755             if($just_check){
757                 $this->rootOC_details = array();        
758                 $mods = array();
760                 /* Get list of possible container objects, to be able to detect naming 
761                  *  attributes and missing attribute types.
762                  */
763                 if(!class_available("departmentManagement")){
764                     $this->checks['rootOC']['STATUS']    = FALSE;
765                     $this->checks['rootOC']['STATUS_MSG']= _("Failed");
766                     $this->checks['rootOC']['ERROR_MSG'] = sprintf(_("Missing GOsa object class '%s'!"),"departmentManagement").
767                         "&nbsp;"._("Please check your installation.");
768                     return;
769                 }
771                 /* Try to detect base class type, e.g. is it a dcObject.
772                  */
773                 $dep_types = departmentManagement::get_support_departments();
774                 $dep_type ="";
775                 foreach($dep_types as $dep_name => $dep_class){
776                     if(in_array($dep_class['CLASS'], $attrs['objectClass'])){
777                         $dep_type = $dep_name;
778                         break;
779                     }
780                 }
782                 /* If no known base class was detect, abort with message
783                  */     
784                 if(empty($dep_type)){
785                     $this->checks['rootOC']['STATUS']    = FALSE;
786                     $this->checks['rootOC']['STATUS_MSG']= _("Failed");
787                     $this->checks['rootOC']['ERROR_MSG'] = 
788                         sprintf(_("Cannot handle the structural object type of your root object. Please try to add the object class '%s' manually."),"gosaDepartment");
789                     return;
790                 }
792                 /* Create 'current' and 'target' object properties, to be able to display 
793                  *  a set of modifications required to create a valid GOsa department.
794                  */     
795                 $str = "dn: ".$cv['base']."\n";
796                 for($i = 0 ; $i<$attrs['objectClass']['count'];$i++){
797                     $str .= "objectClass: ".$attrs['objectClass'][$i]."\n";
798                 }
799                 $this->rootOC_details['current'] = $str;
801                 /* Create target infos 
802                  */
803                 $str = "dn: ".$cv['base']."\n";
804                 for($i = 0 ; $i<$attrs['objectClass']['count'];$i++){
805                     $str .= "objectClass: ".$attrs['objectClass'][$i]."\n";
806                     $mods['objectClass'][] = $attrs['objectClass'][$i];
807                 }
808                 $mods['objectClass'][] = "gosaDepartment";
809                 $str .= "<b>objectClass: gosaDepartment</b>\n";
811                 /* Append attribute 'ou', it is required by gosaDepartment
812                  */
813                 if(!isset($attrs['ou'])){
814                     $val = "GOsa";
815                     if(isset($attrs[$dep_types[$dep_type]['ATTR']][0])){
816                         $val = $attrs[$dep_types[$dep_type]['ATTR']][0];
817                     }
818                     $str .= "<b>ou: ".$val."</b>\n";
819                     $mods['ou'] =$val;
820                 }
822                 /*Append description, it is required by gosaDepartment too.
823                  */
824                 if(!isset($attrs['description'])){
825                     $val = "GOsa";
826                     if(isset($attrs[$dep_types[$dep_type]['ATTR']][0])){
827                         $val = $attrs[$dep_types[$dep_type]['ATTR']][0];
828                     }
829                     $str .= "<b>description: ".$val."</b>\n";
830                     $mods['description'] = $val;
831                 }
832                 $this->rootOC_details['target'] = $str;
833                 $this->rootOC_details['mods'] = $mods;
835                 /*  Add button that allows to open the migration details
836                  */
837                 $this->checks['rootOC']['STATUS']    = FALSE;
838                 $this->checks['rootOC']['STATUS_MSG']= _("Failed");
839                 $this->checks['rootOC']['ERROR_MSG'] = "&nbsp;<button type='submit' 
840                     name='root_add_objectclasses'>"._("Migrate")."</button>";
842                 return(FALSE);
843             }else{
845                 /* Add root object */ 
846                 $ldap->cd($cv['base']);
847                 if(isset($this->rootOC_details['mods'])){
848                     $res  = $ldap->modify($this->rootOC_details['mods']);       
849                     if(!$res){
850                         msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $cv['base'], LDAP_MOD, get_class()));
851                     }
852                     $this->checkBaseOC();
853                     $this->check_administrativeAccount();
854                     return($res);
855                 }else{
856                     trigger_error("No modifications to make... ");
857                 }
858             }
859             return(TRUE);
860         }
862         /* Create & remove of dummy object was successful */
863         $this->checks['rootOC']['STATUS']    = TRUE;
864         $this->checks['rootOC']['STATUS_MSG']= _("Ok");
865         $this->checks['rootOC']['ERROR_MSG'] = "";
866     }
869     /* Return ldif information for a 
870      * given attribute array 
871      */
872     function array_to_ldif($atts)
873     {
874         $ret = "";
875         unset($atts['count']);
876         unset($atts['dn']);
877         foreach($atts as $name => $value){
878             if(is_numeric($name)) {
879                 continue;
880             }
881             if(is_array($value)){
882                 unset($value['count']);
883                 foreach($value as $a_val){
884                     $ret .= $name.": ". $a_val."\n";
885                 }
886             }else{
887                 $ret .= $name.": ". $value."\n";
888             }
889         }
890         return(preg_replace("/\n$/","",$ret));
891     }
895 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
896 ?>