Code

Created trunk inside of 2.6-lhm
[gosa.git] / trunk / gosa-plugins / goto / admin / groups / apps / class_groupApplication.inc
1 <?php
2 class appgroup extends plugin
3 {
4   var $config;
5   var $curbase;
7   /* Contains the menu structure in an array.
8    */
9   var $a_Structure= array();
10   var $a_Structure_on_load = array();
11   var $Releases;
12   var $FAIrelease = 0;
13   var $apps = array();
14   var $_cache = array();
16   var $app_parameter = array();
17   var $edit_entry    = array();
18   var $enableReleaseManagement = FALSE;
20   var $copied_release = ""; 
21    
23   public function __construct(&$config, $dn= NULL, $parent= NULL)
24   {
25     plugin::plugin($config,$dn,$parent);
26     $this->dn = $dn; 
27     $this->_load_menu_structure();
28     $this->a_Structure_on_load = $this->a_Structure;
30     /* Check if we have relase mangement enabled and prepare group application for release management */
31     $tmp = $config->search("faiManagement", "CLASS",array('menu','tabs'));
32     if(!empty($tmp)){
33       $this->enableReleaseManagement = true;
34     }
36     $this->Releases   = $this->getReleases();
38     /* Set intial release */
39     $this->FAIrelease = $config->search("faiManagement","DEFAULTFAIRELEASE",array("menu"));
40     if(empty($this->FAIrelease) || !isset($this->Releases[$this->FAIrelease])){
41       $this->FAIrelease = "/";
42     }
44     $this->curbase    = $this->config->current['BASE'];
45     $this->reload();
46  
47     /* If we have at least one assigned application-
48        Enable this account.
49      */ 
50     $this->is_account = FALSE;
51     if(count($this->_get_all_entries()) > 1){
52       $this->is_account= TRUE;
53     }   
54     $this->initially_was_account = $this->is_account;
55   }
58   /*! \brief Reload the list of applications for the currently selected release.
59              If necessary, maybe the list is already cached.
60    */
61   function reload()
62   {
63     $ret = array();
64     $release_info = $this->Releases[$this->FAIrelease];
66     /* Check if the available application were already been fetched.
67        If not, build up a list of available applications.
68      */  
69     if(!isset($this->_cache['ReleaseApps'][$release_info['suffix']])){
71       /* First of all, get all application departments to search in.
72        */  
73       $ldap = $this->config->get_ldap_link();
74       $ldap->cd($this->config->current['BASE']);
75       $ldap->search("ou=apps",array("dn"));
76       $app_deps = array();
77       while($attrs = $ldap->fetch()){
78         $app_deps[] = $attrs['dn'];
79       }
81       /* Search all release departments for the above fetched application departments
82        */
83       foreach($app_deps as $dep){
84         $ldap->cd($dep);
85         $ldap->search("objectClass=FAIbranch",array("dn"));
86         while($attrs = $ldap->fetch()){
87           $app_deps[] = $attrs['dn'];
88         }
89       }
91       /* Filter out those releases that match the currently selected release, 
92           and fetch all applications from those departments.
93        */
94       foreach($app_deps as $dep){
95         if(preg_match("/^".preg_quote($release_info['suffix'], '/')."/",$dep)){
96           $ret = array_merge($ret,get_list("(objectClass=gosaApplication)","application",$dep,array("*"),GL_NONE));
97         }
98       }
100       /* Create a new array containing all fetch apps for the currently selected release,
101           sort it and store results in cache. 
102        */ 
103       $tmp = array();
104       foreach($ret as $key => $app){
105         $tmp[$key] = $app['cn'][0];
106       }
107       natcasesort($tmp);
108       $res = array();
109       foreach($tmp as $key => $app){
110         $res[] = $ret[$key];
111       }
113       $this->_cache['ReleaseApps'][$release_info['suffix']] = $res;
114     } 
115     $this->apps = $this->_cache['ReleaseApps'][$release_info['suffix']];
116   }
118   
119   
120   /*! \brief generate a list of available releases
121       @return return an array with all available releases.
123       e.g.
125       /     "name"    /
126             "found"   1
127             "parts"   Array (empty)
128             "suffix"  ou=apps,
130       halut "name"    halut
131             "found"   1
132             "FAIstate"  
133             "dn"      ou=halut,ou=apps,ou=Direktorium,o=Landeshauptstadt München,c=de
134             "parts"   0 halut
135             "suffix"  ou=halut,ou=apps,
137       This will be used as base for the application menu structure.
138       If there is a menu assigned for a release, this menu will be 
139        appended with the index 'ENTRIES';
140     */
141   function getReleases()
142   {
143     $ret =array("/" => array("name" => "/", "found" => TRUE , "parts" => array(),"suffix" => get_ou('applicationRDN')));
144     if($this->enableReleaseManagement){
146       /* Only display those releases that we are able to read 
147        */
148       $dn     = get_ou("applicationRDN").$this->config->current['BASE'];
149       $filter = "(&(objectClass=organizationalUnit)(objectClass=FAIbranch))";
150       $res    = get_sub_list($filter,array("application","fai"), 
151           array(get_ou("applicationRDN"),get_ou("faiBaseRDN")),$dn, array("ou","FAIstate"), GL_SUBSEARCH);
153       /* Go through all departments and check which department is a valid 
154           department release.
155        */
156       foreach($res as $attrs){
157         if(preg_match("/".get_ou('applicationRDN')."/",$attrs['dn'])){
159           /* Parse all returned departments dns into a useable type.
160              (ou=1.0.0,ou=halut,ou=apps  ==> halue/1.0.0)
161            */
162           $bb     = preg_replace("/".get_ou('applicationRDN').".*/","",$attrs['dn']);
163           $parts  = array_reverse(split("ou=",$bb));
165           $str ="";
166           foreach($parts as $key => $part){
167             if(empty($part)) {
168               unset($parts[$key]);
169               continue;
170             }
171             $part = str_replace(",","",$part);
172             $str .= $part."/";
173             $parts[$key] = $part;
174           }
175           $name = preg_replace("/\/$/","",$str);
176           if(empty($name)) {
177             $name ="/";
178           }
180           $FAIstate = "";
181           if(isset($attrs['FAIstate'])){
182             $FAIstate = $attrs['FAIstate'][0];
183           }
185           /* Check if this department has a menu structure assigned 
186            */
187           $all = $this->_get_all_entries();
188           $found = FALSE;
189           foreach($all as $entry){
190             if(isset($entry['DN']) && preg_match("/^".preg_quote($bb, '/')."/",$entry['DN'])){
191               $found =TRUE;
192               break;
193             }
194           }
196           $ret[$name] = array("name"     => $name, 
197               "found"    => $found,
198               "FAIstate" => $FAIstate,
199               "dn"       => $attrs['dn'], 
200               "parts"    => $parts,"suffix" => $bb.get_ou('applicationRDN'));
201         }
202       }
203     }
204     ksort($ret);
205     return($ret);
206   }
209   /*! \brief Load the menu structure from ldap and create a multi dimensional array.
211       This will create a multidimensional array.
212       e.g.:
214       $this->a_Structure =
215   
216       [0]['TYPE']   = "BASE"
217       [0]['ENTRIES']  [0]['TYPE']   = "RELEASE"
218                       [0]['NAME']   = "halut"
219                       [0]['ENTRIES']= array()
220                       ...
221       [0]['ENTRIES']  [1]['TYPE']   = "RELEASE"
222                       [1]['NAME']   = "halut/1.0.0"
223                       [1]['ENTRIES']  [0]['TYPE']   = "TYPE"
224                                       [0]['NAME']   = "Programme"
225                                       [0]['ENTRIES'][0]['TYPE'] = "ENTRY"
226                                                     [0]['NAME'] = "konqueror"
227                                                     [1]['TYPE'] = "ENTRY"
228                                                     [1]['NAME'] = "firefox"
229    */
230   function _load_menu_structure()
231   {
232     /* Create the base object
233      */
234     $base =  array();
235     $base['UNIQID'] = uniqid();
236     $base['PARENT'] = 0; 
237     $base['NAME']   = "";
238     $base['TYPE']   = "BASE";
239     $base['ENTRIES']= array();
240     $base['STATUS'] = "LOADED";
241     
242     $this->a_Structure  = array();
243     $this->a_Structure[0] = $base;
245     /* Search for all Releases/Menu Folders and Menu Entries,
246         to append them to our structure array.
247      */
248     $ldap = $this->config->get_ldap_link();
249     $ldap->cd($this->dn);
250     $ldap->search("(|(objectClass=gotoSubmenuEntry)(objectClass=FAIbranch)(objectClass=gotoMenuEntry))",array("*"));
251     while($attrs = $ldap->fetch()){
253       /* Find the correct position where to add this entry.
254           e.g. If we have cn=firefox,cn=Programme,ou=halut...
256           1. get a pointer to the halut array ($this->a_Structure['0'][ENTRIES''][]['halut'])
257           2. then get a pointer to the halut['ENTRIES'][]['Programme'] array. 
258           3. append 'firefox' to the 'ENTRIES' of our "Programme" pointer.
259        */
260       $cur          = &$this->a_Structure[0]['ENTRIES'];
261       $parent_id    = $base['UNIQID'];
262       $sub_dn       = preg_replace("/,".preg_quote($this->dn, '/')."$/","",$attrs['dn']);
263       $sub_dn_array = split("\,",$sub_dn);
265       /* Walk through our menu structure array while we have found 
266           the correct position where to add this object. 
267        */
268       $found = true;
269       for($i = (count($sub_dn_array)-1) ; $i >= 0 ; $i--){
270         $name = preg_replace("/^[^=]*+=/","",$sub_dn_array[$i]);
271         
272         /* We haven't found the end node where this object has to be added
273          */
274         if($i > 0){
275           $found =FALSE;
276           foreach($cur as $key => $entry){
277             if($entry['NAME'] == $name){
278               $cur = &$cur[$key]['ENTRIES'];
279               $parent_id = $entry['UNIQID'];
280               $found =true;
281               break;
282             }
283           }
284         }else{
285           
286           if(!$found){
287             break;
288           }
290           /* Get application priority.
291              And ensure that each priority exists once.
292            */
293           $priority = 1;
294           if(isset($attrs['gosaApplicationPriority'])){
295             $priority= $attrs['gosaApplicationPriority'][0];
296           }
297           while(isset($cur[$priority])){
298             $priority ++;
299           }
301           /* Create the data object that should be added 
302              * Folder
303              * Entry
304              * Release
305            */
306           $data = array();
307     
308           /* Add a menu folder 
309            */
310           if(in_array("gotoSubmenuEntry",$attrs['objectClass'])){
311             $type = "FOLDER";
313             $data['ICON'] = "";
314             if(isset($attrs['gosaApplicationIcon'])){
315               $data['ICON'] = $ldap->get_attribute($attrs['dn'],"gosaApplicationIcon");
316             }
318           /* Add a menu entry 
319            */
320           }elseif(in_array("gotoMenuEntry",$attrs['objectClass'])){
322             $type = "ENTRY";
323             $data['INFO'] = "";
324             $data['PARAMETER'] = array();
325             if(isset($attrs['gosaApplicationParameter'])){
326               for($p = 0 ; $p < $attrs['gosaApplicationParameter']['count'] ; $p ++){
327                 if(preg_match("/:/",$attrs['gosaApplicationParameter'][$p])){
328                   $tmp = split(":",$attrs['gosaApplicationParameter'][$p]);
329                   $data['PARAMETER'][$tmp[0]] = preg_replace('/^[^:]+:/', '', $attrs['gosaApplicationParameter'][$p]);
330                 }elseif($attrs['gosaApplicationParameter'][$p] == "*separator*"){
331                   $type = "SEPERATOR";
332                   $data['PARAMETER'] = array();
333                   break;
334                 }
335               }
336             }
338           /* Add a release
339            */
340           }elseif(in_array("FAIbranch",$attrs['objectClass'])){
341             $type = "RELEASE";
342             if(isset($attrs['FAIstate'][0])){
343               $data['FAIstate'] = $attrs['FAIstate'][0];
344             }else{
345               $data['FAIstate'] = "";
346             }
347           }
349           /* Create object and append it to the current structure pointer 
350            */
351           $data['LDAP_ATTRS'] = $attrs;
352           $data['DN']       = $attrs['dn'];
353           $data['NAME']     = $name;
354           $data['TYPE']     = $type;
355           $data['PRIORITY'] = $priority;
356           $data['ENTRIES']  = array();
357           $data['UNIQID']   = uniqid();
358           $data['PARENT']   = $parent_id;
359           $data['STATUS']   = "LOADED";
360           $cur[$priority]   = $data;
361           ksort($cur);
362         }
363       }
364     }
365   } 
368   function execute()
369   {
370     /* Call parent execute */
371     plugin::execute();
373     if(isset($_GET['r'])) $this->__construct($this->config,$this->dn);
375     if (isset($_POST['modify_state'])){
376       $this->is_account = !$this->is_account;
377     }
379     /* Do we represent a valid account? */
380     if (!$this->is_account){
381       $display= $this->show_disable_header(msgPool::addFeaturesButton(_("Menu")), msgPool::featuresDisabled(_("Menu")));
382       return ($display);
383     }
385     $display= $this->show_disable_header(msgPool::removeFeaturesButton(_("Menu")), msgPool::featuresEnabled(_("Menu")));
387     if(isset($_GET['send'])){
388       $id = $_GET['send'];
389       $all = $this->_get_all_entries();
390       if(isset($all[$id])){
391         send_binary_content($all[$id]['ICON'],$id.".jpg","image/jpeg");
392         exit;
393       }
394     }
396     if(isset($_GET['r']))
397     $this->__construct($this->config,$this->dn);
399     if(count($this->edit_entry)){
400       if($this->edit_entry['TYPE'] == "ENTRY"){
401         $smarty = get_smarty();
402         $smarty->assign("type", "ENTRY");
403         $smarty->assign("entry",$this->edit_entry);
404         $smarty->assign("paras",$this->app_parameter);
405         $display= $smarty->fetch (get_template_path('edit_entry.tpl', TRUE, dirname(__FILE__)));
406         return($display);
407       }
408       if($this->edit_entry['TYPE'] == "FOLDER"){
409         $smarty = get_smarty();
411         session::set("binarytype" , "image/jpeg");
412         session::set("binary" , $this->edit_entry['ICON']);
413   
414         $smarty->assign("rand", microtime(TRUE));
415         $smarty->assign("image_set" , strlen($this->edit_entry['ICON']) > 0); 
416         $smarty->assign("type", "FOLDER");
417         $smarty->assign("entry",$this->edit_entry);
418         $display= $smarty->fetch (get_template_path('edit_entry.tpl', TRUE, dirname(__FILE__)));
419         return($display);
420       }
421     }
423     $smarty = get_smarty();
424     $smarty->assign("plug_id" , $_GET['plug']);
426     /* Create application list */
427     $div = new divSelectBox("appgroup");
428     $div->SetHeight(300);
429     $departments = array();
430     if(!$this->enableReleaseManagement){
431       $res = get_list("(objectClass=gosaDepartment)", "application", $this->curbase,array("description","cn","ou"),GL_SIZELIMIT);
432       foreach($res as $value){
433         $fdn = $value['dn'];
434         $fdn = preg_replace("/".preg_quote($this->curbase, '/')."/","",$fdn);
435         $fdn= LDAP::fix($fdn);
436         if($value["description"][0]!=".."){
437           $departments[$value['dn']]= convert_department_dn($fdn)." - [".$value["description"][0]."]";
438         }else{
439           $departments[$value['dn']]=convert_department_dn($fdn)." ["._("Back")."]";
440         }
441       }
442     }
444     $linkopen = "<a href='?plug=".$_GET['plug']."&amp;act=depopen&amp;depid=%s'>%s</a>";
446     /* Create base back entry */
447     $base_back = preg_replace("/^[^,]+,/","",$this->curbase);
448     if((strlen($base_back)>= strlen($this->config->current['BASE']))&&($this->curbase!=$this->config->current['BASE'])){
449       $div->AddEntry(array(
450             array("string"=>sprintf($linkopen,base64_encode($base_back),".. ["._("back")."]"),
451               "attach"=>"style='border:0px;'")
452             ));
453     }
455     /* Append departments for current base */
456     foreach($departments as $key => $app){
457       $div->AddEntry(array(
458             array("string"=>"<img class='center' src='images/lists/folder.png' alt='"._("department")."'>&nbsp;".sprintf($linkopen,
459                 base64_encode($key),$app),
460               "attach"=>"style='border:0px;'")
461             ));
462     }
464   
465     /* Add applications found on this base */
466     $used_apps = $this->_get_used_entry_name();
467     foreach($this->apps as $key => $app){
468       if(in_array($app['cn'][0],$used_apps)){
469         continue;
470       }
471       if(!preg_match("/".get_ou('applicationRDN').preg_quote($this->curbase, '/')."$/",$app['dn'])){
472         continue;
473       }
475       $name = $app['cn'][0];
476       if(isset($app['description'])){
477         $name .= "&nbsp;[".$app['description'][0]."]";
478       }
479       $div->AddEntry(array(
480             array("string"=>sprintf("<input class='center' type='checkbox' value='1' name='AddApp_%s'>",$key).
481               "<img class='center' src='plugins/goto/images/select_application.png' alt='"._("application")."'>&nbsp;".$name,
482               "attach"=>"style='border:0px;'")
483             ));
484     }
486     /* Assign copy / paste values 
487      */
488     if(!empty($this->copied_release)){
489       $smarty->assign("copied", TRUE);
490       $smarty->assign("copy_source", $this->copied_release);
491     }else{
492       $smarty->assign("copied", FALSE);
493     }
494     $smarty->assign("enableReleaseManagement",$this->enableReleaseManagement);
495     $smarty->assign("FAIrelease",$this->FAIrelease);
496     $smarty->assign("app_list",$div->DrawList());
497     $smarty->assign("i",0);
498     $smarty->assign("releases",$this->Releases);
499     $smarty->assign("folders" , $this->_get_folder_names());
500     $entries = $this->_get_entries_for_release($this->FAIrelease);
501     $smarty->assign("entries",$entries);
502     $display.= $smarty->fetch (get_template_path('app_list.tpl', TRUE, dirname(__FILE__)));
503     return($display);
504   }
506    
507   /*! \brief Returns all used folder names 
508       @return Array  All used folder names.
509    */ 
510   function _get_folder_names()
511   {
512     $data = $this->_get_entries_for_release($this->FAIrelease);
513     $all    = $this->_get_all_entries();
514     $ret = array("BASE" => ".");
515     foreach($data as $entry){
517       if($entry['TYPE'] == "FOLDER"){
518         $str = $entry['NAME'];
519         $parent = $entry['PARENT'];
520         $i = 10;
521         while(isset($all[$parent]) && $i){  
522           $i --;
523           $parent_o = $all[$parent];
524           $str      = $parent_o['NAME']."/".$str;
525           $parent   = $all[$parent_o['UNIQID']]['PARENT'];
526         }        
527         $ret[$entry['UNIQID']] = $str;
528       }
529     }
530     return($ret);
531   }
534   /*! \brief return all used applications 
535       @return Array  All used applications.
536    */ 
537   function _get_used_entry_name()
538   {
539     $data = $this->_get_entries_for_release($this->FAIrelease);
540     $ret = array();
541     foreach($data as $entry){
542       if($entry['TYPE'] == "ENTRY"){
543         $ret[] = $entry['NAME'];
544       }
545     }
546     return($ret);
547   }
550   /*! \brief Returns all folder an entries for the selected release 
551       @return Array  Returns the complete menu structure for the given array.
552    */ 
553   function _get_entries_for_release($release,$cur = NULL)
554   {
555     $all = $this->_get_all_entries();
556     $key = $this->_get_release_key($release);
557     if(isset($all[$key]) && count($all[$key]['ENTRIES'])){
558       $res = $this->_get_all_entries(TRUE,TRUE,$all[$key]['ENTRIES']);
559       return($res);
560     } 
561     return(array());
562   }
565   /*! \brief Save the currently edited entry 
566     */
567   function _save_entry_edit()
568   {
569     $all    = $this->_get_all_entries();
570     $entry  = $this->edit_entry;
571     $r_entry= &$all[$entry['UNIQID']];
574     if($entry['TYPE'] == "ENTRY"){
575       $r_entry['PARAMETER'] = $this->app_parameter;
576       if($r_entry['STATUS'] != "ADDED"){
577         $r_entry['STATUS'] = "EDITED";
578       } 
579     }
580     if($entry['TYPE'] == "FOLDER"){
581       $r_entry['ICON']   = $this->edit_entry['ICON'];
582       $r_entry['STATUS'] = "EDITED";
583     }
584     $this->dialog = FALSE;
585     $this->edit_entry = array();
586   }
589   /*! \brief prepare the entry with the given ID, to be edited.
590               Read application Parameter from ldap.
591    */
592   function _edit_entry_edit($id)
593   {
594     $all   = $this->_get_all_entries();
595     $entry = $all[$id];
597     $this->app_parameter = array();
598     if($entry['TYPE'] == "ENTRY"){
599       $found = FALSE;
600       foreach($this->apps as $id => $app){
602         if($app['cn'][0] == $entry['NAME']){
603           $found = TRUE;
604           break;
605         }
606       }
607       if($found){
608       
609         /* Create a list of editable parameter */
610         if(isset($app['gosaApplicationParameter'])){
611           for($i = 0 ; $i < $app['gosaApplicationParameter']['count'] ; $i++) {
612             $para = $app['gosaApplicationParameter'][$i];
613             $tmp  = split(":",$para);
614             $this->app_parameter[$tmp[0]] = $tmp[1];
615           }
616         }
618         /* Overwrite parameters with entry parameters */
619         foreach($entry['PARAMETER'] as $name => $value){
620           $this->app_parameter[$name] = $value;
621         }
622         
623         $this->dialog = TRUE;
624         $this->edit_entry = $entry;
625       }
626     }
628     if($entry['TYPE'] == "FOLDER"){
629       $this->dialog = TRUE;
630       $this->edit_entry = $entry;
631     }
632   }
635   /*! \brief Removes the menu structure from ldap 
636    */
637   function remove_from_parent()
638   {
639     $ldap = $this->config->get_ldap_link();
640     $ldap->cd($this->dn);
641     $ldap->ls("(|(objectClass=gotoSubmenuEntry)(objectClass=FAIbranch)(objectClass=gotoMenuEntry))",$this->dn,array("*"));
642     $a_remove = array();
643     while($attrs = $ldap->fetch()){
644       $a_remove[] = $attrs['dn'];
645     }
646     foreach($a_remove as $remove){
647       $ldap->rmdir_recursive($remove);
648       if (!$ldap->success()){
649         msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
650       }
651     }
652     $this->_load_menu_structure();
653   }
656   function check()
657   {
658     $message = plugin::check();
659     return($message);
660   }
663   /*! \brief Create missing releases, if there is a release selected \
664               that is currently not part of the menu structure \
665               then create this entry
666    */
667   function _check_missing_release($release)
668   {
669     $release_info = $this->Releases[$release];
671     $parent_id = $this->a_Structure[0]['UNIQID'];
672     $cur = &$this->a_Structure[0]['ENTRIES'];
673     for($i = 0 ; $i < count($release_info['parts']) ; $i ++){
674       $part = $release_info['parts'][$i];
675       $found = FALSE;
676       foreach($cur as $key => $name){
677         if($name['NAME'] == $part){
678           $parent_id = $cur[$key]['UNIQID'];
679           $cur = &$cur[$key]['ENTRIES'];
680           
681           $found =TRUE;
682           break;
683         }
684       }
685       if(!$found){
686         $release           =  array();
687         $release['UNIQID'] = uniqid();
688         $release['PARENT'] = $parent_id;
689         $release['NAME']   = $part;
690         $release['TYPE']   = "RELEASE";
691         $release['ENTRIES']= array();
692         $release['STATUS']   = "ADDED";
693         $release['FAIstate'] =  $release_info['FAIstate'];
694         $cur[] = $release;
695         $i --;
696       }
697     }
698   }
702   /*! \brief Moves a given object ($id) in a specified direction ($dir).
703       @param  String The object ID of the object we want to move
704       @dir    String Move "up" or "down"
705    */
706   function _move_entry($id,$dir)
707   {
708     $all   = $this->_get_all_entries();
709     if($dir == "down"){
710       $to = $this->_get_next($id);
711     } 
712     if($dir == "up"){
713       $to = $this->_get_last($id);
714     }
716     if(!$to){
717       return;
718     }
720     $o_to   = $all[$to];
721     $o_from = $all[$id];
723     if($o_to['PARENT'] == $o_from['UNIQID'] && $dir == "down"){
724       $to    = $this->_get_next($to,$o_from['PARENT']); 
725       $o_to  = $all[$to]; 
726     }
727  
728     /* Target is ENTRY && same BASE, just switch */
729     if($o_to['PARENT'] == $o_from['PARENT'] ){
730       $parent = $all[$o_to['PARENT']];
731       $pos = 0;
732       foreach($parent['ENTRIES'] as $entry){
733         $pos ++;
734         if($entry['UNIQID'] == $to){
735           break;
736         }
737       }
738       if($dir == "up" && $pos > 0){
739         $pos --;
740       }
741       $this->_add_entry($parent['UNIQID'],$o_from,$pos);
742       $this->_remove_entry_id($id);
743       return(TRUE);
744     }
745     return(FALSE);
746   }
749    
750   /*! \brief  Returns the railing object ID of the given object.
751       @return String  The id of the trailing object.
752    */ 
753   function _get_last($id)
754   {
755     $all_l = array_reverse($this->_get_entries_for_release($this->FAIrelease));
756     for($i = 0 ; $i < count($all_l) ; $i ++){
757       if(isset($all_l[$i]['UNIQID']) && $all_l[$i]['UNIQID'] == $id){
758         $i++;
759         break;
760       }
761     }
762     while(isset($all_l[$i]) && !in_array($all_l[$i]['TYPE'],array("ENTRY","FOLDER","CLOSE","OPEN")) && $i < count($all_l)){
763       $i++;
764     }
766     if(!isset($all_l[$i])){
767       return(FALSE);
768     }
770     if(in_array($all_l[$i]['TYPE'],array("CLOSE","OPEN"))){
771       return($all_l[$i]['PARENT']);
772     }     
774     return($all_l[$i]['UNIQID']);
775   }
778   /*! \brief  Returns the following object ID of the given object.
779       @return String  The id of the following object.
780    */ 
781   function _get_next($id,$parent = 0)
782   {
783     $all_l = $this->_get_entries_for_release($this->FAIrelease);
784     for($i = 0 ; $i < count($all_l) ; $i ++){
785       if(isset($all_l[$i]['UNIQID']) && $all_l[$i]['UNIQID'] == $id){
786         $i++;
787         break;
788       }
789     }
790     if($parent != 0){
791       while(isset($all_l[$i]) && $all_l[$i]['PARENT'] != $parent){
792         $i++;
793       }
794     }else{
795       while(isset($all_l[$i]) && !in_array($all_l[$i]['TYPE'],array("ENTRY","FOLDER")) && $i < count($all_l)){
796         $i++;
797       }
798     }
799     if(!isset($all_l[$i])){
800       return(FALSE);
801     }
802     if(in_array($all_l[$i]['TYPE'],array("CLOSE","OPEN"))){
803       return($all_l[$i]['PARENT']);
804     }
805     return($all_l[$i]['UNIQID']);
806   }
811   /* !\brief Handle ui POSTS, like sort up/down/delete
812    */ 
813   function save_object()
814   {
815     foreach($_POST as $name => $value){
817       if(preg_match("/^menu_copy_/",$name)){
818         $this->copied_release = $this->FAIrelease;
819         break;
820       }
821       if(preg_match("/^menu_delete/",$name)){
822         $current_rel  = $this->_get_release_key($this->FAIrelease); 
823         $this->_remove_entry_id($current_rel);
824         break;
825       }
826       if(preg_match("/^menu_paste_/",$name)){
827         $source_rel   = $this->_get_release_key($this->copied_release); 
828         $current_rel  = $this->_get_release_key($this->FAIrelease);
830         $all = $this->_get_all_entries();
831         $menu = $all[$source_rel]['ENTRIES'];
832     
833         foreach($menu as $entry){
834           if(in_array($entry['TYPE'],array("FOLDER","ENTRY","SEPERATOR"))){
835             $this->_add_entry($current_rel,$entry,-1);
836           }
837         }
838         $this->copied_release = "";
839         break;
840       }
842       if(preg_match("/del_/",$name)){
843         $id = preg_replace("/^del_/","",$name);
844         $id = preg_replace("/_(x|y)$/","",$id);
845         $this->_remove_entry_id($id);
846         break;
847       }
848       if(preg_match("/app_entry_edit/",$name)){
849         $id = preg_replace("/^app_entry_edit/","",$name);
850         $id = preg_replace("/_(x|y)$/","",$id);
851         $this->_edit_entry_edit($id);
852         break;
853       }
854       if(preg_match("/up_/",$name)){
855         $id = preg_replace("/^up_/","",$name);
856         $id = preg_replace("/_(x|y)$/","",$id);
857         $this->_move_entry($id,"up");
858         break;
859       }
860       if(preg_match("/down_/",$name)){
861         $id = preg_replace("/^down_/","",$name);
862         $id = preg_replace("/_(x|y)$/","",$id);
863         $this->_move_entry($id,"down");
864         break;
865       }
866       if(preg_match("/^parameter_/",$name) && 
867         count($this->edit_entry) && $this->edit_entry['TYPE'] == "ENTRY"){
868         $name = preg_replace("/^parameter_/","",$name);
869         $this->app_parameter[$name] = $value;
870       }
871     }
872     if(isset($_POST['FAIrelease'])){
873       $this->FAIrelease = $_POST['FAIrelease'];
874       $this->_check_missing_release($this->FAIrelease);
875     }
876     if(isset($_GET['act']) && $_GET['act'] == 'depopen'){
877       $this->curbase = base64_decode($_GET['depid']);
878     }
879     if(isset($_POST['add_to_folder']) && isset($_POST['folder'])){
880       $folder = $_POST['folder'];
881       foreach($_POST as $name => $value){
882         if(preg_match("/^AddApp_[0-9]*$/",$name)){
883           $this->_add_app_id($folder,preg_replace("/^AddApp_/","",$name));   
884         }
885       }
886     }
888     /* Add seperator */
889     if(isset($_POST['add_seperator']) && isset($_POST['menu_folder'])){
890       $folder = $_POST['menu_folder'];
891       $this->_add_seperator($folder);
892     }
894     if(isset($_POST['add_menu_to_folder']) && isset($_POST['menu_folder'])){
895       $folder = $_POST['menu_folder'];
896       $name = $_POST['menu_folder_name'];
897       if(strlen($name) > 0 && preg_match("/[a-z ]/i",$name)){
898         $this->_add_sub_folder($folder,$name);
899       }
900     }
901     if(isset($_POST['app_entry_save'])){ 
902       $this->_save_entry_edit();
903     }
905     if(isset($_FILES['folder_image']) && isset($_POST['folder_image_upload'])){
906       if($_FILES['folder_image']['error'] == 0 && $_FILES['folder_image']['size'] > 0){
907         $this->edit_entry['ICON'] = file_get_contents($_FILES['folder_image']['tmp_name']);
908       }
909     }
911     if(isset($_POST['edit_reset_image'])){
912       $this->edit_entry['ICON'] = "";
913     }
915     if(isset($_POST['app_entry_cancel'])){
916       $this->edit_entry = array();
917       $this->dialog = FALSE;
918     }
919     $this->reload();
920   }
922  
923   /*! \brief Returns the UNIQID of the currently selected release 
924    */ 
925   function _get_release_key($release,$add_if_missing = FALSE)
926   {
927     $release_info = $this->Releases[$release];
929     if($release_info['name'] == "/"){
930       return($this->a_Structure['0']['UNIQID']);
931     }
933     $cur = &$this->a_Structure[0]['ENTRIES'];
934     $s_key = "";
935     $found = FALSE;
936     foreach($release_info['parts'] as $name){
937       foreach($cur as $key => $obj){
938         if($obj['TYPE'] == "RELEASE" && $obj['NAME'] == $name){
939           $s_key = $cur[$key]['UNIQID'];
940           $cur = &$cur[$key]['ENTRIES'];
941           $found = TRUE;
942           break;
943         }
944         $found = FALSE;
945       }
946     }
947     if($found){
948       return($s_key);  
949     }  
950     return(FALSE);
951   }
953  
954   /*! \brief Add a new folder folder to the specified folder id
955       @param  String $folder The folder id in where we want to add the new folder.
956       @param  String $name   The name of the new folder.
957    */ 
958   function _add_sub_folder($folder,$name)
959   {
960     $all = $this->_get_all_entries();
961     if($folder == "BASE"){
962       $folder = $this->_get_release_key($this->FAIrelease,TRUE);
963     }
964     
965     if(isset($all[$folder])){
966       $a_folder = array();
967       $a_folder['STATUS'] = "ADDED";
968       $a_folder['NAME']   = $name;
969       $a_folder['UNIQID'] = uniqid();
970       $a_folder['ENTRIES']= array();
971       $a_folder['PARENT'] = $folder;      
972       $a_folder['TYPE']   = "FOLDER";
973       $a_folder['ICON']   = "";
974       $all[$folder]['ENTRIES'][] = $a_folder;
975     }
976   }
979   /* !\brief  Remove the given id from the menu structure.
980       @param  String  ID to of the entry we want to remove.
981       @return Boolean TRUE on success
982    */
983   function _remove_entry_id($id)
984   {
985     $all = $this->_get_all_entries();
986     if(isset($all[$id])){
987       $all[$id]['STATUS'] = "REMOVED";
988       $all[$id]['ENTRIES'] = array();
989       return(TRUE);
990     }
991     return(FALSE);
992   }
994   
995   /* !\brief  Adds an object to a given folder.
996       @param  String  The folder where we should add the entry
997       @param  Array   The entry we want to add.
998       @param  Array   The position in the destination entry array.
999    */
1000   function _add_entry($folder_id,$entry,$pos = 0)
1001   {
1002     $all = $this->_get_all_entries();
1004     /* Do not add removed */
1005     if($entry['STATUS'] == "REMOVED"){
1006       return;
1007     }
1009     /* Check if the folder exists 
1010      */
1011     if(isset($all[$folder_id])){
1013       /* Check if the entry we want to add, 
1014           contains su objects.
1015        */
1016       if(!isset($entry['ENTRIES'])){
1017         $entries = array();
1018       }else{
1019         $entries = $entry['ENTRIES'];
1020       }
1021       $folder  = &$all[$folder_id];
1023       /* Prepare the entry to be added.
1024        */
1025       $entry['UNIQID'] = uniqid();     
1026       $entry['PARENT'] = $folder_id;
1027       $entry['ENTRIES']= array();
1028       $entry['STATUS'] = "ADDED";
1029      
1030       /* Append the ebtry to the given folder 
1031           and to the given position \$pos
1032        */ 
1033       $cnt = 0; 
1034       $new = array();
1035       $added =FALSE;
1036       foreach($folder['ENTRIES'] as $key => $obj){
1037         if($obj['STATUS'] == "LOADED"){
1038           $obj['STATUS'] = "EDITED";
1039         }
1040         if($pos == $cnt){
1041           $new[] = $entry;
1042           $added = TRUE;
1043         }
1044         $cnt ++;
1045         $new[] = $obj;
1046       }
1047       if(!$added){
1048         $new[] = $entry;
1049       }
1050       $all[$folder_id]['ENTRIES'] = &$new;
1051  
1052       /* Add sub entries too.
1053        */ 
1054       foreach($entries as $sub){
1055         $this->_add_entry($entry['UNIQID'],$sub,-1);
1056       }
1057       return(TRUE);
1058     }
1059     return(FALSE);
1060   }
1062  
1063   /*! \brief Add the application identified by $app_id to folder $folder_id 
1064       @param  String  folder_id The UNIQID of the folder where we want to add the new folder.
1065       @param  Integer app_id    The ID of the application which should be added.
1066    */ 
1067   function _add_app_id($folder_id,$app_id)
1068   {
1069     $all = $this->_get_all_entries();
1070     if($folder_id == "BASE"){
1071       $folder_id = $this->_get_release_key($this->FAIrelease);
1072     }
1073     if(isset($all[$folder_id]) && isset($this->apps[$app_id])){
1075       $new = array();
1076       $new['TYPE']  = "ENTRY";
1077       $new['NAME']  = $this->apps[$app_id]['cn'][0];
1078       $new['UNIQID']= uniqid(); 
1079       $new['PARENT']= $folder_id;
1080       $new['PARAMETER']= array();
1081       if(isset($this->apps[$app_id]['description'][0])){
1082         $new['INFO']  = $this->apps[$app_id]['description'][0];
1083       }else{
1084         $new['INFO']  = "";
1085       }
1086       $new['STATUS']= "ADDED";
1087       $all[$folder_id]['ENTRIES'][] = $new;
1088     }
1089   }
1092   /*! \brief Add the application identified by $app_id to folder $folder_id 
1093       @param  String  folder_id The UNIQID of the folder where we want to add the new folder.
1094       @param  Integer app_id    The ID of the application which should be added.
1095    */ 
1096   function _add_seperator($folder_id)
1097   {
1098     $all = $this->_get_all_entries();
1099     if($folder_id == "BASE"){
1100       $folder_id = $this->_get_release_key($this->FAIrelease);
1101     }
1103     if(isset($all[$folder_id])){
1104       $new = array();
1105       $new['TYPE']  = "SEPERATOR";
1106       $new['NAME']  = "SEPERATOR";
1107       $new['UNIQID']= uniqid(); 
1108       $new['PARENT']= $folder_id;
1109       $new['PARAMETER']= array();
1110       $new['STATUS']= "ADDED";
1111       $all[$folder_id]['ENTRIES'][] = $new;
1112     }
1113   }
1116   /*! \brief  Return all entries linear. ($this->a_Structure is a multidimensional array) 
1117       @param  Boolean   $add_tags  If TRUE, OPEN/CLOSE Tags will be appended.
1118                         Used in the smarty template to display logical sperations.
1119       @param  &Array    Start here, Pointer to an array.
1120    */ 
1121   function _get_all_entries($add_tags = FALSE, $skip_release = FALSE, &$cur = NULL)
1122   {
1123     $ret = array();
1124     if($cur == NULL){
1125       $cur = &$this->a_Structure;
1126     }
1128     /* Walk through all entries and append them to our return array 
1129      */
1130     foreach($cur as $key => $entry){
1131       if($skip_release && $entry['TYPE'] == "RELEASE"){
1132         continue;
1133       }    
1134       if($entry['TYPE'] == "ENTRY"){
1135         $found = FALSE;
1136         foreach($this->apps as $app){
1137           if($app['cn'][0] == $entry['NAME']){
1138             $found = TRUE;
1139             if(isset($app['description'][0])){
1140               $entry['INFO'] = "[".$app['description'][0]."]";
1141             }
1142             break;
1143           }
1144         } 
1145         if(!$found){
1146           $entry['INFO'] = "<font color='red'>"._("Not available in release.")."</font>";
1147         }
1148       }
1150       $tmp = $entry;
1151   
1152       /* Recursive resolution of the subentries  
1153          There are two methods.
1154             - Just add sub entries  
1155             - Add sub entries and additionaly add OPEN / CLOSE tags to be able 
1156                 to display logical seperators in the smarty template.
1157        */ 
1158       if(!$add_tags){
1159         $ret[$tmp['UNIQID']] = &$cur[$key];
1160         if(isset($entry['ENTRIES']) && count($entry['ENTRIES'])){
1161           $ret = array_merge($ret,$this->_get_all_entries($add_tags,$skip_release,$cur[$key]['ENTRIES']));
1162         }
1163       }else{
1164       
1165         if(isset($tmp['ENTRIES'])){
1166           unset($tmp['ENTRIES']);
1167         }
1168         if($tmp['STATUS'] != "REMOVED"){
1169           $ret[] = $tmp;
1170           if(isset($entry['ENTRIES']) && count($entry['ENTRIES'])){
1171             $add = false;
1172             foreach($entry['ENTRIES'] as $entry){
1173               if($entry['STATUS'] != "REMOVED"){
1174                 $add = TRUE;
1175                 break;
1176               }
1177             }
1179             if($add){
1180               $ret[] = array("TYPE" => "OPEN", "PARENT" => $entry['PARENT']);
1181               $ret = array_merge($ret,$this->_get_all_entries($add_tags,$skip_release,$cur[$key]['ENTRIES']));
1182               $ret[] = array("TYPE" => "CLOSE" , "PARENT" => $entry['PARENT']);
1183             }
1184           }
1185         }
1186       }
1187     }
1188     return($ret);
1189   }
1192   /*! \brief Save this plugin data to ldap.
1193              Save the current menu structure to ldap.
1194    */
1195   function save()
1196   {
1197     $ldap = $this->config->get_ldap_link();
1198     $all = $this->_get_all_entries();
1199     $prio = 0;
1200     $Actions = array("Remove" => array(),"Edit" => array() , "Add" => array());
1202     /* Walk through the menu structure and build up the ldap data object, 
1203         the entry dn and the entry priority.
1204      */
1205     $sep_id = 0;
1206     foreach($all as $entry){
1207       $prio ++;
1208       $cur = $entry;
1209       $dn = "";
1211       /* Build entry dn
1212        */
1213       do{  
1214         if($cur['TYPE'] == "SEPERATOR"){
1215           $sep_id ++;
1216           $dn.= "cn=seperator_".$sep_id.",";
1217         }elseif($cur['TYPE'] == "ENTRY"){
1218           $dn.= "cn=".$cur['NAME'].",";
1219         }elseif($cur['TYPE'] == "FOLDER"){
1220           $dn.= "cn=".$cur['NAME'].",";
1221         }elseif($cur['TYPE'] == "RELEASE"){
1222           $dn.= "ou=".$cur['NAME'].",";
1223         }elseif($cur['TYPE'] == "BASE"){
1224         }
1225         if(!isset($all[$cur['PARENT']])){
1226           $cur = NULL;
1227         }else{
1228           $cur = $all[$cur['PARENT']];
1229         }
1230       }while(is_array($cur));
1232       $cur_dn = $dn.$this->dn;
1233       $attrs = array();
1235       /* Build entry data object.
1236        */
1237       switch($entry['TYPE']){
1238         case "SEPERATOR"    :
1239         { 
1240           $attrs['objectClass'] = array("gotoMenuEntry");
1241           $attrs['cn']          = "seperator_".$sep_id;
1242           $attrs['gosaApplicationPriority'] = $prio;
1243           $attrs['gosaApplicationParameter'] = "*separator*";
1244         }
1245         break;
1246         case "ENTRY"    :
1247         { 
1248           $attrs['objectClass'] = array("gotoMenuEntry");
1249           $attrs['cn']          = $entry['NAME'];
1250           $attrs['gosaApplicationPriority'] = $prio;
1251           $attrs['gosaApplicationParameter'] = array(); 
1252           
1253           foreach($entry['PARAMETER'] as $name => $value){
1254             $attrs['gosaApplicationParameter'][] = $name.":".$value; 
1255           }
1256           if($entry['STATUS'] == "ADDED" && !count($attrs['gosaApplicationParameter'])){
1257             unset($attrs['gosaApplicationParameter']);
1258           } 
1259         }
1260         break;
1261         case "FOLDER"   : 
1262         { 
1263           $attrs['objectClass'] = array("gotoSubmenuEntry");
1264           $attrs['cn']          = $entry['NAME'];
1265           $attrs['gosaApplicationPriority'] = $prio;
1266           if($entry['STATUS'] != "ADDED"){
1267             $attrs['gosaApplicationIcon'] = array();
1268           }
1269           
1270           if(!empty($entry['ICON'])){
1271             $attrs['gosaApplicationIcon']     = $entry['ICON'];
1272           }
1273         }
1274         break;
1275         case "RELEASE"  : 
1276         {
1277           $attrs['ou']            = $entry['NAME'];
1278           $attrs['objectClass']   = array();
1279           $attrs['objectClass'][] = "top";
1280           $attrs['objectClass'][] = "organizationalUnit";
1281           $attrs['objectClass'][] = "FAIbranch";
1282           if(!empty($entry['FAIstate'])){
1283             $attrs['FAIstate']      = $entry['FAIstate'];
1284           }
1285         }
1286         break;
1287       }
1288  
1289       /* Append missing ObjectClasses,  ...  Tagging 
1290        */
1291       if(isset($entry['LDAP_ATTRS'])){
1292         for($i = 0 ; $i < $entry['LDAP_ATTRS']['objectClass']['count']; $i ++){
1293           $oc = $entry['LDAP_ATTRS']['objectClass'][$i];
1294           if(!in_array($oc,$attrs['objectClass'])){
1295             $attrs['objectClass'][] = $oc;
1296           }
1297         }
1298       }
1299   
1300       /* Create an array containing all operations sorted by type. (add,remove...)
1301        */
1302       if($entry['STATUS'] == "LOADED"){
1303         continue;
1304       }
1305       if($entry['STATUS'] == "REMOVED"){
1306         if(isset($entry['DN'])){
1307           $Actions['Remove'][$entry['DN']] = $entry['DN'];
1308         }else{
1309           $Actions['Remove'][$cur_dn] = $cur_dn;
1310         }
1311       }
1312       if($entry['STATUS'] == "EDITED"){
1313         $Actions['Edit'][$cur_dn] = $attrs;
1314       }
1315       if($entry['STATUS'] == "ADDED"){
1316         $Actions['Add'][$cur_dn] = $attrs;
1317       }
1318     }
1320     /* First remove entries
1321      */
1322     $ldap = $this->config->get_ldap_link();
1323     $ldap->cd($this->config->current['BASE']);
1324     foreach($Actions['Remove'] as $dn){
1325       $ldap->cd($dn);
1326       $ldap->cat($dn);
1327       if($ldap->count()){
1328         $ldap->rmdir_recursive($dn);
1329         if (!$ldap->success()){
1330           msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_DEL, get_class()));
1331         }
1332       }
1333     }
1334     
1335     /* Add new entries
1336      */
1337     foreach($Actions['Add'] as $dn => $data){
1338       $this->tag_attrs($data,$dn,$this->gosaUnitTag);
1339       $ldap->cd($dn);
1340       $ldap->cat($dn);
1341       if(!$ldap->count()){
1342         $ldap->add($data);
1343         if (!$ldap->success()){
1344           msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_ADD, get_class()));
1345         }
1346       }
1347     }
1349     /* Modify entries
1350      */
1351     foreach($Actions['Edit'] as $dn => $data){
1352       $this->tag_attrs($data,$dn,$this->gosaUnitTag);
1353       $ldap->cd($dn);
1354       $ldap->cat($dn);
1355       if($ldap->count()){
1356         $ldap->modify($data);
1357         if (!$ldap->success()){
1358           msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD, get_class()));
1359         }
1360       }
1361     }
1363     $this->_load_menu_structure();
1364   }
1367   /*! \brief  Return plugin informations for acl handling  
1368       @return Array containing all plugin ACL informations
1369    */ 
1370   static function plInfo()
1371   {
1372     return (array(
1373           "plShortName"   => _("Applications"),
1374           "plDescription" => _("Group applications"),
1375           "plSelfModify"  => FALSE,
1376           "plDepends"     => array(),
1377           "plPriority"    => 7,
1378           "plSection"     => array("administration"),
1379           "plCategory"    => array("groups"),
1380           "plProvidedAcls"=> array(
1381             "gosaMemberApplication"     => _("Application"),
1382             "FAIrelease"                => _("Release"),
1383             "gosaApplicationParameter"  => _("Application parameter"))
1384           ));
1385   }
1388   /* \brief   Prepare this plugin to be copied.
1389               Adapt all required attributes from the source object.
1390               In this case, update the menu structure too, mark all elements
1391                as newly added, so they will be saved in save();
1392    */
1393   function PrepareForCopyPaste($source)
1394   {
1395     plugin::PrepareForCopyPaste($source);
1396    
1397     $tmp = new appgroup($this->config,$source['dn']);
1398     $this->is_account = TRUE;
1399     $this->a_Structure = $tmp->a_Structure;
1400     $all = $this->_get_all_entries();
1401     foreach($all as &$entry){
1402       if(isset($entry['STATUS'])){
1403         $entry['STATUS'] = "ADDED";
1404       }
1405     }
1406   }
1409   /*! \brief  Save HTML posts in multiple edit mode
1410    */
1411   function multiple_save_object()
1412   {
1413     if(isset($_POST['group_apps_multi'])){
1414       $this->save_object(); 
1415       plugin::multiple_save_object();    
1416   
1417       /* Get posts */
1418       foreach(array("apps") as $attr){
1419         if(isset($_POST['use_'.$attr])) {
1420           $this->multi_boxes[] = $attr;
1421         }
1422       }
1423     }
1424   }
1425   
1427   /*! \brief  Return values used in multiple edit mode.
1428               Some values can be modified for multiple 
1429               groups at the same time.
1430       @return Array  All values that support multiple edit.
1431    */
1432   function get_multi_edit_values()
1433   {
1434     $ret = plugin::get_multi_edit_values();
1436     if(in_array("apps",$this->multi_boxes)){
1437       $ret['gosaApplicationParameter'] = $this->gosaApplicationParameter;
1438       $ret['Categories']               = $this->Categories;
1439       $ret['gosaMemberApplication']    = $this->gosaMemberApplication;
1440       $ret['FAIrelease']               = $this->FAIrelease;
1441       $ret['appoption']                = $this->appoption;
1442     }
1443     return($ret);
1444   }
1446 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1447 ?>