Code

Updated Placeholder handling, fixed problems with UPPER/lowercase handling
[gosa.git] / gosa-core / include / class_plugin.inc
index e1a7853b9622a3716553d6e3c996e245a69101f6..0180a8529a50fc25e108417911f1fecfdd84d9ad 100644 (file)
@@ -594,43 +594,45 @@ class plugin
     $ldap->cat ($dn);
     $this->attrs= $ldap->fetch();
 
-    /* Walk through attributes */
-    foreach ($this->attributes as $val){
+    $values = array();
+    foreach(array('uid','sn','givenName') as $name){
+        if(isset($this->parent->$name)){
+            $value = $this->parent->$name;
+            if(is_numeric($name)) continue;
+            if(is_string($value))  $values[$name] = $value;
+            if(is_array($value) && isset($value[0]))  $values[$name] = $value[0];
+        }
+    }
 
-      /* Skip the ones in skip list */
-      if (in_array($val, $skip)){
-        continue;
-      }
+    foreach($this->attributes as $name){
 
-      if (isset($this->attrs["$val"][0])){
+        // Skip the ones in skip list 
+        if (in_array($name, $skip)) continue;
+        if (!isset($this->attrs[$name]['count'])) continue;
 
-        /* If attribute is set, replace dynamic parts: 
-           %sn, %givenName and %uid. Fill these in our local variables. */
-        $value= $this->attrs["$val"][0];
+        $value= $this->attrs[$name][0];
 
-        foreach (array("sn", "givenName", "uid") as $repl){
-          if (preg_match("/%$repl/i", $value)){
-            $value= preg_replace ("/%$repl/i", $this->parent->$repl, $value);
-          }
+        if($this->attrs[$name]['count'] == 1){
+            $value = fillReplacements($this->attrs[$name][0], $values);
+        }else{
+            $value = array();
+            for($i=0;$i<$this->attrs[$name]['count'];$i++){
+                $value[] = fillReplacements($this->attrs[$name][$i], $values);
+            }
         }
-        $this->$val= $value;
-      }
+        $this->$name = $value; 
     }
 
     /* Is Account? */
     $found= TRUE;
     foreach ($this->objectclasses as $obj){
-      if (preg_match('/top/i', $obj)){
-        continue;
-      }
+      if (preg_match('/top/i', $obj)) continue;
       if (!in_array_ics ($obj, $this->attrs['objectClass'])){
         $found= FALSE;
         break;
       }
     }
-    if ($found){
-      $this->is_account= TRUE;
-    }
+    $this->is_account = $found;
   }
 
   /* \brief Indicate whether a password change is needed or not */
@@ -930,6 +932,27 @@ class plugin
       $o_ogroup->save();
     }
 
+    // Migrate objectgroups if needed
+    $objects = get_sub_list("(&(objectClass=gotoEnvironment)(gotoHotplugDeviceDN=".LDAP::prepare4filter(LDAP::fix($src_dn))."))",
+            "users",array(get_ou("core","userRDN"), get_ou("core","groupRDN")),
+            $this->config->current['BASE'],array("dn", "gotoHotplugDeviceDN"), GL_SUBSEARCH | GL_NO_ACL_CHECK);
+    $ldap = $this->config->get_ldap_link();
+    foreach($objects as $obj){
+        $deviceDNS = array();
+        for($i=0; $i < $obj["gotoHotplugDeviceDN"]['count']; $i++){
+            $odn = $obj["gotoHotplugDeviceDN"][$i];
+            if($odn == $src_dn){
+                $odn = $dst_dn;
+            }
+            $deviceDNS[] = $odn;
+        }
+        $ldap->cd($obj['dn']);
+        $ldap->modify(array('gotoHotplugDeviceDN'=>$deviceDNS));
+        if(!$ldap->success()){
+            trigger_error(sprintf("Failed to update gotoHotplugDeviceDN for %s: %s", bold($obj['dn']), $ldap->get_error()));
+        }
+    }
+
     // Migrate rfc groups if needed
     $groups = get_sub_list("(&(objectClass=posixGroup)(member=".LDAP::prepare4filter(LDAP::fix($src_dn))."))","groups", array(get_ou("core", "groupRDN")),$this->config->current['BASE'],array("dn"), GL_SUBSEARCH | GL_NO_ACL_CHECK);
 
@@ -942,16 +965,18 @@ class plugin
     }
 
     /* 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("roleGeneric", "roleRDN")),$this->config->current['BASE'],array("dn"), GL_SUBSEARCH | GL_NO_ACL_CHECK);
-
-    // 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();
-      }
+    if(class_available('roleGeneric')){
+        $roles = get_sub_list("(&(objectClass=organizationalRole)(roleOccupant=".LDAP::prepare4filter(LDAP::fix($src_dn))."))","roles", array(get_ou("roleGeneric", "roleRDN")),$this->config->current['BASE'],array("dn"), GL_SUBSEARCH | GL_NO_ACL_CHECK);
+
+        // 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();
+            }
+        }
     }
 
     // Update 'manager' attributes from gosaDepartment and inetOrgPerson 
@@ -1584,77 +1609,102 @@ class plugin
    *            Replaces placeholder by class values of this plugin instance.
    *  @param    Allows to a add special replacements.
    */
