Code

Updated tagging
[gosa.git] / gosa-core / plugins / personal / generic / class_user.inc
1 <?php
2 /*!
3   \brief   user plugin
4   \author  Cajus Pollmeier <pollmeier@gonicus.de>
5   \version 2.00
6   \date    24.07.2003
8   This class provides the functionality to read and write all attributes
9   relevant for person, organizationalPerson, inetOrgPerson and gosaAccount
10   from/to the LDAP. It does syntax checking and displays the formulars required.
11  */
13 class user extends plugin
14 {
15   /* Definitions */
16   var $plHeadline= "Generic";
17   var $plDescription= "This does something";
19   /* Plugin specific values */
20   var $base= "";
21   var $orig_base= "";
22   var $cn= "";
23   var $new_dn= "";
24   var $personalTitle= "";
25   var $academicTitle= "";
26   var $homePostalAddress= "";
27   var $homePhone= "";
28   var $labeledURI= "";
29   var $o= "";
30   var $ou= "";
31   var $departmentNumber= "";
32   var $employeeNumber= "";
33   var $employeeType= "";
34   var $roomNumber= "";
35   var $telephoneNumber= "";
36   var $facsimileTelephoneNumber= "";
37   var $mobile= "";
38   var $pager= "";
39   var $l= "";
40   var $st= "";
41   var $postalAddress= "";
42   var $dateOfBirth;
43   var $use_dob= "0";
44   var $gender="0";
45   var $preferredLanguage="0";
47   var $jpegPhoto= "*removed*";
48   var $photoData= "";
49   var $old_jpegPhoto= "";
50   var $old_photoData= "";
51   var $cert_dialog= FALSE;
52   var $picture_dialog= FALSE;
53   var $pwObject= NULL;
55   var $userPKCS12= "";
56   var $userSMIMECertificate= "";
57   var $userCertificate= "";
58   var $certificateSerialNumber= "";
59   var $old_certificateSerialNumber= "";
60   var $old_userPKCS12= "";
61   var $old_userSMIMECertificate= "";
62   var $old_userCertificate= "";
64   var $gouvernmentOrganizationalUnit= "";
65   var $houseIdentifier= "";
66   var $street= "";
67   var $postalCode= "";
68   var $vocation= "";
69   var $ivbbLastDeliveryCollective= "";
70   var $gouvernmentOrganizationalPersonLocality= "";
71   var $gouvernmentOrganizationalUnitDescription= "";
72   var $gouvernmentOrganizationalUnitSubjectArea= "";
73   var $functionalTitle= "";
74   var $role= "";
75   var $publicVisible= "";
77   var $orig_dn;
78   var $dialog;
80   /* variables to trigger password changes */
81   var $pw_storage= "crypt";
82   var $last_pw_storage= "unset";
83   var $had_userCertificate= FALSE;
85   var $view_logged = FALSE;
87   /* attribute list for save action */
88   var $attributes= array("sn", "givenName", "uid", "personalTitle", "academicTitle",
89       "homePostalAddress", "homePhone", "labeledURI", "ou", "o", "dateOfBirth", "gender","preferredLanguage",
90       "departmentNumber", "employeeNumber", "employeeType", "l", "st","jpegPhoto",
91       "roomNumber", "telephoneNumber", "mobile", "pager", "cn", "userPKCS12",
92       "postalAddress", "facsimileTelephoneNumber", "userSMIMECertificate");
94   var $objectclasses= array("top", "person", "organizationalPerson", "inetOrgPerson",
95       "gosaAccount");
97   /* attributes that are part of the government mode */
98   var $govattrs= array("gouvernmentOrganizationalUnit", "houseIdentifier", "vocation",
99       "ivbbLastDeliveryCollective", "gouvernmentOrganizationalPersonLocality",
100       "gouvernmentOrganizationalUnitDescription","gouvernmentOrganizationalUnitSubjectArea",
101       "functionalTitle", "certificateSerialNumber", "publicVisible", "street", "role",
102       "postalCode");
104   var $multiple_support = TRUE;
106   /* constructor, if 'dn' is set, the node loads the given
107      'dn' from LDAP */
108   function user (&$config, $dn= NULL)
109   {
110     $this->config= $config;
111     /* Configuration is fine, allways */
112     if ($this->config->current['GOVERNMENTMODE']){
113       $this->attributes=array_merge($this->attributes,$this->govattrs);
114     }
116     /* Load base attributes */
117     plugin::plugin ($config, $dn);
119     $this->orig_dn  = $this->dn;
120     $this->new_dn   = $dn;
122     if ($this->config->current['GOVERNMENTMODE']){
123       /* Fix public visible attribute if unset */
124       if (!isset($this->attrs['publicVisible'])){
125         $this->publicVisible == "nein";
126       }
127     }
129     /* Load government mode attributes */
130     if ($this->config->current['GOVERNMENTMODE']){
131       /* Copy all attributs */
132       foreach ($this->govattrs as $val){
133         if (isset($this->attrs["$val"][0])){
134           $this->$val= $this->attrs["$val"][0];
135         }
136       }
137     }
139     /* Create me for new accounts */
140     if ($dn == "new"){
141       $this->is_account= TRUE;
142     }
144     /* Make hash default to md5 if not set in config */
145     if (!isset($this->config->current['HASH'])){
146       $hash= "md5";
147     } else {
148       $hash= $this->config->current['HASH'];
149     }
151     /* Load data from LDAP? */
152     if ($dn !== NULL){
154       /* Do base conversation */
155       if ($this->dn == "new"){
156         $ui= get_userinfo();
157         $this->base= dn2base($ui->dn);
158       } else {
159         $this->base= dn2base($dn);
160       }
162       /* get password storage type */
163       if (isset ($this->attrs['userPassword'][0])){
164         /* Initialize local array */
165         $matches= array();
166         if (preg_match ("/^{([^}]+)}(.+)/", $this->attrs['userPassword'][0], $matches)){
167           $this->pw_storage= strtolower($matches[1]);
168         } else {
169           if ($this->attrs['userPassword'][0] != ""){
170             $this->pw_storage= "clear";
171           } else {
172             $this->pw_storage= $hash;
173           }
174         }
175       } else {
176         /* Preset with vaule from configuration */
177         $this->pw_storage= $hash;
178       }
180       /* Load extra attributes: certificate and picture */
181       $this->load_cert();
182       $this->load_picture();
183       if ($this->userCertificate != ""){
184         $this->had_userCertificate= TRUE;
185       }
186     }
188     /* Reset password storage indicator, used by password_change_needed() */
189     if ($dn == "new"){
190       $this->last_pw_storage= "unset";
191     } else {
192       $this->last_pw_storage= $this->pw_storage;
193     }
195     /* Generate dateOfBirth entry */
196     if (isset ($this->attrs['dateOfBirth'])){
197       /* This entry is ISO 8601 conform */
198       list($year, $month, $day)= split("-", $this->attrs['dateOfBirth'][0], 3);
199     
200       $this->dateOfBirth=array( 'mon'=> $month,"mday"=> $day,"year"=> $year);
201       $this->use_dob= "1";
202     } else {
203       $this->use_dob= "0";
204     }
206     /* Put gender attribute to upper case */
207     if (isset ($this->attrs['gender'])){
208       $this->gender= strtoupper($this->attrs['gender'][0]);
209     }
210  
211     $this->orig_base = $this->base;
212   }
217   /* execute generates the html output for this node */
218   function execute()
219   {
220     /* Call parent execute */
221     plugin::execute();
223     /* Log view */
224     if($this->is_account && !$this->view_logged){
225       $this->view_logged = TRUE;
226       new log("view","users/".get_class($this),$this->dn);
227     }
229     $smarty= get_smarty();
231     /* Fill calendar */
232     if ($this->dateOfBirth == "0"){
233       $date= getdate();
234     } else {
235       if(is_array($this->dateOfBirth)){
236         $date = $this->dateOfBirth;
237   
238         // Trigger on dates like 1985-04-01, getdate only understands timestamps
239       } else if (!empty($this->dateOfBirth) && !is_numeric($this->dateOfBirth)){
240         $date= getdate(strtotime($this->dateOfBirth));
242       } else {
243         $date = getdate($this->dateOfBirth);
244       }
245     }
247     $days= array();
248     for($d= 1; $d<32; $d++){
249       $days[$d]= $d;
250     }
251     $years= array();
253     if(($date['year']-100)<1901){
254       $start = 1901;
255     }else{
256       $start = $date['year']-100;
257     }
259     $end = $start +100;
260     
261     for($y= $start; $y<=$end; $y++){
262       $years[]= $y;
263     }
264     $years['-']= "-&nbsp;";
265     $months= array(_("January"), _("February"), _("March"), _("April"),
266         _("May"), _("June"), _("July"), _("August"), _("September"),
267         _("October"), _("November"), _("December"), '-' => '-&nbsp;');
268     $smarty->assign("day", $date["mday"]);
269     $smarty->assign("days", $days);
270     $smarty->assign("months", $months);
271     $smarty->assign("month", $date["mon"]-1);
272     $smarty->assign("years", $years);
273     $smarty->assign("year", $date["year"]);
275     /* Assign sex */
276     $sex= array(0 => "&nbsp;", "F" => _("female"), "M" => _("male"));
277     $smarty->assign("gender_list", $sex);
278     $language= array_merge(array(0 => "&nbsp;") ,get_languages(TRUE));
279     $smarty->assign("preferredLanguage_list", $language);
281     /* Get random number for pictures */
282     srand((double)microtime()*1000000); 
283     $smarty->assign("rand", rand(0, 10000));
286     /* Do we represent a valid gosaAccount? */
287     if (!$this->is_account){
288       echo "<img alt=\"\" src=\"images/stop.png\" align=\"middle\">&nbsp;<b>".
289         _("This account has no valid GOsa extensions.")."</b>";
290       return;
291     }
293     /* Base select dialog */
294     $once = true;
295     foreach($_POST as $name => $value){
296       if(preg_match("/^chooseBase/",$name) && $once){
297         $once = false;
298         $this->dialog = new baseSelectDialog($this->config,$this,$this->allowedBasesToMoveTo());
299         $this->dialog->setCurrentBase($this->base);
300       }
301     }
303     /* Password configure dialog handling */
304     if(is_object($this->pwObject) && $this->pwObject->display){
305       $output= $this->pwObject->configure();
306       if ($output != ""){
307         $this->dialog= TRUE;
308         return $output;
309       }
310       $this->dialog= false;
311     }
313     /* Dialog handling */
314     if(is_object($this->dialog)){
315       /* Must be called before save_object */
316       $this->dialog->save_object();
317    
318       if($this->dialog->isClosed()){
319         $this->dialog = false;
320       }elseif($this->dialog->isSelected()){
322         /* check if selected base is allowed to move to / create a new object */
323         $tmp = $this->get_allowed_bases();
324         if(isset($tmp[$this->dialog->isSelected()])){
325           $this->base = $this->dialog->isSelected();
326         }
327         $this->dialog= false;
328       }else{
329         return($this->dialog->execute());
330       }
331     }
333     /* Want password method editing? */
334     if ($this->acl_is_writeable("userPassword")){
335       if (isset($_POST['edit_pw_method'])){
336         if (!is_object($this->pwObject) || $this->pw_storage != $this->pwObject->get_hash_name()){
337           $temp= passwordMethod::get_available_methods();
338           $this->pwObject= new $temp[$this->pw_storage]($this->config,$this->dn);
339         }
340         $this->pwObject->display = TRUE;
341         $this->dialog= TRUE;
342         return ($this->pwObject->configure());
343       }
344     }
346     /* Want picture edit dialog? */
347     if($this->acl_is_writeable("userPicture")) {
348       if (isset($_POST['edit_picture'])){
349         /* Save values for later recovery, in case some presses
350            the cancel button. */
351         $this->old_jpegPhoto= $this->jpegPhoto;
352         $this->old_photoData= $this->photoData;
353         $this->picture_dialog= TRUE;
354         $this->dialog= TRUE;
355       }
356     }
358     /* Remove picture? */
359     if($this->acl_is_writeable("userPicture",(!is_object($this->parent) && !session::is_set('edit'))) ){
360       if (isset($_POST['picture_remove'])){
361         $this->set_picture ();
362         $this->jpegPhoto= "*removed*";
363         $this->is_modified= TRUE;
364         return($smarty->fetch (get_template_path('generic_picture.tpl', TRUE, dirname(__FILE__))));
365       }
366     }
368     /* Save picture */
369     if (isset($_POST['picture_edit_finish'])){
371       /* Check for clean upload */
372       if ($_FILES['picture_file']['name'] != ""){
373         if (!is_uploaded_file($_FILES['picture_file']['tmp_name'])) {
374           msg_dialog::display(_("Error"), _("Cannot upload file!"), ERROR_DIALOG);
375         }else{
376           /* Activate new picture */
377           $this->set_picture($_FILES['picture_file']['tmp_name']);
378         }
379       }
380       $this->picture_dialog= FALSE;
381       $this->dialog= FALSE;
382       $this->is_modified= TRUE;
383     }
386     /* Cancel picture */
387     if (isset($_POST['picture_edit_cancel'])){
389       /* Restore values */
390       $this->jpegPhoto= $this->old_jpegPhoto;
391       $this->photoData= $this->old_photoData;
393       /* Update picture */
394       session::set('binary',$this->photoData);
395       session::set('binarytype',"image/jpeg");
396       $this->picture_dialog= FALSE;
397       $this->dialog= FALSE;
398     }
400     /* Toggle dateOfBirth information */
401     if (isset($_POST['set_dob'])){
402       $this->use_dob= ($this->use_dob == "0")?"1":"0";
403     }
406     /* Want certificate= */
407     if ((isset($_POST['edit_cert'])) && $this->acl_is_readable("Certificate")){
409       /* Save original values for later reconstruction */
410       foreach (array("certificateSerialNumber", "userCertificate",
411             "userSMIMECertificate", "userPKCS12") as $val){
413         $oval= "old_$val";
414         $this->$oval= $this->$val;
415       }
417       $this->cert_dialog= TRUE;
418       $this->dialog= TRUE;
419     }
422     /* Cancel certificate dialog */
423     if (isset($_POST['cert_edit_cancel'])){
425       /* Restore original values in case of 'cancel' */
426       foreach (array("certificateSerialNumber", "userCertificate",
427             "userSMIMECertificate", "userPKCS12") as $val){
429         $oval= "old_$val";
430         $this->$val= $this->$oval;
431       }
432       $this->cert_dialog= FALSE;
433       $this->dialog= FALSE;
434     }
437     /* Remove certificate? */
438     if($this->acl_is_writeable("Certificate",(!is_object($this->parent) && !session::is_set('edit')))){ 
439       foreach (array ("userCertificate", "userSMIMECertificate", "userPKCS12") as $val){
440         if (isset($_POST["remove_$val"])){
442           /* Reset specified cert*/
443           $this->$val= "";
444           $this->is_modified= TRUE;
445         }
446       }
447     }
449     /* Upload new cert and close dialog? */     
450     if($this->acl_is_writeable("Certificate",(!is_object($this->parent) && !session::is_set('edit')))){ 
451       if (isset($_POST['cert_edit_finish'])){
453         /* for all certificates do */
454         foreach (array ("userCertificate", "userSMIMECertificate", "userPKCS12")
455             as $val){
457           /* Check for clean upload */
458           if (array_key_exists($val."_file", $_FILES) &&
459               array_key_exists('name', $_FILES[$val."_file"]) &&
460               $_FILES[$val."_file"]['name'] != "" &&
461               is_uploaded_file($_FILES[$val."_file"]['tmp_name'])) {
462             $this->set_cert("$val", $_FILES[$val."_file"]['tmp_name']);
463           }
464         }
466         /* Save serial number */
467         if (isset($_POST["certificateSerialNumber"]) &&
468             $_POST["certificateSerialNumber"] != ""){
470           if (!tests::is_id($_POST["certificateSerialNumber"])){
471             msg_dialog::display(_("Error"), _("Please enter a valid serial number!"), ERROR_DIALOG);
473             foreach(array("userCertificate", "userSMIMECertificate", "userPKCS12") as $cert){
474               if ($this->$cert != ""){
475                 $smarty->assign("$cert"."_state", "true");
476               } else {
477                 $smarty->assign("$cert"."_state", "");
478               }
479             }
480             return ($smarty->fetch (get_template_path('generic_certs.tpl', TRUE, dirname(__FILE__))));
481           }
483           $this->certificateSerialNumber= $_POST["certificateSerialNumber"];
484           $this->is_modified= TRUE;
485         }
487         $this->cert_dialog= FALSE;
488         $this->dialog= FALSE;
489       }
490     }
491     /* Display picture dialog */
492     if ($this->picture_dialog){
493       return($smarty->fetch (get_template_path('generic_picture.tpl', TRUE, dirname(__FILE__))));
494     }
496     /* Display cert dialog */
497     if ($this->cert_dialog){
498       $smarty->assign("CertificateACL",$this->getacl("Certificate",(!is_object($this->parent) && !session::is_set('edit'))));
499       $smarty->assign("Certificate_readable",$this->acl_is_readable("Certificate"));
501       foreach(array("userCertificate", "userSMIMECertificate", "userPKCS12") as $cert){
502         if ($this->$cert != ""){
503           /* import certificate */
504           $certificate = new certificate;
505           $certificate->import($this->$cert);
506       
507           /* Read out data*/
508           $timeto   = $certificate->getvalidto_date();
509           $timefrom = $certificate->getvalidfrom_date();
510          
511           
512           /* Additional info if start end time is '0' */
513           $add_str_info = "";
514           if($timeto == 0 && $timefrom == 0){
515             $add_str_info = "<br><i>"._("(Some types of certificates are currently not supported and may be displayed as 'invalid'.)")."</i>";
516           }
518           $str = "<table summary=\"\" border=0>
519                     <tr>
520                       <td style='vertical-align:top'>CN</td>
521                       <td>".preg_replace("/ /", "&nbsp;", $certificate->getname())."</td>
522                     </tr>
523                   </table><br>".
525                   sprintf(_("Certificate is valid from %s to %s and is currently %s."),
526                         "<b>".date('d M Y',$timefrom)."</b>",
527                         "<b>".date('d M Y',$timeto)."</b>",
528                         $certificate->isvalid()?"<b><font style='color:green'>"._("valid")."</font></b>":
529                                                 "<b><font style='color:red'>"._("invalid")."</font></b>").$add_str_info;
531           $smarty->assign($cert."info",$str);
532           $smarty->assign($cert."_state","true");
533         } else {
534           $smarty->assign($cert."info", "<i>"._("No certificate installed")."</i>");
535           $smarty->assign($cert."_state","");
536         }
537       }
538       $smarty->assign("governmentmode", "false");
539       return($smarty->fetch (get_template_path('generic_certs.tpl', TRUE, dirname(__FILE__))));
540     }
542     /* Prepare password hashes */
543     if ($this->pw_storage == ""){
544       $this->pw_storage= $this->config->current['HASH'];
545     }
547     $temp= passwordMethod::get_available_methods();
548     $is_configurable= FALSE;
549     $hashes = $temp['name'];
550     if(isset($temp[$this->pw_storage])){
551       $test= new $temp[$this->pw_storage]($this->config);
552       $is_configurable= $test->is_configurable();
553     }else{
554       new msg_dialog(_("Password method"),_("The selected password method is no longer available."),WARNING_DIALOG);
555     }
556     
557     /* Load attributes and acl's */
558     $ui =get_userinfo();
559     foreach($this->attributes as $val){
560       $smarty->assign("$val", $this->$val);
561       if(in_array($val,$this->multi_boxes)){
562         $smarty->assign("use_".$val,TRUE);
563       }else{
564         $smarty->assign("use_".$val,FALSE);
565       }
566     }
567     foreach(array("base","pw_storage","edit_picture") as $val){
568       if(in_array($val,$this->multi_boxes)){
569         $smarty->assign("use_".$val,TRUE);
570       }else{
571         $smarty->assign("use_".$val,FALSE);
572       }
573     }
575     /* Set acls */
576     $tmp = $this->plinfo();
577     foreach($tmp['plProvidedAcls'] as $val => $translation){
578       $smarty->assign("$val"."ACL", $this->getacl($val,(!is_object($this->parent) && !session::is_set('edit'))));
579     }
581     $smarty->assign("pwmode", $hashes);
582     $smarty->assign("pwmode_select", $this->pw_storage);
583     $smarty->assign("pw_configurable", $is_configurable);
584     $smarty->assign("passwordStorageACL", $this->getacl("userPassword",(!is_object($this->parent) && !session::is_set('edit'))));
585     $smarty->assign("base_select",      $this->base);
586     $smarty->assign("CertificatesACL",  $this->getacl("Certificate",(!is_object($this->parent) && !session::is_set('edit'))));
587     $smarty->assign("userPictureACL",   $this->getacl("userPicture",(!is_object($this->parent) && !session::is_set('edit'))));
588     $smarty->assign("userPicture_is_readable",   $this->acl_is_readable("userPicture",(!is_object($this->parent) && !session::is_set('edit'))));
590     /* Create base acls */
591     $tmp = @$this->allowedBasesToMoveTo();
592     $smarty->assign("bases", $tmp);
594     /* Save government mode attributes */
595     if (isset($this->config->current['GOVERNMENTMODE']) &&
596         preg_match('/true/i', $this->config->current['GOVERNMENTMODE'])){
597       $smarty->assign("governmentmode", "true");
598       $ivbbmodes= array("nein", "ivbv", "testa", "ivbv,testa", "internet",
599           "internet,ivbv", "internet,testa", "internet,ivbv,testa");
600       $smarty->assign("ivbbmodes", $ivbbmodes);
601       foreach ($this->govattrs as $val){
602         $smarty->assign("$val", $this->$val);
603         $smarty->assign("$val"."ACL", $this->getacl($val,(!is_object($this->parent) && !session::is_set('edit'))));
604       }
605     } else {
606       $smarty->assign("governmentmode", "false");
607     }
609     /* Special mode for uid */
610     $uidACL= $this->getacl("uid",(!is_object($this->parent) && !session::is_set('edit')));
611     if (isset ($this->dn)){
612       if ($this->dn != "new"){
613         $uidACL= preg_replace("/w/","",$uidACL);
614       }
615     }  else {
616       $uidACL= preg_replace("/w/","",$uidACL);
617     }
618     
619     $smarty->assign("uidACL", $uidACL);
620     $smarty->assign("is_template", $this->is_template);
621     $smarty->assign("use_dob", $this->use_dob);
623     if (isset($this->parent)){
624       if (isset($this->parent->by_object['phoneAccount']) &&
625           $this->parent->by_object['phoneAccount']->is_account){
626         $smarty->assign("has_phoneaccount", "true");
627       } else {
628         $smarty->assign("has_phoneaccount", "false");
629       }
630     } else {
631       $smarty->assign("has_phoneaccount", "false");
632     }
633     $smarty->assign("multiple_support" , $this->multiple_support_active);
634     return($smarty->fetch (get_template_path('generic.tpl', TRUE, dirname(__FILE__))));
635   }
638   /* remove object from parent */
639   function remove_from_parent()
640   {
641     /* Remove password extension */
642     $temp= passwordMethod::get_available_methods();
643     $this->pwObject= new $temp[$this->pw_storage]($this->config,$this->dn);
644     $this->pwObject->remove_from_parent();
646     /* Remove user */
647     $ldap= $this->config->get_ldap_link();
648     $ldap->rmdir ($this->dn);
649     show_ldap_error($ldap->get_error(), sprintf(_("Removing of user/generic account with dn '%s' failed."),$this->dn));
650   
651     new log("remove","users/".get_class($this),$this->dn,$this->attributes,$ldap->get_error());
652   
653     /* Delete references to groups */
654     $ldap->cd ($this->config->current['BASE']);
655     $ldap->search ("(&(objectClass=posixGroup)(memberUid=".$this->uid."))", array("uid"));
656     while ($ldap->fetch()){
657       $g= new group($this->config, $ldap->getDN());
658       $g->removeUser($this->uid);
659       $g->save ();
660     }
662     /* Delete references to object groups */
663     $ldap->cd ($this->config->current['BASE']);
664     $ldap->search ("(&(objectClass=gosaGroupOfNames)(member=".LDAP::preapre4filter($this->dn)."))", array("cn"));
665     while ($ldap->fetch()){
666       $og= new ogroup($this->config, $ldap->getDN());
667       unset($og->member[$this->dn]);
668       $og->save ();
669     }
671     /* If needed, let the password method do some cleanup */
672     $tmp = new passwordMethod($this->config);
673     $available = $tmp->get_available_methods();
674     if (in_array_ics($this->pw_storage, $available['name'])){
675       $test= new $available[$this->pw_storage]($this->config);
676       $test->attrs= $this->attrs;
677       $test->dn= $this->dn;
678       $test->remove_from_parent();
679     }
681     /* Remove ACL dependencies too */
682     $tmp = new acl($this->config,$this->parent,$this->dn);
683     $tmp->remove_acl();
685     /* Optionally execute a command after we're done */
686     $this->handle_post_events("remove",array("uid" => $this->uid));
687   }
690   /* Save data to object */
691   function save_object()
692   {
693     if(isset($_POST['generic']) || isset($_POST['multiple_user_posted'])){
695       /* Make a backup of the current selected base */
696       $base_tmp = $this->base;
698       /* Parents save function */
699       plugin::save_object ();
701       /* Save government mode attributes */
702       if ($this->config->current['GOVERNMENTMODE']){
703         foreach ($this->govattrs as $val){
704           if ($this->acl_is_writeable($val,(!is_object($this->parent) && !session::is_set('edit'))) && isset($_POST["$val"])){
705             $data= stripcslashes($_POST["$val"]);
706             if ($data != $this->$val){
707               $this->is_modified= TRUE;
708             }
709             $this->$val= $data;
710           }
711         }
712       }
714       /* In template mode, the uid is autogenerated... */
715       if ($this->is_template){
716         $this->uid= strtolower($this->sn);
717         $this->givenName= $this->sn;
718       }
720       /* Save base and pw_storage, since these are no LDAP attributes */
721       if (isset($_POST['base'])){
723         $tmp = $this->get_allowed_bases();
724         if(isset($tmp[$_POST['base']])){
725           $base= validate($_POST['base']);
726           if ($base != $this->base){
727             $this->is_modified= TRUE;
728           }
729           $this->base= $base;
730         }else{
731           $this->base = $base_tmp;
732           msg_dialog::display(_("Error"), sprintf(_("You have no permission to move this object to '%s'!"), LDAP::fix($_POST['base'])), ERROR_DIALOG);
733           $this->set_acl_base('dummy,'.$this->base);
734         }
735       }
737       /* Get pw_storage mode */
738       if (isset($_POST['pw_storage'])){
739         foreach(array("pw_storage") as $val){
740           if(isset($_POST[$val])){
741             $data= validate($_POST[$val]);
742             if ($data != $this->$val){
743               $this->is_modified= TRUE;
744             }
745             $this->$val= $data;
746           }
747         }
748       }
750       $this->set_acl_base('dummy,'.$this->base);
751     }
752   }
754   function rebind($ldap, $referral)
755   {
756     $credentials= LDAP::get_credentials($referral, $this->config->current['REFERRAL']);
757     if (ldap_bind($ldap, $credentials['ADMIN'], $credentials['PASSWORD'])) {
758       $this->error = "Success";
759       $this->hascon=true;
760       $this->reconnect= true;
761       return (0);
762     } else {
763       $this->error = "Could not bind to " . $credentials['ADMIN'];
764       return NULL;
765     }
766   }
768   
769   /* Save data to LDAP, depending on is_account we save or delete */
770   function save()
771   {
772     /* Only force save of changes .... 
773        If this attributes aren't changed, avoid saving.
774      */
775     if($this->gender=="0") $this->gender ="";
776     if($this->preferredLanguage=="0") $this->preferredLanguage ="";
778     /* First use parents methods to do some basic fillup in $this->attrs */
779     plugin::save ();
781     if ($this->use_dob == "1"){
782       /* If it is an array, the generic page has never been loaded - so there's no difference. Using an array would cause an error btw. */
783       if(!is_array($this->attrs['dateOfBirth'])) {
784         $this->attrs['dateOfBirth'] = date("Y-m-d", $this->dateOfBirth);
785       }
786     }
788     /* Remove additional objectClasses */
789     $tmp= array();
790     foreach ($this->attrs['objectClass'] as $key => $set){
791       $found= false;
792       foreach (array("ivbbentry", "gosaUserTemplate") as $val){
793         if (preg_match ("/^$set$/i", $val)){
794           $found= true;
795           break;
796         }
797       }
798       if (!$found){
799         $tmp[]= $set;
800       }
801     }
803     /* Replace the objectClass array. This is done because of the
804        separation into government and normal mode. */
805     $this->attrs['objectClass']= $tmp;
807     /* Add objectClasss for template mode? */
808     if ($this->is_template){
809       $this->attrs['objectClass'][]= "gosaUserTemplate";
810     }
812     /* Hard coded government mode? */
813     if ($this->config->current['GOVERNMENTMODE'] != 'false'){
814       $this->attrs['objectClass'][]= "ivbbentry";
816       /* Copy standard attributes */
817       foreach ($this->govattrs as $val){
818         if ($this->$val != ""){
819           $this->attrs["$val"]= $this->$val;
820         } elseif (!$this->is_new) {
821           $this->attrs["$val"]= array();
822         }
823       }
825       /* Remove attribute if set to "nein" */
826       if ($this->publicVisible == "nein"){
827         $this->attrs['publicVisible']= array();
828         if($this->is_new){
829           unset($this->attrs['publicVisible']);
830         }else{
831           $this->attrs['publicVisible']=array();
832         }
834       }
836     }
838     /* Special handling for attribute userCertificate needed */
839     if ($this->userCertificate != ""){
840       $this->attrs["userCertificate;binary"]= $this->userCertificate;
841       $remove_userCertificate= false;
842     } else {
843       $remove_userCertificate= true;
844     }
846     /* Special handling for dateOfBirth value */
847     if ($this->use_dob != "1"){
848       if ($this->is_new) {
849         unset($this->attrs["dateOfBirth"]);
850       } else {
851         $this->attrs["dateOfBirth"]= array();
852       }
853     }
854     if (!$this->gender){
855       if ($this->is_new) {
856         unset($this->attrs["gender"]);
857       } else {
858         $this->attrs["gender"]= array();
859       }
860     }
861     if (!$this->preferredLanguage){
862       if ($this->is_new) {
863         unset($this->attrs["preferredLanguage"]);
864       } else {
865         $this->attrs["preferredLanguage"]= array();
866       }
867     }
869     /* Special handling for attribute jpegPhote needed, scale image via
870        image magick to 147x200 pixels and inject resulting data. */
871     if ($this->jpegPhoto == "*removed*"){
872     
873       /* Reset attribute to avoid writing *removed* as value */    
874       $this->attrs["jpegPhoto"] = array();
876     } else {
878       /* Fallback if there's no image magick inside PHP */
879       if (!function_exists("imagick_blob2image")){
880         /* Get temporary file name for conversation */
881         $fname = tempnam ("/tmp", "GOsa");
882   
883         /* Open file and write out photoData */
884         $fp = fopen ($fname, "w");
885         fwrite ($fp, $this->photoData);
886         fclose ($fp);
888         /* Build conversation query. Filename is generated automatically, so
889            we do not need any special security checks. Exec command and save
890            output. For PHP safe mode, you'll need a configuration which respects
891            image magick as executable... */
892         $query= "convert -size 147x200 $fname -resize 147x200 +profile \"*\" -";
893         @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
894             $query, "Execute");
895   
896         /* Read data written by convert */
897         $output= "";
898         $sh= popen($query, 'r');
899         while (!feof($sh)){
900           $output.= fread($sh, 4096);
901         }
902         pclose($sh);
904         unlink($fname);
906         /* Save attribute */
907         $this->attrs["jpegPhoto"] = $output;
909       } else {
911         /* Load the new uploaded Photo */
912         if(!$handle  =  imagick_blob2image($this->photoData))  {
913           new log("debug","users/".get_class($this),$this->dn,array(),"Could not access uploaded image");
914         }
916         /* Resizing image to 147x200 and blur */
917         if(!imagick_resize($handle,147,200,IMAGICK_FILTER_GAUSSIAN,0)){
918           new log("debug","users/".get_class($this),$this->dn,array(),"Could not resize uploaded image");
919         }
921         /* Converting image to JPEG */
922         if(!imagick_convert($handle,"JPEG")) {
923           new log("debug","users/".get_class($this),$this->dn,array(),"Could not convert uploaded image to jepg");
924         }
926         /* Creating binary Code for the Image */
927         if(!$dump = imagick_image2blob($handle)){
928           new log("debug","users/".get_class($this),$this->dn,array(),"Could not create new user image");
929         }
931         /* Sending Image */
932         $output=  $dump;
934         /* Save attribute */
935         $this->attrs["jpegPhoto"] = $output;
936       }
938     }
940     /* This only gets called when user is renaming himself */
941     $ldap= $this->config->get_ldap_link();
942     if ($this->dn != $this->new_dn){
944       /* Write entry on new 'dn' */
945       $this->update_acls($this->dn,$this->new_dn);
946       $this->move($this->dn, $this->new_dn);
948       /* Happen to use the new one */
949       change_ui_dn($this->dn, $this->new_dn);
950       $this->dn= $this->new_dn;
951     }
954     /* Save data. Using 'modify' implies that the entry is already present, use 'add' for
955        new entries. So do a check first... */
956     $ldap->cat ($this->dn, array('dn'));
957     if ($ldap->fetch()){
958       $mode= "modify";
959     } else {
960       $mode= "add";
961       $ldap->cd($this->config->current['BASE']);
962       $ldap->create_missing_trees(preg_replace('/^[^,]+,/', '', $this->dn));
963     }
965     /* Set password to some junk stuff in case of templates */
966     if ($this->is_template){
967       $this->attrs['userPassword']= '{crypt}N0T$3T4N0W';
968     }
970     @DEBUG (DEBUG_LDAP, __LINE__, __FUNCTION__, __FILE__,
971         $this->attributes, "Save via $mode");
973     /* Finally write data with selected 'mode' */
974     $this->cleanup();
976     if(isset($this->attrs['preferredLanguage'])){
977       $ui = session::get('ui');
978       $ui->language = $this->preferredLanguage;
979       session::set('ui',$ui);
980       session::set('Last_init_lang',"update");
981     }
983     $ldap->cd ($this->dn);
984     $ldap->$mode ($this->attrs);
985     if (show_ldap_error($ldap->get_error(), sprintf(_("Saving of user/generic account with dn '%s' failed."),$this->dn))){
986       return (1);
987     }
989     /* Remove ACL dependencies too */
990     if($this->dn != $this->orig_dn && $this->orig_dn != "new"){
991       $tmp = new acl($this->config,$this->parent,$this->dn);
992       $tmp->update_acl_membership($this->orig_dn,$this->dn);
993     }
995     if($mode == "modify"){
996       new log("modify","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
997     }else{
998       new log("create","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
999     }
1001     /* Remove cert? 
1002        For some reason, the 'ldap' class doesn't want to remove binary entries, so I need
1003        to work around myself. */
1004     if ($remove_userCertificate == true && !$this->is_new && $this->had_userCertificate){
1006       /* Reset array, assemble new, this should be reworked */
1007       $this->attrs= array();
1008       $this->attrs['userCertificate;binary']= array();
1010       /* Prepare connection */
1011       if (!($ds = ldap_connect($this->config->current['SERVER']))) {
1012         die ("Could not connect to LDAP server");
1013       }
1014       ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
1015       if (function_exists("ldap_set_rebind_proc") && isset($this->config->current['RECURSIVE']) && $this->config->current['RECURSIVE'] == "true") {
1016         ldap_set_option($this->cid, LDAP_OPT_REFERRALS, 1);
1017         ldap_set_rebind_proc($ds, array(&$this, "rebind"));
1018       }
1019       if(isset($config->current['TLS']) && $config->current['TLS'] == "true"){
1020         ldap_start_tls($ds);
1021       }
1022       if (!($res = @ldap_bind($ds, $this->config->current['ADMIN'],
1023               $this->config->current['PASSWORD']))) {
1024         die ("Could not bind to LDAP");
1025       }
1027       /* Modify using attrs */
1028       ldap_mod_del($ds,$this->dn,$this->attrs);
1029       ldap_close($ds);
1030     }
1032     /* If needed, let the password method do some cleanup */
1033     if ($this->pw_storage != $this->last_pw_storage){
1034       $tmp = new passwordMethod($this->config);
1035       $available = $tmp->get_available_methods();
1036       if (in_array_ics($this->last_pw_storage, $available['name'])){
1037         $test= new $available[$this->last_pw_storage]($this->config,$this->dn);
1038         $test->attrs= $this->attrs;
1039         $test->remove_from_parent();
1040       }
1041     }
1043     /* Maybe the current password method want's to do some changes... */
1044     if (is_object($this->pwObject)){
1045       $this->pwObject->save($this->dn);
1046     }
1048     /* Optionally execute a command after we're done */
1049     if ($mode == "add"){
1050       $this->handle_post_events("add", array("uid" => $this->uid));
1051     } elseif ($this->is_modified){
1052       $this->handle_post_events("modify", array("uid" => $this->uid));
1053     }
1055     return (0);
1056   }
1058   
1059   function update_new_dn()
1060   {
1061     $pt= "";
1062     if(isset($this->config->current['INCLUDE_PERSONAL_TITLE']) && preg_match("/true/i",$this->config->current['INCLUDE_PERSONAL_TITLE'])){
1063       if(!empty($this->personalTitle)){
1064         $pt = $this->personalTitle." ";
1065       }
1066     }
1067     $this->cn= $pt.$this->givenName." ".$this->sn;
1069     /* Permissions for that base? */
1070     if (isset($this->config->current['DNMODE']) && $this->config->current['DNMODE'] == "uid"){
1071       $this->new_dn= 'uid='.$this->uid.','.get_people_ou().$this->base;
1072     } else {
1073       /* Don't touch dn, if cn hasn't changed */
1074       if (isset($this->saved_attributes['cn']) && $this->saved_attributes['cn'] == $this->cn &&
1075           $this->orig_base == $this->base ){
1076         $this->new_dn= $this->dn;
1077       } else {
1078         $this->new_dn= $this->create_unique_dn('cn', get_people_ou().$this->base);
1079       }
1080     }
1081   }
1082   
1084   /* Check formular input */
1085   function check()
1086   {
1087     /* Call common method to give check the hook */
1088     $message= plugin::check();
1090     $this->update_new_dn();
1092     /* Set the new acl base */
1093     if($this->dn == "new") {
1094       $this->set_acl_base($this->base);
1095     }
1097     /* UID already used? */
1098     $ldap= $this->config->get_ldap_link();
1099     $ldap->cd($this->config->current['BASE']);
1100     $ldap->search("(uid=$this->uid)", array("uid"));
1101     $ldap->fetch();
1102     if ($ldap->count() != 0 && $this->dn == 'new'){
1103       $message[]= _("There's already a person with this 'Login' in the database.");
1104     }
1106     /* In template mode, the uid and givenName are autogenerated... */
1107     if (!$this->is_template){
1108       if ($this->sn == ""){
1109         $message[]= _("The required field 'Name' is not set.");
1110       }
1111       if ($this->givenName == ""){
1112         $message[]= _("The required field 'Given name' is not set.");
1113       }
1114       if ($this->uid == ""){
1115         $message[]= _("The required field 'Login' is not set.");
1116       }
1117       if (!(isset($this->config->current['DNMODE']) && $this->config->current['DNMODE'] == "uid")){
1118         $ldap->cat($this->new_dn);
1119         if ($ldap->count() != 0 && $this->dn != $this->new_dn && $this->dn == 'new'){
1120           $message[]= _("There's already a person with this 'Name'/'Given name' combination in the database.");
1121         }
1122       }
1123     }
1125     /* Check for valid input */
1126     if ($this->is_modified && !tests::is_uid($this->uid)){
1127       $message[]= _("The field 'Login' contains invalid characters. Lowercase, numbers and dashes are allowed.");
1128     }
1129     if (!tests::is_url($this->labeledURI)){
1130       $message[]= _("The field 'Homepage' contains an invalid URL definition.");
1131     }
1132     if (preg_match ("/[\\\\]/", $this->sn)){
1133       $message[]= _("The field 'Name' contains invalid characters.");
1134     }
1135     if (preg_match ("/[\\\\]/", $this->givenName)){
1136       $message[]= _("The field 'Given name' contains invalid characters.");
1137     }
1139     /* Check phone numbers */
1140     if (!tests::is_phone_nr($this->telephoneNumber)){
1141       $message[]= _("The field 'Phone' contains an invalid phone number.");
1142     }
1143     if (!tests::is_phone_nr($this->facsimileTelephoneNumber)){
1144       $message[]= _("The field 'Fax' contains an invalid phone number.");
1145     }
1146     if (!tests::is_phone_nr($this->mobile)){
1147       $message[]= _("The field 'Mobile' contains an invalid phone number.");
1148     }
1149     if (!tests::is_phone_nr($this->pager)){
1150       $message[]= _("The field 'Pager' contains an invalid phone number.");
1151     }
1153     /* Check for reserved characers */
1154     if (preg_match ('/[,+"?\'()=<>;]/', $this->givenName)){
1155       $message[]= _("The field 'Given name' contains invalid characters.");
1156   }
1157   if (preg_match ('/[,+"?\'()=<>;]/', $this->sn)){
1158     $message[]= _("The field 'Name' contains invalid characters.");
1159   }
1161   return $message;
1162   }
1165   /* Indicate whether a password change is needed or not */
1166   function password_change_needed()
1167   {
1168     if(in_array("pw_storage",$this->multi_boxes)){
1169       return(TRUE);
1170     }
1171     return($this->pw_storage != $this->last_pw_storage);
1172   }
1175   /* Load a jpegPhoto from LDAP, this is going to be simplified later on */
1176   function load_picture()
1177   {
1178     $ldap = $this->config->get_ldap_link();
1179     $ldap->cd ($this->dn);
1180     $data = $ldap->get_attribute($this->dn,"jpegPhoto");
1182     if((!$data) || ($data == "*removed*")){ 
1184       /* In case we don't get an entry, load a default picture */
1185       $this->set_picture ();//"./images/default.jpg");
1186       $this->jpegPhoto= "*removed*";
1187     }else{
1189       /* Set picture */
1190       $this->photoData= $data;
1191       session::set('binary',$this->photoData);
1192       session::set('binarytype',"image/jpeg");
1193       $this->jpegPhoto= "";
1194     }
1195   }
1198   /* Load a certificate from LDAP, this is going to be simplified later on */
1199   function load_cert()
1200   {
1201     $ds= ldap_connect($this->config->current['SERVER']);
1202     ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
1203     if (function_exists("ldap_set_rebind_proc") && isset($this->config->current['RECURSIVE']) && $this->config->current['RECURSIVE'] == "true") {
1204       ldap_set_option($this->cid, LDAP_OPT_REFERRALS, 1);
1205       ldap_set_rebind_proc($ds, array(&$this, "rebind"));
1206     }
1207     if(isset($this->config->current['TLS']) &&
1208         $this->config->current['TLS'] == "true"){
1210       ldap_start_tls($ds);
1211     }
1213     $r= ldap_bind($ds);
1214     $sr= @ldap_read($ds, $this->dn, "userCertificate=*", array("userCertificate"));
1216     if ($sr) {
1217       $ei= @ldap_first_entry($ds, $sr);
1218       
1219       if ($ei) {
1220         if (!$info = @ldap_get_values_len($ds, $ei, "userCertificate;binary")){
1221           $this->userCertificate= "";
1222         } else {
1223           $this->userCertificate= $info[0];
1224         }
1225       }
1226     } else {
1227       $this->userCertificate= "";
1228     }
1230     ldap_unbind($ds);
1231   }
1234   /* Load picture from file to object */
1235   function set_picture($filename ="")
1236   {
1237     if (!is_file($filename) || $filename =="" ){
1238       $filename= "./images/default.jpg";
1239       $this->jpegPhoto= "*removed*";
1240     }
1242     $fd = fopen ($filename, "rb");
1243     $this->photoData= fread ($fd, filesize ($filename));
1244     session::set('binary',$this->photoData);
1245     session::set('binarytype',"image/jpeg");
1246     $this->jpegPhoto= "";
1248     fclose ($fd);
1249   }
1252   /* Load certificate from file to object */
1253   function set_cert($cert, $filename)
1254   {
1255     if(!$thsi->acl_is_writeable("Certificate",(!is_object($this->parent) && !session::is_set('edit')))) return;
1256     $fd = fopen ($filename, "rb");
1257     if (filesize($filename)>0) {
1258       $this->$cert= fread ($fd, filesize ($filename));
1259       fclose ($fd);
1260       $this->is_modified= TRUE;
1261     } else {
1262       msg_dialog::display(_("Error"), _("Cannot open certificate!"), ERROR_DIALOG);
1263     }
1264   }
1266   /* Adapt from given 'dn' */
1267   function adapt_from_template($dn)
1268   {
1269     plugin::adapt_from_template($dn);
1271     /* Get base */
1272     $this->base= preg_replace('/^[^,]+,'.get_people_ou().'/i', '', $dn);
1274     if ($this->config->current['GOVERNMENTMODE']){
1276       /* Walk through govattrs */
1277       foreach ($this->govattrs as $val){
1279         if (isset($this->attrs["$val"][0])){
1281           /* If attribute is set, replace dynamic parts: 
1282              %sn, %givenName and %uid. Fill these in our local variables. */
1283           $value= $this->attrs["$val"][0];
1285           foreach (array("sn", "givenName", "uid") as $repl){
1286             if (preg_match("/%$repl/i", $value)){
1287               $value= preg_replace ("/%$repl/i",
1288                   $this->parent->$repl, $value);
1289             }
1290           }
1291           $this->$val= $value;
1292         }
1293       }
1294     }
1296     /* Get back uid/sn/givenName */
1297     if ($this->parent !== NULL){
1298       $this->uid= $this->parent->uid;
1299       $this->sn= $this->parent->sn;
1300       $this->givenName= $this->parent->givenName;
1301     }
1302   }
1304  
1305   /* This avoids that users move themselves out of their rights. 
1306    */
1307   function allowedBasesToMoveTo()
1308   {
1309     /* Get bases */
1310     $bases  = $this->get_allowed_bases();
1311     return($bases);
1312   } 
1315   function getCopyDialog()
1316   {
1317     $str = "";
1319     session::set('binary',$this->photoData); 
1320     session::set('binarytype',"image/jpeg");
1322     /* Get random number for pictures */
1323     srand((double)microtime()*1000000); 
1324     $rand = rand(0, 10000);
1326     $smarty = get_smarty();
1328     $smarty->assign("passwordTodo","clear");
1330     if(isset($_POST['passwordTodo'])){
1331       $smarty->assign("passwordTodo",$_POST['passwordTodo']);
1332     }
1334     $smarty->assign("sn",       $this->sn);
1335     $smarty->assign("givenName",$this->givenName);
1336     $smarty->assign("uid",      $this->uid);
1337     $smarty->assign("rand",     $rand);
1338     $str = $smarty->fetch(get_template_path("paste_generic.tpl",TRUE,dirname(__FILE__)));
1341     $ret = array();
1342     $ret['string'] = $str;
1343     $ret['status'] = "";  
1344     return($ret);
1345   }
1347   function saveCopyDialog()
1348   {
1349     /* Set_acl_base */
1350     $this->set_acl_base("cn=dummy,".get_people_ou().$this->base);
1352     if((isset($_FILES['picture_file']['tmp_name'])) && ($_FILES['picture_file']['size'] > 0)){
1353       $this->set_picture($_FILES['picture_file']['tmp_name']);
1354     }
1356     /* Remove picture? */
1357     if (isset($_POST['picture_remove'])){
1358       $this->jpegPhoto= "*removed*";
1359       $this->set_picture ("./images/default.jpg");
1360       $this->is_modified= TRUE;
1361     }
1363     $attrs = array("uid","givenName","sn");
1364     foreach($attrs as $attr){
1365       if(isset($_POST[$attr])){
1366         $this->$attr = $_POST[$attr];
1367       }
1368     } 
1369   }
1372   function PrepareForCopyPaste($source)
1373   {
1374     plugin::PrepareForCopyPaste($source);
1376     /* Reset certificate information addepted from source user
1377        to avoid setting the same user certificate for the destination user. */
1378     $this->userPKCS12= "";
1379     $this->userSMIMECertificate= "";
1380     $this->userCertificate= "";
1381     $this->certificateSerialNumber= "";
1382     $this->old_certificateSerialNumber= "";
1383     $this->old_userPKCS12= "";
1384     $this->old_userSMIMECertificate= "";
1385     $this->old_userCertificate= "";
1386   }
1389   static function plInfo()
1390   {
1391   
1392     $govattrs= array(
1393         "gouvernmentOrganizationalUnit"             =>  _("Unit"), 
1394         "houseIdentifier"                           =>  _("House identifier"), 
1395         "vocation"                                  =>  _("Vocation"),
1396         "ivbbLastDeliveryCollective"                =>  _("Last delivery"), 
1397         "gouvernmentOrganizationalPersonLocality"   =>  _("Person locality"),
1398         "gouvernmentOrganizationalUnitDescription"  =>  _("Unit description"),
1399         "gouvernmentOrganizationalUnitSubjectArea"  =>  _("Subject area"),
1400         "functionalTitle"                           =>  _("Functional title"),
1401         "certificateSerialNumber"                   =>  _("Certificate serial number"),
1402         "publicVisible"                             =>  _("Public visible"),
1403         "street"                                    =>  _("Street"),
1404         "role"                                      =>  _("Role"),
1405         "postalCode"                                =>  _("Postal code"));
1407     $ret = array(
1408         "plShortName" => _("Generic"),
1409         "plDescription" => _("Generic user settings"),
1410         "plSelfModify"  => TRUE,
1411         "plDepends"     => array(),
1412         "plPriority"    => 1,
1413         "plSection"     => array("personal" => _("My account")),
1414         "plCategory"    => array("users" => array("description" => _("Users"),
1415                                                   "objectClass" => "gosaAccount")),
1417         "plProvidedAcls" => array(
1418           "base"              => _("Base"), 
1419           "userPassword"      => _("User password"), 
1420           "sn"                => _("Surename"),
1421           "givenName"         => _("Given name"),
1422           "uid"               => _("User identification"),
1423           "personalTitle"     => _("Personal title"),
1424           "academicTitle"     => _("Academic title"),
1425           "homePostalAddress" => _("Home postal address"),
1426           "homePhone"         => _("Home phone number"),
1427           "labeledURI"        => _("Homepage"),
1428           "o"                 => _("Organization"),
1429           "ou"                => _("Department"),
1430           "dateOfBirth"       => _("Date of birth"),
1431           "gender"            => _("Gender"),
1432           "preferredLanguage" => _("Preferred language"),
1433           "departmentNumber"  => _("Department number"),
1434           "employeeNumber"    => _("Employee number"),
1435           "employeeType"      => _("Employee type"),
1436           "l"                 => _("Location"),
1437           "st"                => _("State"),
1438           "userPicture"       => _("User picture"),
1439           "roomNumber"        => _("Room number"),
1440           "telephoneNumber"   => _("Telefon number"),
1441           "mobile"            => _("Mobile number"),
1442           "pager"             => _("Pager number"),
1443           "Certificate"        => _("User certificates"),
1445           "postalAddress"                => _("Postal address"),
1446           "facsimileTelephoneNumber"     => _("Fax number"))
1447         );
1449     /* Append government attributes if required */
1450       global $config;
1451     if (isset($config->current['GOVERNMENTMODE']) &&  preg_match('/true/i', $config->current['GOVERNMENTMODE'])){
1452       foreach($govattrs as $attr => $desc){
1453         $ret["plProvidedAcls"][$attr] = $desc;
1454       }
1455     }
1456     return($ret);
1457   }
1459   function get_multi_edit_values()
1460   {
1461     $ret = plugin::get_multi_edit_values();
1462     if(in_array("pw_storage",$this->multi_boxes)){
1463       $ret['pw_storage'] = $this->pw_storage;
1464     }
1465     if(in_array("edit_picture",$this->multi_boxes)){
1466       $ret['jpegPhoto'] = $this->jpegPhoto;
1467       $ret['photoData'] = $this->photoData;
1468       $ret['old_jpegPhoto'] = $this->old_jpegPhoto;
1469       $ret['old_photoData'] = $this->old_photoData;
1470     }
1471     if(isset($ret['dateOfBirth'])){
1472       unset($ret['dateOfBirth']);
1473     }
1474     if(isset($ret['cn'])){
1475       unset($ret['cn']);
1476     }
1477     $ret['is_modified'] = $this->is_modified;
1478     if(in_array("base",$this->multi_boxes)){
1479       $ret['orig_base']="Changed_by_Multi_Plug";
1480       $ret['base']=$this->base;
1481     }
1482     return($ret); 
1483   }
1486   function multiple_save_object()
1487   {
1488     plugin::multiple_save_object();
1490     /* Get pw_storage mode */
1491     if (isset($_POST['pw_storage'])){
1492       foreach(array("pw_storage") as $val){
1493         if(isset($_POST[$val])){
1494           $data= validate(get_post($val));
1495           if ($data != $this->$val){
1496             $this->is_modified= TRUE;
1497           }
1498           $this->$val= $data;
1499         }
1500       }
1501     }
1502     if(isset($_POST['base'])){
1503       $this->base = get_post('base');
1504     }
1506     if(isset($_POST['user_mulitple_edit'])){
1507       foreach(array("base","pw_storage","edit_picture") as $val){
1508         if(isset($_POST["use_".$val])){
1509           $this->multi_boxes[] = $val;
1510         }
1511       }
1512     }
1513   }
1515   
1516   function multiple_check()
1517   {
1518     /* Call check() to set new_dn correctly ... */
1519     $message = plugin::multiple_check();
1521     /* Set the new acl base */
1522     if($this->dn == "new") {
1523       $this->set_acl_base($this->base);
1524     }
1525     if (!tests::is_url($this->labeledURI) && in_array("labeledURI",$this->multi_boxes)){
1526       $message[]= _("The field 'Homepage' contains an invalid URL definition.");
1527     }
1528     if (preg_match ("/[\\\\]/", $this->sn) && in_array("sn",$this->multi_boxes)){
1529       $message[]= _("The field 'Name' contains invalid characters.");
1530     }
1531     if (preg_match ("/[\\\\]/", $this->givenName) && in_array("givenName",$this->multi_boxes)){
1532       $message[]= _("The field 'Given name' contains invalid characters.");
1533     }
1534     if (!tests::is_phone_nr($this->telephoneNumber) && in_array("telephoneNumber",$this->multi_boxes)){
1535       $message[]= _("The field 'Phone' contains an invalid phone number.");
1536     }
1537     if (!tests::is_phone_nr($this->facsimileTelephoneNumber) &&  in_array("facsimileTelephoneNumber",$this->multi_boxes)){
1538       $message[]= _("The field 'Fax' contains an invalid phone number.");
1539     }
1540     if (!tests::is_phone_nr($this->mobile) && in_array("mobile",$this->multi_boxes)){
1541       $message[]= _("The field 'Mobile' contains an invalid phone number.");
1542     }
1543     if (!tests::is_phone_nr($this->pager) && in_array("pager",$this->multi_boxes)){
1544       $message[]= _("The field 'Pager' contains an invalid phone number.");
1545     }
1546     if (preg_match ('/[,+"?\'()=<>;]/', $this->givenName) && in_array("givenName",$this->multi_boxes)){
1547       $message[]= _("The field 'Given name' contains invalid characters.");
1548     }
1549     if (preg_match ('/[,+"?\'()=<>;]/', $this->sn) && in_array("sn",$this->multi_boxes)){
1550       $message[]= _("The field 'Name' contains invalid characters.");
1551     }
1552     return($message);
1553   }
1557   function multiple_execute()
1558   {
1559     return($this->execute());
1560   }
1565 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1566 ?>