Code

Replaced config->search with get_cfg_value
[gosa.git] / gosa-core / include / class_plugin.inc
index 31115eced96878a3e78414b3add8fb5d3c49ebd8..33f750a351abde4216839399a5784ca2d3519d83 100644 (file)
  */
 
 class plugin
  */
 
 class plugin
-{
+{ 
+  /*! \brief    The title shown in path menu while this plugin is visible.
+   */
+  var $pathTitle = "";
+
   /*!
     \brief Reference to parent object
 
   /*!
     \brief Reference to parent object
 
@@ -139,12 +143,24 @@ class plugin
     \param dn Distinguished name to initialize plugin from
     \sa plugin()
    */
     \param dn Distinguished name to initialize plugin from
     \sa plugin()
    */
-  function plugin (&$config, $dn= NULL, $parent= NULL)
+  function plugin (&$config, $dn= NULL, $object= NULL)
   {
     /* Configuration is fine, allways */
     $this->config= &$config;   
     $this->dn= $dn;
 
   {
     /* Configuration is fine, allways */
     $this->config= &$config;   
     $this->dn= $dn;
 
+    // Ensure that we've a valid acl_category set.
+    if(empty($this->acl_category)){
+      $tmp = $this->plInfo();
+      if (isset($tmp['plCategory'])) {
+        $c = key($tmp['plCategory']);
+        if(is_numeric($c)){
+          $c = $tmp['plCategory'][0];
+        }
+        $this->acl_category = $c."/";
+      }
+    }
+
     /* Handle new accounts, don't read information from LDAP */
     if ($dn == "new"){
       return;
     /* Handle new accounts, don't read information from LDAP */
     if ($dn == "new"){
       return;
@@ -167,8 +183,8 @@ class plugin
     if ($dn !== NULL){
 
       /* Load data to 'attrs' and save 'dn' */
     if ($dn !== NULL){
 
       /* Load data to 'attrs' and save 'dn' */
-      if ($parent !== NULL){
-        $this->attrs= $parent->attrs;
+      if ($object !== NULL){
+        $this->attrs= $object->attrs;
       } else {
         $ldap= $this->config->get_ldap_link();
         $ldap->cat ($dn);
       } else {
         $ldap= $this->config->get_ldap_link();
         $ldap->cat ($dn);
@@ -252,9 +268,7 @@ class plugin
   }
 
 
   }
 
 
-  /*! \brief execute plugin
-
-    Generates the html output for this node
+  /*! \brief Generates the html output for this node
    */
   function execute()
   {
    */
   function execute()
   {
@@ -263,11 +277,14 @@ class plugin
 
     /* Reset Lock message POST/GET check array, to prevent perg_match errors*/
     session::set('LOCK_VARS_TO_USE',array());
 
     /* Reset Lock message POST/GET check array, to prevent perg_match errors*/
     session::set('LOCK_VARS_TO_USE',array());
-    session::set('LOCK_VARS_USED',array());
+    session::set('LOCK_VARS_USED_GET',array());
+    session::set('LOCK_VARS_USED_POST',array());
+    session::set('LOCK_VARS_USED_REQUEST',array());
+
+    pathNavigator::registerPlugin($this);
   }
 
   }
 
-  /*! \brief execute plugin
-     Removes object from parent
+  /*! \brief Removes object from parent
    */
   function remove_from_parent()
   {
    */
   function remove_from_parent()
   {
@@ -305,7 +322,7 @@ class plugin
   }
 
 
   }
 
 
-  /*! \brief   Save HTML posted data to object 
+  /*! \brief Save HTML posted data to object 
    */
   function save_object()
   {
    */
   function save_object()
   {
@@ -316,7 +333,7 @@ class plugin
 
     /* Save values to object */
     foreach ($this->attributes as $val){
 
     /* Save values to object */
     foreach ($this->attributes as $val){
-      if ($this->acl_is_writeable($val) && isset ($_POST["$val"])){
+      if (isset ($_POST["$val"]) && $this->acl_is_writeable($val)){
         /* Check for modifications */
         if (get_magic_quotes_gpc()) {
           $data= stripcslashes($_POST["$val"]);
         /* Check for modifications */
         if (get_magic_quotes_gpc()) {
           $data= stripcslashes($_POST["$val"]);
@@ -343,7 +360,7 @@ class plugin
   }
 
 
   }
 
 
-  /* Save data to LDAP, depending on is_account we save or delete */
+  /*! \brief Save data to LDAP, depending on is_account we save or delete */
   function save()
   {
     /* include global link_info */
   function save()
   {
     /* include global link_info */
@@ -438,7 +455,7 @@ class plugin
     }
   }
 
     }
   }
 
-  /* Check formular input */
+  /*! \brief Check formular input */
   function check()
   {
     $message= array();
   function check()
   {
     $message= array();
@@ -449,8 +466,7 @@ class plugin
     }
 
     /* Find hooks entries for this class */
     }
 
     /* Find hooks entries for this class */
-    $command= $this->config->search(get_class($this), "CHECK", array('menu', 'tabs'));
-
+    $command = $config->configRegistry->getPropertyValue(get_class($plugin),"check");
     if ($command != ""){
 
       if (!check_command($command)){
     if ($command != ""){
 
       if (!check_command($command)){
@@ -507,7 +523,7 @@ class plugin
       $current_csn = getEntryCSN($this->dn);
       if($current_csn != $this->entryCSN && !empty($this->entryCSN) && !empty($current_csn)){
         $this->entryCSN = $current_csn;
       $current_csn = getEntryCSN($this->dn);
       if($current_csn != $this->entryCSN && !empty($this->entryCSN) && !empty($current_csn)){
         $this->entryCSN = $current_csn;
-        $message[] = _("The object has changed since opened in GOsa. All changes that may be done by others get lost if you save this entry!");
+        $message[] = _("The current object has been altered while beeing edited. If you save this entry, changes that have been made by others will be discarded!");
       }
     }
     return ($message);
       }
     }
     return ($message);
@@ -562,14 +578,14 @@ class plugin
     }
   }
 
     }
   }
 
-  /* Indicate whether a password change is needed or not */
+  /* \brief Indicate whether a password change is needed or not */
   function password_change_needed()
   {
     return FALSE;
   }
 
 
   function password_change_needed()
   {
     return FALSE;
   }
 
 
-  /* Show header message for tab dialogs */
+  /*! \brief Show header message for tab dialogs */
   function show_enable_header($button_text, $text, $disabled= FALSE)
   {
     if (($disabled == TRUE) || (!$this->acl_is_createable())){
   function show_enable_header($button_text, $text, $disabled= FALSE)
   {
     if (($disabled == TRUE) || (!$this->acl_is_createable())){
@@ -577,15 +593,16 @@ class plugin
     } else {
       $state= "";
     }
     } else {
       $state= "";
     }
-    $display= "<table summary=\"\" width=\"100%\"><tr>\n<td colspan=2><p><b>$text</b></p>\n";
-    $display.= "<input type=submit value=\"$button_text\" name=\"modify_state\" ".$state.
-      "><p class=\"seperator\">&nbsp;</p></td></tr></table>";
+    $display = "<div class='plugin-enable-header'>\n";
+    $display.= "<p>$text</p>\n";
+    $display.= "<button type='submit' name=\"modify_state\" ".$state.">$button_text</button>\n";
+    $display.= "</div>\n";
 
     return($display);
   }
 
 
 
     return($display);
   }
 
 
-  /* Show header message for tab dialogs */
+  /*! \brief Show header message for tab dialogs */
   function show_disable_header($button_text, $text, $disabled= FALSE)
   {
     if (($disabled == TRUE) || !$this->acl_is_removeable()){
   function show_disable_header($button_text, $text, $disabled= FALSE)
   {
     if (($disabled == TRUE) || !$this->acl_is_removeable()){
@@ -593,158 +610,48 @@ class plugin
     } else {
       $state= "";
     }
     } else {
       $state= "";
     }
-    $display= "<table summary=\"\" width=\"100%\"><tr>\n<td colspan=2><p><b>$text</b></p>\n";
-    $display.= "<input type=submit value=\"$button_text\" name=\"modify_state\" ".$state.
-      "><p class=\"seperator\">&nbsp;</p></td></tr></table>";
-
+    $display = "<div class='plugin-disable-header'>\n";
+    $display.= "<p>$text</p>\n";
+    $display.= "<button type='submit' name=\"modify_state\" ".$state.">$button_text</button>\n";
+    $display.= "</div>\n";
     return($display);
   }
 
 
     return($display);
   }
 
 
-  /* Show header message for tab dialogs */
-  function show_header($button_text, $text, $disabled= FALSE)
-  {
-    echo "FIXME: show_header should be replaced by show_disable_header and show_enable_header<br>";
-    if ($disabled == TRUE){
-      $state= "disabled";
-    } else {
-      $state= "";
-    }
-    $display= "<table summary=\"\" width=\"100%\"><tr>\n<td colspan=2><p><b>$text</b></p>\n";
-    $display.= "<input type=submit value=\"$button_text\" name=\"modify_state\" ".
-      ($this->acl_is_createable()?'':'disabled')." ".$state.
-      "><p class=\"seperator\">&nbsp;</p></td></tr></table>";
-
-    return($display);
-  }
-
 
 
-  function postcreate($add_attrs= array())
+  /* Create unique DN */
+  function create_unique_dn2($data, $base)
   {
   {
-    /* Find postcreate entries for this class */
-    $command= $this->config->search(get_class($this), "POSTCREATE",array('menu', 'tabs'));
-
-    if ($command != ""){
-
-      /* Walk through attribute list */
-      foreach ($this->attributes as $attr){
-        if (!is_array($this->$attr)){
-          $add_attrs[$attr] = $this->$attr;
-        }
-      }
-      $add_attrs['dn']=$this->dn;
-
-      $tmp = array();
-      foreach($add_attrs as $name => $value){
-        $tmp[$name] =  strlen($name);
-      }
-      arsort($tmp);
-      
-      /* Additional attributes */
-      foreach ($tmp as $name => $len){
-        $value = $add_attrs[$name];
-        $command= str_replace("%$name", "$value", $command);
-      }
+    $ldap= $this->config->get_ldap_link();
+    $base= preg_replace("/^,*/", "", $base);
 
 
-      if (check_command($command)){
-        @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
-            $command, "Execute");
-        exec($command,$arr);
-        foreach($arr as $str){
-          @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
-            $command, "Result: ".$str);
-        }
-      } else {
-        $message= msgPool::cmdnotfound("POSTCREATE", get_class($this));
-        msg_dialog::display(_("Error"), $message, ERROR_DIALOG);
-      }
+    /* Try to use plain entry first */
+    $dn= "$data,$base";
+    $attribute= preg_replace('/=.*$/', '', $data);
+    $ldap->cat ($dn, array('dn'));
+    if (!$ldap->fetch()){
+      return ($dn);
     }
     }
-  }
 
 
-  function postmodify($add_attrs= array())
-  {
-    /* Find postcreate entries for this class */
-    $command= $this->config->search(get_class($this), "POSTMODIFY",array('menu','tabs'));
-
-    if ($command != ""){
-
-      /* Walk through attribute list */
-      foreach ($this->attributes as $attr){
-        if (!is_array($this->$attr)){
-          $add_attrs[$attr] = $this->$attr;
-        }
-      }
-      $add_attrs['dn']=$this->dn;
-
-      $tmp = array();
-      foreach($add_attrs as $name => $value){
-        $tmp[$name] =  strlen($name);
-      }
-      arsort($tmp);
-      
-      /* Additional attributes */
-      foreach ($tmp as $name => $len){
-        $value = $add_attrs[$name];
-        $command= str_replace("%$name", "$value", $command);
+    /* Look for additional attributes */
+    foreach ($this->attributes as $attr){
+      if ($attr == $attribute || $this->$attr == ""){
+        continue;
       }
 
       }
 
-      if (check_command($command)){
-        @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,$command, "Execute");
-        exec($command,$arr);
-        foreach($arr as $str){
-          @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
-            $command, "Result: ".$str);
-        }
-      } else {
-        $message= msgPool::cmdnotfound("POSTMODIFY", get_class($this));
-        msg_dialog::display(_("Error"), $message, ERROR_DIALOG);
+      $dn= "$data+$attr=".$this->$attr.",$base";
+      $ldap->cat ($dn, array('dn'));
+      if (!$ldap->fetch()){
+        return ($dn);
       }
     }
       }
     }
-  }
-
-  function postremove($add_attrs= array())
-  {
-    /* Find postremove entries for this class */
-    $command= $this->config->search(get_class($this), "POSTREMOVE",array('menu','tabs'));
-    if ($command != ""){
-
-      /* Walk through attribute list */
-      foreach ($this->attributes as $attr){
-        if (!is_array($this->$attr)){
-          $add_attrs[$attr] = $this->$attr;
-        }
-      }
-      $add_attrs['dn']=$this->dn;
-
-      $tmp = array();
-      foreach($add_attrs as $name => $value){
-        $tmp[$name] =  strlen($name);
-      }
-      arsort($tmp);
-      
-      /* Additional attributes */
-      foreach ($tmp as $name => $len){
-        $value = $add_attrs[$name];
-        $command= str_replace("%$name", "$value", $command);
-      }
-
-      if (check_command($command)){
-        @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
-            $command, "Execute");
 
 
-        exec($command,$arr);
-        foreach($arr as $str){
-          @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,
-            $command, "Result: ".$str);
-        }
-      } else {
-        $message= msgPool::cmdnotfound("POSTREMOVE", get_class($this));
-        msg_dialog::display(_("Error"), $message, ERROR_DIALOG);
-      }
-    }
+    /* None found */
+    return ("none");
   }
 
   }
 
-  /* Create unique DN */
+
+  /*! \brief Create unique DN */
   function create_unique_dn($attribute, $base)
   {
     $ldap= $this->config->get_ldap_link();
   function create_unique_dn($attribute, $base)
   {
     $ldap= $this->config->get_ldap_link();
@@ -774,6 +681,7 @@ class plugin
     return ("none");
   }
 
     return ("none");
   }
 
+
   function rebind($ldap, $referral)
   {
     $credentials= LDAP::get_credentials($referral, $this->config->current['REFERRAL']);
   function rebind($ldap, $referral)
   {
     $credentials= LDAP::get_credentials($referral, $this->config->current['REFERRAL']);
@@ -851,6 +759,9 @@ class plugin
     /* FAIvariable=.../..., cn=.. 
         could not be saved, because the attribute FAIvariable was different to 
         the dn FAIvariable=..., cn=... */
     /* FAIvariable=.../..., cn=.. 
         could not be saved, because the attribute FAIvariable was different to 
         the dn FAIvariable=..., cn=... */
+
+    if(!is_array($new['objectClass'])) $new['objectClass'] = array($new['objectClass']);
+
     if(in_array_ics("FAIdebconfInfo",$new['objectClass'])){
       $new['FAIvariable'] = $ldap->fix($new['FAIvariable']);
     }
     if(in_array_ics("FAIdebconfInfo",$new['objectClass'])){
       $new['FAIvariable'] = $ldap->fix($new['FAIvariable']);
     }
@@ -908,14 +819,18 @@ class plugin
 
 
 
 
 
 
-  /*! \brief  Move a given ldap object indentified by $src_dn   \
-               to the given destination $dst_dn   \
-              * Ensure that all references are updated (ogroups) \
-              * Update ACLs   \
-              * Update accessTo   \
-      @param  String  The source dn.
-      @param  String  The destination dn.
-      @return Boolean TRUE on success else FALSE.
+  /*! \brief  Rename/Move a given src_dn to the given dest_dn
+   *
+   * Move a given ldap object indentified by $src_dn to the
+   * given destination $dst_dn
+   *
+   * - Ensure that all references are updated (ogroups)
+   * - Update ACLs   
+   * - Update accessTo
+   *
+   * \param  string  'src_dn' the source DN.
+   * \param  string  'dst_dn' the destination DN.
+   * \return boolean TRUE on success else FALSE.
    */
   function rename($src_dn, $dst_dn)
   {
    */
   function rename($src_dn, $dst_dn)
   {
@@ -926,8 +841,7 @@ class plugin
     $ldap->cd($this->config->current['BASE']);
     $ldap->create_missing_trees(preg_replace("/^[^,]+,/","",$dst_dn));
     if (!$ldap->rename_dn($src_dn,$dst_dn)){
     $ldap->cd($this->config->current['BASE']);
     $ldap->create_missing_trees(preg_replace("/^[^,]+,/","",$dst_dn));
     if (!$ldap->rename_dn($src_dn,$dst_dn)){
-#      msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $src_dn, "", get_class()));
-      new log("debug","Ldap Protocol v3 implementation error, ldap_rename failed, falling back to manual copy.","FROM: $src_dn  -- TO: $dst_dn",array(),$ldap->get_error());
+      new log("debug","LDAP protocol v3 implementation error, ldap_rename failed, falling back to manual copy.","FROM: $src_dn  -- TO: $dst_dn",array(),$ldap->get_error());
       @DEBUG(DEBUG_LDAP,__LINE__,__FUNCTION__,__FILE__,"Rename failed FROM: $src_dn  -- TO:  $dst_dn", 
           "Ldap Protocol v3 implementation error, falling back to maunal method.");
       return(FALSE);
       @DEBUG(DEBUG_LDAP,__LINE__,__FUNCTION__,__FILE__,"Rename failed FROM: $src_dn  -- TO:  $dst_dn", 
           "Ldap Protocol v3 implementation error, falling back to maunal method.");
       return(FALSE);
@@ -940,18 +854,21 @@ class plugin
           array("dn","objectClass"),GL_SUBSEARCH | GL_NO_ACL_CHECK);
     foreach($leaf_objs as $obj){
       $new_dn = $obj['dn'];
           array("dn","objectClass"),GL_SUBSEARCH | GL_NO_ACL_CHECK);
     foreach($leaf_objs as $obj){
       $new_dn = $obj['dn'];
-      $old_dn = preg_replace("/".preg_quote($dst_dn, '/')."$/i",$src_dn,$new_dn);
+      $old_dn = preg_replace("/".preg_quote(LDAP::convert($dst_dn), '/')."$/i",$src_dn,LDAP::convert($new_dn));
       $this->update_acls($old_dn,$new_dn); 
     }
 
     // Migrate objectgroups if needed
       $this->update_acls($old_dn,$new_dn); 
     }
 
     // Migrate objectgroups if needed
-    $ogroups = get_sub_list("(&(objectClass=gosaGroupOfNames)(member=".LDAP::prepare4filter(LDAP::fix($src_dn))."))","ogroups", array(get_ou("ogroupRDN")),$this->config->current['BASE'],array("dn"), GL_SUBSEARCH | GL_NO_ACL_CHECK);
+    $ogroups = get_sub_list("(&(objectClass=gosaGroupOfNames)(member=".LDAP::prepare4filter(LDAP::fix($src_dn))."))",
+      "ogroups", array(get_ou("ogroupRDN")),$this->config->current['BASE'],array("dn"), GL_SUBSEARCH | GL_NO_ACL_CHECK);
 
     // Walk through all objectGroups
     foreach($ogroups as $ogroup){
       // Migrate old to new dn
       $o_ogroup= new ogroup($this->config,$ogroup['dn']);
 
     // Walk through all objectGroups
     foreach($ogroups as $ogroup){
       // Migrate old to new dn
       $o_ogroup= new ogroup($this->config,$ogroup['dn']);
-      unset($o_ogroup->member[$src_dn]);
+      if (isset($o_ogroup->member[$src_dn])) {
+        unset($o_ogroup->member[$src_dn]);
+      }
       $o_ogroup->member[$dst_dn]= $dst_dn;
       
       // Save object group
       $o_ogroup->member[$dst_dn]= $dst_dn;
       
       // Save object group
@@ -959,16 +876,13 @@ class plugin
     }
 
     // Migrate rfc groups if needed
     }
 
     // Migrate rfc groups if needed
-    $groups = get_sub_list("(&(objectClass=posixGroups)(member=".LDAP::prepare4filter(LDAP::fix($src_dn))."))","groups", array(get_ou("groupRDN")),$this->config->current['BASE'],array("dn"), GL_SUBSEARCH | GL_NO_ACL_CHECK);
+    $groups = get_sub_list("(&(objectClass=posixGroup)(member=".LDAP::prepare4filter(LDAP::fix($src_dn))."))","groups", array(get_ou("groupRDN")),$this->config->current['BASE'],array("dn"), GL_SUBSEARCH | GL_NO_ACL_CHECK);
 
     // Walk through all POSIX groups
     foreach($groups as $group){
 
     // Walk through all POSIX groups
     foreach($groups as $group){
+
       // Migrate old to new dn
       $o_group= new group($this->config,$group['dn']);
       // Migrate old to new dn
       $o_group= new group($this->config,$group['dn']);
-      unset($o_group->member[$src_dn]);
-      $o_group->member[$dst_dn]= $dst_dn;
-      
-      // Save object group
       $o_group->save();
     }
 
       $o_group->save();
     }
 
@@ -984,6 +898,23 @@ class plugin
         $role->save();
       }
     }
         $role->save();
       }
     }
+
+    // Update 'manager' attributes from gosaDepartment and inetOrgPerson 
+    $filter = "(&(objectClass=inetOrgPerson)(manager=".LDAP::prepare4filter(LDAP::fix($src_dn))."))";
+    $ocs = $ldap->get_objectclasses();
+    if(isset($ocs['gosaDepartment']['MAY']) && in_array('manager', $ocs['gosaDepartment']['MAY'])){
+      $filter = "(|".$filter."(&(objectClass=gosaDepartment)(manager=".LDAP::prepare4filter(LDAP::fix($src_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' => $dst_dn);
+      $ldap->cd($entry['dn']);
+      $ldap->modify($update);
+      if(!$ldap->success()){
+        trigger_error(sprintf("Failed to update manager for %s: %s", bold($entry['dn']), $ldap->get_error()));
+      }
+    }
  
     /* Check if there are gosa departments moved. 
        If there were deps moved, the force reload of config->deps.
  
     /* Check if there are gosa departments moved. 
        If there were deps moved, the force reload of config->deps.
@@ -1003,7 +934,7 @@ class plugin
   }
 
 
   }
 
 
-
   function move($src_dn, $dst_dn)
   {
     /* Do not copy if only upper- lowercase has changed */
   function move($src_dn, $dst_dn)
   {
     /* Do not copy if only upper- lowercase has changed */
@@ -1044,7 +975,7 @@ class plugin
   }
 
 
   }
 
 
-  /* Move/Rename complete trees */
+  /* \brief Move/Rename complete trees */
   function recursive_move($src_dn, $dst_dn)
   {
     /* Check if the destination entry exists */
   function recursive_move($src_dn, $dst_dn)
   {
     /* Check if the destination entry exists */
@@ -1067,24 +998,6 @@ class plugin
   }
 
 
   }
 
 
-  function handle_post_events($mode, $add_attrs= array())
-  {
-    switch ($mode){
-      case "add":
-        $this->postcreate($add_attrs);
-      break;
-
-      case "modify":
-        $this->postmodify($add_attrs);
-      break;
-
-      case "remove":
-        $this->postremove($add_attrs);
-      break;
-    }
-  }
-
-
   function saveCopyDialog(){
   }
 
   function saveCopyDialog(){
   }
 
@@ -1094,6 +1007,7 @@ class plugin
   }
 
 
   }
 
 
+  /*! \brief Prepare for Copy & Paste */
   function PrepareForCopyPaste($source)
   {
     $todo = $this->attributes;
   function PrepareForCopyPaste($source)
   {
     $todo = $this->attributes;
@@ -1114,11 +1028,8 @@ class plugin
       if (isset($source[$var])){
         if(isset($source[$var]['count'])){
           if($source[$var]['count'] > 1){
       if (isset($source[$var])){
         if(isset($source[$var]['count'])){
           if($source[$var]['count'] > 1){
-            $this->$var = array();
-            $tmp = array();
-            for($i = 0 ; $i < $source[$var]['count']; $i++){
-              $tmp = $source[$var][$i];
-            }
+            $tmp= $source[$var];
+            unset($tmp['count']);
             $this->$var = $tmp;
           }else{
             $this->$var = $source[$var][0];
             $this->$var = $tmp;
           }else{
             $this->$var = $source[$var][0];
@@ -1130,12 +1041,13 @@ class plugin
     }
   }
 
     }
   }
 
-  function tag_attrs(&$at, $dn= "", $tag= "", $show= false)
-  {
-    /* Skip tagging? 
+  /*! \brief Get gosaUnitTag for the given DN
        If this is called from departmentGeneric, we have to skip this
         tagging procedure. 
        If this is called from departmentGeneric, we have to skip this
         tagging procedure. 
-     */
+    */
+  function tag_attrs(&$at, $dn= "", $tag= "", $show= false)
+  {
+    /* Skip tagging? */
     if($this->skipTagging){
       return;
     }
     if($this->skipTagging){
       return;
     }
@@ -1176,7 +1088,8 @@ class plugin
         }
       }
     }
         }
       }
     }
-  
+
+  /*! \brief Add unit tag */ 
     /* Remove tags that may already be here... */
     remove_objectClass("gosaAdministrativeUnitTag", $at);
     if (isset($at['gosaUnitTag'])){
     /* Remove tags that may already be here... */
     remove_objectClass("gosaAdministrativeUnitTag", $at);
     if (isset($at['gosaUnitTag'])){
@@ -1200,7 +1113,11 @@ class plugin
   }
 
 
   }
 
 
-  /* Add possibility to stop remove process */
+  /*! \brief Test for removability of the object
+   *
+   * Allows testing of conditions for removal of object. If removal should be aborted
+   * the function needs to remove an error message.
+   * */
   function allow_remove()
   {
     $reason= "";
   function allow_remove()
   {
     $reason= "";
@@ -1208,382 +1125,19 @@ class plugin
   }
 
 
   }
 
 
-  /* Create a snapshot of the current object */
-  function create_snapshot($type= "snapshot", $description= array())
-  {
-
-    /* Check if snapshot functionality is enabled */
-    if(!$this->snapshotEnabled()){
-      return;
-    }
-
-    /* Get configuration from gosa.conf */
-    $config = $this->config;
-
-    /* Create lokal ldap connection */
-    $ldap= $this->config->get_ldap_link();
-    $ldap->cd($this->config->current['BASE']);
-
-    /* check if there are special server configurations for snapshots */
-    if($config->get_cfg_value("snapshotURI") == ""){
-
-      /* Source and destination server are both the same, just copy source to dest obj */
-      $ldap_to      = $ldap;
-      $snapldapbase = $this->config->current['BASE'];
-
-    }else{
-      $server         = $config->get_cfg_value("snapshotURI");
-      $user           = $config->get_cfg_value("snapshotAdminDn");
-      $password       = $this->config->get_credentials($config->get_cfg_value("snapshotAdminPassword"));
-      $snapldapbase   = $config->get_cfg_value("snapshotBase");
-
-      $ldap_to        = new ldapMultiplexer(new LDAP($user,$password, $server));
-      $ldap_to -> cd($snapldapbase);
-
-      if (!$ldap_to->success()){
-        msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap_to->get_error(), $snapldapbase, "", get_class()));
-      }
-
-    }
-
-    /* check if the dn exists */ 
-    if ($ldap->dn_exists($this->dn)){
-
-      /* Extract seconds & mysecs, they are used as entry index */
-      list($usec, $sec)= explode(" ", microtime());
-
-      /* Collect some infos */
-      $base           = $this->config->current['BASE'];
-      $snap_base      = $config->get_cfg_value("snapshotBase");
-      $base_of_object = preg_replace ('/^[^,]+,/i', '', $this->dn);
-      $new_base       = preg_replace("/".preg_quote($base, '/')."$/","",$base_of_object).$snap_base;
-
-      /* Create object */
-#$data             = preg_replace('/^dn:.*\n/', '', $ldap->gen_ldif($this->dn,"(!(objectClass=gosaDepartment))"));
-      $data             = $ldap->gen_ldif($this->dn,"(&(!(objectClass=gosaDepartment))(!(objectClass=FAIclass)))");
-      $newName          = str_replace(".", "", $sec."-".$usec);
-      $target= array();
-      $target['objectClass']            = array("top", "gosaSnapshotObject");
-      $target['gosaSnapshotData']       = gzcompress($data, 6);
-      $target['gosaSnapshotType']       = $type;
-      $target['gosaSnapshotDN']         = $this->dn;
-      $target['description']            = $description;
-      $target['gosaSnapshotTimestamp']  = $newName;
-
-      /* Insert the new snapshot 
-         But we have to check first, if the given gosaSnapshotTimestamp
-         is already used, in this case we should increment this value till there is 
-         an unused value. */ 
-      $new_dn                           = "gosaSnapshotTimestamp=".$newName.",".$new_base;
-      $ldap_to->cat($new_dn);
-      while($ldap_to->count()){
-        $ldap_to->cat($new_dn);
-        $newName = str_replace(".", "", $sec."-".($usec++));
-        $new_dn                           = "gosaSnapshotTimestamp=".$newName.",".$new_base;
-        $target['gosaSnapshotTimestamp']  = $newName;
-      } 
-
-      /* Inset this new snapshot */
-      $ldap_to->cd($snapldapbase);
-      $ldap_to->create_missing_trees($snapldapbase);
-      $ldap_to->create_missing_trees($new_base);
-      $ldap_to->cd($new_dn);
-      $ldap_to->add($target);
-      if (!$ldap_to->success()){
-        msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap_to->get_error(), $new_dn, LDAP_ADD, get_class()));
-      }
-
-      if (!$ldap->success()){
-        msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $new_base, "", get_class()));
-      }
-
-    }
-  }
-
-  function remove_snapshot($dn)
-  {
-    $ui       = get_userinfo();
-    $old_dn   = $this->dn; 
-    $this->dn = $dn;
-    $ldap = $this->config->get_ldap_link();
-    $ldap->cd($this->config->current['BASE']);
-    $ldap->rmdir_recursive($this->dn);
-    if(!$ldap->success()){
-      msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn));
-    }
-    $this->dn = $old_dn;
-  }
-
-
-  /* returns true if snapshots are enabled, and false if it is disalbed
-     There will also be some errors psoted, if the configuration failed */
-  function snapshotEnabled()
-  {
-    return $this->config->snapshotEnabled();
-  }
-
-
-  /* Return available snapshots for the given base 
+  /*! \brief Test if snapshotting is enabled
+   *
+   * Test weither snapshotting is enabled or not. There will also be some errors posted,
+   * if the configuration failed 
+   * \return TRUE if snapshots are enabled, and FALSE if it is disabled
    */
    */
