Code

Added saving and loading of postalCode / street. Closes #1138.
[gosa.git] / gosa-core / plugins / personal / generic / class_user.inc
index 7c3d548460670122cbe5d85c1fac5b4f3ca380f6..f6de8cfad0f850a579116e6a91127c0270ed2d4f 100644 (file)
@@ -108,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");
+      "roomNumber", "telephoneNumber", "mobile", "pager", "cn", "userPKCS12", "street", "postalCode",
+      "postalAddress", "facsimileTelephoneNumber", "userSMIMECertificate", "gosaLoginRestriction", "manager");
 
   var $objectclasses= array("top", "person", "organizationalPerson", "inetOrgPerson",
       "gosaAccount");
@@ -255,6 +259,20 @@ class user extends plugin
     $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;
+      }
+    }
   }
 
 
@@ -286,6 +304,34 @@ 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 instanceOf singleUserSelect && count($this->dialog->detectPostActions())){
+      $users = $this->dialog->detectPostActions();
+      if(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());
@@ -308,16 +354,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();
@@ -328,26 +364,6 @@ class user extends plugin
       $this->dialog= false;
     }
 
-    /* Dialog handling */
-    if(is_object($this->dialog)){
-      /* Must be called before save_object */
-      $this->dialog->save_object();
-   
-      if($this->dialog->isClosed()){
-        $this->dialog = false;
-      }elseif($this->dialog->isSelected()){
-
-        /* check if selected base is allowed to move to / create a new object */
-        $tmp = $this->get_allowed_bases();
-        if(isset($tmp[$this->dialog->isSelected()])){
-          $this->base = $this->dialog->isSelected();
-        }
-        $this->dialog= false;
-      }else{
-        return($this->dialog->execute());
-      }
-    }
-
     /* Want password method editing? */
     if ($this->acl_is_writeable("userPassword")){
       if (isset($_POST['edit_pw_method'])){
@@ -564,7 +580,7 @@ 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("passwordDefaultHash");
     }
 
     $temp= passwordMethod::get_available_methods();
@@ -612,7 +628,11 @@ class user extends plugin
       $smarty->assign("$val"."ACL", $this->getacl($val,(!is_object($this->parent) && !session::is_set('edit'))));
     }
 
-    $smarty->assign("gosaLoginRestrictionACL", $this->getacl('gosaLoginRestriction', (!is_object($this->parent) && !session::is_set('edit'))));
+    // 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,(!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);
@@ -669,6 +689,7 @@ class user extends plugin
       $smarty->assign("has_phoneaccount", "false");
     }
     $smarty->assign("multiple_support" , $this->multiple_support_active);
+    $smarty->assign("manager_name",$this->manager_name);
     return($smarty->fetch (get_template_path('generic.tpl', TRUE, dirname(__FILE__))));
   }
 
@@ -712,10 +733,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('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"));
@@ -750,17 +787,6 @@ class user extends plugin
   /* Save data to object */
   function save_object()
   {
-    /* 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();
-        $this->is_modified= TRUE;
-      }
-    }
-      
     if(isset($_POST['generic']) || isset($_POST['multiple_user_posted'])){
 
       /* Make a backup of the current selected base */
@@ -769,10 +795,22 @@ 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 */
@@ -949,72 +987,57 @@ class user extends plugin
     /* Special handling for attribute jpegPhote needed, scale image via
        image magick to 147x200 pixels and inject resulting data. */
     if ($this->jpegPhoto == "*removed*"){
-    
-      /* Reset attribute to avoid writing *removed* as value */    
-      $this->attrs["jpegPhoto"] = array();
-
-    } 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);
+        /* Reset attribute to avoid writing *removed* as value */    
+        $this->attrs["jpegPhoto"] = array();
 
-        /* Save attribute */
-        $this->attrs["jpegPhoto"] = $output;
-
-      } else {
-
-        /* 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");
-        }
+    } else {
 
-        /* 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");
-        }
+       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);
 
-        /* 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");
-        }
+            unlink($fname);
 
-        /* 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");
+            /* 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);
         }
-
-        /* Sending Image */
-        $output=  $dump;
-
-        /* Save attribute */
-        $this->attrs["jpegPhoto"] = $output;
-      }
-
     }
 
     /* This only gets called when user is renaming himself */
@@ -1281,6 +1304,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"));
@@ -1343,10 +1371,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("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);
   }
 
 
@@ -1457,6 +1490,7 @@ 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){
 
@@ -1490,6 +1524,19 @@ 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= "";
+    }
+
   }
 
  
@@ -1574,6 +1621,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;
   }
 
 
@@ -1620,9 +1681,12 @@ 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"),
 
@@ -1677,12 +1741,19 @@ class user extends plugin
       $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 */
@@ -1697,7 +1768,7 @@ class user extends plugin
         }
       }
     }
-
+  
     /* Refresh base */
     if ($this->acl_is_moveable($this->base)){
       if (!$this->baseSelector->update()) {
@@ -1715,6 +1786,12 @@ class user extends plugin
         }
       }
     }
+
+    /* Sync lists */
+    $this->gosaLoginRestrictionWidget->save_object();
+    if ($this->gosaLoginRestrictionWidget->isModified()) {
+      $this->gosaLoginRestriction= array_values($this->gosaLoginRestrictionWidget->getMaintainedData());
+    }
   }
 
   
@@ -1759,6 +1836,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($ip, $this->gosaLoginRestriction) && in_array($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($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: