e5d40a9808a9fbccc1222b2fe359d514b75a3807
1 <?php
3 define("DEBUG_FAI_FUNC",FALSE);
6 class FAI
7 {
9 /* TEST PHASE .... */
11 static function get_all_objects_for_given_object($dn,$filter,$detailed = false)
12 {
13 $res = FAI::get_all_objects_for_given_base($dn,$filter,$detailed);
14 $name = preg_replace("/,ou=.*$/","",$dn);
15 $entries = array();
16 foreach($res as $entry_dn => $data){
17 if(!preg_match("/,".$name.",/",$entry_dn)) continue;
18 $entries[$entry_dn] = $data;
19 }
20 return($entries);
21 }
26 /* Returns all object for the given release.
27 This function resolves the releases
28 from base up to the given dn.
29 */
30 static function get_all_objects_for_given_base($Current_DN,$filter,$detailed = false)
31 {
32 global $config;
33 $ldap = $config->get_ldap_link();
34 $ldap->cd($config->current['BASE']);
35 $res = array();
36 $tmp = array();
38 if(!FAI::is_release_department($Current_DN)) {
39 # return($res);
40 }
42 /* Collect some basic informations and initialize some variables */
43 $base_release = FAI::get_release_dn($Current_DN);
44 $previous_releases = array_reverse(FAI::get_previous_releases_of_this_release($base_release,true));
46 $ldap->cat($base_release);
47 $attrs = $ldap->fetch();
48 $FAIstate = "branch";
49 if(isset($attrs['FAIstate'][0])){
50 $FAIstate = $attrs['FAIstate'][0];
51 }
53 /* We must also include the given release dn */
54 $previous_releases[] = $base_release;
56 /* Walk through all releases */
57 foreach($previous_releases as $release){
59 /* Get fai departments */
60 $deps_to_search = FAI::get_FAI_departments($release);
62 /* For every single department (ou=hoos,ou ..) */
63 foreach($deps_to_search as $fai_base){
65 /* Ldap search for fai classes specified in this release */
66 $attributes = array("dn","objectClass","FAIstate","cn","FAIdiskType","FAIlvmDevice","FAIdiskOption");
67 $res_tmp = get_list($filter,"fai",$fai_base,$attributes,GL_SUBSEARCH);
69 /* check the returned objects, and add/replace them in our return variable */
70 foreach($res_tmp as $attr){
72 $buffer = array();
73 $name = preg_replace("/".preg_quote($release, '/')."/i","",$attr['dn']);
75 if(isset($attr['FAIstate'][0])){
76 if(preg_match("/removed$/",$attr['FAIstate'][0])){
77 if(isset($res[$name])){
78 unset($res[$name]);
79 }
80 continue;
81 }
82 }
84 /* Seems to be an inherited class, apply current FAIstate to this classes
85 */
86 if(!preg_match("/".preg_quote($base_release, '/')."$/i",$attr['dn'])){
87 $buffer['FAIstate'] = $FAIstate;
88 }else{
90 /* Seems to be created within this release department.
91 This indicates - it can't be of state "freeze"
92 */
93 if(isset($attr['FAIstate'])){
94 $buffer['FAIstate'] = $attr['FAIstate'][0];
95 }else{
96 $buffer['FAIstate'] = "branch";
97 }
98 }
100 if(isset($attr['FAIdiskType'])){
101 $buffer['FAIdiskType'] = $attr['FAIdiskType'][0];
102 } else {
103 $buffer['FAIdiskType'] = "old";
104 }
106 if(isset($attr['FAIdiskOption'])){
107 $buffer['FAIdiskOption'] = $attr['FAIdiskOption'];
108 } else {
109 $buffer['FAIdiskOption'] = null;
110 }
111 if(isset($attr['FAIlvmDevice'])){
112 $buffer['FAIlvmDevice'] = $attr['FAIlvmDevice'];
113 }
115 /* In detailed mode are some additonal informations visible */
116 if($detailed){
118 /* Create list of parents */
119 if(isset($res[$name])){
120 $buffer = $res[$name];
121 $buffer['parents'][] = $res[$name]['dn'];
122 }else{
123 $buffer['parents'] = array();
124 }
126 /* Append objectClass to resulsts */
127 foreach($attributes as $val){
128 if(isset($attr[$val])){
129 $buffer[$val] = $attr[$val];
130 }
131 }
132 unset($buffer['objectClass']['count']);
133 }
135 /* Add this object to our list */
136 $buffer['dn'] = $attr['dn'];
137 $res[$name] = $buffer;
138 }
139 }
140 }
141 return($res);
142 }
145 /* Return all relevant FAI departments */
146 static function get_FAI_departments($suffix = "")
147 {
148 global $config;
149 $arr = array(
150 get_ou('faiScript', 'faiScriptRDN'),
151 get_ou('faiHook', 'faiHookRDN'),
152 get_ou('faiTemplate', 'faiTemplateRDN'),
153 get_ou('faiVariable', 'faiVariableRDN'),
154 get_ou('faiProfile', 'faiProfileRDN'),
155 get_ou('faiPartitionTable', 'faiPartitionRDN'),
156 get_ou('faiPackage', 'faiPackageRDN')
157 );
159 $tmp = array();
160 if(preg_match("/^,/",$suffix)){
161 $suffix = preg_replace("/^,/","",$suffix);
162 }
163 foreach($arr as $name){
164 if(empty($suffix)){
165 $tmp[$name] = $name;
166 }else{
167 $tmp[$name] = $name.$suffix;
168 }
169 }
170 return($tmp);
171 }
174 /* Return all releases within the given base */
175 static function get_all_releases_from_base($dn,$appendedName=false)
176 {
177 global $config;
179 if(!preg_match("/".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/')."/i",$dn)){
180 $base = get_ou("faiManagement", "faiBaseRDN").$dn;
181 }else{
182 $base = $dn;
183 }
184 $res = array();
186 $ldap = $config->get_ldap_link();
187 $ldap->cd($base);
188 $ldap->search("(objectClass=FAIbranch)",array("ou","dn"));
189 while($attrs = $ldap->fetch()){
190 if($appendedName){
191 $res[$attrs['dn']] = convert_department_dn(preg_replace("/,".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/').".*$/i","",$attrs['dn']));
192 }else{
193 $res[$attrs['dn']] = $attrs['ou'][0];
194 }
195 }
196 return($res);
197 }
200 /* Add this object to list of objects, that must be checked for release saving */
201 static function prepare_to_save_FAI_object($Current_DN,$objectAttrs,$removed = false)
202 {
203 /* Get ldap object */
204 global $config;
205 $addObj['Current_DN'] = $Current_DN;
206 $addObj['objectAttrs']= $objectAttrs;
207 $addObj['removed'] = $removed;
208 $addObj['diff'] = TRUE;
210 if(!$removed){
211 $ldap = $config->get_ldap_link();
212 $ldap->cd($config->current['BASE']);
214 /* Get some basic informations */
215 $parent_obj = FAI::get_parent_release_object($Current_DN);
216 if(!empty($parent_obj)){
217 $ldap->cat($parent_obj,array("*"));
218 $attrs = FAI:: prepare_ldap_fetch_to_be_saved($ldap->fetch());
220 if(!FAI::array_diff_FAI( $attrs,$objectAttrs)){
221 $addObj['diff'] = FALSE;
222 }
223 }
224 }else{
226 /* If this is the last CLASS of a specific name (e.g. DEPOTSERVER)
227 we have to remove this name from all profiles in this release.
228 */
229 $ldap = $config->get_ldap_link();
230 $ldap->cd($config->current['BASE']);
231 $obj_dn = FAI::get_parent_release_object($Current_DN,TRUE);
233 /* Dont't try to modify non FAIclasses
234 */
235 if(!preg_match("/[^,]+,".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/')."/i",$obj_dn)){
236 trigger_error("PLEASE check fai class handling in ".__LINE__." -> ".__FILE__);
237 echo "<br>-->".$Current_DN."<br>";
238 echo "<br>-->".$obj_dn."<br>";
239 }else{
241 /* Get source object and check if it is a base FAIclass
242 */
243 $ldap->cat($obj_dn);
244 $attrs = $ldap->fetch();
245 $classes = array("FAIprofile","FAIscript","FAIpackageList","FAIpartitionTable","FAIHook","FAIvariable","FAItemplate");
246 if(count(array_intersect($classes,$attrs['objectClass']))){
247 $cn = $attrs['cn'][0];
249 /* Check if this is the last with this name in the current release.
250 In this case we have to remove the package name
251 from all profiles in this release.
252 */
253 $classes = FAI::get_all_objects_for_given_base(FAI::get_release_dn($Current_DN),
254 "(&(objectClass=FAIclass)(cn=".$cn."))");
256 /* Check if this is the last class with this name */
257 if(count($classes) == 1){
259 /* Get all FAI Profiles
260 */
261 $profiles = FAI::get_all_objects_for_given_base(FAI::get_release_dn($Current_DN),
262 "(&(objectClass=FAIprofile)(FAIclass=*))");
264 /* Walk though all profiles and remove the source class name
265 */
266 foreach($profiles as $dn){
267 $ldap->cat($dn['dn']);
268 $attrs = $ldap->fetch();
270 $attrs = array('FAIclass' => $attrs['FAIclass'][0]);
272 /* Check if this Profile uses the source class ($cn)
273 */
274 $classlist = split(" ", $attrs['FAIclass']);
275 $new_classlist = "";
276 foreach($classlist as $class){
277 if($class != $cn){
278 $new_classlist = $new_classlist." ".$class;
279 }
280 }
281 $attrs['FAIclass'] = $new_classlist;
282 if(empty($attrs['FAIclass'])){
283 $attrs['FAIclass'] = array();
284 }
285 $ldap->cd($dn['dn']);
286 $ldap->modify($attrs);
287 if (!$ldap->success()){
288 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
289 }
290 }
291 }
292 }
293 }
294 }
298 $FAI_objects_to_save = session::get('FAI_objects_to_save') ;
299 $FAI_objects_to_save[$Current_DN] = $addObj;
300 session::set('FAI_objects_to_save',$FAI_objects_to_save);
301 }
304 /* Detect differences in attribute arrays */
305 static function array_diff_FAI($ar1,$ar2)
306 {
308 if((!isset($ar1['description'])) || (isset($ar1['description']) && (count($ar1['description']) == 0))){
309 $ar1['description'] = "";
310 }
311 if((!isset($ar2['description'])) || (isset($ar2['description']) && (count($ar2['description']) == 0))){
312 $ar2['description'] = "";
313 }
315 if(count($ar1) != count($ar2)) {
316 return (true);
317 }
319 foreach($ar1 as $key1 => $val1){
321 if((is_array($val1)) && (count($val1)==1)){
322 $ar1[$key1] = $val1[0];
323 }
325 if(isset($ar2[$key1])&& (is_array($ar2[$key1])) && (count($ar2[$key1])==1)){
326 $val1 = $val1[0];
327 $ar2[$key1] = $ar2[$key1][0];
328 }
329 }
330 ksort($ar1);
331 ksort($ar2);
332 if(count( array_diff($ar1,$ar2)) || FAI::arr_diff($ar1,$ar2)){
333 return(true);
334 }else{
335 return(false);
336 }
337 }
340 static function arr_diff($ar1,$ar2)
341 {
342 foreach($ar1 as $ak1 => $av1){
343 if(!isset($ar2[$ak1]) || (!($av1 === $ar2[$ak1]))){
344 return(TRUE);
345 }elseif(is_array($av1)){
346 $ret = (FAI::arr_diff($av1,$ar2[$ak1]));
347 if($ret) {
348 return(TRUE);
349 }
350 }
351 }
352 return(FALSE);
353 }
358 /* check which objects must be saved, and save them */
359 static function save_release_changes_now()
360 {
361 global $config;
362 /* Variable init*/
363 $to_save = array();
365 $reload_fai_classes = FALSE;
367 /* check which objects must be saved */
368 if(!session::is_set('FAI_objects_to_save')){
369 return;
370 }
371 $FAI_objects_to_save = session::get('FAI_objects_to_save');
372 if(!is_array($FAI_objects_to_save)) {
373 print_a(array(session::get('FAI_objects_to_save')));
374 trigger_error("Can't save FAI objects, no array given.");
375 return;
376 }
378 foreach($FAI_objects_to_save as $Current_DN => $object){
379 if($object['diff']){
380 $sub_name = $Current_DN;
381 while(isset($FAI_objects_to_save[$sub_name])){
382 $to_save[strlen($sub_name)][$sub_name] = $FAI_objects_to_save[$sub_name];
383 unset($FAI_objects_to_save[$sub_name]);
384 $sub_name = preg_replace('/^[^,]+,/', '', $sub_name);
385 }
386 }
387 }
388 session::set('FAI_objects_to_save',$FAI_objects_to_save);
390 /* Sort list of objects that must be saved, and ensure that
391 container objects are safed, before their childs are saved */
392 ksort($to_save);
393 $tmp = array();
394 foreach($to_save as $SubObjects){
395 foreach($SubObjects as $object){
396 $tmp[] = $object;
397 }
398 }
399 $to_save = $tmp;
402 /* Save objects and manage the correct release behavior*/
403 foreach($to_save as $save){
405 $Current_DN = $save['Current_DN'];
406 $removed = $save['removed'];
407 $objectAttrs= $save['objectAttrs'];
409 /* Get ldap object */
410 $ldap = $config->get_ldap_link();
411 $ldap->cd($config->current['BASE']);
413 /* Get some basic informations */
414 $base_release = FAI::get_release_dn($Current_DN);
415 $sub_releases = FAI::get_sub_releases_of_this_release($base_release,true);
416 $parent_obj = FAI::get_parent_release_object($Current_DN);
417 $following_releases = $sub_releases;
419 /* Check if given dn exists or if is a new entry */
420 $ldap->cat($Current_DN);
421 if(!$ldap->count()){
422 $is_new = true;
423 }else{
424 $is_new = false;
425 }
427 /* if parameter removed is true, we have to add FAIstate to the current attrs
428 FAIstate should end with ...|removed after this operation */
429 if($removed ){
430 $ldap->cat($Current_DN);
432 /* Get current object, because we must add the FAIstate ...|removed */
433 if((!$ldap->count()) && !empty($parent_obj)){
434 $ldap->cat($parent_obj);
435 }
437 /* Check if we have found a suiteable object */
438 if(!$ldap->count()){
439 echo "Error can't remove this object ".$Current_DN;
440 return;
441 }else{
443 /* Set FAIstate to current objectAttrs */
444 $objectAttrs = FAI:: prepare_ldap_fetch_to_be_saved($ldap->fetch());
445 if(isset($objectAttrs['FAIstate'][0])){
446 if(!preg_match("/removed$/",$objectAttrs['FAIstate'][0])){
447 $objectAttrs['FAIstate'][0] .= "|removed";
448 }
449 }else{
450 $objectAttrs['FAIstate'][0] = "|removed";
451 }
453 /* Force reload of FAI classes */
454 $classes = array("FAIprofile","FAIscript","FAIpackageList","FAIpartitionTable","FAIHook","FAIvariable","FAItemplate");
455 if(count(array_intersect($classes,$objectAttrs['objectClass']))){
456 $reload_fai_classes = TRUE;
457 }
458 }
459 }
461 /* Check if this a leaf release or not */
462 if(count($following_releases) == 0 ){
464 /* This is a leaf object. It isn't inherited by any other object */
465 if(DEBUG_FAI_FUNC) {
466 echo "<b>Saving directly, is a leaf object</b><br> ".$Current_DN;
467 print_a($objectAttrs);
468 }
469 FAI::save_FAI_object($Current_DN,$objectAttrs);
471 /* Force reload of FAI classes */
472 $classes = array("FAIprofile","FAIscript","FAIpackageList","FAIpartitionTable","FAIHook","FAIvariable","FAItemplate");
473 if(count(array_intersect($classes,$objectAttrs['objectClass']))){
474 $reload_fai_classes = TRUE;
475 }
477 }else{
479 /* This object is inherited by some sub releases */
481 /* Get all releases, that inherit this object */
482 $r = FAI::get_following_releases_that_inherit_this_object($Current_DN);
484 /* Get parent object */
485 $ldap->cat($parent_obj);
486 $parent_attrs = FAI::prepare_ldap_fetch_to_be_saved($ldap->fetch());
488 /* New objects require special handling */
489 if($is_new){
491 /* Force reload of FAI classes */
492 $classes = array("FAIprofile","FAIscript","FAIpackageList","FAIpartitionTable","FAIHook","FAIvariable","FAItemplate");
493 if(count(array_intersect($classes,$objectAttrs['objectClass']))){
494 $reload_fai_classes = TRUE;
495 }
497 /* check if there is already an entry named like this,
498 in one of our parent releases */
499 if(!empty($parent_obj)){
500 if(DEBUG_FAI_FUNC) {
501 echo "There is already an entry named like this.</b><br>";
503 echo "<b>Saving main object</b>".$Current_DN;
504 print_a($objectAttrs);
505 }
506 FAI::save_FAI_object($Current_DN,$objectAttrs);
508 foreach($r as $key){
509 if(DEBUG_FAI_FUNC) {
510 echo "<b>Saving parent to following release</b> ".$key;
511 print_a($parent_attrs);
512 }
513 FAI::save_FAI_object($key,$parent_attrs);
514 }
515 }else{
517 if(DEBUG_FAI_FUNC) {
518 echo "<b>Saving main object</b>".$Current_DN;
519 print_a($objectAttrs);
520 }
521 FAI::save_FAI_object($Current_DN,$objectAttrs);
523 if(isset($objectAttrs['FAIstate'])){
524 $objectAttrs['FAIstate'] .= "|removed";
525 }else{
526 $objectAttrs['FAIstate'] = "|removed";
527 }
529 foreach($r as $key ){
530 if(DEBUG_FAI_FUNC) {
531 echo "<b>Create an empty placeholder in follwing release</b> ".$key;
532 print_a($objectAttrs);
533 }
534 FAI::save_FAI_object($key,$objectAttrs);
535 }
536 }
537 }else{
539 /* check if we must patch the follwing release */
540 if(!empty($r)){
542 foreach($r as $key ){
543 if(DEBUG_FAI_FUNC) {
544 echo "<b>Copy current objects original attributes to next release</b> ".$key;
545 print_a($parent_attrs);
546 }
548 /* Append FAIstate tag to ensure that freezed objects stay freezed
549 */
550 $rTag = FAI::get_release_tag(FAI::get_release_dn($key));
551 $parent_attrs['FAIstate'] = $rTag;
553 /* FAItemplateFile can be binary, therefore it needs to be fetched with
554 * $ldap->get_attribute */
555 if (isset($parent_attrs['FAItemplateFile'])) {
556 $parent_attrs['FAItemplateFile'] = $ldap->get_attribute($parent_obj, 'FAItemplateFile');
557 }
559 FAI::save_FAI_object($key,$parent_attrs);
560 }
561 }
563 if(DEBUG_FAI_FUNC) {
564 echo "<b>Saving current object</b>".$parent_obj;
565 print_a($objectAttrs);
566 }
567 FAI::save_FAI_object($parent_obj,$objectAttrs);
569 if(($parent_obj != $Current_DN)){
570 msg_dialog::display(_("Error"), sprintf(_("Error, following objects should be equal '%s' and '%s'"),$parent_obj,$Current_DN), ERROR_DIALOG);
571 }
572 }
573 }
574 }
576 /* Reload GOsa si FAI DB/cache
577 */
578 if($reload_fai_classes){
579 if( class_available("DaemonEvent") && class_available("gosaSupportDaemon")){
580 $events = DaemonEvent::get_event_types(SYSTEM_EVENT | HIDDEN_EVENT);
581 if(isset($events['TRIGGERED']['DaemonEvent_recreate_fai_release_db'])){
582 $evt = $events['TRIGGERED']['DaemonEvent_recreate_fai_release_db'];
583 $tmp = new $evt['CLASS_NAME']($config);
584 $tmp->set_type(TRIGGERED_EVENT);
585 $tmp->add_targets(array("GOSA"));
586 $o_queue = new gosaSupportDaemon();
587 if(!$o_queue->append($tmp)){
588 msg_dialog::display(_("Service infrastructure"),msgPool::siError($o_queue->get_error()),ERROR_DIALOG);
589 }
590 }
591 }
592 }
594 session::set('FAI_objects_to_save',array());
595 }
598 /* this function will remove all unused (deleted) objects,
599 that have no parent object */
600 static function clean_up_releases($Current_DN)
601 {
602 global $config;
603 $ldap = $config->get_ldap_link();
604 $ldap->cd($config->current['BASE']);
606 /* Collect some basic informations and initialize some variables */
607 $base_release = FAI::get_release_dn($Current_DN);
608 $previous_releases = array_reverse(FAI:: get_previous_releases_of_this_release($base_release,true));
609 $Kill = array();
610 $Skip = array();
612 /* We must also include the given release dn */
613 $previous_releases[] = $base_release;
615 /* Walk through all releases */
616 foreach($previous_releases as $release){
618 /* Get fai departments */
619 $deps_to_search = FAI::get_FAI_departments($release);
621 /* For every single department (ou=hoos,ou ..) */
622 foreach($deps_to_search as $fai_base){
624 /* Ldap search for fai classes specified in this release */
625 $ldap->cd($fai_base);
626 $ldap->search("(objectClass=FAIclass)",array("dn","objectClass","FAIstate"));
628 /* check the returned objects, and add/replace them in our return variable */
629 while($attr = $ldap->fetch()){
631 $buffer = array();
632 # $name = str_ireplace($release,"",$attr['dn']);
633 $name = preg_replace("/".preg_quote($release, '/')."/i","",$attr['dn']);
635 if(isset($attr['FAIstate'][0])&&(preg_match("/removed$/",$attr['FAIstate'][0]))){
637 /* Check if this object is required somehow */
638 if(!isset($Skip[$name])){
639 $Kill[$attr['dn']] = $attr['dn'];
640 }
641 }else{
643 /* This object is required (not removed), so do not
644 delete any following sub releases of this object */
645 $Skip[$name] = $attr['dn'];
646 }
647 }
648 }
649 }
650 return($Kill);
651 }
654 /* Remove numeric index and 'count' from ldap->fetch result */
655 static function prepare_ldap_fetch_to_be_saved($attrs)
656 {
657 foreach($attrs as $key => $value){
658 if(is_numeric($key) || ($key == "count") || ($key == "dn")){
659 unset($attrs[$key]);
660 }
661 if(is_array($value) && isset($value['count'])){
662 unset($attrs[$key]['count']);
663 }
664 }
665 return($attrs);
666 }
669 /* Save given attrs to specified dn*/
670 static function save_FAI_object($dn,$attrs)
671 {
672 global $config;
673 $ldap = $config->get_ldap_link();
674 $ldap->cd($config->current['BASE']);
675 $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $dn));
676 $ldap->cd($dn);
678 $ldap->cat($dn,array("dn"));
679 if($ldap->count()){
681 /* Remove FAIstate*/
682 if(!isset($attrs['FAIstate'])){
683 $attrs['FAIstate'] = array();
684 }
686 $ldap->modify($attrs);
687 }else{
689 /* Unset description if empty */
690 if(empty($attrs['description'])){
691 unset($attrs['description']);
692 }
694 $ldap->add($attrs);
695 }
696 if (!$ldap->success()){
697 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, 0, get_class()));
698 }
699 }
702 /* Return FAIstate freeze branch or "" for specified release department */
703 static function get_release_tag($dn)
704 {
705 global $config;
706 $ldap = $config->get_ldap_link();
707 $ldap->cd($dn);
708 $ldap->cat($dn,array("FAIstate"));
710 if($ldap->count()){
712 $attr = $ldap->fetch();
713 if(isset($attr['FAIstate'][0])){
714 if(preg_match("/freeze/",$attr['FAIstate'][0])){
715 return("freeze");
716 }elseif(preg_match("/branch/",$attr['FAIstate'][0])){
717 return("branch");
718 }
719 }
720 }
721 return("");
722 }
725 static function get_following_releases_that_inherit_this_object($dn)
726 {
727 global $config;
728 $ldap = $config->get_ldap_link();
729 $ldap->cd($config->current['BASE']);
731 $ret = array();
733 /* Get base release */
734 $base_release = FAI::get_release_dn($dn);
736 /* Get previous release dns */
737 $sub_releases = FAI:: get_sub_releases_of_this_release($base_release);
739 /* Get dn suffix. Example "FAIvairableEntry=keksdose,FAIvariable=Keksregal," */
740 # $dn_suffix = str_ireplace($base_release,"",$dn);
741 $dn_suffix = preg_replace("/".preg_quote($base_release, '/')."/i","",$dn);
743 /* Check if given object also exists whitin one of these releases */
744 foreach($sub_releases as $p_release => $name){
746 $check_dn = $dn_suffix.$p_release;
748 $ldap->cat($check_dn,array("dn","objectClass"));
750 if($ldap->count()){
751 //return($ret);
752 }else{
753 $ret[$check_dn]=$check_dn;
754 }
755 }
756 return($ret);
757 }
760 /* Get previous version of the object dn */
761 static function get_parent_release_object($dn,$include_myself=true)
762 {
763 global $config;
764 $ldap = $config->get_ldap_link();
765 $ldap->cd($config->current['BASE']);
766 $previous_releases= array();
768 /* Get base release */
769 $base_release = FAI::get_release_dn($dn);
770 if($include_myself){
771 $previous_releases[] = $base_release;
772 }
774 /* Get previous release dns */
775 $tmp = FAI:: get_previous_releases_of_this_release($base_release,true);
776 foreach($tmp as $release){
777 $previous_releases[] = $release;
778 }
780 /* Get dn suffix. Example "FAIvairableEntry=keksdose,FAIvariable=Keksregal," */
781 # $dn_suffix = str_ireplace($base_release,"",$dn);
782 $dn_suffix = preg_replace("/".preg_quote($base_release, '/')."/i","",$dn);
784 /* Check if given object also exists whitin one of these releases */
785 foreach($previous_releases as $p_release){
786 $check_dn = $dn_suffix.$p_release;
787 $ldap->cat($check_dn,array("dn","objectClass"));
789 if($ldap->count()){
790 return($check_dn);
791 }
792 }
793 return("");
794 }
797 /* return release names of all parent releases */
798 static function get_previous_releases_of_this_release($dn,$flat)
799 {
800 global $config;
801 $ldap = $config->get_ldap_link();
802 $ldap->cd($config->current['BASE']);
803 $ret = array();
805 /* Explode dns into pieces, to be able to build parent dns */
806 $dns_to_check = gosa_ldap_explode_dn(preg_replace("/".preg_quote(",".$config->current['BASE'], '/')."/i","",$dn));
808 if(!is_array($dns_to_check)){
809 return;
810 }
812 /* Unset first entry which represents the given dn */
813 unset($dns_to_check['count']);
814 unset($dns_to_check[key($dns_to_check)]);
816 /* Create dns addresses and check if this dn is a release dn */
817 $id = 0;
818 while(count($dns_to_check)){
820 /* build parent dn */
821 $new_dn = "";
822 foreach($dns_to_check as $part){
823 $new_dn .= $part.",";
824 }
825 $new_dn .= $config->current['BASE'];
827 /* check if this dn is a release */
828 if(FAI::is_release_department($new_dn)){
829 if($flat){
830 $ret[$id] = $new_dn;
831 }else{
832 $ret = array($new_dn=>$ret);
833 }
834 $id ++;
835 }else{
836 return($ret);
837 }
838 reset($dns_to_check);
839 unset($dns_to_check[key($dns_to_check)]);
840 }
841 return($ret);
842 }
845 /* This function returns all sub release names, recursivly */
846 static function get_sub_releases_of_this_release($dn,$flat = false)
847 {
848 global $config;
849 $res = array();
850 $ldap = $config->get_ldap_link();
851 $ldap->cd($config->current['BASE']);
852 $ldap->ls("(objectClass=FAIbranch)",$dn,array("objectClass","dn","ou"));
853 while($attr = $ldap->fetch()){
855 /* Append department name */
856 if($flat){
857 $res[$attr['dn']] = $attr['ou'][0];
858 }else{
859 $res[$attr['dn']] = array();
860 }
862 /* Get sub release departments of this department */
863 if(in_array("FAIbranch",$attr['objectClass'])) {
864 if($flat){
865 $tmp = FAI:: get_sub_releases_of_this_release($attr['dn'],$flat);
866 foreach($tmp as $dn => $value){
867 $res[$dn]=$value;
868 }
869 }else{
870 $res[$attr['dn']] = FAI:: get_sub_releases_of_this_release($attr['dn']);
871 }
872 }
873 }
874 return($res);
875 }
878 /* Check if the given department is a release department */
879 static function is_release_department($dn)
880 {
881 global $config;
882 $ldap = $config->get_ldap_link();
883 $ldap->cd($config->current['BASE']);
884 $ldap->cat($dn,array("objectClass","ou"));
886 /* Check objectClasses and name to check if this is a release department */
887 if($ldap->count()){
888 $attrs = $ldap->fetch();
890 $ou = "";
891 if(isset($attrs['ou'][0])){
892 $ou = $attrs['ou'][0];
893 }
895 if((in_array("FAIbranch",$attrs['objectClass'])) || ($ou == "fai")){
896 return($attrs['dn']);
897 }
898 }
899 return(false);
900 }
903 static function copy_FAI_group_releases($source_release , $destination_name, $type ="" )
904 {
905 global $config;
906 $start = microtime(TRUE);
907 $source_release = trim($source_release,"/");
909 echo "<h3>".sprintf(_("Creating group application release for %s"),$destination_name)."</h3>";
911 $sub_releases = array();
912 $source_dn = "";
914 $tmp = explode("/",$source_release);
915 foreach($tmp as $part){
916 if(empty($part)){
917 continue;
918 }
919 $source_dn = "ou=".$part.",".$source_dn;
920 $sub_releases[$part] = $source_dn;
921 }
923 /* Get all groups */
924 $ldap =$config->get_ldap_link();
925 $ldap->cd($config->current['BASE']);
926 $ldap->search("(objectClass=posixGroup)",array("dn"));
927 $groups = array();
928 while($attrs = $ldap->fetch()){
929 $groups[$attrs['dn']] = $attrs;
930 }
932 /* Get all FAI releases, to be able to create missing group application releases
933 with the correct type of release (FAIstate=freeze/branch).
934 */
935 $f_releases = array();
936 $ldap->cd ($config->current['BASE']);
937 $ldap->search("(objectClass=FAIbranch)",array("ou","FAIstate"));
938 while($attrs = $ldap->fetch()){
939 foreach($sub_releases as $sub_rel){
940 if(preg_match("/^".preg_quote($sub_rel.get_ou("faiManagement", "faiBaseRDN"), '/')."/i",$attrs['dn'])){
941 $f_releases[$sub_rel.get_ou("faiManagement", "faiBaseRDN")] = $attrs;
942 }
943 }
944 }
946 /* Get all group releases */
947 $g_releases = array();
948 foreach($groups as $dn => $data){
949 $ldap->cd($dn);
950 $ldap->search("(objectClass=FAIbranch)",array("ou","FAIstate"));
951 while($attrs = $ldap->fetch()){
952 $g_releases[$attrs['dn']] = $attrs;
953 }
954 }
956 /* Check if base releases exists.
957 If they do not exist, create them and adapt FAIstate attribute from FAI releases.
958 */
959 foreach($sub_releases as $name => $sub_rel){
961 $FAIstate = "";
962 if(isset($f_releases[$sub_rel.get_ou("faiManagement", "faiBaseRDN")]) && isset($f_releases[$sub_rel.get_ou("faiManagement", "faiBaseRDN")]['FAIstate'])){
963 $FAIstate = $f_releases[$sub_rel.get_ou("faiManagement", "faiBaseRDN")]['FAIstate'][0];
964 }
966 foreach($groups as $dn => $data){
967 if(!isset($g_releases[$sub_rel.$dn])){
968 $ldap->cd($dn);
969 $r_data = array();
970 $r_data['ou'] = $name;
971 $r_data['objectClass'] = array("top","organizationalUnit","FAIbranch");
972 if(!empty($FAIstate)) {
973 $r_data['FAIstate'] = $FAIstate;
974 }
976 $ldap->cd($sub_rel.$dn) ;
977 $ldap->add($r_data);
978 echo " <b>"._("Object").":</b> ";
979 echo sprintf(_("Adding missing group application release container %s."),substr(LDAP::fix($sub_rel.$dn),0,96))."<br>";
980 flush();
981 }
982 }
983 }
985 /* Create new release container in each group.
986 */
987 $n_data = array();
988 $n_data = array();
989 $n_data['ou'] = $destination_name;
990 $n_data['objectClass'] = array("top","organizationalUnit","FAIbranch");
991 if(!empty($type)){
992 $n_data['FAIstate'] = $type."/cow";
993 }
995 foreach($groups as $dn => $att){
996 $n_dn = "ou=".$destination_name.",".$source_dn.$dn;
997 if(!isset($g_releases[$n_dn])){
998 $ldap->cd ($n_dn);
999 $ldap->add($n_data);
1000 echo " <b>"._("Object").":</b> ";
1001 echo sprintf(_("Adding group application release container %s."),substr(LDAP::fix($n_dn),0,96))."<br>";
1002 flush();
1003 }
1004 }
1006 /* If the source release is empty, then create a new release by copying
1007 all group application menus into a new ou=$destination_name release container.
1009 If the source release is not empty.
1010 We detect all releases which match the source release dn and copy the contents.
1011 */
1012 if(empty($source_release)){
1013 $source_dns = $groups;
1014 }else{
1015 $source_dns = array();
1016 foreach($g_releases as $dn => $data){
1017 if(preg_match("/^".preg_quote($source_dn, '/')."/",$dn)){
1018 $source_dns[$dn] = $data;
1019 }
1020 }
1021 }
1023 /* Detect all menu object we have to copy
1024 */
1025 $to_copy = array();
1026 foreach($source_dns as $dn => $attrs){
1027 $ldap->cd($dn);
1028 $ldap->ls("(|(objectClass=gotoSubmenuEntry)(objectClass=gotoMenuEntry))",$dn,array("dn"));
1029 while($attrs = $ldap->fetch()){
1030 $destination = preg_replace("/".preg_quote($dn, '/')."$/","ou=".$destination_name.",".$dn,$attrs['dn']);
1031 $to_copy[$attrs['dn']] = $destination;
1032 }
1033 }
1035 /* At least create the menu objects object */
1036 $plug = new plugin($config);
1037 foreach($to_copy as $source => $destination){
1038 $ldap->cat($destination);
1039 if($ldap->count()){
1040 echo " <b>"._("Object").":</b> ";
1041 echo sprintf(_("Could not create menu entry %s. (Already exists)."),substr(LDAP::fix($destination),0,96))."<br>";
1042 flush();
1043 }else{
1044 $plug->copy($source,$destination);
1045 echo " <b>"._("Object").":</b> ";
1046 echo sprintf(_("Created group application menu entry for %s."),substr(LDAP::fix($destination),0,96))."<br>";
1047 flush();
1048 }
1049 }
1050 }
1053 /*! \brief Create a new FAI branch.
1054 * @param $sourcedn String The source release dn
1055 * @param $destinationdn String The destination dn
1056 * @param $destinationName String The name of the new release
1057 * @param $type String The release type (freeze/branch)
1058 * @param $is_first Boolean Use to identify the first func. call when recursivly called.
1059 * @param $depth Integer Current depth of recursion.
1060 */
1061 static function copy_FAI_resource_recursive($sourcedn,$destinationdn,$destinationName,$type="branch",$is_first = true,$depth=0)
1062 {
1063 global $config;
1064 error_reporting(E_ALL | E_STRICT);
1065 $ldap = $config->get_ldap_link();
1066 $basedn = $config->current['BASE'];
1067 $delarray = array();
1069 /* The following code will output a status string
1070 * for each handled object, in a seperate iframe.
1071 */
1074 /* Display current action information.
1075 */
1076 if($is_first){
1077 echo "<h3>".sprintf(_("Creating copy of %s"),"<i>".LDAP::fix($sourcedn)."</i>")."</h3>";
1078 }else{
1079 if(preg_match("/^ou=/",$sourcedn)){
1080 echo "<h3>"._("Processing")." <i>".LDAP::fix($destinationdn)."</i></h3>";
1081 }else{
1082 $tmp = explode(",",$sourcedn);
1083 echo " <b>"._("Object").":</b> ";
1084 $deststr = LDAP::fix($destinationdn);
1085 if(strlen($deststr) > 96){
1086 $deststr = substr($deststr,0,96)."...";
1087 }
1088 echo $deststr."<br>";
1089 }
1090 }
1091 /* .. immediately display infos */
1092 flush();
1094 /* Check if destination entry already exists
1095 */
1096 $ldap->cat($destinationdn);
1097 if($ldap->count()){
1098 echo _("Could not create new release, the destination DN is already in use.");
1099 return;
1100 }else{
1102 $ldap->clearResult();
1104 /* Get source entry
1105 * if it does not exist, abort here.
1106 */
1107 $ldap->cd($basedn);
1108 $ldap->cat($sourcedn);
1109 $attr = $ldap->fetch();
1110 if((!$attr) || (count($attr)) ==0) {
1111 echo _("Error while fetching source DN - aborted!");
1112 return;
1113 }
1115 /* The current object we want to create is an department.
1116 * Create the department and add the FAIbranch tag.
1117 */
1118 if(in_array("organizationalUnit",$attr['objectClass'])){
1119 $attr['dn'] = LDAP::convert($destinationdn);
1120 $ldap->cd($basedn);
1121 $ldap->create_missing_trees($destinationdn);
1122 $ldap->cd($destinationdn);
1124 /* If is first entry, append FAIbranch to department entry */
1125 if($is_first){
1126 $ldap->cat($destinationdn);
1127 $attr= $ldap->fetch();
1128 /* Filter unneeded informations */
1129 foreach($attr as $key => $value){
1130 if(is_numeric($key)) unset($attr[$key]);
1131 if(isset($attr[$key]['count'])){
1132 if(is_array($attr[$key])){
1133 unset($attr[$key]['count']);
1134 }
1135 }
1136 }
1138 unset($attr['count']);
1139 unset($attr['dn']);
1141 /* Add marking attribute */
1142 $attr['objectClass'][] = "FAIbranch";
1143 $attr['FAIstate'] = $type;
1145 /* Add this entry */
1146 $ldap->modify($attr);
1147 }
1148 }else{
1150 /* Replicate all relevant FAI objects here.
1151 * FAI objects, Apps and Mimetypes.
1152 * Get all attributes as binary value, to ensure that Icon, File template aso
1153 * are created correctly.
1154 */
1155 foreach($attr as $key => $value){
1157 if(in_array($key ,array("gotoLogonScript", "gosaApplicationIcon","gotoMimeIcon"))){
1158 $sr= ldap_read($ldap->cid, LDAP::fix($sourcedn), "$key=*", array($key));
1159 $ei= ldap_first_entry($ldap->cid, $sr);
1160 if ($tmp= @ldap_get_values_len($ldap->cid, $ei,$key)){
1161 $attr[$key] = $tmp;
1162 }
1163 }
1165 if(is_numeric($key)) unset($attr[$key]);
1166 if(isset($attr[$key]['count'])){
1167 if(is_array($attr[$key])){
1168 unset($attr[$key]['count']);
1169 }
1170 }
1171 }
1172 unset($attr['count']);
1173 unset($attr['dn']);
1174 if(!in_array("FAIobject",$attr['objectClass'])){
1175 $attr['objectClass'][] = "FAIobject";
1176 }
1177 $attr['FAIstate'] = $type;
1179 /* Add entry
1180 */
1181 $ldap->cd($destinationdn);
1182 $ldap->cat($destinationdn);
1184 $a = $ldap->fetch();
1185 if(!count($a)){
1186 $ldap->add($attr);
1187 }
1189 if(!$ldap->success()){
1191 /* Some error occurred */
1192 msg_dialog::display(_("Fatal error"),
1193 sprintf(_("Release creation failed due to LDAP errors: %s"),
1194 $ldap->get_error()."<br>".$sourcedn."<br>".$destinationdn."<br>"),FATAL_ERROR_DIALOG);
1195 exit();
1196 }
1197 }
1198 }
1200 echo "<script language=\"javascript\" type=\"text/javascript\">scrollDown2();</script>" ;
1202 /* Prepare for recursive copy.
1203 * Get all object within the source dn and
1204 * call the recursive copy for each.
1205 */
1206 $ldap->ls ("(objectClass=*)",$sourcedn);
1207 while ($ldap->fetch()){
1208 $deldn= $ldap->getDN();
1209 $delarray[$deldn]= strlen($deldn);
1210 }
1211 asort ($delarray);
1212 reset ($delarray);
1213 $depth ++;
1214 foreach($delarray as $dn => $bla){
1215 if($dn != $destinationdn){
1216 $ldap->cd($basedn);
1217 $item = $ldap->fetch($ldap->cat($dn));
1218 if(!in_array("FAIbranch",$item['objectClass'])){
1219 FAI::copy_FAI_resource_recursive($dn,str_replace($sourcedn,$destinationdn,$dn),$destinationName,$type,false,$depth);
1220 }
1221 }
1222 }
1223 if($is_first){
1224 echo "<hr>";
1225 }
1226 }
1230 /* This function returns the dn of the object release */
1231 static function get_release_dn($Current_DN)
1232 {
1233 global $config;
1234 $ldap = $config->get_ldap_link();
1235 $ldap->cd($config->current['BASE']);
1237 /* Split dn into pices */
1238 $dns_to_check = gosa_ldap_explode_dn(preg_replace("/".preg_quote(",".$config->current['BASE'], '/')."/i","",$Current_DN));
1240 if(!is_array($dns_to_check)){
1241 return;
1242 }
1244 /* Use dn pieces, to create sub dns like
1245 ou=test,ou=1,ou=0...
1246 ou=1,ou=0...
1247 ou=0...
1248 To check which dn is our release container.
1249 */
1250 unset($dns_to_check['count']);
1251 while(count($dns_to_check)){
1253 /* Create dn */
1254 $new_dn = "";
1255 foreach($dns_to_check as $part){
1256 $new_dn .= $part.",";
1257 }
1258 $new_dn .= $config->current['BASE'];
1260 /* Check if this dn is a release dn */
1261 if(FAI::is_release_department($new_dn)){
1262 return($new_dn);
1263 }
1265 /* Remove first element of dn pieces */
1266 reset($dns_to_check);
1267 unset($dns_to_check[key($dns_to_check)]);
1268 }
1269 return("");
1270 }
1271 }
1276 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1277 ?>