-  static function callHook($plugin, $cmd, $addAttrs= array(), &$returnOutput = array(), &$returnCode = NULL)
+  static function callHook($plugin, $cmd, $addAttrs= array(), &$returnOutput = array(), 
+          &$returnCode = NULL, &$errorOutput = array(), $displayErrors = TRUE)
   {
-    global $config;
-    $command = $config->configRegistry->getPropertyValue(get_class($plugin),$cmd);
-   
-    if ($command != ""){
+      global $config;
+      $command = $config->configRegistry->getPropertyValue(get_class($plugin),$cmd);
 
-      // 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;
-      $addAttrs['location']=$config->current['NAME'];
-
-      // Sort attributes by length, ensures correct replacement
-      $tmp = array();
-      foreach($addAttrs as $name => $value){
-        $tmp[$name] =  strlen($name);
-      }
-      arsort($tmp);
+      $returnCode = 0; // Simulate a return code to tell the caller that everythin is fine.
+      $returnOutput = array();
+      $arr = array();
 
-      // Now replace the placeholder 
-      foreach ($tmp as $name => $len){
-        $value = $addAttrs[$name];
-        $command= str_replace("%$name", "$value", $command);
-      }
+      if (!empty($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.'",'; 
+          // Walk trough attributes list and add the plugins attributes. 
+          foreach ($plugin->attributes as $attr){
+              if (!is_array($plugin->$attr)){
+                  $addAttrs[$attr] = $plugin->$attr;
               }
-            }
-            $value = '['.trim($s,',').']';
           }
-          if(!is_string($value) && !is_int($value) && !is_float($value) && !is_bool($value)){
-            continue;
+          $ui = get_userinfo();
+          $addAttrs['callerDN']=$ui->dn;
+          $addAttrs['dn']=$plugin->dn;
+          $addAttrs['location']=$config->current['NAME'];
+
+          // Sort attributes by length, ensures correct replacement
+          $tmp = array();
+          foreach($addAttrs as $name => $value){
+              $tmp[$name] =  strlen($name);
+          }
+          arsort($tmp);
+
+          // Now replace the placeholder 
+          $command = fillReplacements($command, $addAttrs, TRUE);
+
+          // 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/", escapeshellarg($value), $command);
+              }
           }
-          $command= preg_replace("/%$name/", escapeshellarg($value), $command);
-        }
-      }
 
-      if (check_command($command)){
+          if (check_command($command)){
 
-        @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,$command,"Execute");
-        exec($command, $arr, $returnCode);
-        $returnOutput = $arr;
+              // Create list of process pipes
+              $descriptorspec = array(
+                      0 => array("pipe", "r"),  // stdin
+                      1 => array("pipe", "w"),  // stdout
+                      2 => array("pipe", "w")); // stderr
 
-        if($returnCode != 0){
-          $str = implode("\n",$arr);
-          @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execution failed code: ".$returnCode);
-          $message= msgPool::cmdexecfailed($cmd,$command, get_class($plugin));
-          msg_dialog::display(_("Error"), $message, ERROR_DIALOG);
-        }elseif(is_array($arr)){
-          $str = implode("\n",$arr);
-          @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Result: ".$str);
-        }
-      } else {
-        $message= msgPool::cmdinvalid($cmd,$command, get_class($plugin));
-        msg_dialog::display(_("Error"), $message, ERROR_DIALOG);
+              // Try to open the process
+              @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__,$command,"Execute");
+              $process = proc_open($command, $descriptorspec, $pipes);
+              if (is_resource($process)) {
+
+                  // Write the password to stdin
+                  // fwrite($pipes[0], $pwd); 
+                  fclose($pipes[0]);
+
+                  // Get results from stdout and stderr
+                  $arr = stream_get_contents($pipes[1]);
+                  $err = stream_get_contents($pipes[2]);
+                  fclose($pipes[1]);
+
+                  // Close the process and check its return value
+                  $returnCode = proc_close($process);
+                  $returnOutput = preg_split("/\n/", $arr,0,PREG_SPLIT_NO_EMPTY);
+                  $errorOutput = preg_split("/\n/",$err,0,PREG_SPLIT_NO_EMPTY);
+              }
+
+              if($returnCode != 0){
+                  @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execution failed code: ".$returnCode);
+                  @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Result: ".$err);
+                  if($displayErrors){
+                      $message= msgPool::cmdexecfailed($cmd,$command, get_class($plugin));
+                      msg_dialog::display(_("Error"), $message, ERROR_DIALOG);
+                  }
+              }elseif(is_array($arr)){
+                  @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Result: ".$arr);
+              }
+          } elseif($displayErrors) {
+              $message= msgPool::cmdinvalid($cmd,$command, get_class($plugin));
+              msg_dialog::display(_("Error"), $message, ERROR_DIALOG);
+          }
       }
-    }
   }
 }