b2085531dc7c755a38ee2de010ec39dad715f9da
1 <?php
2 /*****************************************************************************
3 newldap.inc - version 1.0
4 Copyright (C) 2003 Alejandro Escanero Blanco <alex@ofmin.com>
5 Copyright (C) 2004-2006 Cajus Pollmeier <pollmeier@gonicus.de>
7 Based in code of ldap.inc of
8 Copyright (C) 1998 Eric Kilfoil <eric@ipass.net>
9 *****************************************************************************/
11 define("ALREADY_EXISTING_ENTRY",-10001);
12 define("UNKNOWN_TOKEN_IN_LDIF_FILE",-10002);
13 define("NO_FILE_UPLOADED",10003);
14 define("INSERT_OK",10000);
15 define("SPECIALS_OVERRIDE", TRUE);
17 class LDAP{
19 var $hascon =false;
20 var $hasres =false;
21 var $reconnect=false;
22 var $tls = false;
23 var $basedn ="";
24 var $cid;
25 var $error = ""; // Any error messages to be returned can be put here
26 var $start = 0; // 0 if we are fetching the first entry, otherwise 1
27 var $objectClasses = array(); // Information read from slapd.oc.conf
28 var $binddn = "";
29 var $bindpw = "";
30 var $hostname = "";
31 var $follow_referral = FALSE;
32 var $referrals= array();
33 var $max_ldap_query_time = 0; // 0, empty or negative values will disable this check
35 function LDAP($binddn,$bindpw, $hostname, $follow_referral= FALSE, $tls= FALSE)
36 {
37 global $config;
38 $this->follow_referral= $follow_referral;
39 $this->tls=$tls;
40 $this->binddn=$this->convert($binddn);
42 $this->bindpw=$bindpw;
43 $this->hostname=$hostname;
45 /* Check if MAX_LDAP_QUERY_TIME is defined */
46 if(isset($config->data['MAIN']['MAX_LDAP_QUERY_TIME'])){
47 $str = $config->data['MAIN']['MAX_LDAP_QUERY_TIME'];
48 $this->max_ldap_query_time = (float)($str);
49 }
51 $this->connect();
52 }
55 /* Function to replace all problematic characters inside a DN by \001XX, where
56 \001 is decoded to chr(1) [ctrl+a]. It is not impossible, but very unlikely
57 that this character is inside a DN.
59 Currently used codes:
60 , => CO
61 \2C => CO
62 ( => OB
63 ) => CB
64 / => SL */
65 function convert($dn)
66 {
67 if (SPECIALS_OVERRIDE == TRUE){
68 $tmp= preg_replace(array("/\\\\,/", "/\\\\2C/", "/\(/", "/\)/", "/\//"),
69 array("\001CO", "\001CO", "\001OB", "\001CB", "\001SL"),
70 $dn);
71 return (preg_replace('/,\s+/', ',', $tmp));
72 } else {
73 return ($dn);
74 }
75 }
78 /* Function to fix all problematic characters inside a DN by replacing \001XX
79 codes to their original values. See "convert" for mor information.
80 ',' characters are always expanded to \, (not \2C), since all tested LDAP
81 servers seem to take it the correct way. */
82 function fix($dn)
83 {
84 if (SPECIALS_OVERRIDE == TRUE){
85 return (preg_replace(array("/\001CO/", "/\001OB/", "/\001CB/", "/\001SL/"),
86 array("\,", "(", ")", "/"),
87 $dn));
88 } else {
89 return ($dn);
90 }
91 }
94 function connect()
95 {
96 $this->hascon=false;
97 $this->reconnect=false;
98 if ($this->cid= @ldap_connect($this->hostname)) {
99 @ldap_set_option($this->cid, LDAP_OPT_PROTOCOL_VERSION, 3);
100 if (function_exists("ldap_set_rebind_proc") && $this->follow_referral) {
101 @ldap_set_option($this->cid, LDAP_OPT_REFERRALS, 1);
102 @ldap_set_rebind_proc($this->cid, array(&$this, "rebind"));
103 }
104 if (function_exists("ldap_start_tls") && $this->tls){
105 @ldap_start_tls($this->cid);
106 }
108 $this->error = "No Error";
109 if ($bid = @ldap_bind($this->cid, $this->fix($this->binddn), $this->bindpw)) {
110 $this->error = "Success";
111 $this->hascon=true;
112 } else {
113 if ($this->reconnect){
114 if ($this->error != "Success"){
115 $this->error = "Could not rebind to " . $this->binddn;
116 }
117 } else {
118 $this->error = "Could not bind to " . $this->binddn;
119 }
120 }
121 } else {
122 $this->error = "Could not connect to LDAP server";
123 }
124 }
126 function rebind($ldap, $referral)
127 {
128 $credentials= $this->get_credentials($referral);
129 if (@ldap_bind($ldap, $this->fix($credentials['ADMIN']), $credentials['PASSWORD'])) {
130 $this->error = "Success";
131 $this->hascon=true;
132 $this->reconnect= true;
133 return (0);
134 } else {
135 $this->error = "Could not bind to " . $credentials['ADMIN'];
136 return NULL;
137 }
138 }
140 function reconnect()
141 {
142 if ($this->reconnect){
143 @ldap_unbind($this->cid);
144 $this->cid = NULL;
145 }
146 }
148 function unbind()
149 {
150 @ldap_unbind($this->cid);
151 $this->cid = NULL;
152 }
154 function disconnect()
155 {
156 if($this->hascon){
157 @ldap_close($this->cid);
158 $this->hascon=false;
159 }
160 }
162 function cd($dir)
163 {
164 if ($dir == "..")
165 $this->basedn = $this->getParentDir();
166 else
167 $this->basedn = $this->convert($dir);
168 }
170 function getParentDir($basedn = "")
171 {
172 if ($basedn=="")
173 $basedn = $this->basedn;
174 else
175 $basedn = $this->convert($this->basedn);
176 return(ereg_replace("[^,]*[,]*[ ]*(.*)", "\\1", $basedn));
177 }
179 function search($filter, $attrs= array())
180 {
181 if($this->hascon){
182 if ($this->reconnect) $this->connect();
184 $start = microtime();
186 $this->clearResult();
187 $this->sr = @ldap_search($this->cid, $this->fix($this->basedn), $filter, $attrs);
188 $this->error = @ldap_error($this->cid);
189 $this->resetResult();
190 $this->hasres=true;
192 /* Check if query took longer as specified in max_ldap_query_time */
193 if($this->max_ldap_query_time){
194 $diff = get_MicroTimeDiff($start,microtime());
195 if($diff > $this->max_ldap_query_time){
196 print_red(sprintf(_("The LDAP server is slow (%.2fs for the last query). This may be responsible for performance breakdowns."),$diff)) ;
197 }
198 }
200 return($this->sr);
201 }else{
202 $this->error = "Could not connect to LDAP server";
203 return("");
204 }
205 }
207 function ls($filter = "(objectclass=*)", $basedn = "",$attrs = array("*"))
208 {
209 if($this->hascon){
210 if ($this->reconnect) $this->connect();
211 $this->clearResult();
212 if ($basedn == "")
213 $basedn = $this->basedn;
214 else
215 $basedn= $this->convert($basedn);
217 $start = microtime();
219 $this->sr = @ldap_list($this->cid, $this->fix($basedn), $filter,$attrs);
220 $this->error = @ldap_error($this->cid);
221 $this->resetResult();
222 $this->hasres=true;
224 /* Check if query took longer as specified in max_ldap_query_time */
225 if($this->max_ldap_query_time){
226 $diff = get_MicroTimeDiff($start,microtime());
227 if($diff > $this->max_ldap_query_time){
228 print_red(sprintf(_("The ldapserver is answering very slow (%.2f), this may be responsible for performance breakdowns."),$diff)) ;
229 }
230 }
232 return($this->sr);
233 }else{
234 $this->error = "Could not connect to LDAP server";
235 return("");
236 }
237 }
239 function cat($dn,$attrs= array("*"))
240 {
241 if($this->hascon){
242 if ($this->reconnect) $this->connect();
243 $this->clearResult();
244 $filter = "(objectclass=*)";
245 $this->sr = @ldap_read($this->cid, $this->fix($dn), $filter,$attrs);
246 $this->error = @ldap_error($this->cid);
247 $this->resetResult();
248 $this->hasres=true;
249 return($this->sr);
250 }else{
251 $this->error = "Could not connect to LDAP server";
252 return("");
253 }
254 }
256 function set_size_limit($size)
257 {
258 /* Ignore zero settings */
259 if ($size == 0){
260 @ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, 10000000);
261 }
262 if($this->hascon){
263 @ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, $size);
264 } else {
265 $this->error = "Could not connect to LDAP server";
266 }
267 }
269 function fetch()
270 {
271 $att= array();
272 if($this->hascon){
273 if($this->hasres){
274 if ($this->start == 0)
275 {
276 $this->start = 1;
277 $this->re= @ldap_first_entry($this->cid, $this->sr);
278 } else {
279 $this->re= @ldap_next_entry($this->cid, $this->re);
280 }
281 if ($this->re)
282 {
283 $att= @ldap_get_attributes($this->cid, $this->re);
284 $att['dn']= $this->convert(@ldap_get_dn($this->cid, $this->re));
285 }
286 $this->error = @ldap_error($this->cid);
287 if (!isset($att)){
288 $att= array();
289 }
290 return($att);
291 }else{
292 $this->error = "Perform a Fetch with no Search";
293 return("");
294 }
295 }else{
296 $this->error = "Could not connect to LDAP server";
297 return("");
298 }
299 }
301 function resetResult()
302 {
303 $this->start = 0;
304 }
306 function clearResult()
307 {
308 if($this->hasres){
309 $this->hasres = false;
310 @ldap_free_result($this->sr);
311 }
312 }
314 function getDN()
315 {
316 if($this->hascon){
317 if($this->hasres){
319 if(!$this->re)
320 {
321 $this->error = "Perform a Fetch with no valid Result";
322 }
323 else
324 {
325 $rv = @ldap_get_dn($this->cid, $this->re);
327 $this->error = @ldap_error($this->cid);
328 return($this->convert($rv));
329 }
330 }else{
331 $this->error = "Perform a Fetch with no Search";
332 return("");
333 }
334 }else{
335 $this->error = "Could not connect to LDAP server";
336 return("");
337 }
338 }
340 function count()
341 {
342 if($this->hascon){
343 if($this->hasres){
344 $rv = @ldap_count_entries($this->cid, $this->sr);
345 $this->error = @ldap_error($this->cid);
346 return($rv);
347 }else{
348 $this->error = "Perform a Fetch with no Search";
349 return("");
350 }
351 }else{
352 $this->error = "Could not connect to LDAP server";
353 return("");
354 }
355 }
357 function rm($attrs = "", $dn = "")
358 {
359 if($this->hascon){
360 if ($this->reconnect) $this->connect();
361 if ($dn == "")
362 $dn = $this->basedn;
364 $r = @ldap_mod_del($this->cid, $this->fix($dn), $attrs);
365 $this->error = @ldap_error($this->cid);
366 return($r);
367 }else{
368 $this->error = "Could not connect to LDAP server";
369 return("");
370 }
371 }
373 function rename($attrs, $dn = "")
374 {
375 if($this->hascon){
376 if ($this->reconnect) $this->connect();
377 if ($dn == "")
378 $dn = $this->basedn;
380 $r = @ldap_mod_replace($this->cid, $this->fix($dn), $attrs);
381 $this->error = @ldap_error($this->cid);
382 return($r);
383 }else{
384 $this->error = "Could not connect to LDAP server";
385 return("");
386 }
387 }
389 function rmdir($deletedn)
390 {
391 if($this->hascon){
392 if ($this->reconnect) $this->connect();
393 $r = @ldap_delete($this->cid, $this->fix($deletedn));
394 $this->error = @ldap_error($this->cid);
395 return($r ? $r : 0);
396 }else{
397 $this->error = "Could not connect to LDAP server";
398 return("");
399 }
400 }
402 /**
403 * Function rmdir_recursive
404 *
405 * Description: Based in recursive_remove, adding two thing: full subtree remove, and delete own node.
406 * Parameters: The dn to delete
407 * GiveBack: True on sucessfull , 0 in error, and "" when we don't get a ldap conection
408 *
409 */
411 function rmdir_recursive($deletedn)
412 {
413 if($this->hascon){
414 if ($this->reconnect) $this->connect();
415 $delarray= array();
417 /* Get sorted list of dn's to delete */
418 $this->ls ("(objectClass=*)",$deletedn);
419 while ($this->fetch()){
420 $deldn= $this->getDN();
421 $delarray[$deldn]= strlen($deldn);
422 }
423 arsort ($delarray);
424 reset ($delarray);
426 /* Really Delete ALL dn's in subtree */
427 foreach ($delarray as $key => $value){
428 $this->rmdir_recursive($key);
429 }
431 /* Finally Delete own Node */
432 $r = @ldap_delete($this->cid, $this->fix($deletedn));
433 $this->error = @ldap_error($this->cid);
434 return($r ? $r : 0);
435 }else{
436 $this->error = "Could not connect to LDAP server";
437 return("");
438 }
439 }
441 /* Copy given attributes and sub-dns with attributes to destination dn
442 */
443 function copy_FAI_resource_recursive($sourcedn,$destinationdn,$destinationName,$type="branch",$is_first = true,$depth=0)
444 {
445 error_reporting(E_ALL);
447 if($is_first){
448 echo "<h2>".sprintf(_("Creating copy of %s"),"<i>".@LDAP::fix($sourcedn)."</i>")."</h2>";
449 }else{
450 if(preg_match("/^ou=/",$sourcedn)){
451 echo "<h3>"._("Processing")." <i>".@LDAP::fix($destinationdn)."</i></h3>";
452 }else{
453 $tmp = split(",",$sourcedn);
455 echo " <b>"._("Object").":</b> ";
457 $deststr = @LDAP::fix($destinationdn);
458 if(strlen($deststr) > 96){
459 $deststr = substr($deststr,0,96)."...";
460 }
462 echo $deststr."<br>";
463 }
464 }
466 flush();
468 if($this->hascon){
469 if ($this->reconnect) $this->connect();
471 /* Save base dn */
472 $basedn= $this->basedn;
473 $delarray= array();
475 /* Check if destination entry already exists */
476 $this->cat($destinationdn);
478 if($this->count()){
479 return;
480 }else{
482 $this->clearResult();
484 /* Get source entry */
485 $this->cd($basedn);
486 $this->cat($sourcedn);
487 $attr = $this->fetch();
489 /* Error while fetching object / attribute abort*/
490 if((!$attr) || (count($attr)) ==0) {
491 echo _("Error while fetching source dn - aborted!");
492 return;
493 }
495 /* check if this is a department */
496 if(in_array("organizationalUnit",$attr['objectClass'])){
497 $attr['dn'] = $this->convert($destinationdn);
498 $this->cd($basedn);
499 $this->create_missing_trees($destinationdn);
500 $this->cd($destinationdn);
502 /* If is first entry, append FAIbranch to department entry */
503 if($is_first){
504 $this->cat($destinationdn);
505 $attr= $this->fetch();
507 /* Filter unneeded informations */
508 foreach($attr as $key => $value){
509 if(is_numeric($key)) unset($attr[$key]);
510 if(isset($attr[$key]['count'])){
511 if(is_array($attr[$key])){
512 unset($attr[$key]['count']);
513 }
514 }
515 }
517 unset($attr['count']);
518 unset($attr['dn']);
520 /* Add marking attribute */
521 $attr['objectClass'][] = "FAIbranch";
523 /* Add this entry */
524 $this->modify($attr);
525 }
526 }else{
528 /* If this is no department */
529 foreach($attr as $key => $value){
530 if(in_array($key ,array("FAItemplateFile","FAIscript", "gotoLogonScript", "gosaApplicationIcon"))){
531 $sr= ldap_read($this->cid, $this->fix($sourcedn), "$key=*", array($key));
532 $ei= ldap_first_entry($this->cid, $sr);
533 if ($tmp= @ldap_get_values_len($this->cid, $ei,$key)){
534 $attr[$key] = $tmp;
535 }
536 }
538 if(is_numeric($key)) unset($attr[$key]);
539 if(isset($attr[$key]['count'])){
540 if(is_array($attr[$key])){
541 unset($attr[$key]['count']);
542 }
543 }
544 }
545 unset($attr['count']);
546 unset($attr['dn']);
548 if(!in_array("gosaApplication" , $attr['objectClass'])){
549 if($type=="branch"){
550 $attr['FAIstate'] ="branch";
551 }elseif($type=="freeze"){
552 $attr['FAIstate'] ="freeze";
553 }else{
554 print_red(_("Unknown FAIstate %s"),$type);
555 }
556 }
558 /* Replace FAIdebianRelease with new release name */
559 if(in_array("FAIpackageList" , $attr['objectClass'])){
560 $attr['FAIdebianRelease'] = $destinationName;
561 }
563 /* Add entry */
564 $this->cd($destinationdn);
565 $this->cat($destinationdn);
566 $a = $this->fetch();
567 if(!count($a)){
568 $this->add($attr);
569 }
571 if($this->error != "Success"){
572 /* Some error occured */
573 print "---------------------------------------------";
574 print $this->get_error()."<br>";
575 print $sourcedn."<br>";
576 print $destinationdn."<br>";
577 print_a( $attr);
578 exit();
579 }
580 }
581 }
583 $this->ls ("(objectClass=*)",$sourcedn);
584 while ($this->fetch()){
585 $deldn= $this->getDN();
586 $delarray[$deldn]= strlen($deldn);
587 }
588 asort ($delarray);
589 reset ($delarray);
591 $depth ++;
592 foreach($delarray as $dn => $bla){
593 if($dn != $destinationdn){
594 $this->cd($basedn);
595 $item = $this->fetch($this->cat($dn));
596 if(!in_array("FAIbranch",$item['objectClass'])){
597 $this->copy_FAI_resource_recursive($dn,str_replace($sourcedn,$destinationdn,$dn),$destinationName,$type,false,$depth);
598 }
599 }
600 }
601 }
602 if($is_first){
603 echo "<p class='seperator'> </p>";
604 }
606 }
608 function modify($attrs)
609 {
610 if(count($attrs) == 0){
611 return (0);
612 }
613 if($this->hascon){
614 if ($this->reconnect) $this->connect();
615 $r = @ldap_modify($this->cid, $this->fix($this->basedn), $attrs);
616 $this->error = @ldap_error($this->cid);
617 return($r ? $r : 0);
618 }else{
619 $this->error = "Could not connect to LDAP server";
620 return("");
621 }
622 }
624 function add($attrs)
625 {
626 if($this->hascon){
627 if ($this->reconnect) $this->connect();
628 $r = @ldap_add($this->cid, $this->fix($this->basedn), $attrs);
629 $this->error = @ldap_error($this->cid);
630 return($r ? $r : 0);
631 }else{
632 $this->error = "Could not connect to LDAP server";
633 return("");
634 }
635 }
637 function create_missing_trees($target)
638 {
639 /* Ignore create_missing trees if the base equals target */
640 if ($target == $this->basedn){
641 return;
642 }
644 $real_path= substr($target, 0, strlen($target) - strlen($this->basedn) -1 );
645 $l= array_reverse(ldap_explode_dn($real_path,0));
646 unset($l['count']);
647 $cdn= $this->basedn;
648 $tag= "";
650 foreach ($l as $part){
651 $cdn= "$part,$cdn";
653 /* Ignore referrals */
654 $found= false;
655 foreach($this->referrals as $ref){
656 $base= preg_replace('!^[^:]+://[^/]+/([^?]+).*$!', '\\1', $ref['URL']);
657 if ($base == $cdn){
658 $found= true;
659 break;
660 }
661 }
662 if ($found){
663 continue;
664 }
666 $this->cat ($cdn);
667 $attrs= $this->fetch();
669 /* Create missing entry? */
670 if (count ($attrs)){
672 /* Catch the tag - if present */
673 if (isset($attrs['gosaUnitTag'][0])){
674 $tag= $attrs['gosaUnitTag'][0];
675 }
677 } else {
678 $type= preg_replace('/^([^=]+)=.*$/', '\\1', $cdn);
679 $param= preg_replace('/^[^=]+=([^,]+),.*$/', '\\1', $cdn);
681 $na= array();
682 switch ($type){
683 case 'ou':
684 if ($tag != ""){
685 $na["objectClass"]= array("organizationalUnit", "gosaAdministrativeUnitTag");
686 $na["gosaUnitTag"]= $tag;
687 } else {
688 $na["objectClass"]= "organizationalUnit";
689 }
690 $na["ou"]= $param;
691 break;
692 case 'dc':
693 if ($tag != ""){
694 $na["objectClass"]= array("dcObject", "top", "locality", "gosaAdministrativeUnitTag");
695 $na["gosaUnitTag"]= $tag;
696 } else {
697 $na["objectClass"]= array("dcObject", "top", "locality");
698 }
699 $na["dc"]= $param;
700 break;
701 default:
702 print_red(sprintf(_("Autocreation of type '%s' is currently not supported. Please report to the GOsa team."), $type));
703 echo $_SESSION['errors'];
704 exit;
705 }
706 $this->cd($cdn);
707 $this->add($na);
708 }
709 }
710 }
712 function recursive_remove()
713 {
714 $delarray= array();
716 /* Get sorted list of dn's to delete */
717 $this->search ("(objectClass=*)");
718 while ($this->fetch()){
719 $deldn= $this->getDN();
720 $delarray[$deldn]= strlen($deldn);
721 }
722 arsort ($delarray);
723 reset ($delarray);
725 /* Delete all dn's in subtree */
726 foreach ($delarray as $key => $value){
727 $this->rmdir($key);
728 }
729 }
731 function get_attribute($dn, $name,$r_array=0)
732 {
733 $data= "";
734 if ($this->reconnect) $this->connect();
735 $sr= @ldap_read($this->cid, $this->fix($dn), "objectClass=*", array("$name"));
737 /* fill data from LDAP */
738 if ($sr) {
739 $ei= @ldap_first_entry($this->cid, $sr);
740 if ($ei) {
741 if ($info= @ldap_get_values_len($this->cid, $ei, "$name")){
742 $data= $info[0];
743 }
745 }
746 }
747 if($r_array==0)
748 return ($data);
749 else
750 return ($info);
753 }
757 function get_additional_error()
758 {
759 $error= "";
760 @ldap_get_option ($this->cid, LDAP_OPT_ERROR_STRING, $error);
761 return ($error);
762 }
764 function get_error()
765 {
766 if ($this->error == 'Success'){
767 return $this->error;
768 } else {
769 $adderror= $this->get_additional_error();
770 if ($adderror != ""){
771 $error= $this->error." (".$this->get_additional_error().", ".sprintf(_("while operating on '%s' using LDAP server '%s'"), $this->basedn, $this->hostname).")";
772 } else {
773 $error= $this->error." (".sprintf(_("while operating on LDAP server %s"), $this->hostname).")";
774 }
775 return $error;
776 }
777 }
779 function get_credentials($url, $referrals= NULL)
780 {
781 $ret= array();
782 $url= preg_replace('!\?\?.*$!', '', $url);
783 $server= preg_replace('!^([^:]+://[^/]+)/.*$!', '\\1', $url);
785 if ($referrals == NULL){
786 $referrals= $this->referrals;
787 }
789 if (isset($referrals[$server])){
790 return ($referrals[$server]);
791 } else {
792 $ret['ADMIN']= $this->fix($this->binddn);
793 $ret['PASSWORD']= $this->bindpw;
794 }
796 return ($ret);
797 }
800 function gen_ldif ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE)
801 {
802 $display= "";
804 if ($recursive){
805 $this->cd($dn);
806 $this->search("$filter", array('dn'));
807 while ($attrs= $this->fetch()){
808 $display.= $this->gen_one_entry($attrs['dn'], $filter, $attributes);
809 $display.= "\n";
810 }
811 } else {
812 $display.= $this->gen_one_entry($dn);
813 }
815 return ($display);
816 }
818 function gen_xls ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE,$r_array=0)
819 {
820 $display= "";
822 $this->cd($dn);
823 $this->search("$filter");
825 $i=0;
826 while ($attrs= $this->fetch()){
827 $j=0;
829 foreach ($attributes as $at){
830 $display[$i][$j]= $this->get_attribute($attrs['dn'], $at,$r_array);
831 $j++;
832 }
834 $i++;
835 }
837 return ($display);
838 }
841 function gen_one_entry($dn, $filter= "(objectClass=*)" , $name= array("*"))
842 {
843 $ret = "";
844 $data = "";
845 if($this->reconnect){
846 $this->connect();
847 }
849 /* Searching Ldap Tree */
850 $sr= @ldap_read($this->cid, $this->fix($dn), $filter, $name);
852 /* Get the first entry */
853 $entry= @ldap_first_entry($this->cid, $sr);
855 /* Get all attributes related to that Objekt */
856 $atts = array();
858 /* Assemble dn */
859 $atts[0]['name'] = "dn";
860 $atts[0]['value'] = array('count' => 1, 0 => $dn);
862 /* Reset index */
863 $i = 1 ;
864 $identifier = array();
865 $attribute= @ldap_first_attribute($this->cid,$entry,$identifier);
866 while ($attribute) {
867 $i++;
868 $atts[$i]['name'] = $attribute;
869 $atts[$i]['value'] = @ldap_get_values_len($this->cid, $entry, "$attribute");
871 /* Next one */
872 $attribute= @ldap_next_attribute($this->cid,$entry,$identifier);
873 }
875 foreach($atts as $at)
876 {
877 for ($i= 0; $i<$at['value']['count']; $i++){
879 /* Check if we must encode the data */
880 if(!preg_match('/^[a-z0-9+@#.=, \/ -]+$/i', $at['value'][$i])) {
881 $ret .= $at['name'].":: ".base64_encode($at['value'][$i])."\n";
882 } else {
883 $ret .= $at['name'].": ".$at['value'][$i]."\n";
884 }
885 }
886 }
888 return($ret);
889 }
892 function dn_exists($dn)
893 {
894 return @ldap_list($this->cid, $this->fix($dn), "(objectClass=*)", array("objectClass"));
895 }
899 function import_complete_ldif($str_attr,&$error,$overwrite,$cleanup)
900 {
901 if($this->reconnect) $this->connect();
903 /* First we have to splitt the string ito detect empty lines
904 An empty line indicates an new Entry */
905 $entries = split("\n",$str_attr);
907 $data = "";
908 $cnt = 0;
909 $current_line = 0;
911 /* Every single line ... */
912 foreach($entries as $entry) {
913 $current_line ++;
915 /* Removing Spaces to ..
916 .. test if a new entry begins */
917 $tmp = str_replace(" ","",$data );
919 /* .. prevent empty lines in an entry */
920 $tmp2 = str_replace(" ","",$entry);
922 /* If the Block ends (Empty Line) */
923 if((empty($entry))&&(!empty($tmp))) {
924 /* Add collected lines as a complete block */
925 $all[$cnt] = $data;
926 $cnt ++;
927 $data ="";
928 } else {
930 /* Append lines ... */
931 if(!empty($tmp2)) {
932 /* check if we need base64_decode for this line */
933 if(ereg("::",$tmp2))
934 {
935 $encoded = split("::",$entry);
936 $attr = $encoded[0];
937 $value = base64_decode($encoded[1]);
938 /* Add linenumber */
939 $data .= $current_line."#".base64_encode($attr.":".$value)."\n";
940 }
941 else
942 {
943 /* Add Linenumber */
944 $data .= $current_line."#".base64_encode($entry)."\n";
945 }
946 }
947 }
948 }
950 /* The Data we collected is not in the array all[];
951 For example the Data is stored like this..
953 all[0] = "1#dn : .... \n
954 2#ObjectType: person \n ...."
956 Now we check every insertblock and try to insert */
957 foreach ( $all as $single) {
958 $lineone = split("\n",$single);
959 $ndn = split("#", $lineone[0]);
960 $line = base64_decode($ndn[1]);
962 $dnn = split (":",$line);
963 $current_line = $ndn[0];
964 $dn = $dnn[0];
965 $value = $dnn[1];
967 /* Every block must begin with a dn */
968 if($dn != "dn") {
969 $error= sprintf(_("This is not a valid DN: '%s'. A block for import should begin with 'dn: ...' in line %s"), $line, $current_line);
970 return -2;
971 }
973 /* Should we use Modify instead of Add */
974 $usemodify= false;
976 /* Delete before insert */
977 $usermdir= false;
979 /* The dn address already exists! */
980 if (($this->dn_exists($value))&&((!$overwrite)&&(!$cleanup))) {
982 $error= sprintf(_("The dn: '%s' (from line %s) already exists in the LDAP database."), $line, $current_line);
983 return ALREADY_EXISTING_ENTRY;
985 } elseif(($this->dn_exists($value))&&($cleanup)){
987 /* Delete first, then add */
988 $usermdir = true;
990 } elseif(($this->dn_exists($value))&&($overwrite)) {
992 /* Modify instead of Add */
993 $usemodify = true;
994 }
996 /* If we can't Import, return with a file error */
997 if(!$this->import_single_entry($single,$usemodify,$usermdir) ) {
998 $error= sprintf(_("Error while importing dn: '%s', please check your LDIF from line %s on!"), $line,
999 $current_line);
1000 return UNKNOWN_TOKEN_IN_LDIF_FILE; }
1001 }
1003 return (INSERT_OK);
1004 }
1007 /* Imports a single entry */
1008 function import_single_entry($str_attr,$modify,$delete)
1009 {
1010 if($this->reconnect) $this->connect();
1014 $ret = false;
1015 $rows= split("\n",$str_attr);
1016 $data= false;
1018 foreach($rows as $row) {
1020 /* Check if we use Linenumbers (when import_complete_ldif is called we use
1021 Linenumbers) Linenumbers are use like this 123#attribute : value */
1022 if(!empty($row)) {
1023 if(strpos($row,"#")!=FALSE) {
1025 /* We are using line numbers
1026 Because there is a # before a : */
1027 $tmp1= split("#",$row);
1028 $current_line= $tmp1[0];
1029 $row= base64_decode($tmp1[1]);
1030 }
1032 /* Split the line into attribute and value */
1033 $attr = split(":", $row);
1034 $attr[0]= trim($attr[0]); /* attribute */
1035 $attr[1]= trim($attr[1]); /* value */
1037 /* Check for attributes that are used more than once */
1038 if(!isset($data[$attr[0]])) {
1039 $data[$attr[0]]=$attr[1];
1040 } else {
1041 $tmp = $data[$attr[0]];
1043 if(!is_array($tmp)) {
1044 $new[0]=$tmp;
1045 $new[1]=$attr[1];
1046 $datas[$attr[0]]['count']=1;
1047 $data[$attr[0]]=$new;
1048 } else {
1049 $cnt = $datas[$attr[0]]['count'];
1050 $cnt ++;
1051 $data[$attr[0]][$cnt]=$attr[1];
1052 $datas[$attr[0]]['count'] = $cnt;
1053 }
1054 }
1055 }
1056 }
1057 /* If dn is an index of data, we should try to insert the data */
1058 if(isset($data['dn'])) {
1059 /* Creating Entry */
1060 $this->cd($data['dn']);
1062 /* Delete existing entry */
1063 if($delete){
1064 $this->rmdir_recursive($data['dn']);
1065 }
1067 /* Create missing trees */
1068 $this->create_missing_trees($data['dn']);
1069 unset($data['dn']);
1071 /* If entry exists use modify */
1072 if(!$modify){
1073 $ret = $this->add($data);
1074 } else {
1075 $ret = $this->modify($data);
1076 }
1077 }
1078 show_ldap_error($this->get_error(),_("Ldap import failed"));
1079 return($ret);
1080 }
1083 function importcsv($str)
1084 {
1085 $lines = split("\n",$str);
1086 foreach($lines as $line)
1087 {
1088 /* continue if theres a comment */
1089 if(substr(trim($line),0,1)=="#"){
1090 continue;
1091 }
1093 $line= str_replace ("\t\t","\t",$line);
1094 $line= str_replace ("\t" ,"," ,$line);
1095 echo $line;
1097 $cells = split(",",$line ) ;
1098 $linet= str_replace ("\t\t",",",$line);
1099 $cells = split("\t",$line);
1100 $count = count($cells);
1101 }
1103 }
1105 function get_objectclasses()
1106 {
1107 $objectclasses = array();
1109 # Get base to look for schema
1110 $sr = @ldap_read ($this->cid, NULL, "objectClass=*", array("subschemaSubentry"));
1111 $attr = @ldap_get_entries($this->cid,$sr);
1112 if (!isset($attr[0]['subschemasubentry'][0])){
1113 return array();
1114 }
1116 # Get list of objectclasses
1117 $nb= $attr[0]['subschemasubentry'][0];
1118 $objectclasses= array();
1119 $sr= ldap_read ($this->cid, $nb, "objectClass=*", array("objectclasses"));
1120 $attrs= ldap_get_entries($this->cid,$sr);
1121 if (!isset($attrs[0])){
1122 return array();
1123 }
1124 foreach ($attrs[0]['objectclasses'] as $val){
1125 $name= preg_replace("/^.* NAME\s+\(*\s*'([^']+)'\s*\)*.*$/", '\\1', $val);
1126 if ($name != $val){
1127 $objectclasses[$name]= $val;
1128 }
1129 }
1131 return $objectclasses;
1132 }
1134 }
1136 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1137 ?>