Code

Udpated Log and Copy&Paste
[gosa.git] / include / class_ldap.inc
index fafa96c9765c561a0869b822dcf482b61050ac70..126aabbad27a562be5207cd82998a291f78e8399 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /*****************************************************************************
   newldap.inc - version 1.0
-  Copyright (C) 2003 Alejandro Escanero Blanco <aescanerochaosdimension.org>
+  Copyright (C) 2003 Alejandro Escanero Blanco <aescanero@chaosdimension.org>
   Copyright (C) 2004-2006 Cajus Pollmeier <pollmeier@gonicus.de>
 
   Based in code of ldap.inc of
@@ -95,18 +95,18 @@ class LDAP{
   {
     $this->hascon=false;
     $this->reconnect=false;
-    if ($this->cid= ldap_connect($this->hostname)) {
-      ldap_set_option($this->cid, LDAP_OPT_PROTOCOL_VERSION, 3);
+    if ($this->cid= @ldap_connect($this->hostname)) {
+      @ldap_set_option($this->cid, LDAP_OPT_PROTOCOL_VERSION, 3);
       if (function_exists("ldap_set_rebind_proc") && $this->follow_referral) {
-        ldap_set_option($this->cid, LDAP_OPT_REFERRALS, 1);
-        ldap_set_rebind_proc($this->cid, array(&$this, "rebind"));
+        @ldap_set_option($this->cid, LDAP_OPT_REFERRALS, 1);
+        @ldap_set_rebind_proc($this->cid, array(&$this, "rebind"));
       }
       if (function_exists("ldap_start_tls") && $this->tls){
-        ldap_start_tls($this->cid);
+        @ldap_start_tls($this->cid);
       }
 
       $this->error = "No Error";
-      if ($bid = ldap_bind($this->cid, $this->fix($this->binddn), $this->bindpw)) {
+      if ($bid = @ldap_bind($this->cid, $this->fix($this->binddn), $this->bindpw)) {
         $this->error = "Success";
         $this->hascon=true;
       } else {
@@ -126,7 +126,7 @@ class LDAP{
   function rebind($ldap, $referral)
   {
     $credentials= $this->get_credentials($referral);
-    if (ldap_bind($ldap, $this->fix($credentials['ADMIN']), $credentials['PASSWORD'])) {
+    if (@ldap_bind($ldap, $this->fix($credentials['ADMIN']), $credentials['PASSWORD'])) {
       $this->error = "Success";
       $this->hascon=true;
       $this->reconnect= true;
@@ -140,21 +140,21 @@ class LDAP{
   function reconnect()
   {
     if ($this->reconnect){
-      ldap_unbind($this->cid);
+      @ldap_unbind($this->cid);
       $this->cid = NULL;
     }
   }
 
   function unbind()
   {
-    ldap_unbind($this->cid);
+    @ldap_unbind($this->cid);
     $this->cid = NULL;
   }
 
   function disconnect()
   {
     if($this->hascon){
-      ldap_close($this->cid);
+      @ldap_close($this->cid);
       $this->hascon=false;
     }
   }
@@ -184,8 +184,8 @@ class LDAP{
       $start = microtime();
    
       $this->clearResult();
-      $this->sr = ldap_search($this->cid, $this->fix($this->basedn), $filter, $attrs);
-      $this->error = ldap_error($this->cid);
+      $this->sr = @ldap_search($this->cid, $this->fix($this->basedn), $filter, $attrs);
+      $this->error = @ldap_error($this->cid);
       $this->resetResult();
       $this->hasres=true;
    
@@ -217,8 +217,8 @@ class LDAP{
   
       $start = microtime();
 
-      $this->sr = ldap_list($this->cid, $this->fix($basedn), $filter,$attrs);
-      $this->error = ldap_error($this->cid);
+      $this->sr = @ldap_list($this->cid, $this->fix($basedn), $filter,$attrs);
+      $this->error = @ldap_error($this->cid);
       $this->resetResult();
       $this->hasres=true;
 
@@ -245,8 +245,8 @@ class LDAP{
       if ($this->reconnect) $this->connect();
       $this->clearResult();
       $filter = "(objectclass=*)";
-      $this->sr = ldap_read($this->cid, $this->fix($dn), $filter,$attrs);
-      $this->error = ldap_error($this->cid);
+      $this->sr = @ldap_read($this->cid, $this->fix($dn), $filter,$attrs);
+      $this->error = @ldap_error($this->cid);
       $this->resetResult();
       $this->hasres=true;
       return($this->sr);
@@ -260,10 +260,10 @@ class LDAP{
   {
     /* Ignore zero settings */
     if ($size == 0){
-      ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, 10000000);
+      @ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, 10000000);
     }
     if($this->hascon){
-      ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, $size);
+      @ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, $size);
     } else {
       $this->error = "Could not connect to LDAP server";
     }
