Code

Replaced config->search with get_cfg_value
[gosa.git] / gosa-core / include / class_plugin.inc
index 31d5b4bafd80e2c155c2852626394c08e60b80f1..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
 
@@ -113,6 +117,7 @@ class plugin
 
   var $acl_base= "";
   var $acl_category= "";
 
   var $acl_base= "";
   var $acl_category= "";
+  var $read_only = FALSE; // Used when the entry is opened as "readonly" due to locks.
 
   /* This can be set to render the tabulators in another stylesheet */
   var $pl_notify= FALSE;
 
   /* This can be set to render the tabulators in another stylesheet */
   var $pl_notify= FALSE;
@@ -138,17 +143,39 @@ 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;
     }
 
+    /* Check if this entry was opened in read only mode */
+    if(isset($_POST['open_readonly'])){
+      if(session::global_is_set("LOCK_CACHE")){
+        $cache = &session::get("LOCK_CACHE");
+        if(isset($cache['READ_ONLY'][$this->dn])){
+          $this->read_only = TRUE;
+        }
+      }
+    }
+
     /* Save current dn as acl_base */
     $this->acl_base= $dn;
 
     /* Save current dn as acl_base */
     $this->acl_base= $dn;
 
@@ -156,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);
@@ -168,7 +195,7 @@ class plugin
       foreach ($this->attributes as $val){
         $found= array_key_ics($val, $this->attrs);
         if ($found != ""){
       foreach ($this->attributes as $val){
         $found= array_key_ics($val, $this->attrs);
         if ($found != ""){
-          $this->$val= $this->attrs["$found"][0];
+          $this->$val= $found[0];
         }
       }
 
         }
       }
 
@@ -207,11 +234,12 @@ class plugin
       /* Prepare saved attributes */
       $this->saved_attributes= $this->attrs;
       foreach ($this->saved_attributes as $index => $value){
       /* Prepare saved attributes */
       $this->saved_attributes= $this->attrs;
       foreach ($this->saved_attributes as $index => $value){
-        if (preg_match('/^[0-9]+$/', $index)){
+        if (is_numeric($index)){
           unset($this->saved_attributes[$index]);
           continue;
         }
           unset($this->saved_attributes[$index]);
           continue;
         }
-        if (!in_array($index, $this->attributes) && $index != "objectClass"){
+
+        if (!in_array_ics($index, $this->attributes) && strcasecmp('objectClass', $index)){
           unset($this->saved_attributes[$index]);
           continue;
         }
           unset($this->saved_attributes[$index]);
           continue;
         }
@@ -229,6 +257,7 @@ class plugin
         }
         unset($this->saved_attributes["$index"]["count"]);
       }
         }
         unset($this->saved_attributes["$index"]["count"]);
       }
+
       if(isset($this->attrs['gosaUnitTag'])){
         $this->saved_attributes['gosaUnitTag'] = $this->attrs['gosaUnitTag'][0];
       }
       if(isset($this->attrs['gosaUnitTag'])){
         $this->saved_attributes['gosaUnitTag'] = $this->attrs['gosaUnitTag'][0];
       }
@@ -239,22 +268,23 @@ class plugin
   }
 
 
   }
 
 
-  /*! \brief execute plugin
-
-    Generates the html output for this node
+  /*! \brief Generates the html output for this node
    */
   function execute()
   {
     /* This one is empty currently. Fabian - please fill in the docu code */
    */
   function execute()
   {
     /* This one is empty currently. Fabian - please fill in the docu code */
-    session::set('current_class_for_help',get_class($this));
+    session::global_set('current_class_for_help',get_class($this));
 
     /* 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()
   {
@@ -292,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()
   {
@@ -303,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"]);
@@ -330,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 */
@@ -425,7 +455,7 @@ class plugin
     }
   }
 
     }
   }
 
-  /* Check formular input */
+  /*! \brief Check formular input */
   function check()
   {
     $message= array();
   function check()
   {
     $message= array();
@@ -436,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)){
@@ -494,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);
@@ -549,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())){
@@ -564,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()){
@@ -580,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= preg_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= preg_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= preg_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();
@@ -761,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']);
@@ -790,8 +711,9 @@ class plugin
       ldap_set_rebind_proc($ds, array(&$this, "rebind"));
     }
 
       ldap_set_rebind_proc($ds, array(&$this, "rebind"));
     }
 
