Code

Fixed undefined index
[gosa.git] / include / class_ldap.inc
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.
58      
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();
185    
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;
191    
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);
216   
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);
326         
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();
416         
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       }
430       
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);
446     
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);
454         
455         echo "&nbsp;<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();
467     
468     if($this->hascon){
469       if ($this->reconnect) $this->connect();
471       /* Save base dn */
472       $basedn= $this->basedn;
473       $delarray= array();
474      
475       /* Check if destination entry already exists */
476       $this->cat($destinationdn);
478       if($this->count()){
479         return;
480       }else{
481         
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         }
494   
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             }
516             
517             unset($attr['count']);
518             unset($attr['dn']);
520             /* Add marking attribute */
521             $attr['objectClass'][] = "FAIbranch";
522             
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'>&nbsp;</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)){
671       
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);
751   
752   
753   }
754  
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->ls($filter,$dn, array('dn','objectClass'));
807       $deps = array();
808       while ($attrs= $this->fetch()){
809         $display.= $this->gen_one_entry($attrs['dn'], $filter, $attributes);
810         $display.= "\n";
812         if(in_array("organizationalUnit",$attrs['objectClass'])){
813           $deps[] = $attrs['dn'];
814         }
815       }
816       foreach($deps as $dn){
817         $display .= $this->gen_ldif($dn, $filter,$attributes,$recursive);
818       }
819     } else {
820       $display.= $this->gen_one_entry($dn);
821     }
822     return ($display);
823   }
826   function gen_xls ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE,$r_array=0)
827   {
828     $display= "";
830       $this->cd($dn);
831       $this->search("$filter");
833       $i=0;
834       while ($attrs= $this->fetch()){
835         $j=0;
837         foreach ($attributes as $at){
838           $display[$i][$j]= $this->get_attribute($attrs['dn'], $at,$r_array);
839           $j++;
840         }
842         $i++;
843       }
845     return ($display);
846   }
849   function gen_one_entry($dn, $filter= "(objectClass=*)" , $name= array("*"))
850   {
851     $ret = "";
852     $data = "";
853     if($this->reconnect){
854       $this->connect();
855     }
857     /* Searching Ldap Tree */
858     $sr= @ldap_read($this->cid, $this->fix($dn), $filter, $name);
860     /* Get the first entry */   
861     $entry= @ldap_first_entry($this->cid, $sr);
863     /* Get all attributes related to that Objekt */
864     $atts = array();
865     
866     /* Assemble dn */
867     $atts[0]['name']  = "dn";
868     $atts[0]['value'] = array('count' => 1, 0 => $dn);
870     /* Reset index */
871     $i = 1 ; 
872   $identifier = array();
873     $attribute= @ldap_first_attribute($this->cid,$entry,$identifier);
874     while ($attribute) {
875       $i++;
876       $atts[$i]['name']  = $attribute;
877       $atts[$i]['value'] = @ldap_get_values_len($this->cid, $entry, "$attribute");
879       /* Next one */
880       $attribute= @ldap_next_attribute($this->cid,$entry,$identifier);
881     }
883     foreach($atts as $at)
884     {
885       for ($i= 0; $i<$at['value']['count']; $i++){
887         /* Check if we must encode the data */
888         if(!preg_match('/^[a-z0-9+@#.=, \/ -]+$/i', $at['value'][$i])) {
889           $ret .= $at['name'].":: ".base64_encode($at['value'][$i])."\n";
890         } else {
891           $ret .= $at['name'].": ".$at['value'][$i]."\n";
892         }
893       }
894     }
896     return($ret);
897   }
900   function dn_exists($dn)
901   {
902     return @ldap_list($this->cid, $this->fix($dn), "(objectClass=*)", array("objectClass"));
903   }
904   
907   function import_complete_ldif($str_attr,&$error,$overwrite,$cleanup)
908   {
909     if($this->reconnect) $this->connect();
911     /* First we have to splitt the string ito detect empty lines
912        An empty line indicates an new Entry */
913     $entries = split("\n",$str_attr);
915     $data = "";
916     $cnt = 0; 
917     $current_line = 0;
919     /* Every single line ... */
920     foreach($entries as $entry) {
921       $current_line ++;
923       /* Removing Spaces to .. 
924          .. test if a new entry begins */
925       $tmp  = str_replace(" ","",$data );
927       /* .. prevent empty lines in an entry */
928       $tmp2 = str_replace(" ","",$entry);
930       /* If the Block ends (Empty Line) */
931       if((empty($entry))&&(!empty($tmp))) {
932         /* Add collected lines as a complete block */
933         $all[$cnt] = $data;
934         $cnt ++;
935         $data ="";
936       } else {
938         /* Append lines ... */
939         if(!empty($tmp2)) {
940           /* check if we need base64_decode for this line */
941           if(ereg("::",$tmp2))
942           {
943             $encoded = split("::",$entry);
944             $attr  = $encoded[0];
945             $value = base64_decode($encoded[1]);
946             /* Add linenumber */
947             $data .= $current_line."#".base64_encode($attr.":".$value)."\n";
948           }
949           else
950           {
951             /* Add Linenumber */ 
952             $data .= $current_line."#".base64_encode($entry)."\n";
953           }
954         }
955       }
956     }
958     /* The Data we collected is not in the array all[];
959        For example the Data is stored like this..
961        all[0] = "1#dn : .... \n 
962        2#ObjectType: person \n ...."
963        
964        Now we check every insertblock and try to insert */
965     foreach ( $all as $single) {
966       $lineone = split("\n",$single);  
967       $ndn = split("#", $lineone[0]);
968       $line = base64_decode($ndn[1]);
970       $dnn = split (":",$line);
971       $current_line = $ndn[0];
972       $dn    = $dnn[0];
973       $value = $dnn[1];
975       /* Every block must begin with a dn */
976       if($dn != "dn") {
977         $error= sprintf(_("This is not a valid DN: '%s'. A block for import should begin with 'dn: ...' in line %s"), $line, $current_line);
978         return -2;  
979       }
981       /* Should we use Modify instead of Add */
982       $usemodify= false;
984       /* Delete before insert */
985       $usermdir= false;
986     
987       /* The dn address already exists! */
988       if (($this->dn_exists($value))&&((!$overwrite)&&(!$cleanup))) {
990         $error= sprintf(_("The dn: '%s' (from line %s) already exists in the LDAP database."), $line, $current_line);
991         return ALREADY_EXISTING_ENTRY;   
993       } elseif(($this->dn_exists($value))&&($cleanup)){
995         /* Delete first, then add */
996         $usermdir = true;        
998       } elseif(($this->dn_exists($value))&&($overwrite)) {
999         
1000         /* Modify instead of Add */
1001         $usemodify = true;
1002       }
1003      
1004       /* If we can't Import, return with a file error */
1005       if(!$this->import_single_entry($single,$usemodify,$usermdir) ) {
1006         $error= sprintf(_("Error while importing dn: '%s', please check your LDIF from line %s on!"), $line,
1007                         $current_line);
1008         return UNKNOWN_TOKEN_IN_LDIF_FILE;      }
1009     }
1011     return (INSERT_OK);
1012   }
1015   /* Imports a single entry */
1016   function import_single_entry($str_attr,$modify,$delete)
1017   {
1018     if($this->reconnect) $this->connect();
1020     
1022     $ret = false;
1023     $rows= split("\n",$str_attr);
1024     $data= false;
1026     foreach($rows as $row) {
1027       
1028       /* Check if we use Linenumbers (when import_complete_ldif is called we use
1029          Linenumbers) Linenumbers are use like this 123#attribute : value */
1030       if(!empty($row)) {
1031         if(strpos($row,"#")!=FALSE) {
1033           /* We are using line numbers 
1034              Because there is a # before a : */
1035           $tmp1= split("#",$row);
1036           $current_line= $tmp1[0];
1037           $row= base64_decode($tmp1[1]);
1038         }
1040         /* Split the line into  attribute  and value */
1041         $attr   = split(":", $row);
1042         $attr[0]= trim($attr[0]);  /* attribute */
1043         $attr[1]= trim($attr[1]);  /* value */
1045         /* Check for attributes that are used more than once */
1046         if(!isset($data[$attr[0]])) {
1047           $data[$attr[0]]=$attr[1];
1048         } else {
1049           $tmp = $data[$attr[0]];
1051           if(!is_array($tmp)) {
1052             $new[0]=$tmp;
1053             $new[1]=$attr[1];
1054             $datas[$attr[0]]['count']=1;             
1055             $data[$attr[0]]=$new;
1056           } else {
1057             $cnt = $datas[$attr[0]]['count'];           
1058             $cnt ++;
1059             $data[$attr[0]][$cnt]=$attr[1];
1060             $datas[$attr[0]]['count'] = $cnt;
1061           }
1062         }
1063       }
1064     } 
1065     /* If dn is an index of data, we should try to insert the data */
1066     if(isset($data['dn'])) {
1067       /* Creating Entry */
1068       $this->cd($data['dn']);
1070       /* Delete existing entry */
1071       if($delete){
1072         $this->rmdir_recursive($data['dn']);
1073       }
1074       
1075       /* Create missing trees */
1076       $this->create_missing_trees($data['dn']);
1077       unset($data['dn']);
1078       
1079       /* If entry exists use modify */
1080       if(!$modify){
1081         $ret = $this->add($data);
1082       } else {
1083         $ret = $this->modify($data);
1084       }
1085     }
1086     show_ldap_error($this->get_error(),_("Ldap import failed"));
1087     return($ret);
1088   }
1090   
1091   function importcsv($str)
1092   {
1093     $lines = split("\n",$str);
1094     foreach($lines as $line)
1095     {
1096       /* continue if theres a comment */
1097       if(substr(trim($line),0,1)=="#"){
1098         continue;
1099       }
1101       $line= str_replace ("\t\t","\t",$line);
1102       $line= str_replace ("\t"  ,"," ,$line);
1103       echo $line;
1105       $cells = split(",",$line )  ;
1106       $linet= str_replace ("\t\t",",",$line);
1107       $cells = split("\t",$line);
1108       $count = count($cells);  
1109     }
1111   }
1112   
1113   function get_objectclasses()
1114   {
1115           $objectclasses = array();
1116         
1117           # Get base to look for schema 
1118           $sr = @ldap_read ($this->cid, NULL, "objectClass=*", array("subschemaSubentry"));
1119           $attr = @ldap_get_entries($this->cid,$sr);
1120           if (!isset($attr[0]['subschemasubentry'][0])){
1121             return array();
1122           }
1123         
1124           # Get list of objectclasses
1125           $nb= $attr[0]['subschemasubentry'][0];
1126           $objectclasses= array();
1127           $sr= ldap_read ($this->cid, $nb, "objectClass=*", array("objectclasses"));
1128           $attrs= ldap_get_entries($this->cid,$sr);
1129           if (!isset($attrs[0])){
1130             return array();
1131           }
1132           foreach ($attrs[0]['objectclasses'] as $val){
1133             $name= preg_replace("/^.* NAME\s+\(*\s*'([^']+)'\s*\)*.*$/", '\\1', $val);
1134             if ($name != $val){
1135               $objectclasses[$name]= $val;
1136             }
1137           }
1138           
1139           return $objectclasses;
1140   }
1144 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1145 ?>