1fef153b638bc87723acf6a0508d7f0c0725b73e
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 }else{
163 /* If this is the last CLASS of a specific name (e.g. DEPOTSERVER)
164 we have to remove this name from all profiles in this release.
165 */
166 $ldap = $config->get_ldap_link();
167 $ldap->cd($config->current['BASE']);
168 $obj_dn = FAI::get_parent_release_object($Current_DN,TRUE);
170 /* Dont't try to modify non FAIclasses
171 */
172 if(!preg_match("/[^,]+,".normalizePreg(get_ou("faiou"))."/",$obj_dn)){
173 echo "PLEASE check fai class handling in ".__LINE__." -> ".__FILE__;
174 }else{
176 /* Get source object and check if it is a base FAIclass
177 */
178 $ldap->cat($obj_dn);
179 $attrs = $ldap->fetch();
180 $classes = array("FAIprofile","FAIscript","FAIpackage","FAIpartitionTable","FAIHook","FAIvariable","FAItemplate");
181 if(count(array_intersect($classes,$attrs['objectClass']))){
182 $cn = $attrs['cn'][0];
184 /* Check if this is the last with this name in the current release.
185 In this case we have to remove the package name
186 from all profiles in this release.
187 */
188 $classes = FAI::get_all_objects_for_given_base(FAI::get_release_dn($Current_DN),
189 "(&(objectClass=FAIclass)(cn=".$cn."))");
191 /* Check if this is the last class with this name.
192 */
193 if(count($classes) == 1){
195 /* Get all FAI Profiles
196 */
197 $profiles = FAI::get_all_objects_for_given_base(FAI::get_release_dn($Current_DN),
198 "(&(objectClass=FAIprofile)(FAIclass=*))");
200 /* Walk though all profiles and remove the source class name
201 */
202 foreach($profiles as $dn){
203 $ldap->cat($dn['dn']);
204 $attrs = $ldap->fetch();
206 $attrs = array('FAIclass' => $attrs['FAIclass'][0]);
208 /* Check if this Profile uses the source class ($cn)
209 */
210 if(preg_match("/".normalizePreg($cn)."/",$attrs['FAIclass'])){
211 $attrs['FAIclass'] = preg_replace("/[ ]*".normalizePreg($cn)."[ ]*/i"," ",$attrs['FAIclass']);
212 if(empty($attrs['FAIclass'])){
213 $attrs['FAIclass'] = array();
214 }
215 $ldap->cd($dn['dn']);
216 $ldap->modify($attrs);
218 if (!$ldap->success()){
219 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
220 }
221 }
222 }
223 }
224 }
225 }
226 }
230 $FAI_objects_to_save = session::get('FAI_objects_to_save') ;
231 $FAI_objects_to_save[$Current_DN] = $addObj;
232 session::set('FAI_objects_to_save',$FAI_objects_to_save);
233 }
236 /* Detect differences in attribute arrays */
237 static function array_diff_FAI($ar1,$ar2)
238 {
240 if((!isset($ar1['description'])) || (isset($ar1['description']) && (count($ar1['description']) == 0))){
241 $ar1['description'] = "";
242 }
243 if((!isset($ar2['description'])) || (isset($ar2['description']) && (count($ar2['description']) == 0))){
244 $ar2['description'] = "";
245 }
247 if(count($ar1) != count($ar2)) {
248 return (true);
249 }
251 foreach($ar1 as $key1 => $val1){
253 if((is_array($val1)) && (count($val1)==1)){
254 $ar1[$key1] = $val1[0];
255 }
257 if(isset($ar2[$key1])&& (is_array($ar2[$key1])) && (count($ar2[$key1])==1)){
258 $val1 = $val1[0];
259 $ar2[$key1] = $ar2[$key1][0];
260 }
261 }
262 ksort($ar1);
263 ksort($ar2);
264 if(count( array_diff($ar1,$ar2)) || FAI::arr_diff($ar1,$ar2)){
265 return(true);
266 }else{
267 return(false);
268 }
269 }
272 static function arr_diff($ar1,$ar2)
273 {
274 foreach($ar1 as $ak1 => $av1){
275 if(!isset($ar2[$ak1]) || (!($av1 === $ar2[$ak1]))){
276 return(true);
277 }elseif(is_array($av1)){
278 return(FAI::arr_diff($av1,$ar2[$ak1]));
279 }
280 }
281 return(FALSE);
282 }
287 /* check which objects must be saved, and save them */
288 static function save_release_changes_now()
289 {
290 /* Variable init*/
291 $to_save = array();
293 /* check which objects must be saved */
294 $FAI_objects_to_save = session::get('FAI_objects_to_save');
295 if(!is_array($FAI_objects_to_save)) {
296 trigger_error("Can't save FAI objects, no array given.");
297 return;
298 }
299 foreach($FAI_objects_to_save as $Current_DN => $object){
300 if($object['diff']){
301 $sub_name = $Current_DN;
302 while(isset($FAI_objects_to_save[$sub_name])){
303 $to_save[strlen($sub_name)][$sub_name] = $FAI_objects_to_save[$sub_name];
304 unset($FAI_objects_to_save[$sub_name]);
305 $sub_name = preg_replace('/^[^,]+,/', '', $sub_name);
306 }
307 }
308 }
309 session::set('FAI_objects_to_save',$FAI_objects_to_save);
311 /* Sort list of objects that must be saved, and ensure that
312 container objects are safed, before their childs are saved */
313 ksort($to_save);
314 $tmp = array();
315 foreach($to_save as $SubObjects){
316 foreach($SubObjects as $object){
317 $tmp[] = $object;
318 }
319 }
320 $to_save = $tmp;
322 /* Save objects and manage the correct release behavior*/
323 foreach($to_save as $save){
325 $Current_DN = $save['Current_DN'];
326 $removed = $save['removed'];
327 $objectAttrs= $save['objectAttrs'];
329 /* Get ldap object */
330 global $config;
331 $ldap = $config->get_ldap_link();
332 $ldap->cd($config->current['BASE']);
334 /* Get some basic informations */
335 $base_release = FAI::get_release_dn($Current_DN);
336 $sub_releases = FAI:: get_sub_releases_of_this_release($base_release,true);
337 $parent_obj = FAI::get_parent_release_object($Current_DN);
338 $following_releases = FAI:: get_sub_releases_of_this_release($base_release,true);
340 /* Check if given dn exists or if is a new entry */
341 $ldap->cat($Current_DN);
342 if(!$ldap->count()){
343 $is_new = true;
344 }else{
345 $is_new = false;
346 }
348 /* if parameter removed is true, we have to add FAIstate to the current attrs
349 FAIstate should end with ...|removed after this operation */
350 if($removed ){
351 $ldap->cat($Current_DN);
353 /* Get current object, because we must add the FAIstate ...|removed */
354 if((!$ldap->count()) && !empty($parent_obj)){
355 $ldap->cat($parent_obj);
356 }
358 /* Check if we have found a suiteable object */
359 if(!$ldap->count()){
360 echo "Error can't remove this object ".$Current_DN;
361 return;
362 }else{
364 /* Set FAIstate to current objectAttrs */
365 $objectAttrs = FAI:: prepare_ldap_fetch_to_be_saved($ldap->fetch());
366 if(isset($objectAttrs['FAIstate'][0])){
367 if(!preg_match("/removed$/",$objectAttrs['FAIstate'][0])){
368 $objectAttrs['FAIstate'][0] .= "|removed";
369 }
370 }else{
371 $objectAttrs['FAIstate'][0] = "|removed";
372 }
373 }
374 }
376 /* Check if this a leaf release or not */
377 if(count($following_releases) == 0 ){
379 /* This is a leaf object. It isn't inherited by any other object */
380 if(DEBUG_FAI_FUNC) {
381 echo "<b>Saving directly, is a leaf object</b><br> ".$Current_DN;
382 print_a($objectAttrs);
383 }
384 FAI::save_FAI_object($Current_DN,$objectAttrs);
385 }else{
387 /* This object is inherited by some sub releases */
389 /* Get all releases, that inherit this object */
390 $r = FAI::get_following_releases_that_inherit_this_object($Current_DN);
392 /* Get parent object */
393 $ldap->cat($parent_obj);
394 $parent_attrs = FAI::prepare_ldap_fetch_to_be_saved($ldap->fetch());
396 /* New objects require special handling */
397 if($is_new){
399 /* check if there is already an entry named like this,
400 in one of our parent releases */
401 if(!empty($parent_obj)){
402 if(DEBUG_FAI_FUNC) {
403 echo "There is already an entry named like this.</b><br>";
405 echo "<b>Saving main object</b>".$Current_DN;
406 print_a($objectAttrs);
407 }
408 FAI::save_FAI_object($Current_DN,$objectAttrs);
410 foreach($r as $key){
411 if(DEBUG_FAI_FUNC) {
412 echo "<b>Saving parent to following release</b> ".$key;
413 print_a($parent_attrs);
414 }
415 FAI::save_FAI_object($key,$parent_attrs);
416 }
417 }else{
419 if(DEBUG_FAI_FUNC) {
420 echo "<b>Saving main object</b>".$Current_DN;
421 print_a($objectAttrs);
422 }
423 FAI::save_FAI_object($Current_DN,$objectAttrs);
425 if(isset($objectAttrs['FAIstate'])){
426 $objectAttrs['FAIstate'] .= "|removed";
427 }else{
428 $objectAttrs['FAIstate'] = "|removed";
429 }
431 foreach($r as $key ){
432 if(DEBUG_FAI_FUNC) {
433 echo "<b>Create an empty placeholder in follwing release</b> ".$key;
434 print_a($objectAttrs);
435 }
436 FAI::save_FAI_object($key,$objectAttrs);
437 }
438 }
439 }else{
441 /* check if we must patch the follwing release */
442 if(!empty($r)){
443 foreach($r as $key ){
444 if(DEBUG_FAI_FUNC) {
445 echo "<b>Copy current objects original attributes to next release</b> ".$key;
446 print_a($parent_attrs);
447 }
448 FAI::save_FAI_object($key,$parent_attrs);
449 }
450 }
452 if(DEBUG_FAI_FUNC) {
453 echo "<b>Saving current object</b>".$parent_obj;
454 print_a($objectAttrs);
455 }
456 FAI::save_FAI_object($parent_obj,$objectAttrs);
458 if(($parent_obj != $Current_DN)){
459 msg_dialog::display(_("Error"), sprintf(_("Error, following objects should be equal '%s' and '%s'"),$parent_obj,$Current_DN), ERROR_DIALOG);
460 }
461 }
462 }
463 }
464 session::set('FAI_objects_to_save',array());
465 }
468 /* this function will remove all unused (deleted) objects,
469 that have no parent object */
470 static function clean_up_releases($Current_DN)
471 {
472 global $config;
473 $ldap = $config->get_ldap_link();
474 $ldap->cd($config->current['BASE']);
476 /* Collect some basic informations and initialize some variables */
477 $base_release = FAI::get_release_dn($Current_DN);
478 $previous_releases = array_reverse(FAI:: get_previous_releases_of_this_release($base_release,true));
479 $Kill = array();
480 $Skip = array();
482 /* We must also include the given release dn */
483 $previous_releases[] = $base_release;
485 /* Walk through all releases */
486 foreach($previous_releases as $release){
488 /* Get fai departments */
489 $deps_to_search = FAI::get_FAI_departments($release);
491 /* For every single department (ou=hoos,ou ..) */
492 foreach($deps_to_search as $fai_base){
494 /* Ldap search for fai classes specified in this release */
495 $ldap->cd($fai_base);
496 $ldap->search("(objectClass=FAIclass)",array("dn","objectClass","FAIstate"));
498 /* check the returned objects, and add/replace them in our return variable */
499 while($attr = $ldap->fetch()){
501 $buffer = array();
502 # $name = str_ireplace($release,"",$attr['dn']);
503 $name = preg_replace("/".normalizePreg($release)."/i","",$attr['dn']);
505 if(isset($attr['FAIstate'][0])&&(preg_match("/removed$/",$attr['FAIstate'][0]))){
507 /* Check if this object is required somehow */
508 if(!isset($Skip[$name])){
509 $Kill[$attr['dn']] = $attr['dn'];
510 }
511 }else{
513 /* This object is required (not removed), so do not
514 delete any following sub releases of this object */
515 $Skip[$name] = $attr['dn'];
516 }
517 }
518 }
519 }
520 return($Kill);
521 }
524 /* Remove numeric index and 'count' from ldap->fetch result */
525 static function prepare_ldap_fetch_to_be_saved($attrs)
526 {
527 foreach($attrs as $key => $value){
528 if(is_numeric($key) || ($key == "count") || ($key == "dn")){
529 unset($attrs[$key]);
530 }
531 if(is_array($value) && isset($value['count'])){
532 unset($attrs[$key]['count']);
533 }
534 }
535 return($attrs);
536 }
539 /* Save given attrs to specified dn*/
540 static function save_FAI_object($dn,$attrs)
541 {
542 global $config;
543 $ldap = $config->get_ldap_link();
544 $ldap->cd($config->current['BASE']);
545 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $dn));
546 $ldap->cd($dn);
548 $ldap->cat($dn,array("dn"));
549 if($ldap->count()){
551 /* Remove FAIstate*/
552 if(!isset($attrs['FAIstate'])){
553 $attrs['FAIstate'] = array();
554 }
556 $ldap->modify($attrs);
557 }else{
559 /* Unset description if empty */
560 if(empty($attrs['description'])){
561 unset($attrs['description']);
562 }
564 $ldap->add($attrs);
565 }
566 if (!$ldap->success()){
567 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, 0, get_class()));
568 }
569 }
572 /* Return FAIstate freeze branch or "" for specified release department */
573 static function get_release_tag($dn)
574 {
575 global $config;
576 $ldap = $config->get_ldap_link();
577 $ldap->cd($dn);
578 $ldap->cat($dn,array("FAIstate"));
580 if($ldap->count()){
582 $attr = $ldap->fetch();
583 if(isset($attr['FAIstate'][0])){
584 if(preg_match("/freeze/",$attr['FAIstate'][0])){
585 return("freeze");
586 }elseif(preg_match("/branch/",$attr['FAIstate'][0])){
587 return("branch");
588 }
589 }
590 }
591 return("");
592 }
595 static function get_following_releases_that_inherit_this_object($dn)
596 {
597 global $config;
598 $ldap = $config->get_ldap_link();
599 $ldap->cd($config->current['BASE']);
601 $ret = array();
603 /* Get base release */
604 $base_release = FAI::get_release_dn($dn);
606 /* Get previous release dns */
607 $sub_releases = FAI:: get_sub_releases_of_this_release($base_release);
609 /* Get dn suffix. Example "FAIvairableEntry=keksdose,FAIvariable=Keksregal," */
610 # $dn_suffix = str_ireplace($base_release,"",$dn);
611 $dn_suffix = preg_replace("/".normalizePreg($base_release)."/i","",$dn);
613 /* Check if given object also exists whitin one of these releases */
614 foreach($sub_releases as $p_release => $name){
616 $check_dn = $dn_suffix.$p_release;
618 $ldap->cat($check_dn,array("dn","objectClass"));
620 if($ldap->count()){
621 //return($ret);
622 }else{
623 $ret[$check_dn]=$check_dn;
624 }
625 }
626 return($ret);
627 }
630 /* Get previous version of the object dn */
631 static function get_parent_release_object($dn,$include_myself=true)
632 {
633 global $config;
634 $ldap = $config->get_ldap_link();
635 $ldap->cd($config->current['BASE']);
636 $previous_releases= array();
638 /* Get base release */
639 $base_release = FAI::get_release_dn($dn);
640 if($include_myself){
641 $previous_releases[] = $base_release;
642 }
644 /* Get previous release dns */
645 $tmp = FAI:: get_previous_releases_of_this_release($base_release,true);
646 foreach($tmp as $release){
647 $previous_releases[] = $release;
648 }
650 /* Get dn suffix. Example "FAIvairableEntry=keksdose,FAIvariable=Keksregal," */
651 # $dn_suffix = str_ireplace($base_release,"",$dn);
652 $dn_suffix = preg_replace("/".normalizePreg($base_release)."/i","",$dn);
654 /* Check if given object also exists whitin one of these releases */
655 foreach($previous_releases as $p_release){
656 $check_dn = $dn_suffix.$p_release;
657 $ldap->cat($check_dn,array("dn","objectClass"));
659 if($ldap->count()){
660 return($check_dn);
661 }
662 }
663 return("");
664 }
667 /* return release names of all parent releases */
668 static function get_previous_releases_of_this_release($dn,$flat)
669 {
670 global $config;
671 $ldap = $config->get_ldap_link();
672 $ldap->cd($config->current['BASE']);
673 $ret = array();
675 /* Explode dns into pieces, to be able to build parent dns */
676 $dns_to_check = gosa_ldap_explode_dn(preg_replace("/".normalizePreg(",".$config->current['BASE'])."/i","",$dn));
678 if(!is_array($dns_to_check)){
679 return;
680 }
682 /* Unset first entry which represents the given dn */
683 unset($dns_to_check['count']);
684 unset($dns_to_check[key($dns_to_check)]);
686 /* Create dns addresses and check if this dn is a release dn */
687 $id = 0;
688 while(count($dns_to_check)){
690 /* build parent dn */
691 $new_dn = "";
692 foreach($dns_to_check as $part){
693 $new_dn .= $part.",";
694 }
695 $new_dn .= $config->current['BASE'];
697 /* check if this dn is a release */
698 if(FAI::is_release_department($new_dn)){
699 if($flat){
700 $ret[$id] = $new_dn;
701 }else{
702 $ret = array($new_dn=>$ret);
703 }
704 $id ++;
705 }else{
706 return($ret);
707 }
708 reset($dns_to_check);
709 unset($dns_to_check[key($dns_to_check)]);
710 }
711 return($ret);
712 }
715 /* This function returns all sub release names, recursivly */
716 static function get_sub_releases_of_this_release($dn,$flat = false)
717 {
718 global $config;
719 $res = array();
720 $ldap = $config->get_ldap_link();
721 $ldap->cd($config->current['BASE']);
722 $ldap->ls("(objectClass=FAIbranch)",$dn,array("objectClass","dn","ou"));
723 while($attr = $ldap->fetch()){
725 /* Append department name */
726 if($flat){
727 $res[$attr['dn']] = $attr['ou'][0];
728 }else{
729 $res[$attr['dn']] = array();
730 }
732 /* Get sub release departments of this department */
733 if(in_array("FAIbranch",$attr['objectClass'])) {
734 if($flat){
735 $tmp = FAI:: get_sub_releases_of_this_release($attr['dn'],$flat);
736 foreach($tmp as $dn => $value){
737 $res[$dn]=$value;
738 }
739 }else{
740 $res[$attr['dn']] = FAI:: get_sub_releases_of_this_release($attr['dn']);
741 }
742 }
743 }
744 return($res);
745 }
748 /* Check if the given department is a release department */
749 static function is_release_department($dn)
750 {
751 global $config;
752 $ldap = $config->get_ldap_link();
753 $ldap->cd($config->current['BASE']);
754 $ldap->cat($dn,array("objectClass","ou"));
756 /* Check objectClasses and name to check if this is a release department */
757 if($ldap->count()){
758 $attrs = $ldap->fetch();
760 $ou = "";
761 if(isset($attrs['ou'][0])){
762 $ou = $attrs['ou'][0];
763 }
765 if((in_array("FAIbranch",$attrs['objectClass'])) || ($ou == "fai")){
766 return($attrs['dn']);
767 }
768 }
769 return(false);
770 }
773 static function copy_FAI_group_releases($source_release , $destination_name, $type ="" )
774 {
775 global $config;
776 $start = microtime(TRUE);
777 $source_release = trim($source_release,"/");
779 echo "<h2>".sprintf(_("Creating group application release for %s"),$destination_name)."</h2>";
781 $sub_releases = array();
782 $source_dn = "";
784 $tmp = split("\/",$source_release);
785 foreach($tmp as $part){
786 if(empty($part)){
787 continue;
788 }
789 $source_dn = "ou=".$part.",".$source_dn;
790 $sub_releases[$part] = $source_dn;
791 }
793 /* Get all groups */
794 $ldap =$config->get_ldap_link();
795 $ldap->cd($config->current['BASE']);
796 $ldap->search("(objectClass=posixGroup)",array("dn"));
797 $groups = array();
798 while($attrs = $ldap->fetch()){
799 $groups[$attrs['dn']] = $attrs;
800 }
802 /* Get all FAI releases, to be able to create missing group application releases
803 with the correct type of release (FAIstate=freeze/branch).
804 */
805 $f_releases = array();
806 $ldap->cd ($config->current['BASE']);
807 $ldap->search("(objectClass=FAIbranch)",array("ou","FAIstate"));
808 while($attrs = $ldap->fetch()){
809 foreach($sub_releases as $sub_rel){
810 if(preg_match("/^".normalizePreg($sub_rel.get_ou('faiou'))."/",$attrs['dn'])){
811 $f_releases[$sub_rel.get_ou('faiou')] = $attrs;
812 }
813 }
814 }
816 /* Get all group releases */
817 $g_releases = array();
818 foreach($groups as $dn => $data){
819 $ldap->cd($dn);
820 $ldap->search("(objectClass=FAIbranch)",array("ou","FAIstate"));
821 while($attrs = $ldap->fetch()){
822 $g_releases[$attrs['dn']] = $attrs;
823 }
824 }
826 /* Check if base releases exists.
827 If they do not exist, create them and adapt FAIstate attribute from FAI releases.
828 */
829 foreach($sub_releases as $name => $sub_rel){
831 $FAIstate = "";
832 if(isset($f_releases[$sub_rel.get_ou('faiou')]) && isset($f_releases[$sub_rel.get_ou('faiou')]['FAIstate'])){
833 $FAIstate = $f_releases[$sub_rel.get_ou('faiou')]['FAIstate'][0];
834 }
836 foreach($groups as $dn => $data){
837 if(!isset($g_releases[$sub_rel.$dn])){
838 $ldap->cd($dn);
839 $r_data = array();
840 $r_data['ou'] = $name;
841 $r_data['objectClass'] = array("top","organizationalUnit","FAIbranch");
842 if(!empty($FAIstate)) {
843 $r_data['FAIstate'] = $FAIstate;
844 }
846 $ldap->cd($sub_rel.$dn) ;
847 $ldap->add($r_data);
848 echo " <b>"._("Object").":</b> ";
849 echo sprintf(_("Adding missing group application release container %s."),substr(LDAP::fix($sub_rel.$dn),0,96))."<br>";
850 flush();
851 }
852 }
853 }
855 /* Create new release container in each group.
856 */
857 $n_data = array();
858 $n_data = array();
859 $n_data['ou'] = $destination_name;
860 $n_data['objectClass'] = array("top","organizationalUnit","FAIbranch");
861 if(!empty($type)){
862 $n_data['FAIstate'] = $type."/cow";
863 }
865 foreach($groups as $dn => $att){
866 $n_dn = "ou=".$destination_name.",".$source_dn.$dn;
867 if(!isset($g_releases[$n_dn])){
868 $ldap->cd ($n_dn);
869 $ldap->add($n_data);
870 echo " <b>"._("Object").":</b> ";
871 echo sprintf(_("Adding group application release container %s."),substr(LDAP::fix($n_dn),0,96))."<br>";
872 flush();
873 }
874 }
876 /* If the source release is empty, then create a new release by copying
877 all group application menus into a new ou=$destination_name release container.
879 If the source release is not empty.
880 We detect all releases which match the source release dn and copy the contents.
881 */
882 if(empty($source_release)){
883 $source_dns = $groups;
884 }else{
885 $source_dns = array();
886 foreach($g_releases as $dn => $data){
887 if(preg_match("/^".normalizePreg($source_dn)."/",$dn)){
888 $source_dns[$dn] = $data;
889 }
890 }
891 }
893 /* Detect all menu object we have to copy
894 */
895 $to_copy = array();
896 foreach($source_dns as $dn => $attrs){
897 $ldap->cd($dn);
898 $ldap->ls("(objectClass=gotoSubmenuEntry)(objectClass=gotoMenuEntry)",$dn,array("dn"));
899 while($attrs = $ldap->fetch()){
900 $destination = preg_replace("/".normalizePreg($dn)."$/","ou=".$destination_name.",".$dn,$attrs['dn']);
901 $to_copy[$attrs['dn']] = $destination;
902 }
903 }
905 /* At least create the menu objects object */
906 $plug = new plugin($config);
907 foreach($to_copy as $source => $destination){
908 $ldap->cat($destination);
909 if($ldap->count()){
910 echo " <b>"._("Object").":</b> ";
911 echo sprintf(_("Could not create menu entry %s. (Already exists)."),substr(LDAP::fix($destination),0,96))."<br>";
912 flush();
913 }else{
914 $plug->copy($source,$destination);
915 echo " <b>"._("Object").":</b> ";
916 echo sprintf(_("Created group application menu entry for %s."),substr(LDAP::fix($destination),0,96))."<br>";
917 flush();
918 }
919 }
920 }
923 /*! \brief Create a new FAI branch.
924 * @param $sourcedn String The source release dn
925 * @param $destinationdn String The destination dn
926 * @param $destinationName String The name of the new release
927 * @param $type String The release type (freeze/branch)
928 * @param $is_first Boolean Use to identify the first func. call when recursivly called.
929 * @param $depth Integer Current depth of recursion.
930 */
931 function copy_FAI_resource_recursive($sourcedn,$destinationdn,$destinationName,$type="branch",$is_first = true,$depth=0)
932 {
933 global $config;
934 error_reporting(E_ALL | E_STRICT);
935 $ldap = $config->get_ldap_link();
936 $basedn = $config->current['BASE'];
937 $delarray = array();
939 /* The following code will output a status string
940 * for each handled object, in a seperate iframe.
941 */
944 /* Display current action information.
945 */
946 if($is_first){
947 echo "<h2>".sprintf(_("Creating copy of %s"),"<i>".LDAP::fix($sourcedn)."</i>")."</h2>";
948 }else{
949 if(preg_match("/^ou=/",$sourcedn)){
950 echo "<h3>"._("Processing")." <i>".LDAP::fix($destinationdn)."</i></h3>";
951 }else{
952 $tmp = split(",",$sourcedn);
953 echo " <b>"._("Object").":</b> ";
954 $deststr = LDAP::fix($destinationdn);
955 if(strlen($deststr) > 96){
956 $deststr = substr($deststr,0,96)."...";
957 }
958 echo $deststr."<br>";
959 }
960 }
961 /* .. immediately display infos */
962 flush();
964 /* Check if destination entry already exists
965 */
966 $ldap->cat($destinationdn);
967 if($ldap->count()){
968 echo _("Could not create new release, the destination dn is already in use.");
969 return;
970 }else{
972 $ldap->clearResult();
974 /* Get source entry
975 * if it does not exist, abort here.
976 */
977 $ldap->cd($basedn);
978 $ldap->cat($sourcedn);
979 $attr = $ldap->fetch();
980 if((!$attr) || (count($attr)) ==0) {
981 echo _("Error while fetching source dn - aborted!");
982 return;
983 }
985 /* The current object we want to create is an department.
986 * Create the department and add the FAIbranch tag.
987 */
988 if(in_array("organizationalUnit",$attr['objectClass'])){
989 $attr['dn'] = LDAP::convert($destinationdn);
990 $ldap->cd($basedn);
991 $ldap->create_missing_trees($destinationdn);
992 $ldap->cd($destinationdn);
994 /* If is first entry, append FAIbranch to department entry */
995 if($is_first){
996 $ldap->cat($destinationdn);
997 $attr= $ldap->fetch();
998 /* Filter unneeded informations */
999 foreach($attr as $key => $value){
1000 if(is_numeric($key)) unset($attr[$key]);
1001 if(isset($attr[$key]['count'])){
1002 if(is_array($attr[$key])){
1003 unset($attr[$key]['count']);
1004 }
1005 }
1006 }
1008 unset($attr['count']);
1009 unset($attr['dn']);
1011 /* Add marking attribute */
1012 $attr['objectClass'][] = "FAIbranch";
1014 /* Add this entry */
1015 $ldap->modify($attr);
1016 }
1017 }else{
1019 /* Replicate all relevant FAI objects here.
1020 * FAI objects, Apps and Mimetypes.
1021 * Get all attributes as binary value, to ensure that Icon, File template aso
1022 * are created correctly.
1023 */
1024 foreach($attr as $key => $value){
1026 if(in_array($key ,array("gotoLogonScript", "gosaApplicationIcon","gotoMimeIcon"))){
1027 $sr= ldap_read($ldap->cid, LDAP::fix($sourcedn), "$key=*", array($key));
1028 $ei= ldap_first_entry($ldap->cid, $sr);
1029 if ($tmp= @ldap_get_values_len($ldap->cid, $ei,$key)){
1030 $attr[$key] = $tmp;
1031 }
1032 }
1034 if(is_numeric($key)) unset($attr[$key]);
1035 if(isset($attr[$key]['count'])){
1036 if(is_array($attr[$key])){
1037 unset($attr[$key]['count']);
1038 }
1039 }
1040 }
1041 unset($attr['count']);
1042 unset($attr['dn']);
1044 /* Add entry
1045 */
1046 $ldap->cd($destinationdn);
1047 $ldap->cat($destinationdn);
1049 $a = $ldap->fetch();
1050 if(!count($a)){
1051 $ldap->add($attr);
1052 }
1054 if(!$ldap->success()){
1056 /* Some error occurred */
1057 print "---------------------------------------------";
1058 print $ldap->get_error()."<br>";
1059 print $sourcedn."<br>";
1060 print $destinationdn."<br>";
1061 print_a( $attr);
1062 exit();
1063 }
1064 }
1065 }
1067 echo "<script language=\"javascript\" type=\"text/javascript\">scrollDown2();</script>" ;
1069 /* Prepare for recursive copy.
1070 * Get all object within the source dn and
1071 * call the recursive copy for each.
1072 */
1073 $ldap->ls ("(objectClass=*)",$sourcedn);
1074 while ($ldap->fetch()){
1075 $deldn= $ldap->getDN();
1076 $delarray[$deldn]= strlen($deldn);
1077 }
1078 asort ($delarray);
1079 reset ($delarray);
1080 $depth ++;
1081 foreach($delarray as $dn => $bla){
1082 if($dn != $destinationdn){
1083 $ldap->cd($basedn);
1084 $item = $ldap->fetch($ldap->cat($dn));
1085 if(!in_array("FAIbranch",$item['objectClass'])){
1086 FAI::copy_FAI_resource_recursive($dn,str_replace($sourcedn,$destinationdn,$dn),$destinationName,$type,false,$depth);
1087 }
1088 }
1089 }
1090 if($is_first){
1091 echo "<p class='seperator'> </p>";
1092 }
1093 }
1097 /* This function returns the dn of the object release */
1098 static function get_release_dn($Current_DN)
1099 {
1100 global $config;
1101 $ldap = $config->get_ldap_link();
1102 $ldap->cd($config->current['BASE']);
1104 /* Split dn into pices */
1105 $dns_to_check = gosa_ldap_explode_dn(preg_replace("/".normalizePreg(",".$config->current['BASE'])."/i","",$Current_DN));
1107 if(!is_array($dns_to_check)){
1108 return;
1109 }
1111 /* Use dn pieces, to create sub dns like
1112 ou=test,ou=1,ou=0...
1113 ou=1,ou=0...
1114 ou=0...
1115 To check which dn is our release container.
1116 */
1117 unset($dns_to_check['count']);
1118 while(count($dns_to_check)){
1120 /* Create dn */
1121 $new_dn = "";
1122 foreach($dns_to_check as $part){
1123 $new_dn .= $part.",";
1124 }
1125 $new_dn .= $config->current['BASE'];
1127 /* Check if this dn is a release dn */
1128 if(FAI::is_release_department($new_dn)){
1129 return($new_dn);
1130 }
1132 /* Remove first element of dn pieces */
1133 reset($dns_to_check);
1134 unset($dns_to_check[key($dns_to_check)]);
1135 }
1136 return("");
1137 }
1138 }
1143 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1144 ?>