Code

Sorry for the huge commit:
[gosa.git] / plugins / admin / users / class_userManagement.inc
1 <?php
2 /*
3    This code is part of GOsa (https://gosa.gonicus.de)
4    Copyright (C) 2003-2006 - Cajus Pollmeier <pollmeier@gonicus.de>
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
21 /* Include user tab class */
22 require "tabs_user.inc";
25 class userManagement extends plugin
26 {
27   /* Plugin definitions */
28   var $plHeadline= "Users";
29   var $plDescription= "This does something";
31   /* Dialog attributes */
32   var $usertab= NULL;
33   var $ui= NULL;
34   var $acl= "";
35   var $templates= array();
36   var $got_uid= false;
37   var $departments= array();
38   var $CopyPasteHandler= NULL;
41   function userManagement($config, $ui)
42   {
43   
44     /* Save configuration for internal use */
45     $this->config= $config;
46     $this->ui= $ui;
48     /* Copy & Paste handler */
49     if ($this->config->boolValueIsTrue("main", "enableCopyPaste")){
50       $this->CopyPasteHandler= new CopyPasteHandler($this->config);
51     }
53     /* Get global filter config */
54     if (!isset($_SESSION["userfilter"])){
55       $base= get_base_from_people($ui->dn);
56       $userfilter= array( "mailusers"       => "checked",
57                           "unixusers"       => "checked",
58                           "templates"       => "",
59                           "subsearch"       => "",
60                           "proxyusers"      => "checked",
61                           "sambausers"      => "checked",
62                           "faxusers"        => "checked",
63                           "functionalusers" => "checked",
64                           "regex"           => "*");
65       $_SESSION["userfilter"]= $userfilter;
66     }
67     
68     /* Transfer global base to dialogs people base */
69     if(!isset($_SESSION['CurrentMainBase'])){
70       $base= get_base_from_people($ui->dn);
71       $_SESSION['CurrentMainBase']= $base;
72     }
74     /* LOCK MESSAGE Vars */
75     $_SESSION['LOCK_VARS_TO_USE'] = array("/^act$/","/^id$/","/^user_edit_/","/^user_del_/");
76   }
79   function execute()
80   {
81     //FIXME: This function lacks structure! It's dammn spaghetti code.
82   
83     /* Call parent execute */
84     plugin::execute();
86     $smarty= get_smarty();                  // Smarty instance
87     $userfilter= get_global("userfilter");  // contains Filter Settings
88     $s_action= "";                          // Contains the action to be taken
89     $s_entry= "";                           // The value for s_action
90     $base_back= "";                         // The Link for Backbutton
92     /* Department folder change requested? */
93     if( isset($_GET['act']) && $_GET['act'] == "dep_open" ){
94       $s_action= "open";
95       $s_entry= base64_decode($_GET['dep_id']);
97       /* Set current main base to the requested department DN */
98       $_SESSION['CurrentMainBase']= $this->config->departments[trim($s_entry)];
99     }
101     /* Edit entry button pressed? */
102     if( isset($_GET['act']) && $_GET['act'] == "edit_entry" ){
103       $s_action= "edit";
104       $s_entry= validate($_GET['id']);
105     }
107     /* Test relevant POST values */  
108     foreach($_POST as $key => $val){
110       /* Get every possible POST combination and set s_action/s_entry accordingly */
111       foreach(array("del"       => "user_del",    "edit"      => "user_edit",
112                     "back"      => "dep_back",    "new"       => "user_new",
113                     "home"      => "dep_home",    "new_tpl"   => "user_tplnew",
114                     "change_pw" => "user_chgpw",  "root"      => "dep_root",
115                     "editpaste" => "editpaste",   "copy"      => "copy",
116                     "cut"       => "cut") as $act => $name){
118         if (preg_match("/".$name.".*/", $key)){
119           $s_action= $act;
120           $s_entry= preg_replace("/".$name."_/i", "", $key);
121           break;
122         }
123       }
124       
125     } /* ...Test POST */
127     //FIXME: Remove trailing _what_? There seems to be something encoded in
128     //       the string right now, but it would be helpful to have informations
129     //       about it. I'd like to see quick code reading by other developers.
130     $s_entry= preg_replace("/_.$/", "", $s_entry);
132     /* Seperate possibly encoded tab and entry, default to tab "user" */
133     if(preg_match("/.*-.*/", $s_entry)){
134       $s_tab= preg_replace("/^[^-]*-/i", "" ,$s_entry);
135       $s_entry= preg_replace("/-[^-]*$/i", "", $s_entry);
136     }else{
137       $s_tab= "user";
138     }
140     /* Department has changed? */
141     if(isset($_POST['CurrentMainBase'])){
142       $_SESSION['CurrentMainBase']= validate($_POST['CurrentMainBase']);
143     }
145     /* Home-button is pressed, move to users home DN */
146     if($s_action == "home"){
147       $_SESSION['CurrentMainBase']= preg_replace('/^[^,]+,'.normalizePreg(get_people_ou()).'/', "", $this->ui->dn);
148     }
150     /* Root-button is pressed, move to root DN */
151     if($s_action == "root"){
152       $_SESSION['CurrentMainBase']= $this->config->current['BASE'];
153     }
155     /* If Back-button is pressed, move back one step in DN */
156     if($s_action == "back"){
157       //FIXME: This is not 100% correct. We'll only display ou's, but there may be
158       //       a step between. You'll stumble in a "hidden" department in this case.
159       $base_back= preg_replace("/^[^,]+,/", "", $_SESSION['CurrentMainBase']);
161       /* The department array keeps non DN entries as index. We need to convert
162          it before checking the existance. */
163       $base_back= trim(convert_department_dn($base_back));
165       /* Check if the department exists, otherwise revert to the configure base DN */
166       if(isset($this->config->departments[$base_back])){
167         $_SESSION['CurrentMainBase']= $this->config->departments[$base_back];
168       }else{
169         $_SESSION['CurrentMainBase']= $this->config->departments['/'];
170       }
171     }
173 # |||| ----------------------- copy and paste - move it into a seperate function
174 //FIXME: I've mostly skipped reviewing this. Just a few comments have been
175 //       added. Fact is, that we've an execute() function with more than 800
176 //       lines. I personally tend to make this shorter. Even the complete new
177 //       list management is a huge copy'n paste factor which can be sourced out
178 //       to another function.
180     /* Only perform copy/paste if it is enabled */
181     if($this->CopyPasteHandler){
183       /* Paste copied/cutted object in here */
184       //FIXME: Sure? Does this comment describe what happens below?
185       if( $s_action == "editPaste" || $this->CopyPasteHandler->stillOpen()){
186         $this->CopyPasteHandler->save_object();
187         $this->CopyPasteHandler->SetVar("base", $_SESSION['CurrentMainBase']);
189         /* Execute copy and paste without showing message on success. */
190         //FIXME: It is not clear what really happens, or why we're stopping
191         //       to process data here. See the FIXME in class_CopyAndPasteHandler.
192         //       Normally we don't have something in $ret, because we've fired
193         //       up with (false) <=> which seems to mean "no messages".
194         if( ($ret= $this->CopyPasteHandler->execute(false))){
195           return ($ret);
196         }
198         /* Reload to have freshly copied entries in the list */
199         $this->reload();
200         
201         /* Use the last dn to search for it's ID in the newly generated list. */
202         $dn= $this->CopyPasteHandler->lastdn;
203         foreach($this->list as $id => $entry){
204           if($entry['dn'] == $dn){
205             $s_entry= $id;
206             break;
207           }
208         }
209        
210         /* Change action to "change_pw" if user has requested to do so. */
211         if($_POST['passwordTodo'] == "new"){
212           $s_action= "change_pw";
213         }
214       }
216       /* Copy current object to CopyHandler */
217       if($s_action == "copy"){
218         $this->CopyPasteHandler->Clear();
220         $dn= $this->list[trim($s_entry)]['dn'];
221         $acl= get_permissions ($dn, $this->ui->subtreeACL);
223         $obj= new usertabs($this->config, $this->config->data['TABS']['USERTABS'], $dn);
224         $objNew= new usertabs($this->config, $this->config->data['TABS']['USERTABS'], "new");
226         $obj->set_acl($acl);
227         $objNew->set_acl($acl);
229         foreach($obj->by_object as $name => $tab){
230           foreach(array("photoData","jpegPhoto","is_account") as $attr){
231             if(isset($obj->by_object[$name]->$attr)){
232               $objNew->by_object[$name]->$attr = $obj->by_object[$name]->$attr;
233             }
234           } 
235         }
236         $this->CopyPasteHandler->Copy($obj,$objNew);
237       }
239       /* Copy current object to CopyHandler */
240       //FIXME: Again? This is cut. Hopefully it works without touching the special
241       //       attributes from above.
242       if($s_action == "cut"){
243         $this->CopyPasteHandler->Clear();
244         $dn= $this->list[trim($s_entry)]['dn'];
245         $acl= get_permissions ($dn, $this->ui->subtreeACL);
247         $obj= new usertabs($this->config, $this->config->data['TABS']['USERTABS'], $dn);
248         $obj->set_acl($acl);
250         $this->CopyPasteHandler->Cut($obj);
251       }
252     }
253 # ^^^^^ ----------------------- copy and paste - move it into a seperate function
255     /* Save filter data if we are in the headpage */
256     if(!isset($this->usertab)){
257       $values= array("functionalusers", "unixusers", "mailusers", "sambausers",
258                      "proxyusers", "faxusers", "templates", "subsearch");
259       $userfilter= saveFilter($userfilter, $values);
260       register_global("userfilter", $userfilter);
261     }
263     /* React on user interaction here */
264     if (($_SERVER["REQUEST_METHOD"] == "POST")||($_SERVER["REQUEST_METHOD"]== "GET")){
266       /* User wants to edit data? */
267       if (($s_action=="edit") && (!isset($this->usertab->config))){
269         /* Get 'dn' from posted 'uid', must be unique */
270         $this->dn= $this->list[trim($s_entry)]['dn'];
272         /* Check locking, save current plugin in 'back_plugin', so
273            the dialog knows where to return. */
274         if (($user= get_lock($this->dn)) != ""){
275           return(gen_locked_message ($user, $this->dn));
276         }
278         /* Lock the current entry, so everyone will get the
279            above dialog */
280         add_lock ($this->dn, $this->ui->dn);
282         /* Set up the users ACL's for this 'dn' */
283         $acl= get_permissions ($this->dn, $this->ui->subtreeACL);
285         /* Register usertab to trigger edit dialog */
286         $this->usertab= new usertabs($this->config, 
287                                      $this->config->data['TABS']['USERTABS'], $this->dn);
289         /* Switch tab, in case that was requested by the user */
290         $this->usertab->current = $s_tab;
291         
292         /* Set ACL and move DN to the headline */
293         $this->usertab->set_acl($acl);
294         $_SESSION['objectinfo']= $this->dn;
295       }
296     }
298     /* Reset all relevant data, if we get a _cancel request */
299     if (isset($_POST['edit_cancel']) || isset($_POST['password_cancel'])){
300       if (isset($this->usertab)){
301         del_lock ($this->usertab->dn);
302         unset ($this->usertab);
303       }
304       $this->usertab= NULL;
305       $this->lognames= array();;
306       $this->sn= "";
307       $this->givenName= "";
308       $this->uid= "";
309       unset ($_SESSION['objectinfo']);
310     }
312     /* Password change requested */
313     if ($s_action == "change_pw"){
315       /* Get 'dn' from posted 'uid' */
316       $this->dn= $this->list[trim($s_entry)]['dn'];
318       /* Load permissions for selected 'dn' and check if
319          we're allowed to remove this 'dn' */
320       $acl= get_permissions ($this->dn, $this->ui->subtreeACL);
321       $acl= get_module_permission($acl, "user", $this->dn);
322       if (chkacl($acl, "password") == ""){
324         /* User is allowed to change passwords, save 'dn' and 'acl' for next
325            dialog. */
326         $this->acl= $acl;
327         $_SESSION['objectinfo']= $this->dn;
328         return ($smarty->fetch(get_template_path('password.tpl', TRUE)));
330       } else {
331         /* User is not allowed. Show message and cancel. */
332         print_red (_("You are not allowed to set this users password!"));
333       }
334     }
336     /* Perform password change */
337     if (isset($_POST['password_finish'])){
339       /* For security reasons, check if user is allowed to set password again */
340       if (chkacl($this->acl, "password") == "" || chkacl($this->acl, "create")){
342         /* Check input and feed errors into 'message' */
343         $message= array();
345         /* Sanity checks... */
346         if ($_POST['new_password'] != $_POST['repeated_password']){
348           /* Matching passwords in new and repeated? */
349           $message[]= _("The passwords you've entered as 'New password' and 'Repeated new password' do not match.");
350         } else {
352           /* Empty password is not permitted by default. */
353           if ($_POST['new_password'] == ""){
354             $message[]= _("The password you've entered as 'New password' is empty.");
355           }
356         }
358         /* Errors, or password change? */
359         if (count($message) != 0){
361           /* Show error message and continue editing */
362           show_errors ($message);
363           return($smarty->fetch(get_template_path('password.tpl', TRUE)));
364         }
366         $config= $this->config;
367         $ldap_ui= $this->config->get_ldap_link();
368         if(isset($this->usertab->dn)){
369           $user = ($ldap_ui->fetch($ldap_ui->cat($this->usertab->dn)));
370         }else{
371           $user = ($ldap_ui->fetch($ldap_ui->cat($this->dn)));
372         }
373         if((is_array($user))&&(isset($user['uid']))){
374           $username= $user['uid'][0];
375         }
377         /* Set password, perform required steps */
378         if ($this->usertab){
379           if ($this->usertab->password_change_needed()){
380             $obj= $this->usertab->by_object['user'];
381             change_password ($this->usertab->dn, $_POST['new_password'],
382                 0, $obj->pw_storage);
383             if (isset($config->data['MAIN']['EXTERNALPWDHOOK'])){
384               exec($config->data['MAIN']['EXTERNALPWDHOOK']." ".$username." ".$_POST['new_password'], $resarr);
385             }
387             gosa_log ("Password for '".$this->usertab->dn."' has been changed");
388             unset($this->usertab);
389             $this->usertab= NULL;
390           }
391         } else {
392           change_password ($this->dn, $_POST['new_password']);
393           if (isset($config->data['MAIN']['EXTERNALPWDHOOK'])){
394             exec($config->data['MAIN']['EXTERNALPWDHOOK']." ".$username." ".$_POST['new_password'], $resarr);
395           }
397           gosa_log ("Password for '".$this->dn."' has been changed");
398         }
399       } else {
401         /* Missing permissions, show message */
402         print_red (_("You are not allowed to set this users password!"));
403       }
405       /* Clean session, delete lock */
406       del_lock ($this->dn);
407       $this->reload();
408       unset ($this->usertab);
409       $this->usertab= NULL;
410       $this->lognames= array();;
411       $this->sn= "";
412       $this->givenName= "";
413       $this->uid= "";
414       unset ($_SESSION['objectinfo']);
415     }
417     /* Remove user was requested */
418     if ($s_action=="del"){
420       /* Get 'dn' from posted 'uid' */
421       $this->dn= $this->list[trim($s_entry)]['dn'];
423       /* Load permissions for selected 'dn' and check if
424          we're allowed to remove this 'dn' */
425       $acl= get_permissions ($this->dn, $this->ui->subtreeACL);
426       $this->acl= get_module_permission($acl, "user", $this->dn);
427       if (chkacl($this->acl, "delete") == ""){
429         /* Check locking, save current plugin in 'back_plugin', so
430            the dialog knows where to return. */
431         if (($user= get_lock($this->dn)) != ""){
432           return(gen_locked_message ($user, $this->dn));
433         }
435         /* Lock the current entry, so nobody will edit it during deletion */
436         add_lock ($this->dn, $this->ui->dn);
437         $smarty->assign("info", sprintf(_("You're about to delete the user %s."), @LDAP::fix($this->dn)));
438         return($smarty->fetch(get_template_path('remove.tpl', TRUE)));
439       } else {
441         /* Obviously the user isn't allowed to delete. Show message and
442            clean session. */
443         print_red (_("You are not allowed to delete this user!"));
444       }
445     }
447     /* Confirmation for deletion has been passed. User should be deleted. */
448     if (isset($_POST['delete_user_confirm'])){
450       /* Some nice guy may send this as POST, so we've to check
451          for the permissions again. */
452       if (chkacl($this->acl, "delete") == ""){
454         /* Delete request is permitted, perform LDAP action */
455         $this->usertab= new usertabs($this->config, $this->config->data['TABS']['USERTABS'],
456             $this->dn);
457         $this->usertab->set_acl(array($this->acl));
458         $this->usertab->delete ();
459         gosa_log ("User object '".$this->dn."' has been removed");
460         unset ($this->usertab);
461         $this->usertab= NULL;
463         /* User list has changed, reload it. */
464         $this->reload ();
465       } else {
467         /* Normally this shouldn't be reached, send some extra
468            logs to notify the administrator */
469         print_red (_("You are not allowed to delete this user!"));
471         if(isset($this->ui->uid)){
472           gosa_log ("Warning: '".$this->ui->uid."' tried to trick user deletion.");
473         }
474       }
476       /* Remove lock file after successfull deletion */
477       del_lock ($this->dn);
478     }
481     /* Delete user canceled? */
482     if (isset($_POST['delete_cancel'])){
483       del_lock ($this->dn);
484     }
487     /* Finish user edit is triggered by the tabulator dialog, so
488        the user wants to save edited data. Check and save at this
489        point. */
490     if ((isset($_POST['edit_finish'])) && (isset($this->usertab->config))){
492       /* Check tabs, will feed message array */
493       $this->usertab->last= $this->usertab->current;
494       $this->usertab->save_object();
495       $message= $this->usertab->check();
497       /* Save, or display error message? */
498       if (count($message) == 0){
500         /* No errors. Go ahead and prepare to ask for a password
501            in case we're creating a new user. 'dn' will be 'new'
502            in this case. It is set to the correct value later. */
503         if ($this->dn == "new"){
504           $set_pass= 1;
505         } else {
506           $set_pass= 0;
507         }
509         /* Save user data to ldap */
510         if($this->usertab->save() == 1){
511           gosa_log ("User object '".$this->dn."' saving failed.");
512           return;
513         }
514         gosa_log ("User object '".$this->dn."' has been saved");
516         /* User has been saved successfully, remove lock from
517            LDAP. */
518         if ($this->dn != "new"){
519           del_lock ($this->dn);
520         }
522         /* In case of new users, ask for a password */
523         if (($set_pass || $this->usertab->password_change_needed()) &&
524             !$this->is_template){
526           return($smarty->fetch(get_template_path('password.tpl', TRUE)));
527         }
529         /* There's no page reload so we have to read new users at
530            this point. */
531         $this->reload ();
532         unset ($this->usertab);
533         $this->usertab= NULL;
534         unset ($_SESSION['objectinfo']);
536       } else {
537         /* Ok. There seem to be errors regarding to the tab data,
538            show message and continue as usual. */
539         show_errors($message);
540       }
541     }
543     /* Generate template list */
544     if (($s_action=="new")||($s_action=="create_user_from_tpl")){
546       $this->templates= array();
548       $ldap= $this->config->get_ldap_link();
550       /* Create list of tempaltes */
551       foreach ($this->config->departments as $key => $value){
552     
553         /* Get acls from different ou's */
554         $acl= get_permissions (get_people_ou().$value, $this->ui->subtreeACL);
555         $acl= get_module_permission($acl, "user", get_people_ou().$value);
556   
557         /* If creation of a new user is allowed, append this template */
558         if (chkacl($acl, "create") == ""){
559           
560           /* Search all templates from the current dn */
561           $ldap->cd (get_people_ou().$value);
562           $ldap->search ("(objectClass=gosaUserTemplate)", array("uid"));
564           /* Append */
565           if ($ldap->count() != 0){
566             while ($attrs= $ldap->fetch()){
567               $this->templates[$ldap->getDN()]=
568                 $attrs['uid'][0]." - ".@LDAP::fix($key);
569             }
570             $this->templates['none']= _("none");
571           }
572         }
573       }
575       /* Sort templates */
576       natcasesort ($this->templates);
577       reset ($this->templates);
578     }
580     /* New user/template request */
581     if (($s_action=="create_user_from_tpl")||($s_action=="new") || ($s_action=="new_tpl")){
582       /* By default we set 'dn' to 'new', all relevant plugins will
583          react on this. */
584       $this->dn= "new";
585       if (isset($this->config->current['IDGEN'])){
586         $this->got_uid= false;
587       } else {
588         $this->got_uid= true;
589       }
591       /* Create new usertab object */
592       $this->usertab= new usertabs($this->config,
593           $this->config->data['TABS']['USERTABS'], $this->dn);
594       $this->usertab->set_acl(array(':all'));
595       $this->usertab->by_object['user']->base= $_SESSION['CurrentMainBase'];
597       /* Take care about templates */
598       if ($s_action=="new_tpl"){
599         $this->is_template= TRUE;
600         $this->usertab->set_template_mode ();
601       } else {
602         $this->is_template= FALSE;
603       }
605       /* Use template if there are any of them */
606       if ((count($this->templates) && ($s_action!='new_tpl'))||($s_action=="create_user_from_tpl")){
607         foreach(array("sn", "givenName", "uid", "got_uid", "templates") as $attr){
608           $smarty->assign("$attr", $this->$attr);
609         }
610         if ($s_action=="create_user_from_tpl"){
611           $smarty->assign("template", $this->dn= $this->list[trim($s_entry)]['dn']);
612         } else {
613           $smarty->assign("template", "none");
614         }
615         $smarty->assign("edit_uid", "");
616         return($smarty->fetch(get_template_path('template.tpl', TRUE)));
617       }
618     }
620     /* Continue template editing */
621     if ((isset($_POST['template_continue']) && $_POST['template'] != 'none' && !isset($_POST['uid']))){
622       $this->sn= $_POST['sn'];
623       $this->givenName= $_POST['givenName'];
625       /* Check for requred values */
626       $message= array();
627       if ($this->sn == "") {
628         $message[]= _("The required field 'Name' is not set.");
629       }
630       if ($this->givenName == "") {
631         $message[]= _("The required field 'Given name' is not set.");
632       }
634       /* Check if dn is used */
635       $dn= preg_replace("/^[^,]+,/i", "", $_POST['template']);
636       $ldap= $this->config->get_ldap_link();
637       $ldap->cd ($dn);
638       $ldap->search ("(&(sn=".normalizeLdap($this->sn).")(givenName=".normalizeLdap($this->givenName)."))", array("givenName"));
639       if ($ldap->count () != 0){
640         $message[]= _("A person with the choosen name is already used in this tree.");
641       }
643       /* Show error message / continue editing */
644       if (count($message) > 0){
645         show_errors ($message);
646       } else {
647         $attributes= array('sn' => $this->sn, 'givenName' => $this->givenName);
648         if (isset($this->config->current['IDGEN']) &&
649             $this->config->current['IDGEN'] != ""){
650           $uids= gen_uids ($this->config->current['IDGEN'], $attributes);
651           if (count($uids)){
652             $smarty->assign("edit_uid", "false");
653             $smarty->assign("uids", $uids);
654             $this->uid= current($uids);
655           }
656         } else {
657           $smarty->assign("edit_uid", "");
658           $this->uid= "";
659         }
660         $this->got_uid= true;
661       }
663       foreach(array("sn", "givenName", "uid", "got_uid", "templates") as $attr){
664         $smarty->assign("$attr", $this->$attr);
665       }
666       if (isset($_POST['template'])){
667         $smarty->assign("template", $_POST['template']);
668       }
669       return($smarty->fetch(get_template_path('template.tpl', TRUE)));
670     }
672     /* No template. Ok. Lets fill data into the normal user dialog */
673     if (isset($_POST['template_continue']) && $_POST['template'] == 'none'){
674       foreach(array("sn", "givenName", "uid") as $attr){
675         if (isset($_POST[$attr])){
676           $this->usertab->by_object['user']->$attr= $_POST[$attr];
677         }
678       }
679     }
681     /* Finish template preamble */
682     if (isset($_POST['template_continue']) && $_POST['template'] != 'none' && (isset($_POST['uid']))){
684       /* Might not be filled if IDGEN is unset */
685       $this->sn                 = $_POST['sn'];
686       $this->givenName          = $_POST['givenName'];
688       /* Move user supplied data to sub plugins */
689       $this->uid                = $_POST['uid'];
690       $this->usertab->uid       = $this->uid;
691       $this->usertab->sn        = $this->sn;
692       $this->usertab->givenName = $this->givenName;
693       $template_dn              = $_POST['template'];
694       $this->usertab->adapt_from_template($template_dn);
695       $template_base            = preg_replace("/^[^,]+,".normalizePreg(get_people_ou())."/", '', $template_dn);
696       $this->usertab->by_object['user']->base= $template_base;
698       /* Set up the users ACL's for this 'dn' */
699       $acl= get_permissions ($template_base, $this->ui->subtreeACL);
700       $this->usertab->set_acl($acl);
701     }
702     
703     if (isset($_POST['template_continue']) && ($_POST['template'] == 'none')){
704       $this->usertab->by_object['user']->base= $_SESSION['CurrentMainBase'];
705     }
707     /* Show tab dialog if object is present */
708     if(isset($this->usertab->config)){
709       $display= $this->usertab->execute();
711       /* Don't show buttons if tab dialog requests this */
712       if (!$this->usertab->by_object[$this->usertab->current]->dialog){
713         $display.= "<p style=\"text-align:right\">\n";
714         $display.= "<input type=submit name=\"edit_finish\" value=\""._("Save")."\">\n";
715         $display.= "&nbsp;\n";
716         $display.= "<input type=submit name=\"edit_cancel\" value=\""._("Cancel")."\">\n";
717         $display.= "</p>";
718       }
719       return ($display);
720     }
722     /* Reload if we need a reload... */
723     if (!isset($this->usertab) &&
724         !isset($_POST['new_user']) &&
725         !isset($_POST['new_template']) &&
726         !isset($_POST['delete_user']) &&
727         !isset($_POST['setpass_user']) &&
728         !isset($_POST['select_user'])){
729       $this->reload();
730     }
732     /* Check for exeeded sizelimit */
733     if (($message= check_sizelimit()) != ""){
734       return($message);
735     }
737     /* Prepare departments */
738     $options= "";
739     foreach ($this->config->idepartments as $key => $value){
740       if ($_SESSION['CurrentMainBase'] == $key){
741         $options.= "<option selected value='$key'>$value</option>";
742       } else {
743         $options.= "<option value='$key'>$value</option>";
744       }
745     }
747     /* Choose correct paste icon */
748     if($this->CopyPasteHandler){
749       $Copy_Paste= $this->CopyPasteHandler->generatePasteIcon();
750     }else{
751       $Copy_Paste= "";
752     }
754 #------------------------------------------------------------------------ Review mark
755     //FIXME: Hmm. I spent some hours in the past to get rid of HTML inside the
756     //       PHP code. The section from here until the end of the execute() function
757     //       is not what I'd call a good solution. It works, but its somewhat ugly.
758     //       Currently I've no idea to make it better. HERE docs can help to make
759     //       the code more readable. Smarty templates would be the best solution.
760     //       Just not sure how to do it right now.
762     /* NEW LIST MANAGMENT */
763     //FIXME: Who cares? The old one is not present, and the big letters don't
764     //       make clear that it's still spaghetti code...
765     //FIXME: Variable naming - field1....
766     $listhead = "<div style='background:#F0F0F9;padding:5px;'>".
767       " <input class='center' type='image' src='images/list_root.png' align='middle' title='"._("Go to root department")."' name='dep_root' alt='"._("Root")."'>&nbsp;".
768       " <input class='center' type='image' align='middle' src='images/list_back.png' title='"._("Go up one department")."' alt='"._("Up")."' name='dep_back'>&nbsp;".
769       " <input class='center' type='image' align='middle' src='images/list_home.png' title='"._("Go to users department")."' alt='"._("Home")."' name='dep_home'>&nbsp;".
770       " <input class='center' type='image' src='images/list_reload.png' align='middle' title='"._("Reload list")."' name='submit_department' alt='"._("Submit")."'>&nbsp;".
771       " <img   class='center' src='images/list_seperator.png' align='middle' alt='' height='16' width='1'>&nbsp;".
772       " <input class='center' type='image' align='middle' src='images/list_new_user.png' title='"._("Create new user")."' alt='"._("New user")."' name='user_new'>&nbsp;".
773       " <input class='center' type='image' align='middle' src='images/list_new.png' title='"._("Create new template")."' alt='"._("New template")."' name='user_tplnew'>&nbsp;".
774       $Copy_Paste.
775       " <img   class='center' src='images/list_seperator.png' align='middle' alt='' height='16' width='1'>&nbsp;".
776       _("Base")."&nbsp;<select name='CurrentMainBase' onChange='mainform.submit()' class='center'>$options</select>".
777       " <input class='center' type='image' src='images/list_submit.png' align='middle' title='"._("Submit department")."' name='submit_department' alt='"._("Submit")."'>&nbsp;".
778       "</div>";
779     
780     if($this->CopyPasteHandler){
781       $action = "<input class='center' type='image'
782         src='images/editcut.png' alt='"._("cut")."' name='cut_%KEY%' title='"._("Cut this entry")."'>&nbsp;";
783       $action.= "<input class='center' type='image'
784         src='images/editcopy.png' alt='"._("copy")."' name='copy_%KEY%' title='"._("Copy this entry")."'>&nbsp;";
785       $action.= "<input class='center' type='image' src='images/edit.png' alt='"._("edit")."'     
786         name='user_edit_%KEY%' title='"._("Edit user")."'>";
787       $action.= "<input class='center' type='image' src='images/list_password.png' alt='"._("password")."' 
788         name='user_chgpw_%KEY%' title='"._("Change password")."'>";
789       $action.= "<input class='center' type='image' src='images/edittrash.png' alt='"._("delete")."'   
790         name='user_del_%KEY%' title='"._("Delete user")."'>";
791     }else{
792       $action= "<input class='center' type='image' src='images/edit.png' alt='"._("edit")."'     
793         name='user_edit_%KEY%' title='"._("Edit user")."'>";
794       $action.= "<input class='center' type='image' src='images/list_password.png' alt='"._("password")."' 
795         name='user_chgpw_%KEY%' title='"._("Change password")."'>";
796       $action.= "<input class='center' type='image' src='images/edittrash.png' alt='"._("delete")."'   
797         name='user_del_%KEY%' title='"._("Delete user")."'>";
798     }
800     $divlist = new divlist("userstab");
801     $divlist->SetHeader(array(
802           array("string" => "&nbsp;", "attach" => "style='text-align:center;width:20px;'"),
803           array("string" => _("Username")." / "._("Department"), "attach" => "style=''"),
804           array("string" => _("Properties"), "attach" => "style='width:152px;'"),
805           array("string" => _("Actions"), "attach" => "style='width:102px;border-right:0px;text-align:right;'")));
807     $divlist->SetSummary(_("This table displays all users, in the selected tree."));
808     $divlist->SetEntriesPerPage(0);
810     /* Defining Links */
811     $linkopen = "<a href='?plug=".validate($_GET['plug'])."&amp;act=dep_open&amp;dep_id=%s'>%s</a>";
813     /* Insert departments in divlist*/
814     foreach($this->departments as $key => $val){
816       if(!isset($this->config->departments[trim($key)])){
817         $this->config->departments[trim($key)]="";
818       }
820       $non_empty="";
821       foreach($this->config->departments as $keyd => $vald ){
822         if(preg_match("/".normalizePreg($key)."\/.*/", $keyd)){
823           $non_empty="full";
824         }
825       }
827       $field1 = array("string" => "<img src='images/".$non_empty."folder.png' alt='department'>", "attach" => "style='text-align:center;width:20px;'");
828       $field2 = array("string" => sprintf($linkopen,base64_encode($key),$val), "attach" => "style=''");
829       $field3 = array("string" => "&nbsp;", "attach" => "style='width:152px;'");
830       $field4 = array("string" => "&nbsp;", "attach" => "style='width:90px;border-right:0px;text-align:right;'");
832       $divlist->AddEntry(array($field1,$field2,$field3,$field4));
833     }
835     /* Pictures for Extensions */
836     $usrimg   ="<input class='center' type='image' src='images/penguin.png' alt='"._("GOsa")."'   
837                     name='user_edit_%KEY%-user' title='"._("Edit generic properties")."'>";
838     $posiximg = "<input class='center' type='image' src='images/select_user.png' alt='"._("Posix")."'  
839                     name='user_edit_%KEY%-posixAccount' title='"._("Edit UNIX properties")."'>";
840     $eviroimg = "<input class='center' type='image' src='images/smallenv.png' alt='"._("Environment")."'  
841                     name='user_edit_%KEY%-environment' title='"._("Edit environment properties")."'>";
842     $mailimg  = "<input class='center' type='image' src='images/mailto.png' alt='"._("Mail")."'     
843                     name='user_edit_%KEY%-mailAccount' title='"._("Edit mail properties")."'>";
844     $fonimg   = "<input class='center' type='image' src='images/%image%' alt='"._("Phone")."'     
845                     name='user_edit_%KEY%-phoneAccount' title='"._("Edit phone properties")."%title%'>";
846     $faximg   = "<input class='center' type='image' src='images/fax_small.png' alt='"._("Fax")."'     
847                     name='user_edit_%KEY%-gofaxAccount' title='"._("Edit fax properies")."'>";
848     $sambaimg = "<input class='center' type='image' src='images/select_winstation.png' alt='"._("Samba")."'     
849                     name='user_edit_%KEY%-sambaAccount' title='"._("Edit samba properties")."'>"; 
850     $tplcreateuserimg  = "<input type='image' class='center' src='images/list_new.png' alt='"._("Create user from template")."'
851                     name='userfrom_tpl_%KEY%' title='"._("Create user with this template")."'>";   
853     $empty    = "<img class='center' src='images/empty.png' style='width:16px;height:16px;' alt=''>"; 
855     // User and Template  Images  
856     $userimg  = "<img class='center' src='images/select_user.png' alt='User' title='%s'>";   
857     $tplimg   = "<img class='center' src='images/select_template.png' alt='Template' title='%s'>";   
858     $editlink = "<a href='?plug=".validate($_GET['plug'])."&amp;id=%s&amp;act=edit_entry'>%s</a>";
860     // Defines Arrays to save User and Templates
861     $tpls = array();
862     $users= array();
864     /* Get Configuration for goFon DB (if it is set), to connect to the asterisk tables.
865      * Read Sip Table for specified account (for each user with phoneAccount).
866      * Check the attributes ip port and regseconds.
867      * If regseconds is set and >0 , the phone is logged in.
868      * Else the phone is currently not logged.
869      * If we can't read any Data from the DB or there is no goFon DB specified
870      * show old style without status icons.
871      */
872     $r_db   =false;
873     $r_con  =false;
874     if (isset($_SESSION['config']->data['SERVERS']['FON'])){
875       $a_SETUP= $_SESSION['config']->data['SERVERS']['FON'];
876       // Connect to DB server
877   
878       /* 
879         If you want to disable the status pictures, just comment out the next line
880       */
881       $r_con = false;
882       $r_db  = false;
883       if(is_callable("mysql_pconnect")){
884         $r_con= @mysql_pconnect($a_SETUP['SERVER'],$a_SETUP['LOGIN'],$a_SETUP['PASSWORD']);
885         // Check if we are  connected correctly
886         if($r_con){
887           $r_db  =  @mysql_select_db($a_SETUP['DB'],$r_con);
888         }
889       }
890     }
892     // Test Every Entry and generate divlist Array  
893     foreach($this->list as $key => $val){
894       $connected  = ""; // This string represents timestamp or offline status 
895       $ip_port    = ""; // String that will represent ip : port of the connected phone
896       if((in_array("goFonAccount"    ,$val['objectClass']))){
897   
898         /* Set defaults */
899         $fonac = preg_replace("/%image%/", "select_phone.png", $fonimg);
900         $fonac = preg_replace("/%KEY%/", "$key", $fonac);
901         $fonac = preg_replace("/%title%/", "", $fonac);
903         /* Database connection is ok ?*/
904         if(($r_db)&&(is_callable("mysql_query"))){
905           $res= @mysql_query("SELECT regseconds,name,port,ipaddr FROM ".$a_SETUP['SIP_TABLE']." WHERE (name='".$val['uid'][0]."')");
906           $mysql_entry = @mysql_fetch_row($res);
907           if(is_array($mysql_entry)){
908             if((isset($mysql_entry[0]))&&($mysql_entry[0]>1)){
909               $connected = " | "._("Online")." : ".gmdate("d.m.Y H:i:s",($mysql_entry[0]+(60*60)));
910               $fonac = preg_replace("/%image%/", "select_phone_connected.png", $fonimg);
911               $fonac = preg_replace("/%KEY%/", "$key", $fonac);
912               $fonac = preg_replace("/%title%/", $connected, $fonac);
913               $ip_port= " - ".$mysql_entry[3].":".$mysql_entry[2];
914             }
915             if((isset($mysql_entry[0]))&&($mysql_entry[0]==0)){
916               $connected = " | "._("Offline");
917               $fonac = preg_replace("/%image%/", "select_phone.png", $fonimg);
918               $fonac = preg_replace("/%KEY%/", "$key", $fonac);
919               $fonac = preg_replace("/%title%/", $connected, $fonac);
920             }
921           }
922         }
923       }else{
924         $fonac=$empty;
925       }
927     
929       /* Specify Pics for Extensions */ 
930       //FIXME: Spaghetti code. Please replace by a simple loop.
931       if(in_array("posixAccount"    ,$val['objectClass'])){ 
932         $posix = preg_replace("/%KEY%/", "$key", $posiximg);
933       }else{ 
934         $posix=$empty;
935       }
936       
937       if(in_array("gotoEnvironment"    ,$val['objectClass'])){ 
938         $enviro = preg_replace("/%KEY%/", "$key", $eviroimg);
939       }else{ 
940         $enviro =$empty;
941       }
942    
943       if(in_array("gosaMailAccount" ,$val['objectClass'])){ 
944         $maila = preg_replace("/%KEY%/", "$key", $mailimg);   
945       }else{ 
946         $maila=$empty;
947       } 
948   
949       if(in_array("goFaxAccount"    ,$val['objectClass'])){ 
950         $faxac = preg_replace("/%KEY%/", "$key", $faximg);    
951       }else{ 
952         $faxac=$empty;
953       } 
955       if(in_array("sambaSamAccount" ,$val['objectClass'])){ 
956         $samba = preg_replace("/%KEY%/", "$key", $sambaimg);  
957       }else{ 
958         $samba=$empty;
959       } 
961       if(in_array("gosaUserTemplate",$val['objectClass'])){ 
962         $tpl                          = preg_replace("/%KEY%/", "$key", $tplimg);   
963         $s_img_create_from_template   = preg_replace("/%KEY%/", "$key", $tplcreateuserimg);
964       }else{ 
965         $s_img_create_from_template   = "";
966         $tpl=$userimg;
967       }
969       $usrimg2 = preg_replace("/%KEY%/", "$key", $usrimg);
971       // Generate caption for rows
972       if (isset($val["sn"]) && isset($val["givenName"])){
973         $display= $val["sn"][0].", ".$val["givenName"][0]." [".$val["uid"][0]."]";
974       } else {
975         $display= "[".$val["uid"][0]."]";
976       }
978       /* Create each field */
979       $field1 = array("string" => sprintf($tpl,$val['dn']), "attach" => "style='text-align:center;width:20px;'");
980       $field2 = array("string" => sprintf($editlink,$key,$display).$ip_port, "attach" => "style='' title='dn:&nbsp;".@LDAP::fix($val['dn'])."'");
981       $field3 = array("string" => $usrimg2."&nbsp;".$posix."&nbsp;".$enviro."&nbsp;".$maila."&nbsp;".$fonac."&nbsp;".$faxac."&nbsp;".$samba, "attach" => "style='width:152px;'");
982       $field4 = array("string" => $s_img_create_from_template.preg_replace("/%KEY%/", "$key", $action),"attach" => "style='width:102px;border-right:0px;text-align:right;'");
984       $add = array($field1,$field2,$field3,$field4);
986       // Template or User
987       if(in_array("gosaUserTemplate",$val['objectClass'])){
988         $tpls[strtolower( $val['sn']['0'].$val['uid']['0'])]=$add;
989       }else{
990         $users[strtolower( $val['sn']['0'].$val['uid']['0'])]=$add;
991       }
992     }
994     // Sort Entries 
995     ksort($users);
996     ksort($tpls);
998     // Append Templates
999     foreach($tpls as $key => $val){
1000       $divlist->AddEntry( $val, array(""));
1001     }
1002     // Append Users 
1003     foreach($users as $key => $val){
1004       $divlist->AddEntry( $val, array(""));
1005     }
1006     $smarty->assign("userlist",   $divlist->DrawList());
1007     $smarty->assign("userlisthead", $listhead);
1008     
1009     $smarty->assign("search_image", get_template_path('images/search.png'));
1010     $smarty->assign("tree_image", get_template_path('images/tree.png'));
1011     $smarty->assign("infoimage", get_template_path('images/info.png'));
1012     $smarty->assign("launchimage", get_template_path('images/launch.png'));
1013     $smarty->assign("deplist", $this->config->idepartments);
1015     foreach( array("functionalusers", "unixusers",
1016           "mailusers", "sambausers", "proxyusers", 
1017           "faxusers", "templates", "subsearch") as $type){
1019       $smarty->assign("$type", $userfilter[$type]);
1020     }
1022     $smarty->assign("CurrentMainBase",$_SESSION['CurrentMainBase']);
1023     $smarty->assign("regex", $userfilter["regex"]);
1025     /* Extend if we are not using javascript */
1026     $smarty->assign("apply", apply_filter());
1027     $smarty->assign("alphabet", generate_alphabet());
1028     $smarty->assign("hint", print_sizelimit_warning());
1030     if((is_callable("mysql_close"))&&($r_con)){
1031       @mysql_close($r_con);
1032     }
1034     /* Return rendered main page */
1035     return ($smarty->fetch(get_template_path('headpage.tpl', TRUE)));
1036   }
1037 #----------------------------------------------------------------- Reviewed after this mark
1040   function reload()
1041   {
1042     /* Get config */
1043     $userfilter= get_global('userfilter');
1045     /* Set base for all searches */
1046     $base= $_SESSION['CurrentMainBase'];
1048     /* Regex filter? */
1049     if ($userfilter['regex'] != ""){
1050       $regex= $userfilter['regex'];
1051     } else {
1052       $regex= "*";
1053     }
1055     /* Setup filter depending on selection */
1056     $filter="";
1057     if ($this->config->current['SAMBAVERSION'] == 3){
1058       $samba= "sambaSamAccount";
1059     } else {
1060       $samba= "sambaAccount";
1061     }
1062     if ($userfilter['functionalusers'] == "checked"){
1063       $filter.= "(&(objectClass=gosaAccount)(!(|(objectClass=posixAccount)".
1064                 "(objectClass=gosaMailAccount)(objectClass=$samba)".
1065                 "(objectClass=gosaProxyAccount))))";
1066     }
1067     if ($userfilter['unixusers'] == "checked"){
1068       $filter.= "(objectClass=posixAccount)";
1069     }
1070     if ($userfilter['mailusers'] == "checked"){
1071       $filter.= "(objectClass=gosaMailAccount)";
1072     }
1073     if ($userfilter['sambausers'] == "checked"){
1074       $filter.= "(objectClass=$samba)";
1075     }
1076     if ($userfilter['proxyusers'] == "checked"){
1077       $filter.= "(objectClass=gosaProxyAccount)";
1078     }
1079     if ($userfilter['templates'] == "checked"){
1080       $filter= "(|(objectClass=gosaUserTemplate)(&(objectClass=gosaAccount)(|$filter)))";
1081     } else {
1082       $filter= "(&(objectClass=gosaAccount)(!(objectClass=gosaUserTemplate))(|$filter))";
1083     }
1084     //FIXME: Search filter will fail, if 'regex' contains filter special characters.
1085     $filter= "(&(|(uid=$regex)(sn=$regex)(givenName=$regex))$filter)";
1087     /* Generate userlist */
1088     $ldap= $this->config->get_ldap_link(TRUE);
1089     if ($userfilter['subsearch'] == "checked"){
1090       $this->list= get_list($filter, $this->ui->subtreeACL, $base,
1091                             array("uid", "givenName", "sn", "objectClass"), GL_SUBSEARCH | GL_SIZELIMIT);
1092     } else {
1093       $base= get_people_ou().$base;
1094       $this->list= get_list($filter, $this->ui->subtreeACL, $base, 
1095                             array("uid", "givenName", "sn", "objectClass"), GL_SIZELIMIT);
1096     }
1098     /* NEW LIST MANAGMENT
1099      * We also need to search for the departments
1100      * So we are able to navigate like in konquerer */
1101      //FIXME: Same here - who cares? We need comments that make code reading
1102      //       more easy. No prosa for things that are not important - or even
1103      //       not readable below.
1104      //FIXME: Repeatedly I see things like res1, res3, base2, etc. This is no
1105      //       good coding style at all.
1107     /* Create base to search in */
1108     if(get_people_ou() == ""){
1109       $dep_base= $base;
1110     }else{
1111       $dep_base= preg_replace("/".normalizePreg(get_people_ou())."/i", "", $base);
1112     }
1114     /* Get all departments within this subtree */
1115     $deps= get_list("(&(|(ou=$regex)(description=$regex))(objectClass=gosaDepartment))", $this->ui->subtreeACL,
1116                     $dep_base, array("ou", "description"), GL_SIZELIMIT | GL_CONVERT);
1118     /* Create array with results */
1119     //FIXME: Sure. Interesting. What the heck is happening here? Why do we
1120     //       need so many loops to perform one action? $tmp is used below
1121     //       maybe this is integratable? Why are lowercase and normal variants
1122     //       perpended? Concepts other than "Create array with results"?
1123     $tmp= array();
1124     foreach ($deps as $value){
1125       $tmp[strtolower($value['dn']).$value['dn']]= $value;
1126     }
1128     /* Sort array */
1129     //FIXME: Which is implied by ksort, I guess.
1130     ksort($tmp);
1132     /* Create result array */
1133     //FIXME: Didn't we do that above?
1134     $this->departments= array();
1135     foreach($tmp as $value){
1136       if(isset($value['description'][0])){
1137         $this->departments[$value['dn']]= get_sub_department($value['dn'])." - [".$value["description"][0]."]";
1138       }else{
1139         $this->departments[$value['dn']]= get_sub_department($value['dn']);
1140       }
1141     }
1143   }
1146   function remove_lock()
1147   {
1148     /* Remove user lock if a DN is marked as "currently edited" */
1149     if (isset($this->usertab->dn)){
1150       del_lock ($this->usertab->dn);
1151     }
1152   }
1155   /* A set of disabled and therefore overloaded functions. They are
1156      not needed in this class. */
1157   function remove_from_parent() { } 
1158   function check() { } 
1159   function save() { } 
1160   function adapt_from_template($dn) { } 
1161   function password_change_needed() { } 
1162   function show_header($button_text, $text, $disabled= FALSE) { }
1164 } /* ... class userManagement */
1167 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1168 ?>