Code

Only add FAIobject as objectClass if it is missing
[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       $this->log("LDAP operation: time=".get_MicroTimeDiff($start,microtime())." operation=search('".$this->fix($this->basedn)."', '$filter')");
202       return($this->sr);
203     }else{
204       $this->error = "Could not connect to LDAP server";
205       return("");
206     }
207   }
209   function ls($filter = "(objectclass=*)", $basedn = "",$attrs = array("*"))
210   {
211     if($this->hascon){
212       if ($this->reconnect) $this->connect();
213       $this->clearResult();
214       if ($basedn == "")
215         $basedn = $this->basedn;
216       else
217         $basedn= $this->convert($basedn);
218   
219       $start = microtime();
221       $this->sr = @ldap_list($this->cid, $this->fix($basedn), $filter,$attrs);
222       $this->error = @ldap_error($this->cid);
223       $this->resetResult();
224       $this->hasres=true;
226        /* Check if query took longer as specified in max_ldap_query_time */
227       if($this->max_ldap_query_time){
228         $diff = get_MicroTimeDiff($start,microtime());
229         if($diff > $this->max_ldap_query_time){
230           print_red(sprintf(_("The ldapserver is answering very slow (%.2f), this may be responsible for performance breakdowns."),$diff)) ;
231         }
232       }
234       $this->log("LDAP operation: time=".get_MicroTimeDiff($start,microtime())." operation=ls('".$this->fix($basedn)."', '$filter')");
236       return($this->sr);
237     }else{
238       $this->error = "Could not connect to LDAP server";
239       return("");
240     }
241   }
243   function cat($dn,$attrs= array("*"))
244   {
245     if($this->hascon){
246       if ($this->reconnect) $this->connect();
247       $start = microtime();
248       $this->clearResult();
249       $filter = "(objectclass=*)";
250       $this->sr = @ldap_read($this->cid, $this->fix($dn), $filter,$attrs);
251       $this->error = @ldap_error($this->cid);
252       $this->resetResult();
253       $this->hasres=true;
254       $this->log("LDAP operation: time=".get_MicroTimeDiff($start,microtime())." operation=cat('".$this->fix($dn)."')");
255       return($this->sr);
256     }else{
257       $this->error = "Could not connect to LDAP server";
258       return("");
259     }
260   }
262   function set_size_limit($size)
263   {
264     /* Ignore zero settings */
265     if ($size == 0){
266       @ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, 10000000);
267     }
268     if($this->hascon){
269       @ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, $size);
270     } else {
271       $this->error = "Could not connect to LDAP server";
272     }
273   }
275   function fetch()
276   {
277     $att= array();
278     if($this->hascon){
279       if($this->hasres){
280         if ($this->start == 0)
281         {
282           $this->start = 1;
283           $this->re= @ldap_first_entry($this->cid, $this->sr);
284         } else {
285           $this->re= @ldap_next_entry($this->cid, $this->re);
286         }
287         if ($this->re)
288         {
289           $att= @ldap_get_attributes($this->cid, $this->re);
290           $att['dn']= trim($this->convert(@ldap_get_dn($this->cid, $this->re)));
291         }
292         $this->error = @ldap_error($this->cid);
293         if (!isset($att)){
294           $att= array();
295         }
296         return($att);
297       }else{
298         $this->error = "Perform a Fetch with no Search";
299         return("");
300       }
301     }else{
302       $this->error = "Could not connect to LDAP server";
303       return("");
304     }
305   }
307   function resetResult()
308   {
309     $this->start = 0;
310   }
312   function clearResult()
313   {
314     if($this->hasres){
315       $this->hasres = false;
316       @ldap_free_result($this->sr);
317     }
318   }
320   function getDN()
321   {
322     if($this->hascon){
323       if($this->hasres){
325         if(!$this->re)
326           {
327           $this->error = "Perform a Fetch with no valid Result";
328           }
329           else
330           {
331           $rv = @ldap_get_dn($this->cid, $this->re);
332         
333           $this->error = @ldap_error($this->cid);
334           return(trim($this->convert($rv)));
335            }
336       }else{
337         $this->error = "Perform a Fetch with no Search";
338         return("");
339       }
340     }else{
341       $this->error = "Could not connect to LDAP server";
342       return("");
343     }
344   }
346   function count()
347   {
348     if($this->hascon){
349       if($this->hasres){
350         $rv = @ldap_count_entries($this->cid, $this->sr);
351         $this->error = @ldap_error($this->cid);
352         return($rv);
353       }else{
354         $this->error = "Perform a Fetch with no Search";
355         return("");
356       }
357     }else{
358       $this->error = "Could not connect to LDAP server";
359       return("");
360     }
361   }
363   function rm($attrs = "", $dn = "")
364   {
365     if($this->hascon){
366       if ($this->reconnect) $this->connect();
367       if ($dn == "")
368         $dn = $this->basedn;
370       $r = @ldap_mod_del($this->cid, $this->fix($dn), $attrs);
371       $this->error = @ldap_error($this->cid);
372       return($r);
373     }else{
374       $this->error = "Could not connect to LDAP server";
375       return("");
376     }
377   }
379   function rename($attrs, $dn = "")
380   {
381     if($this->hascon){
382       if ($this->reconnect) $this->connect();
383       if ($dn == "")
384         $dn = $this->basedn;
386       $r = @ldap_mod_replace($this->cid, $this->fix($dn), $attrs);
387       $this->error = @ldap_error($this->cid);
388       return($r);
389     }else{
390       $this->error = "Could not connect to LDAP server";
391       return("");
392     }
393   }
395   function rmdir($deletedn)
396   {
397     if($this->hascon){
398       if ($this->reconnect) $this->connect();
399       $start= microtime();
400       $r = @ldap_delete($this->cid, $this->fix($deletedn));
401       $this->error = @ldap_error($this->cid);
402       $this->log("LDAP operation: time=".get_MicroTimeDiff($start,microtime())." operation=delete('".$this->fix($deletedn)."')");
403       return($r ? $r : 0);
404     }else{
405       $this->error = "Could not connect to LDAP server";
406       return("");
407     }
408   }
410   /**
411   *  Function rmdir_recursive
412   *
413   *  Description: Based in recursive_remove, adding two thing: full subtree remove, and delete own node.
414   *  Parameters:  The dn to delete
415   *  GiveBack:    True on sucessfull , 0 in error, and "" when we don't get a ldap conection
416   *
417   */
419   function rmdir_recursive($deletedn)
420   {
421     if($this->hascon){
422       if ($this->reconnect) $this->connect();
423       $delarray= array();
424         
425       /* Get sorted list of dn's to delete */
426       $this->ls ("(objectClass=*)",$deletedn);
427       while ($this->fetch()){
428         $deldn= $this->getDN();
429         $delarray[$deldn]= strlen($deldn);
430       }
431       arsort ($delarray);
432       reset ($delarray);
434       /* Really Delete ALL dn's in subtree */
435       foreach ($delarray as $key => $value){
436         $this->rmdir_recursive($key);
437       }
438       
439       /* Finally Delete own Node */
440       $r = @ldap_delete($this->cid, $this->fix($deletedn));
441       $this->error = @ldap_error($this->cid);
442       return($r ? $r : 0);
443     }else{
444       $this->error = "Could not connect to LDAP server";
445       return("");
446     }
447   }
449   /* Copy given attributes and sub-dns with attributes to destination dn 
450   */
451   function copy_FAI_resource_recursive($sourcedn,$destinationdn,$destinationName,$type="branch",$is_first = true,$depth=0)
452   {
453     error_reporting(E_ALL);
454     
455     if($is_first){
456       echo "<h2>".sprintf(_("Creating copy of %s"),"<i>".@LDAP::fix($sourcedn)."</i>")."</h2>";
457     }else{
458       if(preg_match("/^ou=/",$sourcedn)){
459         echo "<h3>"._("Processing")." <i>".@LDAP::fix($destinationdn)."</i></h3>";
460       }else{
461         $tmp = split(",",$sourcedn);
462         
463         echo "&nbsp;<b>"._("Object").":</b> ";
465         $deststr = @LDAP::fix($destinationdn);
466         if(strlen($deststr) > 96){
467           $deststr = substr($deststr,0,96)."...";
468         }
470         echo $deststr."<br>";
471       }
472     }
474     flush();
475     
476     if($this->hascon){
477       if ($this->reconnect) $this->connect();
479       /* Save base dn */
480       $basedn= $this->basedn;
481       $delarray= array();
482      
483       /* Check if destination entry already exists */
484       $this->cat($destinationdn);
486       if($this->count()){
487         return;
488       }else{
489         
490         $this->clearResult();
492         /* Get source entry */
493         $this->cd($basedn);
494         $this->cat($sourcedn);
495         $attr = $this->fetch();
497         /* Error while fetching object / attribute abort*/
498         if((!$attr) || (count($attr)) ==0) {
499           echo _("Error while fetching source dn - aborted!");
500           return;
501         }
502   
503         /* check if this is a department */
504         if(in_array("organizationalUnit",$attr['objectClass'])){
505           $attr['dn'] = $this->convert($destinationdn);
506           $this->cd($basedn);
507           $this->create_missing_trees($destinationdn);
508           $this->cd($destinationdn);
510           /* If is first entry, append FAIbranch to department entry */
511           if($is_first){
512             $this->cat($destinationdn);
513             $attr= $this->fetch();
515             /* Filter unneeded informations */
516             foreach($attr as $key => $value){
517               if(is_numeric($key)) unset($attr[$key]);
518               if(isset($attr[$key]['count'])){
519                 if(is_array($attr[$key])){
520                   unset($attr[$key]['count']);
521                 }
522               }
523             }
524             
525             unset($attr['count']);
526             unset($attr['dn']);
528             /* Add marking attribute */
529             $attr['objectClass'][] = "FAIbranch";
530             
531             /* Add this entry */
532             $this->modify($attr);
533           }
534         }else{
536           /* If this is no department */
537           foreach($attr as $key => $value){
538             if(in_array($key ,array("FAItemplateFile","FAIscript", "gotoLogonScript", "gosaApplicationIcon"))){
539               $sr= ldap_read($this->cid, $this->fix($sourcedn), "$key=*", array($key));
540               $ei= ldap_first_entry($this->cid, $sr);
541               if ($tmp= @ldap_get_values_len($this->cid, $ei,$key)){
542                 $attr[$key] = $tmp;
543               }
544             }
546             if(is_numeric($key)) unset($attr[$key]);
547             if(isset($attr[$key]['count'])){
548               if(is_array($attr[$key])){
549                 unset($attr[$key]['count']);
550               }
551             }
552           }
553           unset($attr['count']);
554           unset($attr['dn']);
556           if(!in_array("gosaApplication" , $attr['objectClass'])){
557             if($type=="branch"){
558               $attr['FAIstate'] ="branch";
559             }elseif($type=="freeze"){
560               $attr['FAIstate'] ="freeze";
561             }else{
562               print_red(_("Unknown FAIstate %s"),$type);
563             }
564           }elseif(in_array("gosaApplication",$attr['objectClass'])){
565             if(!in_array("FAIobject",$attr['objectClass'])){
566               $attr['objectClass'][] = "FAIobject";
567             }
568             $attr['FAIstate'] = $type;
569           }
571           /* Replace FAIdebianRelease with new release name */
572           if(in_array("FAIpackageList" , $attr['objectClass'])){
573             $attr['FAIdebianRelease'] = $destinationName;
574             if($type=="branch"){
575               $attr['FAIstate'] ="branch";
576             }elseif($type=="freeze"){
577               $attr['FAIstate'] ="freeze";
578             }else{
579               print_red(_("Unknown FAIstate %s"),$type);
580             }
581           }
583           /* Add entry */
584           $this->cd($destinationdn);
585           $this->cat($destinationdn);
586           $a = $this->fetch();
587           if(!count($a)){
588             $this->add($attr);
589           }
591           if($this->error != "Success"){
592             /* Some error occured */
593             print "---------------------------------------------";
594             print $this->get_error()."<br>";
595             print $sourcedn."<br>";
596             print $destinationdn."<br>";
597             print_a( $attr);
598             exit();
599           }          
600         }
601       }
603       echo "<script language=\"javascript\" type=\"text/javascript\">scrollDown2();</script>" ;
605       $this->ls ("(objectClass=*)",$sourcedn);
606       while ($this->fetch()){
607         $deldn= $this->getDN();
608         $delarray[$deldn]= strlen($deldn);
609       }
610       asort ($delarray);
611       reset ($delarray);
613        $depth ++;
614       foreach($delarray as $dn => $bla){
615         if($dn != $destinationdn){
616           $this->cd($basedn);
617           $item = $this->fetch($this->cat($dn));
618           if(!in_array("FAIbranch",$item['objectClass'])){
619             $this->copy_FAI_resource_recursive($dn,str_replace($sourcedn,$destinationdn,$dn),$destinationName,$type,false,$depth);
620           } 
621         }
622       }
623     }
624     if($is_first){
625       echo "<p class='seperator'>&nbsp;</p>";
626     }
628   }
630   function modify($attrs)
631   {
632     if(count($attrs) == 0){
633       return (0);
634     }
635     if($this->hascon){
636       if ($this->reconnect) $this->connect();
637       $start= microtime();
638       $r = @ldap_modify($this->cid, $this->fix($this->basedn), $attrs);
639       $this->error = @ldap_error($this->cid);
640       $this->log("LDAP operation: time=".get_MicroTimeDiff($start,microtime())." operation=modify('$this->basedn')");
641       return($r ? $r : 0);
642     }else{
643       $this->error = "Could not connect to LDAP server";
644       return("");
645     }
646   }
648   function add($attrs)
649   {
650     if($this->hascon){
651       if ($this->reconnect) $this->connect();
652       $start= microtime();
653       $r = @ldap_add($this->cid, $this->fix($this->basedn), $attrs);
654       $this->error = @ldap_error($this->cid);
655       $this->log("LDAP operation: time=".get_MicroTimeDiff($start,microtime())." operation=add('$this->basedn')");
656       return($r ? $r : 0);
657     }else{
658       $this->error = "Could not connect to LDAP server";
659       return("");
660     }
661   }
663   function create_missing_trees($target)
664   {
665     /* Ignore create_missing trees if the base equals target */
666     if ($target == $this->basedn){
667      return;
668     }
670     $real_path= substr($target, 0, strlen($target) - strlen($this->basedn) -1 );
671     $tmp = ldap_explode_dn($real_path,0);
672     if(!$tmp){
673       print_red(sprintf(_("The referral url '%s' is missing the ldap base. It should look like this 'ldap://server:port/base'."),$this->fix($this->basedn)));
674       return;
675     }
677     $l= array_reverse($tmp);
678     unset($l['count']);
679     $cdn= $this->basedn;
680     $tag= "";
682     foreach ($l as $part){
683       $cdn= "$part,$cdn";
685       /* Ignore referrals */
686       $found= false;
687       foreach($this->referrals as $ref){
688         $base= preg_replace('!^[^:]+://[^/]+/([^?]+).*$!', '\\1', $ref['URL']);
689         if ($base == $cdn){
690           $found= true;
691           break;
692         }
693       }
694       if ($found){
695         continue;
696       }
698       $this->cat ($cdn);
699       $attrs= $this->fetch();
701       /* Create missing entry? */
702       if (count ($attrs)){
703       
704         /* Catch the tag - if present */
705         if (isset($attrs['gosaUnitTag'][0])){
706           $tag= $attrs['gosaUnitTag'][0];
707         }
709       } else {
710         $type= preg_replace('/^([^=]+)=.*$/', '\\1', $cdn);
711         $param= preg_replace('/^[^=]+=([^,]+),.*$/', '\\1', $cdn);
713         $na= array();
714         switch ($type){
715           case 'ou':
716             if ($tag != ""){
717               $na["objectClass"]= array("organizationalUnit", "gosaAdministrativeUnitTag");
718               $na["gosaUnitTag"]= $tag;
719             } else {
720               $na["objectClass"]= "organizationalUnit";
721             }
722             $na["ou"]= $param;
723             break;
724           case 'dc':
725             if ($tag != ""){
726               $na["objectClass"]= array("dcObject", "top", "locality", "gosaAdministrativeUnitTag");
727               $na["gosaUnitTag"]= $tag;
728             } else {
729               $na["objectClass"]= array("dcObject", "top", "locality");
730             }
731             $na["dc"]= $param;
732             break;
733           default:
734             print_red(sprintf(_("Autocreation of type '%s' is currently not supported. Please report to the GOsa team."), $type));
735             echo $_SESSION['errors'];
736             exit;
737         }
738         $this->cd($cdn);
739         $this->add($na);
740       }
741     }
742   }
744   function recursive_remove()
745   {
746     $delarray= array();
748     /* Get sorted list of dn's to delete */
749     $this->search ("(objectClass=*)");
750     while ($this->fetch()){
751       $deldn= $this->getDN();
752       $delarray[$deldn]= strlen($deldn);
753     }
754     arsort ($delarray);
755     reset ($delarray);
757     /* Delete all dn's in subtree */
758     foreach ($delarray as $key => $value){
759       $this->rmdir($key);
760     }
761   }
763   function get_attribute($dn, $name,$r_array=0)
764   {
765     $data= "";
766     if ($this->reconnect) $this->connect();
767     $sr= @ldap_read($this->cid, $this->fix($dn), "objectClass=*", array("$name"));
769     /* fill data from LDAP */
770     if ($sr) {
771       $ei= @ldap_first_entry($this->cid, $sr);
772       if ($ei) {
773         if ($info= @ldap_get_values_len($this->cid, $ei, "$name")){
774           $data= $info[0];
775         }
777       }
778     }
779     if($r_array==0)
780     return ($data);
781     else
782     return ($info);
783   
784   
785   }
786  
789   function get_additional_error()
790   {
791     $error= "";
792     @ldap_get_option ($this->cid, LDAP_OPT_ERROR_STRING, $error);
793     return ($error);
794   }
796   function get_error()
797   {
798     if ($this->error == 'Success'){
799       return $this->error;
800     } else {
801       $adderror= $this->get_additional_error();
802       if ($adderror != ""){
803         $error= $this->error." (".$this->get_additional_error().", ".sprintf(_("while operating on '%s' using LDAP server '%s'"), $this->basedn, $this->hostname).")";
804       } else {
805         $error= $this->error." (".sprintf(_("while operating on LDAP server %s"), $this->hostname).")";
806       }
807       return $error;
808     }
809   }
811   function get_credentials($url, $referrals= NULL)
812   {
813     $ret= array();
814     $url= preg_replace('!\?\?.*$!', '', $url);
815     $server= preg_replace('!^([^:]+://[^/]+)/.*$!', '\\1', $url);
817     if ($referrals == NULL){
818       $referrals= $this->referrals;
819     }
821     if (isset($referrals[$server])){
822       return ($referrals[$server]);
823     } else {
824       $ret['ADMIN']= $this->fix($this->binddn);
825       $ret['PASSWORD']= $this->bindpw;
826     }
828     return ($ret);
829   }
832   function gen_ldif ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE)
833   {
834     $display= "";
836     if ($recursive){
837       $this->cd($dn);
838       $this->search("$filter", array('dn'));
839       while ($attrs= $this->fetch()){
840         $display.= $this->gen_one_entry($attrs['dn'], $filter, $attributes);
841         $display.= "\n";
842       }
843     } else {
844       $display.= $this->gen_one_entry($dn);
845     }
847     return ($display);
848   }
850 function gen_xls ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE,$r_array=0)
851   {
852     $display= "";
854       $this->cd($dn);
855       $this->search("$filter");
857       $i=0;
858       while ($attrs= $this->fetch()){
859         $j=0;
861         foreach ($attributes as $at){
862           $display[$i][$j]= $this->get_attribute($attrs['dn'], $at,$r_array);
863           $j++;
864         }
866         $i++;
867       }
869     return ($display);
870   }
873   function gen_one_entry($dn, $filter= "(objectClass=*)" , $name= array("*"))
874   {
875     $ret = "";
876     $data = "";
877     if($this->reconnect){
878       $this->connect();
879     }
881     /* Searching Ldap Tree */
882     $sr= @ldap_read($this->cid, $this->fix($dn), $filter, $name);
884     /* Get the first entry */   
885     $entry= @ldap_first_entry($this->cid, $sr);
887     /* Get all attributes related to that Objekt */
888     $atts = array();
889     
890     /* Assemble dn */
891     $atts[0]['name']  = "dn";
892     $atts[0]['value'] = array('count' => 1, 0 => $dn);
894     /* Reset index */
895     $i = 1 ; 
896   $identifier = array();
897     $attribute= @ldap_first_attribute($this->cid,$entry,$identifier);
898     while ($attribute) {
899       $i++;
900       $atts[$i]['name']  = $attribute;
901       $atts[$i]['value'] = @ldap_get_values_len($this->cid, $entry, "$attribute");
903       /* Next one */
904       $attribute= @ldap_next_attribute($this->cid,$entry,$identifier);
905     }
907     foreach($atts as $at)
908     {
909       for ($i= 0; $i<$at['value']['count']; $i++){
911         /* Check if we must encode the data */
912         if(!preg_match('/^[a-z0-9+@#.=, \/ -]+$/i', $at['value'][$i])) {
913           $ret .= $at['name'].":: ".base64_encode($at['value'][$i])."\n";
914         } else {
915           $ret .= $at['name'].": ".$at['value'][$i]."\n";
916         }
917       }
918     }
920     return($ret);
921   }
924   function dn_exists($dn)
925   {
926     return @ldap_list($this->cid, $this->fix($dn), "(objectClass=*)", array("objectClass"));
927   }
928   
931   function import_complete_ldif($str_attr,&$error,$overwrite,$cleanup)
932   {
933     if($this->reconnect) $this->connect();
935     /* First we have to splitt the string ito detect empty lines
936        An empty line indicates an new Entry */
937     $entries = split("\n",$str_attr);
939     $data = "";
940     $cnt = 0; 
941     $current_line = 0;
943     /* Every single line ... */
944     foreach($entries as $entry) {
945       $current_line ++;
947       /* Removing Spaces to .. 
948          .. test if a new entry begins */
949       $tmp  = str_replace(" ","",$data );
951       /* .. prevent empty lines in an entry */
952       $tmp2 = str_replace(" ","",$entry);
954       /* If the Block ends (Empty Line) */
955       if((empty($entry))&&(!empty($tmp))) {
956         /* Add collected lines as a complete block */
957         $all[$cnt] = $data;
958         $cnt ++;
959         $data ="";
960       } else {
962         /* Append lines ... */
963         if(!empty($tmp2)) {
964           /* check if we need base64_decode for this line */
965           if(ereg("::",$tmp2))
966           {
967             $encoded = split("::",$entry);
968             $attr  = $encoded[0];
969             $value = base64_decode($encoded[1]);
970             /* Add linenumber */
971             $data .= $current_line."#".$attr.":".$value."\n";
972           }
973           else
974           {
975             /* Add Linenumber */ 
976             $data .= $current_line."#".$entry."\n";
977           }
978         }
979       }
980     }
982     /* The Data we collected is not in the array all[];
983        For example the Data is stored like this..
985        all[0] = "1#dn : .... \n 
986        2#ObjectType: person \n ...."
987        
988        Now we check every insertblock and try to insert */
989     foreach ( $all as $single) {
990       $lineone = split("\n",$single);  
991       $ndn = split("#", $lineone[0]);
992       $line = $ndn[1];
994       $dnn = split (":",$line);
995       $current_line = $ndn[0];
996       $dn    = $dnn[0];
997       $value = $dnn[1];
999       /* Every block must begin with a dn */
1000       if($dn != "dn") {
1001         $error= sprintf(_("This is not a valid DN: '%s'. A block for import should begin with 'dn: ...' in line %s"), $line, $current_line);
1002         return -2;  
1003       }
1005       /* Should we use Modify instead of Add */
1006       $usemodify= false;
1008       /* Delete before insert */
1009       $usermdir= false;
1010     
1011       /* The dn address already exists! */
1012       if (($this->dn_exists($value))&&((!$overwrite)&&(!$cleanup))) {
1014         $error= sprintf(_("The dn: '%s' (from line %s) already exists in the LDAP database."), $line, $current_line);
1015         return ALREADY_EXISTING_ENTRY;   
1017       } elseif(($this->dn_exists($value))&&($cleanup)){
1019         /* Delete first, then add */
1020         $usermdir = true;        
1022       } elseif(($this->dn_exists($value))&&($overwrite)) {
1023         
1024         /* Modify instead of Add */
1025         $usemodify = true;
1026       }
1027      
1028       /* If we can't Import, return with a file error */
1029       if(!$this->import_single_entry($single,$usemodify,$usermdir) ) {
1030         $error= sprintf(_("Error while importing dn: '%s', please check your LDIF from line %s on!"), $line,
1031                         $current_line);
1032         return UNKNOWN_TOKEN_IN_LDIF_FILE;      }
1033     }
1035     return (INSERT_OK);
1036   }
1039   /* Imports a single entry */
1040   function import_single_entry($str_attr,$modify,$delete)
1041   {
1042     if($this->reconnect) $this->connect();
1044     $ret = false;
1045     $rows= split("\n",$str_attr);
1046     $data= false;
1048     foreach($rows as $row) {
1049       
1050       /* Check if we use Linenumbers (when import_complete_ldif is called we use
1051          Linenumbers) Linenumbers are use like this 123#attribute : value */
1052       if(!empty($row)) {
1053         if((strpos($row,"#")!=FALSE)&&(strpos($row,"#")<strpos($row,":"))) {
1055           /* We are using line numbers 
1056              Because there is a # before a : */
1057           $tmp1= split("#",$row);
1058           $current_line= $tmp1[0];
1059           $row= $tmp1[1];
1060         }
1062         /* Split the line into  attribute  and value */
1063         $attr   = split(":", $row);
1064         $attr[0]= trim($attr[0]);  /* attribute */
1065         $attr[1]= trim($attr[1]);  /* value */
1067         /* Check for attributes that are used more than once */
1068         if(!isset($data[$attr[0]])) {
1069           $data[$attr[0]]=$attr[1];
1070         } else {
1071           $tmp = $data[$attr[0]];
1073           if(!is_array($tmp)) {
1074             $new[0]=$tmp;
1075             $new[1]=$attr[1];
1076             $datas[$attr[0]]['count']=1;             
1077             $data[$attr[0]]=$new;
1078           } else {
1079             $cnt = $datas[$attr[0]]['count'];           
1080             $cnt ++;
1081             $data[$attr[0]][$cnt]=$attr[1];
1082             $datas[$attr[0]]['count'] = $cnt;
1083           }
1084         }
1085       }
1086     } 
1087     
1088     /* If dn is an index of data, we should try to insert the data */
1089     if(isset($data['dn'])) {
1090       /* Creating Entry */
1091       $this->cd($data['dn']);
1093       /* Delete existing entry */
1094       if($delete){
1095         $this->rmdir($data['dn']);
1096       }
1097       
1098       /* Create missing trees */
1099       $this->create_missing_trees($data['dn']);
1100       unset($data['dn']);
1101       
1102       /* If entry exists use modify */
1103       if(!$modify){
1104         $ret = $this->add($data);
1105       } else {
1106         $ret = $this->modify($data);
1107       }
1108     }
1110     return($ret);
1111   }
1113   
1114   function importcsv($str)
1115   {
1116     $lines = split("\n",$str);
1117     foreach($lines as $line)
1118     {
1119       /* continue if theres a comment */
1120       if(substr(trim($line),0,1)=="#"){
1121         continue;
1122       }
1124       $line= str_replace ("\t\t","\t",$line);
1125       $line= str_replace ("\t"  ,"," ,$line);
1126       echo $line;
1128       $cells = split(",",$line )  ;
1129       $linet= str_replace ("\t\t",",",$line);
1130       $cells = split("\t",$line);
1131       $count = count($cells);  
1132     }
1134   }
1135   
1136   function get_objectclasses()
1137   {
1138           $objectclasses = array();
1139         
1140           # Get base to look for schema 
1141           $sr           = @ldap_read ($this->cid, NULL, "objectClass=*", array("subschemaSubentry"));
1142           $attr         = @ldap_get_entries($this->cid,$sr);
1144           if (!isset($attr[0]['subschemasubentry'][0])){
1145       $this->error  = @ldap_error($this->cid);
1146       gosa_log($this->get_error());
1147       return array();
1148           }
1149         
1150           # Get list of objectclasses
1151           $nb= $attr[0]['subschemasubentry'][0];
1152           $objectclasses= array();
1153           $sr= ldap_read ($this->cid, $nb, "objectClass=*", array("objectclasses"));
1154           $attrs= ldap_get_entries($this->cid,$sr);
1155           if (!isset($attrs[0])){
1156             return array();
1157           }
1158           foreach ($attrs[0]['objectclasses'] as $val){
1159             $name= preg_replace("/^.* NAME\s+\(*\s*'([^']+)'\s*\)*.*$/", '\\1', $val);
1160             if ($name != $val){
1161               $objectclasses[$name]= $val;
1162             }
1163           }
1164           
1165           return $objectclasses;
1166   }
1169   function log($string)
1170   {
1171     if (isset($_SESSION['config'])){
1172       $cfg= $_SESSION['config'];
1173       if (isset($cfg->current['LDAPSTATS']) && preg_match('/true/i', $cfg->current['LDAPSTATS'])){
1174         syslog (LOG_INFO, $string);
1175       }
1176     }
1177   }
1178   
1179   /* added by Guido Serra aka Zeph <zeph@purotesto.it> */
1180   function getCn($dn){
1181     $simple= split(",", $dn);
1183     foreach($simple as $piece) {
1184       $partial= split("=", $piece);
1186       if($partial[0] == "cn"){
1187         return $partial[1];
1188       }
1189     }
1191   }
1196 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1197 ?>