-    $r=ldap_bind($ds,$this->config->current['ADMIN'], $this->config->current['PASSWORD']);
-    $sr=ldap_read($ds, @LDAP::fix($src_dn), "objectClass=*");
+    $pwd = $this->config->get_credentials($this->config->current['ADMINPASSWORD']);
+    $r=ldap_bind($ds,$this->config->current['ADMINDN'], $pwd);
+    $sr=ldap_read($ds, LDAP::fix($src_dn), "objectClass=*");
 
     /* Fill data from LDAP */
     $new= array();
 
     /* Fill data from LDAP */
     $new= array();
@@ -818,14 +740,14 @@ class plugin
     /* Adapt naming attribute */
     $dst_name= preg_replace("/^([^=]+)=.*$/", "\\1", $dst_dn);
     $dst_val = preg_replace("/^[^=]+=([^,+]+).*,.*$/", "\\1", $dst_dn);
     /* Adapt naming attribute */
     $dst_name= preg_replace("/^([^=]+)=.*$/", "\\1", $dst_dn);
     $dst_val = preg_replace("/^[^=]+=([^,+]+).*,.*$/", "\\1", $dst_dn);
-    $new[$dst_name]= @LDAP::fix($dst_val);
+    $new[$dst_name]= LDAP::fix($dst_val);
 
     /* Check if this is a department.
      * If it is a dep. && there is a , override in his ou 
      *  change \2C to , again, else this entry can't be saved ...
      */
     if((isset($new['ou'])) &&( preg_match("/\\,/",$new['ou']))){
 
     /* Check if this is a department.
      * If it is a dep. && there is a , override in his ou 
      *  change \2C to , again, else this entry can't be saved ...
      */
     if((isset($new['ou'])) &&( preg_match("/\\,/",$new['ou']))){
-      $new['ou'] = preg_replace("/\\\\,/",",",$new['ou']);
+      $new['ou'] = str_replace("\\\\,",",",$new['ou']);
     }
 
     /* Save copy */
     }
 
     /* Save copy */
@@ -837,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']);
     }
@@ -869,7 +794,7 @@ class plugin
     $ldap->cat($dst_dn);
     $attrs= $ldap->fetch();
     if (count($attrs)){
     $ldap->cat($dst_dn);
     $attrs= $ldap->fetch();
     if (count($attrs)){
-      trigger_error("Trying to overwrite ".@LDAP::fix($dst_dn).", which already exists.",
+      trigger_error("Trying to overwrite ".LDAP::fix($dst_dn).", which already exists.",
           E_USER_WARNING);
       return (FALSE);
     }
           E_USER_WARNING);
       return (FALSE);
     }
@@ -877,7 +802,7 @@ class plugin
     $ldap->cat($src_dn);
     $attrs= $ldap->fetch();
     if (!count($attrs)){
     $ldap->cat($src_dn);
     $attrs= $ldap->fetch();
     if (!count($attrs)){
-      trigger_error("Trying to move ".@LDAP::fix($src_dn).", which does not seem to exist.",
+      trigger_error("Trying to move ".LDAP::fix($src_dn).", which does not seem to exist.",
           E_USER_WARNING);
       return (FALSE);
     }
           E_USER_WARNING);
       return (FALSE);
     }
@@ -886,7 +811,7 @@ class plugin
     $ldap->search("objectClass=*",array("dn"));
     while($attrs = $ldap->fetch()){
       $src = $attrs['dn'];
     $ldap->search("objectClass=*",array("dn"));
     while($attrs = $ldap->fetch()){
       $src = $attrs['dn'];
-      $dst = preg_replace("/".normalizePreg($src_dn)."$/",$dst_dn,$attrs['dn']);
+      $dst = preg_replace("/".preg_quote($src_dn, '/')."$/",$dst_dn,$attrs['dn']);
       $this->_copy($src,$dst);
     }
     return (TRUE);
       $this->_copy($src,$dst);
     }
     return (TRUE);
