Code

9e4adc8b53d128a9db020cf053304a2b16110eeb
[gosa.git] / gosa-core / plugins / personal / posix / class_posixAccount.inc
1 <?php
2 /*
3  * This code is part of GOsa (http://www.gosa-project.org)
4  * Copyright (C) 2003-2008 GONICUS GmbH
5  *
6  * ID: $$Id$$
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
23 /*!
24   \brief   posixAccount plugin
25   \author  Cajus Pollmeier <pollmeier@gonicus.de>
26   \version 2.00
27   \date    24.07.2003
29   This class provides the functionality to read and write all attributes
30   relevant for posixAccounts and shadowAccounts from/to the LDAP. It
31   does syntax checking and displays the formulars required.
32  */
34 class posixAccount extends plugin
35 {
36   /* Definitions */
37   var $plHeadline= "POSIX";
38   var $plDescription= "Edit users POSIX settings";
40   /* Plugin specific values */
41   var $homeDirectory= "";
42   var $loginShell= "/bin/bash";
43   var $uidNumber= "";
44   var $gidNumber= "";
45   var $gecos= "";
46   var $shadowMin= "0";
47   var $shadowMax= "0";
48   var $shadowWarning= "0";
49   var $shadowLastChange= "0";
50   var $shadowInactive= "0";
51   var $shadowExpire= "";
52   var $accessTo= array();
54   var $glist=array();
55   var $status= "";
56   var $loginShellList= array();
57   var $groupMembership= array();
58   var $savedGroupMembership= array();
59   var $savedUidNumber= "";
60   var $savedGidNumber= "";
61   var $activate_shadowMin= "0";
62   var $activate_shadowMax= "0";
63   var $activate_shadowWarning= "0";
64   var $activate_shadowInactive= "0";
65   var $activate_shadowExpire= "0";
66   var $mustchangepassword= "0";
67   var $force_ids= 0;
68   var $gotoLastSystemLogin= "";
69   var $groupSelect= FALSE;
70   var $secondaryGroups= array();
71   var $primaryGroup= 0;
72   var $memberGroup= array();
73   var $grouplist= array();
74   var $ui= array();
75   var $ssh= null;
76   var $sshAcl= "";
78   var $view_logged= false;
80   /* attribute list for save action */
81   var $CopyPasteVars  = 
82     array("grouplist","groupMembership","activate_shadowMin",
83         "activate_shadowMax","activate_shadowWarning","activate_shadowInactive","activate_shadowExpire",
84         "must_change_password","printerList","grouplist","savedGidNumber","savedUidNumber");
86   var $attributes     = array("homeDirectory", "loginShell", "uidNumber", "gidNumber", "gecos",
87       "shadowMin", "shadowMax", "shadowWarning", "shadowInactive", "shadowLastChange",
88       "shadowExpire", "uid", "gotoLastSystemLogin");
90   var $objectclasses= array("posixAccount", "shadowAccount");
92   var $uid= "";
93   var $multiple_support = TRUE;
94   var $groupMembership_some = array();
96   /* constructor, if 'dn' is set, the node loads the given
97      'dn' from LDAP */
98   function posixAccount (&$config, $dn= NULL, $parent =NULL)
99   {
100     global $class_mapping;
102     /* Configuration is fine, allways */
103     $this->config= $config;
105     /* Load bases attributes */
106     plugin::plugin($config, $dn, $parent);
108     $this->trustModeDialog = new trustModeDialog($this->config, $this->dn, $parent);
109     $this->trustModeDialog->setAcl('users/posixAccount');
111     /*  If gotoLastSystemLogin is available read it from ldap and create a readable
112         date time string, fallback to sambaLogonTime if available.
113      */
114     if(isset($this->attrs['gotoLastSystemLogin'][0]) && preg_match("/^[0-9]*$/",$this->attrs['gotoLastSystemLogin'][0])){
115       $this->gotoLastSystemLogin = date("d.m.Y H:i:s", strtotime($this->attrs['gotoLastSystemLogin'][0]));
116     } else if(isset($this->attrs['sambaLogonTime'][0]) && preg_match("/^[0-9]*$/",$this->attrs['sambaLogonTime'][0])){
117       $this->gotoLastSystemLogin = date("d.m.Y H:i:s", $this->attrs['sambaLogonTime'][0]);
118     }
120     /* Setting uid to default */
121     if(isset($this->attrs['uid'][0])){
122       $this->uid = $this->attrs['uid'][0];
123     }
125     $ldap= $this->config->get_ldap_link();
127     if ($dn !== NULL){
129       /* Correct is_account. shadowAccount is not required. */
130       if (isset($this->attrs['objectClass']) &&
131           in_array ('posixAccount', $this->attrs['objectClass'])){
133         $this->is_account= TRUE;
134       }
135       $this->initially_was_account= $this->is_account;
137       /* Fill group */
138       $this->primaryGroup= $this->gidNumber;
140       /* Generate status text */
141       $current= date("U");
143       $current= floor($current / 60 /60 / 24);
145       if (($current >= $this->shadowExpire) && $this->shadowExpire){
146         $this->status= _("expired");
147         if (($current - $this->shadowExpire) < $this->shadowInactive){
148           $this->status.= ", "._("grace time active");
149         }
150       } elseif (($this->shadowLastChange + $this->shadowMin) >= $current){
151         $this->status= _("active").", "._("password not changeable");
152       } elseif (($this->shadowLastChange + $this->shadowMax) >= $current){
153         $this->status= _("active").", "._("password expired");
154       } else {
155         $this->status= _("active");
156       }
158       /* Get group membership */
159       $ldap->cd($this->config->current['BASE']);
160       $ldap->search("(&(objectClass=posixGroup)(memberUid=".$this->uid."))", array("cn", "description"));
162       while ($attrs= $ldap->fetch()){
163         if (!isset($attrs["description"][0])){
164           $entry= $attrs["cn"][0];
165         } else {
166           $entry= $attrs["cn"][0]." [".$attrs["description"][0]."]";
167         }
168         $this->groupMembership[$ldap->getDN()]= $entry;
169       }
170       asort($this->groupMembership);
171       reset($this->groupMembership);
172       $this->savedGroupMembership= $this->groupMembership;
173       $this->savedUidNumber= $this->uidNumber;
174       $this->savedGidNumber= $this->gidNumber;
176       // Instanciate SSH object if available
177       if (isset($class_mapping["sshPublicKey"])){
178         if (empty($this->acl_base)){
179           $this->acl_base= $config->current['BASE'];
180         }
182         $this->sshAcl= $this->getacl("sshPublicKey");
183         $this->ssh= new sshPublicKey($this->config, $this->dn, $this->sshAcl);
184       }
185     }
187     /* Adjust shadow checkboxes */
188     foreach (array("shadowMin", "shadowMax", "shadowWarning", "shadowInactive",
189           "shadowExpire") as $val){
191       if ($this->$val != 0){
192         $oval= "activate_".$val;
193         $this->$oval= "1";
194       }
195     }
197     /* Convert shadowExpire for usage */
198     if ($this->shadowExpire == 0){
199       $this->shadowExpire= "";
200     } else {
201       $this->shadowExpire= date('d.m.Y', $this->shadowExpire * 60 * 60 * 24);
202     }
205     /* Generate shell list from CONFIG_DIR./shells */
206     if (file_exists(CONFIG_DIR.'/shells')){
207       $shells = file (CONFIG_DIR.'/shells');
208       foreach ($shells as $line){
209         if (!preg_match ("/^#/", $line)){
210           $this->loginShellList[]= trim($line);
211         }
212       }
213     } else {
214       if ($this->loginShell == ""){
215         $this->loginShellList[]= _("unconfigured");
216       }
217     }
219     /* Insert possibly missing loginShell */
220     if ($this->loginShell != "" && !in_array($this->loginShell, $this->loginShellList)){
221       $this->loginShellList[]= $this->loginShell;
222     }
224     /* Generate group list */
225     $this->ui = get_userinfo(); 
226     $this->secondaryGroups[]= "- "._("automatic")." -";
227     $ldap->cd($this->config->current['BASE']);
228     $ldap->search("(objectClass=posixGroup)", array("cn", "gidNumber"));
229     while($attrs = $ldap->fetch()){
230       $this->secondaryGroups[$attrs['gidNumber'][0]]= $attrs['cn'][0];
231     }
232     asort ($this->secondaryGroups);
234     $this->ui = get_userinfo();
235   }
238   /* execute generates the html output for this node */
239   function execute($isCopyPaste = false)
240   {
241     /* Call parent execute */
242     plugin::execute();
243     $display= "";
245     /* Log view */
246     if($this->is_account && !$this->view_logged){
247       $this->view_logged = TRUE;
248       new log("view","users/".get_class($this),$this->dn);
249     }
250     $this->dialog = FALSE;
252     if($this->multiple_support_active){
253       $this->is_account = TRUE;
254     }
256     if(!$isCopyPaste && ! $this->multiple_support_active){
258       /* Do we need to flip is_account state? */
259       if(isset($_POST['modify_state'])){
260         if($this->is_account && $this->acl_is_removeable()){
261           $this->is_account= FALSE;
262         }elseif(!$this->is_account && $this->acl_is_createable()){
263           $this->is_account= TRUE;
264         }
265       }
267       /* Do we represent a valid posixAccount? */
268       if (!$this->is_account && $this->parent === NULL ){
269         $display= "<img alt=\"\" src=\"images/small-error.png\" align=\"middle\">&nbsp;<b>".
270           msgPool::noValidExtension(_("POSIX"))."</b>";
271         $display.= back_to_main();
272         return ($display);
273       }
276       /* Show tab dialog headers */
277       if ($this->parent !== NULL){
278         if ($this->is_account){
279           if (isset($this->parent->by_object['sambaAccount'])){
280             $obj= $this->parent->by_object['sambaAccount'];
281           }
282           if (isset($obj) && $obj->is_account == TRUE &&
283               ((isset($this->parent->by_object['sambaAccount']))&&($this->parent->by_object['sambaAccount']->is_account))
284               ||(isset($this->parent->by_object['environment'] ))&&($this->parent->by_object['environment'] ->is_account)){
286             /* Samba3 dependency on posix accounts are enabled
287                in the moment, because I need to rely on unique
288                uidNumbers. There'll be a better solution later
289                on. */
290             $display= $this->show_disable_header(msgPool::removeFeaturesButton(_("POSIX")), msgPool::featuresEnabled(_("POSIX"), array(_("Samba"), _("Environment"))), TRUE);
291           } else {
292             $display= $this->show_disable_header(msgPool::removeFeaturesButton(_("POSIX")), msgPool::featuresEnabled(_("POSIX")));
293           }
294         } else {
295           $display= $this->show_enable_header(msgPool::addFeaturesButton(_("POSIX")), msgPool::featuresDisabled(_("POSIX")));
296           return($display);
297         }
298       }
299     }
301     // Display dialog to allow selection of groups
302     if (isset($_POST['edit_groupmembership'])){
303       $this->groupSelect = new groupSelect($this->config,get_userinfo());
304     }
306     // Cancel group dialog
307     if (isset($_POST['add_groups_cancel'])){
308       $this->groupSelect= NULL;
309     }
311     // Add groups selected in groupSelect dialog to ours.
312     if (isset($_POST['add_groups_finish']) && $this->groupSelect){
313       $groups = $this->groupSelect->detectPostActions();
314       if(isset($groups['targets'])){
315         $this->addGroup ($groups['targets']);
316         $this->is_modified= TRUE;
317       }
318       $this->groupSelect= NULL;
319     }
321     // Remove groups from currently selected groups.
322     if (isset($_POST['delete_groupmembership']) && 
323         isset($_POST['group_list']) && count($_POST['group_list'])){
325       $this->delGroup (get_post('group_list'));
326     }
328     /* Templates now! */
329     $smarty= get_smarty();
333     // Handle trust mode dialog
334     $trustModeDialog = $this->trustModeDialog->execute();
335     if($this->trustModeDialog->trustSelect){
336         $this->dialog = TRUE;
337         return($trustModeDialog);
338         
339     }
340     $smarty->assign("trustModeDialog" , $trustModeDialog);
343     /* Manage group add dialog */
344     if ($this->groupSelect){
345       $this->dialog = TRUE;
347       // Build up blocklist
348       session::set('filterBlacklist', array('dn' => array_keys($this->groupMembership)));
349       return($this->groupSelect->execute());
350     }
352     // Handle ssh dialog?
353     if ($this->ssh instanceOf sshPublicKey && preg_match('/[rw]/', $this->getacl("sshPublicKey"))) {
355       if ($result= $this->ssh->execute()) {
356         $this->dialog= true;
357         pathNavigator::registerPlugin("SSH keys");
358         return $result;
359       }
360     }
363     /* Show main page */
364     $smarty= get_smarty();
367     $smarty->assign("sshPublicKeyACL", $this->getacl("sshPublicKey"));
369     /* Depending on pwmode, currently hardcoded because there are no other methods */
370     if ( 1 == 1 ){
371       $smarty->assign("pwmode", dirname(__FILE__)."/posix_shadow");
373       $shadowMinACL     =  $this->getacl("shadowMin");
374       $smarty->assign("shadowmins", sprintf(_("Password can't be changed up to %s days after last change"), 
375             "<input type='text' name=\"shadowMin\" size=3 maxlength=4 value=\"".$this->shadowMin."\">"));
377       $shadowMaxACL     =  $this->getacl("shadowMax");
378       $smarty->assign("shadowmaxs", sprintf(_("Password must be changed after %s days"), 
379             "<input type='text' name=\"shadowMax\" size=3 maxlength=4 value=\"".$this->shadowMax."\">"));
381       $shadowInactiveACL=  $this->getacl("shadowInactive");
382       $smarty->assign("shadowinactives", sprintf(_("Disable account after %s days of inactivity after password expiry"), 
383             "<input type='text' name=\"shadowInactive\" size=3 maxlength=4 value=\"".$this->shadowInactive."\">"));
385       $shadowWarningACL =  $this->getacl("shadowWarning");
386       $smarty->assign("shadowwarnings", sprintf(_("Warn user %s days before password expiry"), 
387             "<input type='text' name=\"shadowWarning\" size=3 maxlength=4 value=\"".$this->shadowWarning."\">"));
389       foreach( array("activate_shadowMin", "activate_shadowMax",
390             "activate_shadowExpire", "activate_shadowInactive","activate_shadowWarning") as $val){
391         if ($this->$val == 1){
392           $smarty->assign("$val", "checked");
393         } else {
394           $smarty->assign("$val", "");
395         }
396         $smarty->assign("$val"."ACL", $this->getacl(preg_replace("/^.*_/","",$val)));
397       }
399       $smarty->assign("mustchangepasswordACL", $this->getacl("mustchangepassword"));
400     }
402     // Set last system login
403     $smarty->assign("gotoLastSystemLogin", set_post($this->gotoLastSystemLogin));
405     /* Fill arrays */
406     $smarty->assign("shells", set_post($this->loginShellList));
407     $smarty->assign("secondaryGroups", $this->secondaryGroups);
408     $smarty->assign("primaryGroup", set_post($this->primaryGroup));
409     if(!$this->multiple_support_active){
410       if (!count($this->groupMembership)){
411         $smarty->assign("groupMembership", array("&nbsp;"));
412       } else {
413         $smarty->assign("groupMembership", set_post($this->groupMembership));
414       }
415     }else{
416       $smarty->assign("groupMembership", set_post($this->groupMembership));
417       $smarty->assign("groupMembership_some", set_post($this->groupMembership_some));
418     }
420     if (count($this->groupMembership) > 16){
421       $smarty->assign("groups", "too_many_for_nfs");
422     } else {
423       $smarty->assign("groups", "");
424     }
426     /* Avoid "Undefined index: forceMode" */
427     $smarty->assign("forceMode", "");
429     /* Checkboxes */
430     if ($this->force_ids == 1){
431       $smarty->assign("force_ids", "checked");
432       if (session::get('js')){
433         $smarty->assign("forceMode", "");
434       }
435     } else {
436       if (session::get('js')){
437         $smarty->assign("forceMode", "disabled");
438       }
439       $smarty->assign("force_ids", "");
440     }
442     /* Create onClick="" action string for the "Force UID/GID" option 
443      */
444     $onClickIDS ="";
445     if(preg_match("/w/",$this->getacl("uidNumber"))){
446       $onClickIDS .= "changeState('uidNumber');";
447     }
448     if(preg_match("/w/",$this->getacl("gidNumber"))){
449       $onClickIDS .= "changeState('gidNumber');";
450     }
451     $smarty->assign("onClickIDS", $onClickIDS);
452     $smarty->assign("force_idsACL", $this->getacl("uidNumber").$this->getacl("gidNumber"));
454     foreach(array("primaryGroup","activate_shadowWarning","activate_shadowInactive","activate_shadowMin","activate_shadowMax","activate_shadowExpire","mustchangepassword") as $val){
455       if(in_array($val,$this->multi_boxes)){
456         $smarty->assign("use_".$val,TRUE);
457       }else{
458         $smarty->assign("use_".$val,FALSE);
459       }
460     }
463     /* Load attributes and acl's */
464     foreach($this->attributes as $val){
465       if(in_array($val,$this->multi_boxes)){
466         $smarty->assign("use_".$val,TRUE);
467       }else{
468         $smarty->assign("use_".$val,FALSE);
469       }
470       $smarty->assign("$val", set_post($this->$val));
471     }
473     $tmp = $this->plInfo();                                                                                    
474     foreach($tmp['plProvidedAcls'] as $val => $desc){                                                          
475       $smarty->assign("$val"."ACL", $this->getacl($val));                                                      
476     }   
478     if($this->read_only){
479       $smarty->assign("groupMembershipACL","r");
480     }else{
481       $smarty->assign("groupMembershipACL","rw");
482     }
483     $smarty->assign("status", $this->status);
485     if($this->mustchangepassword){
486       $smarty->assign("mustchangepassword", " checked ");
487     } else {
488       $smarty->assign("mustchangepassword", "");
489     }
491     // Add SSH button if available
492     $smarty->assign("sshPublicKey", $this->ssh?1:0);
494     $smarty->assign("multiple_support" , $this->multiple_support_active);
495     $display.= $smarty->fetch (get_template_path('generic.tpl', TRUE, dirname(__FILE__)));
496     return($display);
497   }
500   /* remove object from parent */
501   function remove_from_parent()
502   {
503     /* Cancel if there's nothing to do here */
504     if ((!$this->initially_was_account) || (!$this->acl_is_removeable())){
505       return;
506     }
509     /* Remove and write to LDAP */
510     plugin::remove_from_parent();
512     /* Zero out array */
513     $this->attrs['gosaHostACL']= array();
515     /* Keep uid, because we need it for authentification! */
516     unset($this->attrs['uid']);
518     @DEBUG (DEBUG_LDAP, __LINE__, __FUNCTION__, __FILE__,
519         /* include global link_info */
520         $this->attributes, "Save");
521     $ldap= $this->config->get_ldap_link();
522     $ldap->cd($this->dn);
523     $this->cleanup();
524     $ldap->modify ($this->attrs); 
526     new log("remove","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
528     if (!$ldap->success()){
529       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
530     }
532     /* Delete group only if cn is uid and there are no other
533        members inside */
534     $ldap->cd ($this->config->current['BASE']);
535     $ldap->search ("(&(objectClass=posixGroup)(gidNumber=".$this->gidNumber."))", array("cn", "memberUid"));
536     if ($ldap->count() != 0){
537       $attrs= $ldap->fetch();
538       if ($attrs['cn'][0] == $this->uid &&
539           !isset($this->attrs['memberUid'])){
541         $ldap->rmDir($ldap->getDN());
542       }
543     }
545     /* Optionally execute a command after we're done */
546     $this->handle_post_events("remove",array("uid" => $this->uid));
547   }
550   function save_object()
551   {
552     if (isset($_POST['posixTab'])){
553       /* Save values to object */
554       plugin::save_object();
555       $this->trustModeDialog->save_object();
557       /* Save force GID checkbox */
558       if($this->acl_is_writeable("gidNumber") || $this->acl_is_writeable("uidNumber")){
559         if (isset ($_POST['force_ids'])){
560           $data= 1;
561         } else {
562           $data= 0;
563         }
564         if ($this->force_ids != $data){
565           $this->is_modified= TRUE;
566         }
567         $this->force_ids= $data;
568       }
570       /*Save primary group settings */
571       if($this->acl_is_writeable("primaryGroup") && isset($_POST['primaryGroup'])){
572         $data= get_post('primaryGroup');
573         if ($this->primaryGroup != $data){
574           $this->is_modified= TRUE;
575         }
576         $this->primaryGroup= get_post('primaryGroup');
577       }
579       /* Get seelcted shadow checkboxes */
580       foreach(array("shadowMin","shadowMax","shadowExpire","shadowInactive","shadowWarning") as $var) {
581         if($this->acl_is_writeable($var)){
582           $activate_var = "activate_".$var;
583           if(isset($_POST['activate_'.$var])){
584             $this->$activate_var  = true;
585             $this->$var      = get_post($var);
586           }else{
587             $this->$activate_var  = false;
588             if ($var != "shadowExpire") {
589               $this->$var      = 0;
590             }
591           }
592         }
593       }
595       /* Force change password ? */
596       if(isset($_POST['mustchangepassword'])){
597         $this->mustchangepassword = TRUE;
598       }else{
599         $this->mustchangepassword = FALSE;
600       }
601     }
602   }
605   /* Save data to LDAP, depending on is_account we save or delete */
606   function save()
607   {
609     /* Adapt shadow values */
610     if (!$this->activate_shadowExpire){
611       $this->shadowExpire= "0";
612     } else {
613       /* Transform date to days since the beginning */
614       list($day, $month, $year)= explode('.', $this->shadowExpire, 3);
615       $this->shadowExpire= (int)(mktime(0, 0, 0, $month, $day, $year)/ (60 * 60 * 24)) ;
616     }
617     if (!$this->activate_shadowMax){
618       $this->shadowMax= "0";
619     }
620     if ($this->mustchangepassword){
621       $this->shadowLastChange= (int)(date("U") / 86400) - $this->shadowMax - 1;
622     } else {
623 #      $this->shadowLastChange= (int)(date("U") / 86400);
624     }
625     if (!$this->activate_shadowWarning){
626       $this->shadowWarning= "0";
627     }
629     /* Check what to do with ID's 
630        Nothing forced, so we may have to generate our own IDs, if not done already.
631      */
632     if ($this->force_ids == 0){
634       /* Handle uidNumber. 
635        * - use existing number if possible
636        * - if not, try to create a new uniqe one.
637        * */
638       if ($this->savedUidNumber != ""){
639         $this->uidNumber= $this->savedUidNumber;
640       } else {
642         /* Calculate new id's. We need to place a lock before calling get_next_id
643            to get real unique values. 
644          */
645         $wait= 10;
646         while (get_lock("uidnumber") != ""){
647           sleep (1);
649           /* Oups - timed out */
650           if ($wait-- == 0){
651             msg_dialog::display(_("Warning"), _("Timeout while waiting for lock. Ignoring lock!"), WARNING_DIALOG);
652             break;
653           }
654         }
655         add_lock ("uidnumber", "gosa");
656         $this->uidNumber= get_next_id("uidNumber", $this->dn);
657       }
658     }
661     /* Handle gidNumber 
662      * - If we do not have a primary group selected (automatic), we will check if there 
663      *    is already a group  with the same name and use this as primary.
664      * - .. if we couldn't find a group with the same name, we will create a new one, 
665      *    using the users uid as cn and a generated uniqe gidNumber. 
666      * */
667     if ($this->primaryGroup == 0 || $this->force_ids){
669       /* Search for existing group */
670       $ldap = $this->config->get_ldap_link();
671       $ldap->cd($this->config->current['BASE']);
673       /* Are we forced to use a special gidNumber? */ 
674       if($this->force_ids){
675         $ldap->search("(&(objectClass=posixGroup)(gidNumber=".$this->gidNumber."))", array("cn","gidNumber"));
676       }else{
677         $ldap->search("(&(objectClass=posixGroup)(gidNumber=*)(cn=".$this->uid."))", array("cn","gidNumber"));
678       }
680       /* No primary group found, create a new one */
681       if ($ldap->count() == 0){
683         $groupcn = $this->uid;
684         $pri_attr = $this->config->get_cfg_value("core","accountPrimaryAttribute");
685         $groupdn= preg_replace ('/^'.preg_quote($pri_attr,'/').'=[^,]+,'.preg_quote(get_people_ou(),'/').'/i',
686             'cn='.$groupcn.','.get_groups_ou(), $this->dn);
688         /* Request a new and uniqe gidNumber, if required */
689         if(!$this->force_ids){
690           $this->gidNumber= get_next_id("gidNumber", $this->dn);
691         }
693         /* If forced gidNumber could not be found, then check if the given group name already exists 
694            we do not want to modify the gidNumber of an existing group.
695          */
696         $cnt= 0; 
697         while($ldap->dn_exists($groupdn) && ($cnt < 100)){
698           $cnt ++;
699           $groupcn = $this->uid."_".$cnt;
700           $groupdn= preg_replace ('/^'.preg_quote($pri_attr,'/').'=[^,]+,'.preg_quote(get_people_ou(),'/').'/i',
701               'cn='.$groupcn.','.get_groups_ou(), $this->dn);
702         }
704         /* Create new primary group and enforce the new gidNumber */
705         $g= new group($this->config, $groupdn);
706         $g->cn= $groupcn;
707         $g->force_gid= 1;
708         $g->gidNumber= $this->gidNumber;
709         $g->description= _("Group of user")." ".$this->givenName." ".$this->sn;
710         $g->save ();
712         @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
713             sprintf("Primary group '%s' created, using gidNumber '%s'.",$groupcn,$this->gidNumber),"");
714       }else{
715         $attrs = $ldap->fetch();
716         $this->gidNumber = $attrs['gidNumber'][0];
717         @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
718             "Found and used: <i>".$attrs['dn']."</i>",
719             sprintf("Primary group '%s' exists, gidNumber is '%s'.",$this->uid,$this->gidNumber));
720       }
721     }else{
723       /* Primary group was selected by user
724        */
725       $this->gidNumber = $this->primaryGroup;
726       @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,
727           sprintf("Primary group '%s' for user '%s' manually selected.",$this->gidNumber,$this->uid),"");
728     }
730     if ($this->activate_shadowMin != "1" ) {
731       $this->shadowMin = "";
732     }
734     if (($this->activate_shadowMax != "1") && ($this->mustchangepassword != "1")) {
735       $this->shadowMax = "";
736     }
738     if ($this->activate_shadowWarning != "1" ) {
739       $this->shadowWarning = "";
740     }
742     if ($this->activate_shadowInactive != "1" ) {
743       $this->shadowInactive = "";
744     }
746     if ($this->activate_shadowExpire != "1" ) {
747       $this->shadowExpire = "";
748     }
750     /* Fill gecos */
751     if (isset($this->parent) && $this->parent !== NULL){
752       $this->gecos= rewrite($this->parent->by_object['user']->cn);
753       if (!preg_match('/^[a-z0-9 -]+$/i', $this->gecos)){
754         $this->gecos= "";
755       }
756     }
758     foreach(array("shadowMin","shadowMax","shadowWarning","shadowInactive","shadowExpire") as $attr){
759       $this->$attr = (int) $this->$attr;
760     }
761     /* Call parents save to prepare $this->attrs */
762     plugin::save();
764     /* include global link_info */
765     $this->cleanup();
767     /* This is just a test, we have had duplicated ids 
768        in the past when copy & paste was used. 
769        Normaly this should not happen.
770      */ 
771     if(isset($this->attrs['uidNumber']) && !$this->force_ids){
772       $used = $this->get_used_uid_numbers();
773       if(isset($used[$this->attrs['uidNumber']]) && $used[$this->attrs['uidNumber']] != $this->dn){
774         msg_dialog::display(_("Warning"),_("A duplicated UID number was written for this user. If this was not intended please verify all used uidNumbers!"), WARNING_DIALOG);
775       }
776     }
778     $ldap= $this->config->get_ldap_link();
779     $ldap->cd($this->dn);
780     unset($this->attrs['uid']);
781     $ldap->modify ($this->attrs); 
783     /* Log last action */ 
784     if($this->initially_was_account){
785       new log("modify","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
786     }else{
787       new log("create","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
788     }
790     if (!$ldap->success()){
791       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
792     }
794     /* Remove lock needed for unique id generation */
795     del_lock ("uidnumber");
797     // Save ssh stuff if needed
798     if ($this->ssh) {
799       $this->ssh->setDN($this->dn);
800       $this->ssh->save();
801     }
803     $this->trustModeDialog->dn = $this->dn;
804     $this->trustModeDialog->save();
806     /* Take care about groupMembership values: add to groups */
807     foreach ($this->groupMembership as $key => $value){
808       if (!isset($this->savedGroupMembership[$key])){
809         $g= new grouptabs($this->config,$this->config->data['TABS']['GROUPTABS'], $key,"groups");
810         $g->set_acl_base($key);
811         $g->by_object['group']->addUser($this->uid);
812         $g->save();
813       }
814     }
816     /* Remove groups not listed in groupMembership */
817     foreach ($this->savedGroupMembership as $key => $value){
818       if (!isset($this->groupMembership[$key])){
819         $g= new grouptabs($this->config,$this->config->data['TABS']['GROUPTABS'], $key,"groups");
820         $g->set_acl_base($key);
821         $g->by_object['group']->removeUser ($this->uid);
822         $g->save();
823       }
824     }
826     /* Optionally execute a command after we're done */
827     if ($this->initially_was_account == $this->is_account){
828       if ($this->is_modified){
829         $this->handle_post_events("modify",array("uid" => $this->uid));
830       }
831     } else {
832       $this->handle_post_events("add" ,array("uid"=> $this->uid));
833     }
834   }
837   /* Check formular input */
838   function check()
839   {
840     /* Include global link_info */
841     $ldap= $this->config->get_ldap_link();
843     /* Append groups as memberGroup: to check hook 
844      */
845     $tmp_attributes  = $this->attributes;    
846     $this->attributes[] = "memberGroup";
847     $this->memberGroup = array();
848     foreach($this->groupMembership as $dn => $name){
849       $this->memberGroup[] = $name;
850     }
852     /* Call common method to give check the hook */
853     $message= plugin::check();
854     $this->attributes = $tmp_attributes;
856     /* must: homeDirectory */
857     if ($this->homeDirectory == ""){
858       $message[]= msgPool::required(_("Home directory"));
859     }
860     if (!tests::is_path($this->homeDirectory)){
861       $message[]= msgPool::invalid(_("Home directory"), "", "", "/home/yourname" );
862     }
864     /* Check ID's if they are forced by user */
865     if ($this->force_ids == "1"){
867       /* Valid uid/gid? */
868       if (!tests::is_id($this->uidNumber)){
869         $message[]= msgPool::invalid(_("UID"), $this->uidNumber, "/[0-9]/");
870       } else {
871         if ($this->uidNumber < $this->config->get_cfg_value("core","minId")){
872           $message[]= msgPool::toosmall(_("UID"), $this->config->get_cfg_value("core","minId"));
873         }
874       }
875       if (!tests::is_id($this->gidNumber)){
876         $message[]= msgPool::invalid(_("GID"), $this->gidNumber, "/[0-9]/");
877       } else {
878         if ($this->gidNumber < $this->config->get_cfg_value("core","minId")){
879           $message[]= msgPool::toosmall(_("GID"), $this->config->get_cfg_value("core","minId"));
880         }
881       }
882     }
884     /* Check dates */
885     if ($this->activate_shadowExpire && ($this->shadowExpire == "" || !tests::is_date($this->shadowExpire))){
886       $message[]= msgPool::invalid("shadowExpire", $this->shadowExpire);
887     }
889     /* Check shadow settings, well I like spaghetties... */
890     if ($this->activate_shadowMin){
891       if (!tests::is_id($this->shadowMin)){
892         $message[]= msgPool::invalid(_("shadowMin"), $this->shadowMin, "/[0-9]/");
893       }
894     }
895     if ($this->activate_shadowMax){
896       if (!tests::is_id($this->shadowMax)){
897         $message[]= msgPool::invalid(_("shadowMax"), $this->shadowMax, "/[0-9]/");
898       }
899     }
900     if ($this->activate_shadowWarning){
901       if (!tests::is_id($this->shadowWarning)){
902         $message[]= msgPool::invalid(_("shadowWarning"), $this->shadowWarning, "/[0-9]/");
903       }
904       if (!$this->activate_shadowMax){
905         $message[]= msgPool::depends("shadowWarning", "shadowMax");
906       }
907       if ($this->shadowWarning > $this->shadowMax){
908         $message[]= msgPool::toobig("shadowWarning", "shadowMax");
909       }
910       if ($this->activate_shadowMin && $this->shadowWarning < $this->shadowMin){
911         $message[]= msgPool::toosmall("shadowWarning", "shadowMin");
912       }
913     }
914     if ($this->activate_shadowInactive){
915       if (!tests::is_id($this->shadowInactive)){
916         $message[]= msgPool::invalid(_("shadowInactive"), $this->shadowInactive, "/[0-9]/");
917       }
918       if (!$this->activate_shadowMax){
919         $message[]= msgPool::depends("shadowInactive", "shadowMax");
920       }
921     }
922     if ($this->activate_shadowMin && $this->activate_shadowMax){
923       if ($this->shadowMin > $this->shadowMax){
924         $message[]= msgPool::toobig("shadowMin", "shadowMax");
925       }
926     }
928     return ($message);
929   }
932   function multiple_check()
933   {
934     $message = plugin::multiple_check();
935     if ($this->homeDirectory == "" && in_array("homeDirectory",$this->multi_boxes)){
936       $message[]= msgPool::required(_("Home directory"));
937     }
938     if (!tests::is_path($this->homeDirectory) && in_array("homeDirectory",$this->multi_boxes)){
939       $message[]= msgPool::invalid(_("Home directory"), "", "", "/home/yourname" );
940     }
942     /* Check shadow settings, well I like spaghetties... */
943     if ($this->activate_shadowMin && in_array("activate_shadowMin",$this->multi_boxes)){
944       if (!tests::is_id($this->shadowMin)){
945         $message[]= msgPool::invalid(_("shadowMin"), $this->shadowMin, "/[0-9]/");
946       }
947     }
948     if ($this->activate_shadowMax && in_array("activate_shadowMax",$this->multi_boxes)){
949       if (!tests::is_id($this->shadowMax)){
950         $message[]= msgPool::invalid(_("shadowMax"), $this->shadowMax, "/[0-9]/");
951       }
952     }
953     if ($this->activate_shadowWarning && in_array("activate_shadowWarning",$this->multi_boxes)){
954       if (!tests::is_id($this->shadowWarning)){
955         $message[]= msgPool::invalid(_("shadowWarning"), $this->shadowWarning, "/[0-9]/");
956       }
957       if (!$this->activate_shadowMax && in_array("activate_shadowMax",$this->multi_boxes)){
958         $message[]= msgPool::depends("shadowWarning", "shadowMax");
959       }
960       if ($this->shadowWarning > $this->shadowMax && in_array("activate_shadowWarning",$this->multi_boxes)){
961         $message[]= msgPool::toobig("shadowWarning", "shadowMax");
962       }
963       if ($this->activate_shadowMin && $this->shadowWarning < $this->shadowMin && in_array("activate_shadowMin",$this->multi_boxes)){
964         $message[]= msgPool::tosmall("shadowWarning", "shadowMin");
965       }
966     }
967     if ($this->activate_shadowInactive && in_array("activate_shadowInactive",$this->multi_boxes)){
968       if (!tests::is_id($this->shadowInactive)){
969         $message[]= msgPool::invalid(_("shadowInactive"), $this->shadowInactive, "/[0-9]/");
970       }
971       if (!$this->activate_shadowMax && in_array("activate_shadowMax",$this->multi_boxes)){
972         $message[]= msgPool::depends("shadowInactive", "shadowMax");
973       }
974     }
975     if ($this->activate_shadowMin && $this->activate_shadowMax && in_array("activate_shadowMin",$this->multi_boxes)){
976       if ($this->shadowMin > $this->shadowMax){
977         $message[]= msgPool::toobig("shadowMin", "shadowMax");
978       }
979     }
981     return($message);
982   }
985   function addGroup ($groups)
986   {
987     /* include global link_info */
988     $ldap= $this->config->get_ldap_link();
990     /* Walk through groups and add the descriptive entry if not exists */
991     foreach ($groups as $value){
993       if (!array_key_exists($value, $this->groupMembership)){
994         $ldap->cat($value, array('cn', 'description', 'dn'));
995         $attrs= $ldap->fetch();
996         error_reporting (0);
997         if (!isset($attrs['description'][0])){
998           $entry= $attrs["cn"][0];
999         } else {
1000           $dsc= preg_replace ('/^Group of user/', _("Group of user"), $attrs["description"][0]);
1001           $entry= $attrs["cn"][0]." [$dsc]";
1002         }
1003         error_reporting (E_ALL | E_STRICT);
1005         if(obj_is_writable($attrs['dn'],"groups/group","memberUid")){
1006           $this->groupMembership[$attrs['dn']]= $entry;
1007           if($this->multiple_support_active && isset($this->groupMembership_some[$attrs['dn']])){
1008             unset($this->groupMembership_some[$attrs['dn']]);
1009           }
1010         }
1011       }
1012     }
1014     /* Sort groups */
1015     asort ($this->groupMembership);
1016     reset ($this->groupMembership);
1017   }
1020   /* Del posix user from some groups */
1021   function delGroup ($groups)
1022   {
1023     $dest= array();
1024     foreach($groups as $dn_to_del){
1025       if(isset($this->groupMembership[$dn_to_del]) && obj_is_writable($dn_to_del,"groups/group","memberUid")){
1026         unset($this->groupMembership[$dn_to_del]);
1027       }
1028       if($this->multiple_support_active){
1029         if(isset($this->groupMembership_some[$dn_to_del]) && obj_is_writable($dn_to_del,"groups/group","memberUid")){
1030           unset($this->groupMembership_some[$dn_to_del]);
1031         }
1032       }
1033     }
1034   }
1037   /* Adapt from template, using 'dn' */
1038   function adapt_from_template($dn, $skip= array())
1039   {
1040     /* Include global link_info */
1041     $ldap= $this->config->get_ldap_link();
1043     plugin::adapt_from_template($dn, $skip);
1044     $template= $this->attrs['uid'][0];
1046     /* Adapt group membership */
1047     $ldap->cd($this->config->current['BASE']);
1048     $ldap->search("(&(objectClass=posixGroup)(memberUid=".$this->attrs["uid"][0]."))", array("description", "cn"));
1050     while ($this->attrs= $ldap->fetch()){
1051       if (!isset($this->attrs["description"][0])){
1052         $entry= $this->attrs["cn"][0];
1053       } else {
1054         $entry= $this->attrs["cn"][0]." [".$this->attrs["description"][0]."]";
1055       }
1056       $this->groupMembership[$ldap->getDN()]= $entry;
1057     }
1059     /* Fix primary group settings */
1060     $ldap->cd($this->config->current['BASE']);
1061     $ldap->search("(&(objectClass=posixGroup)(cn=$template)(gidNumber=".$this->gidNumber."))", array("cn"));
1062     if ($ldap->count() != 1){
1063       $this->primaryGroup= $this->gidNumber;
1064     }
1066     $ldap->cd($this->config->current['BASE']);
1067     $ldap->search("(&(objectClass=gosaUserTemplate)(uid=".$template.")(accessTo=*))", array("cn","accessTo"));
1068     while($attr = $ldap->fetch()){
1069       $tmp = $attr['accessTo'];
1070       unset ($tmp['count']);
1071       $this->accessTo = $tmp;   
1072     }
1074     /* Adjust shadow checkboxes */
1075     foreach (array("shadowMin", "shadowMax", "shadowWarning", "shadowInactive") as $val){
1076       if ($this->$val != 0){
1077         $oval= "activate_".$val;
1078         $this->$oval= "1";
1079       }
1080     }
1082     /* Only enable checkbox, if shadowExpire is in the future */
1083     if($this->shadowExpire > time()) {
1084       $this->activate_shadowExpire= "1";
1085     }
1087     /* Convert shadowExpire for usage */
1088     if ($this->shadowExpire == 0){
1089       $this->shadowExpire= "";
1090     } else {
1091       $this->shadowExpire= date('d.m.Y', $this->shadowExpire * 60 * 60 * 24);
1092     }
1093   }
1095   function convertToSeconds($val)
1096   {
1097     if ($val != 0){
1098       $val*= 60 * 60 * 24;
1099     } else {
1100       $date= getdate();
1101       $val= floor($date[0] / (60*60*24)) * 60 * 60 * 24;
1102     }
1103     return($val);
1104   }
1107   function get_used_uid_numbers()
1108   {
1109     $ids= array();
1110     $ldap= $this->config->get_ldap_link();
1112     $ldap->cd ($this->config->current['BASE']);
1113     $ldap->search ("(&(objectClass=posixAccount)(uidNumber=*))", array("uidNumber"));
1115     /* Get list of ids */
1116     while ($attrs= $ldap->fetch()){
1117       $ids[$attrs['uidNumber'][0]] = $attrs['dn'];
1118     }
1119     return($ids);
1120   }
1123   /* Get posts from copy & paste dialog */ 
1124   function saveCopyDialog()
1125   {
1126     if(isset($_POST['homeDirectory'])){
1127       $this->homeDirectory = get_post('homeDirectory');
1128       if (isset ($_POST['force_ids'])){
1129         $data= 1;
1130         $this->gidNumber = get_post('gidNumber');
1131         $this->uidNumber = get_post('uidNumber');
1132       } else {
1133         $data= 0;
1134       }
1135       if ($this->force_ids != $data){
1136         $this->is_modified= TRUE;
1137       }
1138       $this->force_ids= $data;
1139       $data= get_post('primaryGroup');
1140       if ($this->primaryGroup != $data){
1141         $this->is_modified= TRUE;
1142       }
1143       $this->primaryGroup= get_post('primaryGroup');
1144     }
1145   }
1148   /* Create the posix dialog part for copy & paste */
1149   function getCopyDialog()
1150   {
1151     /* Skip dialog creation if this is not a valid account*/
1152     if(!$this->is_account) return("");
1153     if ($this->force_ids == 1){
1154       $force_ids = "checked";
1155       if (session::get('js')){
1156         $forceMode = "";
1157       }
1158     } else {
1159       if (session::get('js')){
1160         if($this->acl != "#none#")
1161           $forceMode ="disabled";
1162       }
1163       $force_ids = "";
1164     }
1166     $sta = "";
1168     /* Open group add dialog */
1169     if(isset($_POST['edit_groupmembership'])){
1170       $this->groupSelect = new groupSelect($this->config,get_userinfo());
1171       $sta = "SubDialog";
1172     }
1174     /* If the group-add dialog is closed, call execute 
1175        to ensure that the membership is updatd */
1176     if(isset($_POST['add_groups_finish']) || isset($_POST['add_groups_cancel'])){
1177       $this->execute();
1178       $this->groupSelect =NULL;
1179     }
1181     if($this->groupSelect){
1182       $str = $this->execute(true);
1183       $ret = array();
1184       $ret['string'] = $str;
1185       $ret['status'] = $sta;
1186       return($ret);
1187     }
1189     /* If a group member should be deleted, simply call execute */
1190     if(isset($_POST['delete_groupmembership'])){
1191       $this->execute();
1192     }
1194     /* Assigned informations to smarty */
1195     $smarty = get_smarty();
1196     $smarty->assign("homeDirectory",set_post($this->homeDirectory));
1197     $smarty->assign("secondaryGroups",$this->secondaryGroups);
1198     $smarty->assign("primaryGroup",set_post($this->primaryGroup));
1200     $smarty->assign("uidNumber",set_post($this->uidNumber));
1201     $smarty->assign("gidNumber",set_post($this->gidNumber));
1202     $smarty->assign("forceMode",set_post($forceMode));
1203     $smarty->assign("force_ids",set_post($force_ids));
1204     if (!count($this->groupMembership)){
1205       $smarty->assign("groupMembership", array("&nbsp;"));
1206     } else {
1207       $smarty->assign("groupMembership", set_post($this->groupMembership));
1208     }
1210     /* Display wars message if there are more than 16 group members */
1211     if (count($this->groupMembership) > 16){
1212       $smarty->assign("groups", "too_many_for_nfs");
1213     } else {
1214       $smarty->assign("groups", "");
1215     }
1216     $str = $smarty->fetch(get_template_path("paste_generic.tpl",TRUE,dirname(__FILE__)));
1218     $ret = array();
1219     $ret['string'] = $str;
1220     $ret['status'] = $sta;
1221     return($ret);
1222   }
1225   function PrepareForCopyPaste($source)
1226   {
1227     plugin::PrepareForCopyPaste($source);
1229     $this->trustModeDialog->PrepareForCopyPaste($source);
1231     /* Avoid using the same gid/uid number as source user 
1232        empty numbers to enforce new ones. */
1233     $this->savedUidNumber = "";
1234     $this->savedGidNumber = "";
1236     /* Get group membership */
1237     $ldap = $this->config->get_ldap_link();
1238     $ldap->cd($this->config->current['BASE']);
1239     $ldap->search("(&(objectClass=posixGroup)(memberUid=".$source['uid'][0]."))", array("cn", "description"));
1241     while ($attrs= $ldap->fetch()){
1242       if (!isset($attrs["description"][0])){
1243         $entry= $attrs["cn"][0];
1244       } else {
1245         $entry= $attrs["cn"][0]." [".$attrs["description"][0]."]";
1246       }
1247       $this->groupMembership[$ldap->getDN()]= $entry;
1248     }
1249     asort($this->groupMembership);
1250     reset($this->groupMembership);
1252     /* Fill group */
1253     if(isset($source['gidNumber'][0])){
1254       $this->primaryGroup= $source['gidNumber'][0];
1255     }
1258     /* Adjust shadow checkboxes */
1259     foreach (array("shadowMin", "shadowMax", "shadowWarning", "shadowInactive",
1260                 "shadowExpire") as $val){
1262         if ($this->$val != 0){
1263             $oval= "activate_".$val;
1264             $this->$oval= "1";
1265         }
1266     }
1268     /* Convert shadowExpire for usage */
1269     if ($this->shadowExpire == 0){
1270       $this->shadowExpire= "";
1271     } else {
1272       $this->shadowExpire= date('d.m.Y', $this->shadowExpire * 60 * 60 * 24);
1273     }
1275     $tmp = new trustModeDialog($this->config, $source['dn']);
1276     $this->trustModeDialog = new trustModeDialog($this->config, $this->dn);
1277     $this->trustModeDialog->trustModel = $tmp->trustModel;
1278     $this->trustModeDialog->accessTo = $tmp->accessTo;
1279     $this->trustModeDialog->setAcl('users/posixAccount');
1281   }
1284   function multiple_execute()
1285   {
1286     return($this->execute());
1287   }
1290   static function plInfo()
1291   {
1292     return (array(
1293           "plDescription"     => _("POSIX account"),
1294           "plSelfModify"      => TRUE,
1295           "plDepends"         => array("user"),
1296           "plPriority"        => 2,
1297           "plSection"         => array("personal" => _("My account")),
1298           "plCategory"        => array("users"),
1299           "plOptions"         => array(),
1300           "plRequirements"=> array(
1301               'ldapSchema' => array('posixAccount' => ''),
1302               'onFailureDisablePlugin' => array(get_class(), 'sambaAccount','netatalk','environment')
1303               ),
1305           "plProvidedAcls"  => array(
1307             "homeDirectory"       =>  _("Home directory"), 
1308             "primaryGroup"        =>  _("Primary group"), 
1309             "loginShell"          =>  _("Shell"),
1310             "uidNumber"           =>  _("User ID"),
1311             "gidNumber"           =>  _("Group ID"),
1313             "shadowLastChange"    =>  _("Shadow last changed"),
1314             "gotoLastSystemLogin"    =>  _("Last login"),
1316             "mustchangepassword"=>  _("Force password change on login"),
1317             "shadowMin"           =>  _("Shadow min"),
1318             "shadowMax"           =>  _("Shadow max"),
1319             "shadowWarning"       =>  _("Shadow warning"),
1320             "shadowInactive"      =>  _("Shadow inactive"),
1321             "shadowExpire"        =>  _("Shadow expire"),
1322             "sshPublicKey"        =>  _("Public SSH key"),
1323             "accessTo"            =>  _("System trust model")))
1324               );
1325   }
1328   /* Return selected values for multiple edit */
1329   function get_multi_edit_values()
1330   {
1331     $ret = plugin::get_multi_edit_values();
1332     $ret = array_merge($ret,$this->trustModeDialog->get_multi_edit_values());
1333     $ret['groupMembership']     = $this->groupMembership;
1334     $ret['groupMembership_some']= $this->groupMembership_some;
1336     if(in_array("primaryGroup",$this->multi_boxes)){
1337       $ret['primaryGroup'] = $this->primaryGroup;
1338     }
1339     foreach(array("shadowWarning","shadowInactive","shadowMin","shadowMax", "shadowExpire") as $entry){
1340       $active = "activate_".$entry;
1341       if(in_array($active,$this->multi_boxes)){
1342         $ret[$entry] = $this->$entry;
1343         $ret[$active] = $this->$active;
1344       }
1345     }
1346     if(in_array("mustchangepassword",$this->multi_boxes)){
1347       $ret['mustchangepassword'] = $this->mustchangepassword;
1348     }
1349     return($ret);
1350   }
1353   /* Save posts for multiple edit 
1354    */
1355   function multiple_save_object()
1356   {
1357     if(isset($_POST['posix_mulitple_edit'])){
1359       /* Backup expire value */ 
1360       $expire_tmp = $this->shadowExpire;
1362       /* Update all values */
1363       plugin::multiple_save_object();
1365       $this->trustModeDialog->multiple_save_object();
1367       /* Get selected checkboxes */
1368       foreach(array("primaryGroup","mustchangepassword","activate_shadowWarning","activate_shadowInactive","activate_shadowMin", "activate_shadowMax","activate_shadowExpire") as $val){
1369         if(isset($_POST["use_".$val])){
1370           $this->multi_boxes[] = $val;
1371         }
1372       }
1374       /* Update special values, checkboxes for posixShadow */
1375       foreach(array("shadowMin","shadowMax","shadowExpire","shadowInactive","shadowWarning") as $var) {
1376         if($this->acl_is_writeable($var)){
1377           $activate_var = "activate_".$var;
1378           if(in_array($activate_var, $this->multi_boxes)){
1379             if(isset($_POST['activate_'.$var])){
1380               $this->$activate_var  = true;
1381               $this->$var      = get_post($var);
1382             }else{
1383               $this->$activate_var  = false;
1384               $this->$var      = 0;
1385             }
1386           }
1387         }
1388       }
1390       /* Restore shadow value, if the shadow attribute isn't used */
1391       if(!in_array("activate_shadowExpire",$this->multi_boxes)){
1392         $this->shadowExpire = $expire_tmp;
1393       }
1395       /* Force change password ? */
1396       if(isset($_POST['mustchangepassword'])){
1397         $this->mustchangepassword = TRUE;
1398       }else{
1399         $this->mustchangepassword = FALSE;
1400       }
1402       /* Save primary group settings */
1403       if($this->acl_is_writeable("primaryGroup") && isset($_POST['primaryGroup'])){
1404         $data= get_post('primaryGroup');
1405         if ($this->primaryGroup != $data){
1406           $this->is_modified= TRUE;
1407         }
1408         $this->primaryGroup= get_post('primaryGroup');
1409       }
1410     }
1411   }
1414   /* Initialize plugin with given atribute arrays 
1415    */
1416   function init_multiple_support($attrs,$all)
1417   {
1418     plugin::init_multiple_support($attrs,$all);
1419     $this->trustModeDialog->init_multiple_support($attrs,$all);
1421     /* Some dummy values */
1422     $groups_some = array();
1423     $groups_all  = array();
1424     $groups_uid  = array();
1425     $uids        = array();
1426     $first       = TRUE;
1428     /* Get all groups used by currently edited users */
1429     $uid_filter="";  
1430     for($i =0; $i < $this->multi_attrs_all['uid']['count'] ; $i ++){
1431       $uid = $this->multi_attrs_all['uid'][$i];
1432       $uids[] = $uid;
1433       $uid_filter.= "(memberUid=".$uid.")"; 
1434     }
1435     $uid_filter = "(&(objectClass=posixGroup)(|".$uid_filter."))";
1436     $ldap = $this->config->get_ldap_link();
1437     $ldap->cd($this->config->current['BASE']);
1438     $ldap->search($uid_filter,array("dn","cn","memberUid"));
1439     while($group = $ldap->fetch()){
1440       $groups_some[$group['dn']] = $group['cn'][0];
1441       for($i = 0 ; $i < $group['memberUid']['count'] ; $i++){
1442         $groups_uid[$group['dn']][] = $group['memberUid'][$i];
1443       }
1444     }
1446     /* Create an array, containing all used groups */
1447     $groups_all = $groups_some;
1448     foreach($groups_all as $id => $group){
1449       foreach($uids as $uid){
1450         if(!in_array($uid,$groups_uid[$id])){
1451           unset($groups_all[$id]);
1452           break;
1453         }
1454       }
1455     }
1457     /* Assign group array */
1458     $this->groupMembership = $groups_all;
1460     /* Create an array of all grouops used by all users */
1461     foreach( $groups_all as $dn => $cn){
1462       if(isset($groups_some[$dn])){
1463         unset($groups_some[$dn]);
1464       }
1465     }
1466     $this->groupMembership_some = $groups_some;
1467     $this->primaryGroup = $this->gidNumber;
1469     /* Adjust shadow checkboxes */
1470     foreach (array("shadowMin", "shadowMax", "shadowWarning", "shadowInactive",
1471           "shadowExpire") as $val){
1472       if ($this->$val != 0){
1473         $oval= "activate_".$val;
1474         $this->$oval= "1";
1475       }
1476     }
1478     /* Convert to seconds */
1479     if(isset($this->multi_attrs['shadowExpire'])){
1480       $this->shadowExpire = $this->convertToSeconds($this->multi_attrs['shadowExpire'][0]);
1481     }else{
1482       $this->activate_shadowExpire = FALSE;
1483     }
1484   }
1487   function set_multi_edit_values($attrs)
1488   {
1489     $groups = array();
1491     /* Update groupMembership, keep optinal group */
1492     foreach($attrs['groupMembership_some'] as $dn => $cn){
1493       if(isset($this->groupMembership[$dn])){
1494         $groups[$dn] = $cn;
1495       }
1496     }
1497     /* Update groupMembership, add forced groups */
1498     foreach($attrs['groupMembership'] as $dn => $cn){
1499       $groups[$dn] = $cn;
1500     }
1501     plugin::set_multi_edit_values($attrs);
1502     $this->trustModeDialog->set_multi_edit_values($attrs);
1503     $this->groupMembership = $groups;
1504   }
1506   function set_acl_base($base)
1507   {
1508     @DEBUG (DEBUG_ACL, __LINE__, __FUNCTION__, __FILE__,"<b>".$base."</b>","<b>ACL-Base:</b> ");
1509     $this->acl_base= $base;
1510     $this->trustModeDialog->set_acl_base($base);
1511   }
1513   /*! \brief  Enables multiple support for this plugin
1514    */
1515   function enable_multiple_support()
1516   {
1517     plugin::enable_multiple_support();
1518     $this->trustModeDialog->enable_multiple_support();
1519   }
1523 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1524 ?>