diff --git a/include/class_ldap.inc b/include/class_ldap.inc
index ad98c710bc000e74412c8fdcf86dc01b83bbc6e3..a1f960aa3bc730f67939ee52a170f3530ec83e84 100644 (file)
--- a/include/class_ldap.inc
+++ b/include/class_ldap.inc
/*****************************************************************************
newldap.inc - version 1.0
Copyright (C) 2003 Alejandro Escanero Blanco <alex@ofmin.com>
- Copyright (C) 2004 Cajus Pollmeier <pollmeier@gonicus.de>
+ Copyright (C) 2004-2006 Cajus Pollmeier <pollmeier@gonicus.de>
Based in code of ldap.inc of
Copyright (C) 1998 Eric Kilfoil <eric@ipass.net>
define("UNKNOWN_TOKEN_IN_LDIF_FILE",-10002);
define("NO_FILE_UPLOADED",10003);
define("INSERT_OK",10000);
-define("COLON_OVERRIDE", TRUE);
+define("SPECIALS_OVERRIDE", TRUE);
class LDAP{
var $hostname = "";
var $follow_referral = FALSE;
var $referrals= array();
+ var $max_ldap_query_time = 0; // 0, empty or negative values will disable this check
function LDAP($binddn,$bindpw, $hostname, $follow_referral= FALSE, $tls= FALSE)
{
+ global $config;
$this->follow_referral= $follow_referral;
$this->tls=$tls;
$this->binddn=$this->convert($binddn);
$this->bindpw=$bindpw;
$this->hostname=$hostname;
+
+ /* Check if MAX_LDAP_QUERY_TIME is defined */
+ if(isset($config->data['MAIN']['MAX_LDAP_QUERY_TIME'])){
+ $str = $config->data['MAIN']['MAX_LDAP_QUERY_TIME'];
+ $this->max_ldap_query_time = (float)($str);
+ }
+
$this->connect();
}
+ /* Function to replace all problematic characters inside a DN by \001XX, where
+ \001 is decoded to chr(1) [ctrl+a]. It is not impossible, but very unlikely
+ that this character is inside a DN.
+
+ Currently used codes:
+ , => CO
+ \2C => CO
+ ( => OB
+ ) => CB
+ / => SL */
function convert($dn)
{
- if (COLON_OVERRIDE == TRUE){
- $res= preg_replace("/\\\\,/", '###GOSAREPLACED###', $dn);
- $res= preg_replace("/\\\\2C/", '###GOSAREPLACED###', $res);
- $res= preg_replace("/\(/", '###OPENBRACE###', $res);
- $res= preg_replace("/\)/", '###CLOSEBRACE###', $res);
- $res= preg_replace("/\//", '###SLASH###', $res);
-
- #if ($dn != $res){
- # echo "Conversation from '$dn' to '$res'<br>";
- #}
- return ($res);
+ if (SPECIALS_OVERRIDE == TRUE){
+ return (preg_replace(array("/\\\\,/", "/\\\\2C/", "/\(/", "/\)/", "/\//"),
+ array("\001CO", "\001CO", "\001OB", "\001CB", "\001SL"),
+ $dn));
} else {
return ($dn);
}
}
+ /* Function to fix all problematic characters inside a DN by replacing \001XX
+ codes to their original values. See "convert" for mor information.
+ ',' characters are always expanded to \, (not \2C), since all tested LDAP
+ servers seem to take it the correct way. */
function fix($dn)
{
- if (COLON_OVERRIDE == TRUE){
- $res= preg_replace("/###GOSAREPLACED###/", '\,', $dn);
- $res= preg_replace("/###OPENBRACE###/", '(', $res);
- $res= preg_replace("/###CLOSEBRACE###/", ')', $res);
- $res= preg_replace("/###SLASH###/", '/', $res);
-
- #if ($dn != $res){
- # echo "Fix from '$dn' to '$res'<br>";
- #}
- return ($res);
+ if (SPECIALS_OVERRIDE == TRUE){
+ return (preg_replace(array("/\001CO/", "/\001OB/", "/\001CB/", "/\001SL/"),
+ array("\,", "(", ")", "/"),
+ $dn));
} else {
return ($dn);
}
{
if($this->hascon){
if ($this->reconnect) $this->connect();
+
+ $start = microtime();
+
$this->clearResult();
$this->sr = @ldap_search($this->cid, $this->fix($this->basedn), $filter, $attrs);
$this->error = @ldap_error($this->cid);
$this->resetResult();
$this->hasres=true;
-
+
+ /* Check if query took longer as specified in max_ldap_query_time */
+ if($this->max_ldap_query_time){
+ $diff = get_MicroTimeDiff($start,microtime());
+ if($diff > $this->max_ldap_query_time){
+ print_red(sprintf(_("The LDAP server is slow (%.2fs for the last query). This may be responsible for performance breakdowns."),$diff)) ;
+ }
+ }
+
return($this->sr);
}else{
$this->error = "Could not connect to LDAP server";
$basedn = $this->basedn;
else
$basedn= $this->convert($basedn);
+
+ $start = microtime();
+
$this->sr = @ldap_list($this->cid, $this->fix($basedn), $filter,$attrs);
$this->error = @ldap_error($this->cid);
$this->resetResult();
$this->hasres=true;
+
+ /* Check if query took longer as specified in max_ldap_query_time */
+ if($this->max_ldap_query_time){
+ $diff = get_MicroTimeDiff($start,microtime());
+ if($diff > $this->max_ldap_query_time){
+ print_red(sprintf(_("The ldapserver is answering very slow (%.2f), this may be responsible for performance breakdowns."),$diff)) ;
+ }
+ }
+
return($this->sr);
}else{
$this->error = "Could not connect to LDAP server";
function fetch()
{
+ $att= array();
if($this->hascon){
if($this->hasres){
if ($this->start == 0)
if ($target == $this->basedn){
return;
}
-echo "FIXME";
- $l= array_reverse(explode(",", preg_replace("/,".$this->basedn."/", "", $target)));
+
+ $real_path= substr($target, 0, strlen($target) - strlen($this->basedn) -1 );
+ $l= array_reverse(ldap_explode_dn($real_path,0));
+ unset($l['count']);
$cdn= $this->basedn;
+ $tag= "";
+
foreach ($l as $part){
$cdn= "$part,$cdn";
$attrs= $this->fetch();
/* Create missing entry? */
- if (!count ($attrs)){
+ if (count ($attrs)){
+
+ /* Catch the tag - if present */
+ if (isset($attrs['gosaUnitTag'][0])){
+ $tag= $attrs['gosaUnitTag'][0];
+ }
+
+ } else {
$type= preg_replace('/^([^=]+)=.*$/', '\\1', $cdn);
$param= preg_replace('/^[^=]+=([^,]+),.*$/', '\\1', $cdn);
$na= array();
switch ($type){
case 'ou':
- $na["objectClass"]= "organizationalUnit";
+ if ($tag != ""){
+ $na["objectClass"]= array("organizationalUnit", "gosaAdministrativeUnitTag");
+ $na["gosaUnitTag"]= $tag;
+ } else {
+ $na["objectClass"]= "organizationalUnit";
+ }
$na["ou"]= $param;
break;
case 'dc':
- $na["objectClass"]= array("dcObject", "top", "locality");
+ if ($tag != ""){
+ $na["objectClass"]= array("dcObject", "top", "locality", "gosaAdministrativeUnitTag");
+ $na["gosaUnitTag"]= $tag;
+ } else {
+ $na["objectClass"]= array("dcObject", "top", "locality");
+ }
$na["dc"]= $param;
break;
default:
if ($this->error == 'Success'){
return $this->error;
} else {
- $error= $this->error." (".$this->get_additional_error().")";
+ $adderror= $this->get_additional_error();
+ if ($adderror != ""){
+ $error= $this->error." (".$this->get_additional_error().", ".sprintf(_("while operating on '%s' using LDAP server '%s'"), $this->base, $this->hostname).")";
+ } else {
+ $error= $this->error." (".sprintf(_("while operating on LDAP server %s"), $this->hostname).")";
+ }
return $error;
}
}
@@ -1034,6 +1094,35 @@ function gen_xls ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $rec
}
}
+
+ function get_objectclasses()
+ {
+ $objectclasses = array();
+
+ # Get base to look for schema
+ $sr = @ldap_read ($this->cid, NULL, "objectClass=*", array("subschemaSubentry"));
+ $attr = @ldap_get_entries($this->cid,$sr);
+ if (!isset($attr[0]['subschemasubentry'][0])){
+ return array();
+ }
+
+ # Get list of objectclasses
+ $nb= $attr[0]['subschemasubentry'][0];
+ $objectclasses= array();
+ $sr= ldap_read ($this->cid, $nb, "objectClass=*", array("objectclasses"));
+ $attrs= ldap_get_entries($this->cid,$sr);
+ if (!isset($attrs[0])){
+ return array();
+ }
+ foreach ($attrs[0]['objectclasses'] as $val){
+ $name= preg_replace("/^.* NAME\s+\(*\s*'([^']+)'\s*\)*.*$/", '\\1', $val);
+ if ($name != $val){
+ $objectclasses[$name]= $val;
+ }
+ }
+
+ return $objectclasses;
+ }
}