Code

5e3b15c7ed3a9b8a42ee46e592ae4af8654b637a
[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     }
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("SEPERATOR","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("SEPERATOR","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   }
808   /* !\brief Handle ui POSTS, like sort up/down/delete
809    */ 
810   function save_object()
811   {
812     foreach($_POST as $name => $value){
814       if(preg_match("/^menu_copy_/",$name)){
815         $this->copied_release = $this->FAIrelease;
816         break;
817       }
818       if(preg_match("/^menu_delete/",$name)){
819         $current_rel  = $this->_get_release_key($this->FAIrelease); 
820         $this->_remove_entry_id($current_rel);
821         break;
822       }
823       if(preg_match("/^menu_paste_/",$name)){
824         $source_rel   = $this->_get_release_key($this->copied_release); 
825         $current_rel  = $this->_get_release_key($this->FAIrelease);
827         $all = $this->_get_all_entries();
828         $menu = $all[$source_rel]['ENTRIES'];
829     
830         foreach($menu as $entry){
831           if(in_array($entry['TYPE'],array("FOLDER","ENTRY","SEPERATOR"))){
832             $this->_add_entry($current_rel,$entry,-1);
833           }
834         }
835         $this->copied_release = "";
836         break;
837       }
839       if(preg_match("/del_/",$name)){
840         $id = preg_replace("/^del_/","",$name);
841         $id = preg_replace("/_(x|y)$/","",$id);
842         $this->_remove_entry_id($id);
843         break;
844       }
845       if(preg_match("/app_entry_edit/",$name)){
846         $id = preg_replace("/^app_entry_edit/","",$name);
847         $id = preg_replace("/_(x|y)$/","",$id);
848         $this->_edit_entry_edit($id);
849         break;
850       }
851       if(preg_match("/up_/",$name)){
852         $id = preg_replace("/^up_/","",$name);
853         $id = preg_replace("/_(x|y)$/","",$id);
854         $this->_move_entry($id,"up");
855         break;
856       }
857       if(preg_match("/down_/",$name)){
858         $id = preg_replace("/^down_/","",$name);
859         $id = preg_replace("/_(x|y)$/","",$id);
860         $this->_move_entry($id,"down");
861         break;
862       }
863       if(preg_match("/^parameter_/",$name) && 
864         count($this->edit_entry) && $this->edit_entry['TYPE'] == "ENTRY"){
865         $name = preg_replace("/^parameter_/","",$name);
866         $this->app_parameter[$name] = $value;
867       }
868     }
869     if(isset($_POST['FAIrelease'])){
870       $this->FAIrelease = $_POST['FAIrelease'];
871       $this->_check_missing_release($this->FAIrelease);
872     }
873     if(isset($_GET['act']) && $_GET['act'] == 'depopen'){
874       $this->curbase = base64_decode($_GET['depid']);
875     }
876     if(isset($_POST['add_to_folder']) && isset($_POST['folder'])){
877       $folder = $_POST['folder'];
878       foreach($_POST as $name => $value){
879         if(preg_match("/^AddApp_[0-9]*$/",$name)){
880           $this->_add_app_id($folder,preg_replace("/^AddApp_/","",$name));   
881         }
882       }
883     }
885     /* Add seperator */
886     if(isset($_POST['add_seperator']) && isset($_POST['menu_folder'])){
887       $folder = $_POST['menu_folder'];
888       $this->_add_seperator($folder);
889     }
891     if(isset($_POST['add_menu_to_folder']) && isset($_POST['menu_folder'])){
892       $folder = $_POST['menu_folder'];
893       $name = $_POST['menu_folder_name'];
894       if(strlen($name) > 0 && preg_match("/[a-z ]/i",$name)){
895         $this->_add_sub_folder($folder,$name);
896       }
897     }
898     if(isset($_POST['app_entry_save'])){ 
899       $this->_save_entry_edit();
900     }
902     if(isset($_FILES['folder_image']) && isset($_POST['folder_image_upload'])){
903       if($_FILES['folder_image']['error'] == 0 && $_FILES['folder_image']['size'] > 0){
904         $this->edit_entry['ICON'] = file_get_contents($_FILES['folder_image']['tmp_name']);
905       }
906     }
908     if(isset($_POST['edit_reset_image'])){
909       $this->edit_entry['ICON'] = "";
910     }
912     if(isset($_POST['app_entry_cancel'])){
913       $this->edit_entry = array();
914       $this->dialog = FALSE;
915     }
916     $this->reload();
917   }
919  
920   /*! \brief Returns the UNIQID of the currently selected release 
921    */ 
922   function _get_release_key($release,$add_if_missing = FALSE)
923   {
924     $release_info = $this->Releases[$release];
926     if($release_info['name'] == "/"){
927       return($this->a_Structure['0']['UNIQID']);
928     }
930     $cur = &$this->a_Structure[0]['ENTRIES'];
931     $s_key = "";
932     $found = FALSE;
933     foreach($release_info['parts'] as $name){
934       foreach($cur as $key => $obj){
935         if($obj['TYPE'] == "RELEASE" && $obj['NAME'] == $name){
936           $s_key = $cur[$key]['UNIQID'];
937           $cur = &$cur[$key]['ENTRIES'];
938           $found = TRUE;
939           break;
940         }
941         $found = FALSE;
942       }
943     }
944     if($found){
945       return($s_key);  
946     }  
947     return(FALSE);
948   }
950  
951   /*! \brief Add a new folder folder to the specified folder id
952       @param  String $folder The folder id in where we want to add the new folder.
953       @param  String $name   The name of the new folder.
954    */ 
955   function _add_sub_folder($folder,$name)
956   {
957     $all = $this->_get_all_entries();
958     if($folder == "BASE"){
959       $folder = $this->_get_release_key($this->FAIrelease,TRUE);
960     }
961     
962     if(isset($all[$folder])){
963       $a_folder = array();
964       $a_folder['STATUS'] = "ADDED";
965       $a_folder['NAME']   = $name;
966       $a_folder['UNIQID'] = uniqid();
967       $a_folder['ENTRIES']= array();
968       $a_folder['PARENT'] = $folder;      
969       $a_folder['TYPE']   = "FOLDER";
970       $a_folder['ICON']   = "";
971       $all[$folder]['ENTRIES'][] = $a_folder;
972     }
973   }
976   /* !\brief  Remove the given id from the menu structure.
977       @param  String  ID to of the entry we want to remove.
978       @return Boolean TRUE on success
979    */
980   function _remove_entry_id($id)
981   {
982     $all = $this->_get_all_entries();
983     if(isset($all[$id])){
984       $all[$id]['STATUS'] = "REMOVED";
985       $all[$id]['ENTRIES'] = array();
986       return(TRUE);
987     }
988     return(FALSE);
989   }
991   
992   /* !\brief  Adds an object to a given folder.
993       @param  String  The folder where we should add the entry
994       @param  Array   The entry we want to add.
995       @param  Array   The position in the destination entry array.
996    */
997   function _add_entry($folder_id,$entry,$pos = 0)
998   {
999     $all = $this->_get_all_entries();
1001     /* Do not add removed */
1002     if($entry['STATUS'] == "REMOVED"){
1003       return;
1004     }
1006     /* Check if the folder exists 
1007      */
1008     if(isset($all[$folder_id])){
1010       /* Check if the entry we want to add, 
1011           contains su objects.
1012        */
1013       if(!isset($entry['ENTRIES'])){
1014         $entries = array();
1015       }else{
1016         $entries = $entry['ENTRIES'];
1017       }
1018       $folder  = &$all[$folder_id];
1020       /* Prepare the entry to be added.
1021        */
1022       $entry['UNIQID'] = uniqid();     
1023       $entry['PARENT'] = $folder_id;
1024       $entry['ENTRIES']= array();
1025       $entry['STATUS'] = "ADDED";
1026      
1027       /* Append the ebtry to the given folder 
1028           and to the given position \$pos
1029        */ 
1030       $cnt = 0; 
1031       $new = array();
1032       $added =FALSE;
1033       foreach($folder['ENTRIES'] as $key => $obj){
1034         if($obj['STATUS'] == "LOADED"){
1035           $obj['STATUS'] = "EDITED";
1036         }
1037         if($pos == $cnt){
1038           $new[] = $entry;
1039           $added = TRUE;
1040         }
1041         $cnt ++;
1042         $new[] = $obj;
1043       }
1044       if(!$added){
1045         $new[] = $entry;
1046       }
1047       $all[$folder_id]['ENTRIES'] = &$new;
1048  
1049       /* Add sub entries too.
1050        */ 
1051       foreach($entries as $sub){
1052         $this->_add_entry($entry['UNIQID'],$sub,-1);
1053       }
1054       return(TRUE);
1055     }
1056     return(FALSE);
1057   }
1059  
1060   /*! \brief Add the application identified by $app_id to folder $folder_id 
1061       @param  String  folder_id The UNIQID of the folder where we want to add the new folder.
1062       @param  Integer app_id    The ID of the application which should be added.
1063    */ 
1064   function _add_app_id($folder_id,$app_id)
1065   {
1066     $all = $this->_get_all_entries();
1067     if($folder_id == "BASE"){
1068       $folder_id = $this->_get_release_key($this->FAIrelease);
1069     }
1070     if(isset($all[$folder_id]) && isset($this->apps[$app_id])){
1072       $new = array();
1073       $new['TYPE']  = "ENTRY";
1074       $new['NAME']  = $this->apps[$app_id]['cn'][0];
1075       $new['UNIQID']= uniqid(); 
1076       $new['PARENT']= $folder_id;
1077       $new['PARAMETER']= array();
1078       if(isset($this->apps[$app_id]['description'][0])){
1079         $new['INFO']  = $this->apps[$app_id]['description'][0];
1080       }else{
1081         $new['INFO']  = "";
1082       }
1083       $new['STATUS']= "ADDED";
1084       $all[$folder_id]['ENTRIES'][] = $new;
1085     }
1086   }
1089   /*! \brief Add the application identified by $app_id to folder $folder_id 
1090       @param  String  folder_id The UNIQID of the folder where we want to add the new folder.
1091       @param  Integer app_id    The ID of the application which should be added.
1092    */ 
1093   function _add_seperator($folder_id)
1094   {
1095     $all = $this->_get_all_entries();
1096     if($folder_id == "BASE"){
1097       $folder_id = $this->_get_release_key($this->FAIrelease);
1098     }
1100     if(isset($all[$folder_id])){
1101       $new = array();
1102       $new['TYPE']  = "SEPERATOR";
1103       $new['NAME']  = "SEPERATOR";
1104       $new['UNIQID']= uniqid(); 
1105       $new['PARENT']= $folder_id;
1106       $new['PARAMETER']= array();
1107       $new['STATUS']= "ADDED";
1108       $all[$folder_id]['ENTRIES'][] = $new;
1109     }
1110   }
1113   /*! \brief  Return all entries linear. ($this->a_Structure is a multidimensional array) 
1114       @param  Boolean   $add_tags  If TRUE, OPEN/CLOSE Tags will be appended.
1115                         Used in the smarty template to display logical sperations.
1116       @param  &Array    Start here, Pointer to an array.
1117    */ 
1118   function _get_all_entries($add_tags = FALSE, $skip_release = FALSE, &$cur = NULL)
1119   {
1120     $ret = array();
1121     if($cur == NULL){
1122       $cur = &$this->a_Structure;
1123     }
1125     /* Walk through all entries and append them to our return array 
1126      */
1127     foreach($cur as $key => $entry){
1128       if($skip_release && $entry['TYPE'] == "RELEASE"){
1129         continue;
1130       }    
1131       if($entry['TYPE'] == "ENTRY"){
1132         $found = FALSE;
1133         foreach($this->apps as $app){
1134           if($app['cn'][0] == $entry['NAME']){
1135             $found = TRUE;
1136             if(isset($app['description'][0])){
1137               $entry['INFO'] = "[".$app['description'][0]."]";
1138             }
1139             break;
1140           }
1141         } 
1142         if(!$found){
1143           $entry['INFO'] = "<font color='red'>"._("Not available in release.")."</font>";
1144         }
1145       }
1147       $tmp = $entry;
1148   
1149       /* Recursive resolution of the subentries  
1150          There are two methods.
1151             - Just add sub entries  
1152             - Add sub entries and additionaly add OPEN / CLOSE tags to be able 
1153                 to display logical seperators in the smarty template.
1154        */ 
1155       if(!$add_tags){
1156         $ret[$tmp['UNIQID']] = &$cur[$key];
1157         if(isset($entry['ENTRIES']) && count($entry['ENTRIES'])){
1158           $ret = array_merge($ret,$this->_get_all_entries($add_tags,$skip_release,$cur[$key]['ENTRIES']));
1159         }
1160       }else{
1161       
1162         if(isset($tmp['ENTRIES'])){
1163           unset($tmp['ENTRIES']);
1164         }
1165         if($tmp['STATUS'] != "REMOVED"){
1166           $ret[] = $tmp;
1167           if(isset($entry['ENTRIES']) && count($entry['ENTRIES'])){
1168             $add = false;
1169             foreach($entry['ENTRIES'] as $entry){
1170               if($entry['STATUS'] != "REMOVED"){
1171                 $add = TRUE;
1172                 break;
1173               }
1174             }
1176             if($add){
1177               $ret[] = array("TYPE" => "OPEN", "PARENT" => $entry['PARENT']);
1178               $ret = array_merge($ret,$this->_get_all_entries($add_tags,$skip_release,$cur[$key]['ENTRIES']));
1179               $ret[] = array("TYPE" => "CLOSE" , "PARENT" => $entry['PARENT']);
1180             }
1181           }
1182         }
1183       }
1184     }
1185     return($ret);
1186   }
1189   /*! \brief Save this plugin data to ldap.
1190              Save the current menu structure to ldap.
1191    */
1192   function save()
1193   {
1194     $ldap = $this->config->get_ldap_link();
1195     $all = $this->_get_all_entries();
1196     $prio = 0;
1197     $Actions = array("Remove" => array(),"Edit" => array() , "Add" => array());
1199     /* Walk through the menu structure and build up the ldap data object, 
1200         the entry dn and the entry priority.
1201      */
1202     $sep_id = 0;
1203     foreach($all as $entry){
1204       $prio ++;
1205       $cur = $entry;
1206       $dn = "";
1208       /* Build entry dn
1209        */
1210       do{  
1211         if($cur['TYPE'] == "SEPERATOR"){
1212           $sep_id ++;
1213           $dn.= "cn=seperator_".$sep_id.",";
1214         }elseif($cur['TYPE'] == "ENTRY"){
1215           $dn.= "cn=".$cur['NAME'].",";
1216         }elseif($cur['TYPE'] == "FOLDER"){
1217           $dn.= "cn=".$cur['NAME'].",";
1218         }elseif($cur['TYPE'] == "RELEASE"){
1219           $dn.= "ou=".$cur['NAME'].",";
1220         }elseif($cur['TYPE'] == "BASE"){
1221         }
1222         if(!isset($all[$cur['PARENT']])){
1223           $cur = NULL;
1224         }else{
1225           $cur = $all[$cur['PARENT']];
1226         }
1227       }while(is_array($cur));
1229       $cur_dn = $dn.$this->dn;
1230       $attrs = array();
1232       /* Build entry data object.
1233        */
1234       switch($entry['TYPE']){
1235         case "SEPERATOR"    :
1236         { 
1237           $attrs['objectClass'] = array("gotoMenuEntry");
1238           $attrs['cn']          = "seperator_".$sep_id;
1239           $attrs['gosaApplicationPriority'] = $prio;
1240           $attrs['gosaApplicationParameter'] = "*separator*";
1241         }
1242         break;
1243         case "ENTRY"    :
1244         { 
1245           $attrs['objectClass'] = array("gotoMenuEntry");
1246           $attrs['cn']          = $entry['NAME'];
1247           $attrs['gosaApplicationPriority'] = $prio;
1248           $attrs['gosaApplicationParameter'] = array(); 
1249           
1250           foreach($entry['PARAMETER'] as $name => $value){
1251             $attrs['gosaApplicationParameter'][] = $name.":".$value; 
1252           }
1253           if($entry['STATUS'] == "ADDED" && !count($attrs['gosaApplicationParameter'])){
1254             unset($attrs['gosaApplicationParameter']);
1255           } 
1256         }
1257         break;
1258         case "FOLDER"   : 
1259         { 
1260           $attrs['objectClass'] = array("gotoSubmenuEntry");
1261           $attrs['cn']          = $entry['NAME'];
1262           $attrs['gosaApplicationPriority'] = $prio;
1263           if($entry['STATUS'] != "ADDED"){
1264             $attrs['gosaApplicationIcon'] = array();
1265           }
1266           
1267           if(!empty($entry['ICON'])){
1268             $attrs['gosaApplicationIcon']     = $entry['ICON'];
1269           }
1270         }
1271         break;
1272         case "RELEASE"  : 
1273         {
1274           $attrs['ou']            = $entry['NAME'];
1275           $attrs['objectClass']   = array();
1276           $attrs['objectClass'][] = "top";
1277           $attrs['objectClass'][] = "organizationalUnit";
1278           $attrs['objectClass'][] = "FAIbranch";
1279           if(!empty($entry['FAIstate'])){
1280             $attrs['FAIstate']      = $entry['FAIstate'];
1281           }
1282         }
1283         break;
1284       }
1285  
1286       /* Append missing ObjectClasses,  ...  Tagging 
1287        */
1288       if(isset($entry['LDAP_ATTRS'])){
1289         for($i = 0 ; $i < $entry['LDAP_ATTRS']['objectClass']['count']; $i ++){
1290           $oc = $entry['LDAP_ATTRS']['objectClass'][$i];
1291           if(!in_array($oc,$attrs['objectClass'])){
1292             $attrs['objectClass'][] = $oc;
1293           }
1294         }
1295       }
1296   
1297       /* Create an array containing all operations sorted by type. (add,remove...)
1298        */
1299       if($entry['STATUS'] == "LOADED"){
1300         continue;
1301       }
1302       if($entry['STATUS'] == "REMOVED"){
1303         if(isset($entry['DN'])){
1304           $Actions['Remove'][$entry['DN']] = $entry['DN'];
1305         }else{
1306           $Actions['Remove'][$cur_dn] = $cur_dn;
1307         }
1308       }
1309       if($entry['STATUS'] == "EDITED"){
1310         $Actions['Edit'][$cur_dn] = $attrs;
1311       }
1312       if($entry['STATUS'] == "ADDED"){
1313         $Actions['Add'][$cur_dn] = $attrs;
1314       }
1315     }
1317     /* First remove entries
1318      */
1319     $ldap = $this->config->get_ldap_link();
1320     $ldap->cd($this->config->current['BASE']);
1321     foreach($Actions['Remove'] as $dn){
1322       $ldap->cd($dn);
1323       $ldap->cat($dn);
1324       if($ldap->count()){
1325         $ldap->rmdir_recursive($dn);
1326         if (!$ldap->success()){
1327           msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_DEL, get_class()));
1328         }
1329       }
1330     }
1331     
1332     /* Add new entries
1333      */
1334     foreach($Actions['Add'] as $dn => $data){
1335       $this->tag_attrs($data,$dn,$this->gosaUnitTag);
1336       $ldap->cd($dn);
1337       $ldap->cat($dn);
1338       if(!$ldap->count()){
1339         $ldap->add($data);
1340         if (!$ldap->success()){
1341           msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_ADD, get_class()));
1342         }
1343       }
1344     }
1346     /* Modify entries
1347      */
1348     foreach($Actions['Edit'] as $dn => $data){
1349       $this->tag_attrs($data,$dn,$this->gosaUnitTag);
1350       $ldap->cd($dn);
1351       $ldap->cat($dn);
1352       if($ldap->count()){
1353         $ldap->modify($data);
1354         if (!$ldap->success()){
1355           msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD, get_class()));
1356         }
1357       }
1358     }
1360     $this->_load_menu_structure();
1361   }
1364   /*! \brief  Return plugin informations for acl handling  
1365       @return Array containing all plugin ACL informations
1366    */ 
1367   static function plInfo()
1368   {
1369     return (array(
1370           "plShortName"   => _("Applications"),
1371           "plDescription" => _("Group applications"),
1372           "plSelfModify"  => FALSE,
1373           "plDepends"     => array(),
1374           "plPriority"    => 7,
1375           "plSection"     => array("administration"),
1376           "plCategory"    => array("groups"),
1377           "plProvidedAcls"=> array(
1378             "gosaMemberApplication"     => _("Application"),
1379             "FAIrelease"                => _("Release"),
1380             "gosaApplicationParameter"  => _("Application parameter"))
1381           ));
1382   }
1385   /* \brief   Prepare this plugin to be copied.
1386               Adapt all required attributes from the source object.
1387               In this case, update the menu structure too, mark all elements
1388                as newly added, so they will be saved in save();
1389    */
1390   function PrepareForCopyPaste($source)
1391   {
1392     plugin::PrepareForCopyPaste($source);
1393    
1394     $tmp = new appgroup($this->config,$source['dn']);
1395     $this->is_account = TRUE;
1396     $this->a_Structure = $tmp->a_Structure;
1397     $all = $this->_get_all_entries();
1398     foreach($all as &$entry){
1399       if(isset($entry['STATUS'])){
1400         $entry['STATUS'] = "ADDED";
1401       }
1402     }
1403   }
1406   /*! \brief  Save HTML posts in multiple edit mode
1407    */
1408   function multiple_save_object()
1409   {
1410     if(isset($_POST['group_apps_multi'])){
1411       $this->save_object(); 
1412       plugin::multiple_save_object();    
1413   
1414       /* Get posts */
1415       foreach(array("apps") as $attr){
1416         if(isset($_POST['use_'.$attr])) {
1417           $this->multi_boxes[] = $attr;
1418         }
1419       }
1420     }
1421   }
1422   
1424   /*! \brief  Return values used in multiple edit mode.
1425               Some values can be modified for multiple 
1426               groups at the same time.
1427       @return Array  All values that support multiple edit.
1428    */
1429   function get_multi_edit_values()
1430   {
1431     $ret = plugin::get_multi_edit_values();
1433     if(in_array("apps",$this->multi_boxes)){
1434       $ret['gosaApplicationParameter'] = $this->gosaApplicationParameter;
1435       $ret['Categories']               = $this->Categories;
1436       $ret['gosaMemberApplication']    = $this->gosaMemberApplication;
1437       $ret['FAIrelease']               = $this->FAIrelease;
1438       $ret['appoption']                = $this->appoption;
1439     }
1440     return($ret);
1441   }
1443 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1444 ?>