Code

Updated in_array checks in GOsa.
[gosa.git] / gosa-core / plugins / personal / generic / class_user.inc
index cf2d762d6b91cb20132f0c87a800aaf1515dd513..da5180054daee2081c0b2ace8e55b483fd594e40 100644 (file)
@@ -66,6 +66,7 @@ class user extends plugin
   var $use_dob= "0";
   var $gender="0";
   var $preferredLanguage="0";
+  var $baseSelector;
 
   var $jpegPhoto= "*removed*";
   var $photoData= "";
@@ -107,12 +108,16 @@ class user extends plugin
 
   var $view_logged = FALSE;
 
+  var $manager = "";
+  var $manager_name = "";
+
+
   /* attribute list for save action */
   var $attributes= array("sn", "givenName", "uid", "personalTitle", "academicTitle",
       "homePostalAddress", "homePhone", "labeledURI", "ou", "o", "dateOfBirth", "gender","preferredLanguage",
       "departmentNumber", "employeeNumber", "employeeType", "l", "st","jpegPhoto",
       "roomNumber", "telephoneNumber", "mobile", "pager", "cn", "userPKCS12",
-      "postalAddress", "facsimileTelephoneNumber", "userSMIMECertificate", "gosaLoginRestriction");
+      "postalAddress", "facsimileTelephoneNumber", "userSMIMECertificate", "gosaLoginRestriction", "manager");
 
   var $objectclasses= array("top", "person", "organizationalPerson", "inetOrgPerson",
       "gosaAccount");
@@ -136,7 +141,7 @@ class user extends plugin
 
     $this->config= $config;
     /* Configuration is fine, allways */
-    if($this->config->get_cfg_value("honourIvbbAttributes") == "true"){
+    if($this->config->get_cfg_value("core","honourIvbbAttributes") == "true"){
       $this->governmentmode = TRUE;
       $this->attributes=array_merge($this->attributes,$this->govattrs);
     }
@@ -170,7 +175,7 @@ class user extends plugin
     }
 
     /* Make hash default to md5 if not set in config */
-    $hash= $this->config->get_cfg_value("passwordDefaultHash", "crypt/md5");
+    $hash= $this->config->get_cfg_value("core","passwordDefaultHash");
 
     /* Load data from LDAP? */
     if ($dn !== NULL){
@@ -223,7 +228,7 @@ class user extends plugin
     /* Generate dateOfBirth entry */
     if (isset ($this->attrs['dateOfBirth'])){
       /* This entry is ISO 8601 conform */
-      list($year, $month, $day)= split("-", $this->attrs['dateOfBirth'][0], 3);
+      list($year, $month, $day)= explode("-", $this->attrs['dateOfBirth'][0], 3);
     
       #TODO: use $lang to convert date
       $this->dateOfBirth= "$day.$month.$year";
@@ -250,6 +255,24 @@ class user extends plugin
     $this->gosaLoginRestrictionWidget->setHeight("70px");
  
     $this->orig_base = $this->base;
+    $this->baseSelector= new baseSelector($this->allowedBasesToMoveTo(), $this->base);
+    $this->baseSelector->setSubmitButton(false);
+    $this->baseSelector->setHeight(300);
+    $this->baseSelector->update(true);
+
+
+    // Detect the managers name
+    $this->manager_name = "";
+    $ldap = $this->config->get_ldap_link();
+    if(!empty($this->manager)){
+      $ldap->cat($this->manager, array('cn'));
+      if($ldap->count()){
+        $attrs = $ldap->fetch();
+        $this->manager_name = $attrs['cn'][0];
+      }else{
+        $this->manager_name = "("._("unknown")."!): ".$this->manager;
+      }
+    }
   }
 
 
@@ -259,19 +282,19 @@ class user extends plugin
     /* Call parent execute */
     plugin::execute();
 
-    /* Let the lists update themselves */
-    $this->gosaLoginRestrictionWidget->setAcl($this->getacl('gosaLoginRestriction', (!is_object($this->parent) && !session::is_set('edit'))));
+    /* Set list ACL */
+    $this->gosaLoginRestrictionWidget->setAcl($this->getacl('gosaLoginRestriction'));
     $this->gosaLoginRestrictionWidget->update();
 
     /* Handle add/delete for restriction mode */
     if (isset($_POST['add_res']) && isset($_POST['res'])) {
-      $val= validate($_POST['res']);
+      $val= get_post('res');
       if (preg_match('/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/', $val) ||
           preg_match('/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/([0-9]+)$/', $val) ||
           preg_match('/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/', $val)) {
         $this->gosaLoginRestrictionWidget->addEntry($val);
       } else {
-        msg_dialog::display(_("Error"), _("Please add a single IP address or a network/netmask combination!"), ERROR_DIALOG);
+        msg_dialog::display(_("Error"), _("Please add a single IP address or a network/net mask combination!"), ERROR_DIALOG);
       }
     }
 
@@ -281,8 +304,35 @@ class user extends plugin
       new log("view","users/".get_class($this),$this->dn);
     }
 
+    // Clear manager attribute if requested
+    if(preg_match("/ removeManager/i", " ".implode(array_keys($_POST),' ')." ")){
+      $this->manager = "";
+      $this->manager_name = "";
+    }
+
+    // Allow to select a new inetOrgPersion:manager 
+    if(preg_match("/ editManager/i", " ".implode(array_keys($_POST),' ')." ")){
+      $this->dialog = new singleUserSelect($this->config, get_userinfo());
+    }
+    if($this->dialog && $this->dialog instanceOf singleUserSelect && count($this->dialog->detectPostActions())){
+      $users = $this->dialog->detectPostActions();
+      if(isset($users['action']) && $users['action'] =='userSelected' && isset($users['targets']) && count($users['targets'])){
+        $headpage = $this->dialog->getHeadpage();
+        $dn = $users['targets'][0];
+        $attrs = $headpage->getEntry($dn);
+        $this->manager = $dn;
+        $this->manager_name = $attrs['cn'][0];
+        $this->dialog = NULL;
+      }
+    }
+    if(isset($_POST['add_users_cancel'])){
+      $this->dialog = NULL;
+    }
+    if($this->dialog instanceOf singleUserSelect) return($this->dialog->execute()); 
+
+
     $smarty= get_smarty();
