X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=include%2Fclass_ldap.inc;h=126aabbad27a562be5207cd82998a291f78e8399;hb=fc44dae33071cec905b366610a5468809b09977b;hp=9938fc5d1387f672cfa9702628cb070a982735dc;hpb=c871e6c6b00a65134ed52d6241b845d7c5e2a402;p=gosa.git diff --git a/include/class_ldap.inc b/include/class_ldap.inc index 9938fc5d1..126aabbad 100644 --- a/include/class_ldap.inc +++ b/include/class_ldap.inc @@ -1,8 +1,8 @@ - Copyright (C) 2004 Cajus Pollmeier + Copyright (C) 2003 Alejandro Escanero Blanco + Copyright (C) 2004-2006 Cajus Pollmeier Based in code of ldap.inc of Copyright (C) 1998 Eric Kilfoil @@ -11,11 +11,8 @@ define("ALREADY_EXISTING_ENTRY",-10001); define("UNKNOWN_TOKEN_IN_LDIF_FILE",-10002); define("NO_FILE_UPLOADED",10003); - - define("INSERT_OK",10000); - - +define("SPECIALS_OVERRIDE", TRUE); class LDAP{ @@ -33,17 +30,67 @@ 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=$binddn; + $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 (SPECIALS_OVERRIDE == TRUE){ + $tmp= preg_replace(array("/\\\\,/", "/\\\\2C/", "/\(/", "/\)/", "/\//"), + array("\001CO", "\001CO", "\001OB", "\001CB", "\001SL"), + $dn); + return (preg_replace('/,\s+/', ',', $tmp)); + } 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 (SPECIALS_OVERRIDE == TRUE){ + return (preg_replace(array("/\001CO/", "/\001OB/", "/\001CB/", "/\001SL/"), + array("\,", "(", ")", "/"), + $dn)); + } else { + return ($dn); + } + } + + function connect() { $this->hascon=false; @@ -59,7 +106,7 @@ class LDAP{ } $this->error = "No Error"; - if ($bid = @ldap_bind($this->cid, $this->binddn, $this->bindpw)) { + if ($bid = @ldap_bind($this->cid, $this->fix($this->binddn), $this->bindpw)) { $this->error = "Success"; $this->hascon=true; } else { @@ -79,7 +126,7 @@ class LDAP{ function rebind($ldap, $referral) { $credentials= $this->get_credentials($referral); - if (@ldap_bind($ldap, $credentials['ADMIN'], $credentials['PASSWORD'])) { + if (@ldap_bind($ldap, $this->fix($credentials['ADMIN']), $credentials['PASSWORD'])) { $this->error = "Success"; $this->hascon=true; $this->reconnect= true; @@ -117,26 +164,40 @@ class LDAP{ if ($dir == "..") $this->basedn = $this->getParentDir(); else - $this->basedn = $dir; + $this->basedn = $this->convert($dir); } function getParentDir($basedn = "") { if ($basedn=="") $basedn = $this->basedn; + else + $basedn = $this->convert($this->basedn); return(ereg_replace("[^,]*[,]*[ ]*(.*)", "\\1", $basedn)); } function search($filter, $attrs= array()) { - if($this->hascon){ if ($this->reconnect) $this->connect(); + + $start = microtime(); + $this->clearResult(); - $this->sr = @ldap_search($this->cid, $this->basedn, $filter, $attrs); + $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)) ; + } + } + + $this->log("LDAP operation: time=".get_MicroTimeDiff($start,microtime())." operation=search('".$this->fix($this->basedn)."', '$filter')"); return($this->sr); }else{ $this->error = "Could not connect to LDAP server"; @@ -144,17 +205,33 @@ class LDAP{ } } - function ls($filter = "(objectclass=*)", $basedn = "") + function ls($filter = "(objectclass=*)", $basedn = "",$attrs = array("*")) { if($this->hascon){ if ($this->reconnect) $this->connect(); $this->clearResult(); if ($basedn == "") $basedn = $this->basedn; - $this->sr = @ldap_list($this->cid, $basedn, $filter); + 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)) ; + } + } + + $this->log("LDAP operation: time=".get_MicroTimeDiff($start,microtime())." operation=ls('".$this->fix($basedn)."', '$filter')"); + return($this->sr); }else{ $this->error = "Could not connect to LDAP server"; @@ -162,13 +239,13 @@ class LDAP{ } } - function cat($dn) + function cat($dn,$attrs= array("*")) { if($this->hascon){ if ($this->reconnect) $this->connect(); $this->clearResult(); $filter = "(objectclass=*)"; - $this->sr = @ldap_read($this->cid, $dn, $filter); + $this->sr = @ldap_read($this->cid, $this->fix($dn), $filter,$attrs); $this->error = @ldap_error($this->cid); $this->resetResult(); $this->hasres=true; @@ -194,6 +271,7 @@ class LDAP{ function fetch() { + $att= array(); if($this->hascon){ if($this->hasres){ if ($this->start == 0) @@ -206,7 +284,7 @@ class LDAP{ if ($this->re) { $att= @ldap_get_attributes($this->cid, $this->re); - $att['dn']= @ldap_get_dn($this->cid, $this->re); + $att['dn']= trim($this->convert(@ldap_get_dn($this->cid, $this->re))); } $this->error = @ldap_error($this->cid); if (!isset($att)){ @@ -250,8 +328,7 @@ class LDAP{ $rv = @ldap_get_dn($this->cid, $this->re); $this->error = @ldap_error($this->cid); - $rv= preg_replace("/[ ]*,[ ]*/", ",", $rv); - return($rv); + return(trim($this->convert($rv))); } }else{ $this->error = "Perform a Fetch with no Search"; @@ -287,7 +364,7 @@ class LDAP{ if ($dn == "") $dn = $this->basedn; - $r = @ldap_mod_del($this->cid, $dn, $attrs); + $r = @ldap_mod_del($this->cid, $this->fix($dn), $attrs); $this->error = @ldap_error($this->cid); return($r); }else{ @@ -303,7 +380,7 @@ class LDAP{ if ($dn == "") $dn = $this->basedn; - $r = @ldap_mod_replace($this->cid, $dn, $attrs); + $r = @ldap_mod_replace($this->cid, $this->fix($dn), $attrs); $this->error = @ldap_error($this->cid); return($r); }else{ @@ -316,7 +393,7 @@ class LDAP{ { if($this->hascon){ if ($this->reconnect) $this->connect(); - $r = @ldap_delete($this->cid, $deletedn); + $r = @ldap_delete($this->cid, $this->fix($deletedn)); $this->error = @ldap_error($this->cid); return($r ? $r : 0); }else{ @@ -355,7 +432,7 @@ class LDAP{ } /* Finally Delete own Node */ - $r = @ldap_delete($this->cid, $deletedn); + $r = @ldap_delete($this->cid, $this->fix($deletedn)); $this->error = @ldap_error($this->cid); return($r ? $r : 0); }else{ @@ -364,12 +441,184 @@ class LDAP{ } } + /* Copy given attributes and sub-dns with attributes to destination dn + */ + function copy_FAI_resource_recursive($sourcedn,$destinationdn,$destinationName,$type="branch",$is_first = true,$depth=0) + { + error_reporting(E_ALL); + + if($is_first){ + echo "

".sprintf(_("Creating copy of %s"),"".@LDAP::fix($sourcedn)."")."

"; + }else{ + if(preg_match("/^ou=/",$sourcedn)){ + echo "

"._("Processing")." ".@LDAP::fix($destinationdn)."

"; + }else{ + $tmp = split(",",$sourcedn); + + echo " "._("Object").": "; + + $deststr = @LDAP::fix($destinationdn); + if(strlen($deststr) > 96){ + $deststr = substr($deststr,0,96)."..."; + } + + echo $deststr."
"; + } + } + + flush(); + + if($this->hascon){ + if ($this->reconnect) $this->connect(); + + /* Save base dn */ + $basedn= $this->basedn; + $delarray= array(); + + /* Check if destination entry already exists */ + $this->cat($destinationdn); + + if($this->count()){ + return; + }else{ + + $this->clearResult(); + + /* Get source entry */ + $this->cd($basedn); + $this->cat($sourcedn); + $attr = $this->fetch(); + + /* Error while fetching object / attribute abort*/ + if((!$attr) || (count($attr)) ==0) { + echo _("Error while fetching source dn - aborted!"); + return; + } + + /* check if this is a department */ + if(in_array("organizationalUnit",$attr['objectClass'])){ + $attr['dn'] = $this->convert($destinationdn); + $this->cd($basedn); + $this->create_missing_trees($destinationdn); + $this->cd($destinationdn); + + /* If is first entry, append FAIbranch to department entry */ + if($is_first){ + $this->cat($destinationdn); + $attr= $this->fetch(); + + /* Filter unneeded informations */ + foreach($attr as $key => $value){ + if(is_numeric($key)) unset($attr[$key]); + if(isset($attr[$key]['count'])){ + if(is_array($attr[$key])){ + unset($attr[$key]['count']); + } + } + } + + unset($attr['count']); + unset($attr['dn']); + + /* Add marking attribute */ + $attr['objectClass'][] = "FAIbranch"; + + /* Add this entry */ + $this->modify($attr); + } + }else{ + + /* If this is no department */ + foreach($attr as $key => $value){ + 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)){ + $attr[$key] = $tmp; + } + } + + if(is_numeric($key)) unset($attr[$key]); + if(isset($attr[$key]['count'])){ + if(is_array($attr[$key])){ + unset($attr[$key]['count']); + } + } + } + unset($attr['count']); + unset($attr['dn']); + + if((!in_array("gosaApplication" , $attr['objectClass'])) && (!in_array("gotoMimeType", $attr['objectClass']))){ + $attr['FAIdebianRelease'] = $destinationName; + if($type=="branch"){ + $attr['FAIstate'] ="branch"; + }elseif($type=="freeze"){ + $attr['FAIstate'] ="freeze"; + }else{ + print_red(_("Unknown FAIstate %s"),$type); + } + } + + /* Replace FAIdebianRelease with new release name */ + if(in_array("FAIpackageList" , $attr['objectClass'])){ + $attr['FAIdebianRelease'] = $destinationName; + } + + /* Add entry */ + $this->cd($destinationdn); + $this->cat($destinationdn); + $a = $this->fetch(); + if(!count($a)){ + $this->add($attr); + } + + if($this->error != "Success"){ + /* Some error occured */ + print "---------------------------------------------"; + print $this->get_error()."
"; + print $sourcedn."
"; + print $destinationdn."
"; + print_a( $attr); + exit(); + } + } + } + + echo "" ; + + $this->ls ("(objectClass=*)",$sourcedn); + while ($this->fetch()){ + $deldn= $this->getDN(); + $delarray[$deldn]= strlen($deldn); + } + asort ($delarray); + reset ($delarray); + + $depth ++; + foreach($delarray as $dn => $bla){ + if($dn != $destinationdn){ + $this->cd($basedn); + $item = $this->fetch($this->cat($dn)); + if(!in_array("FAIbranch",$item['objectClass'])){ + $this->copy_FAI_resource_recursive($dn,str_replace($sourcedn,$destinationdn,$dn),$destinationName,$type,false,$depth); + } + } + } + } + if($is_first){ + echo "

 

"; + } + + } function modify($attrs) { + if(count($attrs) == 0){ + return (0); + } if($this->hascon){ if ($this->reconnect) $this->connect(); - $r = @ldap_modify($this->cid, $this->basedn, $attrs); + $r = @ldap_modify($this->cid, $this->fix($this->basedn), $attrs); $this->error = @ldap_error($this->cid); return($r ? $r : 0); }else{ @@ -382,7 +631,7 @@ class LDAP{ { if($this->hascon){ if ($this->reconnect) $this->connect(); - $r = @ldap_add($this->cid, $this->basedn, $attrs); + $r = @ldap_add($this->cid, $this->fix($this->basedn), $attrs); $this->error = @ldap_error($this->cid); return($r ? $r : 0); }else{ @@ -393,14 +642,26 @@ class LDAP{ function create_missing_trees($target) { - /* Ignore create_missing trees if the base equals target */ + global $config; + + $real_path= substr($target, 0, strlen($target) - strlen($this->basedn) -1 ); + if ($target == $this->basedn){ - return; + $l= array("dummy"); + } else { + $l= array_reverse(gosa_ldap_explode_dn($real_path)); } - $l= array_reverse(explode(",", preg_replace("/,".$this->basedn."/", "", $target))); + 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; @@ -419,31 +680,109 @@ class LDAP{ $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"; - $na["ou"]= $param; - break; - case 'dc': - $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)); + + /* 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']; + } + } + } + + /* 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(); @@ -463,11 +802,11 @@ class LDAP{ } } - function get_attribute($dn, $name) + function get_attribute($dn, $name,$r_array=0) { $data= ""; if ($this->reconnect) $this->connect(); - $sr= @ldap_read($this->cid, $dn, "objectClass=*", array("$name")); + $sr= @ldap_read($this->cid, $this->fix($dn), "objectClass=*", array("$name")); /* fill data from LDAP */ if ($sr) { @@ -476,11 +815,18 @@ class LDAP{ if ($info= @ldap_get_values_len($this->cid, $ei, "$name")){ $data= $info[0]; } + } } - + if($r_array==0) return ($data); + else + return ($info); + + } + + function get_additional_error() { @@ -494,7 +840,12 @@ class LDAP{ 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->basedn, $this->hostname).")"; + } else { + $error= $this->error." (".sprintf(_("while operating on LDAP server %s"), $this->hostname).")"; + } return $error; } } @@ -512,7 +863,7 @@ class LDAP{ if (isset($referrals[$server])){ return ($referrals[$server]); } else { - $ret['ADMIN']= $this->binddn; + $ret['ADMIN']= $this->fix($this->binddn); $ret['PASSWORD']= $this->bindpw; } @@ -526,14 +877,42 @@ class LDAP{ if ($recursive){ $this->cd($dn); - $this->search("$filter", array('dn')); + $this->ls($filter,$dn, array('dn','objectClass')); + $deps = array(); + + $display .= $this->gen_one_entry($dn)."\n"; + while ($attrs= $this->fetch()){ - $display.= $this->gen_one_entry($attrs['dn'], $filter, $attributes); - $display.= "\n"; + $deps[] = $attrs['dn']; + } + foreach($deps as $dn){ + $display .= $this->gen_ldif($dn, $filter,$attributes,$recursive); } } else { $display.= $this->gen_one_entry($dn); } + return ($display); + } + + + function gen_xls ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE,$r_array=0) + { + $display= array(); + + $this->cd($dn); + $this->search("$filter"); + + $i=0; + while ($attrs= $this->fetch()){ + $j=0; + + foreach ($attributes as $at){ + $display[$i][$j]= $this->get_attribute($attrs['dn'], $at,$r_array); + $j++; + } + + $i++; + } return ($display); } @@ -548,9 +927,9 @@ class LDAP{ } /* Searching Ldap Tree */ - $sr= @ldap_read($this->cid, $dn, $filter, $name); + $sr= @ldap_read($this->cid, $this->fix($dn), $filter, $name); - /* Get the first entry */ + /* Get the first entry */ $entry= @ldap_first_entry($this->cid, $sr); /* Get all attributes related to that Objekt */ @@ -562,7 +941,7 @@ class LDAP{ /* Reset index */ $i = 1 ; - $identifier = array(); + $identifier = array(); $attribute= @ldap_first_attribute($this->cid,$entry,$identifier); while ($attribute) { $i++; @@ -592,12 +971,19 @@ class LDAP{ function dn_exists($dn) { - return @ldap_list($this->cid, $dn, "(objectClass=*)", array("objectClass")); + return @ldap_list($this->cid, $this->fix($dn), "(objectClass=*)", array("objectClass")); } - function import_complete_ldif($str_attr,&$error,$overwrite,$cleanup) + /* This funktion imports ldifs + + If DeleteOldEntries is true, the destination entry will be deleted first. + If JustModify is true the destination entry will only be touched by the attributes specified in the ldif. + if JustMofify id false the destination dn will be overwritten by the new ldif. + */ + + function import_complete_ldif($str_attr,&$error,$JustModify,$DeleteOldEntries) { if($this->reconnect) $this->connect(); @@ -609,8 +995,21 @@ class LDAP{ $cnt = 0; $current_line = 0; + /* FIX ldif */ + $last = ""; + $tmp = ""; + $i = 0; + foreach($entries as $entry){ + if(preg_match("/^ /",$entry)){ + $tmp[$i] .= trim($entry); + }else{ + $i ++; + $tmp[$i] = trim($entry); + } + } + /* Every single line ... */ - foreach($entries as $entry) { + foreach($tmp as $entry) { $current_line ++; /* Removing Spaces to .. @@ -634,15 +1033,15 @@ class LDAP{ if(ereg("::",$tmp2)) { $encoded = split("::",$entry); - $attr = $encoded[0]; - $value = base64_decode($encoded[1]); + $attr = trim($encoded[0]); + $value = base64_decode(trim($encoded[1])); /* Add linenumber */ - $data .= $current_line."#".$attr.":".$value."\n"; + $data .= $current_line."#".base64_encode($attr.":".$value)."\n"; } else { /* Add Linenumber */ - $data .= $current_line."#".$entry."\n"; + $data .= $current_line."#".base64_encode($entry)."\n"; } } } @@ -658,9 +1057,9 @@ class LDAP{ foreach ( $all as $single) { $lineone = split("\n",$single); $ndn = split("#", $lineone[0]); - $line = $ndn[1]; + $line = base64_decode($ndn[1]); - $dnn = split (":",$line); + $dnn = split (":",$line,2); $current_line = $ndn[0]; $dn = $dnn[0]; $value = $dnn[1]; @@ -677,18 +1076,18 @@ class LDAP{ /* Delete before insert */ $usermdir= false; - /* The dn address already exists! */ - if (($this->dn_exists($value))&&((!$overwrite)&&(!$cleanup))) { + /* The dn address already exists, Don't delete destination entry, overwrite it */ + if (($this->dn_exists($value))&&((!$JustModify)&&(!$DeleteOldEntries))) { - $error= sprintf(_("The dn: '%s' (from line %s) already exists in the LDAP database."), $line, $current_line); - return ALREADY_EXISTING_ENTRY; + $usermdir = $usemodify = false; - } elseif(($this->dn_exists($value))&&($cleanup)){ + /* Delete old entry first, then add new */ + } elseif(($this->dn_exists($value))&&($DeleteOldEntries)){ /* Delete first, then add */ $usermdir = true; - } elseif(($this->dn_exists($value))&&($overwrite)) { + } elseif(($this->dn_exists($value))&&($JustModify)) { /* Modify instead of Add */ $usemodify = true; @@ -705,7 +1104,11 @@ class LDAP{ } - /* Imports a single entry */ + /* Imports a single entry + If $delete is true; The old entry will be deleted if it exists. + if $modify is true; All variables that are not touched by the new ldif will be kept. + if $modify is false; The new ldif overwrites the old entry, and all untouched attributes get lost. + */ function import_single_entry($str_attr,$modify,$delete) { if($this->reconnect) $this->connect(); @@ -719,19 +1122,27 @@ class LDAP{ /* Check if we use Linenumbers (when import_complete_ldif is called we use Linenumbers) Linenumbers are use like this 123#attribute : value */ if(!empty($row)) { - if((strpos($row,"#")!=FALSE)&&(strpos($row,"#")cd($data['dn']); /* Delete existing entry */ if($delete){ - $this->rmdir($data['dn']); + $this->rmdir_recursive($data['dn']); } - + /* Create missing trees */ + $this->cd ($this->basedn); $this->create_missing_trees($data['dn']); + $this->cd($data['dn']); + + $dn = $data['dn']; unset($data['dn']); - /* If entry exists use modify */ if(!$modify){ - $ret = $this->add($data); + + $this->cat($dn); + if($this->count()){ + + /* The destination entry exists, overwrite it with the new entry */ + $attrs = $this->fetch(); + foreach($attrs as $name => $value ){ + if(!is_numeric($name)){ + if(in_array($name,array("dn","count"))) continue; + if(!isset($data[$name])){ + $data[$name] = array(); + } + } + } + $ret = $this->modify($data); + + }else{ + + /* The destination entry doesn't exists, create it */ + $ret = $this->add($data); + } + } else { + + /* Keep all vars that aren't touched by this ldif */ $ret = $this->modify($data); } } - + show_ldap_error($this->get_error(), sprintf(_("Ldap import with dn '%s' failed."),$dn)); return($ret); } @@ -801,6 +1249,170 @@ class LDAP{ } } + + function get_objectclasses() + { + $objectclasses = array(); + + # Get base to look for schema + $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 and fill array */ + $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){ + 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'])){ + $cfg= $_SESSION['config']; + if (isset($cfg->current['LDAPSTATS']) && preg_match('/true/i', $cfg->current['LDAPSTATS'])){ + syslog (LOG_INFO, $string); + } + } + } + + /* added by Guido Serra aka Zeph */ + function getCn($dn){ + $simple= split(",", $dn); + + foreach($simple as $piece) { + $partial= split("=", $piece); + + if($partial[0] == "cn"){ + return $partial[1]; + } + } + } + + + function get_naming_contexts($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 ($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); + } + }