Code

Prepare sortedlist for additional attributes
[gosa.git] / gosa-core / plugins / personal / generic / class_user.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   user 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 person, organizationalPerson, inetOrgPerson and gosaAccount
31   from/to the LDAP. It does syntax checking and displays the formulars required.
32  */
34 class user extends plugin
35 {
36   /* Definitions */
37   var $plHeadline= "Generic";
38   var $plDescription= "Edit organizational user settings";
40   /* Plugin specific values */
41   var $base= "";
42   var $orig_base= "";
43   var $cn= "";
44   var $new_dn= "";
45   var $personalTitle= "";
46   var $academicTitle= "";
47   var $homePostalAddress= "";
48   var $homePhone= "";
49   var $labeledURI= "";
50   var $o= "";
51   var $ou= "";
52   var $departmentNumber= "";
53   var $gosaLoginRestriction= array();
54   var $gosaLoginRestrictionWidget;
55   var $employeeNumber= "";
56   var $employeeType= "";
57   var $roomNumber= "";
58   var $telephoneNumber= "";
59   var $facsimileTelephoneNumber= "";
60   var $mobile= "";
61   var $pager= "";
62   var $l= "";
63   var $st= "";
64   var $postalAddress= "";
65   var $dateOfBirth;
66   var $use_dob= "0";
67   var $gender="0";
68   var $preferredLanguage="0";
70   var $jpegPhoto= "*removed*";
71   var $photoData= "";
72   var $old_jpegPhoto= "";
73   var $old_photoData= "";
74   var $cert_dialog= FALSE;
75   var $picture_dialog= FALSE;
76   var $pwObject= NULL;
78   var $userPKCS12= "";
79   var $userSMIMECertificate= "";
80   var $userCertificate= "";
81   var $certificateSerialNumber= "";
82   var $old_certificateSerialNumber= "";
83   var $old_userPKCS12= "";
84   var $old_userSMIMECertificate= "";
85   var $old_userCertificate= "";
87   var $gouvernmentOrganizationalUnit= "";
88   var $houseIdentifier= "";
89   var $street= "";
90   var $postalCode= "";
91   var $vocation= "";
92   var $ivbbLastDeliveryCollective= "";
93   var $gouvernmentOrganizationalPersonLocality= "";
94   var $gouvernmentOrganizationalUnitDescription= "";
95   var $gouvernmentOrganizationalUnitSubjectArea= "";
96   var $functionalTitle= "";
97   var $role= "";
98   var $publicVisible= "";
100   var $orig_dn;
101   var $dialog;
103   /* variables to trigger password changes */
104   var $pw_storage= "md5";
105   var $last_pw_storage= "unset";
106   var $had_userCertificate= FALSE;
108   var $view_logged = FALSE;
110   /* attribute list for save action */
111   var $attributes= array("sn", "givenName", "uid", "personalTitle", "academicTitle",
112       "homePostalAddress", "homePhone", "labeledURI", "ou", "o", "dateOfBirth", "gender","preferredLanguage",
113       "departmentNumber", "employeeNumber", "employeeType", "l", "st","jpegPhoto",
114       "roomNumber", "telephoneNumber", "mobile", "pager", "cn", "userPKCS12",
115       "postalAddress", "facsimileTelephoneNumber", "userSMIMECertificate", "gosaLoginRestriction");
117   var $objectclasses= array("top", "person", "organizationalPerson", "inetOrgPerson",
118       "gosaAccount");
120   /* attributes that are part of the government mode */
121   var $govattrs= array("gouvernmentOrganizationalUnit", "houseIdentifier", "vocation",
122       "ivbbLastDeliveryCollective", "gouvernmentOrganizationalPersonLocality",
123       "gouvernmentOrganizationalUnitDescription","gouvernmentOrganizationalUnitSubjectArea",
124       "functionalTitle", "certificateSerialNumber", "publicVisible", "street", "role",
125       "postalCode");
127   var $multiple_support = TRUE;
129   var $governmentmode = FALSE;
131   /* constructor, if 'dn' is set, the node loads the given
132      'dn' from LDAP */
133   function user (&$config, $dn= NULL)
134   {
135     global $lang;
137     $this->config= $config;
138     /* Configuration is fine, allways */
139     if($this->config->get_cfg_value("honourIvbbAttributes") == "true"){
140       $this->governmentmode = TRUE;
141       $this->attributes=array_merge($this->attributes,$this->govattrs);
142     }
144     /* Load base attributes */
145     plugin::plugin ($config, $dn);
147     $this->orig_dn  = $this->dn;
148     $this->new_dn   = $dn;
150     if ($this->governmentmode){
151       /* Fix public visible attribute if unset */
152       if (!isset($this->attrs['publicVisible'])){
153         $this->publicVisible == "nein";
154       }
155     }
157     /* Load government mode attributes */
158     if ($this->governmentmode){
159       /* Copy all attributs */
160       foreach ($this->govattrs as $val){
161         if (isset($this->attrs["$val"][0])){
162           $this->$val= $this->attrs["$val"][0];
163         }
164       }
165     }
167     /* Create me for new accounts */
168     if ($dn == "new"){
169       $this->is_account= TRUE;
170     }
172     /* Make hash default to md5 if not set in config */
173     $hash= $this->config->get_cfg_value("passwordDefaultHash", "crypt/md5");
175     /* Load data from LDAP? */
176     if ($dn !== NULL){
178       /* Do base conversation */
179       if ($this->dn == "new"){
180         $ui= get_userinfo();
181         $this->base= dn2base(session::global_is_set("CurrentMainBase")?"cn=dummy,".session::global_get("CurrentMainBase"):$ui->dn);
182       } else {
183         $this->base= dn2base($dn);
184       }
186       /* get password storage type */
187       if (isset ($this->attrs['userPassword'][0])){
188         /* Initialize local array */
189         $matches= array();
190         if (preg_match ("/^{[^}]+}/", $this->attrs['userPassword'][0])){
191           $tmp= passwordMethod::get_method($this->attrs['userPassword'][0]);
192           if(is_object($tmp)){
193             $this->pw_storage= $tmp->get_hash(); 
194           }
196         } else {
197           if ($this->attrs['userPassword'][0] != ""){
198             $this->pw_storage= "clear";
199           } else {
200             $this->pw_storage= $hash;
201           }
202         }
203       } else {
204         /* Preset with vaule from configuration */
205         $this->pw_storage= $hash;
206       }
208       /* Load extra attributes: certificate and picture */
209       $this->load_cert();
210       $this->load_picture();
211       if ($this->userCertificate != ""){
212         $this->had_userCertificate= TRUE;
213       }
214     }
216     /* Reset password storage indicator, used by password_change_needed() */
217     if ($dn == "new"){
218       $this->last_pw_storage= "unset";
219     } else {
220       $this->last_pw_storage= $this->pw_storage;
221     }
223     /* Generate dateOfBirth entry */
224     if (isset ($this->attrs['dateOfBirth'])){
225       /* This entry is ISO 8601 conform */
226       list($year, $month, $day)= split("-", $this->attrs['dateOfBirth'][0], 3);
227     
228       #TODO: use $lang to convert date
229       $this->dateOfBirth= "$day.$month.$year";
230     } else {
231       $this->dateOfBirth= "";
232     }
234     /* Put gender attribute to upper case */
235     if (isset ($this->attrs['gender'])){
236       $this->gender= strtoupper($this->attrs['gender'][0]);
237     }
239     // Get login restrictions
240     if(isset($this->attrs['gosaLoginRestriction'])){
241       $this->gosaLoginRestriction  =array();
242       for($i =0;$i < $this->attrs['gosaLoginRestriction']['count']; $i++){
243         $this->gosaLoginRestriction[] = $this->attrs['gosaLoginRestriction'][$i];
244       }
245     }
246     $this->gosaLoginRestrictionWidget= new sortableListing($this->gosaLoginRestriction);
247     $this->gosaLoginRestrictionWidget->setDeleteable(true);
248     $this->gosaLoginRestrictionWidget->setColspecs(array('*'));
249     $this->gosaLoginRestrictionWidget->setWidth("100%");
250     $this->gosaLoginRestrictionWidget->setHeight("70px");
251  
252     $this->orig_base = $this->base;
253   }
256   /* execute generates the html output for this node */
257   function execute()
258   {
259     /* Call parent execute */
260     plugin::execute();
262     /* Set list ACL */
263     $this->gosaLoginRestrictionWidget->setAcl($this->getacl('gosaLoginRestriction', (!is_object($this->parent) && !session::is_set('edit'))));
265     /* Handle add/delete for restriction mode */
266     if (isset($_POST['add_res']) && isset($_POST['res'])) {
267       $val= validate($_POST['res']);
268       if (preg_match('/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/', $val) ||
269           preg_match('/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/([0-9]+)$/', $val) ||
270           preg_match('/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/', $val)) {
271         $this->gosaLoginRestrictionWidget->addEntry($val);
272       } else {
273         msg_dialog::display(_("Error"), _("Please add a single IP address or a network/netmask combination!"), ERROR_DIALOG);
274       }
275     }
277     /* Log view */
278     if($this->is_account && !$this->view_logged){
279       $this->view_logged = TRUE;
280       new log("view","users/".get_class($this),$this->dn);
281     }
283     $smarty= get_smarty();
284     $smarty->assign("usePrototype", "true");
285     $smarty->assign("gosaLoginRestrictionWidget", $this->gosaLoginRestrictionWidget->render());
287     /* Assign sex */
288     $sex= array(0 => "&nbsp;", "F" => _("female"), "M" => _("male"));
289     $smarty->assign("gender_list", $sex);
290     $language= array_merge(array(0 => "&nbsp;") ,get_languages(TRUE));
291     $smarty->assign("preferredLanguage_list", $language);
293     /* Get random number for pictures */
294     srand((double)microtime()*1000000); 
295     $smarty->assign("rand", rand(0, 10000));
298     /* Do we represent a valid gosaAccount? */
299     if (!$this->is_account){
300       $str = "<img alt=\"\" src=\"images/small-error.png\" align=\"middle\">&nbsp;<b>".
301         msgPool::noValidExtension("GOsa")."</b>";
302       return($str);
303     }
305     /* Base select dialog */
306     $once = true;
307     foreach($_POST as $name => $value){
308       if(preg_match("/^chooseBase/",$name) && $once && $this->acl_is_writeable("base")){
309         $once = false;
310         $this->dialog = new baseSelectDialog($this->config,$this,$this->allowedBasesToMoveTo());
311         $this->dialog->setCurrentBase($this->base);
312       }
313     }
315     /* Password configure dialog handling */
316     if(is_object($this->pwObject) && $this->pwObject->display){
317       $output= $this->pwObject->configure();
318       if ($output != ""){
319         $this->dialog= TRUE;
320         return $output;
321       }
322       $this->dialog= false;
323     }
325     /* Dialog handling */
326     if(is_object($this->dialog)){
327       /* Must be called before save_object */
328       $this->dialog->save_object();
329    
330       if($this->dialog->isClosed()){
331         $this->dialog = false;
332       }elseif($this->dialog->isSelected()){
334         /* check if selected base is allowed to move to / create a new object */
335         $tmp = $this->get_allowed_bases();
336         if(isset($tmp[$this->dialog->isSelected()])){
337           $this->base = $this->dialog->isSelected();
338         }
339         $this->dialog= false;
340       }else{
341         return($this->dialog->execute());
342       }
343     }
345     /* Want password method editing? */
346     if ($this->acl_is_writeable("userPassword")){
347       if (isset($_POST['edit_pw_method'])){
348         if (!is_object($this->pwObject) || $this->pw_storage != $this->pwObject->get_hash_name()){
349           $temp= passwordMethod::get_available_methods();
350           $this->pwObject= new $temp[$this->pw_storage]($this->config,$this->dn);
351         }
352         $this->pwObject->display = TRUE;
353         $this->dialog= TRUE;
354         return ($this->pwObject->configure());
355       }
356     }
358     /* Want picture edit dialog? */
359     if($this->acl_is_writeable("userPicture")) {
360       if (isset($_POST['edit_picture'])){
361         /* Save values for later recovery, in case some presses
362            the cancel button. */
363         $this->old_jpegPhoto= $this->jpegPhoto;
364         $this->old_photoData= $this->photoData;
365         $this->picture_dialog= TRUE;
366         $this->dialog= TRUE;
367       }
368     }
370     /* Remove picture? */
371     if($this->acl_is_writeable("userPicture",(!is_object($this->parent) && !session::is_set('edit'))) ){
372       if (isset($_POST['picture_remove'])){
373         $this->set_picture ();
374         $this->jpegPhoto= "*removed*";
375         $this->is_modified= TRUE;
376         return($smarty->fetch (get_template_path('generic_picture.tpl', TRUE, dirname(__FILE__))));
377       }
378     }
380     /* Save picture */
381     if (isset($_POST['picture_edit_finish'])){
383       /* Check for clean upload */
384       if ($_FILES['picture_file']['name'] != ""){
385         if (!is_uploaded_file($_FILES['picture_file']['tmp_name'])) {
386           msg_dialog::display(_("Error"), _("Cannot upload file!"), ERROR_DIALOG);
387         }else{
388           /* Activate new picture */
389           $this->set_picture($_FILES['picture_file']['tmp_name']);
390         }
391       }
392       $this->picture_dialog= FALSE;
393       $this->dialog= FALSE;
394       $this->is_modified= TRUE;
395     }
398     /* Cancel picture */
399     if (isset($_POST['picture_edit_cancel'])){
401       /* Restore values */
402       $this->jpegPhoto= $this->old_jpegPhoto;
403       $this->photoData= $this->old_photoData;
405       /* Update picture */
406       session::set('binary',$this->photoData);
407       session::set('binarytype',"image/jpeg");
408       $this->picture_dialog= FALSE;
409       $this->dialog= FALSE;
410     }
412     /* Want certificate= */
413     if ((isset($_POST['edit_cert'])) && $this->acl_is_readable("Certificate")){
415       /* Save original values for later reconstruction */
416       foreach (array("certificateSerialNumber", "userCertificate",
417             "userSMIMECertificate", "userPKCS12") as $val){
419         $oval= "old_$val";
420         $this->$oval= $this->$val;
421       }
423       $this->cert_dialog= TRUE;
424       $this->dialog= TRUE;
425     }
428     /* Cancel certificate dialog */
429     if (isset($_POST['cert_edit_cancel'])){
431       /* Restore original values in case of 'cancel' */
432       foreach (array("certificateSerialNumber", "userCertificate",
433             "userSMIMECertificate", "userPKCS12") as $val){
435         $oval= "old_$val";
436         $this->$val= $this->$oval;
437       }
438       $this->cert_dialog= FALSE;
439       $this->dialog= FALSE;
440     }
443     /* Remove certificate? */
444     if($this->acl_is_writeable("Certificate",(!is_object($this->parent) && !session::is_set('edit')))){ 
445       foreach (array ("userCertificate", "userSMIMECertificate", "userPKCS12") as $val){
446         if (isset($_POST["remove_$val"])){
448           /* Reset specified cert*/
449           $this->$val= "";
450           $this->is_modified= TRUE;
451         }
452       }
453     }
455     /* Upload new cert and close dialog? */     
456     if($this->acl_is_writeable("Certificate",(!is_object($this->parent) && !session::is_set('edit')))){ 
458       $fail =false;
460       if (isset($_POST['cert_edit_finish'])){
462         /* for all certificates do */
463         foreach (array ("userCertificate", "userSMIMECertificate", "userPKCS12")
464             as $val){
466           /* Check for clean upload */
467           if (array_key_exists($val."_file", $_FILES) &&
468               array_key_exists('name', $_FILES[$val."_file"]) &&
469               $_FILES[$val."_file"]['name'] != "" &&
470               is_uploaded_file($_FILES[$val."_file"]['tmp_name'])) {
471             $this->set_cert("$val", $_FILES[$val."_file"]['tmp_name']);
472           }
473         }
475         /* Save serial number */
476         if (isset($_POST["certificateSerialNumber"]) &&
477             $_POST["certificateSerialNumber"] != ""){
479           if (!tests::is_id($_POST["certificateSerialNumber"])){
480             $fail = true;
481             msg_dialog::display(_("Error"), msgPool::invalid(_("Serial number"),$_POST["certificateSerialNumber"],"/[0-9]/"),ERROR_DIALOG);
483             foreach(array("userCertificate", "userSMIMECertificate", "userPKCS12") as $cert){
484               if ($this->$cert != ""){
485                 $smarty->assign("$cert"."_state", "true");
486               } else {
487                 $smarty->assign("$cert"."_state", "");
488               }
489             }
490           }
492           $this->certificateSerialNumber= $_POST["certificateSerialNumber"];
493           $this->is_modified= TRUE;
494         }
495         if(!$fail){
496           $this->cert_dialog= FALSE;
497           $this->dialog= FALSE;
498         }
499       }
500     }
501     /* Display picture dialog */
502     if ($this->picture_dialog){
503       return($smarty->fetch (get_template_path('generic_picture.tpl', TRUE, dirname(__FILE__))));
504     }
506     /* Display cert dialog */
507     if ($this->cert_dialog){
508       $smarty->assign("CertificateACL",$this->getacl("Certificate",(!is_object($this->parent) && !session::is_set('edit'))));
509       $smarty->assign("Certificate_readable",$this->acl_is_readable("Certificate"));
510       $smarty->assign("certificateSerialNumber",$this->certificateSerialNumber);
512       foreach(array("userCertificate", "userSMIMECertificate", "userPKCS12") as $cert){
513         if ($this->$cert != ""){
514           /* import certificate */
515           $certificate = new certificate;
516           $certificate->import($this->$cert);
517       
518           /* Read out data*/
519           $timeto   = $certificate->getvalidto_date();
520           $timefrom = $certificate->getvalidfrom_date();
521          
522           
523           /* Additional info if start end time is '0' */
524           $add_str_info = "";
525           if($timeto == 0 && $timefrom == 0){
526             $add_str_info = "<br><i>"._("(Some types of certificates are currently not supported and may be displayed as 'invalid'.)")."</i>";
527           }
529           $str = "<table summary=\"\" border=0>
530                     <tr>
531                       <td style='vertical-align:top'>CN</td>
532                       <td>".preg_replace("/ /", "&nbsp;", $certificate->getname())."</td>
533                     </tr>
534                   </table><br>".
536                   sprintf(_("Certificate is valid from %s to %s and is currently %s."),
537                         "<b>".date('d M Y',$timefrom)."</b>",
538                         "<b>".date('d M Y',$timeto)."</b>",
539                         $certificate->isvalid()?"<b><font style='color:green'>"._("valid")."</font></b>":
540                                                 "<b><font style='color:red'>"._("invalid")."</font></b>").$add_str_info;
542           $smarty->assign($cert."info",$str);
543           $smarty->assign($cert."_state","true");
544         } else {
545           $smarty->assign($cert."info", "<i>"._("No certificate installed")."</i>");
546           $smarty->assign($cert."_state","");
547         }
548       }
549   
550       if($this->governmentmode){
551         $smarty->assign("honourIvbbAttributes", "true");
552       }else{
553         $smarty->assign("honourIvbbAttributes", "false");
554       }
555       $smarty->assign("governmentmode", $this->governmentmode);
556       return($smarty->fetch (get_template_path('generic_certs.tpl', TRUE, dirname(__FILE__))));
557     }
559     /* Prepare password hashes */
560     if ($this->pw_storage == ""){
561       $this->pw_storage= $this->config->get_cfg_value("hash");
562     }
564     $temp= passwordMethod::get_available_methods();
565     $is_configurable= FALSE;
566     $hashes = $temp['name'];
567     if(isset($temp[$this->pw_storage])){
568       $test= new $temp[$this->pw_storage]($this->config);
569       $is_configurable= $test->is_configurable();
570     }else{
571       new msg_dialog(_("Password method"),_("The selected password method is no longer available."),WARNING_DIALOG);
572     }
575     /* Create password methods array */
576     $pwd_methods = array();
577     foreach($hashes as $id => $name){
578       if(!empty($temp['desc'][$id])){
579         $pwd_methods[$name] = $name." (".$temp['desc'][$id].")";
580       }else{
581         $pwd_methods[$name] = $name;
582       }
583     }
584  
585     /* Load attributes and acl's */
586     $ui =get_userinfo();
587     foreach($this->attributes as $val){
588       $smarty->assign("$val", $this->$val);
589       if(in_array($val,$this->multi_boxes)){
590         $smarty->assign("use_".$val,TRUE);
591       }else{
592         $smarty->assign("use_".$val,FALSE);
593       }
594     }
595     foreach(array("base","pw_storage","edit_picture") as $val){
596       if(in_array($val,$this->multi_boxes)){
597         $smarty->assign("use_".$val,TRUE);
598       }else{
599         $smarty->assign("use_".$val,FALSE);
600       }
601     }
603     /* Set acls */
604     $tmp = $this->plinfo();
605     foreach($tmp['plProvidedAcls'] as $val => $translation){
606       $smarty->assign("$val"."ACL", $this->getacl($val,(!is_object($this->parent) && !session::is_set('edit'))));
607     }
609     $smarty->assign("gosaLoginRestrictionACL", $this->getacl('gosaLoginRestriction', (!is_object($this->parent) && !session::is_set('edit'))));
610     $smarty->assign("pwmode", $pwd_methods);
611     $smarty->assign("pwmode_select", $this->pw_storage);
612     $smarty->assign("pw_configurable", $is_configurable);
613     $smarty->assign("passwordStorageACL", $this->getacl("userPassword",(!is_object($this->parent) && !session::is_set('edit'))));
614     $smarty->assign("base_select",      $this->base);
616     if(!session::is_set('edit')){
617       $smarty->assign("CertificatesACL","");
618     }else{
619       $smarty->assign("CertificatesACL",  $this->getacl("Certificate"));
620     }
621     
622     $smarty->assign("userPictureACL",   $this->getacl("userPicture",(!is_object($this->parent) && !session::is_set('edit'))));
623     $smarty->assign("userPicture_is_readable",   $this->acl_is_readable("userPicture",(!is_object($this->parent) && !session::is_set('edit'))));
625     /* Create base acls */
626     $tmp = @$this->allowedBasesToMoveTo();
627     $smarty->assign("bases", $tmp);
629     /* Save government mode attributes */
630     if($this->governmentmode){
631       $smarty->assign("governmentmode", "true");
632       $ivbbmodes= array("nein", "ivbv", "testa", "ivbv,testa", "internet",
633           "internet,ivbv", "internet,testa", "internet,ivbv,testa");
634       $smarty->assign("ivbbmodes", $ivbbmodes);
635       foreach ($this->govattrs as $val){
636         $smarty->assign("$val", $this->$val);
637         $smarty->assign("$val"."ACL", $this->getacl($val,(!is_object($this->parent) && !session::is_set('edit'))));
638       }
639     } else {
640       $smarty->assign("governmentmode", "false");
641     }
643     /* Special mode for uid */
644     $uidACL= $this->getacl("uid",(!is_object($this->parent) && !session::is_set('edit')));
645     if (isset ($this->dn)){
646       if ($this->dn != "new"){
647         $uidACL= preg_replace("/w/","",$uidACL);
648       }
649     }  else {
650       $uidACL= preg_replace("/w/","",$uidACL);
651     }
652     
653     $smarty->assign("uidACL", $uidACL);
654     $smarty->assign("is_template", $this->is_template);
655     $smarty->assign("use_dob", $this->use_dob);
657     if (isset($this->parent)){
658       if (isset($this->parent->by_object['phoneAccount']) &&
659           $this->parent->by_object['phoneAccount']->is_account){
660         $smarty->assign("has_phoneaccount", "true");
661       } else {
662         $smarty->assign("has_phoneaccount", "false");
663       }
664     } else {
665       $smarty->assign("has_phoneaccount", "false");
666     }
667     $smarty->assign("multiple_support" , $this->multiple_support_active);
668     return($smarty->fetch (get_template_path('generic.tpl', TRUE, dirname(__FILE__))));
669   }
672   /* remove object from parent */
673   function remove_from_parent()
674   {
675     /* Only remove valid accounts */
676     if(!$this->initially_was_account) return;
678     /* Remove password extension */
679     $temp= passwordMethod::get_available_methods();
681     /* Remove password method from user account */
682     if(isset($temp[$this->pw_storage]) && class_available($temp[$this->pw_storage])){
683       $this->pwObject= new $temp[$this->pw_storage]($this->config,$this->dn);
684       $this->pwObject->remove_from_parent();
685     }
687     /* Remove user */
688     $ldap= $this->config->get_ldap_link();
689     $ldap->rmdir ($this->dn);
690     if (!$ldap->success()){
691       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
692     }
693   
694     new log("remove","users/".get_class($this),$this->dn,$this->attributes,$ldap->get_error());
695   
696     /* Delete references to groups */
697     $ldap->cd ($this->config->current['BASE']);
698     $ldap->search ("(&(objectClass=posixGroup)(memberUid=".$this->uid."))", array("uid"));
699     while ($ldap->fetch()){
700       $g= new group($this->config, $ldap->getDN());
701       $g->removeUser($this->uid);
702       $g->save ();
703     }
705     /* Delete references to object groups */
706     $ldap->cd ($this->config->current['BASE']);
707     $ldap->search ("(&(objectClass=gosaGroupOfNames)(member=".LDAP::prepare4filter($this->dn)."))", array("cn"));
708     while ($ldap->fetch()){
709       $og= new ogroup($this->config, $ldap->getDN());
710       unset($og->member[$this->dn]);
711       $og->member= array_values($og->member);
712       $og->save ();
713     }
715     /* Delete references to roles */
716     $ldap->cd ($this->config->current['BASE']);
717     $ldap->search ("(&(objectClass=organizationalRole)(roleOccupant=".LDAP::prepare4filter($this->dn)."))", array("cn"));
718     while ($ldap->fetch()){
719       $role= new roleGeneric($this->config, $ldap->getDN());
720       $key = array_search($this->dn,$role->roleOccupant);
721       if($key !== FALSE){
722         unset($role->roleOccupant[$key]);
723         $role->roleOccupant= array_values($role->roleOccupant);
724         $role->save ();
725       }
726     }
728     /* If needed, let the password method do some cleanup */
729     $tmp = new passwordMethod($this->config);
730     $available = $tmp->get_available_methods();
731     if (in_array_ics($this->pw_storage, $available['name'])){
732       $test= new $available[$this->pw_storage]($this->config);
733       $test->attrs= $this->attrs;
734       $test->dn= $this->dn;
735       $test->remove_from_parent();
736     }
738     /* Remove ACL dependencies too */
739     acl::remove_acl_for($this->dn);
741     /* Optionally execute a command after we're done */
742     $this->handle_post_events("remove",array("uid" => $this->uid));
743   }
746   /* Save data to object */
747   function save_object()
748   {
749     if(isset($_POST['generic']) || isset($_POST['multiple_user_posted'])){
751       /* Make a backup of the current selected base */
752       $base_tmp = $this->base;
754       /* Parents save function */
755       plugin::save_object ();
757       /* Sync lists */
758       $this->gosaLoginRestrictionWidget->update();
759       if ($this->gosaLoginRestrictionWidget->isModified()) {
760         $this->gosaLoginRestriction= $this->gosaLoginRestrictionWidget->getMaintainedData();
761       }
763       /* Save government mode attributes */
764       if ($this->governmentmode){
765         foreach ($this->govattrs as $val){
766           if ($this->acl_is_writeable($val,(!is_object($this->parent) && !session::is_set('edit'))) && isset($_POST["$val"])){
767             $data= stripcslashes($_POST["$val"]);
768             if ($data != $this->$val){
769               $this->is_modified= TRUE;
770             }
771             $this->$val= $data;
772           }
773         }
774       }
776       /* In template mode, the uid is autogenerated... */
777       if ($this->is_template){
778         $this->uid= strtolower($this->sn);
779         $this->givenName= $this->sn;
780       }
782       /* Save base - its no no LDAP attribute */
783       if (isset($_POST['base'])){
784         $base= get_post('base');
785         if ($base != $this->base){
786           $tmp = $this->get_allowed_bases();
787           if(isset($tmp[$base])){
788             if ($base != $this->base){
789               $this->is_modified= TRUE;
790             }
791             $this->base= $base;
792           }else{
793             $this->base = $base_tmp;
794             msg_dialog::display(_("Error"), msgPool::permMove(), ERROR_DIALOG);
795           }
796         }
797       }
799       /* Get pw_storage mode */
800       if (isset($_POST['pw_storage'])){
801         foreach(array("pw_storage") as $val){
802           if(isset($_POST[$val])){
803             $data= validate($_POST[$val]);
804             if ($data != $this->$val){
805               $this->is_modified= TRUE;
806             }
807             $this->$val= $data;
808           }
809         }
810       }
812       if($this->pw_storage != $this->last_pw_storage && isset($_POST['pw_storage'])){
813         if ($this->acl_is_writeable("userPassword")){
814           $temp= passwordMethod::get_available_methods();
815           if (!is_object($this->pwObject) || !($this->pwObject instanceOf $temp[$this->pw_storage])){
816             foreach($temp as $id => $data){
817               if(isset($data['name']) && $data['name'] == $this->pw_storage && $data['is_configurable']){
818                 $this->pwObject= new $temp[$this->pw_storage]($this->config,$this->dn);
819                 break;
820               }
821             }
822           }
823         }
824       }
826       /* Save current cn
827        */
828       $this->cn = $this->givenName." ".$this->sn;
829     }
830   }
832   function rebind($ldap, $referral)
833   {
834     $credentials= LDAP::get_credentials($referral, $this->config->current['REFERRAL']);
835     if (ldap_bind($ldap, $credentials['ADMIN'], $credentials['PASSWORD'])) {
836       $this->error = "Success";
837       $this->hascon=true;
838       $this->reconnect= true;
839       return (0);
840     } else {
841       $this->error = "Could not bind to " . $credentials['ADMIN'];
842       return NULL;
843     }
844   }
846   
847   /* Save data to LDAP, depending on is_account we save or delete */
848   function save()
849   {
850     global $lang;
852     /* Only force save of changes .... 
853        If this attributes aren't changed, avoid saving.
854      */
855   
856     if($this->gender=="0") $this->gender ="";
857     if($this->preferredLanguage=="0") $this->preferredLanguage ="";
859     /* First use parents methods to do some basic fillup in $this->attrs */
860     plugin::save ();
862     if ($this->dateOfBirth != ""){
863       if(!is_array($this->attrs['dateOfBirth'])) {
864         #TODO: use $lang to convert date
865         list($day, $month, $year)= split("\.", $this->dateOfBirth);
866         $this->attrs['dateOfBirth'] = sprintf("%04d-%02d-%02d", $year, $month, $day);
867       }
868     }
870     /* Remove additional objectClasses */
871     $tmp= array();
872     foreach ($this->attrs['objectClass'] as $key => $set){
873       $found= false;
874       foreach (array("ivbbentry", "gosaUserTemplate") as $val){
875         if (preg_match ("/^$set$/i", $val)){
876           $found= true;
877           break;
878         }
879       }
880       if (!$found){
881         $tmp[]= $set;
882       }
883     }
885     /* Replace the objectClass array. This is done because of the
886        separation into government and normal mode. */
887     $this->attrs['objectClass']= $tmp;
889     /* Add objectClasss for template mode? */
890     if ($this->is_template){
891       $this->attrs['objectClass'][]= "gosaUserTemplate";
892     }
894     /* Hard coded government mode? */
895     if ($this->governmentmode){
896       $this->attrs['objectClass'][]= "ivbbentry";
898       /* Copy standard attributes */
899       foreach ($this->govattrs as $val){
900         if ($this->$val != ""){
901           $this->attrs["$val"]= $this->$val;
902         } elseif (!$this->is_new) {
903           $this->attrs["$val"]= array();
904         }
905       }
907       /* Remove attribute if set to "nein" */
908       if ($this->publicVisible == "nein"){
909         $this->attrs['publicVisible']= array();
910         if($this->is_new){
911           unset($this->attrs['publicVisible']);
912         }else{
913           $this->attrs['publicVisible']=array();
914         }
916       }
918     }
920     /* Special handling for attribute userCertificate needed */
921     if ($this->userCertificate != ""){
922       $this->attrs["userCertificate;binary"]= $this->userCertificate;
923       $remove_userCertificate= false;
924     } else {
925       $remove_userCertificate= true;
926     }
928     /* Special handling for dateOfBirth value */
929     if ($this->dateOfBirth == ""){
930       if ($this->is_new) {
931         unset($this->attrs["dateOfBirth"]);
932       } else {
933         $this->attrs["dateOfBirth"]= array();
934       }
935     }
936     if (!$this->gender){
937       if ($this->is_new) {
938         unset($this->attrs["gender"]);
939       } else {
940         $this->attrs["gender"]= array();
941       }
942     }
943     if (!$this->preferredLanguage){
944       if ($this->is_new) {
945         unset($this->attrs["preferredLanguage"]);
946       } else {
947         $this->attrs["preferredLanguage"]= array();
948       }
949     }
951     /* Special handling for attribute jpegPhote needed, scale image via
952        image magick to 147x200 pixels and inject resulting data. */
953     if ($this->jpegPhoto == "*removed*"){
954     
955       /* Reset attribute to avoid writing *removed* as value */    
956       $this->attrs["jpegPhoto"] = array();
958     } else {
960       /* Fallback if there's no image magick inside PHP */
961       if (!function_exists("imagick_blob2image")){
962         /* Get temporary file name for conversation */
963         $fname = tempnam (TEMP_DIR, "GOsa");
964   
965         /* Open file and write out photoData */
966         $fp = fopen ($fname, "w");
967         fwrite ($fp, $this->photoData);
968         fclose ($fp);
970         /* Build conversation query. Filename is generated automatically, so
971            we do not need any special security checks. Exec command and save
972            output. For PHP safe mode, you'll need a configuration which respects
973            image magick as executable... */
974         $query= "convert -size 147x200 $fname -resize 147x200 +profile \"*\" -";
975         @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
976             $query, "Execute");
977   
978         /* Read data written by convert */
979         $output= "";
980         $sh= popen($query, 'r');
981         while (!feof($sh)){
982           $output.= fread($sh, 4096);
983         }
984         pclose($sh);
986         unlink($fname);
988         /* Save attribute */
989         $this->attrs["jpegPhoto"] = $output;
991       } else {
993         /* Load the new uploaded Photo */
994         if(!$handle  =  imagick_blob2image($this->photoData))  {
995           new log("debug","users/".get_class($this),$this->dn,array(),"Could not access uploaded image");
996         }
998         /* Resizing image to 147x200 and blur */
999         if(!imagick_resize($handle,147,200,IMAGICK_FILTER_GAUSSIAN,0)){
1000           new log("debug","users/".get_class($this),$this->dn,array(),"Could not resize uploaded image");
1001         }
1003         /* Converting image to JPEG */
1004         if(!imagick_convert($handle,"JPEG")) {
1005           new log("debug","users/".get_class($this),$this->dn,array(),"Could not convert uploaded image to jepg");
1006         }
1008         /* Creating binary Code for the Image */
1009         if(!$dump = imagick_image2blob($handle)){
1010           new log("debug","users/".get_class($this),$this->dn,array(),"Could not create new user image");
1011         }
1013         /* Sending Image */
1014         $output=  $dump;
1016         /* Save attribute */
1017         $this->attrs["jpegPhoto"] = $output;
1018       }
1020     }
1022     /* This only gets called when user is renaming himself */
1023     $ldap= $this->config->get_ldap_link();
1024     if ($this->dn != $this->new_dn){
1026       /* Write entry on new 'dn' */
1027       $this->update_acls($this->dn,$this->new_dn);
1028       $this->move($this->dn, $this->new_dn);
1030       /* Happen to use the new one */
1031       change_ui_dn($this->dn, $this->new_dn);
1032       $this->dn= $this->new_dn;
1033     }
1036     /* Save data. Using 'modify' implies that the entry is already present, use 'add' for
1037        new entries. So do a check first... */
1038     $ldap->cat ($this->dn, array('dn'));
1039     if ($ldap->fetch()){
1040       $mode= "modify";
1041     } else {
1042       $mode= "add";
1043       $ldap->cd($this->config->current['BASE']);
1044       $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
1045     }
1047     /* Set password to some junk stuff in case of templates */
1048     if ($this->is_template){
1049       $temp= passwordMethod::get_available_methods();
1050       foreach($temp as $id => $data){
1051         if(isset($data['name']) && $data['name'] == $this->pw_storage){
1052           $tmp = new  $temp[$this->pw_storage]($this->config,$this->dn);
1053           $tmp->set_hash($this->pw_storage);
1054           $this->attrs['userPassword'] = $tmp->create_template_hash($this->attrs);
1055           break;
1056         }
1057       }
1058     }
1060     @DEBUG (DEBUG_LDAP, __LINE__, __FUNCTION__, __FILE__,
1061         $this->attributes, "Save via $mode");
1063     /* Finally write data with selected 'mode' */
1064     $this->cleanup();
1066     /* Update current locale settings, if we have edited ourselves */
1067     $ui = session::get('ui');
1068     if(isset($this->attrs['preferredLanguage']) && $this->dn == $ui->dn){
1069       $ui->language = $this->preferredLanguage;
1070       session::set('ui',$ui);
1071       session::set('Last_init_lang',"update");
1072     }
1074     $ldap->cd ($this->dn);
1075     $ldap->$mode ($this->attrs);
1076     if (!$ldap->success()){
1077       msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
1078       return (1);
1079     }
1081     /* Remove ACL dependencies too */
1082     if($this->dn != $this->orig_dn && $this->orig_dn != "new"){
1083       $tmp = new acl($this->config,$this->parent,$this->dn);
1084       $tmp->update_acl_membership($this->orig_dn,$this->dn);
1085     }
1087     if($mode == "modify"){
1088       new log("modify","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1089     }else{
1090       new log("create","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
1091     }
1093     /* Remove cert? 
1094        For some reason, the 'ldap' class doesn't want to remove binary entries, so I need
1095        to work around myself. */
1096     if ($remove_userCertificate == true && !$this->is_new && $this->had_userCertificate){
1098       /* Reset array, assemble new, this should be reworked */
1099       $this->attrs= array();
1100       $this->attrs['userCertificate;binary']= array();
1102       /* Prepare connection */
1103       if (!($ds = ldap_connect($this->config->current['SERVER']))) {
1104         die ("Could not connect to LDAP server");
1105       }
1106       ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
1107       if (function_exists("ldap_set_rebind_proc") && $this->config->get_cfg_value("ldapFollowReferrals") == "true") {
1108         ldap_set_option($this->cid, LDAP_OPT_REFERRALS, 1);
1109         ldap_set_rebind_proc($ds, array(&$this, "rebind"));
1110       }
1111       if($this->config->get_cfg_value("ldapTLS") == "true"){
1112         ldap_start_tls($ds);
1113       }
1114       if (!($res = @ldap_bind($ds, $this->config->current['ADMIN'],
1115               $this->config->current['PASSWORD']))) {
1116         die ("Could not bind to LDAP");
1117       }
1119       /* Modify using attrs */
1120       ldap_mod_del($ds,$this->dn,$this->attrs);
1121       ldap_close($ds);
1122     }
1124     /* If needed, let the password method do some cleanup */
1125     if ($this->pw_storage != $this->last_pw_storage){
1126       $tmp = new passwordMethod($this->config);
1127       $available = $tmp->get_available_methods();
1128       if (in_array_ics($this->last_pw_storage, $available['name'])){
1129         $test= new $available[$this->last_pw_storage]($this->config,$this->dn);
1130         $test->attrs= $this->attrs;
1131         $test->remove_from_parent();
1132       }
1133     }
1135     /* Maybe the current password method want's to do some changes... */
1136     if (is_object($this->pwObject)){
1137       $this->pwObject->save($this->dn);
1138     }
1140     /* Optionally execute a command after we're done */
1141     if ($mode == "add"){
1142       $this->handle_post_events("add", array("uid" => $this->uid));
1143     } elseif ($this->is_modified){
1144       $this->handle_post_events("modify", array("uid" => $this->uid));
1145     }
1147     return (0);
1148   }
1151   function create_initial_rdn($pattern)
1152   {
1153     // Only generate single RDNs
1154     if (preg_match('/\+/', $pattern)){
1155       msg_dialog::display(_("Error"), _("Cannot build RDN: no + allowed to build sub RDN!"), ERROR_DIALOG);
1156       return "";
1157     }
1159     // Extract attribute
1160     $attribute= preg_replace('/=.*$/', '', $pattern);
1161     if (!in_array_ics($attribute, $this->attributes)) {
1162       msg_dialog::display(_("Error"), _("Cannot build RDN: attribute is not defined!"), ERROR_DIALOG);
1163       return "";
1164     }
1166     // Sort attributes for length
1167     $attrl= array();
1168     foreach ($this->attributes as $attr) {
1169       $attrl[$attr]= strlen($attr);
1170     }
1171     arsort($attrl);
1172     
1173     // Walk thru sorted attributes and replace them in pattern
1174     foreach ($attrl as $attr => $dummy) {
1175       if (!is_array($this->$attr)){
1176         $pattern= preg_replace("/%$attr/", $this->$attr, $pattern);
1177       } else {
1178         // Array elements cannot be used for ID generation
1179         if (preg_match("/%$attr/", $pattern)) {
1180           msg_dialog::display(_("Error"), _("Cannot build RDN: invalid attribute parameters!"), ERROR_DIALOG);
1181           break;
1182         }
1183       }
1184     }
1186     // Internally assign value
1187     $this->$attribute= preg_replace('/^[^=]+=/', '', $pattern);
1189     return $pattern;
1190   }
1192   
1193   function update_new_dn()
1194   {
1195     // Alternative way to handle DN
1196     $pattern= $this->config->get_cfg_value("accountRDN");
1197     if ($pattern != "") {
1198       $rdn= $this->create_initial_rdn($pattern);
1199       $attribute= preg_replace('/=.*$/', '', $rdn);
1200       $value= preg_replace('/^[^=]+=$/', '', $rdn);
1202       /* Don't touch dn, if $attribute hasn't changed */
1203       if (isset($this->saved_attributes[$attribute]) && $this->saved_attributes[$attribute] == $this->$attribute &&
1204             $this->orig_base == $this->base ){
1205         $this->new_dn= $this->dn;
1206       } else {
1207         $this->new_dn= $this->create_unique_dn2($rdn, get_people_ou().$this->base);
1208       }
1210     // Original way to handle DN
1211     } else {
1213       $pt= "";
1214       if($this->config->get_cfg_value("personalTitleInDN") == "true"){
1215         if(!empty($this->personalTitle)){
1216           $pt = $this->personalTitle." ";
1217         }
1218       }
1220       $this->cn= $pt.$this->givenName." ".$this->sn;
1222       /* Permissions for that base? */
1223       if ($this->config->get_cfg_value("accountPrimaryAttribute") == "uid"){
1224         $this->new_dn= 'uid='.$this->uid.','.get_people_ou().$this->base;
1225       } else {
1226         /* Don't touch dn, if cn hasn't changed */
1227         if (isset($this->saved_attributes['cn']) && $this->saved_attributes['cn'] == $this->cn &&
1228             $this->orig_base == $this->base ){
1229           $this->new_dn= $this->dn;
1230         } else {
1231           $this->new_dn= $this->create_unique_dn('cn', get_people_ou().$this->base);
1232         }
1233       }
1234     }
1235   }
1236   
1238   /* Check formular input */
1239   function check()
1240   {
1241     /* Call common method to give check the hook */
1242     $message= plugin::check();
1244     /* Configurable password methods should be configured initially. 
1245      */ 
1246     if($this->last_pw_storage != $this->pw_storage){
1247       $temp= passwordMethod::get_available_methods();
1248       foreach($temp['name'] as $id => $name){
1249         if($name == $this->pw_storage){
1250           if($temp['is_configurable'][$id] && !$this->pwObject instanceof $temp[$name] ){
1251             $message[] = _("The selected password method requires initial configuration!");
1252           }
1253           break;
1254         }
1255       }
1256     }
1258     $this->update_new_dn();
1260     /* Set the new acl base */
1261     if($this->dn == "new") {
1262       $this->set_acl_base($this->base);
1263     }
1265     /* Check if we are allowed to create/move this user */
1266     if($this->orig_dn == "new" && !$this->acl_is_createable($this->base)){
1267       $message[]= msgPool::permCreate();
1268     }elseif($this->orig_dn != "new" && $this->new_dn != $this->orig_dn && !$this->acl_is_moveable($this->base)){
1269       $message[]= msgPool::permMove();
1270     }
1272     /* UID already used? */
1273     $ldap= $this->config->get_ldap_link();
1274     $ldap->cd($this->config->current['BASE']);
1275     $ldap->search("(uid=$this->uid)", array("uid"));
1276     $ldap->fetch();
1277     if ($ldap->count() != 0 && $this->dn == 'new'){
1278       $message[]= msgPool::duplicated(_("Login"));
1279     }
1281     /* In template mode, the uid and givenName are autogenerated... */
1282     if ($this->sn == ""){
1283       $message[]= msgPool::required(_("Name"));
1284     }
1286     if (!$this->is_template){
1287       if ($this->givenName == ""){
1288         $message[]= msgPool::required(_("Given name"));
1289       }
1290       if ($this->uid == ""){
1291         $message[]= msgPool::required(_("Login"));
1292       }
1293       if ($this->config->get_cfg_value("accountPrimaryAttribute") != "uid"){
1294         $ldap->cat($this->new_dn);
1295         if ($ldap->count() != 0 && $this->dn != $this->new_dn && $this->dn == 'new'){
1296           $message[]= msgPool::duplicated(_("Name"));
1297         }
1298       }
1299     }
1301     /* Check for valid input */
1302     if ($this->is_modified && !tests::is_uid($this->uid)){
1304       if (strict_uid_mode()){
1305         $message[]= msgPool::invalid(_("Login"), $this->uid, "/[a-z0-9_-]/");
1306       } else {
1307         $message[]= msgPool::invalid(_("Login"), $this->uid, "/[a-z0-9_-]/i");
1308       }
1309     }
1310     if (!tests::is_url($this->labeledURI)){
1311       $message[]= msgPool::invalid(_("Homepage"), "", "", "http://www.your-domain.com/yourname");
1312     }
1314     /* Check phone numbers */
1315     if (!tests::is_phone_nr($this->telephoneNumber)){
1316       $message[]= msgPool::invalid(_("Phone"), $this->telephoneNumber, "/[\/0-9 ()+*-]/");
1317     }
1318     if (!tests::is_phone_nr($this->facsimileTelephoneNumber)){
1319       $message[]= msgPool::invalid(_("Fax"), $this->facsimileTelephoneNumber, "/[\/0-9 ()+*-]/");
1320     }
1321     if (!tests::is_phone_nr($this->mobile)){
1322       $message[]= msgPool::invalid(_("Mobile"), $this->mobile, "/[\/0-9 ()+*-]/");
1323     }
1324     if (!tests::is_phone_nr($this->pager)){
1325       $message[]= msgPool::invalid(_("Pager"), $this->pager, "/[\/0-9 ()+*-]/");
1326     }
1328     /* Check dates */
1329     if (!tests::is_date($this->dateOfBirth)){
1330       $message[]= msgPool::invalid(_("Date of birth"), $this->dateOfBirth,"" ,"23.02.2009");
1331     }
1333     /* Check for reserved characers */
1334     if (preg_match ('/[,+"?\'()=<>;\\\\]/', $this->givenName)){
1335       $message[]= msgPool::invalid(_("Given name"), $this->givenName, '/[^,+"?\'()=<>;\\\\]/');
1336     }
1337     if (preg_match ('/[,+"?\'()=<>;\\\\]/', $this->sn)){
1338       $message[]= msgPool::invalid(_("Name"), $this->sn, '/[^,+"?\'()=<>;\\\\]/');
1339     }
1341     return $message;
1342   }
1345   /* Indicate whether a password change is needed or not */
1346   function password_change_needed()
1347   {
1348     if(in_array("pw_storage",$this->multi_boxes)){
1349       return(TRUE);
1350     }
1351     return($this->pw_storage != $this->last_pw_storage && !$this->is_template);
1352   }
1355   /* Load a jpegPhoto from LDAP, this is going to be simplified later on */
1356   function load_picture()
1357   {
1358     $ldap = $this->config->get_ldap_link();
1359     $ldap->cd ($this->dn);
1360     $data = $ldap->get_attribute($this->dn,"jpegPhoto");
1362     if((!$data) || ($data == "*removed*")){ 
1364       /* In case we don't get an entry, load a default picture */
1365       $this->set_picture ();
1366       $this->jpegPhoto= "*removed*";
1367     }else{
1369       /* Set picture */
1370       $this->photoData= $data;
1371       session::set('binary',$this->photoData);
1372       session::set('binarytype',"image/jpeg");
1373       $this->jpegPhoto= "";
1374     }
1375   }
1378   /* Load a certificate from LDAP, this is going to be simplified later on */
1379   function load_cert()
1380   {
1381     $ds= ldap_connect($this->config->current['SERVER']);
1382     ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
1383     if (function_exists("ldap_set_rebind_proc") && $this->config->get_cfg_value("ldapFollowReferrals") == "true"){
1384       ldap_set_option($this->cid, LDAP_OPT_REFERRALS, 1);
1385       ldap_set_rebind_proc($ds, array(&$this, "rebind"));
1386     }
1387     if ($this->config->get_cfg_value("ldapTLS") == "true"){
1388       ldap_start_tls($ds);
1389     }
1391     $r= ldap_bind($ds);
1392     $sr= @ldap_read($ds, $this->dn, "userCertificate=*", array("userCertificate"));
1394     if ($sr) {
1395       $ei= @ldap_first_entry($ds, $sr);
1396       
1397       if ($ei) {
1398         if (!$info = @ldap_get_values_len($ds, $ei, "userCertificate;binary")){
1399           $this->userCertificate= "";
1400         } else {
1401           $this->userCertificate= $info[0];
1402         }
1403       }
1404     } else {
1405       $this->userCertificate= "";
1406     }
1408     ldap_unbind($ds);
1409   }
1412   /* Load picture from file to object */
1413   function set_picture($filename ="")
1414   {
1415     if (!is_file($filename) || $filename =="" ){
1416       $filename= "./plugins/users/images/default.jpg";
1417       $this->jpegPhoto= "*removed*";
1418     }
1420     $fd = fopen ($filename, "rb");
1421     $this->photoData= fread ($fd, filesize ($filename));
1422     session::set('binary',$this->photoData);
1423     session::set('binarytype',"image/jpeg");
1424     $this->jpegPhoto= "";
1426     fclose ($fd);
1427   }
1430   /* Load certificate from file to object */
1431   function set_cert($cert, $filename)
1432   {
1433     if(!$this->acl_is_writeable("Certificate",(!is_object($this->parent) && !session::is_set('edit')))) return;
1434     $fd = fopen ($filename, "rb");
1435     if (filesize($filename)>0) {
1436       $this->$cert= fread ($fd, filesize ($filename));
1437       fclose ($fd);
1438       $this->is_modified= TRUE;
1439     } else {
1440       msg_dialog::display(_("Error"), _("Cannot open certificate!"), ERROR_DIALOG);
1441     }
1442   }
1444   /* Adapt from given 'dn' */
1445   function adapt_from_template($dn, $skip= array())
1446   {
1447     plugin::adapt_from_template($dn, $skip);
1449     /* Get password method from template 
1450      */
1451     $tmp= passwordMethod::get_method($this->attrs['userPassword'][0]);
1452     if(is_object($tmp)){
1453       if($tmp->is_configurable()){
1454         $tmp->adapt_from_template($dn);
1455         $this->pwObject = &$tmp;
1456       }
1457       $this->pw_storage= $tmp->get_hash();
1458     }
1460     /* Get base */
1461     $this->base= preg_replace('/^[^,]+,'.preg_quote(get_people_ou(), '/').'/i', '', $dn);
1463     if($this->governmentmode){
1465       /* Walk through govattrs */
1466       foreach ($this->govattrs as $val){
1468         if (in_array($val, $skip)){
1469           continue;
1470         }
1472         if (isset($this->attrs["$val"][0])){
1474           /* If attribute is set, replace dynamic parts: 
1475              %sn, %givenName and %uid. Fill these in our local variables. */
1476           $value= $this->attrs["$val"][0];
1478           foreach (array("sn", "givenName", "uid") as $repl){
1479             if (preg_match("/%$repl/i", $value)){
1480               $value= preg_replace ("/%$repl/i",
1481                   $this->parent->$repl, $value);
1482             }
1483           }
1484           $this->$val= $value;
1485         }
1486       }
1487     }
1489     /* Get back uid/sn/givenName - only write if nothing's skipped */
1490     if ($this->parent !== NULL && count($skip) == 0){
1491       $this->uid= $this->parent->uid;
1492       $this->sn= $this->parent->sn;
1493       $this->givenName= $this->parent->givenName;
1494     }
1495   }
1497  
1498   /* This avoids that users move themselves out of their rights. 
1499    */
1500   function allowedBasesToMoveTo()
1501   {
1502     /* Get bases */
1503     $bases  = $this->get_allowed_bases();
1504     return($bases);
1505   } 
1508   function getCopyDialog()
1509   {
1510     $str = "";
1512     session::set('binary',$this->photoData); 
1513     session::set('binarytype',"image/jpeg");
1515     /* Get random number for pictures */
1516     srand((double)microtime()*1000000); 
1517     $rand = rand(0, 10000);
1519     $smarty = get_smarty();
1521     $smarty->assign("passwordTodo","clear");
1523     if(isset($_POST['passwordTodo'])){
1524       $smarty->assign("passwordTodo",$_POST['passwordTodo']);
1525     }
1527     $smarty->assign("sn",       $this->sn);
1528     $smarty->assign("givenName",$this->givenName);
1529     $smarty->assign("uid",      $this->uid);
1530     $smarty->assign("rand",     $rand);
1531     $str = $smarty->fetch(get_template_path("paste_generic.tpl",TRUE,dirname(__FILE__)));
1534     $ret = array();
1535     $ret['string'] = $str;
1536     $ret['status'] = "";  
1537     return($ret);
1538   }
1540   function saveCopyDialog()
1541   {
1542     /* Set_acl_base */
1543     $this->set_acl_base($this->base);
1545     if((isset($_FILES['picture_file']['tmp_name'])) && ($_FILES['picture_file']['size'] > 0)){
1546       $this->set_picture($_FILES['picture_file']['tmp_name']);
1547     }
1549     /* Remove picture? */
1550     if (isset($_POST['picture_remove'])){
1551       $this->jpegPhoto= "*removed*";
1552       $this->set_picture ("./plugins/users/images/default.jpg");
1553       $this->is_modified= TRUE;
1554     }
1556     $attrs = array("uid","givenName","sn");
1557     foreach($attrs as $attr){
1558       if(isset($_POST[$attr])){
1559         $this->$attr = $_POST[$attr];
1560       }
1561     } 
1562   }
1565   function PrepareForCopyPaste($source)
1566   {
1567     plugin::PrepareForCopyPaste($source);
1569     /* Reset certificate information addepted from source user
1570        to avoid setting the same user certificate for the destination user. */
1571     $this->userPKCS12= "";
1572     $this->userSMIMECertificate= "";
1573     $this->userCertificate= "";
1574     $this->certificateSerialNumber= "";
1575     $this->old_certificateSerialNumber= "";
1576     $this->old_userPKCS12= "";
1577     $this->old_userSMIMECertificate= "";
1578     $this->old_userCertificate= "";
1579   }
1582   static function plInfo()
1583   {
1584   
1585     $govattrs= array(
1586         "gouvernmentOrganizationalUnit"             =>  _("Unit"), 
1587         "houseIdentifier"                           =>  _("House identifier"), 
1588         "vocation"                                  =>  _("Vocation"),
1589         "ivbbLastDeliveryCollective"                =>  _("Last delivery"), 
1590         "gouvernmentOrganizationalPersonLocality"   =>  _("Person locality"),
1591         "gouvernmentOrganizationalUnitDescription"  =>  _("Unit description"),
1592         "gouvernmentOrganizationalUnitSubjectArea"  =>  _("Subject area"),
1593         "functionalTitle"                           =>  _("Functional title"),
1594         "certificateSerialNumber"                   =>  _("Certificate serial number"),
1595         "publicVisible"                             =>  _("Public visible"),
1596         "street"                                    =>  _("Street"),
1597         "role"                                      =>  _("Role"),
1598         "postalCode"                                =>  _("Postal code"));
1600     $ret = array(
1601         "plShortName" => _("Generic"),
1602         "plDescription" => _("Generic user settings"),
1603         "plSelfModify"  => TRUE,
1604         "plDepends"     => array(),
1605         "plPriority"    => 1,
1606         "plSection"     => array("personal" => _("My account")),
1607         "plCategory"    => array("users" => array("description" => _("Users"),
1608                                                   "objectClass" => "gosaAccount")),
1610         "plProvidedAcls" => array(
1612           "sn"                => _("Surname"),
1613           "givenName"         => _("Given name"),
1614           "uid"               => _("User identification"),
1615           "personalTitle"     => _("Personal title"),
1616           "academicTitle"     => _("Academic title"),
1618           "dateOfBirth"       => _("Date of birth"),
1619           "gender"            => _("Sex"),
1620           "preferredLanguage" => _("Preferred language"),
1621           "base"              => _("Base"), 
1623           "userPicture"       => _("User picture"),
1625           "o"                 => _("Organization"),
1626           "ou"                => _("Department"),
1627           "departmentNumber"  => _("Department number"),
1628           "employeeNumber"    => _("Employee number"),
1629           "employeeType"      => _("Employee type"),
1631           "roomNumber"        => _("Room number"),
1632           "telephoneNumber"   => _("Telefon number"),
1633           "pager"             => _("Pager number"),
1634           "mobile"            => _("Mobile number"),
1635           "facsimileTelephoneNumber"     => _("Fax number"),
1637           "st"                => _("State"),
1638           "l"                 => _("Location"),
1639           "postalAddress"     => _("Postal address"),
1641           "homePostalAddress" => _("Home postal address"),
1642           "homePhone"         => _("Home phone number"),
1643           "labeledURI"        => _("Homepage"),
1644           "userPassword"      => _("User password method"), 
1645           "Certificate"       => _("User certificates"))
1647         );
1649     /* Append government attributes if required */
1650     global $config;
1651     if($config->get_cfg_value("honourIvbbAttributes") == "true"){
1652       foreach($govattrs as $attr => $desc){
1653         $ret["plProvidedAcls"][$attr] = $desc;
1654       }
1655     }
1656     return($ret);
1657   }
1659   function get_multi_edit_values()
1660   {
1661     $ret = plugin::get_multi_edit_values();
1662     if(in_array("pw_storage",$this->multi_boxes)){
1663       $ret['pw_storage'] = $this->pw_storage;
1664     }
1665     if(in_array("edit_picture",$this->multi_boxes)){
1666       $ret['jpegPhoto'] = $this->jpegPhoto;
1667       $ret['photoData'] = $this->photoData;
1668       $ret['old_jpegPhoto'] = $this->old_jpegPhoto;
1669       $ret['old_photoData'] = $this->old_photoData;
1670     }
1671     if(isset($ret['dateOfBirth'])){
1672       unset($ret['dateOfBirth']);
1673     }
1674     if(isset($ret['cn'])){
1675       unset($ret['cn']);
1676     }
1677     $ret['is_modified'] = $this->is_modified;
1678     if(in_array("base",$this->multi_boxes)){
1679       $ret['orig_base']="Changed_by_Multi_Plug";
1680       $ret['base']=$this->base;
1681     }
1682     return($ret); 
1683   }
1686   function multiple_save_object()
1687   {
1688     plugin::multiple_save_object();
1690     /* Get pw_storage mode */
1691     if (isset($_POST['pw_storage'])){
1692       foreach(array("pw_storage") as $val){
1693         if(isset($_POST[$val])){
1694           $data= validate(get_post($val));
1695           if ($data != $this->$val){
1696             $this->is_modified= TRUE;
1697           }
1698           $this->$val= $data;
1699         }
1700       }
1701     }
1702     if(isset($_POST['base'])){
1703       $this->base = get_post('base');
1704     }
1706     if(isset($_POST['user_mulitple_edit'])){
1707       foreach(array("base","pw_storage","edit_picture") as $val){
1708         if(isset($_POST["use_".$val])){
1709           $this->multi_boxes[] = $val;
1710         }
1711       }
1712     }
1713   }
1715   
1716   function multiple_check()
1717   {
1718     /* Call check() to set new_dn correctly ... */
1719     $message = plugin::multiple_check();
1721     /* Set the new acl base */
1722     if($this->dn == "new") {
1723       $this->set_acl_base($this->base);
1724     }
1725     if (!tests::is_url($this->labeledURI) && in_array("labeledURI",$this->multi_boxes)){
1726       $message[]= msgPool::invalid(_("Homepage"));
1727     }
1728     if (!tests::is_phone_nr($this->telephoneNumber) && in_array("telephoneNumber",$this->multi_boxes)){
1729       $message[]= msgPool::invalid(_("Phone"), $this->telephoneNumber, "/[\/0-9 ()+*-]/");
1730     }
1731     if (!tests::is_phone_nr($this->facsimileTelephoneNumber) &&  in_array("facsimileTelephoneNumber",$this->multi_boxes)){
1732       $message[]= msgPool::invalid(_("Fax"), $this->facsimileTelephoneNumber, "/[\/0-9 ()+*-]/");
1733     }
1734     if (!tests::is_phone_nr($this->mobile) && in_array("mobile",$this->multi_boxes)){
1735       $message[]= msgPool::invalid(_("Mobile"), $this->mobile, "/[\/0-9 ()+*-]/");
1736     }
1737     if (!tests::is_phone_nr($this->pager) && in_array("pager",$this->multi_boxes)){
1738       $message[]= msgPool::invalid(_("Pager"), $this->pager, "/[\/0-9 ()+*-]/");
1739     }
1740     if (preg_match ('/[,+"?\'()=<>;\\\\]/', $this->givenName) && in_array("givenName",$this->multi_boxes)){
1741       $message[]= msgPool::invalid(_("Given name"), $this->giveName, '/[^,+"?\'()=<>;\\\\]/');
1742     }
1743     if (preg_match ('/[,+"?\'()=<>;\\\\]/', $this->sn) && in_array("sn",$this->multi_boxes)){
1744       $message[]= msgPool::invalid(_("Name"), $this->sn, '/[^,+"?\'()=<>;\\\\]/');
1745     }
1746     return($message);
1747   }
1751   function multiple_execute()
1752   {
1753     return($this->execute());
1754   }
1759 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1760 ?>