@@ -277,16 +277,16 @@ class LDAP{
         if ($this->start == 0)
         {
           $this->start = 1;
-          $this->re= ldap_first_entry($this->cid, $this->sr);
+          $this->re= @ldap_first_entry($this->cid, $this->sr);
         } else {
-          $this->re= ldap_next_entry($this->cid, $this->re);
+          $this->re= @ldap_next_entry($this->cid, $this->re);
         }
         if ($this->re)
         {
-          $att= ldap_get_attributes($this->cid, $this->re);
-          $att['dn']= trim($this->convert(ldap_get_dn($this->cid, $this->re)));
+          $att= @ldap_get_attributes($this->cid, $this->re);
+          $att['dn']= trim($this->convert(@ldap_get_dn($this->cid, $this->re)));
         }
-        $this->error = ldap_error($this->cid);
+        $this->error = @ldap_error($this->cid);
         if (!isset($att)){
           $att= array();
         }
@@ -310,7 +310,7 @@ class LDAP{
   {
     if($this->hasres){
       $this->hasres = false;
-      ldap_free_result($this->sr);
+      @ldap_free_result($this->sr);
     }
   }
 
@@ -325,9 +325,9 @@ class LDAP{
           }
           else
           {
-          $rv = ldap_get_dn($this->cid, $this->re);
+          $rv = @ldap_get_dn($this->cid, $this->re);
         
-          $this->error = ldap_error($this->cid);
+          $this->error = @ldap_error($this->cid);
           return(trim($this->convert($rv)));
            }
       }else{
@@ -344,8 +344,8 @@ class LDAP{
   {
     if($this->hascon){
       if($this->hasres){
-        $rv = ldap_count_entries($this->cid, $this->sr);
-        $this->error = ldap_error($this->cid);
+        $rv = @ldap_count_entries($this->cid, $this->sr);
+        $this->error = @ldap_error($this->cid);
         return($rv);
       }else{
         $this->error = "Perform a Fetch with no Search";
@@ -364,8 +364,8 @@ class LDAP{
       if ($dn == "")
         $dn = $this->basedn;
 
-      $r = ldap_mod_del($this->cid, $this->fix($dn), $attrs);
-      $this->error = ldap_error($this->cid);
+      $r = @ldap_mod_del($this->cid, $this->fix($dn), $attrs);
+      $this->error = @ldap_error($this->cid);
       return($r);
     }else{
       $this->error = "Could not connect to LDAP server";
@@ -380,8 +380,8 @@ class LDAP{
       if ($dn == "")
         $dn = $this->basedn;
 
-      $r = ldap_mod_replace($this->cid, $this->fix($dn), $attrs);
-      $this->error = ldap_error($this->cid);
+      $r = @ldap_mod_replace($this->cid, $this->fix($dn), $attrs);
+      $this->error = @ldap_error($this->cid);
       return($r);
     }else{
       $this->error = "Could not connect to LDAP server";
@@ -393,8 +393,8 @@ class LDAP{
   {
     if($this->hascon){
       if ($this->reconnect) $this->connect();
-      $r = ldap_delete($this->cid, $this->fix($deletedn));
-      $this->error = ldap_error($this->cid);
+      $r = @ldap_delete($this->cid, $this->fix($deletedn));
+      $this->error = @ldap_error($this->cid);
       return($r ? $r : 0);
     }else{
       $this->error = "Could not connect to LDAP server";
@@ -432,8 +432,8 @@ class LDAP{
       }
       
       /* Finally Delete own Node */
-      $r = ldap_delete($this->cid, $this->fix($deletedn));
-      $this->error = ldap_error($this->cid);
+      $r = @ldap_delete($this->cid, $this->fix($deletedn));
+      $this->error = @ldap_error($this->cid);
       return($r ? $r : 0);
     }else{
       $this->error = "Could not connect to LDAP server";
@@ -448,16 +448,16 @@ class LDAP{
     error_reporting(E_ALL);
     
     if($is_first){
-      echo "<h2>".sprintf(_("Creating copy of %s"),"<i>".LDAP::fix($sourcedn)."</i>")."</h2>";
+      echo "<h2>".sprintf(_("Creating copy of %s"),"<i>".@LDAP::fix($sourcedn)."</i>")."</h2>";
     }else{
       if(preg_match("/^ou=/",$sourcedn)){
-        echo "<h3>"._("Processing")." <i>".LDAP::fix($destinationdn)."</i></h3>";
+        echo "<h3>"._("Processing")." <i>".@LDAP::fix($destinationdn)."</i></h3>";
       }else{
         $tmp = split(",",$sourcedn);
         
         echo "&nbsp;<b>"._("Object").":</b> ";
 
-        $deststr = LDAP::fix($destinationdn);
+        $deststr = @LDAP::fix($destinationdn);
         if(strlen($deststr) > 96){
           $deststr = substr($deststr,0,96)."...";
         }
@@ -533,7 +533,7 @@ class LDAP{
             if(in_array($key ,array("FAItemplateFile","FAIscript", "gotoLogonScript", "gosaApplicationIcon","gotoMimeIcon"))){
               $sr= ldap_read($this->cid, $this->fix($sourcedn), "$key=*", array($key));
               $ei= ldap_first_entry($this->cid, $sr);
-              if ($tmp= ldap_get_values_len($this->cid, $ei,$key)){
+              if ($tmp= @ldap_get_values_len($this->cid, $ei,$key)){
                 $attr[$key] = $tmp;
               }
             }
@@ -618,8 +618,8 @@ class LDAP{
     }
     if($this->hascon){
       if ($this->reconnect) $this->connect();
-      $r = ldap_modify($this->cid, $this->fix($this->basedn), $attrs);
-      $this->error = ldap_error($this->cid);
+      $r = @ldap_modify($this->cid, $this->fix($this->basedn), $attrs);
+      $this->error = @ldap_error($this->cid);
       return($r ? $r : 0);
     }else{
       $this->error = "Could not connect to LDAP server";
@@ -631,8 +631,8 @@ class LDAP{
   {
     if($this->hascon){
       if ($this->reconnect) $this->connect();
-      $r = ldap_add($this->cid, $this->fix($this->basedn), $attrs);
-      $this->error = ldap_error($this->cid);
+      $r = @ldap_add($this->cid, $this->fix($this->basedn), $attrs);
+      $this->error = @ldap_error($this->cid);
       return($r ? $r : 0);
     }else{
       $this->error = "Could not connect to LDAP server";
@@ -642,19 +642,26 @@ class LDAP{
 
   function create_missing_trees($target)
   {
-    /* Ignore create_missing trees if the base equals target */
-    if ($target == $this->basedn){
-     return;
-    }
+    global $config;
 
     $real_path= substr($target, 0, strlen($target) - strlen($this->basedn) -1 );
-    $l= array_reverse(gosa_ldap_explode_dn($real_path));
+
+    if ($target == $this->basedn){
+      $l= array("dummy");
+    } else {
+      $l= array_reverse(gosa_ldap_explode_dn($real_path));
+    }
     unset($l['count']);
     $cdn= $this->basedn;
     $tag= "";
 
+    /* Load schema if available... */
+    $classes= $this->get_objectclasses();
+
     foreach ($l as $part){
-      $cdn= "$part,$cdn";
+      if ($part != "dummy"){
+        $cdn= "$part,$cdn";
+      }
 
       /* Ignore referrals */
       $found= false;
@@ -685,36 +692,97 @@ class LDAP{
         $param= preg_replace('/^[^=]+=([^,]+),.*$/', '\\1', $cdn);
 
         $na= array();
-        switch ($type){
-          case 'ou':
-            if ($tag != ""){
-              $na["objectClass"]= array("organizationalUnit", "gosaAdministrativeUnitTag");
-              $na["gosaUnitTag"]= $tag;
-            } else {
-              $na["objectClass"]= "organizationalUnit";
-            }
-            $na["ou"]= $param;
-            break;
-          case 'dc':
-            if ($tag != ""){
-              $na["objectClass"]= array("dcObject", "top", "locality", "gosaAdministrativeUnitTag");
-              $na["gosaUnitTag"]= $tag;
-            } else {
-              $na["objectClass"]= array("dcObject", "top", "locality");
+
+        /* Automatic or traditional? */
+        if(count($classes)){
+
+          /* Get name of first matching objectClass */
+          $ocname= "";
+          foreach($classes as $class){
+            if (isset($class['MUST']) && $class['MUST'] == "$type"){
+
+              /* Look for first classes that is structural... */
+              if (isset($class['STRUCTURAL'])){
+                $ocname= $class['NAME'];
+                break;
+              }
+
+              /* Look for classes that are auxiliary... */
+              if (isset($class['AUXILIARY'])){
+                $ocname= $class['NAME'];
+              }
             }
-            $na["dc"]= $param;
-            break;
-          default:
-            print_red(sprintf(_("Autocreation of type '%s' is currently not supported. Please report to the GOsa team."), $type));
+          }
+
+          /* Bail out, if we've nothing to do... */
+          if ($ocname == ""){
+            print_red(sprintf(_("Autocreation of subtree failed. No objectClass found for attribute '%s'."), $type));
             echo $_SESSION['errors'];
             exit;
+          }
+
+          /* Assemble_entry */
+          if ($tag != ""){
+            $na['objectClass']= array($ocname, "gosaAdministrativeUnitTag");
+          } else {
+            $na['objectClass']= array($ocname);
+          }
+          if (isset($classes[$ocname]['AUXILIARY'])){
+            $na['objectClass'][]= $classes[$ocname]['SUP'];
+          }
+          if ($type == "dc"){
+            /* This is bad actually, but - tell me a better way? */
+            $na['objectClass'][]= 'locality';
+          }
+          $na[$type]= $param;
+          if (is_array($classes[$ocname]['MUST'])){
+            foreach($classes[$ocname]['MUST'] as $attr){
+              $na[$attr]= "filled";
+            }
+          }
+
+        } else {
+
+          /* Use alternative add... */
+          switch ($type){
+            case 'ou':
+              if ($tag != ""){
+                $na["objectClass"]= array("organizationalUnit", "gosaAdministrativeUnitTag");
+                $na["gosaUnitTag"]= $tag;
+              } else {
+                $na["objectClass"]= "organizationalUnit";
+              }
+              $na["ou"]= $param;
+              break;
+            case 'dc':
+              if ($tag != ""){
+                $na["objectClass"]= array("dcObject", "top", "locality", "gosaAdministrativeUnitTag");
+                $na["gosaUnitTag"]= $tag;
+              } else {
+                $na["objectClass"]= array("dcObject", "top", "locality");
+              }
+              $na["dc"]= $param;
+              break;
+            default:
+              print_red(sprintf(_("Autocreation of type '%s' is currently not supported. Please report to the GOsa team."), $type));
+              echo $_SESSION['errors'];
+              exit;
+          }
+
         }
         $this->cd($cdn);
         $this->add($na);
+        show_ldap_error($this->get_error(), sprintf(_("Creating subtree '%s' failed."),$cdn));
+        if (!preg_match('/success/i', $this->error)){
+          return FALSE;
+        }
       }
     }
+
+    return TRUE;
   }
 
+
   function recursive_remove()
   {
     $delarray= array();
@@ -738,13 +806,13 @@ class LDAP{
   {
     $data= "";
     if ($this->reconnect) $this->connect();
-    $sr= ldap_read($this->cid, $this->fix($dn), "objectClass=*", array("$name"));
+    $sr= @ldap_read($this->cid, $this->fix($dn), "objectClass=*", array("$name"));
 
     /* fill data from LDAP */
     if ($sr) {
-      $ei= ldap_first_entry($this->cid, $sr);
+      $ei= @ldap_first_entry($this->cid, $sr);
       if ($ei) {
-        if ($info= ldap_get_values_len($this->cid, $ei, "$name")){
+        if ($info= @ldap_get_values_len($this->cid, $ei, "$name")){
           $data= $info[0];
         }
 
@@ -763,7 +831,7 @@ class LDAP{
   function get_additional_error()
   {
     $error= "";
-    ldap_get_option ($this->cid, LDAP_OPT_ERROR_STRING, $error);
+    @ldap_get_option ($this->cid, LDAP_OPT_ERROR_STRING, $error);
     return ($error);
   }
 
@@ -859,10 +927,10 @@ class LDAP{
     }
 
     /* Searching Ldap Tree */
-    $sr= ldap_read($this->cid, $this->fix($dn), $filter, $name);
+    $sr= @ldap_read($this->cid, $this->fix($dn), $filter, $name);
 
     /* Get the first entry */   
-    $entry= ldap_first_entry($this->cid, $sr);
+    $entry= @ldap_first_entry($this->cid, $sr);
 
     /* Get all attributes related to that Objekt */
     $atts = array();
@@ -874,14 +942,14 @@ class LDAP{
     /* Reset index */
     $i = 1 ; 
   $identifier = array();
-    $attribute= ldap_first_attribute($this->cid,$entry,$identifier);
+    $attribute= @ldap_first_attribute($this->cid,$entry,$identifier);
     while ($attribute) {
       $i++;
       $atts[$i]['name']  = $attribute;
-      $atts[$i]['value'] = ldap_get_values_len($this->cid, $entry, "$attribute");
+      $atts[$i]['value'] = @ldap_get_values_len($this->cid, $entry, "$attribute");
 
       /* Next one */
-      $attribute= ldap_next_attribute($this->cid,$entry,$identifier);
+      $attribute= @ldap_next_attribute($this->cid,$entry,$identifier);
     }
 
     foreach($atts as $at)
@@ -889,7 +957,7 @@ class LDAP{
       for ($i= 0; $i<$at['value']['count']; $i++){
 
         /* Check if we must encode the data */
-        if(!preg_match('/^[a-z0-9+#.=, \/ -]+$/i', $at['value'][$i])) {
+        if(!preg_match('/^[a-z0-9+@#.=, \/ -]+$/i', $at['value'][$i])) {
           $ret .= $at['name'].":: ".base64_encode($at['value'][$i])."\n";
         } else {
           $ret .= $at['name'].": ".$at['value'][$i]."\n";
@@ -903,7 +971,7 @@ class LDAP{
 
   function dn_exists($dn)
   {
-    return ldap_list($this->cid, $this->fix($dn), "(objectClass=*)", array("objectClass"));
+    return @ldap_list($this->cid, $this->fix($dn), "(objectClass=*)", array("objectClass"));
   }
   
 
@@ -1184,16 +1252,20 @@ class LDAP{
   
   function get_objectclasses()
   {
-         $objectclasses = array();
+    $objectclasses = array();
        
          # Get base to look for schema 
-         $sr = ldap_read ($this->cid, NULL, "objectClass=*", array("subschemaSubentry"));
-         $attr = ldap_get_entries($this->cid,$sr);
+         $sr = @ldap_read ($this->cid, NULL, "objectClass=*", array("subschemaSubentry"));
+    if(!$sr){
+           $sr = @ldap_read ($this->cid, "", "objectClass=*", array("subschemaSubentry"));
+    }
+
+         $attr = @ldap_get_entries($this->cid,$sr);
          if (!isset($attr[0]['subschemasubentry'][0])){
            return array();
          }
        
-         # Get list of objectclasses
+         /* Get list of objectclasses and fill array */
          $nb= $attr[0]['subschemasubentry'][0];
          $objectclasses= array();
          $sr= ldap_read ($this->cid, $nb, "objectClass=*", array("objectclasses"));
@@ -1202,15 +1274,74 @@ class LDAP{
            return array();
          }
          foreach ($attrs[0]['objectclasses'] as $val){
-           $name= preg_replace("/^.* NAME\s+\(*\s*'([^']+)'\s*\)*.*$/", '\\1', $val);
-           if ($name != $val){
-             $objectclasses[$name]= $val;
-           }
+      if (preg_match('/^[0-9]+$/', $val)){
+        continue;
+      }
+      $name= "OID";
+      $pattern= split(' ', $val);
+      $ocname= preg_replace("/^.* NAME\s+\(*\s*'([^']+)'\s*\)*.*$/", '\\1', $val);
+      $objectclasses[$ocname]= array();
+
+      foreach($pattern as $chunk){
+        switch($chunk){
+
+          case '(':
+                    $value= "";
+                    break;
+
+          case ')': if ($name != ""){
+                      $objectclasses[$ocname][$name]= $this->value2container($value);
+                    }
+                    $name= "";
+                    $value= "";
+                    break;
+
+          case 'NAME':
+          case 'DESC':
+          case 'SUP':
+          case 'STRUCTURAL':
+          case 'ABSTRACT':
+          case 'AUXILIARY':
+          case 'MUST':
+          case 'MAY':
+                    if ($name != ""){
+                      $objectclasses[$ocname][$name]= $this->value2container($value);
+                    }
+                    $name= $chunk;
+                    $value= "";
+                    break;
+
+          default:  $value.= $chunk." ";
+        }
+      }
+
          }
-         
          return $objectclasses;
   }
 
+
+  function value2container($value)
+  {
+    /* Set emtpy values to "true" only */
+    if (preg_match('/^\s*$/', $value)){
+      return true;
+    }
+
+    /* Remove ' and " if needed */
+    $value= preg_replace('/^[\'"]/', '', $value);
+    $value= preg_replace('/[\'"] *$/', '', $value);
+
+    /* Convert to array if $ is inside... */
+    if (preg_match('/\$/', $value)){
+      $container= preg_split('/\s*\$\s*/', $value);
+    } else {
+      $container= chop($value);
+    }
+
+    return ($container);
+  }
+
+
   function log($string)
   {
     if (isset($_SESSION['config'])){
@@ -1221,7 +1352,7 @@ class LDAP{
     }
   }
 
-  /* added by Guido Serra aka Zeph <zephpurotesto.it> */
+  /* added by Guido Serra aka Zeph <zeph@purotesto.it> */
   function getCn($dn){
     $simple= split(",", $dn);
 
@@ -1234,6 +1365,7 @@ class LDAP{
     }
   }
 
+
   function get_naming_contexts($server, $admin= "", $password= "")
   {
     /* Build LDAP connection */
@@ -1245,13 +1377,43 @@ class LDAP{
     $r= ldap_bind ($ds, $admin, $password);
 
     /* Get base to look for naming contexts */
-    $sr  = ldap_read ($ds, "", "objectClass=*", array("namingContexts"));
-    $attr= ldap_get_entries($ds,$sr);
-    
+    $sr  = @ldap_read ($ds, "", "objectClass=*", array("+"));
+    $attr= @ldap_get_entries($ds,$sr);
+
     return ($attr[0]['namingcontexts']);
   }
 
 
+  function get_root_dse($server, $admin= "", $password= "")
+  {
+    /* Build LDAP connection */
+    $ds= ldap_connect ($server);
+    if (!$ds) {
+      die ("Can't bind to LDAP. No check possible!");
+    }
+    ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
+    $r= ldap_bind ($ds, $admin, $password);
+
+    /* Get base to look for naming contexts */
+    $sr  = @ldap_read ($ds, "", "objectClass=*", array("+"));
+    $attr= @ldap_get_entries($ds,$sr);
+   
+    /* Return empty array, if nothing was set */
+    if (!isset($attr[0])){
+      return array();
+    }
+
+    /* Rework array... */
+    $result= array();
+    for ($i= 0; $i<$attr[0]['count']; $i++){
+      $result[$attr[0][$i]]= $attr[0][$attr[0][$i]];
+      unset($result[$attr[0][$i]]['count']);
+    }
+
+    return ($result);
+  }
+
+
 }
 
 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: