Code

updated acls
[gosa.git] / gosa-plugins / goto / personal / environment / class_environment.inc
1 <?php
3 class environment extends plugin
4 {
5   var $plIcon = "plugins/goto/images/plugin.png";
7   /* attribute list for save action */
8   var $ignore_account       = FALSE;
9   var $plHeadline           = "Environment";
10   var $plDescription        = "This does something";
11   var $dialog               = false;    // Indicates that we are currently editing in an seperate dialog
12   
13   var $in_dialog            = false;
14   var $uid                  = "";
16   var $is_group             = false;
17   var $view_logged = FALSE;
19   /* Attribute definition
20    */
22   /* profile management */
23   var $useProfile         = false;  // Specifies if we want to use a Server 
24   var $gotoProfileServer  = "";     // Specifies the selected profile server
25   var $gotoProfileServers = array();// Specifies all available and selectable servers
26   var $gotoProfileFlags   = "";     // Flags enabled  ? only used to set ACL and save 
27   var $gotoProfileFlagC  = "";     // Flag is set to C if we have the profile caching fucntion enabled 
28   
29   var $gotoXResolution    = "auto";     // The selected resolution eg: 1024x768
30   var $gotoXResolutions   = array();// Contains all available resolutions for this account
31   var $gotoProfileFlagL  = "";     // Flag is set to L to enable runtime resolution change 
32   var $gotoProfileQuota   = "";     // User Quota Settings
34   /* Logon script section*/
35   var $gotoLogonScripts   = array();// Contains all available Logon Scripts  
36   var $gotoLogonScript    = "";     // The selected Logon Script
38   /* Printer */
39   var $gotoPrinter        = array();// All available Printer, with their configurations
40   var $gotoPrinterSel     = "";     //  The selected Printer
41   var $gosaDefaultPrinter = "";     // Default printer
43   /* Share */
44   var $gotoShares         = array();// Current Share Options
45   var $gotoShare          = "";     // currently selected Share Option
46   var $gotoShareSelections= array();// Available Shares for this account in Listbox format
47   var $gotoAvailableShares= array();// Available Shares for this account
49   /* Kiosk profile */
50   var $kiosk_enabled      = FALSE;
51   var $gotoKioskProfile   = "";     // The selected Kiosk Profile
52   var $gotoKioskProfile_Server    = "";     // The selected Kiosk Profile
53   var $gotoKioskProfile_Profile   = "";     // The selected Kiosk Profile
54   var $gotoKioskProfiles  = array();// All available Kiosk profiles
56   /* Hotplug Devices */
57   var $gotoHotplugDevice  = array();     // Selected hotplug
58   var $gotoHotplugDevices = array();// Already configured hotplug devices 
59   var $gotoHotplugDeviceDN= array();
61   var $NewAddedPrinters   = array();
62   var $NewDeletedPrinters = array();
64   /* general settings */
65   // Sets the attributes which will kept on page reload, which will be saved, ...
67   var $CopyPasteVars      = array("gotoHotplugDevices","gotoAvailableShares","gotoShareSelections","gotoPrinterSel","gotoProfileFlagL","gotoXResolutions","gotoProfileFlagC","gotoProfileServers","useProfile","is_group","in_dialog","OrigCn","gotoKioskProfile_Server","gotoKioskProfile_Profile");
69   var $attributes         = array("uid","gotoProfileServer","gotoProfileFlags","gotoHotplugDeviceDN",
70       "gotoXResolution","gotoProfileQuota",
71       "gotoLogonScript",
72       "gotoPrinter", "gosaDefaultPrinter",
73       "gotoShare",
74       "gotoKioskProfile");
75   var $objectclasses      = array("gotoEnvironment"); // Specifies the objectClass which contains the attributes edited here 
76   var $cn;
77   var $OrigCn;
78   var $add_del_printer_member_was_called = false;
80   var $multiple_support =TRUE;
82   var $use_gotoPrinter;
84   function environment (&$config, $dn= NULL)
85   {
86     plugin::plugin ($config, $dn);
88     /* Setting uid to default */
89     if(isset($this->attrs['uid'][0])){
90       $this->uid = $this->attrs['uid'][0];
91     }
93     /* Check : Are we currently editing a group or user dialog */
94     if((isset($this->attrs['cn'][0]))&&(!isset($this->attrs['uid'][0]))){
95       $suffix="Group";
96       $this->uid          = $this->attrs['cn'][0];
97       $this->attrs['uid'] = $this->attrs['cn'][0];
98       $this->OrigCn = $this->attrs['cn'][0];
99     }else{
100       $suffix="User";
101     }
103     /* Get all Printer assignments */
104     $ldap = $this->config->get_ldap_link();
105     $ldap->cd($this->config->current['BASE']);
106     $ldap->search("(&(objectClass=gotoPrinter)(goto".$suffix."Printer=".$this->uid."))",array("*"));
107     while($printer = $ldap->fetch()){
108       $this->gotoPrinter[$printer['cn'][0]]=$printer;
109       $this->gotoPrinter[$printer['cn'][0]]['mode']="user";
110     }
111     $ldap->search("(&(objectClass=gotoPrinter)(goto".$suffix."AdminPrinter=".$this->uid."))",array("*"));
112     while($printer = $ldap->fetch()){
113       $this->gotoPrinter[$printer['cn'][0]]=$printer;
114       $this->gotoPrinter[$printer['cn'][0]]['mode']="admin";
115     }
118     /* Prepare hotplugs */
119     if(isset($this->attrs['gotoHotplugDeviceDN']) && is_array($this->attrs['gotoHotplugDeviceDN'])){
120       $ldap = $this->config->get_ldap_link();
121       $ldap->cd($this->config->current['BASE']);
122       for($i = 0 ; $i < $this->attrs['gotoHotplugDeviceDN']['count'] ; $i ++){
123         $ldap->cat($this->attrs['gotoHotplugDeviceDN'][$i]);
124         if($ldap->count()){
125           $attrs = $ldap->fetch(); 
127           if(isset($attrs['gotoHotplugDevice'][0])){
128             $tmp      = preg_split("/\|/",$attrs['gotoHotplugDevice'][0]);
129             $tmp2     = array();
130             $tmp2['name']         = $attrs['cn'][0];
131             $tmp2['description']  = $tmp[0];
132             $tmp2['id']           = $tmp[1];
133             $tmp2['produkt']      = $tmp[2];
134             $tmp2['vendor']       = $tmp[3];
135             $tmp2['dn']           = $attrs['dn'];
136             $this->gotoHotplugDevices[] = $tmp2; 
137           }
138         }else{
139           msg_dialog::display(_("Warning"), sprintf(_("Device '%s' is not available anymore. It will be removed!"), $this->attrs['gotoHotplugDeviceDN'][$i]), WARNING_DIALOG);
140         }
141       }
142     }
144  
145     /* prepare LogonScripts */
146     if((isset($this->attrs['gotoLogonScript']))&&(is_array($this->attrs['gotoLogonScript']))){
147       unset($this->attrs['gotoLogonScript']['count']);
148       foreach($this->attrs['gotoLogonScript'] as $device){
149         $tmp = $tmp2 = array();
150         $tmp = explode("|",$device);
151         $tmp2['LogonName']        = $tmp[0]; 
152         $tmp2['LogonPriority']    = $tmp[2]; 
153         if(preg_match("/O/i",$tmp[1])){
154           $tmp2['LogonOverload'] = "O";
155         }else{
156           $tmp2['LogonOverload'] = "";
157         }
158         if(preg_match("/L/i",$tmp[1])){
159           $tmp2['LogonLast'] = "L";
160         }else{
161           $tmp2['LogonLast'] = "";
162         }
163         $tmp2['LogonData']        = base64_decode($tmp[3]); 
164         $tmp2['LogonDescription'] = $tmp[4];
165         $this->gotoLogonScripts[$tmp[0]]=$tmp2;
166       }
167     }
169     /* Prepare Shares */
170     if((isset($this->attrs['gotoShare']))&&(is_array($this->attrs['gotoShare']))){
171       unset($this->attrs['gotoShare']['count']);
172       foreach($this->attrs['gotoShare'] as $share){
173         $tmp = $tmp2 = array();
174         $tmp = explode("|",$share);
175         $tmp2['server']      =$tmp[0];
176         $tmp2['name']        =$tmp[1];
178         /* Decode base64 if needed */
179         if (!preg_match('%/%', $tmp[2])){
180           $tmp2['mountPoint']  =base64_decode($tmp[2]);
181         } else {
182           $tmp2['mountPoint']  =$tmp[2];
183         }
185         if(isset($tmp[3])){
186           $tmp2['PwdHash']  =$tmp[3];
187         }else{
188           $tmp2['PwdHash']  ="";
189         }
190         if(isset($tmp[4])){
191           $tmp2['Username']  =$tmp[4];
192         }else{
193           $tmp2['Username']  ="";
194         }
195         $this->gotoShares[$tmp[1]."|".$tmp[0]]=$tmp2;
196       }
197     }
199     for($i = 0 ; $i < strlen($this->gotoProfileFlags) ; $i ++){
200       $chr = $this->gotoProfileFlags[$i];
201       $name = "gotoProfileFlag".$chr;
202       $this->$name=$chr;
203     }
205     if((!empty($this->gotoProfileServer))||($this->gotoProfileFlagC=="C")){
206       $this->useProfile = true;
207     }else{
208       $this->useProfile = false;
209     }
211     /* Set resolutions */
212     $this->gotoXResolutions = array("auto"=>_("auto"),
213                                     "640x480"   =>  "640x480",
214                                     "800x600"   =>  "800x600",
215                                     "1024x768"  =>  "1024x768",
216                                     "1152x864"  =>  "1152x864",
217                                     "1280x768"  =>  "1280x768",
218                                     "1280x1024" =>  "1280x1024");
220     if($this->config->get_cfg_value("resolutions") != ""){
221       $file = $this->config->get_cfg_value("resolutions");
223       if(is_readable($file)){
224         $str = file_get_contents($file);
225         $lines = preg_split("/\n/",$str);
226         foreach($lines as $line){
227           $line = trim($line);
228           if(!empty($line)){
229             $this->gotoXResolutions[$line]=$line;
230           }
231         }
232         //natcasesort($this->gotoXResolutions);
233       }else{
234         msg_dialog::display(_("Configuration error"), sprintf(_("Cannot open file '%s'!"), $file), WARNING_DIALOG);
235       }
236     }
238     $this->gotoProfileServers= $config->getShareServerList() ;
239     $this->gotoShareSelections= $config->getShareList(true);
240     $this->gotoAvailableShares= $config->getShareList(false);  
241   
242     /* Ensure that a currently selected server will stay selected, even if the list of profile servers
243         is empty due to insufficient permissions.
244      */
245     if(count($this->gotoProfileServers) && !empty($this->gotoProfileServer)){
247       /* The currently selected profile server is outdated/no longer available */
248       if(!isset($this->gotoProfileServers[$this->gotoProfileServer])){
250       }else{
251         $c = $this->gotoProfileServers[$this->gotoProfileServer];
252         if(!preg_match("/r/",$c['ACL'])){
254           /* We are not allowed to read to currently selected server.
255              But to ensure that the selection will be kept after saving the account, we 
256               override the current ACL tag.
257            */          
258           $this->gotoProfileServers[$this->gotoProfileServer]['ACL'] .= "r";
259         }
260       }
261     }
262     $this->update_kiosk_profiles();
263   }
266   function update_kiosk_profiles()
267   { 
268     $this->gotoKioskProfile_Server = preg_replace("/^.*:\/\/([^\/]*).*$/","\\1",$this->gotoKioskProfile);
269     $this->gotoKioskProfile_Profile= preg_replace("/^.*\//","",$this->gotoKioskProfile);
271     $tmp1  = array("none" => array(_("disabled")));
272     $tmp2  = array("none" => _("disabled"));
273     $tmp3  = array();
274     $ldap = $this->config->get_ldap_link();
275     $ldap->cd($this->config->current['BASE']);
276     $ldap->search("(&(objectClass=goEnvironmentServer)(gotoKioskProfile=*)(cn=*))",array("cn","gotoKioskProfile"));
277     $cnt = 0;
278     $ui = get_userinfo();
279     while($attrs = $ldap->fetch()){
280       $acl = $ui->get_permissions($attrs['dn'],"server/goKioskService","");
281       for($i = 0 ; $i < $attrs['gotoKioskProfile']['count'] ; $i ++){
282         if(preg_match("/r/",$acl) || $this->gotoKioskProfile_Server == $attrs['cn'][0]){
283           $name = preg_replace("/^.*\//","",$attrs['gotoKioskProfile'][$i]);
284           $tmp1[$attrs['cn'][0]][] = $name;
285           $tmp3[$attrs['cn'][0]][$name] = $attrs['gotoKioskProfile'][$i];
286           $tmp2[$attrs['cn'][0]]= $attrs['cn'][0];
287           $cnt ++;
288         }
289       }
290     }
292     if($cnt && $this->config->search("environment","kioskpath",array('menu','tabs'))){
293       $this->kiosk_enabled = TRUE;
294     }
296     $this->gotoKioskProfiles['BY_SERVER'] = $tmp1;
297     $this->gotoKioskProfiles['SERVERS']   = $tmp2;
298     $this->gotoKioskProfiles['MAP']       = $tmp3;
299   
300     $error = false;
301     if(!isset($this->gotoKioskProfiles['SERVERS'][$this->gotoKioskProfile_Server])){
302       $error = true;
303     }elseif(!in_array($this->gotoKioskProfile_Profile, $this->gotoKioskProfiles['BY_SERVER'][$this->gotoKioskProfile_Server])){
304       $error = true;
305     }
306     if($error && !empty($this->gotoKioskProfile)){
307       msg_dialog::display(_("Warning"), sprintf(_("Kiosk profile '%s' located on server '%s' is not available anymore. Kiosk profile will be disabled!"), $this->gotoKioskProfile_Profile, $this->gotoKioskProfile_Server), WARNING_DIALOG);
308       $this->gotoKioskProfile_Server ="none";
309       $this->gotoKioskProfile_Profile="";
310     }elseif(empty($this->gotoKioskProfile)){
311       $this->gotoKioskProfile_Server ="none";
312       $this->gotoKioskProfile_Profile="";
313     }
314   }
317   /* Detect type of edited object (user|group)*/
318   function detect_grouptype()
319   {
320     if((!isset($this->parent))&&(!$this->is_account)){
321       $this->is_group     = false;
322     }elseif((isset($this->parent))&&(!isset($this->parent->by_object['posixAccount']))){
323       $this->is_group     = true;
324     }else{
325       $this->is_group     = false;
326     }
327   }
330   function execute()
331   {
333     /* Call parent execute */
334     plugin::execute();
335     /* Log view */
336     if($this->is_account && !$this->view_logged){
337       $this->view_logged = TRUE;
338       if(isset($this->parent->by_object['user']) || (isset($this->attrs['objectClass']) &&in_array("gosaAccount",$this->attrs['objectClass']))){
339         new log("view","users/".get_class($this),$this->dn);
340       }else{
341         new log("view","groups/".get_class($this),$this->dn);
342       }
343     }
345     /* Check profile server */
346     if($this->acl_is_writeable("gotoProfileServer")){
348       if(!empty($this->gotoProfileServer) && !isset($this->gotoProfileServers[$this->gotoProfileServer])){
351         if(count($this->gotoProfileServers)){
353           /* Get First Profile */
354           $new = key($this->gotoProfileServers);
356           /* Another profile server found */
357           msg_dialog::display(_("Warning"), sprintf(_("Profile server '%s' is not available anymore. Switched to server '%s'."), $this->gotoProfileServer, $new), WARNING_DIALOG);
358         }else{
360           /* No other profile servers found */
361           msg_dialog::display(_("Warning"), sprintf(_("Profile server '%s' is not available anymore. Kiosk profile will be disabled."), $this->gotoProfileServer), WARNING_DIALOG);
362           $this->gotoProfileServer = "none";
363         }
364       }
365     }    
367     $this->detect_grouptype();
369     /* Fill templating stuff */
370     $smarty= get_smarty();
371     $smarty->assign("kiosk_enabled",$this->kiosk_enabled);
372     $display= "";
374     $smarty->assign("is_group",$this->is_group);
376     /* Prepare all variables for smarty */
377     foreach($this->attributes as $s_attr){
378       /* Set value*/
379       $smarty->assign($s_attr,$this->$s_attr);
381       /* Set checkbox state*/
382       if(empty($this->$s_attr)){
383         $smarty->assign($s_attr."CHK","");
384       }else{
385         $smarty->assign($s_attr."CHK"," checked ");
386       }
388       /* Prepare ACL settings*/
389       $smarty->assign($s_attr."ACL",$this->getacl($s_attr));
390     }
392     /* Is accout enabled | are we editing from usermenu or admin menu 
393        All these tab management is done here
394      */
397     /* Working from Usermenu an the Account is currently disbled
398      * this->parent :  is only set if we are working in a list of tabs
399      * is_account   :  is only true if the needed objectClass is given
400      */
401     if((!isset($this->parent))&&(!$this->is_account)){
402       /* We are currently editing this tab from usermenu, but this account is not enabled */
403       $smarty->assign("is_account",$this->is_account);
404       /* Load template */
405       $display .= $smarty->fetch(get_template_path('environment.tpl', TRUE));
406       /* Avoid the "You are currently editing ...." message when you leave this tab */
407       $display .= back_to_main(); 
408       /* Display our message to the user */
409       return $display;
412       /* We are currently editing from group tabs, because 
413        * $this->parent is set
414        * posixAccount is not set, so we are not in usertabs.
415        */
416     }elseif((isset($this->parent))&&(!isset($this->parent->by_object['posixAccount']))){
417       $smarty->assign("is_account","true");
418       $this->uid          = $this->cn;
419       $this->attrs['uid'] = $this->cn;
421       /* Change state if needed */
422       if (isset($_POST['modify_state'])){
423         if(($this->acl_is_createable() && !$this->is_account) || 
424             ($this->acl_is_removeable() &&  $this->is_account)){
425           $this->is_account= !$this->is_account;
426         }
427       }
428       /* Group Dialog with enabled environment options */
429       if ($this->is_account){
430         $display= $this->show_enable_header(msgPool::removeFeaturesButton(_("Environment")),
431             msgPool::featuresEnabled(_("Environment")));
432       } else {
434         /* Environment is disabled 
435            If theres is no posixAccount enabled, you won't be able to enable 
436            environment extensions
437          */
438         if((isset($this->parent->by_object['group']))||(isset($this->attrs['objectClass']))&&((in_array("posixAccount",$this->attrs['objectClass'])))){
439           $display= $this->show_enable_header(msgPool::addFeaturesButton(_("Environment")),
440               msgPool::featuresDisabled(_("Environment")));
441           return $display;
442         }elseif((isset($this->parent->by_object['ogroup']))){
443           $display= $this->show_enable_header(msgPool::addFeaturesButton(_("Environment")),
444               msgPool::featuresDisabled(_("Environment")));
445           return $display;
446         }else{
447           $display= $this->show_enable_header(msgPool::addFeaturesButton(_("Environment")),
448               msgPool::featuresDisabled(_("Environment"), _("POSIX")), TRUE);
449           return $display;
450         }
451       }
452     }else{
453       /* Editing from Usermenu 
454        *  Tell smarty that this accoutn is enabled 
455        */
456       $smarty->assign("is_account","true");
458       /* Change state if needed */
459       if (isset($_POST['modify_state'])){
460         if(($this->acl_is_createable() && !$this->is_account) || 
461             ($this->acl_is_removeable() &&  $this->is_account)){
462           $this->is_account= !$this->is_account;
463         }
464       }
466       if(isset($this->parent)){
468         // 3. Account enabled . Editing from adminmenu
469         if ($this->is_account){
470           $display= $this->show_enable_header(msgPool::removeFeaturesButton(_("Environment")),
471               msgPool::featuresEnabled(_("Environment")));
472         } else {
474           if($this->parent->by_object['posixAccount']->is_account==true){
475             $display= $this->show_enable_header(msgPool::addFeaturesButton(_("Environment")),
476                 msgPool::featuresDisabled(_("Environment")));
477             return $display;
478           }else{
479             $display= $this->show_enable_header(msgPool::addFeaturesButton(_("Environment")),
480                 msgPool::featuresDisabled(_("Environment"), _("POSIX")), TRUE);
481             return $display;
482           }
483         }
484       }
485     }
486   
487     /* Reset header toggle */
488     if($this->multiple_support_active){
489       $display = "";
490     }
492     /* Account is Account : is_accounbt=true.
493      * Else we won't reach this. 
494      */
496     /* Prepare all variables for smarty */
497     foreach($this->attributes as $s_attr){
498       /* Set value*/
499       $smarty->assign($s_attr,$this->$s_attr);
501       /* Set checkbox state*/
502       if(empty($this->$s_attr)){
503         $smarty->assign($s_attr."CHK","");
504       }else{
505         $smarty->assign($s_attr."CHK"," checked ");
506       }
508       /* Prepare ACL settings*/
509       $smarty->assign($s_attr."ACL",$this->getacl($s_attr));
510     }
512     foreach(array("gotoProfileFlagC","gotoProfileFlagL") as $s_attr){
513       $smarty->assign($s_attr."ACL",$this->getacl($s_attr));
514     }
516     if($this->read_only) {
517       $smarty->assign("gotoPrinterACL","r");
518     }else{
519       $smarty->assign("gotoPrinterACL","rw");
520     }
523     $smarty->assign("useProfile",$this->useProfile);
524     if(empty($this->useProfile) && !$this->multiple_support_active){
525       $smarty->assign("useProfileCHK","");
526       $smarty->assign("gotoProfileServerACL" , preg_replace("/w/","",$this->getacl("gotoProfileServer")));
527       $smarty->assign("gotoProfileQuotaACL" , preg_replace("/w/","",$this->getacl("gotoProfileQuota")));
528       $smarty->assign("gotoProfileFlagCACL" , preg_replace("/w/","",$this->getacl("gotoProfileFlagC")));
529     }else{
530       $smarty->assign("useProfileCHK"," checked ");
531     }
532     
533     $smarty->assign("gotoProfileServerWriteable", $this->acl_is_writeable("gotoProfileServer"));
534     $smarty->assign("gotoProfileACL", $this->getacl("gotoProfileServer").$this->getacl("gotoProfileQuota"));
536     /* HANDLE Profile Settings here 
537      * Assign available Quota and resolution settings
538      * Get all available profile server
539      * Get cache checkbox
540      * Assign this all to Smarty 
541      */
543     if(empty($this->gotoProfileFlagL)){
544       $smarty->assign("gotoProfileFlagLCHK"," ");
545     }else{
546       $smarty->assign("gotoProfileFlagLCHK"," checked ");
547     }
549     if(empty($this->gotoProfileFlagC)){
550       $smarty->assign("gotoProfileFlagCCHK"," ");
551     }else{
552       $smarty->assign("gotoProfileFlagCCHK"," checked ");
553     }
556     $smarty->assign("gotoXResolutions"    , $this->gotoXResolutions);
557     $smarty->assign("gotoXResolutionKeys" , array_flip($this->gotoXResolutions));
559     $smarty->assign("gotoProfileServers",$this->gotoProfileServers);
560     if(!is_array($this->gotoProfileServers)){
561       $this->gotoProfileServers =array();
562     }
564     /* Handle kiosk profiles*/
565     $smarty->assign("kiosk_servers" , $this->gotoKioskProfiles['SERVERS']);
566     $smarty->assign("kiosk_server" ,  $this->gotoKioskProfile_Server);
567     $smarty->assign("kiosk_profiles" , $this->gotoKioskProfiles['BY_SERVER'][$this->gotoKioskProfile_Server]);
568     $smarty->assign("kiosk_profile" ,  $this->gotoKioskProfile_Profile);
569   
571     /* Logonscript Management
572      * Get available LogonScripts (possibly grey out (or mark) these script that are defined for the group) 
573      * Perform add Delete edit Posts 
574      */
576     /* Dialog Save */
577     if(isset($_POST['LogonSave'])){
579       if(!$this->acl_is_writeable("gotoLogonScript")){
580         msg_dialog::display(_("Permission error"), msgPool::permModify(_("Logon scripts")), ERROR_DIALOG);
581         unset($this->dialog);
582         $this->dialog=FALSE;
583         $this->is_dialog=false;
584       }else{
585         $this->dialog->save_object();
586         if(count($this->dialog->check())!=0){
587           foreach($this->dialog->check() as $msg){
588             msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
589           }
590         }else{
591           $tmp = $this->dialog->save();
592           unset($this->dialog);
593           $this->dialog=FALSE;
594           $this->is_dialog=false;
596           if($this->multiple_support_active){
597             $tmp['UsedByAllUsers'] = TRUE;
598           }
599           $this->gotoLogonScripts[$tmp['LogonName']]=$tmp; 
600         }
601       }
602     }
603     
605     /* Dialog Quit without saving */
606     if(isset($_POST['LogonCancel'])){
607       $this->is_dialog= false;
608       unset($this->dialog);
609       $this->dialog= FALSE;
610     }
612     /* Check Edit Del New Posts for a selected LogonScript */ 
613     if($this->acl_is_writeable("gotoLogonScript") && 
614         (isset($_POST['gotoLogonScriptNew'])) || isset($_POST['gotoLogonScriptEdit']) ||isset($_POST['gotoLogonScriptDel'])){
616       /* New Logon Script: Open an edit dialog, we don't need a $_POST['gotoLogonScript'] here.
617        * In this case we create a new Logon Script.
618        */
619       if(isset($_POST['gotoLogonScriptNew'])){
620         $this->is_dialog = true;
621         $this->dialog = new logonManagementDialog($this->config,$this->dn);
622       }
624       /* If we receive a Delete request and there is a Script selected in the selectbox, delete this one.
625        * We only can delete if there is an entry selected.
626        */
627       if((isset($_POST['gotoLogonScriptDel']))&&(isset($_POST['gotoLogonScript']))){
628         unset($this->gotoLogonScripts[$_POST['gotoLogonScript']]);
629       }
631       /* In this case we want to edit an existing entry, we open a new Dialog to allow editing.
632        * There must be an entry selected to perform edit request.
633        */
634       if((isset($_POST['gotoLogonScriptEdit']))&&(isset($_POST['gotoLogonScript']))){
635         $is_entry = $this->gotoLogonScripts[$_POST['gotoLogonScript']];
636         $this->is_dialog = true;
637         $this->dialog = new logonManagementDialog($this->config,$this->dn,$is_entry);
638       }
639     }
641     /* Append List to smarty*/
642     if($this->multiple_support_active){
643       $smarty->assign("gotoLogonScripts",  $this->gotoLogonScripts);
644       $smarty->assign("gotoLogonScriptKeysCnt",count($this->gotoLogonScripts));
645     }else{
646       $ls = $this->printOutLogonScripts();
647       $smarty->assign("gotoLogonScripts",  $ls);
648       $smarty->assign("gotoLogonScriptKeys",array_flip($ls));
649       $smarty->assign("gotoLogonScriptKeysCnt",count($ls));
650     }
652     /* In this section server shares will be defined 
653      * A user can select one of the given shares and a mount point
654      *  and attach this combination to his setup.
655      */
657     $smarty->assign("gotoShareSelections",    $this->gotoShareSelections);
658     if(!is_array($this->gotoShareSelections)){
659       $this->gotoShareSelections = array();
660     }
661     $smarty->assign("gotoShareSelectionKeys", array_flip($this->gotoShareSelections));
663     /* if $_POST['gotoShareAdd'] is set, we will try to add a new entry 
664      * This entry will be, a combination of mountPoint and sharedefinitions 
665      */
666     if(isset($_POST['gotoShareAdd']) && $this->acl_is_writeable("gotoShare")){
668       /* We assign a share to this user, if we don't know where to mount the share */
669       if(!isset($_POST['gotoShareSelection']) || get_post('gotoShareSelection') == ""){
670         msg_dialog::display(_("Error"), msgPool::invalid(_("Share")), ERROR_DIALOG);
671       }elseif((!isset($_POST['gotoShareMountPoint']))||(empty($_POST['gotoShareMountPoint']))||(preg_match("/[\|]/i",$_POST['gotoShareMountPoint']))){
672         msg_dialog::display(_("Error"), msgPool::invalid(_("Mount point")), ERROR_DIALOG);
673       }elseif(preg_match('/ /', $_POST['gotoShareMountPoint'])){
674         msg_dialog::display(_("Error"), msgPool::invalid(_("Mount point"), "/[^\s]/"), ERROR_DIALOG);
675       }elseif(!(
676             preg_match("/^\//",$_POST['gotoShareMountPoint'])  ||
677             preg_match("/^~/",$_POST['gotoShareMountPoint']) ||
678             preg_match("/^\$HOME/",$_POST['gotoShareMountPoint']) ||
679             preg_match("/^.HOME/",$_POST['gotoShareMountPoint']) ||
680             preg_match("/^\$USER/",$_POST['gotoShareMountPoint']) ||
681             preg_match("/^.USER/",$_POST['gotoShareMountPoint']) ||
682             preg_match("/^%/",$_POST['gotoShareMountPoint'])
683             )
684           ){
685         msg_dialog::display(_("Error"), msgPool::invalid(_("Mount point")), ERROR_DIALOG);
686       }else{
687         $a_share = $this->gotoAvailableShares[$_POST['gotoShareSelection']];
688         $s_mount = $_POST['gotoShareMountPoint'];
689         $s_user  = $_POST['ShareUser'];
690         /* Preparing the new assignment */ 
691         $this->gotoShares[$a_share['name']."|".$a_share['server']]=$a_share;
692         $this->gotoShares[$a_share['name']."|".$a_share['server']]['Username']=$s_user;
693         $this->gotoShares[$a_share['name']."|".$a_share['server']]['PwdHash']="";
694         $this->gotoShares[$a_share['name']."|".$a_share['server']]['mountPoint']=$s_mount;
696         if($this->multiple_support_active){
697           $this->gotoShares[$a_share['name']."|".$a_share['server']]['UsedByAllUsers']= TRUE;
698         }
699       }
700     }  
702     /* if the Post  gotoShareDel is set, someone asked GOsa to delete the selected entry (if there is one selected)
703      * If there is no defined share selected, we will abort the deletion without any message 
704      */
705     $once = true;
706     if($this->acl_is_writeable("gotoShare")){
707       foreach($_POST as $name => $value){
708         if((preg_match("/^gotoShareDel_/",$name)) && ($once)){
709           $once = false;  
710           $key  = preg_replace("/^gotoShareDel_/","",$name);
711           $key  = preg_replace("/_+[xy]$/","",$key);
712           $key  = base64_decode($key);
713           if(isset($this->gotoShares[$key])) {
714             unset($this->gotoShares[$key]);
715           }
717           /* Remove corresponding password entry, too. This is a workaround
718              to get rid of old-style entries. */
719           $key= preg_replace("/\|/", "|!", $key);
720           if(isset($this->gotoShares[$key])) {
721             unset($this->gotoShares[$key]);
722           }
723         }
724         if((preg_match("/^gotoShareResetPwd_/",$name)) && ($once)){
725           $once = false;
726           $key  = preg_replace("/^gotoShareResetPwd_/","",$name);
727           $key  = preg_replace("/_+[xy]$/","",$key);
728           $key  = base64_decode($key);
729           $this->gotoShares[$key]['PwdHash'] = "";
730           if(preg_match("/^!/",$this->gotoShares[$key]['server'])){
731             unset($this->gotoShares[$key]);
732           }
733         }
734       }
735     }
736     $divlistShares = new divSelectBox("gotoShares");
737     $divlistShares->SetHeight(100);
740     $tmp = array();
741     if($this->acl_is_readable("gotoShare")){
742       $tmp = $this->printOutAssignedShares();
743     }
745     
746     foreach($tmp as $key => $value){
747       $img = "";
749       /* Skip apssword only entries */
750       if( empty($this->gotoShares[$key]['server']) && 
751           empty($this->gotoShares[$key]['name']) &&
752           empty($this->gotoShares[$key]['mountPoint']) &&
753           empty($this->gotoShares[$key]['Username'])){
754         continue;
755       } 
757       $color = "";
758       if($this->multiple_support_active){
759         if($this->gotoShares[$key]['UsedByAllUsers']){
760           $value .= "&nbsp;(<b>"._("Used by all users")."</b>)";
761         }else{
762           $color = "color: #999999;";
763           $value .= "&nbsp;(<b>"._("Used by some users")."</b>)";
764         }
765       }
767       /* Check if entry starts with an ! */
768       if(preg_match("/^!/",$this->gotoShares[$key]['server'])){
770         /* If we are currently editing groups environment, skip those ! entries */ 
771         if($this->is_group) continue;
773         /* Create pwd reset images */
774         if($this->gotoShares[$key]['PwdHash'] != ""){
775           $img.= "<input type='image' name='gotoShareResetPwd_".base64_encode($key)." 
776             'src='plugins/goto/images/list_reset_password.png' alt='"._("Reset password hash")."' 
777             title='"._("Reset password hash")."'>";
778         }
779         $field1 = array("string" => "<font style=\"color:#C0C0C0\">".$value."</font>" , "attach" => "style='".$color."'");
780         $field2 = array("string" => $img   , "attach" => "style='border-right:0px;'");
781       }else{
783         /* Create pwd reset img && delete image */
784         if($this->gotoShares[$key]['PwdHash'] != ""){
785           $img.= "<input type='image' name='gotoShareResetPwd_".base64_encode($key)." 
786             'src='plugins/goto/images/list_reset_password.png' alt='"._("Reset password hash")."' 
787             title='"._("Reset password hash")."'>";
788           $img.= "&nbsp;";
789         }
790         $img.= "<input type='image' name='gotoShareDel_".base64_encode($key)." 'src='images/lists/trash.png' alt='".msgPool::delButton()."' 
791           title='"._("Delete share entry")."'>";
792         $field1 = array("string" => $value , "attach" => "style='".$color."'");
793         $field2 = array("string" => $img   , "attach" => "style='border-right:0px;'");
794       }
795       $divlistShares->AddEntry(array($field1,$field2));
796     }
797     $smarty->assign("divlistShares",$divlistShares->DrawList());
799     /* Hotplug devices will be handled here 
800      * There are 3 possible methods for this feature
801      * Create a new Hotplug, A Dialog will open where you can specify some hotplug information
802      * Delete will erase an entry, the entry must be selcted in the ListBox first
803      * Editing an entry will open a dialog where the informations about the selcted entry can be changed
804      */
806     /* We have to delete the selected hotplug from the list*/
807     if((isset($_POST['gotoHotplugDeviceDel']))&&(isset($_POST['gotoHotplugDevice_post'])) && $this->acl_is_writeable("gotoHotplugDevice")){
808       if($this->acl_is_writeable("gotoHotplugDevice")){
809         foreach($_POST['gotoHotplugDevice_post'] as $name){
810           unset($this->gotoHotplugDevices[$name]);
811         }
812       }
813     }
815     /* There are already defined hotplugs from other users we could use */
816     if(isset($_POST['gotoHotplugDeviceUse']) && $this->acl_is_writeable("gotoHotplugDevice")){
817       $tmp  =array();
818       foreach($this->gotoHotplugDevices as $plugs){
819         $tmp[] = $plugs['name'];
820       }
821       $this->dialog = new hotplugSelect($this->config, get_userinfo());
822       $this->is_dialog = true;
823     }
825     /* Dialog Aborted */
826     if(isset($_POST['hotplugSelect_cancel'])){
827       $this->dialog= FALSE;
828       $this->is_dialog = false;
829     }
831     /* Dialod saved */
832     if(isset($_POST['hotplugSelect_save'])){
834       $res = $this->dialog->save();
835       foreach($res as $hotplug){
836         $name = $hotplug['cn'][0];
837         $entry['dn'] = $hotplug['dn'];
839         /* Set class values */
840         $tmp = preg_split("/\|/",$hotplug['gotoHotplugDevice'][0]);
841         $entry['name']          = $hotplug['cn'][0];
842         $entry['description'] = $tmp[0];
843         $entry['id']       = $tmp[1];
844         $entry['produkt']      = $tmp[2];
845         $entry['vendor']     = $tmp[3];
846         if($this->multiple_support_active){
847           $entry['UsedByAllUsers'] = TRUE;
848         }
849         $this->gotoHotplugDevices[$name]= $entry; 
850       }
851       $this->dialog= FALSE;
852       $this->is_dialog = false;
853     }
855     if($this->dialog instanceOf hotplugSelect){
856     
857       // Build up blocklist
858       session::set('filterBlacklist', array('cn' => array_keys($this->gotoHotplugDevices)));
859       return($this->dialog->execute());
860     }
862     if($this->multiple_support_active){
863       $smarty->assign("gotoHotplugDevices",$this->gotoHotplugDevices);
864     }else{
865       $smarty->assign("gotoHotplugDevices",$this->printOutHotPlugDevices());
866       $smarty->assign("gotoHotplugDeviceKeys",array_flip($this->printOutHotPlugDevices()));
867     }
869     /* Printer Assignment will managed below 
870      * A printer can be assigned in two different ways and two different types
871      * There are 2 types of users assigned to a printer : user and admin
872      * They only differ in the member attribute they will be assigned to. user: gotoUserPrinter admin: gotoadminPrinter
873      * The different types of assigning a user are : 1 assigning a user to a printer 2. assigning a group to a printer
874      */ 
876     /* First handle Add Post. Open a dialog that allows us to select a printer or two */ 
877     if(isset($_POST['gotoPrinterAdd'])){
878       $this->dialog = new printerSelect($this->config,get_userinfo());
879       $this->is_dialog=true;
880     }
882     if(isset($_POST['printerSelect_cancel']) && $this->dialog instanceOf printerSelect){
883       $this->is_dialog=false;
884       $this->dialog=FALSE;
885     }
887     if(isset($_POST['printerSelect_save'])  && $this->dialog instanceOf printerSelect){
889       $res = $this->dialog->save();
890         foreach($res as $printer){
892           $pname = $printer['cn'][0];
893           $printerObj = new printtabs($this->config,$this->config->data['TABS']['PRINTTABS'], $printer['dn'],"printer");
894           $printerObj->set_acl_base($printer['dn']);
896           $type = false;
898           
899           if($this->is_group){
900             if($this->dn == "new"){  
901               $type = "AddGroup";
902             }elseif(isset($this->NewDeletedPrinters[$pname])){
903               $type = "AddGroup";
904             }elseif($printerObj->by_object['printgeneric']->AddMember("AddGroup",$this->dn)){
905               $type = "AddGroup";
906             }
907           }else{
908             if($this->multiple_support_active){
909               $type = "AddUser";
910             }elseif(isset($this->NewDeletedPrinters[$pname])){
911               $type = "AddUser";
912             }elseif($printerObj->by_object['printgeneric']->AddMember("AddUser",$this->dn)){
913               $type = "AddUser";
914             }
915           }
917           if($type){
918             $this->gotoPrinter[$pname]=$printer;
919             $this->gotoPrinter[$pname]['mode']="user";
920             $this->add_del_printer_member_was_called = true;
922             $this->NewAddedPrinters[$pname] = $pname;
923             if(isset($this->NewDeletedPrinters[$pname])){
924               unset($this->NewDeletedPrinters[$pname]);
925             }
926           }
927         }
929         $this->is_dialog=false;
930         unset($this->dialog);
931         $this->dialog   =FALSE;
932     }
934     // Display printer selection dialog 
935     if($this->dialog instanceOf printerSelect){
937       // Build up blocklist
938       session::set('filterBlacklist',array('cn' => array_keys($this->gotoPrinter)));
939       return($this->dialog->execute());
940     }
943     if((isset($_POST['gotoPrinterDel']))&&(isset($_POST['gotoPrinterSel']))&&(!empty($_POST['gotoPrinterSel']))){
944       $printer = $_POST['gotoPrinterSel'];
945       foreach($printer as $pname){
947         $printerObj = new printtabs($this->config,$this->config->data['TABS']['PRINTTABS'],$this->gotoPrinter[$pname]['dn'],"printer");
948         $printerObj->set_acl_base($this->gotoPrinter[$pname]['dn']);
950         $type = false;
951         if($this->is_group){
952           if(isset($this->NewAddedPrinters[$pname])){
953             $type = "Group";
954           }elseif($printerObj->by_object['printgeneric']->DelMember("AddGroup",$this->cn)){
955             $type = "Group";
956           }
957         }else{
958           if(isset($this->NewAddedPrinters[$pname])){
959             $type = "User";
960           }elseif($printerObj->by_object['printgeneric']->DelMember("AddUser",$this->uid)){
961             $type = "User";
962           }
963         }
964         if($type){
965           $this->add_del_printer_member_was_called = true;
966           unset($this->gotoPrinter[$pname]);
968           $this->NewDeletedPrinters[$pname] = $pname;
969           if(isset($this->NewAddedPrinters[$pname])){
970             UNSET($this->NewAddedPrinters[$pname]);
971           }
972         }
973       }
974     }
976     if((isset($_POST['gotoPrinterEdit']))&&(isset($_POST['gotoPrinterSel']))&&(!empty($_POST['gotoPrinterSel']))){
977       $printers = $_POST['gotoPrinterSel'];
978       $this->add_del_printer_member_was_called = true;
979       foreach($printers as $printer){
980         if($this->gotoPrinter[$printer]['mode']=="user"){
981           $this->gotoPrinter[$printer]['mode']="admin";
982         }else{
983           $this->gotoPrinter[$printer]['mode']="user";
984         }
985       }
986     }
988     if((isset($_POST['gotoPrinterDefault']))&&(isset($_POST['gotoPrinterSel']))&&(!empty($_POST['gotoPrinterSel']))){
989       if($this->is_group){
990         msg_dialog::display(_("Error"), _("Cannot set default printer flag for groups!"), ERROR_DIALOG);
991       }else{
992         if ($this->gosaDefaultPrinter == $_POST['gotoPrinterSel'][0]){
993           $this->gosaDefaultPrinter= "";
994         } else {
995           $this->gosaDefaultPrinter= $_POST['gotoPrinterSel'][0];
996         }
997       }
998     }
1000     $smarty->assign("gotoPrinter",$this->printOutPrinterDevices());
1002     /* General behavior */
1003     if(is_object($this->dialog)){
1004       $this->dialog->save_object();
1005       $disp =$this->dialog->execute();
1006       return($disp);
1007     }
1009     /* Assign used attributes for multiple edit */
1010     foreach(array("gotoPrinter","kiosk_server","gotoProfileFlagL","gotoXResolution",
1011                   "useProfile","gotoProfileServer","gotoProfileQuota","gotoProfileFlagC") as $box){
1012       $ubox ="use_".$box;
1013       if(in_array($box,$this->multi_boxes)){
1014         $smarty->assign($ubox,TRUE);
1015       }else{
1016         $smarty->assign($ubox,FALSE);
1017       }
1018     }
1020     /* Als smarty vars are set. Get smarty template and generate output */
1021     $smarty->assign("multiple_support",$this->multiple_support_active);
1022     $display.= $smarty->fetch(get_template_path('environment.tpl', TRUE,dirname(__FILE__)));
1023     return($display);
1024   }
1026   function remove_from_parent()
1027   {
1028     /* only if it was an account*/
1029     if (!$this->initially_was_account){
1030       return;
1031     }
1033     /* include global link_info */
1034     $ldap= $this->config->get_ldap_link();
1036     /* Remove and write to LDAP */
1037     plugin::remove_from_parent();
1039     /* Don't save our template variables */
1040     $skip = array("uid","gotoLogonScripts","gotoPrinter","gotoShares","gotoHotplugDevices" );
1042     /* Skip all these attributes */
1043     foreach($skip as $del){
1044       unset($this->attrs[$del]);
1045     }
1047     @DEBUG (DEBUG_LDAP, __LINE__, __FUNCTION__, __FILE__,$this->attributes, "Save");
1049     $ldap->cd($this->dn);
1050     $this->cleanup();
1051     $ldap->modify ($this->attrs); 
1053     if($this->is_group){
1054       new log("remove","groups/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1055     }else{
1056       new log("remove","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1057     }
1059     if (!$ldap->success()){
1060       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, 0, get_class()));
1061     }
1063     /* Optionally execute a command after we're done */
1064     $this->handle_post_events("remove",array("uid" => $this->uid));
1065   }
1068   /* Save data to object */
1069   function save_object()
1070   {
1071     /* Get all Posted vars 
1072      * Setup checkboxes 
1073      */
1074     if(isset($_POST['iamposted'])){
1076       $PACL =  $this->getacl("gotoProfileServer").$this->getacl("gotoProfileQuota");
1078       if(isset($_POST['kiosk_server'])){
1079         $tmp = $_POST['kiosk_server'];
1080         if(isset($this->gotoKioskProfiles['SERVERS'][$tmp])){
1081           $this->gotoKioskProfile_Server = $_POST['kiosk_server'];
1082         }
1083       }
1084       if(isset($_POST['kiosk_profile'])){
1085         $tmp = $_POST['kiosk_profile'];
1086         if(in_array($tmp,$this->gotoKioskProfiles['BY_SERVER'][$this->gotoKioskProfile_Server])){
1087           $this->gotoKioskProfile_Profile = $_POST['kiosk_profile'];
1088         }
1089       }
1091       if(preg_match("/w/",$PACL)){
1092         if(isset($_POST['useProfile'])){
1093           $this->useProfile = true;
1094         }else{
1095           $this->useProfile = false;
1096         }
1097       }
1099       if($this->acl_is_writeable("gotoProfileFlagC")){
1100         if(isset($_POST['gotoProfileFlagC'])){
1101           $this->gotoProfileFlagC = $_POST['gotoProfileFlagC'];
1102         }else{
1103           $this->gotoProfileFlagC = false;
1104         }
1105       }
1107       if($this->acl_is_writeable("gotoProfileFlagL")){
1108         if(isset($_POST['gotoProfileFlagL'])){
1109           $this->gotoProfileFlagL = $_POST['gotoProfileFlagL'];
1110         }else{
1111           $this->gotoProfileFlagL = false;
1112         }
1113       }
1115       plugin::save_object();
1116       foreach($this->attributes as $s_attr){
1117         if((!isset($_POST[$s_attr])) || 
1118             in_array($s_attr,array("gosaDefaultPrinter","gotoShare","gotoHotplugDevices","gotoPrinter","gotoLogonScripts","uid"))) continue;
1119         if(!$this->acl_is_writeable($s_attr)){
1120           continue;
1121         }else{ 
1122           if(isset($_POST[$s_attr])){
1123             $this->$s_attr = $_POST[$s_attr];
1124           }else{
1125             $this->$s_attr = false;
1126           }
1127         }
1128       }
1129     }
1130   }
1133   /* Check supplied data */
1134   function check()
1135   {
1136     /* Call common method to give check the hook */
1137     $message= plugin::check();
1139     $this->detect_grouptype();
1141     if(preg_match("/[^0-9]/",$this->gotoProfileQuota)) {
1142       $message[] = msgPool::invalid(_("Profile quota"),$this->gotoProfileQuota,"/[0-9]/") ;
1143     } 
1144     if(!isset($this->attrs['objectClass'])){
1145       $this->attrs['objectClass']=array();
1146     } 
1147     if(!$this->is_group){
1148       if((!((in_array("posixAccount",$this->attrs['objectClass']))||($this->parent->by_object['posixAccount']->is_account==true)))&&(!$this->is_group)){
1149         $message[]= msgPool::featuresDisabled(_("environment"),_("POSIX"));  
1150       }
1151     }
1152     return ($message);
1153   }
1156   /* Save to LDAP */
1157   function save()
1158   {
1159     /* If group was renamed, all printer settings get lost
1160      */ 
1161     /* only save changed variables ....*/
1162     if ($this->gotoKioskProfile_Server != "none"){
1163       $method = $this->gotoKioskProfiles['MAP'][$this->gotoKioskProfile_Server][$this->gotoKioskProfile_Profile];
1164       $this->gotoKioskProfile= $method;
1165     }else{
1166       $this->gotoKioskProfile= array();
1167     }
1169     plugin::save();
1170     $ldap= $this->config->get_ldap_link();
1172     $realyUsedAttrs= array();
1174     /* Save already used objectClasses */
1175     $ocs        = $this->attrs['objectClass'];
1176     unset($ocs['count']);
1177     $this->attrs = array();
1178     $this->attrs['objectClass']= gosa_array_merge($ocs,$this->objectclasses);
1180     /* 1. Search all printers that have our uid/cn as member 
1181      * 2. Delete this uid/cn from every single entry and save it again.
1182      * 2.1 There are different types of members: Users / Groups, this will be defined in $suffix
1183      * 2.2 And each type has two modes, Admin (e.g. 'gotoUserAdminPrinter') and Normal 
1184      */
1185     
1186     $this->detect_grouptype();
1188     if($this->add_del_printer_member_was_called){
1190       $types = array( "gotoUserPrinter"       => "AddUser",
1191           "gotoGroupPrinter"      => "AddGroup",
1192           "gotoUserAdminPrinter"  => "AddAdminUser",
1193           "gotoGroupAdminPrinter" => "AddAdminGroup");
1195       if($this->is_group){
1196         $s_suffix = "Group";
1197         $useVar   = "cn";
1198       }else{
1199         $useVar   = "uid";
1200         $s_suffix = "User";
1201       }
1203       /* Remove old entries */
1204       $ldap->cd($this->config->current['BASE']);;
1205       $ldap->search("(&(objectClass=gotoPrinter)(goto".$s_suffix."Printer=".$this->$useVar."))",array("*"));
1206       while($attr = $ldap->fetch()){
1207         $printerObj = NULL;
1208         $printerObj = new printtabs($this->config,$this->config->data['TABS']['PRINTTABS'],$attr['dn'],"printer");
1209         $printerObj->set_acl_base($attr['dn']);
1210         $printerObj->by_object['printgeneric']->DelMember($types["goto".$s_suffix."Printer"],$this->$useVar);
1211         $printerObj->by_object['printgeneric']->save();
1212       }
1214       $ldap->cd($this->config->current['BASE']);;
1215       $ldap->search("(&(objectClass=gotoPrinter)(goto".$s_suffix."AdminPrinter=".$this->$useVar."))",array("*"));
1216       while($attr = $ldap->fetch()){
1217         $printerObj = NULL;
1218         $printerObj = new printtabs($this->config,$this->config->data['TABS']['PRINTTABS'],$attr['dn'],"printer");
1219         $printerObj->set_acl_base($attr['dn']);
1220         $printerObj->by_object['printgeneric']->DelMember($types["goto".$s_suffix."AdminPrinter"],$this->$useVar);
1221         $printerObj->by_object['printgeneric']->save();
1222       }
1224       foreach($this->gotoPrinter as $printer){
1225         $printerObj = NULL;
1226         $printerObj = new printtabs($this->config,$this->config->data['TABS']['PRINTTABS'],$printer['dn'],"printer");
1227         $printerObj->set_acl_base($printer['dn']);
1230         if($printer['mode'] == "admin") {
1231           $attribute = "goto".$s_suffix."AdminPrinter";
1232         }else{
1233           $attribute = "goto".$s_suffix."Printer";
1234         }
1236         $printerObj->by_object['printgeneric']->AddMember($types[$attribute],$this->dn);
1237         $printerObj->by_object['printgeneric']->save();
1238       }
1239     }    
1241     /* Prepare HotPlug devices */
1242     $this->attrs['gotoHotplugDeviceDN'] = array();
1243     foreach($this->gotoHotplugDevices as $name => $device){
1244       $this->attrs['gotoHotplugDeviceDN'][]= LDAP::fix($device['dn']);
1245     }
1247     /* Prepare LogonScripts */
1248     $this->attrs['gotoLogonScript'] = array();
1249     foreach($this->gotoLogonScripts as $name => $script){
1250       $this->attrs['gotoLogonScript'][] =   $script['LogonName']."|".
1251         $script['LogonOverload'].$script['LogonLast']."|".
1252         $script['LogonPriority']."|".
1253         base64_encode($script['LogonData'])."|".
1254         $script['LogonDescription'];
1255     }
1257     /* Prepare Shares */
1258     $this->attrs['gotoShare']=array();
1259     foreach($this->gotoShares as $name => $share){
1260       $mntp= $share['mountPoint'];
1261       if (!preg_match('=^[a-z0-9+\._/%-]+$=i', $mntp)){
1262         $mntp= base64_encode($mntp);
1263       }
1264       $this->attrs['gotoShare'][] =$share['server']."|".$share['name']."|".$mntp."|".$share['PwdHash']."|".$share['Username'];
1265     }
1268     if($this->gotoXResolution == "auto") $this->gotoXResolution ="";
1269     $saveThis = array("gotoProfileQuota","gotoXResolution","gotoProfileServer","gotoKioskProfile","gosaDefaultPrinter");
1271     foreach($saveThis as $tosave){
1272       if(!empty($this->$tosave)){
1273         $this->attrs[$tosave]=$this->$tosave;
1274       }else{
1275         $this->attrs[$tosave]=array();
1276       }
1277     }
1279     /* Prepare Flags */
1280     $this->attrs['gotoProfileFlags'] = array($this->gotoProfileFlagC.$this->gotoProfileFlagL);
1281     if(empty($this->attrs['gotoProfileFlags'][0])){
1282       $this->attrs['gotoProfileFlags']=array();
1283     }
1285     if($this->useProfile == false){
1286       $this->attrs['gotoProfileFlags'] = preg_replace("/C/i","",$this->attrs['gotoProfileFlags']);
1287       $this->attrs['gotoProfileServer']= array(); 
1288     }
1290     $ldap->cat ($this->dn, array('dn'));
1291     if ($ldap->fetch()){
1292       $mode= "modify";
1293     } else {
1294       $mode= "add";
1295       $ldap->cd($this->config->current['BASE']);
1296       $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
1297     }
1299     $ldap->cd($this->dn);
1300     $this->cleanup();
1301     $ldap->$mode($this->attrs);
1302   
1303     $cat = "users";
1304     if($this->is_group){
1305       $cat = "groups";
1306     }
1308     /* Log last action */ 
1309     if($this->initially_was_account){
1310       new log("modify",$cat."/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1311     }else{
1312       new log("create",$cat."/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1313     }
1315     if (!$ldap->success()){
1316       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, 0, get_class()));
1317     }
1318     $this->handle_post_events($mode,array("uid"=>$this->uid));
1319   }
1321   /* Generate ListBox frindly output for the defined shares 
1322    * Possibly Add or remove an attribute here, 
1323    */
1324   function printOutAssignedShares()
1325   {
1326     $a_return = array();
1327     if(is_array($this->gotoShares)){
1328       foreach($this->gotoShares as $share){
1329         if(preg_match("/^!/",$share['server'])){
1330           $a_return[$share['name']."|".$share['server']]= preg_replace("/^!/","",$share['server'])."://".$share['name']." - "._("group share"); 
1331         }else{
1332           $a_return[$share['name']."|".$share['server']]= $share['server']."://".$share['name']." on ".$share['mountPoint']." as ".$share['Username'];
1333         }
1334       }
1335       natcasesort($a_return);
1336     }
1337     return($a_return);
1338   }
1340   /* Generate ListBox frindly output for the definedhotplugs 
1341    * Possibly Add or remove an attribute here,
1342    */
1343   function printOutHotPlugDevices()
1344   {
1345     $a_return= array();
1346     if(is_array($this->gotoHotplugDevices)){
1347       foreach($this->gotoHotplugDevices as $key=>$device){
1348         $a_return[$key] = $device['name']." - ".$device['id'];
1349       }
1350     }
1351     return($a_return);
1352   }
1354   /* Generates ListBox frienly output of used printer devices 
1355    * Append ' - admin' if printer is used in admin mode
1356    */
1357   function printOutPrinterDevices()
1358   {
1359     $a_return = array();
1361     if(is_array($this->gotoPrinter)){
1362       foreach($this->gotoPrinter as $printer){
1363         if($printer['mode'] == 'admin'){
1364           $a_return[$printer['cn'][0]]= $printer['cn'][0]." - "._("Administrator");
1365         }else{
1366           $a_return[$printer['cn'][0]]= $printer['cn'][0]; 
1367         }
1368         if ($printer['cn'][0] == $this->gosaDefaultPrinter){
1369           $a_return[$printer['cn'][0]].=" - "._("Default printer");
1370         }
1371       }
1372     }
1373                 asort($a_return);
1374     return($a_return);
1375   }
1378   function PrepareForCopyPaste($source)
1379   {
1380     plugin::PrepareForCopyPaste($source);
1382     $class= get_class($this);
1383     $o_source = new $class($this->config,$source['dn']);
1384     foreach($this->CopyPasteVars as $attr){
1385       $this->$attr = $o_source->$attr;  
1386     }
1387   }
1390   function saveCopyDialog()
1391   {
1392     if(isset($_POST['cn'])){
1393       $this->cn = $_POST['cn'];
1394       $this->uid = $_POST['cn'];
1395     }
1396   }
1399   /* Generates ListBox frienly output of used logonscripts 
1400    */
1401   function printOutLogonScripts()
1402   {
1403     $a_return = array();
1404     if(is_array($this->gotoLogonScripts)){
1405       foreach($this->gotoLogonScripts as $script){
1406         $a_return[$script['LogonName']]= $script['LogonPriority']." - ".$script['LogonName']; 
1407       }
1408     }
1409     return($a_return);
1410   }
1413   function multiple_execute()
1414   {
1415     /* Reset header toggle */
1416     $this->is_account = TRUE;
1417     return($this->execute());
1418   }
1421     /* Initialize plugin with given atribute arrays
1422    */
1423   function init_multiple_support($attrs,$all)
1424   {
1425     plugin::init_multiple_support($attrs,$all);
1427     /* Prepare Shares */
1428     if((isset($this->multi_attrs_all['gotoShare']))&&(is_array($this->multi_attrs_all['gotoShare']))){
1429       unset($this->multi_attrs_all['gotoShare']['count']);
1430       foreach($this->multi_attrs_all['gotoShare'] as $share){
1431         $tmp = $tmp2 = array();
1432         $tmp = explode("|",$share);
1433         $tmp2['server']      =$tmp[0];
1434         $tmp2['name']        =$tmp[1];
1436         /* Decode base64 if needed */
1437         if (!preg_match('%/%', $tmp[2])){
1438           $tmp2['mountPoint']  =base64_decode($tmp[2]);
1439         } else {
1440           $tmp2['mountPoint']  =$tmp[2];
1441         }
1443         if(isset($tmp[3])){
1444           $tmp2['PwdHash']  =$tmp[3];
1445         }else{
1446           $tmp2['PwdHash']  ="";
1447         }
1448         if(isset($tmp[4])){
1449           $tmp2['Username']  =$tmp[4];
1450         }else{
1451           $tmp2['Username']  ="";
1452         }
1453         $tmp2['UsedByAllUsers'] = FALSE;
1454         $this->gotoShares[$tmp[1]."|".$tmp[0]]=$tmp2;
1455       }
1456     }
1458     /* Prepare Shares */
1459     if((isset($this->multi_attrs['gotoShare']))&&(is_array($this->multi_attrs['gotoShare']))){
1460       unset($this->multi_attrs['gotoShare']['count']);
1461       foreach($this->multi_attrs['gotoShare'] as $share){
1462         $tmp = $tmp2 = array();
1463         $tmp = explode("|",$share);
1464         $tmp2['server']      =$tmp[0];
1465         $tmp2['name']        =$tmp[1];
1467         /* Decode base64 if needed */
1468         if (!preg_match('%/%', $tmp[2])){
1469           $tmp2['mountPoint']  =base64_decode($tmp[2]);
1470         } else {
1471           $tmp2['mountPoint']  =$tmp[2];
1472         }
1474         if(isset($tmp[3])){
1475           $tmp2['PwdHash']  =$tmp[3];
1476         }else{
1477           $tmp2['PwdHash']  ="";
1478         }
1479         if(isset($tmp[4])){
1480           $tmp2['Username']  =$tmp[4];
1481         }else{
1482           $tmp2['Username']  ="";
1483         }
1484         $tmp2['UsedByAllUsers'] = TRUE;
1485         $this->gotoShares[$tmp[1]."|".$tmp[0]]=$tmp2;
1486       }
1487     }
1490     /* prepare LogonScripts */
1491     if((isset($this->multi_attrs_all['gotoLogonScript']))&&(is_array($this->multi_attrs_all['gotoLogonScript']))){
1492       unset($this->multi_attrs_all['gotoLogonScript']['count']);
1493       foreach($this->multi_attrs_all['gotoLogonScript'] as $device){
1494         $tmp = $tmp2 = array();
1495         $tmp = explode("|",$device);
1496         $tmp2['LogonName']        = $tmp[0];
1497         $tmp2['LogonPriority']    = $tmp[2];
1498         if(preg_match("/O/i",$tmp[1])){
1499           $tmp2['LogonOverload'] = "O";
1500         }else{
1501           $tmp2['LogonOverload'] = "";
1502         }
1503         if(preg_match("/L/i",$tmp[1])){
1504           $tmp2['LogonLast'] = "L";
1505         }else{
1506           $tmp2['LogonLast'] = "";
1507         }
1508         $tmp2['LogonData']        = base64_decode($tmp[3]);
1509         $tmp2['LogonDescription'] = $tmp[4];
1510         $tmp2['UsedByAllUsers'] = FALSE;
1511         $this->gotoLogonScripts[$tmp[0]]=$tmp2;
1512       }
1513     }
1515     /* prepare LogonScripts */
1516     if((isset($this->multi_attrs['gotoLogonScript']))&&(is_array($this->multi_attrs['gotoLogonScript']))){
1517       unset($this->multi_attrs['gotoLogonScript']['count']);
1518       foreach($this->multi_attrs['gotoLogonScript'] as $device){
1519         $tmp = $tmp2 = array();
1520         $tmp = explode("|",$device);
1521         $tmp2['LogonName']        = $tmp[0];
1522         $tmp2['LogonPriority']    = $tmp[2];
1523         if(preg_match("/O/i",$tmp[1])){
1524           $tmp2['LogonOverload'] = "O";
1525         }else{
1526           $tmp2['LogonOverload'] = "";
1527         }
1528         if(preg_match("/L/i",$tmp[1])){
1529           $tmp2['LogonLast'] = "L";
1530         }else{
1531           $tmp2['LogonLast'] = "";
1532         }
1533         $tmp2['LogonData']        = base64_decode($tmp[3]);
1534         $tmp2['LogonDescription'] = $tmp[4];
1535         $tmp2['UsedByAllUsers'] = TRUE;
1536         $this->gotoLogonScripts[$tmp[0]]=$tmp2;
1537       }
1538     }
1540     /* Prepare hotplugs */
1541     if(isset($this->multi_attrs_all['gotoHotplugDeviceDN']) && is_array($this->multi_attrs_all['gotoHotplugDeviceDN'])){
1542       $ldap = $this->config->get_ldap_link();
1543       $ldap->cd($this->config->current['BASE']);
1544       for($i = 0 ; $i < $this->multi_attrs_all['gotoHotplugDeviceDN']['count'] ; $i ++){
1545         $ldap->cat($this->multi_attrs_all['gotoHotplugDeviceDN'][$i]);
1546         if($ldap->count()){
1547           $multi_attrs_all = $ldap->fetch();
1549           if(isset($multi_attrs_all['gotoHotplugDevice'][0])){
1550             $tmp      = preg_split("/\|/",$multi_attrs_all['gotoHotplugDevice'][0]);
1551             $tmp2     = array();
1552             $tmp2['name']         = $multi_attrs_all['cn'][0];
1553             $tmp2['description']  = $tmp[0];
1554             $tmp2['id']           = $tmp[1];
1555             $tmp2['produkt']      = $tmp[2];
1556             $tmp2['vendor']       = $tmp[3];
1557             $tmp2['dn']           = $multi_attrs_all['dn'];
1558             $tmp2['UsedByAllUsers'] = FALSE;
1559             $this->gotoHotplugDevices[$tmp2['dn']] = $tmp2;
1560           }
1561         }
1562       }
1563     }
1565     /* Prepare hotplugs */
1566     if(isset($this->multi_attrs['gotoHotplugDeviceDN']) && is_array($this->multi_attrs['gotoHotplugDeviceDN'])){
1567       $ldap = $this->config->get_ldap_link();
1568       $ldap->cd($this->config->current['BASE']);
1569       for($i = 0 ; $i < $this->multi_attrs['gotoHotplugDeviceDN']['count'] ; $i ++){
1570         $ldap->cat($this->multi_attrs['gotoHotplugDeviceDN'][$i]);
1571         if($ldap->count()){
1572           $multi_attrs = $ldap->fetch();
1574           if(isset($multi_attrs['gotoHotplugDevice'][0])){
1575             $tmp      = preg_split("/\|/",$multi_attrs['gotoHotplugDevice'][0]);
1576             $tmp2     = array();
1577             $tmp2['name']         = $multi_attrs['cn'][0];
1578             $tmp2['description']  = $tmp[0];
1579             $tmp2['id']           = $tmp[1];
1580             $tmp2['produkt']      = $tmp[2];
1581             $tmp2['vendor']       = $tmp[3];
1582             $tmp2['dn']           = $multi_attrs['dn'];
1583             $tmp2['UsedByAllUsers'] = TRUE;
1584             $this->gotoHotplugDevices[$tmp2['dn']] = $tmp2;
1585           }
1586         }
1587       }
1588     }
1589     $this->gotoHotplugDevices = array_values($this->gotoHotplugDevices);
1590     for($i = 0 ; $i < strlen($this->gotoProfileFlags) ; $i ++){
1591       $chr = $this->gotoProfileFlags[$i];
1592       $name = "gotoProfileFlag".$chr;
1593       $this->$name=$chr;
1594     }
1595     $this->update_kiosk_profiles();
1596     $this->gotoKioskProfile= preg_replace("/^.*\//i","",$this->gotoKioskProfile);
1598     if((!empty($this->gotoProfileServer))||($this->gotoProfileFlagC=="C")){
1599       $this->useProfile = true;
1600     }else{
1601       $this->useProfile = false;
1602     }
1604   }
1607   function set_multi_edit_values($attrs)
1608   {
1609     $shares = $this->gotoShares;
1610     $scripts= $this->gotoLogonScripts;
1611     $plugs= $this->gotoHotplugDevices;
1612     plugin::set_multi_edit_values($attrs);
1614     $this->gotoShares = $shares;
1615     $this->gotoLogonScripts = $scripts;
1616     $this->gotoHotplugDevices = $plugs;
1618     foreach($attrs['gotoShares'] as $name => $share){
1619       if($share['UsedByAllUsers'] == TRUE){
1620         $this->gotoShares[$name] = $share;
1621       }
1622     }
1623     foreach($this->gotoShares as $name => $share){
1624       if(!isset($attrs['gotoShares'][$name])){
1625         unset($this->gotoShares[$name]);
1626       }
1627     }
1628     foreach($attrs['gotoLogonScripts'] as $name => $script){
1629       if($script['UsedByAllUsers'] == TRUE){
1630         $this->gotoLogonScripts[$name] = $script;
1631       }
1632     }
1633     foreach($this->gotoLogonScripts as $name => $script){
1634       if(!isset($attrs['gotoLogonScripts'][$name])){
1635         unset($this->gotoLogonScripts[$name]);
1636       }
1637     }
1638     $tmp = array();
1639     foreach($this->gotoHotplugDevices as $entry){
1640       $tmp[$entry['dn']] = $entry;
1641     }
1642   
1643     foreach($attrs['gotoHotplugDevices'] as $name => $plug){
1644       if($plug['UsedByAllUsers'] == TRUE){
1645         $tmp[$plug['dn']] = $plug;
1646       }
1647     }
1648     foreach($tmp as $name => $plug){
1649       $found = false;
1650       foreach($attrs['gotoHotplugDevices'] as $test){
1651         if($test['dn'] == $name){
1652           $found = true;
1653         }
1654       }
1655       if(!$found){
1656         unset($tmp[$name]);
1657       }
1658     }
1659   }
1662     /* Return selected values for multiple edit */
1663   function get_multi_edit_values()
1664   {
1665     $ret = plugin::get_multi_edit_values();
1666     $ret['gotoShares'] = $this->gotoShares;
1667     $ret['gotoLogonScripts'] = $this->gotoLogonScripts;
1668     $ret['gotoHotplugDevices'] = $this->gotoHotplugDevices;
1669   
1670     if(in_array("gotoPrinter",$this->multi_boxes)){
1671       $ret['gotoPrinter'] = $this->gotoPrinter;
1672       $ret['gotoPrinterSel'] = $this->gotoPrinterSel;
1673       $ret['gosaDefaultPrinter'] = $this->gosaDefaultPrinter;
1674   
1675       /* Force printer reset */
1676       $ret['add_del_printer_member_was_called'] = TRUE;
1677     }
1678   
1679     if(in_array("gotoProfileFlagL",$this->multi_boxes)){
1680       $ret['gotoProfileFlagL'] = $this->gotoProfileFlagL;
1681     }
1683     if(in_array("useProfile",$this->multi_boxes)){
1684       $ret['useProfile']=$this->useProfile;
1685       if(in_array("gotoProfileServer",$this->multi_boxes)){
1686         $ret['gotoProfileServer']=$this->gotoProfileServer;
1687       }
1688       if(in_array("gotoProfileQuota",$this->multi_boxes)){
1689         $ret['gotoProfileQuota']=$this->gotoProfileQuota;
1690       }
1691       if(in_array("gotoProfileFlagC",$this->multi_boxes)){
1692         $ret['gotoProfileFlagC'] = $this->gotoProfileFlagC;
1693       }
1694     }
1695     if(in_array("gotoXResolution",$this->multi_boxes)){
1696       $ret['gotoXResolution'] = $this->gotoXResolution;
1697     }
1698     if(in_array("kiosk_server",$this->multi_boxes)){
1699       $ret['gotoKioskProfile_Server'] = $this->gotoKioskProfile_Server;
1700       $ret['gotoKioskProfile_Profile'] = $this->gotoKioskProfile_Profile;
1701     }
1702     return($ret);
1703   }
1706   function multiple_check() 
1707   {
1708     $message = plugin::multiple_check();
1709     $this->detect_grouptype();
1711     if(preg_match("/[^0-9]/",$this->gotoProfileQuota) && in_array("gotoProfileQuota",$this->multi_boxes)) {
1712       $message[] = msgPool::invalid(_("Profile quota"),$this->gotoProfileQuota,"/[0-9]/") ;
1713     }
1714     return($message);
1715   }
1718   function multiple_save_object()
1719   {
1720     if(isset($_POST['environment_multiple_posted'])){
1721       plugin::multiple_save_object();
1722       
1723       if(isset($_POST['useProfile'])){
1724         $this->useProfile = true;
1725       }else{
1726         $this->useProfile = false;
1727       }
1728       if(isset($_POST['gotoProfileFlagC'])){
1729         $this->gotoProfileFlagC = $_POST['gotoProfileFlagC'];
1730       }else{
1731         $this->gotoProfileFlagC = false;
1732       }
1734       if(isset($_POST['gotoProfileFlagL'])){
1735         $this->gotoProfileFlagL = $_POST['gotoProfileFlagL'];
1736       }else{
1737         $this->gotoProfileFlagL = false;
1738       }
1740       foreach(array("gotoProfileFlagL","gotoPrinter","kiosk_server","gotoXResolution",
1741                     "useProfile","gotoProfileServer","gotoProfileQuota","gotoProfileFlagC") as $attr){
1742         $uattr = "use_".$attr;
1743         if(isset($_POST[$uattr])){
1744           $this->multi_boxes[] = $attr;
1745         }
1746       }
1747       if(isset($_POST['kiosk_server'])){
1748         $tmp = $_POST['kiosk_server'];
1749         if(isset($this->gotoKioskProfiles['SERVERS'][$tmp])){
1750           $this->gotoKioskProfile_Server = $_POST['kiosk_server'];
1751         }
1752       }
1753       if(isset($_POST['kiosk_profile'])){
1754         $tmp = $_POST['kiosk_profile'];
1755         if(in_array($tmp,$this->gotoKioskProfiles['BY_SERVER'][$this->gotoKioskProfile_Server])){
1756           $this->gotoKioskProfile_Profile = $_POST['kiosk_profile'];
1757         }
1758       }
1760     }
1761   }
1763   /* Return plugin informations for acl handling 
1764 #FIXME these ACLs should work for groups too */ 
1765   static function plInfo()
1766   {
1767     return (array("plShortName"     => _("Environment"),
1768           "plDescription"   => _("Environment settings"),         // Description
1769           "plSelfModify"    => TRUE,                              
1770           "plDepends"       => array("user", "posixAccount"),     // This plugin depends on 
1771           "plPriority"      => 3,                                 // Position in tabs 
1772           "plSection"     => array("personal" => _("My account")),
1773           "plCategory"    => array("users",
1774                                    "groups"),
1775           "plOptions"       => array("resolution_hook" => array("type" => "string",
1776               "description" => _("Command to extend the list of possible screen resolutions"))),
1778           "plProvidedAcls"  => array(
1780             "gotoPrinter"         => _("Printer") ,
1781             "gotoProfileServer"   => _("Profile server") ,
1782             "gosaDefaultPrinter"  => _("Default printer"),
1783             "gotoProfileQuota"    => _("Profile quota") ,
1784             "gotoProfileFlagC"    => _("Cache profile localy") ,
1785             "gotoShare"          => _("Shares"),
1786             "gotoHotplugDeviceDN" => _("Hotplug devices"),
1787             "gotoKioskProfile"    => _("Kiosk profile") ,
1788             "gotoProfileFlagL"    => _("Resolution changeable during session") ,
1789             "gotoXResolution"     => _("Resolution") ,
1790             "gotoLogonScript"     => _("Logon script"))
1791             ));
1792   }
1795 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1796 ?>