@@ -894,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)
   {
@@ -911,77 +840,79 @@ class plugin
     $ldap = $this->config->get_ldap_link();
     $ldap->cd($this->config->current['BASE']);
     $ldap->create_missing_trees(preg_replace("/^[^,]+,/","",$dst_dn));
     $ldap = $this->config->get_ldap_link();
     $ldap->cd($this->config->current['BASE']);
     $ldap->create_missing_trees(preg_replace("/^[^,]+,/","",$dst_dn));
-
     if (!$ldap->rename_dn($src_dn,$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());
+      @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);
     }
 
       return(FALSE);
     }
 
-    /* Get list of groups within this tree,
+    /* Get list of users,groups and roles within this tree,
         maybe we have to update ACL references.
      */
         maybe we have to update ACL references.
      */
-    $leaf_groups = get_list("(objectClass=posixGroup)",array("all"),$dst_dn,
+    $leaf_objs = get_list("(|(objectClass=posixGroup)(objectClass=gosaAccount)(objectClass=gosaRole))",array("all"),$dst_dn,
           array("dn","objectClass"),GL_SUBSEARCH | GL_NO_ACL_CHECK);
           array("dn","objectClass"),GL_SUBSEARCH | GL_NO_ACL_CHECK);
-    
-    /* Get list of users within this tree,
-        maybe we have to update ACL references.
-     */
-    $leaf_users=  get_list("(objectClass=gosaAccount)",array("all"),$dst_dn,
-          array("dn","objectClass"),GL_SUBSEARCH | GL_NO_ACL_CHECK);
-
-
-    /* Updated acls set for this groups */
-    foreach($leaf_groups as $group){
-      $new_dn = $group['dn'];
-      $old_dn = preg_replace("/".normalizePreg($dst_dn)."$/i",$src_dn,$new_dn);
+    foreach($leaf_objs as $obj){
+      $new_dn = $obj['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); 
     }
 
       $this->update_acls($old_dn,$new_dn); 
     }
 
-    /* Updated acls set for this users */
-    foreach($leaf_users as $user){
-      $new_dn = $user['dn'];
-      $old_dn = preg_replace("/".normalizePreg($dst_dn)."$/i",$src_dn,$new_dn);
-      $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);
+
+    // Walk through all objectGroups
+    foreach($ogroups as $ogroup){
+      // Migrate old to new dn
+      $o_ogroup= new ogroup($this->config,$ogroup['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->save();
     }
 
     }
 
-    /* Get all objectGroups defined in this database. 
-        and check if there is an entry matching the source dn,
-        if this is the case, then update this objectgroup to use the new dn.
-     */
-    $ogroups = get_sub_list("(&(objectClass=gosaGroupOfNames)(member=*))","ogroups",
-        array(get_ou("ogroupou")),$this->config->current['BASE'],array("member"),
-        GL_SUBSEARCH | GL_NO_ACL_CHECK) ;
+    // Migrate rfc groups if needed
+    $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 objectGroups and check if there are 
-        members matching the source dn 
-     */
-    foreach($ogroups as $ogroup){
-      if(isset($ogroup['member'])){
+    // Walk through all POSIX groups
+    foreach($groups as $group){
 
 
-        /* Reset class object, this will be initialized with class_ogroup on demand 
-         */
-        $o_ogroup = NULL; 
-        for($i = 0 ; $i < $ogroup['member']['count'] ; $i ++){
+      // Migrate old to new dn
+      $o_group= new group($this->config,$group['dn']);
+      $o_group->save();
+    }
 
 
-          $c_mem = $ogroup['member'][$i];
-  
-          if(preg_match("/".normalizePreg($src_dn)."$/i",$c_mem)){
-            $d_mem = preg_replace("/".normalizePreg($src_dn)."$/i",$dst_dn,$ogroup['member'][$i]);
+    /* Update roles to use the new entry dn */
+    $roles = get_sub_list("(&(objectClass=organizationalRole)(roleOccupant=".LDAP::prepare4filter(LDAP::fix($src_dn))."))","roles", array(get_ou("roleRDN")),$this->config->current['BASE'],array("dn"), GL_SUBSEARCH | GL_NO_ACL_CHECK);
 
 
-            if($o_ogroup == NULL){
-              $o_ogroup = new ogroup($this->config,$ogroup['dn']);
-            }              
+    // Walk through all roles
+    foreach($roles as $role){
+      $role = new roleGeneric($this->config,$role['dn']);
+      $key= array_search($src_dn, $role->roleOccupant);      
+      if($key !== FALSE){
+        $role->roleOccupant[$key] = $dst_dn;
+        $role->save();
+      }
+    }
 
 
-            unset($o_ogroup->member[$c_mem]);
-            $o_ogroup->member[$d_mem]= $d_mem;
-          }
-        }
-       
-        /* Save object group if there were changes made on the membership */ 
-        if($o_ogroup != NULL){
-          $o_ogroup->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()));
       }
     }
  
       }
     }
  
@@ -994,7 +925,7 @@ class plugin
     if(count($leaf_deps)){
       $this->config->get_departments();
       $this->config->make_idepartments();
     if(count($leaf_deps)){
       $this->config->get_departments();
       $this->config->make_idepartments();
-      session::set("config",$this->config);
+      session::global_set("config",$this->config);
       $ui =get_userinfo();
       $ui->reset_acl_cache();
     }
       $ui =get_userinfo();
       $ui->reset_acl_cache();
     }
@@ -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;
     }
@@ -1158,7 +1070,7 @@ class plugin
           }
 
           /* This one matches with the latter part. Break and don't fix this entry */
           }
 
           /* This one matches with the latter part. Break and don't fix this entry */
-          if (preg_match('/(^|,)'.normalizePreg($key).'$/', $dn)){
+          if (preg_match('/(^|,)'.preg_quote($key, '/').'$/', $dn)){
             @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "DEBUG: Possibly relevant: $key", "Tagging");
             $relevant[strlen($key)]= $ntag;
             continue;
             @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, "DEBUG: Possibly relevant: $key", "Tagging");
             $relevant[strlen($key)]= $ntag;
             continue;
@@ -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,406 +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("snapshot_server") == ""){
-
-      /* 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("snapshot_server");
-      $user           = $config->get_cfg_value("snapshot_user");
-      $password       = $config->get_cfg_value("snapshot_password");
-      $snapldapbase   = $config->get_cfg_value("snapshot_base");
-
-      $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("snapshot_base");
-      $base_of_object = preg_replace ('/^[^,]+,/i', '', $this->dn);
-      $new_base       = preg_replace("/".normalizePreg($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          = preg_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 = preg_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($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()
-  {
-    $config = $this->config;
-    if($config->get_cfg_value("enable_snapshot") == "true"){
-           /* Check if the snapshot_base is defined */
-           if ($config->get_cfg_value("snapshot_base") == ""){
-                   msg_dialog::display(_("Configuration error"), sprintf(_("The snapshot functionality is enabled, but the required variable '%s' is not set."),"SNAPSHOT_BASE"), ERROR_DIALOG);
-                   return(FALSE);
-           }
-
-           /* check if there are special server configurations for snapshots */
-           if ($config->get_cfg_value("snapshot_server") != ""){
-
-                   /* check if all required vars are available to create a new ldap connection */
-                   $missing = "";
-                   foreach(array("snapshot_server","snapshot_user","snapshot_password","snapshot_base") as $var){
-                           if($config->get_cfg_value($var) == ""){
-                                   $missing .= $var." ";
-                                   msg_dialog::display(_("Configuration error"), sprintf(_("The snapshot functionality is enabled, but the required variable '%s' is not set."), $missing), ERROR_DIALOG);
-                                   return(FALSE);
-                           }
-                   }
-           }
-           return(TRUE);
-    }
-    return(FALSE);
-  }
-
-
-  /* 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(isset($cfg['SERVER']) && isset($cfg['SNAPSHOT_SERVER']) && $cfg['SERVER'] == $cfg['SNAPSHOT_SERVER']){
-      $ldap_to    = $ldap;
-    }elseif(isset($cfg['SNAPSHOT_SERVER'])){
-      $server       = $cfg['SNAPSHOT_SERVER'];
-      $user         = $cfg['SNAPSHOT_USER'];
-      $password     = $cfg['SNAPSHOT_PASSWORD'];
-      $snapldapbase = $cfg['SNAPSHOT_BASE'];
-
-      $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()));
-      }
-    }else{
-      $ldap_to    = $ldap;
-    }
-
-    /* Prepare bases and some other infos */
-    $base           = $this->config->current['BASE'];
-    $snap_base      = $cfg['SNAPSHOT_BASE'];
-    $base_of_object = preg_replace ('/^[^,]+,/i', '', $dn);
-    $new_base       = preg_replace("/".normalizePreg($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(isset($cfg['SNAPSHOT_SERVER'])){
-      $server       = $cfg['SNAPSHOT_SERVER'];
-      $user         = $cfg['SNAPSHOT_USER'];
-      $password     = $cfg['SNAPSHOT_PASSWORD'];
-      $snapldapbase = $cfg['SNAPSHOT_BASE'];
-      $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()));
-      }
-    }else{
-      $ldap_to    = $ldap;
-    }
-
-    /* Prepare bases */ 
-    $base           = $this->config->current['BASE'];
-    $snap_base      = $cfg['SNAPSHOT_BASE'];
-    $new_base       = preg_replace("/".normalizePreg($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(isset($cfg['SNAPSHOT_SERVER'])){
-      $server       = $cfg['SNAPSHOT_SERVER'];
-      $user         = $cfg['SNAPSHOT_USER'];
-      $password     = $cfg['SNAPSHOT_PASSWORD'];
-      $snapldapbase = $cfg['SNAPSHOT_BASE'];
-      $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()));
-      }
-    }else{
-      $ldap_to    = $ldap;
-    }
-
-    /* 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_/",$name) && $once){
-        $once = false;
-        $entry = preg_replace("/^CreateSnapShotDialog_/","",$name);
-        $entry = base64_decode(preg_replace("/_[xy]$/","",$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 = preg_replace("/^RestoreSnapShotDialog_/","",$name);
-        $entry = base64_decode(preg_replace("/_[xy]$/","",$entry));
-        if(!empty($entry) && $ui->allow_snapshot_restore($entry,$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($base,$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 = preg_replace("/^RestoreSnapShot_/","",$name);
-        $entry = base64_decode(trim(preg_replace("/_[xy]$/","",$entry)));
-        if(!empty($entry) && $ui->allow_snapshot_restore($entry,$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();
@@ -1616,18 +1146,21 @@ 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/";
   }
 
 
   function acl_is_writeable($attribute,$skip_write = FALSE)
   {
     $this->acl_category= "$category/";
   }
 
 
   function acl_is_writeable($attribute,$skip_write = FALSE)
   {
+    if($this->read_only) return(FALSE);
     $ui= get_userinfo();
     return preg_match('/w/', $ui->get_permissions($this->acl_base, $this->acl_category.get_class($this), $attribute, $skip_write));
   }
     $ui= get_userinfo();
     return preg_match('/w/', $ui->get_permissions($this->acl_base, $this->acl_category.get_class($this), $attribute, $skip_write));
   }
@@ -1642,6 +1175,7 @@ class plugin
 
   function acl_is_createable($base ="")
   {
 
   function acl_is_createable($base ="")
   {
+    if($this->read_only) return(FALSE);
     $ui= get_userinfo();
     if($base == "") $base = $this->acl_base;
     return preg_match('/c/', $ui->get_permissions($base, $this->acl_category.get_class($this), '0'));
     $ui= get_userinfo();
     if($base == "") $base = $this->acl_base;
     return preg_match('/c/', $ui->get_permissions($base, $this->acl_category.get_class($this), '0'));
@@ -1650,6 +1184,7 @@ class plugin
 
   function acl_is_removeable($base ="")
   {
 
   function acl_is_removeable($base ="")
   {
+    if($this->read_only) return(FALSE);
     $ui= get_userinfo();
     if($base == "") $base = $this->acl_base;
     return preg_match('/d/', $ui->get_permissions($base, $this->acl_category.get_class($this), '0'));
     $ui= get_userinfo();
     if($base == "") $base = $this->acl_base;
     return preg_match('/d/', $ui->get_permissions($base, $this->acl_category.get_class($this), '0'));
@@ -1658,6 +1193,7 @@ class plugin
 
   function acl_is_moveable($base = "")
   {
 
   function acl_is_moveable($base = "")
   {
+    if($this->read_only) return(FALSE);
     $ui= get_userinfo();
     if($base == "") $base = $this->acl_base;
     return preg_match('/m/', $ui->get_permissions($base, $this->acl_category.get_class($this), '0'));
     $ui= get_userinfo();
     if($base == "") $base = $this->acl_base;
     return preg_match('/m/', $ui->get_permissions($base, $this->acl_category.get_class($this), '0'));
@@ -1672,15 +1208,17 @@ class plugin
   function getacl($attribute,$skip_write= FALSE)
   {
     $ui= get_userinfo();
   function getacl($attribute,$skip_write= FALSE)
   {
     $ui= get_userinfo();
+    $skip_write |= $this->read_only;
     return  $ui->get_permissions($this->acl_base, $this->acl_category.get_class($this), $attribute,$skip_write);
   }
 
 
     return  $ui->get_permissions($this->acl_base, $this->acl_category.get_class($this), $attribute,$skip_write);
   }
 
 
-  /*! \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()
   {
@@ -1714,9 +1252,9 @@ class plugin
   }
 
 
   }
 
 
-  /* This function modifies object acls too, if an object is moved.
-   *  $old_dn   specifies the actually used dn
-   *  $new_dn   specifies the destiantion dn
+  /* This function updates ACL settings if $old_dn was used.
+   *  \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,11 +1265,11 @@ class plugin
     }
 
     /* Update userinfo if necessary */
     }
 
     /* Update userinfo if necessary */
