Code

e238692681b07d10b98eacf6ad93cc7efb34c57c
[gosa.git] / 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  */
24 /****************
25  * FUNCTIONS 
27 Step_Migrate                - Constructor.
28 update_strings              - Used to update the displayed step informations.
29 initialize_checks           - Initialize migration steps.
30 check_ldap_permissions      - Check if the used admin account has full access to the ldap database.
31 check_gosaAccounts          - Check if there are users without the required objectClasses.
32 migrate_gosaAccounts        - Migrate selected users to GOsa user accounts.
33 check_organizationalUnits   - Check if there are departments, that are not visible for GOsa
34 migrate_organizationalUnits - Migrate selected departments 
35 check_administrativeAccount - Check if there is at least one acl entry available                  
36 checkBase                   - Check if there is a root object available 
38 get_user_list               - Get list of available users
39 get_group_list              - Get list of groups
40   
41 create_admin                
42 create_admin_user           
44 execute                     - Generate html output of this plugin
45 save_object                 - Save posts 
46 array_to_ldif               - Create ldif output of an ldap result array 
47  
48  ****************/
52 class Step_Migrate extends setup_step
53 {
54   var $languages      = array();
55   var $attributes     = array();
56   var $header_image   = "images/monitoring.png";
57   var $checks         = array();
59   /* Department migration attributes */
60   var $dep_migration_dialog = FALSE;
61   var $deps_to_migrate      = array();
63   /* Department migration attributes */
64   var $users_migration_dialog= FALSE;
65   var $users_to_migrate      = array();
67   /* Create Acl attributes */
68   var $acl_create_dialog  = FALSE;
69   var $acl_create_type    = "group";
70   var $acl_create_selected= ""; // Currently selected element, that should receive admin rights 
71   var $acl_create_changes = ""; // Contains ldif information about changes 
72   var $acl_create_confirmed= FALSE;
74   /* Checks initialised ? */
75   var $checks_initialised = FALSE;
77   /* Users outside to people ou */
78   var $outside_users        = array();
79   var $outside_users_dialog = FALSE;
81   /* Users outside to groups ou */
82   var $outside_groups        = array();
83   var $outside_groups_dialog = FALSE;
85   /* Win-Workstations outside to reserved ou */
86   var $outside_winstations        = array();
87   var $outside_winstations_dialog = FALSE;
89   /* check for multiple use of same uidNumber */
90   var $check_uidNumbers        = array();
91   var $check_uidNumbers_dialog = FALSE;
93   /* check for multiple use of same gidNumber */
94   var $check_gidNumbers        = array();
95   var $check_gidNumbers_dialog = FALSE;
98   function Step_Migrate()
99   {
100     $this->update_strings(); 
101   }
103   function update_strings()
104   {
105     $this->s_title      = _("LDAP inspection");
106     $this->s_title_long = _("LDAP inspection");
107     $this->s_info       = _("Analyze your current LDAP for GOsa compatibility");
108   }
110   function initialize_checks()
111   {
112     $this->checks = array();
113     $this->checks['root']['TITLE']     = _("Checking for root object");
114     $this->checks['root']['STATUS']    = FALSE;
115     $this->checks['root']['STATUS_MSG']= "";
116     $this->checks['root']['ERROR_MSG'] = "";
117     $this->checkBase();
119     $this->checks['permissions']['TITLE']     = _("Checking permissions on ldap database");
120     $this->checks['permissions']['STATUS']    = FALSE;
121     $this->checks['permissions']['STATUS_MSG']= "";
122     $this->checks['permissions']['ERROR_MSG'] = "";
123     $this->check_ldap_permissions();
125     $this->checks['deps_visible']['TITLE']     = _("Checking for invisible deparmtments");
126     $this->checks['deps_visible']['STATUS']    = FALSE;
127     $this->checks['deps_visible']['STATUS_MSG']= "";
128     $this->checks['deps_visible']['ERROR_MSG'] = "";
129     $this->check_organizationalUnits();
131     $this->checks['users_visible']['TITLE']     = _("Checking for invisible user");
132     $this->checks['users_visible']['STATUS']    = FALSE;
133     $this->checks['users_visible']['STATUS_MSG']= "";
134     $this->checks['users_visible']['ERROR_MSG'] = "";
135     $this->check_gosaAccounts();
137     $this->checks['acls']['TITLE']     = _("Checking for administrational account");
138     $this->checks['acls']['STATUS']    = FALSE;
139     $this->checks['acls']['STATUS_MSG']= "";
140     $this->checks['acls']['ERROR_MSG'] = "";
141     $this->check_administrativeAccount();
143     $this->checks['outside_users']['TITLE']     = _("Checking for users outside the people department.");
144     $this->checks['outside_users']['STATUS']    = FALSE;
145     $this->checks['outside_users']['STATUS_MSG']= "";
146     $this->checks['outside_users']['ERROR_MSG'] = "";
147     $this->search_outside_users();
148     
149     $this->checks['outside_groups']['TITLE']     = _("Checking for groups outside the groups department.");
150     $this->checks['outside_groups']['STATUS']    = FALSE;
151     $this->checks['outside_groups']['STATUS_MSG']= "";
152     $this->checks['outside_groups']['ERROR_MSG'] = "";
153     $this->search_outside_groups();
155     $this->checks['outside_winstations']['TITLE']     = _("Checking for windows workstations outside the winstation department.");
156     $this->checks['outside_winstations']['STATUS']    = FALSE;
157     $this->checks['outside_winstations']['STATUS_MSG']= "";
158     $this->checks['outside_winstations']['ERROR_MSG'] = "";
159     $this->search_outside_winstations();
161     $this->checks['uidNumber_usage']['TITLE']     = _("Checking for multiple use of same uidNumber value.");
162     $this->checks['uidNumber_usage']['STATUS']    = FALSE;
163     $this->checks['uidNumber_usage']['STATUS_MSG']= "";
164     $this->checks['uidNumber_usage']['ERROR_MSG'] = "";
165     $this->check_uidNumber();
166     
167     $this->checks['gidNumber_usage']['TITLE']     = _("Checking for multiple use of same gidNumber value.");
168     $this->checks['gidNumber_usage']['STATUS']    = FALSE;
169     $this->checks['gidNumber_usage']['STATUS_MSG']= "";
170     $this->checks['gidNumber_usage']['ERROR_MSG'] = "";
171     $this->check_gidNumber();
172   }
175   function check_uidNumber()
176   {
177     $cv = $this->parent->captured_values;
178     $ldap = new LDAP($cv['admin'],
179         $cv['password'],
180         $cv['connection'],
181         FALSE,
182         $cv['tls']);
184     $ldap->cd($cv['base']);
185     $res = $ldap->search("uidNumber=*",array("dn","uidNumber"));
186     if(!$res){
187       $this->checks['uidNumber_usage']['STATUS']    = FALSE;
188       $this->checks['uidNumber_usage']['STATUS_MSG']= _("Ldap query failed.");
189       $this->checks['uidNumber_usage']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
190       return(false);
191     }
193     $this->check_uidNumbers= array(); 
194     $tmp = array();
195     while($attrs = $ldap->fetch()){
196       $tmp[$attrs['uidNumber'][0]][] = $attrs;
197     }
199     foreach($tmp as $id => $entries){
200       if(count($entries) > 1){
201         foreach($entries as $entry){
202           $this->check_uidNumbers[base64_encode($entry['dn'])] = $entry;
203         }
204       }
205     }
207     if($this->check_uidNumbers){
208       $this->checks['uidNumber_usage']['STATUS']    = FALSE;
209       $this->checks['uidNumber_usage']['STATUS_MSG']= _("Failed");
210       $this->checks['uidNumber_usage']['ERROR_MSG'] =
211         sprintf(_("Found %s duplicated uidNumber values."),count($this->check_uidNumbers));
212       return(false);
213     }else{
214       $this->checks['uidNumber_usage']['STATUS']    = TRUE;
215       $this->checks['uidNumber_usage']['STATUS_MSG']= _("Ok");
216       $this->checks['uidNumber_usage']['ERROR_MSG'] = "";
217       return(TRUE);
218     }
219   }
221   function check_gidNumber()
222   {
223     $cv = $this->parent->captured_values;
224     $ldap = new LDAP($cv['admin'],
225         $cv['password'],
226         $cv['connection'],
227         FALSE,
228         $cv['tls']);
230     $ldap->cd($cv['base']);
231     $res = $ldap->search("gidNumber=*",array("dn","gidNumber"));
232     if(!$res){
233       $this->checks['gidNumber_usage']['STATUS']    = FALSE;
234       $this->checks['gidNumber_usage']['STATUS_MSG']= _("Ldap query failed.");
235       $this->checks['gidNumber_usage']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
236       return(false);
237     }
239     $this->check_gidNumbers= array(); 
240     $tmp = array();
241     while($attrs = $ldap->fetch()){
242       $tmp[$attrs['gidNumber'][0]][] = $attrs;
243     }
245     foreach($tmp as $id => $entries){
246       if(count($entries) > 1){
247         foreach($entries as $entry){
248           $this->check_gidNumbers[base64_encode($entry['dn'])] = $entry;
249         }
250       }
251     }
253     if($this->check_gidNumbers){
254       $this->checks['gidNumber_usage']['STATUS']    = FALSE;
255       $this->checks['gidNumber_usage']['STATUS_MSG']= _("Failed");
256       $this->checks['gidNumber_usage']['ERROR_MSG'] =
257         sprintf(_("Found %s duplicated gidNumber values."),count($this->check_gidNumbers));
258       return(false);
259     }else{
260       $this->checks['gidNumber_usage']['STATUS']    = TRUE;
261       $this->checks['gidNumber_usage']['STATUS_MSG']= _("Ok");
262       $this->checks['gidNumber_usage']['ERROR_MSG'] = "";
263       return(TRUE);
264     }
265   }
268   /* Search for winstations outside the winstation ou */
269   function search_outside_winstations()
270   {
271     $cv = $this->parent->captured_values;
272     $ldap = new LDAP($cv['admin'],
273         $cv['password'],
274         $cv['connection'],
275         FALSE,
276         $cv['tls']);
278     /* Get winstation ou */
279     if($cv['generic_settings']['wws_ou_active']) {
280       $winstation_ou = $cv['generic_settings']['ws_ou'];
281     }else{
282       $winstation_ou = "ou=winstations";
283     }
284  
285     $ldap->cd($cv['base']);
286     $res = $ldap->search("(&(objectClass=posixGroup)(sambaGroupType=2)(sambaSID=*))",array("dn","sambaSID"));
287     if(!$res){
288       $this->checks['outside_winstations']['STATUS']    = FALSE;
289       $this->checks['outside_winstations']['STATUS_MSG']= _("Ldap query failed.");
290       $this->checks['outside_winstations']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
291       return(false);
292     }
294     $this->outside_winstations = array();
295     while($attrs = $ldap->fetch()){
296       if(preg_match("/-516$/","",$attrs['sambaSID'][0]) && !preg_match("/^[^,]+,".normalizePreg($winstation_ou)."/",$attrs['dn'])){
297         $this->outside_winstations[base64_encode($attrs['dn'])] = $attrs;
298       }
299     }
301     if(count($this->outside_winstations)){
302       $this->checks['outside_winstations']['STATUS']    = FALSE;
303       $this->checks['outside_winstations']['STATUS_MSG']= _("Failed");
304       $this->checks['outside_winstations']['ERROR_MSG'] = 
305         sprintf(_("Found %s winstations outside the predefined winstation department ou '%s'."),count($this->outside_winstations),$winstation_ou);
306       return(false);
307     }else{
308       $this->checks['outside_winstations']['STATUS']    = TRUE;
309       $this->checks['outside_winstations']['STATUS_MSG']= _("Ok");
310       $this->checks['outside_winstations']['ERROR_MSG'] = "";
311       return(TRUE);
312     }
313   }
316   /* Search for groups outside the group ou */
317   function search_outside_groups()
318   {
319     $cv = $this->parent->captured_values;
320     $ldap = new LDAP($cv['admin'],
321         $cv['password'],
322         $cv['connection'],
323         FALSE,
324         $cv['tls']);
326     $group_ou = $cv['groupou'];
327     $ldap->cd($cv['base']);
328     $res = $ldap->search("(objectClass=posixGroup)",array("dn"));
329     if(!$res){
330       $this->checks['outside_groups']['STATUS']    = FALSE;
331       $this->checks['outside_groups']['STATUS_MSG']= _("Ldap query failed.");
332       $this->checks['outside_groups']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
333       return(false);
334     }
337     $this->outside_groups = array();
338     while($attrs = $ldap->fetch()){
339       if(!preg_match("/^[^,]+,".normalizePreg($group_ou)."/",$attrs['dn'])){
340         $this->outside_groups[base64_encode($attrs['dn'])] = $attrs;
341       }
342     }
344     if(count($this->outside_groups)){
345       $this->checks['outside_groups']['STATUS']    = FALSE;
346       $this->checks['outside_groups']['STATUS_MSG']= _("Failed");
347       $this->checks['outside_groups']['ERROR_MSG'] = 
348         sprintf(_("Found %s groups outside the selected group ou '%s'."),count($this->outside_groups),$group_ou);
349       return(false);
350     }else{
351       $this->checks['outside_groups']['STATUS']    = TRUE;
352       $this->checks['outside_groups']['STATUS_MSG']= _("Ok");
353       $this->checks['outside_groups']['ERROR_MSG'] = "";
354       return(TRUE);
355     }
356   }
358   /* Search for users outside the people ou */
359   function search_outside_users()
360   {
361     $cv = $this->parent->captured_values;
362     $ldap = new LDAP($cv['admin'],
363         $cv['password'],
364         $cv['connection'],
365         FALSE,
366         $cv['tls']);
367     $people_ou = $cv['peopleou'];
368     $ldap->cd($cv['base']);
369     $res = $ldap->search("(objectClass=gosaAccount)",array("dn"));
370     if(!$res){
371       $this->checks['outside_users']['STATUS']    = FALSE;
372       $this->checks['outside_users']['STATUS_MSG']= _("Ldap query failed.");
373       $this->checks['outside_users']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
374       return(false);
375     }
378     $this->outside_users = array();
379     while($attrs = $ldap->fetch()){
380       if(!preg_match("/^[^,]+,".normalizePreg($people_ou)."/",$attrs['dn'])){
381         $attrs['selected'] = FALSE;
382         $attrs['ldif']     = "";
383         $this->outside_users[base64_encode($attrs['dn'])] = $attrs;
384       }
385     }
387     if(count($this->outside_users)){
388       $this->checks['outside_users']['STATUS']    = FALSE;
389       $this->checks['outside_users']['STATUS_MSG']= _("Failed");
390       $this->checks['outside_users']['ERROR_MSG'] = 
391         sprintf(_("Found %s users outside the selected user ou '%s'."),count($this->outside_users),$people_ou);
392       $this->checks['outside_users']['ERROR_MSG'].= "<input type='submit' name='outside_users_dialog' value='"._("Migrate")."'>";
393       return(false);
394     }else{
395       $this->checks['outside_users']['STATUS']    = TRUE;
396       $this->checks['outside_users']['STATUS_MSG']= _("Ok");
397       $this->checks['outside_users']['ERROR_MSG'] = "";
398       return(TRUE);
399     }
400   }
403   /* Check ldap accessibility 
404    * Create and remove a dummy object, 
405    *  to ensure that we have the necessary permissions
406    */
407   function check_ldap_permissions()
408   {
409     $cv = $this->parent->captured_values;
410     $ldap = new LDAP($cv['admin'],
411         $cv['password'],
412         $cv['connection'],
413         FALSE,
414         $cv['tls']);
416     /* Create dummy entry 
417      */
418     $name     = "GOsa_setup_text_entry_".session_id().rand(0,999999);
419     $dn       = "ou=".$name.",".$cv['base'];
420     $testEntry= array();
421     $testEntry['objectClass'][]= "top";
422     $testEntry['objectClass'][]= "organizationalUnit";
423     $testEntry['objectClass'][]= "gosaDepartment";
424     $testEntry['description']= "Created by GOsa setup, this object can be removed.";
425     $testEntry['ou']  = $name;
427     /* check if simple ldap cat will be successful 
428      */
429     $res = $ldap->cat($cv['base']);  
430     if(!$res){
431       $this->checks['permissions']['STATUS']    = FALSE;
432       $this->checks['permissions']['STATUS_MSG']= _("Ldap query failed.");
433       $this->checks['permissions']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
434       return(false);
435     }
436   
437     /* Try to create dummy object 
438      */ 
439     $ldap->cd ($dn);
440     $ldap->create_missing_trees($dn);
441     $res = $ldap->add($testEntry);
442     if(!$res){
443       gosa_log($ldap->get_error());
444       $this->checks['permissions']['STATUS']    = FALSE;
445       $this->checks['permissions']['STATUS_MSG']= _("Failed");
446       $this->checks['permissions']['ERROR_MSG'] = 
447         sprintf(_("The specified user '%s' does not have full access to your ldap database."),$cv['admin']);
448       return(false);
449     }
451     /* Try to remove created entry 
452      */
453     $res = $ldap->rmDir($dn);
454     if(!$res){
455       gosa_log($ldap->get_error());
456       $this->checks['permissions']['STATUS']    = FALSE;
457       $this->checks['permissions']['STATUS_MSG']= _("Failed");
458       $this->checks['permissions']['ERROR_MSG'] = 
459         sprintf(_("The specified user '%s' does not have full access to your ldap database."),$cv['admin']);
460       return(false);
461     }
463     /* Create & remove of dummy object was successful */
464     $this->checks['permissions']['STATUS']    = TRUE;
465     $this->checks['permissions']['STATUS_MSG']= _("Ok");
466     $this->checks['permissions']['ERROR_MSG'] = "";
467     return(true);
468   } 
471   /* Check if there are users which will 
472    *  be invisible for GOsa 
473    */
474   function check_gosaAccounts()
475   {
476     /* Remember old list of ivisible users, to be able to set 
477      *  the 'html checked' status for the checkboxes again 
478      */
479     $cnt_ok = 0;
480     $old    = $this->users_to_migrate;
481     $this->users_to_migrate = array();
483     /* Get collected configuration settings */
484     $cv = $this->parent->captured_values;
486     /* Establish ldap connection */
487     $ldap = new LDAP($cv['admin'],
488         $cv['password'],
489         $cv['connection'],
490         FALSE,
491         $cv['tls']);
493     /* Get all invisible users 
494      */
495     $ldap->cd($cv['base']); 
496     $res =$ldap->search("(&(|(objectClass=posixAccount)(objectClass=inetOrgPerson)(objectClass=organizationalPerson))(!(objectClass=gosaAccount)))",array("sn","givenName","cn","uid"));
497     while($attrs = $ldap->fetch()){
498       if(!preg_match("/,dc=addressbook,/",$attrs['dn'])){
499         $attrs['checked'] = FALSE;
500         $attrs['before']  = "";
501         $attrs['after']   = "";
503         /* Set objects to selected, that were selected before reload */
504         if(isset($old[base64_encode($attrs['dn'])])){
505           $attrs['checked'] = $old[base64_encode($attrs['dn'])]['checked'];
506         }
507         $this->users_to_migrate[base64_encode($attrs['dn'])] = $attrs;
508       }
509     }
511     /* No invisible */
512     if(!$res){
513       $this->checks['users_visible']['STATUS']    = FALSE;
514       $this->checks['users_visible']['STATUS_MSG']= _("Ldap query failed.");
515       $this->checks['users_visible']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
516     }elseif(count($this->users_to_migrate) == 0){
517       $this->checks['users_visible']['STATUS']    = TRUE;
518       $this->checks['users_visible']['STATUS_MSG']= _("Ok");
519       $this->checks['users_visible']['ERROR_MSG'] = "";
520     }else{
521       $this->checks['users_visible']['STATUS']    = FALSE;
522       $this->checks['users_visible']['STATUS_MSG']= "";
523       $this->checks['users_visible']['ERROR_MSG'] = sprintf(_("Found %s users that will not be visible in GOsa."), 
524           count($this->users_to_migrate));
525       $this->checks['users_visible']['ERROR_MSG'] .= "<input type='submit' name='users_visible_migrate' value='"._("Migrate")."'>";
526     }
527   }
530   /* Start user account migration 
531    */  
532   function migrate_gosaAccounts($only_ldif = FALSE)
533   {
534     /* Get collected configuration settings */
535     $cv = $this->parent->captured_values;
537     /* Establish ldap connection */
538     $ldap = new LDAP($cv['admin'],
539         $cv['password'],
540         $cv['connection'],
541         FALSE,
542         $cv['tls']);
544     /* Add gosaAccount objectClass to the selected users  
545      */
546     foreach($this->users_to_migrate as $key => $dep){
547       if($dep['checked']){
549         /* Get old objectClasses */
550         $ldap->cat($dep['dn'],array("objectClass"));
551         $attrs      = $ldap->fetch();
553         /* Create new objectClass array */
554         $new_attrs  = array();
555         $new_attrs['objectClass']= array("gosaAccount","inetOrgPerson","organizationalPerson");
556         for($i = 0 ; $i < $attrs['objectClass']['count']; $i ++ ){
557           if(!in_array_ics($attrs['objectClass'][$i], $new_attrs['objectClass'])){
558             $new_attrs['objectClass'][]   = $attrs['objectClass'][$i];
559           }
560         }
562         /* Set info attributes for current object, 
563          *  or write changes to the ldap database 
564          */
565         if($only_ldif){
566           $this->users_to_migrate[$key]['before'] = $this->array_to_ldif($attrs);
567           $this->users_to_migrate[$key]['after']  = $this->array_to_ldif($new_attrs);
568         }else{
569           $ldap->cd($attrs['dn']);
570           if(!$ldap->modify($new_attrs)){
571             print_red(sprintf(_("Failed to migrate the department '%s' into GOsa, error message is as follows '%s'."),$attrs['dn'],$ldap->get_error()));
572             return(false);
573           }
574         }
575       }
576     }
577     return(TRUE);
578   }
581   /* Check if there are invisible organizational Units 
582    */
583   function check_organizationalUnits()
584   {
585     $cnt_ok = 0;
586     $old = $this->deps_to_migrate;
587     $this->deps_to_migrate = array();
589     /* Get collected configuration settings */
590     $cv = $this->parent->captured_values;
592     /* Establish ldap connection */
593     $ldap = new LDAP($cv['admin'],
594         $cv['password'],
595         $cv['connection'],
596         FALSE,
597         $cv['tls']);
599     /* Skip GOsa internal departments */
600     $skip_dns = array("/^ou=people,/","/^ou=groups,/","/(,|)ou=configs,/","/(,|)ou=systems,/",
601         "/^ou=apps,/","/^ou=mime,/","/^ou=aclroles,/","/^ou=incoming,/",
602         "/ou=snapshots,/","/(,|)dc=addressbook,/","/^(,|)ou=machineaccounts,/",
603         "/(,|)ou=winstations,/");
606     /* Get all invisible departments */
607     $ldap->cd($cv['base']); 
608     $res = $ldap->search("(&(objectClass=organizationalUnit)(!(objectClass=gosaDepartment)))",array("ou","description","dn"));
609     while($attrs = $ldap->fetch()){
610       $attrs['checked'] = FALSE;
611       $attrs['before']  = "";
612       $attrs['after']   = "";
614       /* Set objects to selected, that were selected before reload */
615       if(isset($old[base64_encode($attrs['dn'])])){
616         $attrs['checked'] = $old[base64_encode($attrs['dn'])]['checked'];
617       }
618       $this->deps_to_migrate[base64_encode($attrs['dn'])] = $attrs;
619     }
621     /* Filter returned list of departments and ensure that 
622      *  GOsa internal departments will not be listed 
623      */
624     foreach($this->deps_to_migrate as $key => $attrs){
625       $dn = $attrs['dn'];
626       $skip = false;
627       foreach($skip_dns as $skip_dn){
628         if(preg_match($skip_dn,$dn)){
629           $skip = true;
630         }
631       }
632       if($skip){
633         unset($this->deps_to_migrate[$key]);
634       }
635     }
637     /* If we have no invisible departments found  
638      *  tell the user that everything is ok 
639      */
640     if(!$res){
641       $this->checks['deps_visible']['STATUS']    = FALSE;
642       $this->checks['deps_visible']['STATUS_MSG']= _("Ldap query failed.");
643       $this->checks['deps_visible']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
644     }elseif(count($this->deps_to_migrate) == 0 ){
645       $this->checks['deps_visible']['STATUS']    = TRUE;
646       $this->checks['deps_visible']['STATUS_MSG']= _("Ok");
647       $this->checks['deps_visible']['ERROR_MSG'] = "";
648     }else{
649       $this->checks['deps_visible']['STATUS']    = FALSE;
650       $this->checks['deps_visible']['STATUS_MSG']= "";//sprintf(_("%s entries found"),count($this->deps_to_migrate));
651       $this->checks['deps_visible']['ERROR_MSG'] = sprintf(_("Found %s departments that will not be visible in GOsa."),count($this->deps_to_migrate));
652       $this->checks['deps_visible']['ERROR_MSG'] .= "<input type='submit' name='deps_visible_migrate' value='"._("Migrate")."'>";
653     }
654   }
658   /* Start deparmtment migration */  
659   function migrate_organizationalUnits($only_ldif = FALSE)
660   {
661     /* Get collected configuration settings */
662     $cv = $this->parent->captured_values;
664     /* Establish ldap connection */
665     $ldap = new LDAP($cv['admin'],
666         $cv['password'],
667         $cv['connection'],
668         FALSE,
669         $cv['tls']);
671     /* Add gosaDepartment objectClass to each selected entry 
672      */
673     foreach($this->deps_to_migrate as $key => $dep){
674       if($dep['checked']){
676         /* Get current objectClasses */
677         $ldap->cat($dep['dn'],array("objectClass","description"));
678         $attrs      = $ldap->fetch();
680         /* Create new objectClass attribute including gosaDepartment*/
681         $new_attrs  = array();
682         for($i = 0 ; $i < $attrs['objectClass']['count']; $i ++ ){
683           $new_attrs['objectClass'][]   = $attrs['objectClass'][$i];
684         }
685         $new_attrs['objectClass'][] = "gosaDepartment";
687         /* Append description it is missing */
688         if(!isset($attrs['description'])){
689           $new_attrs['description'][] = "GOsa department";
690         }
692         /* Depending on the parameter >only_diff< we save the changes as ldif
693          *  or we write our changes directly to the ldap database
694          */
695         if($only_ldif){
696           $this->deps_to_migrate[$key]['before'] = $this->array_to_ldif($attrs);
697           $this->deps_to_migrate[$key]['after']  = $this->array_to_ldif($new_attrs);
698         }else{
699           $ldap->cd($attrs['dn']);
700           if(!$ldap->modify($new_attrs)){
701             print_red(sprintf(_("Failed to migrate the department '%s' into GOsa, error message is as follows '%s'."),$attrs['dn'],$ldap->get_error()));
702             return(false);
703           }
704         }
705       }
706     }
707     return(TRUE);
708   }
711   /* Check Acls if there is at least one object with acls defined 
712    */
713   function check_administrativeAccount()
714   {
715     /* Establish ldap connection */
716     $cv = $this->parent->captured_values;
717     $ldap = new LDAP($cv['admin'],
718         $cv['password'],
719         $cv['connection'],
720         FALSE,
721         $cv['tls']);
723     /* Search for gosaAcls */ 
724     $ldap->cd($cv['base']);
725     $res = $ldap->search("(&(objectClass=gosaAccount)(|(objectClass=posixAccount)".     
726                            "(objectClass=inetOrgPerson)(objectClass=organizationalPerson)))");
727     if(!$res){
728       $this->checks['acls']['STATUS']    = FALSE;
729       $this->checks['acls']['STATUS_MSG']= _("Ldap query failed.");
730       $this->checks['acls']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
731     }elseif($ldap->count()){
732       $this->checks['acls']['STATUS']    = TRUE;
733       $this->checks['acls']['STATUS_MSG']= _("Ok");
734     }else{
735       $this->checks['acls']['STATUS']    = FALSE;
736       $this->checks['acls']['STATUS_MSG']= _("Failed");
737       $this->checks['acls']['ERROR_MSG'].= "<input type='submit' name='create_acls' value='"._("Create adminitrational account")."'>";
738     }
739     return($ldap->count()>=1);
740   }
744   function create_admin($only_ldif = FALSE)
745   {
746     /* Reset '' */
747     $this->acl_create_changes="";
749     /* Object that should receive admin acls */
750     $dn = $this->acl_create_selected;
752     /* Get collected configuration settings */
753     $cv = $this->parent->captured_values;
755     /* Establish ldap connection */
756     $ldap = new LDAP($cv['admin'],
757         $cv['password'],
758         $cv['connection'],
759         FALSE,
760         $cv['tls']);
762     /* Get current base attributes */
763     $ldap->cd($cv['base']);
764     $ldap->cat($cv['base'],array("dn","objectClass","gosaAclEntry"));
765     $attrs = $ldap->fetch();
767     /* Add acls for the selcted user to the base */
768     $attrs_new['objectClass'] = array("gosaACL");
770     for($i = 0; $i < $attrs['objectClass']['count']; $i ++){
771       if(!in_array_ics($attrs['objectClass'][$i],$attrs_new['objectClass'])){
772         $attrs_new['objectClass'][] = $attrs['objectClass'][$i];
773       }
774     }
776     $acl = "0:sub:".base64_encode($dn).":all;cmdrw";    
777     $attrs_new['gosaAclEntry'][] = $acl;
778     if(isset($attrs['gosaAclEntry'])){
779       for($i = 0 ; $i < $attrs['gosaAclEntry']['count']; $i ++){
780           
781         $prio = preg_replace("/[:].*$/","",$attrs['gosaAclEntry'][$i]);
782         $rest = preg_replace("/^[^:]/","",$attrs['gosaAclEntry'][$i]);
783  
784         $data = ($prio+1).$rest;
785         $attrs_new['gosaAclEntry'][] = $data;
786       }
787     }
789     if($only_ldif){
790       $this->acl_create_changes ="\n".$cv['base']."\n";
791       $this->acl_create_changes.=$this->array_to_ldif($attrs)."\n";
792       $this->acl_create_changes.="\n".$cv['base']."\n";
793       $this->acl_create_changes.=$this->array_to_ldif($attrs_new);
794     }else{
795    
796       $ldap->cd($cv['base']);
797       if(!$ldap->modify($attrs_new)){
798         print_red(sprintf(_("Adding acls for user '%s' failed, ldap says '%s'."),$dn,$ldap->get_error()));
799       }
800     }
801   }
802  
803   
804   function create_admin_user()
805   {
806     if(isset($_POST['new_user_password']) && !empty($_POST['new_user_password'])){
807       $pwd = $_POST['new_user_password'];
808     }else{
809       print_red(_("Please specify a valid password for the new GOsa admin user."));
810       return(FALSE);
811     }
812     
813     /* Establish ldap connection */
814     $cv = $this->parent->captured_values;
815     $ldap = new LDAP($cv['admin'],
816         $cv['password'],
817         $cv['connection'],
818         FALSE,
819         $cv['tls']);
821     /* Get current base attributes */
822     $ldap->cd($cv['base']);
823   
824     if($cv['peopledn'] == "cn"){
825       $dn = "cn=System Administrator,".$cv['peopleou'].",".$cv['base'];
826     }else{
827       $dn = "uid=admin,".$cv['peopleou'].",".$cv['base'];
828     }
830     $methods = @passwordMethod::get_available_methods_if_not_loaded();
831     $p_m = $methods[$cv['encryption']];
832     $p_c = new $p_m(array());
833     $hash = $p_c->generate_hash($pwd);
835     $new_user=array();
836     $new_user['objectClass']= array("top","person","gosaAccount","organizationalPerson","inetOrgPerson");
837     $new_user['givenName']  = "System";
838     $new_user['sn']  = "Administrator";
839     $new_user['cn']  = "System Administrator";
840     $new_user['uid'] = "admin";
841     $new_user['userPassword'] = $hash;
842     
843     $ldap->cd($cv['base']);
844     $ldap->create_missing_trees(preg_replace("/^[^,]+,/","",$dn));
845     $ldap->cd($dn);  
846     $res = $ldap->add($new_user);
847     $this->acl_create_selected = $dn;
848     $this->create_admin();
849     
850     if(!$res){
851       print_red($ldap->get_error());
852     }
853   
854     $this->acl_create_dialog=FALSE;        
855     $this->check_administrativeAccount();
856   }
857  
859   function migrate_outside_users($perform = FALSE)
860   {
861     /* Check if there was a destination department posted */
862     if(isset($_POST['move_user_to'])){
863       $destination_dep = $_POST['move_user_to'];
864     }else{
865       print_red(_("Couldn't move users to specified department."));
866       return(false);
867     }
868  
869     foreach($this->outside_users as $b_dn => $data){
870       $this->outside_users[$b_dn]['ldif'] ="";
871       if($data['selected']){
872         $dn = base64_decode($b_dn);
873         $d_dn = preg_replace("/,.*$/",",".base64_decode($destination_dep),$dn);
874         if(!$perform){
875           $this->outside_users[$b_dn]['ldif'] = $dn."<br>".$d_dn;
876         }else{
877           $this->move($dn,$d_dn);
878         }
879       }
880     }
881   }
882   
884   function execute()
885   {
886     /* Initialise checks if this is the first call */
887     if(!$this->checks_initialised || isset($_POST['reload'])){
888       $this->initialize_checks();
889       $this->checks_initialised = TRUE;
890     }
892     /*************
893      * User outside the people ou 
894      *************/
895     
896     if(isset($_POST['outside_users_dialog_cancel'])){
897       $this->outside_users_dialog = FALSE;
898       $this->dialog = FALSE;
899     }
900    
901     if(isset($_POST['outside_users_dialog_whats_done'])){
902       $this->migrate_outside_users(FALSE);
903     }
904  
905     if(isset($_POST['outside_users_dialog_perform'])){
906       $this->migrate_outside_users(TRUE);
907       $this->search_outside_users();
908     }
910     if(isset($_POST['outside_users_dialog'])){
911       $this->outside_users_dialog = TRUE;
912       $this->dialog = TRUE;
913     }
914     
915     if($this->outside_users_dialog){
916       $smarty = get_smarty();
917       $smarty->assign("ous",$this->get_all_people_ous());
918       $smarty->assign("method","outside_users");
919       $smarty->assign("outside_users",$this->outside_users);
920       return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
921     }
922  
923     /*************
924      * Root object check  
925      *************/
926   
927     if(isset($_POST['retry_root_create'])){
929       $state = $this->checks['root']['STATUS'];
930       $this->checkBase(FALSE);
931       if($state != $this->checks['root']['STATUS']){
932         $this->initialize_checks();
933       }
934     }
935  
936     /*************
937      * User Migration handling 
938      *************/
940     if(isset($_POST['retry_acls'])){
941       $this->check_administrativeAccount();
942     }
944     if(isset($_POST['create_acls'])){
945       $this->acl_create_dialog = TRUE;
946       $this->dialog = TRUE;
947     }
948   
949     if(isset($_POST['create_acls_cancel'])){
950       $this->acl_create_dialog = FALSE;
951       $this->dialog = FALSE;
952     }
954     if(isset($_POST['create_acls_create_confirmed'])){
955       $this->create_admin();
956     }
958     if(isset($_POST['create_acls_create'])){
959       $this->create_admin(TRUE);
960     }
962     if(isset($_POST['create_admin_user'])){
963       $this->create_admin_user();
964     }
966     if($this->acl_create_dialog){
967       $smarty = get_smarty();
968       $smarty->assign("new_user_password",@$_POST['new_user_password']);
969       $smarty->assign("users" ,$this->get_user_list());
970       $smarty->assign("users_cnt" ,count($this->get_user_list()));
971       $smarty->assign("groups",$this->get_group_list());
972       $smarty->assign("groups_cnt",count($this->get_group_list()));
973       $smarty->assign("type"  ,$this->acl_create_type);
974       $smarty->assign("method","create_acls");
975       $smarty->assign("acl_create_selected",$this->acl_create_selected);
976       $smarty->assign("what_will_be_done_now",$this->acl_create_changes);
977       return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
978     }
980     /*************
981      * User Migration handling 
982      *************/
984     /* Refresh list of deparments */
985     if(isset($_POST['users_visible_migrate_refresh'])){
986       $this->check_gosaAccounts();
987     }
989     /* Open migration dialog */
990     if(isset($_POST['users_visible_migrate'])){
991       $this->users_migration_dialog = TRUE;
992       $this->dialog =TRUE;
993     }
995     /* Close migration dialog */
996     if(isset($_POST['users_visible_migrate_close'])){
997       $this->users_migration_dialog = FALSE;
998       $this->dialog =FALSE;
999     }
1001     /* Start migration */
1002     if(isset($_POST['users_visible_migrate_migrate'])){
1003       if($this->migrate_gosaAccounts()){
1004         $this->check_gosaAccounts();
1005       }
1006     }
1008     /* Start migration */
1009     if(isset($_POST['users_visible_migrate_whatsdone'])){
1010       $this->migrate_gosaAccounts(TRUE);
1011     }
1013     /* Display migration dialog */
1014     if($this->users_migration_dialog){
1015       $smarty = get_smarty();
1016       $smarty->assign("users_to_migrate",$this->users_to_migrate);
1017       $smarty->assign("method","migrate_users");
1018       return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
1019     }
1022     /*************
1023      * Department Migration handling 
1024      *************/
1026     /* Refresh list of deparments */
1027     if(isset($_POST['deps_visible_migrate_refresh'])){
1028       $this->check_organizationalUnits();
1029     }
1031     /* Open migration dialog */
1032     if(isset($_POST['deps_visible_migrate'])){
1033       $this->dep_migration_dialog = TRUE;
1034       $this->dialog =TRUE;
1035     }
1037     /* Close migration dialog */
1038     if(isset($_POST['deps_visible_migrate_close'])){
1039       $this->dep_migration_dialog = FALSE;
1040       $this->dialog =FALSE;
1041     }
1043     /* Start migration */
1044     if(isset($_POST['deps_visible_migrate_migrate'])){
1045       if($this->migrate_organizationalUnits()){
1046         $this->check_organizationalUnits();
1047       }
1048     }
1050     /* Start migration */
1051     if(isset($_POST['deps_visible_migrate_whatsdone'])){
1052       $this->migrate_organizationalUnits(TRUE);
1053     }
1055     /* Display migration dialog */
1056     if($this->dep_migration_dialog){
1057       $smarty = get_smarty();
1058       $smarty->assign("deps_to_migrate",$this->deps_to_migrate);
1059       $smarty->assign("method","migrate_deps");
1060       return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
1061     }
1063     $smarty = get_smarty();
1064     $smarty->assign("checks",$this->checks);
1065     $smarty->assign("method","default");
1066     return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
1067   }
1070   function save_object()
1071   {
1072     /* Capture all selected users from outside_users_dialog */
1073     if($this->outside_users_dialog){
1074       foreach($this->outside_users as $dn => $data){
1075         if(isset($_POST['select_user_'.$dn])){
1076           $this->outside_users[$dn]['selected'] = TRUE;
1077         }else{
1078           $this->outside_users[$dn]['selected'] = FALSE;
1079         }
1080       }
1081     }
1083     /* Get "create acl" dialog posts */
1084     if($this->acl_create_dialog){
1085       if(isset($_POST['create_acls_create'])){
1086         if(isset($_POST['create_acls_selected'])){
1087           $this->acl_create_selected = base64_decode($_POST['create_acls_selected']);
1088         }else{
1089           $this->acl_create_selected = ""; 
1090         }
1091       }
1093       if(isset($_POST['create_acls_create_abort'])){
1094         $this->acl_create_selected = "";
1095       }
1097       if(isset($_POST['acl_create_type'])){
1098         $this->acl_create_type = $_POST['acl_create_type'];
1099       }
1100     }
1102     /* Get selected departments */
1103     if($this->dep_migration_dialog){
1104       foreach($this->deps_to_migrate as $id => $data){
1105         if(isset($_POST['migrate_'.$id])){
1106           $this->deps_to_migrate[$id]['checked'] = TRUE;
1107         }else{
1108           $this->deps_to_migrate[$id]['checked'] = FALSE;
1109         }
1110       }
1111     }
1113     /* Get selected users */
1114     if($this->users_migration_dialog){
1115       foreach($this->users_to_migrate as $id => $data){
1116         if(isset($_POST['migrate_'.$id])){
1117           $this->users_to_migrate[$id]['checked'] = TRUE;
1118         }else{
1119           $this->users_to_migrate[$id]['checked'] = FALSE;
1120         }
1121       }
1122     }
1123   }
1126   /* Check if the root object exists.
1127    * If the parameter just_check is true, then just check if the 
1128    *  root object is missing and update the info messages.
1129    * If the Parameter is false, try to create a new root object.
1130    */
1131   function checkBase($just_check = TRUE)
1132   {
1133     /* Get collected setup informations */
1134     $cv = $this->parent->captured_values;
1136     /* Establish ldap connection */
1137     $ldap = new LDAP($cv['admin'],
1138         $cv['password'],
1139         $cv['connection'],
1140         FALSE,
1141         $cv['tls']);
1143     /* Check if root object exists */
1144     $ldap->cd($cv['base']);
1145     $res = $ldap->search("(objectClass=*)");
1146     $err = ldap_errno($ldap->cid); 
1148     if( !$res || 
1149         $err == 0x20 ||  # LDAP_NO_SUCH_OBJECT
1150         $err == 0x40) {  # LDAP_NAMING_VIOLATION
1152       /* Root object doesn't exists 
1153        */
1154       if($just_check){
1155         $this->checks['root']['STATUS']    = FALSE;
1156         $this->checks['root']['STATUS_MSG']= _("Failed");
1157         $this->checks['root']['ERROR_MSG'].=  "<input type='submit' name='retry_root_create' value='"._("Try to create root object")."'>";
1158         return(FALSE);
1159       }else{
1161       echo "REMOVE this : Autocreation of the root object will be done by create_missing_tree later. !!!!!!!";
1163          /* Try to find out which values are necessary */
1164         $tmp = $ldap->get_objectclasses();
1165         $oc = $tmp['organization'];
1166       
1167         $must_attrs = $oc['MUST'];
1168         if(!is_array($must_attrs)){
1169           $must_attrs = array($must_attrs);
1170         }
1171       
1172         /* Root object does not exists try to create it */
1173         $ldapadd["objectclass"][0]="top";
1174         $ldapadd["objectclass"][1]="organization";
1176         /* Try to fill all collected must attributes */
1177         $base_parts = preg_split("/,/",$cv['base']);
1178         foreach($must_attrs as $attr){
1179           foreach($base_parts as $part){
1180             if(preg_match("/^".$attr."=/",$part) && !isset($ldapadd[$attr])){
1181               $ldapadd[$attr]= preg_replace("/^[^=]*+=/","",$part);
1182             }
1183           }
1184         }
1186         /* Add root object */ 
1187         $ldap->cd($cv['base']);
1188         $res = $ldap->add($ldapadd);
1190         /* Add root object */ 
1191         $ldap->cd($cv['base']);
1192  #       $res = $ldap->create_missing_trees($cv['base']);
1194         /* If adding failed, tell the user */
1195         if(!$res){
1196           $this->checks['root']['STATUS']    = FALSE;
1197           $this->checks['root']['STATUS_MSG']= _("Failed");
1198           $this->checks['root']['ERROR_MSG'] = _("Root object couldn't be created, you should try it on your own.");
1199           $this->checks['root']['ERROR_MSG'].= "<input type='submit' name='retry_root_create' value='"._("Try to create root object")."'>";
1200           return($res);;
1201         }
1202       }
1203     }
1205     /* Create & remove of dummy object was successful */
1206     $this->checks['root']['STATUS']    = TRUE;
1207     $this->checks['root']['STATUS_MSG']= _("Ok");
1208   }
1211   /* Return ldif information for a 
1212    * given attribute array 
1213    */
1214   function array_to_ldif($atts)
1215   {
1216     $ret = "";
1217     unset($atts['count']);
1218     unset($atts['dn']);
1219     foreach($atts as $name => $value){
1220       if(is_numeric($name)) {
1221         continue;
1222       }
1223       if(is_array($value)){
1224         unset($value['count']);
1225         foreach($value as $a_val){
1226           $ret .= $name.": ". $a_val."\n";
1227         }
1228       }else{
1229         $ret .= $name.": ". $value."\n";
1230       }
1231     }
1232     return(preg_replace("/\n$/","",$ret));
1233   }
1236   function get_user_list()
1237   {
1238     /* Get collected configuration settings */
1239     $cv = $this->parent->captured_values;
1241     /* Establish ldap connection */
1242     $ldap = new LDAP($cv['admin'],
1243         $cv['password'],
1244         $cv['connection'],
1245         FALSE,
1246         $cv['tls']);
1247     
1248     $ldap->cd($cv['base']);
1249     $ldap->search("(objectClass=gosaAccount)",array("dn"));
1250   
1251     $tmp = array();
1252     while($attrs = $ldap->fetch()){
1253       $tmp[base64_encode($attrs['dn'])] = @LDAP::fix($attrs['dn']);
1254     }
1255     return($tmp);
1256   }
1259   function get_all_people_ous()
1260   {
1261     /* Get collected configuration settings */
1262     $cv = $this->parent->captured_values;
1264     /* Establish ldap connection */
1265     $ldap = new LDAP($cv['admin'],
1266         $cv['password'],
1267         $cv['connection'],
1268         FALSE,
1269         $cv['tls']);
1271     $ldap->cd($cv['base']);
1272     $ldap->search("(".$cv['peopleou'].")",array("dn"));
1273   
1274     if($ldap->count() == 0 ){
1275       $add_dn = $cv['peopleou'].",".$cv['base'];
1276       $naming_attr = preg_replace("/=.*$/","",$add_dn);
1277       $naming_value = preg_replace("/^[^=]*+=([^,]*).*$/","\\1",$add_dn);
1278       $add = array();
1279       $add['objectClass'] = array("organizationalUnit");
1280       $add[$naming_attr] = $naming_value;
1282       $ldap->cd($cv['base']);
1283       $ldap->create_missing_trees(preg_replace("/^[^,]+,/","",$add_dn));
1284       $ldap->cd($add_dn);
1285       $ldap->add($add);
1286     }
1288     $ldap->search("(".$cv['peopleou'].")",array("dn"));
1289     $tmp = array();
1290     while($attrs= $ldap->fetch()){
1291       if(!preg_match("/ou=snapshots,/",$attrs['dn'])){
1292         $tmp[base64_encode($attrs['dn'])] = $ldap->fix($attrs['dn']);
1293       }
1294     }
1295     return($tmp); 
1296   }
1299   function get_group_list()
1300   {
1301     /* Get collected configuration settings */
1302     $cv = $this->parent->captured_values;
1304     /* Establish ldap connection */
1305     $ldap = new LDAP($cv['admin'],
1306         $cv['password'],
1307         $cv['connection'],
1308         FALSE,
1309         $cv['tls']);
1310     
1311     $ldap->cd($cv['base']);
1312     $ldap->search("(objectClass=posixGroup)",array("dn"));
1313   
1314     $tmp = array();
1315     while($attrs = $ldap->fetch()){
1316       $tmp[base64_encode($attrs['dn'])] = @LDAP::fix($attrs['dn']);
1317     }
1318     return($tmp);
1319   }
1322   function move($source,$destination)
1323   {
1324     /* Get collected configuration settings */
1325     $cv = $this->parent->captured_values;
1327     /* Establish ldap connection */
1328     $ldap = new LDAP($cv['admin'],
1329         $cv['password'],
1330         $cv['connection'],
1331         FALSE,
1332         $cv['tls']);
1334      /* Rename dn in possible object groups */
1335 #    $ldap->cd($cv['base']);
1336 #    $ldap->search('(&(objectClass=gosaGroupOfNames)(member='.@LDAP::fix($source).'))',
1337 #        array('cn'));
1338  #   while ($attrs= $ldap->fetch()){
1339  #     $og= new ogroup($this->config, $ldap->getDN());
1340  #     unset($og->member[$src_dn]);
1341  #     $og->member[$dst_dn]= $dst_dn;
1342  #     $og->save ();
1343  #   }
1345     $ldap->cat($source);
1346     $new_data = $this->cleanup_array($ldap->fetch());
1347     $ldap->cd($destination);
1348     $res = $ldap->add($new_data);
1349     
1350     if(!$res){
1351       print_red(_("Failed to copy '%s' to '%s'. Ldap says '%s'."),$source,$destination,$ldap->get_error());
1352     }else{
1353       $ldap->rmDir($source);
1354       show_ldap_error($ldap->get_error(),_("Something went wrong while copying dns."));
1355     }
1356   }
1358   
1359   /* Cleanup ldap result to be able to write it be to ldap */
1360   function cleanup_array($attrs)
1361   {
1362     foreach($attrs as $key => $value) {
1363       if(is_numeric($key) || in_array($key,array("count","dn"))){
1364         unset($attrs[$key]);
1365       }
1366       if(is_array($value) && isset($value['count'])){
1367         unset($attrs[$key]['count']);
1368       }
1369     }
1370     return($attrs);
1371   }
1374 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1375 ?>