X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=gosa-core%2Finclude%2Fclass_ldap.inc;h=6af377218add9ef4562a5ccf76858426a92b4d81;hb=46e5854a4fc9e9ed72276149b64ee8399abdb7d9;hp=625d052cd48603c2b7c9dd737ebe3cd268818a5b;hpb=292ae6f5c9c63240443ea67e8c4f664afcb005dd;p=gosa.git diff --git a/gosa-core/include/class_ldap.inc b/gosa-core/include/class_ldap.inc index 625d052cd..6af377218 100644 --- a/gosa-core/include/class_ldap.inc +++ b/gosa-core/include/class_ldap.inc @@ -1,12 +1,26 @@ - Copyright (C) 2004-2006 Cajus Pollmeier - - Based in code of ldap.inc of - Copyright (C) 1998 Eric Kilfoil - *****************************************************************************/ +/* + * This code is part of GOsa (http://www.gosa-project.org) + * Copyright (C) 2003-2008 GONICUS GmbH + * Copyright (C) 2003 Alejandro Escanero Blanco + * Copyright (C) 1998 Eric Kilfoil + * + * ID: $$Id$$ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ define("ALREADY_EXISTING_ENTRY",-10001); define("UNKNOWN_TOKEN_IN_LDIF_FILE",-10002); @@ -17,13 +31,16 @@ define("SPECIALS_OVERRIDE", TRUE); class LDAP{ var $hascon =false; - var $hasres =false; var $reconnect=false; var $tls = false; - var $basedn =""; var $cid; + var $hasres = array(); + var $sr = array(); + var $re = array(); + var $basedn =""; + var $start = array(); // 0 if we are fetching the first entry, otherwise 1 var $error = ""; // Any error messages to be returned can be put here - var $start = 0; // 0 if we are fetching the first entry, otherwise 1 + var $srp = 0; var $objectClasses = array(); // Information read from slapd.oc.conf var $binddn = ""; var $bindpw = ""; @@ -52,6 +69,15 @@ class LDAP{ } + function getSearchResource() + { + $this->sr[$this->srp]= NULL; + $this->start[$this->srp]= 0; + $this->hasres[$this->srp]= false; + return $this->srp++; + } + + /* 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. @@ -91,6 +117,14 @@ class LDAP{ } + /* Function to fix problematic characters in DN's that are used for search + requests. I.e. member=.... */ + static function prepare4filter($dn) + { + return normalizeLdap(preg_replace('/\\\\/', '\\\\\\', LDAP::fix($dn))); + } + + function connect() { $this->hascon=false; @@ -161,33 +195,35 @@ class LDAP{ function cd($dir) { - if ($dir == "..") + if ($dir == ".."){ $this->basedn = $this->getParentDir(); - else + } else { $this->basedn = LDAP::convert($dir); + } } function getParentDir($basedn = "") { - if ($basedn=="") + if ($basedn==""){ $basedn = $this->basedn; - else + } else { $basedn = LDAP::convert($this->basedn); + } return(ereg_replace("[^,]*[,]*[ ]*(.*)", "\\1", $basedn)); } - function search($filter, $attrs= array()) + + function search($srp, $filter, $attrs= array()) { if($this->hascon){ if ($this->reconnect) $this->connect(); $start = microtime(); - - $this->clearResult(); - $this->sr = @ldap_search($this->cid, LDAP::fix($this->basedn), $filter, $attrs); + $this->clearResult($srp); + $this->sr[$srp] = @ldap_search($this->cid, LDAP::fix($this->basedn), $filter, $attrs); $this->error = @ldap_error($this->cid); - $this->resetResult(); - $this->hasres=true; + $this->resetResult($srp); + $this->hasres[$srp]=true; /* Check if query took longer as specified in max_ldap_query_time */ if($this->max_ldap_query_time){ @@ -198,28 +234,29 @@ class LDAP{ } $this->log("LDAP operation: time=".get_MicroTimeDiff($start,microtime())." operation=search('".LDAP::fix($this->basedn)."', '$filter')"); - return($this->sr); + return($this->sr[$srp]); }else{ $this->error = "Could not connect to LDAP server"; return(""); } } - function ls($filter = "(objectclass=*)", $basedn = "",$attrs = array("*")) + function ls($srp, $filter = "(objectclass=*)", $basedn = "",$attrs = array("*")) { if($this->hascon){ if ($this->reconnect) $this->connect(); - $this->clearResult(); + + $this->clearResult($srp); if ($basedn == "") $basedn = $this->basedn; else $basedn= LDAP::convert($basedn); $start = microtime(); - $this->sr = @ldap_list($this->cid, LDAP::fix($basedn), $filter,$attrs); + $this->sr[$srp] = @ldap_list($this->cid, LDAP::fix($basedn), $filter,$attrs); $this->error = @ldap_error($this->cid); - $this->resetResult(); - $this->hasres=true; + $this->resetResult($srp); + $this->hasres[$srp]=true; /* Check if query took longer as specified in max_ldap_query_time */ if($this->max_ldap_query_time){ @@ -231,24 +268,25 @@ class LDAP{ $this->log("LDAP operation: time=".get_MicroTimeDiff($start,microtime())." operation=ls('".LDAP::fix($basedn)."', '$filter')"); - return($this->sr); + return($this->sr[$srp]); }else{ $this->error = "Could not connect to LDAP server"; return(""); } } - function cat($dn,$attrs= array("*")) + function cat($srp, $dn,$attrs= array("*")) { if($this->hascon){ if ($this->reconnect) $this->connect(); - $this->clearResult(); + + $this->clearResult($srp); $filter = "(objectclass=*)"; - $this->sr = @ldap_read($this->cid, LDAP::fix($dn), $filter,$attrs); + $this->sr[$srp] = @ldap_read($this->cid, LDAP::fix($dn), $filter,$attrs); $this->error = @ldap_error($this->cid); - $this->resetResult(); - $this->hasres=true; - return($this->sr); + $this->resetResult($srp); + $this->hasres[$srp]=true; + return($this->sr[$srp]); }else{ $this->error = "Could not connect to LDAP server"; return(""); @@ -268,26 +306,26 @@ class LDAP{ } } - function fetch() + function fetch($srp) { $att= array(); if($this->hascon){ - if($this->hasres){ - if ($this->start == 0) + if($this->hasres[$srp]){ + if ($this->start[$srp] == 0) { - if ($this->sr){ - $this->start = 1; - $this->re= @ldap_first_entry($this->cid, $this->sr); + if ($this->sr[$srp]){ + $this->start[$srp] = 1; + $this->re[$srp]= @ldap_first_entry($this->cid, $this->sr[$srp]); } else { return array(); } } else { - $this->re= @ldap_next_entry($this->cid, $this->re); + $this->re[$srp]= @ldap_next_entry($this->cid, $this->re[$srp]); } - if ($this->re) + if ($this->re[$srp]) { - $att= @ldap_get_attributes($this->cid, $this->re); - $att['dn']= trim(LDAP::convert(@ldap_get_dn($this->cid, $this->re))); + $att= @ldap_get_attributes($this->cid, $this->re[$srp]); + $att['dn']= trim(LDAP::convert(@ldap_get_dn($this->cid, $this->re[$srp]))); } $this->error = @ldap_error($this->cid); if (!isset($att)){ @@ -295,7 +333,7 @@ class LDAP{ } return($att); }else{ - $this->error = "Perform a Fetch with no Search"; + $this->error = "Perform a fetch with no search"; return(""); } }else{ @@ -304,31 +342,31 @@ class LDAP{ } } - function resetResult() + function resetResult($srp) { - $this->start = 0; + $this->start[$srp] = 0; } - function clearResult() + function clearResult($srp) { - if($this->hasres){ - $this->hasres = false; - @ldap_free_result($this->sr); + if($this->hasres[$srp]){ + $this->hasres[$srp] = false; + @ldap_free_result($this->sr[$srp]); } } - function getDN() + function getDN($srp) { if($this->hascon){ - if($this->hasres){ + if($this->hasres[$srp]){ - if(!$this->re) + if(!$this->re[$srp]) { $this->error = "Perform a Fetch with no valid Result"; } else { - $rv = @ldap_get_dn($this->cid, $this->re); + $rv = @ldap_get_dn($this->cid, $this->re[$srp]); $this->error = @ldap_error($this->cid); return(trim(LDAP::convert($rv))); @@ -343,11 +381,11 @@ class LDAP{ } } - function count() + function count($srp) { if($this->hascon){ - if($this->hasres){ - $rv = @ldap_count_entries($this->cid, $this->sr); + if($this->hasres[$srp]){ + $rv = @ldap_count_entries($this->cid, $this->sr[$srp]); $this->error = @ldap_error($this->cid); return($rv); }else{ @@ -405,6 +443,55 @@ class LDAP{ } } + + /*! \brief Move the given Ldap entry from $source to $dest + @param String $source The source dn. + @param String $dest The destination dn. + @return Boolean TRUE on success else FALSE. + */ + function rename_dn($source,$dest) + { + $source = LDAP::fix($source); + $dest = LDAP::fix($dest); + + /* Check if source and destination are the same entry */ + if(strtolower($source) == strtolower($dest)){ + trigger_error("Source and destination can't be the same entry."); + $this->error = "Source and destination can't be the same entry."; + return(FALSE); + } + + /* Check if destination entry exists */ + if($this->dn_exists($dest)){ + trigger_error("Destination '$dest' already exists."); + $this->error = "Destination '$dest' already exists."; + return(FALSE); + } + + /* Extract the name and the parent part out ouf source dn. + e.g. cn=herbert,ou=department,dc=... + parent => ou=department,dc=... + dest_rdn => cn=herbert + */ + $parent = preg_replace("/^[^,]+,/","",$dest); + $dest_rdn = preg_replace("/,.*$/","",$dest); + + if($this->hascon){ + if ($this->reconnect) $this->connect(); + $r= ldap_rename($this->cid,$source,$dest_rdn,$parent,TRUE); + $this->error = ldap_error($this->cid); + + /* Check if destination dn exists, if not the + server may not support this operation */ + $r &= is_resource($this->dn_exists($dest)); + return($r); + }else{ + $this->error = "Could not connect to LDAP server"; + return(FALSE); + } + } + + /** * Function rmdir_recursive * @@ -413,17 +500,16 @@ class LDAP{ * GiveBack: True on sucessfull , 0 in error, and "" when we don't get a ldap conection * */ - - function rmdir_recursive($deletedn) + function rmdir_recursive($srp, $deletedn) { if($this->hascon){ if ($this->reconnect) $this->connect(); $delarray= array(); /* Get sorted list of dn's to delete */ - $this->ls ("(objectClass=*)",$deletedn); - while ($this->fetch()){ - $deldn= $this->getDN(); + $this->ls ($srp, "(objectClass=*)",$deletedn); + while ($this->fetch($srp)){ + $deldn= $this->getDN($srp); $delarray[$deldn]= strlen($deldn); } arsort ($delarray); @@ -431,7 +517,7 @@ class LDAP{ /* Really Delete ALL dn's in subtree */ foreach ($delarray as $key => $value){ - $this->rmdir_recursive($key); + $this->rmdir_recursive($srp, $key); } /* Finally Delete own Node */ @@ -474,7 +560,7 @@ class LDAP{ } } - function create_missing_trees($target) + function create_missing_trees($srp, $target) { global $config; @@ -510,8 +596,8 @@ class LDAP{ continue; } - $this->cat ($cdn); - $attrs= $this->fetch(); + $this->cat ($srp, $cdn); + $attrs= $this->fetch($srp); /* Create missing entry? */ if (count ($attrs)){ @@ -550,8 +636,8 @@ class LDAP{ /* Bail out, if we've nothing to do... */ if ($ocname == ""){ - msg_dialog::display(_("Internal error"), sprintf(_("Cannot automatically create subtrees with RDN '%s': no object class found"),$type), ERROR_DIALOG); - display_error_page(); + msg_dialog::display(_("Internal error"), sprintf(_("Cannot automatically create subtrees with RDN '%s': no object class found!"),$type), FATAL_ERROR_DIALOG); + exit(); } /* Assemble_entry */ @@ -598,16 +684,16 @@ class LDAP{ $na["dc"]= $param; break; default: - msg_dialog::display(_("Internal error"), sprintf(_("Cannot automatically create subtrees with RDN '%s': not supported"),$type), ERROR_DIALOG); - display_error_page(); + msg_dialog::display(_("Internal error"), sprintf(_("Cannot automatically create subtrees with RDN '%s': not supported"),$type), FATAL_ERROR_DIALOG); + 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)){ + if (!$this->success()){ + msg_dialog::display(_("LDAP error"), msgPool::ldaperror($this->get_error(), $cdn, LDAP_ADD, get_class())); return FALSE; } } @@ -617,14 +703,14 @@ class LDAP{ } - function recursive_remove() + function recursive_remove($srp) { $delarray= array(); /* Get sorted list of dn's to delete */ - $this->search ("(objectClass=*)"); - while ($this->fetch()){ - $deldn= $this->getDN(); + $this->search ($srp, "(objectClass=*)"); + while ($this->fetch($srp)){ + $deldn= $this->getDN($srp); $delarray[$deldn]= strlen($deldn); } arsort ($delarray); @@ -668,6 +754,13 @@ class LDAP{ return ($error); } + + function success() + { + return (preg_match('/Success/i', $this->error)); + } + + function get_error() { if ($this->error == 'Success'){ @@ -704,22 +797,22 @@ class LDAP{ } - function gen_ldif ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE) + function gen_ldif ($srp, $dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE) { $display= ""; if ($recursive){ $this->cd($dn); - $this->ls($filter,$dn, array('dn','objectClass')); + $this->ls($srp, $filter,$dn, array('dn','objectClass')); $deps = array(); $display .= $this->gen_one_entry($dn)."\n"; - while ($attrs= $this->fetch()){ + while ($attrs= $this->fetch($srp)){ $deps[] = $attrs['dn']; } foreach($deps as $dn){ - $display .= $this->gen_ldif($dn, $filter,$attributes,$recursive); + $display .= $this->gen_ldif($srp, $dn, $filter,$attributes,$recursive); } } else { $display.= $this->gen_one_entry($dn); @@ -728,15 +821,15 @@ class LDAP{ } - function gen_xls ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE,$r_array=0) + function gen_xls ($srp, $dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE,$r_array=0) { $display= array(); $this->cd($dn); - $this->search("$filter"); + $this->search($srp, "$filter"); $i=0; - while ($attrs= $this->fetch()){ + while ($attrs= $this->fetch($srp)){ $j=0; foreach ($attributes as $at){ @@ -816,7 +909,7 @@ class LDAP{ if JustMofify id false the destination dn will be overwritten by the new ldif. */ - function import_complete_ldif($str_attr,&$error,$JustModify,$DeleteOldEntries) + function import_complete_ldif($srp, $str_attr,$error,$JustModify,$DeleteOldEntries) { if($this->reconnect) $this->connect(); @@ -927,7 +1020,7 @@ class LDAP{ } /* If we can't Import, return with a file error */ - if(!$this->import_single_entry($single,$usemodify,$usermdir) ) { + if(!$this->import_single_entry($srp, $single,$usemodify,$usermdir) ) { $error= sprintf(_("Error while importing dn: '%s', please check your LDIF from line %s on!"), $line, $current_line); return UNKNOWN_TOKEN_IN_LDIF_FILE; } @@ -942,7 +1035,7 @@ class LDAP{ 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) + function import_single_entry($srp, $str_attr,$modify,$delete) { global $config; @@ -1023,13 +1116,13 @@ class LDAP{ /* Delete existing entry */ if($delete){ - $this->rmdir_recursive($data['dn']); + $this->rmdir_recursive($srp, $data['dn']); } /* Create missing trees */ $this->cd ($this->basedn); $this->cd($config->current['BASE']); - $this->create_missing_trees(preg_replace("/^[^,]+,/","",$data['dn'])); + $this->create_missing_trees($srp, preg_replace("/^[^,]+,/","",$data['dn'])); $this->cd($data['dn']); $dn = $data['dn']; @@ -1037,11 +1130,11 @@ class LDAP{ if(!$modify){ - $this->cat($dn); - if($this->count()){ + $this->cat($srp, $dn); + if($this->count($srp)){ /* The destination entry exists, overwrite it with the new entry */ - $attrs = $this->fetch(); + $attrs = $this->fetch($srp); foreach($attrs as $name => $value ){ if(!is_numeric($name)){ if(in_array($name,array("dn","count"))) continue; @@ -1064,7 +1157,11 @@ class LDAP{ $ret = $this->modify($data); } } - show_ldap_error($this->get_error(), sprintf(_("Ldap import with dn '%s' failed."),$dn)); + + if (!$this->success()){ + msg_dialog::display(_("LDAP error"), msgPool::ldaperror($this->get_error(), $dn, "", get_class())); + } + return($ret); } @@ -1102,13 +1199,15 @@ class LDAP{ return($objectclasses); } } + + /* Return the cached results. */ + if(class_available('session') && session::is_set("LDAP_CACHE::get_objectclasses")){ + $objectclasses = session::get("LDAP_CACHE::get_objectclasses"); + return($objectclasses); + } # 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")); - } - + $sr = @ldap_read ($this->cid, "", "objectClass=*", array("subschemaSubentry")); $attr = @ldap_get_entries($this->cid,$sr); if (!isset($attr[0]['subschemasubentry'][0])){ return array(); @@ -1165,6 +1264,10 @@ class LDAP{ } } + if(class_available("session")){ + session::set("LDAP_CACHE::get_objectclasses",$objectclasses); + } + return $objectclasses; } @@ -1261,6 +1364,7 @@ class LDAP{ return ($result); } + } // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: ?>