-    $ui = session::get('ui');
+    $ui = session::global_get('ui');
     if($ui->dn == $old_dn){
       $ui->dn = $new_dn;
     if($ui->dn == $old_dn){
       $ui->dn = $new_dn;
-      session::set('ui',$ui);
-      new log("view","acl/".get_class($this),$this->dn,array(),"Updated current user dn from '".$old_dn."' to '".$new_dn."'");
+      session::global_set('ui',$ui);
+      new log("view","acl/".get_class($this),$this->dn,array(),"Updated current object dn from '".$old_dn."' to '".$new_dn."'");
     }
 
     /* Object was moved, ensure that all acls will be moved too */
     }
 
     /* Object was moved, ensure that all acls will be moved too */
@@ -1741,59 +1279,45 @@ class plugin
       $update = array();
       $ldap = $this->config->get_ldap_link();
       $ldap->cd ($this->config->current['BASE']);
       $update = array();
       $ldap = $this->config->get_ldap_link();
       $ldap->cd ($this->config->current['BASE']);
-      $ldap->search("(&(objectClass=gosaAcl)(gosaAclEntry=*))",array("cn","gosaAclEntry"));
+      $ldap->search("(&(objectClass=gosaAcl)(gosaAclEntry=*".base64_encode($old_dn)."*))",array("cn","gosaAclEntry"));
       while($attrs = $ldap->fetch()){
       while($attrs = $ldap->fetch()){
-
         $acls = array();
         $acls = array();
-
-        /* Reset vars */
         $found = false;
         $found = false;
-
-        /* Walk through acls */
         for($i = 0 ; $i <  $attrs['gosaAclEntry']['count'] ; $i ++ ){
         for($i = 0 ; $i <  $attrs['gosaAclEntry']['count'] ; $i ++ ){
+          $acl_parts = explode(":",$attrs['gosaAclEntry'][$i]);
 
 
-          /* Get Acl parts */
-          $acl_parts = split(":",$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.
+           */
+          $id = ($acl_parts[1] == "role") ? 3 : 2;
 
 
-          /* Get every single member for this acl */  
-          $members = array();  
-          if(preg_match("/,/",$acl_parts[2])){
-            $members = split(",",$acl_parts[2]);
-          }else{
-            $members = array($acl_parts[2]);
-          } 
-      
-          /* Check if member match current dn */
+          /* Update member entries to use $new_dn instead of old_dn
+           */
+          $members = explode(",",$acl_parts[$id]);
           foreach($members as $key => $member){
             $member = base64_decode($member);
             if($member == $old_dn){
           foreach($members as $key => $member){
             $member = base64_decode($member);
             if($member == $old_dn){
-              $found = true;
               $members[$key] = base64_encode($new_dn);
               $members[$key] = base64_encode($new_dn);
+              $found = TRUE;
             }
           } 
             }
           } 
-       
-          /* Create new member string */ 
-          $new_members = "";
-          foreach($members as $member){
-            $new_members .= $member.",";
-          }
-          $new_members = preg_replace("/,$/","",$new_members);
-          $acl_parts[2] = $new_members;
-        
-          /* Reconstruckt acl entry */
-          $acl_str  ="";
-          foreach($acl_parts as $t){
-           $acl_str .= $t.":";
+
+          /* Check if the selected role has to updated
+           */
+          if($acl_parts[1] == "role" && $acl_parts[2] == base64_encode($old_dn)){
+            $acl_parts[2] = base64_encode($new_dn);
+            $found = TRUE;
           }
           }
-          $acl_str = preg_replace("/:$/","",$acl_str);
-          $acls[] = $acl_str;
-       }
 
 
-       /* Acls for this object must be adjusted */
-       if($found){
+          /* Build new acl string */ 
+          $acl_parts[$id] = implode($members,",");
+          $acls[] = implode($acl_parts,":");
+        }
+
+        /* 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();
@@ -1813,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()
@@ -1827,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)
   {
@@ -1838,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];
         }
       }
     }
         }
       }
     }
@@ -1857,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()
   {
@@ -1881,24 +1407,23 @@ 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 */
-    session::set('current_class_for_help',get_class($this));
+    session::global_set('current_class_for_help',get_class($this));
 
     /* 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()
   {
@@ -1915,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()) {
@@ -1937,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
@@ -1950,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()
   {
@@ -1958,134 +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 ;
-      }
-
-      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);
+     return(array());
   }
 
   }
 
-
-  function get_snapshot_action($base,$category)
+  function is_modal_dialog()
   {
   {
-    $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;";
-      }
-    }
-
-    return($str);
+    return(isset($this->dialog) && $this->dialog);
   }
 
 
   }
 
 
-  function get_copypaste_action($base,$category,$class,$copy = TRUE, $cut = TRUE)
+  /*! \brief    Forward command execution requests
+   *             to the hook execution method. 
+   */
+  function handle_post_events($mode, $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;";
-        }
-      }
+    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($action); 
+      case "remove":
+        plugin::callHook($this,"POSTREMOVE", $addAttrs);
+      break;
+    }
   }
 
 
   }
 
 