-  function Available_SnapsShots($dn,$raw = false)
-  {
-    if(!$this->snapshotEnabled()) return(array());
-
-    /* Create an additional ldap object which
-       points to our ldap snapshot server */
-    $ldap= $this->config->get_ldap_link();
-    $ldap->cd($this->config->current['BASE']);
-    $cfg= &$this->config->current;
-
-    /* check if there are special server configurations for snapshots */
-    if($this->config->get_cfg_value("snapshotURI") == ""){
-      $ldap_to      = $ldap;
-    }else{
-      $server         = $this->config->get_cfg_value("snapshotURI");
-      $user           = $this->config->get_cfg_value("snapshotAdminDn");
-      $password       = $this->config->get_credentials($this->config->get_cfg_value("snapshotAdminPassword"));
-      $snapldapbase   = $this->config->get_cfg_value("snapshotBase");
-      $ldap_to        = new ldapMultiplexer(new LDAP($user,$password, $server));
-      $ldap_to -> cd($snapldapbase);
-      if (!$ldap_to->success()){
-        msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap_to->get_error(), $snapldapbase, "", get_class()));
-      }
-    }
-
-    /* Prepare bases and some other infos */
-    $base           = $this->config->current['BASE'];
-    $snap_base      = $this->config->get_cfg_value("snapshotBase");
-    $base_of_object = preg_replace ('/^[^,]+,/i', '', $dn);
-    $new_base       = preg_replace("/".preg_quote($base, '/')."$/","",$base_of_object).$snap_base;
-    $tmp            = array(); 
-
-    /* Fetch all objects with  gosaSnapshotDN=$dn */
-    $ldap_to->cd($new_base);
-    $ldap_to->ls("(&(objectClass=gosaSnapshotObject)(gosaSnapshotDN=".$dn."))",$new_base,
-        array("gosaSnapshotType","gosaSnapshotTimestamp","gosaSnapshotDN","description")); 
-
-    /* Put results into a list and add description if missing */
-    while($entry = $ldap_to->fetch()){ 
-      if(!isset($entry['description'][0])){
-        $entry['description'][0]  = "";
-      }
-      $tmp[] = $entry; 
-    }
-
-    /* Return the raw array, or format the result */
-    if($raw){
-      return($tmp);
-    }else{  
-      $tmp2 = array();
-      foreach($tmp as $entry){
-        $tmp2[base64_encode($entry['dn'])] = $entry['description'][0]; 
-      }
-    }
-    return($tmp2);
-  }
-
-
-  function getAllDeletedSnapshots($base_of_object,$raw = false)
-  {
-    if(!$this->snapshotEnabled()) return(array());
-
-    /* Create an additional ldap object which
-       points to our ldap snapshot server */
-    $ldap= $this->config->get_ldap_link();
-    $ldap->cd($this->config->current['BASE']);
-    $cfg= &$this->config->current;
-
-    /* check if there are special server configurations for snapshots */
-    if($this->config->get_cfg_value("snapshotURI") == ""){
-      $ldap_to      = $ldap;
-    }else{
-      $server         = $this->config->get_cfg_value("snapshotURI");
-      $user           = $this->config->get_cfg_value("snapshotAdminDn");
-      $password       = $this->config->get_credentials($this->config->get_cfg_value("snapshotAdminPassword"));
-      $snapldapbase   = $this->config->get_cfg_value("snapshotBase");
-      $ldap_to        = new ldapMultiplexer(new LDAP($user,$password, $server));
-      $ldap_to -> cd($snapldapbase);
-      if (!$ldap_to->success()){
-        msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap_to->get_error(), $snapldapbase, "", get_class()));
-      }
-    }
-
-    /* Prepare bases */ 
-    $base           = $this->config->current['BASE'];
-    $snap_base      = $this->config->get_cfg_value("snapshotBase");
-    $new_base       = preg_replace("/".preg_quote($base, '/')."$/","",$base_of_object).$snap_base;
-
-    /* Fetch all objects and check if they do not exist anymore */
-    $ui = get_userinfo();
-    $tmp = array();
-    $ldap_to->cd($new_base);
-    $ldap_to->ls("(objectClass=gosaSnapshotObject)",$new_base,array("gosaSnapshotType","gosaSnapshotTimestamp","gosaSnapshotDN","description"));
-    while($entry = $ldap_to->fetch()){
-
-      $chk =  str_replace($new_base,"",$entry['dn']);
-      if(preg_match("/,ou=/",$chk)) continue;
-
-      if(!isset($entry['description'][0])){
-        $entry['description'][0]  = "";
-      }
-      $tmp[] = $entry; 
-    }
-
-    /* Check if entry still exists */
-    foreach($tmp as $key => $entry){
-      $ldap->cat($entry['gosaSnapshotDN'][0]);
-      if($ldap->count()){
-        unset($tmp[$key]);
-      }
-    }
-
-    /* Format result as requested */
-    if($raw) {
-      return($tmp);
-    }else{
-      $tmp2 = array();
-      foreach($tmp as $key => $entry){
-        $tmp2[base64_encode($entry['dn'])] = $entry['description'][0]; 
-      }
-    }
-    return($tmp2);
-  } 
-
-
-  /* Restore selected snapshot */
-  function restore_snapshot($dn)
-  {
-    if(!$this->snapshotEnabled()) return(array());
-
-    $ldap= $this->config->get_ldap_link();
-    $ldap->cd($this->config->current['BASE']);
-    $cfg= &$this->config->current;
-
-    /* check if there are special server configurations for snapshots */
-    if($this->config->get_cfg_value("snapshotURI") == ""){
-      $ldap_to      = $ldap;
-    }else{
-      $server         = $this->config->get_cfg_value("snapshotURI");
-      $user           = $this->config->get_cfg_value("snapshotAdminDn");
-      $password       = $this->config->get_credentials($this->config->get_cfg_value("snapshotAdminPassword"));
-      $snapldapbase   = $this->config->get_cfg_value("snapshotBase");
-      $ldap_to        = new ldapMultiplexer(new LDAP($user,$password, $server));
-      $ldap_to -> cd($snapldapbase);
-      if (!$ldap_to->success()){
-        msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap_to->get_error(), $snapldapbase, "", get_class()));
-      }
-    }
-
-    /* Get the snapshot */ 
-    $ldap_to->cat($dn);
-    $restoreObject = $ldap_to->fetch();
-
-    /* Prepare import string */
-    $data  = gzuncompress($ldap_to->get_attribute($dn,'gosaSnapshotData'));
-
-    /* Import the given data */
-    $err = "";
-    $ldap->import_complete_ldif($data,$err,false,false);
-    if (!$ldap->success()){
-      msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, "", get_class()));
-    }
-  }
-
-
-  function showSnapshotDialog($base,$baseSuffixe,&$parent)
+  function snapshotEnabled()
   {
   {
-    $once = true;
-    $ui = get_userinfo();
-    $this->parent = $parent;
-
-    foreach($_POST as $name => $value){
-
-      /* Create a new snapshot, display a dialog */
-      if(preg_match("/^CreateSnapShotDialog_[^_]*_[xy]$/",$name) && $once){
-
-                         $entry = base64_decode(preg_replace("/^CreateSnapShotDialog_([^_]*)_[xy]$/","\\1",$name));
-        $once = false;
-        $entry = preg_replace("/^CreateSnapShotDialog_/","",$entry);
-
-        if(!empty($entry) && $ui->allow_snapshot_create($entry,$this->parent->acl_module)){
-          $this->snapDialog = new SnapShotDialog($this->config,$entry,$this);
-        }else{
-          msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to create a snapshot for %s."),$entry),ERROR_DIALOG);
-        }
-      }  
-  
-      /* Restore a snapshot, display a dialog with all snapshots of the current object */
-      if(preg_match("/^RestoreSnapShotDialog_/",$name) && $once){
-        $once = false;
-        $entry = base64_decode(preg_replace("/^RestoreSnapShotDialog_([^_]*)_[xy]$/i","\\1",$name));
-        if(!empty($entry) && $ui->allow_snapshot_restore($this->dn,$this->parent->acl_module)){
-          $this->snapDialog = new SnapShotDialog($this->config,$entry,$this);
-          $this->snapDialog->display_restore_dialog = true;
-        }else{
-          msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s."),$entry),ERROR_DIALOG);
-        }
-      }
-
-      /* Restore one of the already deleted objects */
-      if(((isset($_POST['menu_action']) && $_POST['menu_action'] == "RestoreDeletedSnapShot") 
-          || preg_match("/^RestoreDeletedSnapShot_/",$name)) && $once){
-        $once = false;
-
-        if($ui->allow_snapshot_restore($this->dn,$this->parent->acl_module)){
-          $this->snapDialog = new SnapShotDialog($this->config,"",$this);
-          $this->snapDialog->set_snapshot_bases($baseSuffixe);
-          $this->snapDialog->display_restore_dialog      = true;
-          $this->snapDialog->display_all_removed_objects  = true;
-        }else{
-          msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s."),$base),ERROR_DIALOG);
-        }
-      }
-
-      /* Restore selected snapshot */
-      if(preg_match("/^RestoreSnapShot_/",$name) && $once){
-        $once = false;
-        $entry = base64_decode(preg_replace("/^RestoreSnapShot_([^_]*)_[xy]$/i","\\1",$name));
-
-        if(!empty($entry) && $ui->allow_snapshot_restore($this->dn,$this->parent->acl_module)){
-          $this->restore_snapshot($entry);
-          $this->snapDialog = NULL;
-        }else{
-          msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s."),$entry),ERROR_DIALOG);
-        }
-      }
-    }
-
-    /* Create a new snapshot requested, check
-       the given attributes and create the snapshot*/
-    if(isset($_POST['CreateSnapshot']) && is_object($this->snapDialog)){
-      $this->snapDialog->save_object();
-      $msgs = $this->snapDialog->check();
-      if(count($msgs)){
-        foreach($msgs as $msg){
-          msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
-        }
-      }else{
-        $this->dn =  $this->snapDialog->dn;
-        $this->create_snapshot("snapshot",$this->snapDialog->CurrentDescription);
-        $this->snapDialog = NULL;
-      }
-    }
-
-    /* Restore is requested, restore the object with the posted dn .*/
-    if((isset($_POST['RestoreSnapshot'])) && (isset($_POST['SnapShot']))){
-    }
-
-    if(isset($_POST['CancelSnapshot'])){
-      $this->snapDialog = NULL;
-    }
-
-    if(is_object($this->snapDialog )){
-      $this->snapDialog->save_object();
-      return($this->snapDialog->execute());
-    }
+      return $this->config->snapshotEnabled();
   }
 
 
   }
 
 
+  /*! \brief Return plugin informations for acl handling */
   static function plInfo()
   {
     return array();
   static function plInfo()
   {
     return array();
@@ -1592,12 +1146,14 @@ class plugin
 
   function set_acl_base($base)
   {
 
   function set_acl_base($base)
   {
+    @DEBUG (DEBUG_ACL, __LINE__, __FUNCTION__, __FILE__,"<b>".$base."</b>","<b>ACL-Base:</b> ");
     $this->acl_base= $base;
   }
 
 
   function set_acl_category($category)
   {
     $this->acl_base= $base;
   }
 
 
   function set_acl_category($category)
   {
+    @DEBUG (DEBUG_ACL, __LINE__, __FUNCTION__, __FILE__,"<b>".$category."</b>(/".get_class($this).")","<b>ACL-Category:</b> ");
     $this->acl_category= "$category/";
   }
 
     $this->acl_category= "$category/";
   }
 
@@ -1657,11 +1213,12 @@ class plugin
   }
 
 
   }
 
 
-  /*! \brief    Returns a list of all available departments for this object.  
-                If this object is new, all departments we are allowed to create a new user in are returned.
-                If this is an existing object, return all deps. we are allowed to move tis object too.
-
-      @return   Array [dn] => "..name"  // All deps. we are allowed to act on.
+  /*! \brief Returns a list of all available departments for this object.
+   * 
+   * If this object is new, all departments we are allowed to create a new user in
+   * are returned. If this is an existing object, return all deps. 
+   * We are allowed to move tis object too.
+   * \return array [dn] => "..name"  // All deps. we are allowed to act on.
   */
   function get_allowed_bases()
   {
   */
   function get_allowed_bases()
   {
@@ -1696,8 +1253,8 @@ class plugin
 
 
   /* This function updates ACL settings if $old_dn was used.
 
 
   /* This function updates ACL settings if $old_dn was used.
-   *  $old_dn   specifies the actually used dn
-   *  $new_dn   specifies the destiantion dn
+   *  \param string 'old_dn' specifies the actually used dn
+   *  \param string 'new_dn' specifies the destiantion dn
    */
   function update_acls($old_dn,$new_dn,$output_changes = FALSE)
   {
    */
   function update_acls($old_dn,$new_dn,$output_changes = FALSE)
   {
@@ -1727,7 +1284,7 @@ class plugin
         $acls = array();
         $found = false;
         for($i = 0 ; $i <  $attrs['gosaAclEntry']['count'] ; $i ++ ){
         $acls = array();
         $found = false;
         for($i = 0 ; $i <  $attrs['gosaAclEntry']['count'] ; $i ++ ){
-          $acl_parts = split(":",$attrs['gosaAclEntry'][$i]);
+          $acl_parts = explode(":",$attrs['gosaAclEntry'][$i]);
 
           /* Roles uses antoher data storage order, members are stored int the third part, 
              while the members in direct ACL assignments are stored in the second part.
 
           /* Roles uses antoher data storage order, members are stored int the third part, 
              while the members in direct ACL assignments are stored in the second part.
@@ -1760,8 +1317,7 @@ class plugin
         /* Acls for this object must be adjusted */
         if($found){
 
         /* Acls for this object must be adjusted */
         if($found){
 
-          $debug_info=  _("Changing ACL dn")."&nbsp;:&nbsp;<br>&nbsp;-"._("from")."&nbsp;<b>&nbsp;".
-            $old_dn."</b><br>&nbsp;-"._("to")."&nbsp;<b>".$new_dn."</b><br>";
+          $debug_info= sprintf(_("Changing ACL DN from %s to %s"), bold($old_dn), bold($new_dn));
           @DEBUG (DEBUG_ACL, __LINE__, __FUNCTION__, __FILE__,$debug_info,"ACL");
 
           $update[$attrs['dn']] =array();
           @DEBUG (DEBUG_ACL, __LINE__, __FUNCTION__, __FILE__,$debug_info,"ACL");
 
           $update[$attrs['dn']] =array();
@@ -1781,9 +1337,10 @@ class plugin
 
   
 
 
   
 
-  /* This function enables the entry Serial ID check.
-   * If an entry was edited while we have edited the entry too,
-   *  an error message will be shown. 
+  /*! \brief Enable the Serial ID check
+   *
+   * This function enables the entry Serial ID check.  If an entry was edited while
+   * we have edited the entry too, an error message will be shown. 
    * To configure this check correctly read the FAQ.
    */    
   function enable_CSN_check()
    * To configure this check correctly read the FAQ.
    */    
   function enable_CSN_check()
@@ -1795,7 +1352,7 @@ class plugin
 
   /*! \brief  Prepares the plugin to be used for multiple edit
    *          Update plugin attributes with given array of attribtues.
 
   /*! \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.
+   *  \param  array   Array with attributes that must be updated.
    */
   function init_multiple_support($attrs,$all)
   {
    */
   function init_multiple_support($attrs,$all)
   {
@@ -1806,9 +1363,10 @@ class plugin
     /* Copy needed attributes */
     foreach ($this->attributes as $val){
       $found= array_key_ics($val, $this->multi_attrs);
     /* Copy needed attributes */
     foreach ($this->attributes as $val){
       $found= array_key_ics($val, $this->multi_attrs);
       if ($found != ""){
       if ($found != ""){
-        if(isset($this->multi_attrs["$found"][0])){
-          $this->$val= $this->multi_attrs["$found"][0];
+        if(isset($this->multi_attrs["$val"][0])){
+          $this->$val= $this->multi_attrs["$val"][0];
         }
       }
     }
         }
       }
     }
@@ -1825,7 +1383,7 @@ class plugin
 
 
   /*! \brief  Returns all values that have been modfied in multiple edit mode.
 
 
   /*! \brief  Returns all values that have been modfied in multiple edit mode.
-      @return array Cotaining all mdofied values. 
+      \return array Cotaining all modified values. 
    */
   function get_multi_edit_values()
   {
    */
   function get_multi_edit_values()
   {
@@ -1849,10 +1407,7 @@ class plugin
   }
 
 
   }
 
 
-  /*! \brief execute plugin
-
-    Generates the html output for this node
-   */
+  /*! \brief Generates the html output for this node for multi edit*/
   function multiple_execute()
   {
     /* This one is empty currently. Fabian - please fill in the docu code */
   function multiple_execute()
   {
     /* This one is empty currently. Fabian - please fill in the docu code */
@@ -1860,13 +1415,15 @@ class plugin
 
     /* Reset Lock message POST/GET check array, to prevent perg_match errors*/
     session::set('LOCK_VARS_TO_USE',array());
 
     /* Reset Lock message POST/GET check array, to prevent perg_match errors*/
     session::set('LOCK_VARS_TO_USE',array());
-    session::set('LOCK_VARS_USED',array());
+    session::set('LOCK_VARS_USED_GET',array());
+    session::set('LOCK_VARS_USED_POST',array());
+    session::set('LOCK_VARS_USED_REQUEST',array());
     
     return("Multiple edit is currently not implemented for this plugin.");
   }
 
 
     
     return("Multiple edit is currently not implemented for this plugin.");
   }
 
 
-  /*! \brief   Save HTML posted data to object for multiple edit
+  /*! \brief Save HTML posted data to object for multiple edit
    */
   function multiple_save_object()
   {
    */
   function multiple_save_object()
   {
@@ -1883,7 +1440,7 @@ class plugin
         $this->multi_boxes[] = $val;
       }
 
         $this->multi_boxes[] = $val;
       }
 
-      if ($this->acl_is_writeable($val) && isset ($_POST["$val"])){
+      if (isset ($_POST["$val"]) && $this->acl_is_writeable($val)){
 
         /* Check for modifications */
         if (get_magic_quotes_gpc()) {
 
         /* Check for modifications */
         if (get_magic_quotes_gpc()) {
@@ -1905,7 +1462,7 @@ class plugin
   }
 
 
   }
 
 
-  /*! \brief  Returns all attributes of this plugin, 
+  /*! \brief Returns all attributes of this plugin, 
                to be able to detect multiple used attributes 
                in multi_plugg::detect_multiple_used_attributes().
       @return array Attributes required for intialization of multi_plug
                to be able to detect multiple used attributes 
                in multi_plugg::detect_multiple_used_attributes().
       @return array Attributes required for intialization of multi_plug
@@ -1918,7 +1475,7 @@ class plugin
 
 
   /*! \brief  Check given values in multiple edit
 
 
   /*! \brief  Check given values in multiple edit
-      @return array Error messages
+      \return array Error messages
    */
   function multiple_check()
   {
    */
   function multiple_check()
   {
@@ -1926,139 +1483,108 @@ class plugin
     return($message);
   }
 
     return($message);
   }
 
-
-  /*! \brief  Returns the snapshot header part for "Actions" menu in management dialogs 
-      @param  $layer_menu  
-   */   
-  function get_snapshot_header($base,$category)
+  function get_used_snapshot_bases()
   {
   {
-    $str = "";
-    $ui = get_userinfo();
-    if($this->snapshotEnabled() && $ui->allow_snapshot_restore($base,$category)){
-
-      $ok = false;
-      foreach($this->get_used_snapshot_bases() as $base){
-        $ok |= count($this->getAllDeletedSnapshots($base)) >= 1 ;
-      }
+     return(array());
+  }
 
 
-      if($ok){
-        $str = "..|<img class='center' src='images/lists/restore.png' ".
-          "alt='"._("Restore")."'>&nbsp;"._("Restore").                       "|RestoreDeletedSnapShot|\n";
-      }else{
-        $str = "..|<img class='center' src='images/lists/restore_grey.png' alt=''>&nbsp;"._("Restore")."||\n";
-      }
-    }
-    return($str);
+  function is_modal_dialog()
+  {
+    return(isset($this->dialog) && $this->dialog);
   }
 
 
   }
 
 
-  function get_snapshot_action($base,$category)
+  /*! \brief    Forward command execution requests
+   *             to the hook execution method. 
+   */
+  function handle_post_events($mode, $addAttrs= array())
   {
   {
-    $str= ""; 
-    $ui = get_userinfo();
-    if($this->snapshotEnabled()){
-      if ($ui->allow_snapshot_restore($base,$category)){
-
-        if(count($this->Available_SnapsShots($base))){
-          $str.= "<input class='center' type='image' src='images/lists/restore.png'
-            alt='"._("Restore snapshot")."' name='RestoreSnapShotDialog_".base64_encode($base)."' title='"._("Restore snapshot")."'>&nbsp;";
-        } else {
-          $str = "<img class='center' src='images/lists/restore_grey.png' alt=''>&nbsp;";
-        }
-      }
-      if($ui->allow_snapshot_create($base,$category)){
-        $str.= "<input class='center' type='image' src='images/snapshot.png'
-          alt='"._("Create snapshot")."' name='CreateSnapShotDialog_".base64_encode($base)."' 
-          title='"._("Create a new snapshot from this object")."'>&nbsp;";
-      }else{
-        $str = "<img class='center' src='images/empty.png' alt=' '>&nbsp;";
-      }
+    if(!in_array($mode, array('add','remove','modify'))){
+      trigger_error(sprintf("Invalid post event type given %s! Valid types are [add,modify,remove].", bold($mode)));
+      return;
     }
     }
+    switch ($mode){
+      case "add":
+        plugin::callHook($this,"POSTCREATE", $addAttrs);
+      break;
+
+      case "modify":
+        plugin::callHook($this,"POSTMODIFY", $addAttrs);
+      break;
 
 
-    return($str);
+      case "remove":
+        plugin::callHook($this,"POSTREMOVE", $addAttrs);
+      break;
+    }
   }
 
 
   }
 
 
-  function get_copypaste_action($base,$category,$class,$copy = TRUE, $cut = TRUE)
+  /*! \brief    Calls external hooks which are defined for this plugin (gosa.conf)
+   *            Replaces placeholder by class values of this plugin instance.
+   *  @param    Allows to a add special replacements.
+   */
+  static function callHook($plugin, $cmd, $addAttrs= array())
   {
   {
-    $ui = get_userinfo();
-    $action = "";
-    if($this->CopyPasteHandler){
-      if($cut){
-        if($ui->is_cutable($base,$category,$class)){
-          $action .= "<input class='center' type='image'
-            src='images/lists/cut.png' alt='"._("cut")."' name='cut_%KEY%' title='"._("Cut this entry")."'>&nbsp;";
-        }else{
-          $action.="<img src='images/empty.png' alt=' ' class='center'>&nbsp;";
-        }
-      }
-      if($copy){
-        if($ui->is_copyable($base,$category,$class)){
-          $action.= "<input class='center' type='image'
-            src='images/lists/copy.png' alt='"._("copy")."' name='copy_%KEY%' title='"._("Copy this entry")."'>&nbsp;";
-        }else{
-          $action.="<img src='images/empty.png' alt=' ' class='center'>&nbsp;";
+    global $config;
+    $command = $config->configRegistry->getPropertyValue(get_class($plugin),$cmd);
+    
+    if ($command != ""){
+
+      // Walk trough attributes list and add the plugins attributes. 
+      foreach ($plugin->attributes as $attr){
+        if (!is_array($plugin->$attr)){
+          $addAttrs[$attr] = $plugin->$attr;
         }
       }
         }
       }
-    }
+      $ui = get_userinfo();
+      $addAttrs['callerDN']=$ui->dn;
+      $addAttrs['dn']=$plugin->dn;
 
 
-    return($action); 
-  }
-
-
-  function get_copypaste_header($base,$category,$copy = TRUE, $cut = TRUE)
-  {
-    $s = "";
-    $ui =get_userinfo();
+      // Sort attributes by length, ensures correct replacement
+      $tmp = array();
+      foreach($addAttrs as $name => $value){
+        $tmp[$name] =  strlen($name);
+      }
+      arsort($tmp);
 
 
-    if(!is_array($category)){
-      $category = array($category);
-    }
+      // Now replace the placeholder 
+      foreach ($tmp as $name => $len){
+        $value = $addAttrs[$name];
+        $command= str_replace("%$name", "$value", $command);
+      }
 
 
-    /* Check permissions for each category, if there is at least one category which 
-        support read or paste permissions for the given base, then display the specific actions.
-     */
-    $readable = $pasteable = false;
-    foreach($category as $cat){
-      $readable= $readable || preg_match('/r/', $ui->get_category_permissions($base, $cat));
-      $pasteable= $pasteable || $ui->is_pasteable($base, $cat) == 1;
-    }
-  
-    if(($cut || $copy) && isset($this->CopyPasteHandler) && is_object($this->CopyPasteHandler)){
-      if($readable){
-        $s.= "..|---|\n";
-        if($copy){
-          $s.= "..|<img src='images/lists/copy.png' alt='' border='0' class='center'>".
-            "&nbsp;"._("Copy")."|"."multiple_copy_systems|\n";
-        }
-        if($cut){
-          $s.= "..|<img src='images/lists/cut.png' alt='' border='0' class='center'>".
-            "&nbsp;"._("Cut")."|"."multiple_cut_systems|\n";
+      // If there are still some %.. in our command, try to fill these with some other class vars 
+      if(preg_match("/%/",$command)){
+        $attrs = get_object_vars($plugin);
+        foreach($attrs as $name => $value){
+          if(is_array($value)){
+            $s = "";
+            foreach($value as $val){
+              if(is_string($val) || is_int($val) || is_float($val) || is_bool($val)){
+                $s .= '"'.$val.'",'; 
+              }
+            }
+            $value = '['.trim($s,',').']';
+          }
+          if(!is_string($value) && !is_int($value) && !is_float($value) && !is_bool($value)){
+            continue;
+          }
+          $command= preg_replace("/%$name/", $value, $command);
         }
       }
 
         }
       }
 
-      if($pasteable){
-        if($this->CopyPasteHandler->entries_queued()){
-          $img = "<img border='0' class='center' src='images/lists/paste.png' alt=''>";
-          $s.="..|".$img."&nbsp;"._("Paste")."|editPaste|\n";
-        }else{
-          $img = "<img border='0' class='center' src='images/lists/paste-grey.png' alt=''>";
-          $s.="..|".$img."&nbsp;"._("Paste")."\n";
+      if (check_command($command)){
+        @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,$command,"Execute");
+        exec($command,$arr);
+        if(is_array($arr)){
+          $str = implode("\n",$arr);
+          @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Result: ".$str);
         }
         }
+      } else {
+        $message= msgPool::cmdnotfound("POSTCREATE", get_class($plugin));
+        msg_dialog::display(_("Error"), $message, ERROR_DIALOG);
       }
     }
       }
     }
-    return($s);
-  }
-
-
-  function get_used_snapshot_bases()
-  {
-     return(array());
-  }
-
-  function is_modal_dialog()
-  {
-    return(isset($this->dialog) && $this->dialog);
   }
 }
 
   }
 }