Code

Removed show_ldap_error() calls
[gosa.git] / gosa-plugins / fai / admin / fai / class_FAI.inc
1 <?php
3 define("DEBUG_FAI_FUNC",FALSE);
6 class FAI
7 {
9   /* TEST PHASE .... */
11   /* Returns all object for the given release.
12      This function resolves the releases  
13      from base up to the given dn.
14    */
15   static function get_all_objects_for_given_base($Current_DN,$filter,$detailed = false)
16   {
17     global $config;
18     $ldap = $config->get_ldap_link();
19     $ldap->cd($config->current['BASE']);
20     $res = array();
21     $tmp = array();
23     if(!FAI::is_release_department($Current_DN)) {
24       return($res);
25     }
27     /* Collect some basic informations and initialize some variables */ 
28     $base_release       = FAI::get_release_dn($Current_DN);
29     $previous_releases  = array_reverse(FAI::             get_previous_releases_of_this_release($base_release,true));
31     /* We must also include the given release dn */
32     $previous_releases[] = $base_release;
34     /* Walk through all releases */
35     foreach($previous_releases as $release){
37       /* Get fai departments */
38       $deps_to_search = FAI::get_FAI_departments($release); 
40       /* For every single department  (ou=hoos,ou ..) */
41       foreach($deps_to_search as $fai_base){
43         /* Ldap search for fai classes specified in this release */
44         $attributes  = array("dn","objectClass","FAIstate","cn");
45         $res_tmp = get_list($filter,"fai",$fai_base,$attributes,GL_SUBSEARCH | GL_SIZELIMIT);
47         /* check the returned objects, and add/replace them in our return variable */
48         foreach($res_tmp as $attr){
50           $buffer = array();
51           $name = preg_replace("/".normalizePreg($release)."/i","",$attr['dn']);
53           if(isset($attr['FAIstate'][0])){
54             if(preg_match("/removed$/",$attr['FAIstate'][0])){
55               if(isset($res[$name])){
56                 unset($res[$name]);
57               }
58               continue;
59             }
60           }
62           /* In detailed mode are some additonal informations visible */
63           if($detailed){
65             /* Create list of parents */
66             if(isset($res[$name])){
67               $buffer = $res[$name];
68               $buffer['parents'][] = $res[$name]['dn'];
69             }else{
70               $buffer['parents'] = array();
71             }
73             /* Append objectClass to resulsts */
74             foreach($attributes as $val){
75               if(isset($attr[$val])){
76                 $buffer[$val] = $attr[$val];
77               }
78             }
79             unset($buffer['objectClass']['count']);
80           }
82           /* Add this object to our list */
83           $buffer['dn']           = $attr['dn'];
84           $res[$name] = $buffer;
85         }
86       }
87     }
88     return($res);
89   }
92   /* Return all relevant FAI departments */
93   static function get_FAI_departments($suffix = "")
94   {
95     $arr = array("hooks","scripts","disk","packages","profiles","templates","variables");
96     $tmp = array();
97     if(preg_match("/^,/",$suffix)){
98       $suffix = preg_replace("/^,/","",$suffix);
99     }
100     foreach($arr as $name){
101       if(empty($suffix)){
102         $tmp[$name] = "ou=".$name;
103       }else{
104         $tmp[$name] = "ou=".$name.",".$suffix;
105       }
106     }
107     return($tmp);
108   }
111   /* Return all releases within the given base */
112   static function get_all_releases_from_base($dn,$appendedName=false)
113   {
114     global $config;
116     if(!preg_match("/".normalizePreg(get_ou('faiou'))."/",$dn)){
117       $base = get_ou('faiou').$dn;
118     }else{
119       $base = $dn;
120     }
121     $res = array();  
123     $ldap = $config->get_ldap_link();
124     $ldap->cd($base);
125     $ldap->search("(objectClass=FAIbranch)",array("ou","dn"));
126     while($attrs = $ldap->fetch()){
127       if($appendedName){
128         $res[$attrs['dn']] = convert_department_dn(preg_replace("/,".normalizePreg(get_ou('faiou')).".*$/","",$attrs['dn']));
129       }else{
130         $res[$attrs['dn']] = $attrs['ou'][0];
131       }
132     }
133     return($res);
134   }
137   /* Add this object to list of objects, that must be checked for release saving */
138   static function prepare_to_save_FAI_object($Current_DN,$objectAttrs,$removed = false)
139   {
140     /* Get ldap object */  
141     global $config;
142     $addObj['Current_DN'] = $Current_DN;
143     $addObj['objectAttrs']= $objectAttrs;
144     $addObj['removed']    = $removed;
145     $addObj['diff']       = TRUE;
147     if(!$removed){
148       $ldap = $config->get_ldap_link();
149       $ldap->cd($config->current['BASE']);
151       /* Get some basic informations */
152       $parent_obj   = FAI::get_parent_release_object($Current_DN);
153       if(!empty($parent_obj)){
154         $ldap->cat($parent_obj,array("*"));
155         $attrs = FAI::                           prepare_ldap_fetch_to_be_saved($ldap->fetch());
157         if(!FAI::array_diff_FAI( $attrs,$objectAttrs)){
158           $addObj['diff'] = FALSE;
159         }
160       } 
161     }
162     $FAI_objects_to_save = session::get('FAI_objects_to_save') ;
163     $FAI_objects_to_save[$Current_DN] =  $addObj;
164     session::set('FAI_objects_to_save',$FAI_objects_to_save);
165   }
168   /* Detect differences in attribute arrays  */
169   static function array_diff_FAI($ar1,$ar2)
170   {
172     if((!isset($ar1['description'])) || (isset($ar1['description']) && (count($ar1['description']) == 0))){
173       $ar1['description'] = "";
174     }
175     if((!isset($ar2['description'])) || (isset($ar2['description']) && (count($ar2['description']) == 0))){
176       $ar2['description'] = "";
177     }
179     if(count($ar1) != count($ar2)) {
180       return (true);
181     }
183     foreach($ar1 as $key1 => $val1){
185       if((is_array($val1)) && (count($val1)==1)){
186         $ar1[$key1] = $val1[0];
187       }
189       if((is_array($ar2[$key1])) && (count($ar2[$key1])==1)){
190         $val1 = $val1[0];
191         $ar2[$key1] = $ar2[$key1][0];
192       }
193     }
194     ksort($ar1);
195     ksort($ar2);
196     if(count( array_diff($ar1,$ar2)) || FAI::arr_diff($ar1,$ar2)){
197       return(true);
198     }else{
199       return(false);
200     }
201   }
204   static function arr_diff($ar1,$ar2)
205   {
206     foreach($ar1 as $ak1 => $av1){
207       if(!isset($ar2[$ak1]) || (!($av1 === $ar2[$ak1]))){
208         return(true);
209       }elseif(is_array($av1)){
210         return(FAI::arr_diff($av1,$ar2[$ak1]));
211       }
212     }
213     return(FALSE);
214   }
219   /* check which objects must be saved, and save them */
220   static function save_release_changes_now()
221   {
222     /* Variable init*/
223     $to_save = array();
225     /* check which objects must be saved */
226     $FAI_objects_to_save = session::get('FAI_objects_to_save');
227     foreach($FAI_objects_to_save as $Current_DN => $object){
228       if($object['diff']){
229         $sub_name = $Current_DN;
230         while(isset($FAI_objects_to_save[$sub_name])){
231           $to_save[strlen($sub_name)][$sub_name] = $FAI_objects_to_save[$sub_name]; 
232           unset($FAI_objects_to_save[$sub_name]);
233           $sub_name = preg_replace('/^[^,]+,/', '', $sub_name);
234         }
235       }
236     }
237     session::set('FAI_objects_to_save',$FAI_objects_to_save);
239     /* Sort list of objects that must be saved, and ensure that 
240        container   objects are safed, before their childs are saved */
241     ksort($to_save);
242     $tmp = array();
243     foreach($to_save as $SubObjects){
244       foreach($SubObjects as $object){
245         $tmp[] = $object;
246       }
247     }
248     $to_save = $tmp;
250     /* Save objects and manage the correct release behavior*/
251     foreach($to_save as $save){
253       $Current_DN = $save['Current_DN'];
254       $removed    = $save['removed'];
255       $objectAttrs= $save['objectAttrs'];
257       /* Get ldap object */ 
258       global $config;
259       $ldap = $config->get_ldap_link();
260       $ldap->cd($config->current['BASE']);
262       /* Get some basic informations */
263       $base_release       = FAI::get_release_dn($Current_DN);
264       $sub_releases       = FAI::                       get_sub_releases_of_this_release($base_release,true);
265       $parent_obj         = FAI::get_parent_release_object($Current_DN);
266       $following_releases = FAI::                       get_sub_releases_of_this_release($base_release,true);
268       /* Check if given dn exists or if is a new entry */
269       $ldap->cat($Current_DN);
270       if(!$ldap->count()){
271         $is_new = true;
272       }else{
273         $is_new = false;
274       }
276       /* if parameter removed is true, we have to add FAIstate to the current attrs 
277          FAIstate should end with ...|removed after this operation */  
278       if($removed ){
279         $ldap->cat($Current_DN);
281         /* Get current object, because we must add the FAIstate ...|removed */
282         if((!$ldap->count()) && !empty($parent_obj)){
283           $ldap->cat($parent_obj);
284         }
286         /* Check if we have found a suiteable object */ 
287         if(!$ldap->count()){
288           echo "Error can't remove this object ".$Current_DN;
289           return;
290         }else{
292           /* Set FAIstate to current objectAttrs */
293           $objectAttrs = FAI::                           prepare_ldap_fetch_to_be_saved($ldap->fetch());
294           if(isset($objectAttrs['FAIstate'][0])){
295             if(!preg_match("/removed$/",$objectAttrs['FAIstate'][0])){
296               $objectAttrs['FAIstate'][0] .= "|removed";
297             }
298           }else{
299             $objectAttrs['FAIstate'][0] = "|removed";
300           }
301         }
302       }
304       /* Check if this a leaf release or not */ 
305       if(count($following_releases) == 0 ){
307         /* This is a leaf object. It isn't inherited by any other object */    
308         if(DEBUG_FAI_FUNC) { 
309           echo "<b>Saving directly, is a leaf object</b><br> ".$Current_DN;
310           print_a($objectAttrs);
311         }
312         FAI::save_FAI_object($Current_DN,$objectAttrs);
313       }else{
315         /* This object is inherited by some sub releases */  
317         /* Get all releases, that inherit this object */ 
318         $r = FAI::get_following_releases_that_inherit_this_object($Current_DN);
320         /* Get parent object */
321         $ldap->cat($parent_obj);
322         $parent_attrs = FAI::prepare_ldap_fetch_to_be_saved($ldap->fetch());
324         /* New objects require special handling */
325         if($is_new){
327           /* check if there is already an entry named like this,
328              in one of our parent releases */
329           if(!empty($parent_obj)){
330             if(DEBUG_FAI_FUNC) { 
331               echo "There is already an entry named like this.</b><br>";
333               echo "<b>Saving main object</b>".$Current_DN;
334               print_a($objectAttrs);
335             }    
336             FAI::save_FAI_object($Current_DN,$objectAttrs);
338             foreach($r as $key){
339               if(DEBUG_FAI_FUNC) { 
340                 echo "<b>Saving parent to following release</b> ".$key;
341                 print_a($parent_attrs);
342               }
343               FAI::save_FAI_object($key,$parent_attrs);
344             }
345           }else{
347             if(DEBUG_FAI_FUNC) { 
348               echo "<b>Saving main object</b>".$Current_DN;
349               print_a($objectAttrs);
350             }
351             FAI::save_FAI_object($Current_DN,$objectAttrs);
353             if(isset($objectAttrs['FAIstate'])){
354               $objectAttrs['FAIstate'] .= "|removed"; 
355             }else{
356               $objectAttrs['FAIstate'] = "|removed";
357             }
359             foreach($r as $key ){
360               if(DEBUG_FAI_FUNC) { 
361                 echo "<b>Create an empty placeholder in follwing release</b> ".$key; 
362                 print_a($objectAttrs);
363               }
364               FAI::save_FAI_object($key,$objectAttrs);
365             }
366           }
367         }else{
369           /* check if we must patch the follwing release */
370           if(!empty($r)){
371             foreach($r as $key ){
372               if(DEBUG_FAI_FUNC) { 
373                 echo "<b>Copy current objects original attributes to next release</b> ".$key;
374                 print_a($parent_attrs);
375               }
376               FAI::save_FAI_object($key,$parent_attrs);
377             }
378           }
380           if(DEBUG_FAI_FUNC) { 
381             echo "<b>Saving current object</b>".$parent_obj;
382             print_a($objectAttrs);
383           }
384           FAI::save_FAI_object($parent_obj,$objectAttrs);
386           if(($parent_obj != $Current_DN)){
387             msg_dialog::display(_("Error"), sprintf(_("Error, following objects should be equal '%s' and '%s'"),$parent_obj,$Current_DN), ERROR_DIALOG);
388           }
389         }
390       }
391     } 
392     session::set('FAI_objects_to_save',array());
393   }
396   /* this function will remove all unused (deleted) objects,
397      that have no parent object */
398   static function clean_up_releases($Current_DN)
399   {
400     global $config;
401     $ldap = $config->get_ldap_link();
402     $ldap->cd($config->current['BASE']);
404     /* Collect some basic informations and initialize some variables */ 
405     $base_release       = FAI::get_release_dn($Current_DN);
406     $previous_releases  = array_reverse(FAI::             get_previous_releases_of_this_release($base_release,true));
407     $Kill = array();
408     $Skip = array();
410     /* We must also include the given release dn */
411     $previous_releases[] = $base_release;
413     /* Walk through all releases */
414     foreach($previous_releases as $release){
416       /* Get fai departments */
417       $deps_to_search = FAI::get_FAI_departments($release); 
419       /* For every single department  (ou=hoos,ou ..) */
420       foreach($deps_to_search as $fai_base){
422         /* Ldap search for fai classes specified in this release */
423         $ldap->cd($fai_base);
424         $ldap->search("(objectClass=FAIclass)",array("dn","objectClass","FAIstate"));
426         /* check the returned objects, and add/replace them in our return variable */
427         while($attr = $ldap->fetch()){
429           $buffer = array();
430 #        $name = str_ireplace($release,"",$attr['dn']);
431           $name = preg_replace("/".normalizePreg($release)."/i","",$attr['dn']);
433           if(isset($attr['FAIstate'][0])&&(preg_match("/removed$/",$attr['FAIstate'][0]))){
435             /* Check if this object is required somehow */    
436             if(!isset($Skip[$name])){
437               $Kill[$attr['dn']] = $attr['dn'];
438             }
439           }else{
441             /* This object is required (not removed), so do not 
442                delete any following sub releases of this object */
443             $Skip[$name] = $attr['dn'];
444           }
445         }
446       }
447     }
448     return($Kill);
449   }
452   /* Remove numeric index and 'count' from ldap->fetch result */
453   static function prepare_ldap_fetch_to_be_saved($attrs)
454   {
455     foreach($attrs as $key => $value){
456       if(is_numeric($key) || ($key == "count") || ($key == "dn")){
457         unset($attrs[$key]);
458       }
459       if(is_array($value) && isset($value['count'])){
460         unset($attrs[$key]['count']);
461       }
462     }
463     return($attrs);
464   }
467   /* Save given attrs to specified dn*/
468   static function save_FAI_object($dn,$attrs)
469   {
470     global $config;
471     $ldap = $config->get_ldap_link();
472     $ldap->cd($config->current['BASE']);
473     $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $dn));
474     $ldap->cd($dn);
476     $ldap->cat($dn,array("dn"));
477     if($ldap->count()){
479       /* Remove FAIstate*/
480       if(!isset($attrs['FAIstate'])){
481         $attrs['FAIstate'] = array();
482       }
484       $ldap->modify($attrs);
485     }else{
487       /* Unset description if empty  */
488       if(empty($attrs['description'])){
489         unset($attrs['description']);
490       }    
492       $ldap->add($attrs);
493     }
494     if (!$ldap->success()){
495       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, 0, get_class()));
496     }
497   }
500   /* Return FAIstate freeze branch or "" for specified release department */
501   static function get_release_tag($dn)
502   {
503     global $config;
504     $ldap = $config->get_ldap_link();
505     $ldap->cd($dn);
506     $ldap->cat($dn,array("FAIstate"));
508     if($ldap->count()){
510       $attr = $ldap->fetch();
511       if(isset($attr['FAIstate'][0])){
512         if(preg_match("/freeze/",$attr['FAIstate'][0])){
513           return("freeze");
514         }elseif(preg_match("/branch/",$attr['FAIstate'][0])){
515           return("branch");
516         }
517       }
518     }
519     return("");
520   }
523   static function get_following_releases_that_inherit_this_object($dn)
524   {
525     global $config;
526     $ldap = $config->get_ldap_link();
527     $ldap->cd($config->current['BASE']);
529     $ret = array();
531     /* Get base release */
532     $base_release = FAI::get_release_dn($dn);
534     /* Get previous release dns */
535     $sub_releases = FAI::                       get_sub_releases_of_this_release($base_release);
537     /* Get dn suffix. Example  "FAIvairableEntry=keksdose,FAIvariable=Keksregal," */
538 #  $dn_suffix = str_ireplace($base_release,"",$dn);
539     $dn_suffix = preg_replace("/".normalizePreg($base_release)."/i","",$dn);
541     /* Check if given object also exists whitin one of these releases */
542     foreach($sub_releases as $p_release => $name){
544       $check_dn = $dn_suffix.$p_release;
546       $ldap->cat($check_dn,array("dn","objectClass"));
548       if($ldap->count()){
549         //return($ret);
550       }else{
551         $ret[$check_dn]=$check_dn;
552       }
553     }
554     return($ret);
555   }
558   /* Get previous version of the object dn */
559   static function get_parent_release_object($dn,$include_myself=true)
560   {
561     global $config;
562     $ldap = $config->get_ldap_link();
563     $ldap->cd($config->current['BASE']);
564     $previous_releases= array();
566     /* Get base release */
567     $base_release = FAI::get_release_dn($dn);
568     if($include_myself){
569       $previous_releases[] = $base_release;  
570     }
572     /* Get previous release dns */
573     $tmp = FAI::             get_previous_releases_of_this_release($base_release,true);
574     foreach($tmp as $release){
575       $previous_releases[] = $release;
576     }
578     /* Get dn suffix. Example  "FAIvairableEntry=keksdose,FAIvariable=Keksregal," */
579 #  $dn_suffix = str_ireplace($base_release,"",$dn);
580     $dn_suffix = preg_replace("/".normalizePreg($base_release)."/i","",$dn);
582     /* Check if given object also exists whitin one of these releases */
583     foreach($previous_releases as $p_release){
584       $check_dn = $dn_suffix.$p_release;
585       $ldap->cat($check_dn,array("dn","objectClass"));
587       if($ldap->count()){
588         return($check_dn);
589       }
590     }
591     return("");
592   }
595   /* return release names of all parent releases */
596   static function get_previous_releases_of_this_release($dn,$flat)
597   {
598     global $config;
599     $ldap = $config->get_ldap_link();
600     $ldap->cd($config->current['BASE']);
601     $ret = array();
603     /* Explode dns into pieces, to be able to build parent dns */
604     $dns_to_check = gosa_ldap_explode_dn(preg_replace("/".normalizePreg(",".$config->current['BASE'])."/i","",$dn));
606     if(!is_array($dns_to_check)){
607       return;  
608     }
610     /* Unset first entry which represents the given dn */
611     unset($dns_to_check['count']); 
612     unset($dns_to_check[key($dns_to_check)]);
614     /* Create dns addresses and check if this dn is a release dn */
615     $id = 0;
616     while(count($dns_to_check)){
618       /* build parent dn */
619       $new_dn = "";
620       foreach($dns_to_check as $part){
621         $new_dn .= $part.",";
622       }
623       $new_dn .= $config->current['BASE'];
625       /* check if this dn is a release */
626       if(FAI::is_release_department($new_dn)){
627         if($flat){
628           $ret[$id] = $new_dn; 
629         }else{
630           $ret = array($new_dn=>$ret); 
631         }
632         $id ++;
633       }else{
634         return($ret);
635       }
636       reset($dns_to_check);
637       unset($dns_to_check[key($dns_to_check)]);
638     }
639     return($ret);
640   } 
643   /* This function returns all sub release names, recursivly  */
644   static function get_sub_releases_of_this_release($dn,$flat = false)
645   {
646     global $config;
647     $res  = array();
648     $ldap = $config->get_ldap_link();
649     $ldap->cd($config->current['BASE']);
650     $ldap->ls("(objectClass=FAIbranch)",$dn,array("objectClass","dn","ou"));
651     while($attr = $ldap->fetch()){
653       /* Append department name */
654       if($flat){
655         $res[$attr['dn']] = $attr['ou'][0];
656       }else{
657         $res[$attr['dn']] = array();
658       }
660       /* Get sub release departments of this department */
661       if(in_array("FAIbranch",$attr['objectClass'])) {
662         if($flat){
663           $tmp = FAI::                       get_sub_releases_of_this_release($attr['dn'],$flat);
664           foreach($tmp as $dn => $value){
665             $res[$dn]=$value;
666           }
667         }else{
668           $res[$attr['dn']] = FAI::                       get_sub_releases_of_this_release($attr['dn']);
669         }
670       }
671     }
672     return($res);
673   }
676   /* Check if the given department is a release department */
677   static function is_release_department($dn)
678   {
679     global $config;
680     $ldap = $config->get_ldap_link();
681     $ldap->cd($config->current['BASE']);
682     $ldap->cat($dn,array("objectClass","ou"));
684     /* Check objectClasses and name to check if this is a release department */
685     if($ldap->count()){
686       $attrs = $ldap->fetch();
688       $ou = "";
689       if(isset($attrs['ou'][0])){
690         $ou = $attrs['ou'][0];  
691       }
693       if((in_array("FAIbranch",$attrs['objectClass'])) || ($ou == "fai")){
694         return($attrs['dn']);
695       }
696     }
697     return(false);
698   }
701   static function copy_FAI_group_releases($source_release , $destination_name, $type ="" )
702   {
703     global $config;
704     $start = microtime(TRUE);
705     $source_release = trim($source_release,"/");
707     echo "<h2>".sprintf(_("Creating group application release for %s"),$destination_name)."</h2>";
709     $sub_releases = array();
710     $source_dn = "";
711     
712     $tmp = split("\/",$source_release);
713     foreach($tmp as $part){
714       if(empty($part)){
715         continue;
716       }
717       $source_dn            = "ou=".$part.",".$source_dn;
718       $sub_releases[$part]  = $source_dn;
719     }
721     /* Get all groups */
722     $ldap =$config->get_ldap_link();
723     $ldap->cd($config->current['BASE']);
724     $ldap->search("(objectClass=posixGroup)",array("dn"));
725     $groups = array();
726     while($attrs = $ldap->fetch()){
727       $groups[$attrs['dn']] = $attrs;
728     }
730     /* Get all FAI releases, to be able to create missing group application releases 
731         with the correct type of release (FAIstate=freeze/branch).
732      */
733     $f_releases = array();
734     $ldap->cd ($config->current['BASE']);
735     $ldap->search("(objectClass=FAIbranch)",array("ou","FAIstate"));
736     while($attrs = $ldap->fetch()){
737       foreach($sub_releases as $sub_rel){
738         if(preg_match("/^".normalizePreg($sub_rel.get_ou('faiou'))."/",$attrs['dn'])){
739           $f_releases[$sub_rel.get_ou('faiou')] = $attrs;
740         }
741       }
742     }
744     /* Get all group releases */
745     $g_releases = array();
746     foreach($groups as $dn => $data){
747       $ldap->cd($dn);
748       $ldap->search("(objectClass=FAIbranch)",array("ou","FAIstate"));
749       while($attrs = $ldap->fetch()){
750         $g_releases[$attrs['dn']] = $attrs;
751       }
752     }
754     /* Check if base releases exists.
755        If they do not exist, create them and adapt FAIstate attribute from FAI releases. 
756      */
757     foreach($sub_releases as $name => $sub_rel){
759       $FAIstate = "";
760       if(isset($f_releases[$sub_rel.get_ou('faiou')]) && isset($f_releases[$sub_rel.get_ou('faiou')]['FAIstate'])){
761         $FAIstate = $f_releases[$sub_rel.get_ou('faiou')]['FAIstate'][0];
762       }
764       foreach($groups as $dn => $data){
765         if(!isset($g_releases[$sub_rel.$dn])){
766           $ldap->cd($dn);
767           $r_data = array();
768           $r_data['ou'] = $name;
769           $r_data['objectClass'] = array("top","organizationalUnit","FAIbranch");
770           if(!empty($FAIstate)) {
771             $r_data['FAIstate'] = $FAIstate;
772           }
773  
774           $ldap->cd($sub_rel.$dn) ;
775           $ldap->add($r_data);
776           echo "&nbsp;<b>"._("Object").":</b> ";
777           echo sprintf(_("Adding missing group application release container %s."),substr(LDAP::fix($sub_rel.$dn),0,96))."<br>";
778           flush();
779         }
780       }
781     } 
782  
783     /* Create new release container in each group.
784      */
785     $n_data = array();
786     $n_data = array();
787     $n_data['ou'] = $destination_name;
788     $n_data['objectClass'] = array("top","organizationalUnit","FAIbranch");
789     if(!empty($type)){
790       $n_data['FAIstate'] = $type;
791     }
793     foreach($groups as $dn => $att){
794       $n_dn = "ou=".$destination_name.",".$source_dn.$dn;
795       if(!isset($g_releases[$n_dn])){
796         $ldap->cd ($n_dn);
797         $ldap->add($n_data);
798         echo "&nbsp;<b>"._("Object").":</b> ";
799         echo sprintf(_("Adding group application release container %s."),substr(LDAP::fix($n_dn),0,96))."<br>";
800         flush();
801       }
802     }
804     /* If the source release is empty, then create a new release by copying 
805         all group application menus into a new ou=$destination_name release container.
806       
807        If the source release is not empty. 
808          We detect all releases which match the source release dn and copy the contents.
809      */
810     if(empty($source_release)){
811       $source_dns = $groups;
812     }else{
813       $source_dns = array();
814       foreach($g_releases as $dn => $data){
815         if(preg_match("/^".normalizePreg($source_dn)."/",$dn)){
816           $source_dns[$dn] = $data; 
817         }
818       }
819     }
821     /* Detect all menu object we have to copy 
822      */
823     $to_copy = array();
824     foreach($source_dns as $dn => $attrs){
825       $ldap->cd($dn);
826       $ldap->ls("(objectClass=gotoSubmenuEntry)(objectClass=gotoMenuEntry)",$dn,array("dn"));
827       while($attrs = $ldap->fetch()){
828         $destination = preg_replace("/".normalizePreg($dn)."$/","ou=".$destination_name.",".$dn,$attrs['dn']);
829         $to_copy[$attrs['dn']] = $destination;
830       }
831     }
832    
833     /* At least create the menu objects object */
834     $plug = new plugin($config);
835     foreach($to_copy as $source => $destination){
836       $ldap->cat($destination);
837       if($ldap->count()){
838         echo "&nbsp;<b>"._("Object").":</b> ";
839         echo sprintf(_("Could not create menu entry %s. (Already exists)."),substr(LDAP::fix($destination),0,96))."<br>";
840         flush();
841       }else{
842         $plug->copy($source,$destination);
843         echo "&nbsp;<b>"._("Object").":</b> ";
844         echo sprintf(_("Created group application menu entry for %s."),substr(LDAP::fix($destination),0,96))."<br>";
845         flush();
846       }
847     }
848   }
851   /*! \brief Create a new FAI branch.
852    *  @param $sourcedn          String  The source release dn
853    *  @param $destinationdn     String  The destination dn
854    *  @param $destinationName   String  The name of the new release
855    *  @param $type              String  The release type (freeze/branch)
856    *  @param $is_first          Boolean Use to identify the first func. call when recursivly called.
857    *  @param $depth             Integer Current depth of recursion.
858    */
859   function copy_FAI_resource_recursive($sourcedn,$destinationdn,$destinationName,$type="branch",$is_first = true,$depth=0)
860   {
861     global $config;
862     error_reporting(E_ALL | E_STRICT);
863     $ldap     = $config->get_ldap_link();
864     $basedn   = $config->current['BASE'];
865     $delarray = array();
867     /* The following code will output a status string
868      *  for each handled object, in a seperate iframe.
869      */
872     /* Display current action information.
873      */
874     if($is_first){
875       echo "<h2>".sprintf(_("Creating copy of %s"),"<i>".LDAP::fix($sourcedn)."</i>")."</h2>";
876     }else{
877       if(preg_match("/^ou=/",$sourcedn)){
878         echo "<h3>"._("Processing")." <i>".LDAP::fix($destinationdn)."</i></h3>";
879       }else{
880         $tmp = split(",",$sourcedn);
881         echo "&nbsp;<b>"._("Object").":</b> ";
882         $deststr = LDAP::fix($destinationdn);
883         if(strlen($deststr) > 96){
884           $deststr = substr($deststr,0,96)."...";
885         }
886         echo $deststr."<br>";
887       }
888     }
889     /* .. immediately display infos */
890     flush();
892     /* Check if destination entry already exists
893      */
894     $ldap->cat($destinationdn);
895     if($ldap->count()){
896       echo _("Could not create new release, the destination dn is already in use.");
897       return;
898     }else{
900       $ldap->clearResult();
902       /* Get source entry
903        *  if it does not exist, abort here.
904        */
905       $ldap->cd($basedn);
906       $ldap->cat($sourcedn);
907       $attr = $ldap->fetch();
908       if((!$attr) || (count($attr)) ==0) {
909         echo _("Error while fetching source dn - aborted!");
910         return;
911       }
913       /* The current object we want to create is an department.
914        * Create the department and add the FAIbranch tag.
915        */
916       if(in_array("organizationalUnit",$attr['objectClass'])){
917         $attr['dn'] = LDAP::convert($destinationdn);
918         $ldap->cd($basedn);
919         $ldap->create_missing_trees($destinationdn);
920         $ldap->cd($destinationdn);
922         /* If is first entry, append FAIbranch to department entry */
923         if($is_first){
924           $ldap->cat($destinationdn);
925           $attr= $ldap->fetch();
926           /* Filter unneeded informations */
927           foreach($attr as $key => $value){
928             if(is_numeric($key)) unset($attr[$key]);
929             if(isset($attr[$key]['count'])){
930               if(is_array($attr[$key])){
931                 unset($attr[$key]['count']);
932               }
933             }
934           }
936           unset($attr['count']);
937           unset($attr['dn']);
939           /* Add marking attribute */
940           $attr['objectClass'][] = "FAIbranch";
942           /* Add this entry */
943           $ldap->modify($attr);
944         }
945       }else{
947         /* Replicate all relevant FAI objects here.
948          * FAI objects, Apps and Mimetypes.
949          * Get all attributes as binary value, to ensure that Icon, File template aso
950          *  are created correctly.
951          */
952         foreach($attr as $key => $value){
954           if(in_array($key ,array("gotoLogonScript", "gosaApplicationIcon","gotoMimeIcon"))){
955             $sr= ldap_read($ldap->cid, LDAP::fix($sourcedn), "$key=*", array($key));
956             $ei= ldap_first_entry($ldap->cid, $sr);
957             if ($tmp= @ldap_get_values_len($ldap->cid, $ei,$key)){
958               $attr[$key] = $tmp;
959             }
960           }
962           if(is_numeric($key)) unset($attr[$key]);
963           if(isset($attr[$key]['count'])){
964             if(is_array($attr[$key])){
965               unset($attr[$key]['count']);
966             }
967           }
968         }
969         unset($attr['count']);
970         unset($attr['dn']);
972         /* Add entry
973          */
974         $ldap->cd($destinationdn);
975         $ldap->cat($destinationdn);
977         $a = $ldap->fetch();
978         if(!count($a)){
979           $ldap->add($attr);
980         }
982         if($ldap->error != "Success"){
984           /* Some error occurred */
985           print "---------------------------------------------";
986           print $ldap->get_error()."<br>";
987           print $sourcedn."<br>";
988           print $destinationdn."<br>";
989           print_a( $attr);
990           exit();
991         }
992       }
993     }
995     echo "<script language=\"javascript\" type=\"text/javascript\">scrollDown2();</script>" ;
997     /* Prepare for recursive copy.
998      * Get all object within the source dn and
999      *  call the recursive copy for each.
1000      */
1001     $ldap->ls ("(objectClass=*)",$sourcedn);
1002     while ($ldap->fetch()){
1003       $deldn= $ldap->getDN();
1004       $delarray[$deldn]= strlen($deldn);
1005     }
1006     asort ($delarray);
1007     reset ($delarray);
1008     $depth ++;
1009     foreach($delarray as $dn => $bla){
1010       if($dn != $destinationdn){
1011         $ldap->cd($basedn);
1012         $item = $ldap->fetch($ldap->cat($dn));
1013         if(!in_array("FAIbranch",$item['objectClass'])){
1014           FAI::copy_FAI_resource_recursive($dn,str_replace($sourcedn,$destinationdn,$dn),$destinationName,$type,false,$depth);
1015         }
1016       }
1017     }
1018     if($is_first){
1019       echo "<p class='seperator'>&nbsp;</p>";
1020     }
1021   }
1025   /* This function returns the dn of the object release */
1026   static function get_release_dn($Current_DN)
1027   {
1028     global $config;
1029     $ldap = $config->get_ldap_link();
1030     $ldap->cd($config->current['BASE']);
1032     /* Split dn into pices */ 
1033     $dns_to_check = gosa_ldap_explode_dn(preg_replace("/".normalizePreg(",".$config->current['BASE'])."/i","",$Current_DN));
1035     if(!is_array($dns_to_check)){
1036       return;  
1037     }
1039     /* Use dn pieces, to create sub dns like 
1040        ou=test,ou=1,ou=0...
1041        ou=1,ou=0...
1042        ou=0... 
1043        To check which dn is our release container.
1044      */
1045     unset($dns_to_check['count']); 
1046     while(count($dns_to_check)){
1048       /* Create dn */
1049       $new_dn = "";
1050       foreach($dns_to_check as $part){
1051         $new_dn .= $part.",";
1052       }
1053       $new_dn .= $config->current['BASE'];
1055       /* Check if this dn is a release dn */
1056       if(FAI::is_release_department($new_dn)){
1057         return($new_dn);
1058       }
1060       /* Remove first element of dn pieces */
1061       reset($dns_to_check);
1062       unset($dns_to_check[key($dns_to_check)]);
1063     }
1064     return("");
1065   }
1071 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1072 ?>