-  function get_copypaste_header($base,$category,$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())
   {
   {
-    $s = "";
-    $ui =get_userinfo();
-
-    if(!is_array($category)){
-      $category = array($category);
-    }
+    global $config;
+    $command = $config->configRegistry->getPropertyValue(get_class($plugin),$cmd);
+    
+    if ($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 = TRUE;
-    foreach($category as $cat){
-      $readable |= $ui->get_category_permissions($base,$cat);
-      $pasteable|= $ui->is_pasteable($base,$cat);
-    }
-  
-    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";
+      // Walk trough attributes list and add the plugins attributes. 
+      foreach ($plugin->attributes as $attr){
+        if (!is_array($plugin->$attr)){
+          $addAttrs[$attr] = $plugin->$attr;
         }
         }
-        if($cut){
-          $s.= "..|<img src='images/lists/cut.png' alt='' border='0' class='center'>".
-            "&nbsp;"._("Cut")."|"."multiple_cut_systems|\n";
+      }
+      $ui = get_userinfo();
+      $addAttrs['callerDN']=$ui->dn;
+      $addAttrs['dn']=$plugin->dn;
+
+      // Sort attributes by length, ensures correct replacement
+      $tmp = array();
+      foreach($addAttrs as $name => $value){
+        $tmp[$name] =  strlen($name);
+      }
+      arsort($tmp);
+
+      // Now replace the placeholder 
+      foreach ($tmp as $name => $len){
+        $value = $addAttrs[$name];
+        $command= str_replace("%$name", "$value", $command);
+      }
+
+      // 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());
   }
 }
 
   }
 }