-    $smarty->assign("usePrototype", "true");
+
     $smarty->assign("gosaLoginRestrictionWidget", $this->gosaLoginRestrictionWidget->render());
 
     /* Assign sex */
@@ -303,16 +353,6 @@ class user extends plugin
       return($str);
     }
 
-    /* Base select dialog */
-    $once = true;
-    foreach($_POST as $name => $value){
-      if(preg_match("/^chooseBase/",$name) && $once && $this->acl_is_writeable("base")){
-        $once = false;
-        $this->dialog = new baseSelectDialog($this->config,$this,$this->allowedBasesToMoveTo());
-        $this->dialog->setCurrentBase($this->base);
-      }
-    }
-
     /* Password configure dialog handling */
     if(is_object($this->pwObject) && $this->pwObject->display){
       $output= $this->pwObject->configure();
@@ -352,6 +392,7 @@ class user extends plugin
         }
         $this->pwObject->display = TRUE;
         $this->dialog= TRUE;
+        pathNavigator::registerPlugin(_("Password configuration"));
         return ($this->pwObject->configure());
       }
     }
@@ -369,7 +410,7 @@ class user extends plugin
     }
 
     /* Remove picture? */
-    if($this->acl_is_writeable("userPicture",(!is_object($this->parent) && !session::is_set('edit'))) ){
+    if($this->acl_is_writeable("userPicture")){
       if (isset($_POST['picture_remove'])){
         $this->set_picture ();
         $this->jpegPhoto= "*removed*";
@@ -381,16 +422,17 @@ class user extends plugin
     /* Save picture */
     if (isset($_POST['picture_edit_finish'])){
 
-      /* Check for clean upload */
-      if ($_FILES['picture_file']['name'] != ""){
-        if (!is_uploaded_file($_FILES['picture_file']['tmp_name'])) {
-          msg_dialog::display(_("Error"), _("Cannot upload file!"), ERROR_DIALOG);
-        }else{
-          /* Activate new picture */
-          $this->set_picture($_FILES['picture_file']['tmp_name']);
+        /* Check for clean upload */
+        if ($_FILES['picture_file']['name'] != ""){
+            $filename = gosa_file_name($_FILES['picture_file']['tmp_name']);
+            if (!file_exists($filename)) {
+                msg_dialog::display(_("Error"), _("Cannot upload file!"), ERROR_DIALOG);
+            }else{
+                /* Activate new picture */
+                $this->set_picture($filename);
+            }
         }
-      }
-      $this->picture_dialog= FALSE;
+        $this->picture_dialog= FALSE;
       $this->dialog= FALSE;
       $this->is_modified= TRUE;
     }
@@ -442,7 +484,7 @@ class user extends plugin
 
 
     /* Remove certificate? */
-    if($this->acl_is_writeable("Certificate",(!is_object($this->parent) && !session::is_set('edit')))){ 
+    if($this->acl_is_writeable("Certificate")){
       foreach (array ("userCertificate", "userSMIMECertificate", "userPKCS12") as $val){
         if (isset($_POST["remove_$val"])){
 
@@ -454,10 +496,8 @@ class user extends plugin
     }
 
     /* Upload new cert and close dialog? */    
-    if($this->acl_is_writeable("Certificate",(!is_object($this->parent) && !session::is_set('edit')))){ 
-
+    if($this->acl_is_writeable("Certificate")){
       $fail =false;
-
       if (isset($_POST['cert_edit_finish'])){
 
         /* for all certificates do */
@@ -468,8 +508,8 @@ class user extends plugin
           if (array_key_exists($val."_file", $_FILES) &&
               array_key_exists('name', $_FILES[$val."_file"]) &&
               $_FILES[$val."_file"]['name'] != "" &&
-              is_uploaded_file($_FILES[$val."_file"]['tmp_name'])) {
-            $this->set_cert("$val", $_FILES[$val."_file"]['tmp_name']);
+              is_readable($_FILES[$val."_file"]['tmp_name'])) {
+            $this->set_cert("$val", gosa_file_name($_FILES[$val."_file"]['tmp_name']));
           }
         }
 
@@ -477,7 +517,7 @@ class user extends plugin
         if (isset($_POST["certificateSerialNumber"]) &&
             $_POST["certificateSerialNumber"] != ""){
 
-          if (!tests::is_id($_POST["certificateSerialNumber"])){
+          if (!tests::is_id(get_post('certificateSerialNumber'))){
             $fail = true;
             msg_dialog::display(_("Error"), msgPool::invalid(_("Serial number"),$_POST["certificateSerialNumber"],"/[0-9]/"),ERROR_DIALOG);
 
@@ -490,7 +530,7 @@ class user extends plugin
             }
           }
 
-          $this->certificateSerialNumber= $_POST["certificateSerialNumber"];
+          $this->certificateSerialNumber= get_post("certificateSerialNumber");
           $this->is_modified= TRUE;
         }
         if(!$fail){
@@ -501,12 +541,14 @@ class user extends plugin
     }
     /* Display picture dialog */
     if ($this->picture_dialog){
+      pathNavigator::registerPlugin(_("User picture"));
       return($smarty->fetch (get_template_path('generic_picture.tpl', TRUE, dirname(__FILE__))));
     }
 
     /* Display cert dialog */
     if ($this->cert_dialog){
-      $smarty->assign("CertificateACL",$this->getacl("Certificate",(!is_object($this->parent) && !session::is_set('edit'))));
+      pathNavigator::registerPlugin(_("Certificates"));
+      $smarty->assign("CertificateACL",$this->getacl("Certificate"));
       $smarty->assign("Certificate_readable",$this->acl_is_readable("Certificate"));
       $smarty->assign("certificateSerialNumber",$this->certificateSerialNumber);
 
@@ -524,21 +566,21 @@ class user extends plugin
           /* Additional info if start end time is '0' */
           $add_str_info = "";
           if($timeto == 0 && $timefrom == 0){
-            $add_str_info = "<br><i>"._("(Some types of certificates are currently not supported and may be displayed as 'invalid'.)")."</i>";
+            $add_str_info = "<br>".bold(_("(Not supported certificate types are marked as invalid.)"));
           }
 
-          $str = "<table summary=\"\" border=0>
+          $str = "<table \"\" border=0 summary='"._("Certificates")."'>
                     <tr>
-                      <td style='vertical-align:top'>CN</td>
+                      <td>CN</td>
                       <td>".preg_replace("/ /", "&nbsp;", $certificate->getname())."</td>
                     </tr>
                   </table><br>".
 
                   sprintf(_("Certificate is valid from %s to %s and is currently %s."),
-                        "<b>".date('d M Y',$timefrom)."</b>",
-                        "<b>".date('d M Y',$timeto)."</b>",
-                        $certificate->isvalid()?"<b><font style='color:green'>"._("valid")."</font></b>":
-                                                "<b><font style='color:red'>"._("invalid")."</font></b>").$add_str_info;
+                        bold(date('d M Y',$timefrom)),
+                        bold(date('d M Y',$timeto)),
+                        $certificate->isvalid()?bold("<span style='color:green'>"._("valid")."</span>"):
+                                                bold("<span style='color:red'>"._("invalid")."</span>")).$add_str_info;
 
           $smarty->assign($cert."info",$str);
           $smarty->assign($cert."_state","true");
@@ -559,14 +601,14 @@ class user extends plugin
 
     /* Prepare password hashes */
     if ($this->pw_storage == ""){
-      $this->pw_storage= $this->config->get_cfg_value("hash");
+      $this->pw_storage= $this->config->get_cfg_value("core","passwordDefaultHash");
     }
 
     $temp= passwordMethod::get_available_methods();
     $is_configurable= FALSE;
     $hashes = $temp['name'];
     if(isset($temp[$this->pw_storage])){
-      $test= new $temp[$this->pw_storage]($this->config);
+      $test= new $temp[$this->pw_storage]($this->config, $this->dn);
       $is_configurable= $test->is_configurable();
     }else{
       new msg_dialog(_("Password method"),_("The selected password method is no longer available."),WARNING_DIALOG);
@@ -586,15 +628,15 @@ class user extends plugin
     /* Load attributes and acl's */
     $ui =get_userinfo();
     foreach($this->attributes as $val){
-      $smarty->assign("$val", $this->$val);
-      if(in_array($val,$this->multi_boxes)){
+      $smarty->assign("$val", set_post($this->$val));
+      if(in_array_strict($val,$this->multi_boxes)){
         $smarty->assign("use_".$val,TRUE);
       }else{
         $smarty->assign("use_".$val,FALSE);
       }
     }
     foreach(array("base","pw_storage","edit_picture") as $val){
-      if(in_array($val,$this->multi_boxes)){
+      if(in_array_strict($val,$this->multi_boxes)){
         $smarty->assign("use_".$val,TRUE);
       }else{
         $smarty->assign("use_".$val,FALSE);
@@ -604,45 +646,40 @@ class user extends plugin
     /* Set acls */
     $tmp = $this->plinfo();
     foreach($tmp['plProvidedAcls'] as $val => $translation){
-      $smarty->assign("$val"."ACL", $this->getacl($val,(!is_object($this->parent) && !session::is_set('edit'))));
+      $smarty->assign("$val"."ACL", $this->getacl($val));
     }
 
-    $smarty->assign("gosaLoginRestrictionACL", $this->getacl('gosaLoginRestriction', (!is_object($this->parent) && !session::is_set('edit'))));
-    $smarty->assign("pwmode", $pwd_methods);
-    $smarty->assign("pwmode_select", $this->pw_storage);
-    $smarty->assign("pw_configurable", $is_configurable);
-    $smarty->assign("passwordStorageACL", $this->getacl("userPassword",(!is_object($this->parent) && !session::is_set('edit'))));
-    $smarty->assign("base_select",      $this->base);
+    // Special ACL for gosaLoginRestrictions - 
+    // In case of multiple edit, we need a readonly ACL for the list. 
+    $smarty->assign('gosaLoginRestriction_ONLY_R_ACL', preg_replace("/[^r]/i","", $this->getacl($val)));
 
-    if(!session::is_set('edit')){
-      $smarty->assign("CertificatesACL","");
-    }else{
-      $smarty->assign("CertificatesACL",  $this->getacl("Certificate"));
-    }
-    
-    $smarty->assign("userPictureACL",   $this->getacl("userPicture",(!is_object($this->parent) && !session::is_set('edit'))));
-    $smarty->assign("userPicture_is_readable",   $this->acl_is_readable("userPicture",(!is_object($this->parent) && !session::is_set('edit'))));
+    $smarty->assign("pwmode", set_post($pwd_methods));
+    $smarty->assign("pwmode_select", set_post($this->pw_storage));
+    $smarty->assign("pw_configurable", $is_configurable);
+    $smarty->assign("passwordStorageACL", $this->getacl("userPassword"));
+    $smarty->assign("CertificatesACL",  $this->getacl("Certificate"));
+    $smarty->assign("userPictureACL",   $this->getacl("userPicture"));
+    $smarty->assign("userPicture_is_readable",   $this->acl_is_readable("userPicture"));
 
     /* Create base acls */
-    $tmp = @$this->allowedBasesToMoveTo();
-    $smarty->assign("bases", $tmp);
+    $smarty->assign("base", $this->baseSelector->render());
 
     /* Save government mode attributes */
     if($this->governmentmode){
       $smarty->assign("governmentmode", "true");
-      $ivbbmodes= array("nein", "ivbv", "testa", "ivbv,testa", "internet",
-          "internet,ivbv", "internet,testa", "internet,ivbv,testa");
+      $ivbbmodes= array("nein", "", "ivbv", "testa", "ivbv,testa", "internet",
+                        "internet,ivbv", "internet,testa", "internet,ivbv,testa");
       $smarty->assign("ivbbmodes", $ivbbmodes);
       foreach ($this->govattrs as $val){
-        $smarty->assign("$val", $this->$val);
-        $smarty->assign("$val"."ACL", $this->getacl($val,(!is_object($this->parent) && !session::is_set('edit'))));
+        $smarty->assign("$val", set_post($this->$val));
+        $smarty->assign("$val"."ACL", $this->getacl($val));
       }
     } else {
       $smarty->assign("governmentmode", "false");
     }
 
     /* Special mode for uid */
-    $uidACL= $this->getacl("uid",(!is_object($this->parent) && !session::is_set('edit')));
+    $uidACL= $this->getacl("uid");
     if (isset ($this->dn)){
       if ($this->dn != "new"){
         $uidACL= preg_replace("/w/","",$uidACL);
@@ -666,6 +703,7 @@ class user extends plugin
       $smarty->assign("has_phoneaccount", "false");
     }
     $smarty->assign("multiple_support" , $this->multiple_support_active);
+    $smarty->assign("manager_name", set_post($this->manager_name));
     return($smarty->fetch (get_template_path('generic.tpl', TRUE, dirname(__FILE__))));
   }
 
@@ -709,10 +747,26 @@ class user extends plugin
     while ($ldap->fetch()){
       $og= new ogroup($this->config, $ldap->getDN());
       unset($og->member[$this->dn]);
-      $og->member= array_values($og->member);
       $og->save ();
     }
 
+    // Update 'manager' attributes from gosaDepartment and inetOrgPerson
+    $filter = "(&(objectClass=inetOrgPerson)(manager=".LDAP::prepare4filter($this->dn)."))";
+    $ocs = $ldap->get_objectclasses();
+    if(isset($ocs['gosaDepartment']['MAY']) && in_array_strict('manager', $ocs['gosaDepartment']['MAY'])){
+      $filter = "(|".$filter."(&(objectClass=gosaDepartment)(manager=".LDAP::prepare4filter($this->dn).")))";
+    }
+    $leaf_deps=  get_list($filter,array("all"),$this->config->current['BASE'],
+        array("manager","dn","objectClass"),GL_SUBSEARCH | GL_NO_ACL_CHECK);
+    foreach($leaf_deps as $entry){
+      $update = array('manager' => array());
+      $ldap->cd($entry['dn']);
+      $ldap->modify($update);
+      if(!$ldap->success()){
+        trigger_error(sprintf("Failed to update manager for '%s', error was '%s'", $entry['dn'], $ldap->get_error()));
+      }
+    }
+
     /* Delete references to roles */
     $ldap->cd ($this->config->current['BASE']);
     $ldap->search ("(&(objectClass=organizationalRole)(roleOccupant=".LDAP::prepare4filter($this->dn)."))", array("cn"));
@@ -727,7 +781,7 @@ class user extends plugin
     }
 
     /* If needed, let the password method do some cleanup */
-    $tmp = new passwordMethod($this->config);
+    $tmp = new passwordMethod($this->config, $this->dn);
     $available = $tmp->get_available_methods();
     if (in_array_ics($this->pw_storage, $available['name'])){
       $test= new $available[$this->pw_storage]($this->config);
@@ -755,16 +809,29 @@ class user extends plugin
       /* Parents save function */
       plugin::save_object ();
 
+      /* Refresh base */
+      if ($this->acl_is_moveable($this->base) || 
+            ($this->dn == "new" && $this->acl_is_createable($this->base))){
+        if (!$this->baseSelector->update()) {
+          msg_dialog::display(_("Error"), msgPool::permMove(), ERROR_DIALOG);
+        }
+        if ($this->base != $this->baseSelector->getBase()) {
+          $this->base= $this->baseSelector->getBase();
+          $this->is_modified= TRUE;
+        }
+      }
+      
       /* Sync lists */
+      $this->gosaLoginRestrictionWidget->save_object();
       if ($this->gosaLoginRestrictionWidget->isModified()) {
-        $this->gosaLoginRestriction= $this->gosaLoginRestrictionWidget->getMaintainedData();
+        $this->gosaLoginRestriction= array_values($this->gosaLoginRestrictionWidget->getMaintainedData());
       }
 
       /* Save government mode attributes */
       if ($this->governmentmode){
         foreach ($this->govattrs as $val){
-          if ($this->acl_is_writeable($val,(!is_object($this->parent) && !session::is_set('edit'))) && isset($_POST["$val"])){
-            $data= stripcslashes($_POST["$val"]);
+          if ($this->acl_is_writeable($val)){
+            $data= get_post($val);
             if ($data != $this->$val){
               $this->is_modified= TRUE;
             }
@@ -779,28 +846,11 @@ class user extends plugin
         $this->givenName= $this->sn;
       }
 
-      /* Save base - its no no LDAP attribute */
-      if (isset($_POST['base'])){
-        $base= get_post('base');
-        if ($base != $this->base){
-          $tmp = $this->get_allowed_bases();
-          if(isset($tmp[$base])){
-            if ($base != $this->base){
-              $this->is_modified= TRUE;
-            }
-            $this->base= $base;
-          }else{
-            $this->base = $base_tmp;
-            msg_dialog::display(_("Error"), msgPool::permMove(), ERROR_DIALOG);
-          }
-        }
-      }
-
       /* Get pw_storage mode */
       if (isset($_POST['pw_storage'])){
         foreach(array("pw_storage") as $val){
           if(isset($_POST[$val])){
-            $data= validate($_POST[$val]);
+            $data= get_post($val);
             if ($data != $this->$val){
               $this->is_modified= TRUE;
             }
@@ -862,7 +912,7 @@ class user extends plugin
     if ($this->dateOfBirth != ""){
       if(!is_array($this->attrs['dateOfBirth'])) {
         #TODO: use $lang to convert date
-        list($day, $month, $year)= split("\.", $this->dateOfBirth);
+        list($day, $month, $year)= explode(".", $this->dateOfBirth);
         $this->attrs['dateOfBirth'] = sprintf("%04d-%02d-%02d", $year, $month, $day);
       }
     }
@@ -957,84 +1007,56 @@ class user extends plugin
 
     } else {
 
-      /* Fallback if there's no image magick inside PHP */
-      if (!function_exists("imagick_blob2image")){
-        /* Get temporary file name for conversation */
-        $fname = tempnam (TEMP_DIR, "GOsa");
-  
-        /* Open file and write out photoData */
-        $fp = fopen ($fname, "w");
-        fwrite ($fp, $this->photoData);
-        fclose ($fp);
-
-        /* Build conversation query. Filename is generated automatically, so
-           we do not need any special security checks. Exec command and save
-           output. For PHP safe mode, you'll need a configuration which respects
-           image magick as executable... */
-        $query= "convert -size 147x200 $fname -resize 147x200 +profile \"*\" -";
-        @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
-            $query, "Execute");
-  
-        /* Read data written by convert */
-        $output= "";
-        $sh= popen($query, 'r');
-        while (!feof($sh)){
-          $output.= fread($sh, 4096);
-        }
-        pclose($sh);
-
-        unlink($fname);
-
-        /* Save attribute */
-        $this->attrs["jpegPhoto"] = $output;
-
-      } else {
+        if(class_exists('Imagick')){
+
+            $im = new Imagick();
+            $im->readImageBlob($this->photoData);
+            $im->setImageOpacity(1.0);
+            $im->resizeImage(147,200,Imagick::FILTER_UNDEFINED,0.5,TRUE);
+            $im->setCompressionQuality(90);
+            $im->setImageFormat('jpeg'); 
+            $this->attrs["jpegPhoto"] = $im->getImageBlob();
+
+        }elseif (exec('convert')){
+            /* Get temporary file name for conversation */
+            $fname = tempnam (TEMP_DIR, "GOsa");
+
+            /* Open file and write out photoData */
+            $fp = fopen ($fname, "w");
+            fwrite ($fp, $this->photoData);
+            fclose ($fp);
+
+            /* Build conversation query. Filename is generated automatically, so
+               we do not need any special security checks. Exec command and save
+               output. For PHP safe mode, you'll need a configuration which respects
+               image magick as executable... */
+            $query= "convert -size 147x200 $fname -resize 147x200 +profile \"*\" -";
+            @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
+                    $query, "Execute");
+
+            /* Read data written by convert */
+            $output= "";
+            $sh= popen($query, 'r');
+            while (!feof($sh)){
+                $output.= fread($sh, 4096);
+            }
+            pclose($sh);
 
-        /* Load the new uploaded Photo */
-        if(!$handle  =  imagick_blob2image($this->photoData))  {
-          new log("debug","users/".get_class($this),$this->dn,array(),"Could not access uploaded image");
-        }
+            unlink($fname);
 
-        /* Resizing image to 147x200 and blur */
-        if(!imagick_resize($handle,147,200,IMAGICK_FILTER_GAUSSIAN,0)){
-          new log("debug","users/".get_class($this),$this->dn,array(),"Could not resize uploaded image");
-        }
-
-        /* Converting image to JPEG */
-        if(!imagick_convert($handle,"JPEG")) {
-          new log("debug","users/".get_class($this),$this->dn,array(),"Could not convert uploaded image to jepg");
-        }
+            /* Save attribute */
+            $this->attrs["jpegPhoto"] = $output;
+        }else{
+            msg_dialog::display(_("Error"),
+                    _("Cannot save user picture: GOsa requires the package 'imagemagick' or 'php5-imagick' to be installed!"),
+                    ERROR_DIALOG);
 
-        /* Creating binary Code for the Image */
-        if(!$dump = imagick_image2blob($handle)){
-          new log("debug","users/".get_class($this),$this->dn,array(),"Could not create new user image");
         }
-
-        /* Sending Image */
-        $output=  $dump;
-
-        /* Save attribute */
-        $this->attrs["jpegPhoto"] = $output;
-      }
-
-    }
-
-    /* This only gets called when user is renaming himself */
-    $ldap= $this->config->get_ldap_link();
-    if ($this->dn != $this->new_dn){
-
-      /* Write entry on new 'dn' */
-      $this->update_acls($this->dn,$this->new_dn);
-      $this->move($this->dn, $this->new_dn);
-
-      /* Happen to use the new one */
-      change_ui_dn($this->dn, $this->new_dn);
-      $this->dn= $this->new_dn;
     }
 
-
     /* Save data. Using 'modify' implies that the entry is already present, use 'add' for
        new entries. So do a check first... */
+    $ldap= $this->config->get_ldap_link();
     $ldap->cat ($this->dn, array('dn'));
     if ($ldap->fetch()){
       $mode= "modify";
@@ -1104,11 +1126,11 @@ class user extends plugin
         die ("Could not connect to LDAP server");
       }
       ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
-      if (function_exists("ldap_set_rebind_proc") && $this->config->get_cfg_value("ldapFollowReferrals") == "true") {
+      if (function_exists("ldap_set_rebind_proc") && $this->config->get_cfg_value("core","ldapFollowReferrals") == "true") {
         ldap_set_option($this->cid, LDAP_OPT_REFERRALS, 1);
         ldap_set_rebind_proc($ds, array(&$this, "rebind"));
       }
-      if($this->config->get_cfg_value("ldapTLS") == "true"){
+      if($this->config->get_cfg_value("core","ldapTLS") == "true"){
         ldap_start_tls($ds);
       }
       if (!($res = @ldap_bind($ds, $this->config->current['ADMIN'],
@@ -1123,7 +1145,7 @@ class user extends plugin
 
     /* If needed, let the password method do some cleanup */
     if ($this->pw_storage != $this->last_pw_storage){
-      $tmp = new passwordMethod($this->config);
+      $tmp = new passwordMethod($this->config, $this->dn);
       $available = $tmp->get_available_methods();
       if (in_array_ics($this->last_pw_storage, $available['name'])){
         $test= new $available[$this->last_pw_storage]($this->config,$this->dn);
@@ -1193,7 +1215,7 @@ class user extends plugin
   function update_new_dn()
   {
     // Alternative way to handle DN
-    $pattern= $this->config->get_cfg_value("accountRDN");
+    $pattern= $this->config->get_cfg_value("user","accountRDN");
     if ($pattern != "") {
       $rdn= $this->create_initial_rdn($pattern);
       $attribute= preg_replace('/=.*$/', '', $rdn);
@@ -1211,7 +1233,7 @@ class user extends plugin
     } else {
 
       $pt= "";
-      if($this->config->get_cfg_value("personalTitleInDN") == "true"){
+      if($this->config->get_cfg_value("core","personalTitleInDN") == "true"){
         if(!empty($this->personalTitle)){
           $pt = $this->personalTitle." ";
         }
@@ -1220,7 +1242,7 @@ class user extends plugin
       $this->cn= $pt.$this->givenName." ".$this->sn;
 
       /* Permissions for that base? */
-      if ($this->config->get_cfg_value("accountPrimaryAttribute") == "uid"){
+      if ($this->config->get_cfg_value("core","accountPrimaryAttribute") == "uid"){
         $this->new_dn= 'uid='.$this->uid.','.get_people_ou().$this->base;
       } else {
         /* Don't touch dn, if cn hasn't changed */
@@ -1265,8 +1287,19 @@ class user extends plugin
     /* Check if we are allowed to create/move this user */
     if($this->orig_dn == "new" && !$this->acl_is_createable($this->base)){
       $message[]= msgPool::permCreate();
-    }elseif($this->orig_dn != "new" && $this->new_dn != $this->orig_dn && !$this->acl_is_moveable($this->base)){
-      $message[]= msgPool::permMove();
+    }elseif($this->orig_dn != "new" && $this->new_dn != $this->orig_dn){
+
+        /* Check if the objects dn has changed while the base was left unchanged. 
+         * In this case we've to check move permissions for the object itself.
+         * 
+         * If the base has changed then we've to check the permission for the destination
+         *  base.
+         */
+        if($this->orig_base == $this->base && !$this->acl_is_moveable($this->dn)){
+            $message[]= msgPool::permMove();
+        }elseif($this->orig_base != $this->base && !$this->acl_is_moveable($this->base)){
+            $message[]= msgPool::permMove();
+        }
     }
 
     /* UID already used? */
@@ -1283,6 +1316,11 @@ class user extends plugin
       $message[]= msgPool::required(_("Name"));
     }
 
+    // Check if a wrong base was supplied
+    if(!$this->baseSelector->checkLastBaseUpdate()){
+      $message[]= msgPool::check_base();;
+    }
+
     if (!$this->is_template){
       if ($this->givenName == ""){
         $message[]= msgPool::required(_("Given name"));
@@ -1290,7 +1328,7 @@ class user extends plugin
       if ($this->uid == ""){
         $message[]= msgPool::required(_("Login"));
       }
-      if ($this->config->get_cfg_value("accountPrimaryAttribute") != "uid"){
+      if ($this->config->get_cfg_value("core","accountPrimaryAttribute") != "uid"){
         $ldap->cat($this->new_dn);
         if ($ldap->count() != 0 && $this->dn != $this->new_dn && $this->dn == 'new'){
           $message[]= msgPool::duplicated(_("Name"));
@@ -1345,10 +1383,15 @@ class user extends plugin
   /* Indicate whether a password change is needed or not */
   function password_change_needed()
   {
-    if(in_array("pw_storage",$this->multi_boxes)){
-      return(TRUE);
+    if($this->multiple_support_active){
+      return(FALSE);
+    }else{
+
+      if(in_array_strict("pw_storage",$this->multi_boxes)){
+        return(TRUE);
+      }
+      return($this->pw_storage != $this->last_pw_storage && !$this->is_template);
     }
-    return($this->pw_storage != $this->last_pw_storage && !$this->is_template);
   }
 
 
@@ -1380,11 +1423,11 @@ class user extends plugin
   {
     $ds= ldap_connect($this->config->current['SERVER']);
     ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
-    if (function_exists("ldap_set_rebind_proc") && $this->config->get_cfg_value("ldapFollowReferrals") == "true"){
+    if (function_exists("ldap_set_rebind_proc") && $this->config->get_cfg_value("core","ldapFollowReferrals") == "true"){
       ldap_set_option($this->cid, LDAP_OPT_REFERRALS, 1);
       ldap_set_rebind_proc($ds, array(&$this, "rebind"));
     }
-    if ($this->config->get_cfg_value("ldapTLS") == "true"){
+    if ($this->config->get_cfg_value("core","ldapTLS") == "true"){
       ldap_start_tls($ds);
     }
 
@@ -1430,7 +1473,7 @@ class user extends plugin
   /* Load certificate from file to object */
   function set_cert($cert, $filename)
   {
-    if(!$this->acl_is_writeable("Certificate",(!is_object($this->parent) && !session::is_set('edit')))) return;
+    if(!$this->acl_is_writeable("Certificate")) return;
     $fd = fopen ($filename, "rb");
     if (filesize($filename)>0) {
       $this->$cert= fread ($fd, filesize ($filename));
@@ -1459,13 +1502,14 @@ class user extends plugin
 
     /* Get base */
     $this->base= preg_replace('/^[^,]+,'.preg_quote(get_people_ou(), '/').'/i', '', $dn);
+    $this->baseSelector->setBase($this->base);
 
     if($this->governmentmode){
 
       /* Walk through govattrs */
       foreach ($this->govattrs as $val){
 
-        if (in_array($val, $skip)){
+        if (in_array_strict($val, $skip)){
           continue;
         }
 
@@ -1492,6 +1536,17 @@ class user extends plugin
       $this->sn= $this->parent->sn;
       $this->givenName= $this->parent->givenName;
     }
+
+    /* Generate dateOfBirth entry */
+    if (isset ($this->attrs['dateOfBirth'])){
+      /* This entry is ISO 8601 conform */
+      list($year, $month, $day)= explode("-", $this->attrs['dateOfBirth'][0], 3);
+    
+      #TODO: use $lang to convert date
+      $this->dateOfBirth= "$day.$month.$year";
+    } else {
+      $this->dateOfBirth= "";
+    }
   }
 
  
@@ -1521,12 +1576,12 @@ class user extends plugin
     $smarty->assign("passwordTodo","clear");
 
     if(isset($_POST['passwordTodo'])){
-      $smarty->assign("passwordTodo",$_POST['passwordTodo']);
+      $smarty->assign("passwordTodo",set_post(get_post('passwordTodo')));
     }
 
-    $smarty->assign("sn",       $this->sn);
-    $smarty->assign("givenName",$this->givenName);
-    $smarty->assign("uid",      $this->uid);
+    $smarty->assign("sn",       set_post($this->sn));
+    $smarty->assign("givenName",set_post($this->givenName));
+    $smarty->assign("uid",      set_post($this->uid));
     $smarty->assign("rand",     $rand);
     $str = $smarty->fetch(get_template_path("paste_generic.tpl",TRUE,dirname(__FILE__)));
 
@@ -1543,7 +1598,7 @@ class user extends plugin
     $this->set_acl_base($this->base);
 
     if((isset($_FILES['picture_file']['tmp_name'])) && ($_FILES['picture_file']['size'] > 0)){
-      $this->set_picture($_FILES['picture_file']['tmp_name']);
+      $this->set_picture(gosa_file_name($_FILES['picture_file']['tmp_name']));
     }
 
     /* Remove picture? */
@@ -1556,7 +1611,7 @@ class user extends plugin
     $attrs = array("uid","givenName","sn");
     foreach($attrs as $attr){
       if(isset($_POST[$attr])){
-        $this->$attr = $_POST[$attr];
+        $this->$attr = get_post($attr);
       }
     } 
   }
@@ -1576,6 +1631,20 @@ class user extends plugin
     $this->old_userPKCS12= "";
     $this->old_userSMIMECertificate= "";
     $this->old_userCertificate= "";
+
+    /* Generate dateOfBirth entry */
+    if (isset ($source['dateOfBirth'])){
+        list($year, $month, $day)= explode("-", $source['dateOfBirth'][0], 3);
+        $this->dateOfBirth= "$day.$month.$year";
+    } else {
+        $this->dateOfBirth= "";
+    }
+
+    // Try to load the user picture
+    $tmp_dn = $this->dn;
+    $this->dn = $source['dn'];
+    $this->load_picture();
+    $this->dn = $tmp_dn;
   }
 
 
@@ -1607,11 +1676,35 @@ class user extends plugin
         "plCategory"    => array("users" => array("description" => _("Users"),
                                                   "objectClass" => "gosaAccount")),
 
+        "plRequirements"=> array(
+            'ldapSchema' => array(
+                'gosaAccount' => '>=2.7',
+                'gosaUserTemplate' => '>=2.7'
+                ),
+            'onFailureDisablePlugin' => array(get_class(),'userManagement', 'user')
+            ),
+
+        "plProperties" => array(
+            array(
+                "name"          => "accountRDN",
+                "type"          => "string",
+                "default"       => "",
+                "description"   =>  _("Pattern for the generation of user DNs. Please read the FAQ for details."),
+                "check"         => "gosaProperty::isString",
+                "migrate"       => "",
+                "group"         => "plugin",
+                "mandatory"     => FALSE
+                )
+
+            ),
         "plProvidedAcls" => array(
 
           "sn"                => _("Surname"),
           "givenName"         => _("Given name"),
-          "uid"               => _("User identification"),
+          "uid"               => _("Login"),
+
+          "gosaUserDefinedFilter"  => _("Allow definition of custom filters"),
+
           "personalTitle"     => _("Personal title"),
           "academicTitle"     => _("Academic title"),
 
@@ -1622,14 +1715,17 @@ class user extends plugin
 
           "userPicture"       => _("User picture"),
 
+          "gosaLoginRestriction" => _("Login restrictions"),         
+
           "o"                 => _("Organization"),
           "ou"                => _("Department"),
           "departmentNumber"  => _("Department number"),
+          "manager"           => _("Manager"),
           "employeeNumber"    => _("Employee number"),
           "employeeType"      => _("Employee type"),
 
           "roomNumber"        => _("Room number"),
-          "telephoneNumber"   => _("Telefon number"),
+          "telephoneNumber"   => _("Telephone number"),
           "pager"             => _("Pager number"),
           "mobile"            => _("Mobile number"),
           "facsimileTelephoneNumber"     => _("Fax number"),
@@ -1646,23 +1742,23 @@ class user extends plugin
 
         );
 
-    /* Append government attributes if required */
-    global $config;
-    if($config->get_cfg_value("honourIvbbAttributes") == "true"){
-      foreach($govattrs as $attr => $desc){
-        $ret["plProvidedAcls"][$attr] = $desc;
-      }
-    }
+#   /* Append government attributes if required */
+#   global $config;
+#   if($config->get_cfg_value("core","honourIvbbAttributes") == "true"){
+#     foreach($govattrs as $attr => $desc){
+#       $ret["plProvidedAcls"][$attr] = $desc;
+#     }
+#   }
     return($ret);
   }
 
   function get_multi_edit_values()
   {
     $ret = plugin::get_multi_edit_values();
-    if(in_array("pw_storage",$this->multi_boxes)){
+    if(in_array_strict("pw_storage",$this->multi_boxes)){
       $ret['pw_storage'] = $this->pw_storage;
     }
-    if(in_array("edit_picture",$this->multi_boxes)){
+    if(in_array_strict("edit_picture",$this->multi_boxes)){
       $ret['jpegPhoto'] = $this->jpegPhoto;
       $ret['photoData'] = $this->photoData;
       $ret['old_jpegPhoto'] = $this->old_jpegPhoto;
@@ -1675,23 +1771,30 @@ class user extends plugin
       unset($ret['cn']);
     }
     $ret['is_modified'] = $this->is_modified;
-    if(in_array("base",$this->multi_boxes)){
+    if(in_array_strict("base",$this->multi_boxes)){
       $ret['orig_base']="Changed_by_Multi_Plug";
       $ret['base']=$this->base;
     }
+
+    $ret['gosaLoginRestriction'] = $this->gosaLoginRestriction;
+    $ret['gosaLoginRestriction_some'] = $this->gosaLoginRestriction_some;
+
     return($ret); 
   }
 
 
   function multiple_save_object()
   {
+
+    if(!isset($_POST['user_mulitple_edit'])) return;
+
     plugin::multiple_save_object();
 
     /* Get pw_storage mode */
     if (isset($_POST['pw_storage'])){
       foreach(array("pw_storage") as $val){
         if(isset($_POST[$val])){
-          $data= validate(get_post($val));
+          $data= get_post($val);
           if ($data != $this->$val){
             $this->is_modified= TRUE;
           }
@@ -1699,8 +1802,15 @@ class user extends plugin
         }
       }
     }
-    if(isset($_POST['base'])){
-      $this->base = get_post('base');
+  
+    /* Refresh base */
+    if ($this->acl_is_moveable($this->base)){
+      if (!$this->baseSelector->update()) {
+        msg_dialog::display(_("Error"), msgPool::permMove(), ERROR_DIALOG);
+      }
+      if ($this->base != $this->baseSelector->getBase()) {
+        $this->base= $this->baseSelector->getBase();
+      }
     }
 
     if(isset($_POST['user_mulitple_edit'])){
@@ -1710,6 +1820,12 @@ class user extends plugin
         }
       }
     }
+
+    /* Sync lists */
+    $this->gosaLoginRestrictionWidget->save_object();
+    if ($this->gosaLoginRestrictionWidget->isModified()) {
+      $this->gosaLoginRestriction= array_values($this->gosaLoginRestrictionWidget->getMaintainedData());
+    }
   }
 
   
@@ -1722,25 +1838,25 @@ class user extends plugin
     if($this->dn == "new") {
       $this->set_acl_base($this->base);
     }
-    if (!tests::is_url($this->labeledURI) && in_array("labeledURI",$this->multi_boxes)){
+    if (!tests::is_url($this->labeledURI) && in_array_strict("labeledURI",$this->multi_boxes)){
       $message[]= msgPool::invalid(_("Homepage"));
     }
-    if (!tests::is_phone_nr($this->telephoneNumber) && in_array("telephoneNumber",$this->multi_boxes)){
+    if (!tests::is_phone_nr($this->telephoneNumber) && in_array_strict("telephoneNumber",$this->multi_boxes)){
       $message[]= msgPool::invalid(_("Phone"), $this->telephoneNumber, "/[\/0-9 ()+*-]/");
     }
-    if (!tests::is_phone_nr($this->facsimileTelephoneNumber) &&  in_array("facsimileTelephoneNumber",$this->multi_boxes)){
+    if (!tests::is_phone_nr($this->facsimileTelephoneNumber) &&  in_array_strict("facsimileTelephoneNumber",$this->multi_boxes)){
       $message[]= msgPool::invalid(_("Fax"), $this->facsimileTelephoneNumber, "/[\/0-9 ()+*-]/");
     }
-    if (!tests::is_phone_nr($this->mobile) && in_array("mobile",$this->multi_boxes)){
+    if (!tests::is_phone_nr($this->mobile) && in_array_strict("mobile",$this->multi_boxes)){
       $message[]= msgPool::invalid(_("Mobile"), $this->mobile, "/[\/0-9 ()+*-]/");
     }
-    if (!tests::is_phone_nr($this->pager) && in_array("pager",$this->multi_boxes)){
+    if (!tests::is_phone_nr($this->pager) && in_array_strict("pager",$this->multi_boxes)){
       $message[]= msgPool::invalid(_("Pager"), $this->pager, "/[\/0-9 ()+*-]/");
     }
-    if (preg_match ('/[,+"?\'()=<>;\\\\]/', $this->givenName) && in_array("givenName",$this->multi_boxes)){
+    if (preg_match ('/[,+"?\'()=<>;\\\\]/', $this->givenName) && in_array_strict("givenName",$this->multi_boxes)){
       $message[]= msgPool::invalid(_("Given name"), $this->giveName, '/[^,+"?\'()=<>;\\\\]/');
     }
-    if (preg_match ('/[,+"?\'()=<>;\\\\]/', $this->sn) && in_array("sn",$this->multi_boxes)){
+    if (preg_match ('/[,+"?\'()=<>;\\\\]/', $this->sn) && in_array_strict("sn",$this->multi_boxes)){
       $message[]= msgPool::invalid(_("Name"), $this->sn, '/[^,+"?\'()=<>;\\\\]/');
     }
     return($message);
@@ -1754,6 +1870,89 @@ class user extends plugin
   }
 
 
+  /*! \brief  Prepares the plugin to be used for multiple edit
+   *          Update plugin attributes with given array of attribtues.
+   *  \param  array   Array with attributes that must be updated.
+   */
+  function init_multiple_support($attrs,$all)
+  {
+    plugin::init_multiple_support($attrs,$all);
+
+    // Get login restrictions
+    if(isset($attrs['gosaLoginRestriction'])){
+      $this->gosaLoginRestriction  =array();
+      for($i =0;$i < $attrs['gosaLoginRestriction']['count']; $i++){
+        $this->gosaLoginRestriction[] = $attrs['gosaLoginRestriction'][$i];
+      }
+    }
+
+    // Detect the managers name
+    $this->manager_name = "";
+    $ldap = $this->config->get_ldap_link();
+    if(!empty($this->manager)){
+      $ldap->cat($this->manager, array('cn'));
+      if($ldap->count()){
+        $attrs = $ldap->fetch();
+        $this->manager_name = $attrs['cn'][0];
+      }else{
+        $this->manager_name = "("._("unknown")."!): ".$this->manager;
+      }
+    }
+
+    // Detect login restriction not used in all user objects.
+    $this->gosaLoginRestriction_some = array();
+    if(isset($all['gosaLoginRestriction'])){
+      for($i=0;$i<$all['gosaLoginRestriction']['count'];$i++){
+        $this->gosaLoginRestriction_some[] = $all['gosaLoginRestriction'][$i];
+      }
+    }
+
+
+    // Reinit the login restriction list.
+    $data = $this->convertLoginRestriction();
+    if(count($data)){
+      $this->gosaLoginRestrictionWidget->setListData($data['data'], $data['displayData']);
+    }
+  }
+
+
+  function set_multi_edit_values($attrs)
+  {
+    $lR = array();
+
+    // Update loginRestrictions, keep my settings while ip is optional
+    foreach($attrs['gosaLoginRestriction_some'] as $ip){
+      if(in_array_strict($ip, $this->gosaLoginRestriction) && in_array_strict($ip, $attrs['gosaLoginRestriction'])){
+        $lR[] = $ip;
+      }
+    }
+
+    // Add enforced loginRestrictions 
+    foreach($attrs['gosaLoginRestriction'] as $ip){
+      $lR[] = $ip;
+    }
+
+    $lR = array_values(array_unique($lR));
+    $this->is_modified |=  array_differs($this->gosaLoginRestriction, $lR);
+    plugin::set_multi_edit_values($attrs);
+    $this->gosaLoginRestriction = $lR;
+  }
+
+
+  function convertLoginRestriction()
+  {
+    $all = array_unique(array_merge($this->gosaLoginRestriction,$this->gosaLoginRestriction_some));
+    $data = array();
+    foreach($all as $ip){
+      $data['data'][] = $ip;
+      if(!in_array_strict($ip, $this->gosaLoginRestriction)){
+        $data['displayData'][] = array('mode' => LIST_MARKED , 'data' => array($ip.' ('._("Entries differ").')'));
+      }else{
+        $data['displayData'][] = array('mode' => 0 , 'data' => array($ip));
+      }
+    }   
+    return($data);
+  }
 }
 
 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: