Code

c420d22243d5f78bdd956cd6dd4e43a5dfcc6150
[gosa.git] / gosa-plugins / fai / admin / fai / class_faiManagement.inc
1 <?php
2 /*
3  * This code is part of GOsa (http://www.gosa-project.org)
4  * Copyright (C) 2003-2008 GONICUS GmbH
5  *
6  * ID: $$Id: class_faiManagement.inc 14742 2009-11-04 13:18:33Z hickert $$
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
23 class faiManagement extends management
24 {
25   var $plHeadline     = "Software deployment";
26   var $plDescription  = "Manage software packages and deployment recipes for Windows and Linux systems";
27   var $plIcon  = "plugins/fai/images/plugin.png";
29   // Tab definition 
30   protected $tabClass = "";
31   protected $tabType = "";
32   protected $aclCategory = "";
33   protected $aclPlugin   = "";
34   protected $objectName   = "FAI object";
35   protected $releaseSelector = NULL;
37   //  Attributes Managed by this plugin can be used in post events
38   public $attributes   = array("lock_type","lock_name","lock_dn");  
40   var $dispNewBranch=false;
41   var $dispNewFreeze=false;
43   var $fai_release = ""; // The currently selected release while in release management mode!
44   var $fai_base = ""; 
45   var $acl_base = ""; 
47   var $lock_type = "";
48   var $lock_dn = "";
49   var $lock_name = "";
51   var $opsi = NULL;
54   function __construct($config,$ui)
55   {
56     $this->config = $config;
58     /* Check if the opsi plugin is installed.
59      */
60     if(class_available("opsi")){
61       $this->opsi = new opsi($this->config);;
62     }
64     $this->fai_base = get_ou("faiManagement", "faiBaseRDN").$this->config->current['BASE'];
65     $cfg_rel = $this->config->get_cfg_value("faiManagement","defaultFaiRelease");
67     if(!empty($cfg_rel)){
68       $this->fai_release = $cfg_rel;
69     }else{
70       $this->fai_release = $this->fai_base;
71     }
73     $releases = $this->getReleaseList();
74     if(!isset($releases[$this->fai_release])){
75       $this->fai_release = $this->fai_base;
76     }
78     $this->acl_base = $this->config->current['BASE'];
79     $this->ui = $ui;
80     $this->storagePoints = array(
81         get_ou("faiPartitionTable", "faiPartitionRDN"),
82         get_ou("faiPackage", "faiPackageRDN"),
83         get_ou("faiScript", "faiScriptRDN"),
84         get_ou("faiVariable", "faiVariableRDN"),
85         get_ou("faiHook", "faiHookRDN"),
86         get_ou("faiProfile", "faiProfileRDN"),
87         get_ou("faiTemplate", "faiTemplateRDN"));
89     // Build filter
90     if (session::global_is_set(get_class($this)."_filter")){
91       $filter= session::global_get(get_class($this)."_filter");
92     } else {
93       $filter = new filter(get_template_path("fai-filter.xml", true));
94       $filter->setObjectStorage($this->storagePoints);
95     }
96     $filter->elementValues['RELEASE'] = $this->fai_release;
97     $this->setFilter($filter);
99     // Build headpage
100     $headpage = new listing(get_template_path("fai-list.xml", true));
101     $headpage->setFilter($filter);
102     $headpage->setBase($this->fai_release);
103     $headpage->registerElementFilter("filterProperties", "faiManagement::filterProperties");
105     // Add copy&paste and snapshot handler.
106     if ($this->config->boolValueIsTrue("core", "copyPaste")){
107       $this->cpHandler = new CopyPasteHandler($this->config);
108     }
110     $this->registerAction("remove_multiple","removeEntryRequested");
111     $this->registerAction("new_profile","newEntry");
112     $this->registerAction("new_template","newEntry");
113     $this->registerAction("new_script","newEntry");
114     $this->registerAction("new_hook","newEntry");
115     $this->registerAction("new_variable","newEntry");
116     $this->registerAction("new_package","newEntry");
117     $this->registerAction("new_partition","newEntry");
118     $this->registerAction("newClassNameSelected","newClassNameSelected");
119     $this->registerAction("saveOpsiProperties","saveOpsiProperties");
120     $this->registerAction("editByGroup","editByGroup");
121     $this->registerAction("createBranch","createBranch");
122     $this->registerAction("createFreeze","createFreeze");
123     $this->registerAction("removeBranch","removeBranch");
124     $this->registerAction("removeBranchConfirmed","removeBranchConfirmed");
125     $this->registerAction("saveBranch","saveBranch");
126     $this->registerAction("PerformBranch","PerformBranch");
128     $releases = $this->getReleaseStates($this->config,$this->fai_base);
129     $this->releaseSelector = new releaseSelector($releases, $this->fai_release, $this->fai_base);
130     parent::__construct($config, $ui, "FAI object", $headpage);
131   }
134   /*! \brief  Act on copy & paste actions here.
135    */
136   function copyPasteHandler($action="",$target=array(),$all=array(),$altTabClass ="",$altTabType="",$altAclCategory="",$altAclPlugin="")
137   {
138     // Collect real dns, the listed objects are grouped by their cn
139     $headpage = $this->getHeadpage();
140     if($action == "copy"){
142       if(count($target) == 1){
144         // We just want to copy a single FAI object, let the user choose entries from the FAI-Group
145         $entry = $headpage->getEntry($target[0]);
146         if(count($entry['GROUPS']) == 1){
147           $data = array_pop($entry['GROUPS']);
148           $type = $this->get_type($data);
149           $this->cpHandler->add_to_queue($data['dn'],"copy",$type[0],$type[2],'fai',$this);
150           @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$g['dn'],"Entry copied!");
151         }else{
152           $this->dialogObject = new faiGroupHandle($entry['GROUPS'],"copy");
153         }
154         
155       }else{
157         // More than one group was selected, expect that the user wants to copy the complete groups.
158         foreach($target as $t){
159           $entry = $headpage->getEntry($t);
161           // Check for valid FAI objects
162           if(in_array('FAKE_OC_FAI', $entry['objectClass'])){
163             foreach($entry['GROUPS'] as $g){
164               $type = $this->get_type($g);
165               $this->cpHandler->add_to_queue($g['dn'],"copy",$type[0],$type[2],'fai',$this);
166               @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$g['dn'],"Entry copied!");
167             }
168           }
169         }
170       }
171     }
173     // Initiate pasting
174     if($action == "paste"){
175       $this->cpPastingStarted = TRUE;
176     }
178     // Display any c&p dialogs, eg. object modifications required before pasting.
179     if($this->cpPastingStarted && $this->cpHandler->entries_queued()){
180       $this->cpHandler->SetVar("base",$headpage->getBase());
181       $data = $this->cpHandler->execute();
182       FAI::save_release_changes_now();
183       if(!empty($data)){
184         return($data);
185       }
186     }
188     // Automatically disable pasting process since there is no entry left to paste.
189     if(isset($this->cpHandler) && !$this->cpHandler->entries_queued()){
190       $this->cpPastingStarted = FALSE;
191     }
192     return("");
193   }
196   /*! \brief  A new FAI object was requested, let the user specify a name theis object now. 
197    */
198   function newEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
199   {
200     $types = array( 
201         "new_partition"     =>  "FAIpartitionTable",
202         "new_script"        =>  "FAIscript",
203         "new_hook"          =>  "FAIhook",
204         "new_variable"      =>  "FAIvariable",
205         "new_template"      =>  "FAItemplate",
206         "new_package"       =>  "FAIpackageList");
207     $types_i18n = array( 
208         "new_partition"     =>  _("partition table"),
209         "new_script"        =>  _("script"),
210         "new_hook"          =>  _("hook"),
211         "new_variable"      =>  _("variable"),
212         "new_template"      =>  _("template"),
213         "new_package"       =>  _("package list"));
215     if(isset($types[$action])){
216       $type_acl_mapping = array(
217           "FAIpartitionTable"  => "faiPartitionTable",
218           "FAIpackageList"     => "faiPackage",
219           "FAIscript"          => "faiScript",
220           "FAIvariable"        => "faiVariable",
221           "FAIhook"            => "faiHook",
222           "FAIprofile"         => "faiProfile",
223           "FAItemplate"        => "faiTemplate");
225       $acl = $this->ui->get_permissions($this->acl_base,"fai/".$type_acl_mapping[$types[$action]]);
226       if(preg_match("/c/",$acl)){
227         $this->dialogObject = new askClassName($this->config,$this->dn,$this->ui,$types[$action]);
228         $this->dialogObject->parent = &$this;
229       }else{
230         msg_dialog::display(_("Permission error"), 
231             sprintf(_("You have no permission to create a new %s!"), $types_i18n[$action]),      ERROR_DIALOG);
232       }
233     }
234     if($action == "new_profile"){
235       $this->dn = "new" ;
237       $acl = $this->ui->get_permissions($this->acl_base,"fai/faiProfile");
238       if(preg_match("/c/",$acl)){
239         $type= $this->get_type(array("objectClass"=>array("FAIprofile")));
240         $str= management::newEntry('newEntry',array(),array(),$type[0],$type[2],'fai');
241         if($str) return($str);
242         $this->tabObject->set_acl_base($this->acl_base);
243       }else{
244         msg_dialog::display(_("Permission error"), sprintf(_("You have no permission to create a new %s!"), _("profile")), ERROR_DIALOG);
245       }
246     }
247   }
250   /*! \brief   A new FAI class was requested and the user had a specify a name for it.
251    *           Here we check if this name is useable and then open the edit dialogs.
252    */
253   function newClassNameSelected()
254   {
255     $this->dialogObject->save_object();
256     if(count($this->dialogObject->check())!=0){
257       foreach($this->dialogObject->check() as $msg){
258         msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
259       }
260     }elseif(isset($this->dialogObject->objectClass)){
261       $this->dn = "new" ;
262       $type= $this->get_type(array("objectClass"=>array($this->dialogObject->objectClass)));
263       $name = $this->dialogObject->save();
265       if(class_exists($type[0])){
266         $this->closeDialogs();
267         $str = management::newEntry('newEntry',array(),array(),$type[0],$type[2],"fai");
268         if($str) return($str);
269         $this->tabObject->set_acl_base($this->acl_base);
270         $this->tabObject->by_object[$type[1]]->cn = $name;
271       }
272     }
273   }
276   /*! \brief   Edit the selected entry.
277    *           If there was a FAI group clicked, display a dialog with all members of the group.
278    */
279   function editEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
280   {
281     $headpage = $this->getHeadpage();
282     if(count($target) == 1){
283       $entry = $headpage->getEntry($target[0]);
284       if($entry){
286         // Edit Opsi objects here 
287         if(in_array("opsi_local", $entry['TYPES']) || in_array("opsi_netboot", $entry['TYPES'])){ 
288           $name = $entry['cn'];
289           $cfg = $this->opsi->get_product_properties($name);
291           $str = management::editEntry('editEntry',array($name),array(),'tabs_opsiProdConfig','OPSIPRODCONFIG','opsi');
292           if($str) return($str);
293           if(isset($this->tabObject->by_object['opsiProperties'])){
294             $this->tabObject->by_object['opsiProperties']->set_cfg($cfg);
295             $this->tabObject->by_object['opsiProperties']->set_product($name);
296             $this->skipFooter = TRUE;
297           }else{
298             trigger_error("Unknown tab, please check config.");
299           }
301         }else{
303           // Edit FAI objects here 
304           if(count($entry['GROUPS']) == 1){
305             $data = array_pop($entry['GROUPS']);
306             $type = $this->get_type($data);
307             $str = management::editEntry('editEntry',array($data['dn']),array(),$type[0],$type[2],"fai");
308             if($str) return($str);
309             $this->tabObject->by_object[$type[1]]->FAIstate = $data['FAIstate'];
310             $this->tabObject->read_only = preg_match("/freeze/i", $data['FAIstate']);
312           }else{
313             $this->dialogObject = new faiGroupHandle($entry['GROUPS'],"edit");
314           }
315         }
316       }
317     }
318   }
321   /*! \brief   Save changes made in opsi dialogs.
322    */
323   function saveOpsiProperties()
324   {
325     if($this->tabObject instanceof tabs_opsiProdConfig && isset($_POST['save_properties'])){
326       $this->tabObject->save_object();
327       $op    = $this->tabObject->by_object['opsiProperties'];
328       $name  = $op->get_product();
329       $cfg   = $op->get_cfg();
330       $this->opsi->set_product_properties($name,$cfg);
331       if($this->opsi->is_error()){
332         msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG);
333       }else{
334         $this->remove_lock();
335         $this->closeDialogs();
336       }
337     }
338   }
341   /*! \brief   Someone wants to remove some object(s)
342    *            ask for a confirmation now.
343    */
344   function removeEntryRequested($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
345   {
346     $this->closeDialogs();
347     if($action == "remove_multiple"){
349       // Collect objects to delete
350       $headpage = $this->getHeadpage();
351       $to_delete = array();
352       foreach($target as $id){
353         $object = $headpage->getEntry($id);
354         if(in_array("FAKE_OC_FAI", $object['objectClass'])){
355           foreach($object['GROUPS']  as $entry){
356             array_push($to_delete, $entry);
357           }
358         }
359       }
360       return($this->removeFAIObjects($to_delete));
361     }else{
363       // Try to remove a single object, only FAI objects can be removed!
364       $headpage = $this->getHeadpage();
365       if(count($target) == 1){
366         $entry = $headpage->getEntry($target[0]);
367         if($entry && in_array("FAKE_OC_FAI",$entry['objectClass'])){
368           $this->dialogObject = new faiGroupHandle($entry['GROUPS'],"remove");
369         }
370       }
371     }
372   }
375   /*! \brief   Someone wants to remove some object(s)
376    *            ask for a confirmation now.
377    */
378   function removeFAIObjects($to_delete)
379   {
380     // Close dialogs and remove locks for currently handled dns
381     $this->cancelEdit();
383     // Do not allow to remove objects with state freeezed
384     $errors = $disallowed = array();
385   
386     foreach($to_delete as $obj){
387       $type = $this->get_type($obj);
388       $acl  = $this->ui->get_permissions($obj['dn'],"fai/".$type[1]);
389       if(!preg_match("/d/",$acl)){
390         $disallowed[] = $obj['dn'];
391       }elseif(isset($obj['FAIstate']) && preg_match('/^freeze/', $obj['FAIstate'])){
392         $errors[] = $obj['dn'];
393       }else{
394         $this->dns[] = $obj['dn'];
395       }
396     }
397     if(count($errors)){
398       msg_dialog::display(_("Branch locked"),
399           sprintf(_("The following entries are locked, you can't remove them %s."),msgPool::buildList($errors)),INFO_DIALOG);
400     }
401     if(count($disallowed)){ 
402       msg_dialog::display(_("Permission error"), msgPool::permDelete($disallowed), ERROR_DIALOG);
403     }
405     // Check entry locking
406     $smarty = get_smarty();
407     if(count($this->dns)){
408       if ($user= get_multiple_locks($this->dns)){
409         return(gen_locked_message($user,$this->dns));
410       }
411       if(count($this->dns)){
413         // Add locks
414         $dns_names = array();
415         $types = array();
416         $h = $this->getHeadpage();
418         // Build list of object -labels
419         foreach($h->objectTypes as $type){
420           $map[$type['objectClass']]= $type['label'];
421         }
423         foreach($this->dns as $dn){
424           $tmp = $h->getType($dn);
425           if(isset($map[$tmp])){
426             $dns_names[] = '('._($map[$tmp]).')&nbsp;-&nbsp;'.LDAP::fix($dn);
427           }else{
428             $dns_names[] =LDAP::fix($dn);
429           }
430         }
431         add_lock ($this->dns, $this->ui->dn);
433         $smarty->assign("info",msgPool::deleteInfo($dns_names));
434         return($smarty->fetch(get_template_path('removeEntries.tpl')));
435       }
436     }
437   }
440   /*! \brief   Entry removal is confirmed, now remove objects
441    */
442   function removeEntryConfirmed($action="",$target=array(),$all=array(),
443       $altTabClass="",$altTabType="",$altAclCategory="", $altAclPlugin="")
444   {
445     $ldap = $this->config->get_ldap_link();
446     $ldap->cd($this->config->current['BASE']); 
448     $disallowed = array();
449     foreach($this->dns as $key => $dn){
450       $ldap->cat($dn);
451       if($ldap->count()){
452         $attrs = $ldap->fetch();
453         $type= $this->get_type($attrs);
454         $acl  = $this->ui->get_permissions($dn,"fai/".$type[1]);
455         if(preg_match("/d/",$acl)){
457           // Delete the object
458           $this->dn = $dn;
459           $tabClass = $type[0];
460           $this->tabObject= new $tabClass($this->config,$this->config->data['TABS'][$type[2]], 
461               $this->dn, "fai", true, true);
462           $this->tabObject->set_acl_base($this->dn);
463           $this->tabObject->parent = &$this;
464           $this->tabObject->by_object[$type[1]]->remove_from_parent ();
466           FAI::save_release_changes_now();
467           $to_del = FAI::clean_up_releases($dn);
468           foreach($to_del as $dn){
469             $ldap->rmdir_recursive($dn);
470           }
472         } else {
473           $disallowed[] = $dn;
474           new log("security","fai/".get_class($this),$dn,array(),"Tried to trick deletion.");
475         }
476       }
477     }
478    
479     $this->remove_lock();
480     $this->closeDialogs();
482     /* Normally this shouldn't be reached, send some extra
483        logs to notify the administrator */
484     if(count($disallowed)){ 
485       msg_dialog::display(_("Permission error"), msgPool::permDelete($disallowed), ERROR_DIALOG);
486     }
487   }
490   /*! \brief   Someone clicked on edit/remove for a grouped FAI object.
491    *           We are now going to display a dialog to let the user select the entry 
492    *            he wants to perform the action on.
493    */
494   function editByGroup()
495   {
496     if($this->dialogObject instanceOf faiGroupHandle && $this->dialogObject->get_mode() == "edit"){
497       $this->dialogObject->save_object();
498       $entry = $this->dialogObject->get_selected();
499       $this->closeDialogs();
500       $data = array_pop($entry);
501       $type = $this->get_type($data);
502       $str = management::editEntry('editEntry',array($data['dn']),array(),$type[0],$type[2],'fai');
503       if($str) return($str);
504       $this->tabObject->by_object[$type[1]]->FAIstate = $data['FAIstate'];
505       $this->tabObject->read_only = preg_match("/freeze/i", $data['FAIstate']);
506     }elseif($this->dialogObject instanceOf faiGroupHandle && $this->dialogObject->get_mode() == "remove"){
507       $this->dialogObject->save_object();
508       $to_delete = $entry = $this->dialogObject->get_selected();
509       if(count($to_delete)) $this->closeDialogs();
510       return($this->removeFAIObjects($to_delete));
511     }elseif($this->dialogObject instanceOf faiGroupHandle && $this->dialogObject->get_mode() == "copy"){
512       $this->dialogObject->save_object();
513       $entries = $entry = $this->dialogObject->get_selected();
514       if(count($entries)){
515         foreach($entries as $entry){
516           $type = $this->get_type($entry);
517           $this->cpHandler->add_to_queue($entry['dn'],"copy",$type[0],$type[2],'fai',$this);
518           @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$entry['dn'],"Entry copied!");
519         }
520         $this->closeDialogs();
521       }
522     }
523   }
526   /*! \brief   Save dialog/object modifications
527    */
528   protected function saveChanges()
529   {
530     $str = management::saveChanges();
531     if($str) return($str);
533     // Now save changes
534     FAI::save_release_changes_now();
535     $to_del = FAI::clean_up_releases($this->last_dn);
536     $ldap= $this->config->get_ldap_link();
537     foreach($to_del as $dn){
538       $ldap->rmdir_recursive($dn);
539     }
540   }
543   /*! \brief   Save dialog/object modifications but keep the dialogs opened
544    */
545   protected function applyChanges()
546   {
547     $str = management::applyChanges();
548     if($str) return($str);
550     // Now save changes
551     FAI::save_release_changes_now();
552     $to_del = FAI::clean_up_releases($this->dn);
553     foreach($to_del as $dn){
554       $ldap->rmdir_recursive($dn);
555     }
556   }
559   /*! \brief   Initiates release removal
560    */
561   function removeBranch()
562   {
563     /* Check if we have a post remove method configured
564      *  else skip this operation. (Skip:Button in the ui should be disabled in this case too)
565      */
566     if("" != $this->config->get_cfg_value("faiManagement","postremove")){
567       /* Load permissions for selected 'dn' and check if
568          we're allowed to remove this 'dn' */
569       if(preg_match("/d/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){
570         $smarty=get_smarty();
571         $smarty->assign("release_hidden",base64_encode($this->fai_release));
572         $smarty->assign("info", msgPool::deleteInfo(LDAP::fix($this->fai_release),_("FAI branch/freeze")));
573         return($smarty->fetch(get_template_path('remove_branch.tpl',TRUE)));
574       } else {
575         msg_dialog::display(_("Permission error"), _("You have no permission to delete this release!"), ERROR_DIALOG);
576       }
577     }
578   }
581   /*! \brief   Remove a release after removal was confirmed
582    */
583   function removeBranchConfirmed()
584   {
585     /* Check if we have a post remove method configured
586      *  else skip this operation. (Skip:Button in the ui should be disabled in this case too)
587      */
588     if("" != $this->config->get_cfg_value("faiManagement","postremove")){
590       if(!isset($_POST['release_hidden']) || base64_decode($_POST['release_hidden']) != $this->fai_release){
591         msg_dialog::display(_("Warning"),_("Release remove aborted because the release name check failed!"));
592       }else{
594         $bb =  $this->fai_release;
595         $ldap = $this->config->get_ldap_link();
597         $br = $this->getBranches();
599         if(isset($br[$bb]) && preg_match("/d/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){
600           $name = $br[$bb];
602           $ldap->cd($bb);
603           $ldap->recursive_remove();
604           $ldap->cd(preg_replace('/,'.preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/').'/i', ','.get_ou("application", "applicationRDN"), $bb));
605           $ldap->recursive_remove();
606           $ldap->cd(preg_replace('/,'.preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/').'/i', ','.get_ou("mimetype", "mimetypeRDN"), $bb));
607           $ldap->recursive_remove();
609           /* Search for all groups with configured application menus.
610              - First search all groups, to ensure that we only remove entries form whithin groups.
611              - The search für menu configuration for the specified release and collect all those dns.
612              - Remove entries
613            */
614           $release_ou = preg_replace("/".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/').".*$/i","",$bb);
615           $ldap->cd($this->config->current['BASE']);
616           $ldap->search("(objectClass=posixGroup)",array("dn"));
618           /* Collect all group dns
619            */
620           $groups = array();
621           while($attrs = $ldap->fetch()){
622             $groups[] = $attrs['dn'];
623           }
626           /* Collect all group menu release dns that match the release we have removed
627            */
628           $dns = array();
629           foreach($groups as $dn){
630             $ldap->cd($dn);
631             $ldap->search("(objectClass=FAIbranch)",array("dn"));
632             while($attrs = $ldap->fetch()){
633               if(preg_match("/^".preg_quote($release_ou, '/')."/",$attrs['dn'])){
634                 $dns[] = $attrs['dn'];
635               }
636             }
637           }
639           /* Finally remove collected release dns
640            */
641           foreach($dns as $dn){
642             $ldap->cd($dn);
643             $ldap->recursive_remove();
644           }
646           /* Post remove */
647           $this->fai_release = preg_replace("/^[^,]*+,/","", $this->fai_release);
649           $this->lock_name   = $name;
650           $this->lock_dn     = $bb;
651           $this->handle_post_events('remove');
653           // Update list and release selector to point to a valid release again.
654           $releases = $this->getReleaseStates($this->config,$this->fai_base);
655           if(!isset($releases[$this->fai_release])){
656             $this->fai_release = $this->fai_base;
657           }
659           $headpage = $this->getHeadpage();
660           $headpage->setBase($this->fai_release);
661           $headpage->update();
663           $this->releaseSelector->setBases($releases);
664           $this->releaseSelector->setBase($this->fai_release);
666           new log("remove","fai/".get_class($this),$br[$bb],array(),"Release removed");
667         }
668       }
669     }
670   }
673   /*! \brief   Initiates release creation 
674    */
675   function createBranch()
676   { 
677     if($this->config->get_cfg_value("faiManagement", "postcreate") == ""){ 
678       msg_dialog::display(_("Configuration"), msgPool::cmdnotfound("POSTCREATE", get_class()), ERROR_DIALOG);
679     }elseif(!preg_match("/c/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){
680       msg_dialog::display(_("Permission error"), msgPool::permCreate(_("Branch")), ERROR_DIALOG);
681     }else{
682       $smarty = get_smarty();
683       $this->dispNewBranch=true;
684       $this->dispNewFreeze=false;
685       $smarty->assign("iframe",false);
686       if(isset($_POST['BranchName'])){
687         $smarty->assign("BranchName", get_post('BranchName'));
688       }else{
689         $smarty->assign("BranchName","");
690       }
691       return($smarty->fetch(get_template_path('faiNewBranch.tpl', TRUE, dirname(__FILE__))));
692     }
693   }
696   /*! \brief   Initiates release creation 
697    */
698   function createFreeze()
699   {
700     if($this->config->get_cfg_value("faiManagement", "postcreate") == ""){ 
701       msg_dialog::display(_("Configuration"), msgPool::cmdnotfound("POSTCREATE", get_class()), ERROR_DIALOG);
702     }elseif(!preg_match("/c/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){
703       msg_dialog::display(_("Permission error"), msgPool::permCreate(_("Branch")), ERROR_DIALOG);
704     }else{
705       $smarty = get_smarty();
706       $this->dispNewFreeze=true;
707       $this->dispNewBranch=false;
708       $smarty->assign("iframe",false);
709       if(isset($_POST['BranchName'])){
710         $smarty->assign("BranchName", get_post('BranchName'));
711       }else{
712         $smarty->assign("BranchName","");
713       }
714       return($smarty->fetch(get_template_path('faiNewBranch.tpl', TRUE, dirname(__FILE__))));
715     }
716   }
719   /*! \brief   Creates a new branch
720    */
721   function PerformBranch()
722   {
723     if(!preg_match("/c/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){
724       msg_dialog::display(_("Permission error"), msgPool::permCreate(_("Branch")), ERROR_DIALOG);
725     }else{
727       /* In order to see error messages we have to reset the error handler.
728          Due to the exit();
729        */
730       restore_error_handler();
732       $this->dispNewBranch = false;
733       $this->dispNewFreeze = false;
735       $LASTPOST = session::get('LASTPOST');
736       $base = $LASTPOST['base'];
737       $_POST  = session::get('LASTPOST');
738       $name = $_POST['BranchName'];
740       $type = $LASTPOST['type'];
741       $ldap = $this->config->get_ldap_link();
743       $baseToUse = $base;
744       if($this->fai_release !=  $this->fai_base){
745         $baseToUse = $this->fai_release;
746       }
748       /* Create new Release name to be able to set faidebianRelease for FAIpackageList */
750       $CurrentReleases  = $this->getBranches();
751       $NewReleaseName   = $name;
752       if(isset($CurrentReleases[$this->fai_release])) {
753         if($this->fai_release != $this->fai_base){
754           $NewReleaseName = $CurrentReleases[$this->fai_release]."/".$name;
755           $NewReleaseName = preg_replace("#\/#","/",$NewReleaseName);
756         }else{
757           $NewReleaseName   = $name;
758         }
759       }
761       $targetReleaseDN = "ou=".$name.",".$baseToUse;
763       $appsEnabled = class_available("application");
764       $mimeEnabled = class_available("mimetype");
765       if($appsEnabled){
766           $appsrc = preg_replace("/".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/')."/i",
767                   get_ou("application", "applicationRDN"),$baseToUse);
768           $appdst = preg_replace("/".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/')."/i",
769                   get_ou("application", "applicationRDN"),"ou=".$name.",".$baseToUse) ;
770       }
771       if($mimeEnabled){
772           $mimesrc = preg_replace("/".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/')."/i",
773                   get_ou("mimetype", "mimetypeRDN"),$baseToUse);
774           $mimedst = preg_replace("/".preg_quote(get_ou("faiManagement", "faiBaseRDN"), '/')."/i",
775                   get_ou("mimetype", "mimetypeRDN"),"ou=".$name.",".$baseToUse) ;
776       }
778       $useBases = array();
779       $useBases[] = $baseToUse;
780       if($appsEnabled) $useBases[] = $appsrc;
781       if($mimeEnabled) $useBases[] = $mimesrc;
783       /* Check if source depeartments exist */
784       foreach($useBases as $dep){
785         $ldap->cd($this->config->current['BASE']);
786         $ldap->cat($dep);
787         if(!$ldap->count()){
788           $ldap->create_missing_trees($dep);
789         }
790       }
792       /* Print header to have styles included */
793       echo '  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
794         <html>
795         <head>
796         <title></title>
797         <style type="text/css">@import url("themes/default/style.css");</style>
798         <script language="javascript" src="include/gosa.js" type="text/javascript"></script>
799         </head>
800         <body style="background: none;margin:3px;color:black">
801         ';
803       new log("create","fai/".get_class($this),$NewReleaseName,array(),"New $type created");
805       /* Duplicate group application releases
806        */
807       FAI::copy_FAI_group_releases($CurrentReleases[$this->fai_release],$name,$type);
809       /* Duplicate applications
810        */
811       if($appsEnabled){
812           $ldap->cat($appsrc,array("dn")) ;
813           if($ldap->count()){
814               $ldap->cd ($appdst);
815               $ldap->recursive_remove();
816               FAI::copy_FAI_resource_recursive($appsrc,$appdst,$NewReleaseName,$type,true);
817           }
818       }
820       /* Duplicate mime types
821        */
822       if($mimeEnabled){
823           $ldap->cat($mimesrc,array("dn")) ;
824           if($ldap->count()){
825               $ldap->cd ($mimedst);
826               $ldap->recursive_remove();
827               FAI::copy_FAI_resource_recursive($mimesrc,$mimedst,$NewReleaseName,$type,true);
828           }
829       }
831       $attr = array();
832       $attr['objectClass'] = array("organizationalUnit","FAIbranch");
833       $attr['ou']       = $name;
834       $attr['FAIstate'] = $type;
835       $ldap->cd($this->config->current['BASE']);
836       $ldap->cd("ou=".$name.",".$baseToUse);
837       $ldap->cat("ou=".$name.",".$baseToUse);
838       if($ldap->count()){
839         $ldap->modify($attr);
840       }else{
841         $ldap->add($attr);
842       }
844       /* Duplicate fai objects
845        */
846       //      $ldap->cd ("ou=".$name.",".$baseToUse);
847       //      $ldap->recursive_remove();
848       //      FAI::copy_FAI_resource_recursive($baseToUse,"ou=".$name.",".$baseToUse,$NewReleaseName,$type,true);
850       echo "<div style='width:100%;text-align:right;'><form name='form' method='post' action='?plug=".$_GET['plug']."' target='_parent'>
851         <br><input type='submit' name='CloseIFrame' value='"._("Continue")."'>
852         <input type='hidden' name='php_c_check' value='1'>
853         </form></div>";
855       echo "<script language=\"javascript\" type=\"text/javascript\">scrollDown2();</script>" ;
857       /* Print footer to have valid html */
858       echo "</body></html>";
860       $this->dispNewFreeze = false;
862       /* Assign possible attributes */
863       $this->lock_type  = $type;
864       $this->lock_name  = $name;
865       $this->lock_dn    = $baseToUse;
866       $this->handle_post_events('add');
868       /* Send daemon event to reload the fai release database
869        */
870       if(class_available("DaemonEvent") && class_available("gosaSupportDaemon")){
871         $events = DaemonEvent::get_event_types(SYSTEM_EVENT | HIDDEN_EVENT);
872         if(isset($events['TRIGGERED']['DaemonEvent_recreate_fai_release_db'])){
873           $evt = $events['TRIGGERED']['DaemonEvent_recreate_fai_release_db'];
874           $tmp = new $evt['CLASS_NAME']($this->config);
875           $tmp->set_type(TRIGGERED_EVENT);
876           $tmp->add_targets(array("GOSA"));
877           $o_queue = new gosaSupportDaemon();
878           if(!$o_queue->append($tmp)){
879             msg_dialog::display(_("Service infrastructure"),msgPool::siError($o_queue->get_error()),ERROR_DIALOG);
880           }
881         }
882       }else{
883           if($this->config->boolValueIsTrue("core","developmentMode")){
884               trigger_error("Unknown class DaemonEvent / gosaSupportDaemon");
885               msg_dialog::display(_("Fatal error"),
886                       "Daemon events called but classes where not accessible, DaemonEvent gosaSupportDaemon",
887                       FATAL_ERROR_DIALOG);
888           }
889       }
890     
891       // Update list and release selector to point to the newly created release 
892       $headpage = $this->getHeadpage();
893       $this->fai_release = $targetReleaseDN;
894       $headpage->setBase($this->fai_release);
895       $headpage->update();
896  
897       $releases = $this->getReleaseStates($this->config,$this->fai_base);
898       $this->releaseSelector->setBases($releases);
899       $this->releaseSelector->setBase($this->fai_release);
900       exit();
901     }
902   }
905   /*! \brief   Creates a new branch, after a useable name was specified.
906    */
907   function saveBranch()
908   {
909     if($this->dispNewBranch){
910       $type = "branch";
911     }else{
912       $type = "freeze";
913     }
915     /* Check branch name */
916     $name = $_POST['BranchName'];
917     $is_ok = true;
918     $smarty = get_smarty();
919     $smarty->assign("BranchName",$name);
920     $base= $this->fai_base;
922     /* Check used characters */
923     if(!preg_match("/^[0-9a-z\.]*$/",$name)){
924       msg_dialog::display(_("Error"), msgPool::invalid(_("Name"),$name,"/[0-9a-z\.]/"), ERROR_DIALOG);
925       $is_ok = false;
926     }
928     // Check if this name is already in use 
929     if(!$this->CheckNewBranchName($_POST['BranchName'],$this->fai_release)){
930       msg_dialog::display(_("Error"), msgPool::duplicated(_("Name")), ERROR_DIALOG);
931       $is_ok = false;
932     }
934     // Handle errors
935     if(!$is_ok && $this->dispNewFreeze){
936       return($this->createFreeze());
937     }elseif(!$is_ok && $this->dispNewBranch){
938       return($this->createBranch());
939     }
941     // Now create new release
943     if(session::is_set('LASTPOST')){
944       $LASTPOST = session::get('LASTPOST');
945     }else{
946       $LASTPOST = array();
947     }
948     $LASTPOST['base'] = $base;
949     $LASTPOST['type'] = $type;
950     $LASTPOST['BranchName'] = $name;
951     session::set('LASTPOST',$LASTPOST);
952     $smarty->assign("iframe", true);
953     $smarty->assign("plugID", $_GET['plug']);
954     $display  = $smarty->fetch(get_template_path('faiNewBranch.tpl', TRUE, dirname(__FILE__)));
955     return($display);
957   }
961   /*! \brief   Returns a list of all releases for useable for drop down boxes.
962    *                      ou=fai... /
963    *              ou=siga,ou=fai... &nbsp; siga
964    *         ou=1,ou=siga,ou=fai... &nbsp;&nbsp; 1
965    */
966   function getReleaseList($base = "", $prefix ="")
967   {
968     $list = array();
969     if(empty($base)){
970       $base = $this->fai_base;
971       $list[$base] = "/";
972     }
974     $ldap = $this->config->get_ldap_link();
975     $ldap->ls("(objectClass=FAIbranch)",$base,array("ou","FAIstate"));
976     while($release = $ldap->fetch()){
977       $list[$release['dn']] = $prefix.$release['ou'][0];
978       $list = array_merge($list,$this->getReleaseList($release['dn'],$prefix."&nbsp; "));
979     }
980     return($list);
981   }
984   /*! \brief   Returns a list of all releases for the releaseSelector
985    *                      ou=fai... 
986    *              ou=siga,ou=fai... "branch"
987    *         ou=1,ou=siga,ou=fai... "freeze"
988    */
989   static function getReleaseStates($config,$base = "", $fai_base="")
990   {
991     $list = array();
992     if(empty($fai_base)){
993       $fai_base = $base;
994       $list[$base] = "";
995     }
997     $ldap = $config->get_ldap_link();
998     $ldap->ls("(objectClass=FAIbranch)",$base,array("ou","FAIstate"));
1000     while($release = $ldap->fetch()){
1001       $list[$release['dn']] = _("Release");
1002       if(isset($release['FAIstate'][0]) && preg_match("/freeze/i",$release['FAIstate'][0])){
1003         $list[$release['dn']] = _("Freeze");
1004       }
1005       $list = array_merge($list,faiManagement::getReleaseStates($config,$release['dn'], $fai_base));
1006     }
1007     return($list);
1008   }
1011   /*! \brief   Returns a list of all releases with full release names
1012    *                      ou=fai... /
1013    *              ou=siga,ou=fai... siga
1014    *         ou=1,ou=siga,ou=fai... siga/1
1015    */
1016   function getBranches($base = false,$prefix = "")
1017   {
1018     $ret = array("/"=>$this->fai_base);
1019     $ldap = $this->config->get_ldap_link();
1020     if(!$base){
1021       $base = $this->fai_base;
1022     }
1023     $tmp = FAI::get_all_releases_from_base($base,true);
1024     foreach($tmp as $dn => $name){
1025       $ret[$name]=$dn;
1026     }
1027     ksort($ret);
1028     $ret = array_flip($ret);
1030     return ($ret);
1031   }
1034   /*! \brief   Detects object info like corresponding  tab,class,acl 
1035    *    e.g.    [0]   =  tabsPartition
1036    *            [1]   =  faiPartitionTable
1037    *            [2]   =  FAIPARTITIONTABS
1038    */
1039   function get_type($array)
1040   {
1041     if(!isset($array['objectClass'])) return(array());
1042     if(in_array("FAIpartitionTable",$array['objectClass'])){
1043       return(array("tabsPartition","faiPartitionTable","FAIPARTITIONTABS"));
1044     }
1045     if(in_array("FAIscript",$array['objectClass'])){
1046       return(array("tabsScript","faiScript","FAISCRIPTTABS"));
1047     }
1048     if(in_array("FAItemplate",$array['objectClass'])){
1049       return(array("tabsTemplate","faiTemplate","FAITEMPLATETABS"));
1050     }
1051     if(in_array("FAIhook",$array['objectClass'])){
1052       return(array("tabsHook","faiHook","FAIHOOKTABS"));
1053     }
1054     if(in_array("FAIvariable",$array['objectClass'])){
1055       return(array("tabsVariable","faiVariable","FAIVARIABLETABS"));
1056     }
1057     if(in_array("FAIprofile",$array['objectClass'])){
1058       return(array("tabsProfile","faiProfile","FAIPROFILETABS"));
1059     }
1060     if(in_array("FAIpackageList",$array['objectClass'])){
1061       return(array("tabsPackage","faiPackage","FAIPACKAGETABS"));
1062     }
1063     return(array());
1064   }
1067   /*! \brief   Checks if the given string can be used as class name
1068    */
1069   static function check_class_name($oc,$name,$dn)
1070   {
1071     $base = FAI::get_release_dn($dn);
1073     if($oc == "FAIprofile"){
1074       $f = "";
1075       $ocs = array("FAIprofile","FAItemplate","FAIhook","FAIpartitionTable","FAIpackageList","FAIscript","FAIvariable");
1076       foreach($ocs as $oc){
1077         $f .= "(objectClass=".$oc.")";
1078       }
1079       $res  = FAI::get_all_objects_for_given_base($base,"(|".$f.")",TRUE);
1080     }else{
1081       $res  = FAI::get_all_objects_for_given_base($base,"(objectClass=".$oc.")",TRUE);
1082     }
1083     $delete = array();
1084     $used   = array();
1085     foreach($res as $object){
1086       $used[$object['cn'][0]]= $object['cn'][0];
1087     }
1088     return($used);
1089   }
1092   /*! \brief   Checks if the given string can be used for a new release
1093    */
1094   function CheckNewBranchName($name,$base)
1095   {
1096     $f = $this->fai_release;
1097     if($name == ""){
1098       return(false);
1099     }elseif(in_array($name,$this->getBranches($f))) {
1100       return(false);
1101     }elseif(tests::is_department_name_reserved($name,$base)){
1102       return(false);
1103     }
1104     return(true);
1105   }
1108   /*! \brief   This filter is used to display small icons for each listed object 
1109    *            instead of their typ names
1110    */
1111   static function filterProperties($row, $classes)
1112   {
1113     $objects = array(
1114         "FAIpartitionTable"  => array("IMG"=> "plugins/fai/images/fai_partitionTable.png",
1115           "NAME"=>_("Partition table"),"KZL"=> "PT", "VAR"=>"ShowPartitions"),
1116         "FAIpackageList"     => array("IMG"=> "plugins/fai/images/fai_packages.png",
1117           "NAME"=>_("Package list") ,  "KZL"=> "PL", "VAR"=>"ShowPackages"),
1118         "FAIscript"          => array("IMG"=> "plugins/fai/images/fai_script.png",
1119           "NAME"=>_("Scripts") ,       "KZL"=> "S",  "VAR"=>"ShowScripts"),
1120         "FAIvariable"        => array("IMG"=> "plugins/fai/images/fai_variable.png",
1121           "NAME"=>_("Variables") ,     "KZL"=> "V",  "VAR"=>"ShowVariables"),
1122         "FAIhook"            => array("IMG"=> "plugins/fai/images/fai_hook.png",
1123           "NAME"=>_("Hooks"),          "KZL"=> "H",  "VAR"=>"ShowHooks"),
1124         "FAIprofile"         => array("IMG"=> "plugins/fai/images/fai_profile.png",
1125           "NAME"=>_("Profile") ,       "KZL"=> "P",  "VAR"=>"ShowProfiles"),
1126         "FAItemplate"        => array("IMG"=> "plugins/fai/images/fai_template.png",
1127           "NAME"=>_("Templates") ,     "KZL"=> "T",  "VAR"=>"ShowTemplates"),
1128         "opsi_netboot"       => array("IMG"=> "plugins/opsi/images/netboot_package.png",
1129           "NAME"=>_("OPSI net boot product") ,     "KZL"=> "ON",  "VAR"=>"ShowOpsiNetboot"),
1130         "opsi_local"         => array("IMG"=> "plugins/opsi/images/local_package.png",
1131           "NAME"=>_("OPSI local boot product")   ,     "KZL"=> "OL",  "VAR"=>"ShowOpsiLocal"));
1133     $icon_list = "";
1134     foreach($objects as $type => $type_data){
1135       if(in_array($type, $classes)){
1136         $icon_list .= image($type_data['IMG'],'edit_'.$row.'_'.$type,$type_data['NAME']);
1137       }else{
1138         $icon_list .= image('images/empty.png');
1139       }
1140     }
1142     return $icon_list;
1143   }
1146   /*! \brief   Overridden render method of class mangement. 
1147    *            this allows us to add a release selection box.
1148    */
1149   function renderList()
1150   {
1151     $filter = $this->getFilter();
1152     $headpage = $this->getHeadpage();
1153     $this->releaseSelector->update();
1154     $this->fai_release = $this->releaseSelector->getBase();
1155     $headpage->setBase($this->fai_release);
1156     $headpage->update();
1157     $smarty = get_smarty();
1158     $r = $this->config->get_cfg_value("faiManagement", "postremove");
1159     $c = $this->config->get_cfg_value("faiManagement", "postcreate");
1160     $smarty->assign("allow_create", $c);
1161     $smarty->assign("allow_remove", $r);
1162     $smarty->assign("RELEASE", $this->releaseSelector->render());
1163     $display = $headpage->render();
1164     return($this->getHeader().$display);
1165   }
1168   /*! \brief   Convert POST and GET variables into actions.
1169    */
1170   function detectPostActions()
1171   {
1172     $action = management::detectPostActions();
1173     if(isset($_POST['remove_multiple'])) $action['action'] = "remove";
1174     if(isset($_POST['new_profile'])) $action['action'] = "new_profile";
1175     if(isset($_POST['new_template'])) $action['action'] = "new_template";
1176     if(isset($_POST['new_script'])) $action['action'] = "new_script";
1177     if(isset($_POST['new_hook'])) $action['action'] = "new_hook";
1178     if(isset($_POST['new_variable'])) $action['action'] = "new_variable";
1179     if(isset($_POST['new_package'])) $action['action'] = "new_package";
1180     if(isset($_POST['new_partition'])) $action['action'] = "new_partition";
1182     if(isset($_POST['save_properties'])) $action['action'] = "saveOpsiProperties";
1183     if(isset($_POST['cancel_properties'])) $action['action'] = "cancel";
1185     if(isset($_POST['edit_continue'])) $action['action'] = "newClassNameSelected";
1186     if(isset($_POST['edit_cancel'])) $action['action'] = "cancel";
1188     if(isset($_POST['faiGroupHandle_cancel'])) $action['action'] = "cancel";
1189     if(isset($_POST['CancelBranchName'])) $action['action'] = "cancel";
1190     if(isset($_POST['delete_branch_confirm'])) $action['action'] = "removeBranchConfirmed";
1191     if(isset($_GET['PerformBranch'])) $action['action'] = "PerformBranch";
1192     if(isset($_POST['UseBranchName'])) $action['action'] = "saveBranch";
1193     if(isset($_POST['faiGroupHandle_apply']))  $action['action'] = "editByGroup";
1194     if(isset($_GET['act']) && $_GET['act'] == "branch_branch")  $action['action'] = "createBranch";
1195     if(isset($_GET['act']) && $_GET['act'] == "freeze_branch")  $action['action'] = "createFreeze";
1196     if(isset($_GET['act']) && $_GET['act'] == "remove_branch")  $action['action'] = "removeBranch";
1198     foreach($_POST as $name => $value){
1199       if(preg_match("/^edit_([0-9]*)_([a-z_]*)/i", $name)){
1200         $id = preg_replace("/^edit_([0-9]*)_([a-z_]*)/i","\\1", $name);
1201         $tab = preg_replace("/^edit_([0-9]*)_([a-z_]*)/i","\\2", $name);
1203         $headpage = $this->getHeadpage();
1204         $entry = $headpage->entries[$id];
1206         if(in_array('FAKE_OC_FAI', $entry['objectClass'])){
1207           unset($_POST[$name]);
1208           if(isset($headpage->entries[$id]['GROUPS'][$tab])){
1209             $data =$headpage->entries[$id]['GROUPS'][$tab];
1210             $type = $this->get_type($data);
1211             $str = management::editEntry('editEntry',array($data['dn']),array(),$type[0],$type[2],"fai"); 
1212             if($str) return($str);
1213           } 
1214         }else{
1215           $str = $this->editEntry('editEntry',array($entry['dn'])); 
1216           if($str) return($str);
1217         }
1218         break;
1219       }
1220     }
1221     return($action);
1222   }
1225   static function plInfo()
1226   {
1227       return (array(
1228                   "plShortName"   => _("FAI releases"),
1229                   "plDescription" => _("FAI release management"),
1230                   "plSelfModify"  => FALSE,
1231                   "plDepends"     => array(),
1232                   "plPriority"    => 0,
1233                   "plSection"     => array("administration"),
1234                   "plRequirements"=> array(
1235                       'onFailureDisablePlugin' => array(
1236                           'faiDiskEntry',
1237                           'faiHookEntry',
1238                           'faiHook',
1239                           'faiManagement',
1240                           'faiPackageConfiguration',
1241                           'faiPackage',
1242                           'faiPartition',
1243                           'faiPartitionTableEntry',
1244                           'faiPartitionTable',
1245                           'faiProfile',
1246                           'faiScriptEntry',
1247                           'faiScript',
1248                           'faiSummaryTab',
1249                           'faiTemplateEdit',
1250                           'faiTemplateEntry',
1251                           'faiTemplate',
1252                           'faiVariableEntry',
1253                           'faiVariable',
1254                           'servrepository'
1255                           ),
1256                       'ldapSchema' => array(
1257                           'FAIclass' => '>=2.7',
1258                           'FAIbranch' => '>=2.7',
1259                           'FAIdebconfInfo' => '>=2.7',
1260                           'FAIobject' => '>=2.7',
1261                           'FAIpackageList' => '>=2.7',
1262                           'FAItemplate' => '>=2.7',
1263                           'FAIscript' => '>=2.7',
1264                           'FAIvariable' => '>=2.7',
1265                           'FAIhook' => '>=2.7',
1266                           'FAItemplateEntry' => '>=2.7',
1267                           'FAIscriptEntry' => '>=2.7',
1268                           'FAIvariableEntry' => '>=2.7',
1269                           'FAIhookEntry' => '>=2.7',
1270                           'FAIpartitionTable' => '>=2.7',
1271                           'FAIpartitionDisk' => '>=2.7',
1272                           'FAIpartitionEntry' => '>=2.7',
1273                           'FAIprofile' => '>=2.7',
1274                           'FAIpartitionEntry' => '>=2.7',
1275                           'FAIrepository' => '>=2.7',
1276                           'FAIrepositoryServer' => '>=2.7'
1277                               )
1278                               ),
1279                   "plProperties" =>
1280                   array(
1281                       array(
1282                           "name"          => "faiBaseRDN",
1283                           "type"          => "rdn",
1284                           "default"       => "ou=fai,ou=configs,ou=systems,",
1285                           "description"   => _("RDN for FAI storage."),
1286                           "check"         => "gosaProperty::isRdn",
1287                           "migrate"       => "migrate_faiBaseRDN",
1288                           "group"         => "plugin",
1289                           "mandatory"     => TRUE
1290                           ),
1291                       array(
1292                           "name"          => "defaultFaiRelease",
1293                           "type"          => "dn",
1294                           "default"       => "",
1295                           "description"   => _("Name of the FAI default release."),
1296                           "check"         => "gosaProperty::isDn",
1297                           "migrate"       => "",
1298                           "group"         => "fai",
1299                           "mandatory"     => FALSE
1300                           )
1301                           ),
1303                           "plCategory"    => array("fai"=> array("description" => _("FAI"),"objectClass" => "FAIclass")),
1304                           "plProvidedAcls"=> array()));
1305   }
1306
1307 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1308 ?>