Code

Sorry for the huge commit:
[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();
35   function LDAP($binddn,$bindpw, $hostname, $follow_referral= FALSE, $tls= FALSE)
36   {
37     $this->follow_referral= $follow_referral;
38     $this->tls=$tls;
39     $this->binddn=$this->convert($binddn);
41     $this->bindpw=$bindpw;
42     $this->hostname=$hostname;
43     $this->connect();
44   }
47   /* Function to replace all problematic characters inside a DN by \001XX, where
48      \001 is decoded to chr(1) [ctrl+a]. It is not impossible, but very unlikely
49      that this character is inside a DN.
50      
51      Currently used codes:
52       ,   => CO
53       \2C => CO
54       (   => OB
55       )   => CB
56       /   => SL                                                                  */
57   function convert($dn)
58   {
59     if (SPECIALS_OVERRIDE == TRUE){
60       return (preg_replace(array("/\\\\,/", "/\\\\2C/", "/\(/", "/\)/", "/\//"),
61                            array("\001CO", "\001CO", "\001OB", "\001CB", "\001SL"),
62                            $dn));
63     } else {
64       return ($dn);
65     }
66   }
69   /* Function to fix all problematic characters inside a DN by replacing \001XX
70      codes to their original values. See "convert" for mor information. 
71      ',' characters are always expanded to \, (not \2C), since all tested LDAP
72      servers seem to take it the correct way.                                  */
73   function fix($dn)
74   {
75     if (SPECIALS_OVERRIDE == TRUE){
76       return (preg_replace(array("/\001CO/", "/\001OB/", "/\001CB/", "/\001SL/"),
77                            array("\,", "(", ")", "/"),
78                            $dn));
79     } else {
80       return ($dn);
81     }
82   }
85   function connect()
86   {
87     $this->hascon=false;
88     $this->reconnect=false;
89     if ($this->cid= @ldap_connect($this->hostname)) {
90       @ldap_set_option($this->cid, LDAP_OPT_PROTOCOL_VERSION, 3);
91       if (function_exists("ldap_set_rebind_proc") && $this->follow_referral) {
92         @ldap_set_option($this->cid, LDAP_OPT_REFERRALS, 1);
93         @ldap_set_rebind_proc($this->cid, array(&$this, "rebind"));
94       }
95       if (function_exists("ldap_start_tls") && $this->tls){
96         @ldap_start_tls($this->cid);
97       }
99       $this->error = "No Error";
100       if ($bid = @ldap_bind($this->cid, $this->fix($this->binddn), $this->bindpw)) {
101         $this->error = "Success";
102         $this->hascon=true;
103       } else {
104         if ($this->reconnect){
105           if ($this->error != "Success"){
106             $this->error = "Could not rebind to " . $this->binddn;
107           }
108         } else {
109           $this->error = "Could not bind to " . $this->binddn;
110         }
111       }
112     } else {
113       $this->error = "Could not connect to LDAP server";
114     }
115   }
117   function rebind($ldap, $referral)
118   {
119     $credentials= $this->get_credentials($referral);
120     if (@ldap_bind($ldap, $this->fix($credentials['ADMIN']), $credentials['PASSWORD'])) {
121       $this->error = "Success";
122       $this->hascon=true;
123       $this->reconnect= true;
124       return (0);
125     } else {
126       $this->error = "Could not bind to " . $credentials['ADMIN'];
127       return NULL;
128     }
129   }
131   function reconnect()
132   {
133     if ($this->reconnect){
134       @ldap_unbind($this->cid);
135       $this->cid = NULL;
136     }
137   }
139   function unbind()
140   {
141     @ldap_unbind($this->cid);
142     $this->cid = NULL;
143   }
145   function disconnect()
146   {
147     if($this->hascon){
148       @ldap_close($this->cid);
149       $this->hascon=false;
150     }
151   }
153   function cd($dir)
154   {
155     if ($dir == "..")
156       $this->basedn = $this->getParentDir();
157     else
158       $this->basedn = $this->convert($dir);
159   }
161   function getParentDir($basedn = "")
162   {
163     if ($basedn=="")
164       $basedn = $this->basedn;
165     else
166       $basedn = $this->convert($this->basedn);
167     return(ereg_replace("[^,]*[,]*[ ]*(.*)", "\\1", $basedn));
168   }
170   function search($filter, $attrs= array())
171   {
172     if($this->hascon){
173       if ($this->reconnect) $this->connect();
174       $this->clearResult();
175       $this->sr = @ldap_search($this->cid, $this->fix($this->basedn), $filter, $attrs);
176       $this->error = @ldap_error($this->cid);
177       $this->resetResult();
178       $this->hasres=true;
179   
180       return($this->sr);
181     }else{
182       $this->error = "Could not connect to LDAP server";
183       return("");
184     }
185   }
187   function ls($filter = "(objectclass=*)", $basedn = "",$attrs = array("*"))
188   {
189     if($this->hascon){
190       if ($this->reconnect) $this->connect();
191       $this->clearResult();
192       if ($basedn == "")
193         $basedn = $this->basedn;
194       else
195         $basedn= $this->convert($basedn);
196       $this->sr = @ldap_list($this->cid, $this->fix($basedn), $filter,$attrs);
197       $this->error = @ldap_error($this->cid);
198       $this->resetResult();
199       $this->hasres=true;
200       return($this->sr);
201     }else{
202       $this->error = "Could not connect to LDAP server";
203       return("");
204     }
205   }
207   function cat($dn,$attrs= array("*"))
208   {
209     if($this->hascon){
210       if ($this->reconnect) $this->connect();
211       $this->clearResult();
212       $filter = "(objectclass=*)";
213       $this->sr = @ldap_read($this->cid, $this->fix($dn), $filter,$attrs);
214       $this->error = @ldap_error($this->cid);
215       $this->resetResult();
216       $this->hasres=true;
217       return($this->sr);
218     }else{
219       $this->error = "Could not connect to LDAP server";
220       return("");
221     }
222   }
224   function set_size_limit($size)
225   {
226     /* Ignore zero settings */
227     if ($size == 0){
228       @ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, 10000000);
229     }
230     if($this->hascon){
231       @ldap_set_option($this->cid, LDAP_OPT_SIZELIMIT, $size);
232     } else {
233       $this->error = "Could not connect to LDAP server";
234     }
235   }
237   function fetch()
238   {
239     if($this->hascon){
240       if($this->hasres){
241         if ($this->start == 0)
242         {
243           $this->start = 1;
244           $this->re= @ldap_first_entry($this->cid, $this->sr);
245         } else {
246           $this->re= @ldap_next_entry($this->cid, $this->re);
247         }
248         if ($this->re)
249         {
250           $att= @ldap_get_attributes($this->cid, $this->re);
251           $att['dn']= $this->convert(@ldap_get_dn($this->cid, $this->re));
252         }
253         $this->error = @ldap_error($this->cid);
254         if (!isset($att)){
255           $att= array();
256         }
257         return($att);
258       }else{
259         $this->error = "Perform a Fetch with no Search";
260         return("");
261       }
262     }else{
263       $this->error = "Could not connect to LDAP server";
264       return("");
265     }
266   }
268   function resetResult()
269   {
270     $this->start = 0;
271   }
273   function clearResult()
274   {
275     if($this->hasres){
276       $this->hasres = false;
277       @ldap_free_result($this->sr);
278     }
279   }
281   function getDN()
282   {
283     if($this->hascon){
284       if($this->hasres){
286         if(!$this->re)
287           {
288           $this->error = "Perform a Fetch with no valid Result";
289           }
290           else
291           {
292           $rv = @ldap_get_dn($this->cid, $this->re);
293         
294           $this->error = @ldap_error($this->cid);
295           return($this->convert($rv));
296            }
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 count()
308   {
309     if($this->hascon){
310       if($this->hasres){
311         $rv = @ldap_count_entries($this->cid, $this->sr);
312         $this->error = @ldap_error($this->cid);
313         return($rv);
314       }else{
315         $this->error = "Perform a Fetch with no Search";
316         return("");
317       }
318     }else{
319       $this->error = "Could not connect to LDAP server";
320       return("");
321     }
322   }
324   function rm($attrs = "", $dn = "")
325   {
326     if($this->hascon){
327       if ($this->reconnect) $this->connect();
328       if ($dn == "")
329         $dn = $this->basedn;
331       $r = @ldap_mod_del($this->cid, $this->fix($dn), $attrs);
332       $this->error = @ldap_error($this->cid);
333       return($r);
334     }else{
335       $this->error = "Could not connect to LDAP server";
336       return("");
337     }
338   }
340   function rename($attrs, $dn = "")
341   {
342     if($this->hascon){
343       if ($this->reconnect) $this->connect();
344       if ($dn == "")
345         $dn = $this->basedn;
347       $r = @ldap_mod_replace($this->cid, $this->fix($dn), $attrs);
348       $this->error = @ldap_error($this->cid);
349       return($r);
350     }else{
351       $this->error = "Could not connect to LDAP server";
352       return("");
353     }
354   }
356   function rmdir($deletedn)
357   {
358     if($this->hascon){
359       if ($this->reconnect) $this->connect();
360       $r = @ldap_delete($this->cid, $this->fix($deletedn));
361       $this->error = @ldap_error($this->cid);
362       return($r ? $r : 0);
363     }else{
364       $this->error = "Could not connect to LDAP server";
365       return("");
366     }
367   }
369   /**
370   *  Function rmdir_recursive
371   *
372   *  Description: Based in recursive_remove, adding two thing: full subtree remove, and delete own node.
373   *  Parameters:  The dn to delete
374   *  GiveBack:    True on sucessfull , 0 in error, and "" when we don't get a ldap conection
375   *
376   */
378   function rmdir_recursive($deletedn)
379   {
380     if($this->hascon){
381       if ($this->reconnect) $this->connect();
382       $delarray= array();
383         
384       /* Get sorted list of dn's to delete */
385       $this->ls ("(objectClass=*)",$deletedn);
386       while ($this->fetch()){
387         $deldn= $this->getDN();
388         $delarray[$deldn]= strlen($deldn);
389       }
390       arsort ($delarray);
391       reset ($delarray);
393       /* Really Delete ALL dn's in subtree */
394       foreach ($delarray as $key => $value){
395         $this->rmdir_recursive($key);
396       }
397       
398       /* Finally Delete own Node */
399       $r = @ldap_delete($this->cid, $this->fix($deletedn));
400       $this->error = @ldap_error($this->cid);
401       return($r ? $r : 0);
402     }else{
403       $this->error = "Could not connect to LDAP server";
404       return("");
405     }
406   }
408   /* Copy given attributes and sub-dns with attributes to destination dn 
409   */
410   function copy_FAI_resource_recursive($sourcedn,$destinationdn,$type="branch",$is_first = true,$depth=0)
411   {
412     error_reporting(E_ALL);
413     
414     if($is_first){
415       echo "<h2>".sprintf(_("Creating copy of %s"),"<i>".$sourcedn."</i>")."</h2>";
416     }else{
417       if(preg_match("/^ou=/",$sourcedn)){
418         echo "<h3>"._("Processing")." <i>$destinationdn</i></h3>";
419       }else{
420         $tmp = split(",",$sourcedn);
421         
422         echo "&nbsp;<b>"._("Object").":</b> ";
424         $deststr = $destinationdn;
425         if(strlen($deststr) > 96){
426           $deststr = substr($deststr,0,96)."...";
427         }
429         echo $deststr."<br>";
430       }
431     }
433     flush();
434     
435     if($this->hascon){
436       if ($this->reconnect) $this->connect();
438       /* Save base dn */
439       $basedn= $this->basedn;
440       $delarray= array();
441      
442       /* Check if destination entry already exists */
443       $this->cat($destinationdn);
445       if($this->count()){
446         return;
447       }else{
448         
449         $this->clearResult();
451         /* Get source entry */
452         $this->cd($basedn);
453         $this->cat($sourcedn);
454         $attr = $this->fetch();
456         /* Error while fetching object / attribute abort*/
457         if((!$attr) || (count($attr)) ==0) {
458           echo _("Error while fetching source dn - aborted!");
459           return;
460         }
461   
462         /* check if this is a department */
463         if(in_array("organizationalUnit",$attr['objectClass'])){
464           $attr['dn'] = $this->convert($destinationdn);
465           $this->cd($basedn);
466           $this->create_missing_trees($destinationdn);
467           $this->cd($destinationdn);
469           /* If is first entry, append FAIbranch to department entry */
470           if($is_first){
471             $this->cat($destinationdn);
472             $attr= $this->fetch();
474             /* Filter unneeded informations */
475             foreach($attr as $key => $value){
476               if(is_numeric($key)) unset($attr[$key]);
477               if(isset($attr[$key]['count'])){
478                 if(is_array($attr[$key])){
479                   unset($attr[$key]['count']);
480                 }
481               }
482             }
483             
484             unset($attr['count']);
485             unset($attr['dn']);
487             /* Add marking attribute */
488             $attr['objectClass'][] = "FAIbranch";
489             
490             /* Add this entry */
491             $this->modify($attr);
492           }
493         }else{
495           /* If this is no department */
496           foreach($attr as $key => $value){
497             if(in_array($key ,array("FAItemplateFile","FAIscript", "gotoLogonScript", "gosaApplicationIcon"))){
498               $sr= ldap_read($this->cid, $this->fix($sourcedn), "$key=*", array($key));
499               $ei= ldap_first_entry($this->cid, $sr);
500               if ($tmp= @ldap_get_values_len($this->cid, $ei,$key)){
501                 $attr[$key] = $tmp;
502               }
503             }
505             if(is_numeric($key)) unset($attr[$key]);
506             if(isset($attr[$key]['count'])){
507               if(is_array($attr[$key])){
508                 unset($attr[$key]['count']);
509               }
510             }
511           }
512           unset($attr['count']);
513           unset($attr['dn']);
515           if(!in_array("gosaApplication" , $attr['objectClass'])){
516             if($type=="branch"){
517               $attr['FAIstate'] ="branch";
518             }elseif($type=="freeze"){
519               $attr['FAIstate'] ="freeze";
520             }else{
521               print_red(_("Unknown FAIstate %s"),$type);
522             }
523           }
525           /* Add entry */
526           $this->cd($destinationdn);
527           $this->cat($destinationdn);
528           $a = $this->fetch();
529           if(!count($a)){
530             $this->add($attr);
531           }
533           if($this->error != "Success"){
534             /* Some error occured */
535             print "---------------------------------------------";
536             print $this->get_error()."<br>";
537             print $sourcedn."<br>";
538             print $destinationdn."<br>";
539             print_a( $attr);
540             exit();
541           }          
542         }
543       }
545       $this->ls ("(objectClass=*)",$sourcedn);
546       while ($this->fetch()){
547         $deldn= $this->getDN();
548         $delarray[$deldn]= strlen($deldn);
549       }
550       asort ($delarray);
551       reset ($delarray);
553        $depth ++;
554       foreach($delarray as $dn => $bla){
555         if($dn != $destinationdn){
556           $this->cd($basedn);
557           $item = $this->fetch($this->cat($dn));
558           if(!in_array("FAIbranch",$item['objectClass'])){
559             $this->copy_FAI_resource_recursive($dn,str_replace($sourcedn,$destinationdn,$dn),$type,false,$depth);
560           } 
561         }
562       }
563     }
564     if($is_first){
565       echo "<p class='seperator'>&nbsp;</p>";
566     }
568   }
570   function modify($attrs)
571   {
572     if(count($attrs) == 0){
573       return (0);
574     }
575     if($this->hascon){
576       if ($this->reconnect) $this->connect();
577       $r = @ldap_modify($this->cid, $this->fix($this->basedn), $attrs);
578       $this->error = @ldap_error($this->cid);
579       return($r ? $r : 0);
580     }else{
581       $this->error = "Could not connect to LDAP server";
582       return("");
583     }
584   }
586   function add($attrs)
587   {
588     if($this->hascon){
589       if ($this->reconnect) $this->connect();
590       $r = @ldap_add($this->cid, $this->fix($this->basedn), $attrs);
591       $this->error = @ldap_error($this->cid);
592       return($r ? $r : 0);
593     }else{
594       $this->error = "Could not connect to LDAP server";
595       return("");
596     }
597   }
599   function create_missing_trees($target)
600   {
601     /* Ignore create_missing trees if the base equals target */
602     if ($target == $this->basedn){
603      return;
604     }
606     $real_path= substr($target, 0, strlen($target) - strlen($this->basedn) -1 );
607     $l= array_reverse(ldap_explode_dn($real_path,0));
608     unset($l['count']);
609     $cdn= $this->basedn;
611     foreach ($l as $part){
612       $cdn= "$part,$cdn";
614       /* Ignore referrals */
615       $found= false;
616       foreach($this->referrals as $ref){
617         $base= preg_replace('!^[^:]+://[^/]+/([^?]+).*$!', '\\1', $ref['URL']);
618         if ($base == $cdn){
619           $found= true;
620           break;
621         }
622       }
623       if ($found){
624         continue;
625       }
627       $this->cat ($cdn);
628       $attrs= $this->fetch();
630       /* Create missing entry? */
631       if (!count ($attrs)){
632         $type= preg_replace('/^([^=]+)=.*$/', '\\1', $cdn);
633         $param= preg_replace('/^[^=]+=([^,]+),.*$/', '\\1', $cdn);
635         $na= array();
636         switch ($type){
637           case 'ou':
638             $na["objectClass"]= "organizationalUnit";
639             $na["ou"]= $param;
640             break;
641           case 'dc':
642             $na["objectClass"]= array("dcObject", "top", "locality");
643             $na["dc"]= $param;
644             break;
645           default:
646             print_red(sprintf(_("Autocreation of type '%s' is currently not supported. Please report to the GOsa team."), $type));
647             echo $_SESSION['errors'];
648             exit;
649         }
650         $this->cd($cdn);
651         $this->add($na);
652       }
653     }
654   }
656   function recursive_remove()
657   {
658     $delarray= array();
660     /* Get sorted list of dn's to delete */
661     $this->search ("(objectClass=*)");
662     while ($this->fetch()){
663       $deldn= $this->getDN();
664       $delarray[$deldn]= strlen($deldn);
665     }
666     arsort ($delarray);
667     reset ($delarray);
669     /* Delete all dn's in subtree */
670     foreach ($delarray as $key => $value){
671       $this->rmdir($key);
672     }
673   }
675   function get_attribute($dn, $name,$r_array=0)
676   {
677     $data= "";
678     if ($this->reconnect) $this->connect();
679     $sr= @ldap_read($this->cid, $this->fix($dn), "objectClass=*", array("$name"));
681     /* fill data from LDAP */
682     if ($sr) {
683       $ei= @ldap_first_entry($this->cid, $sr);
684       if ($ei) {
685         if ($info= @ldap_get_values_len($this->cid, $ei, "$name")){
686           $data= $info[0];
687         }
689       }
690     }
691     if($r_array==0)
692     return ($data);
693     else
694     return ($info);
695   
696   
697   }
698  
701   function get_additional_error()
702   {
703     $error= "";
704     @ldap_get_option ($this->cid, LDAP_OPT_ERROR_STRING, $error);
705     return ($error);
706   }
708   function get_error()
709   {
710     if ($this->error == 'Success'){
711       return $this->error;
712     } else {
713       $error= $this->error." (".$this->get_additional_error().")";
714       return $error;
715     }
716   }
718   function get_credentials($url, $referrals= NULL)
719   {
720     $ret= array();
721     $url= preg_replace('!\?\?.*$!', '', $url);
722     $server= preg_replace('!^([^:]+://[^/]+)/.*$!', '\\1', $url);
724     if ($referrals == NULL){
725       $referrals= $this->referrals;
726     }
728     if (isset($referrals[$server])){
729       return ($referrals[$server]);
730     } else {
731       $ret['ADMIN']= $this->fix($this->binddn);
732       $ret['PASSWORD']= $this->bindpw;
733     }
735     return ($ret);
736   }
739   function gen_ldif ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE)
740   {
741     $display= "";
743     if ($recursive){
744       $this->cd($dn);
745       $this->search("$filter", array('dn'));
746       while ($attrs= $this->fetch()){
747         $display.= $this->gen_one_entry($attrs['dn'], $filter, $attributes);
748         $display.= "\n";
749       }
750     } else {
751       $display.= $this->gen_one_entry($dn);
752     }
754     return ($display);
755   }
757 function gen_xls ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE,$r_array=0)
758   {
759     $display= "";
761       $this->cd($dn);
762       $this->search("$filter");
764       $i=0;
765       while ($attrs= $this->fetch()){
766         $j=0;
768         foreach ($attributes as $at){
769           $display[$i][$j]= $this->get_attribute($attrs['dn'], $at,$r_array);
770           $j++;
771         }
773         $i++;
774       }
776     return ($display);
777   }
780   function gen_one_entry($dn, $filter= "(objectClass=*)" , $name= array("*"))
781   {
782     $ret = "";
783     $data = "";
784     if($this->reconnect){
785       $this->connect();
786     }
788     /* Searching Ldap Tree */
789     $sr= @ldap_read($this->cid, $this->fix($dn), $filter, $name);
791     /* Get the first entry */   
792     $entry= @ldap_first_entry($this->cid, $sr);
794     /* Get all attributes related to that Objekt */
795     $atts = array();
796     
797     /* Assemble dn */
798     $atts[0]['name']  = "dn";
799     $atts[0]['value'] = array('count' => 1, 0 => $dn);
801     /* Reset index */
802     $i = 1 ; 
803   $identifier = array();
804     $attribute= @ldap_first_attribute($this->cid,$entry,$identifier);
805     while ($attribute) {
806       $i++;
807       $atts[$i]['name']  = $attribute;
808       $atts[$i]['value'] = @ldap_get_values_len($this->cid, $entry, "$attribute");
810       /* Next one */
811       $attribute= @ldap_next_attribute($this->cid,$entry,$identifier);
812     }
814     foreach($atts as $at)
815     {
816       for ($i= 0; $i<$at['value']['count']; $i++){
818         /* Check if we must encode the data */
819         if(!preg_match('/^[a-z0-9+@#.=, \/ -]+$/i', $at['value'][$i])) {
820           $ret .= $at['name'].":: ".base64_encode($at['value'][$i])."\n";
821         } else {
822           $ret .= $at['name'].": ".$at['value'][$i]."\n";
823         }
824       }
825     }
827     return($ret);
828   }
831   function dn_exists($dn)
832   {
833     return @ldap_list($this->cid, $this->fix($dn), "(objectClass=*)", array("objectClass"));
834   }
835   
838   function import_complete_ldif($str_attr,&$error,$overwrite,$cleanup)
839   {
840     if($this->reconnect) $this->connect();
842     /* First we have to splitt the string ito detect empty lines
843        An empty line indicates an new Entry */
844     $entries = split("\n",$str_attr);
846     $data = "";
847     $cnt = 0; 
848     $current_line = 0;
850     /* Every single line ... */
851     foreach($entries as $entry) {
852       $current_line ++;
854       /* Removing Spaces to .. 
855          .. test if a new entry begins */
856       $tmp  = str_replace(" ","",$data );
858       /* .. prevent empty lines in an entry */
859       $tmp2 = str_replace(" ","",$entry);
861       /* If the Block ends (Empty Line) */
862       if((empty($entry))&&(!empty($tmp))) {
863         /* Add collected lines as a complete block */
864         $all[$cnt] = $data;
865         $cnt ++;
866         $data ="";
867       } else {
869         /* Append lines ... */
870         if(!empty($tmp2)) {
871           /* check if we need base64_decode for this line */
872           if(ereg("::",$tmp2))
873           {
874             $encoded = split("::",$entry);
875             $attr  = $encoded[0];
876             $value = base64_decode($encoded[1]);
877             /* Add linenumber */
878             $data .= $current_line."#".$attr.":".$value."\n";
879           }
880           else
881           {
882             /* Add Linenumber */ 
883             $data .= $current_line."#".$entry."\n";
884           }
885         }
886       }
887     }
889     /* The Data we collected is not in the array all[];
890        For example the Data is stored like this..
892        all[0] = "1#dn : .... \n 
893        2#ObjectType: person \n ...."
894        
895        Now we check every insertblock and try to insert */
896     foreach ( $all as $single) {
897       $lineone = split("\n",$single);  
898       $ndn = split("#", $lineone[0]);
899       $line = $ndn[1];
901       $dnn = split (":",$line);
902       $current_line = $ndn[0];
903       $dn    = $dnn[0];
904       $value = $dnn[1];
906       /* Every block must begin with a dn */
907       if($dn != "dn") {
908         $error= sprintf(_("This is not a valid DN: '%s'. A block for import should begin with 'dn: ...' in line %s"), $line, $current_line);
909         return -2;  
910       }
912       /* Should we use Modify instead of Add */
913       $usemodify= false;
915       /* Delete before insert */
916       $usermdir= false;
917     
918       /* The dn address already exists! */
919       if (($this->dn_exists($value))&&((!$overwrite)&&(!$cleanup))) {
921         $error= sprintf(_("The dn: '%s' (from line %s) already exists in the LDAP database."), $line, $current_line);
922         return ALREADY_EXISTING_ENTRY;   
924       } elseif(($this->dn_exists($value))&&($cleanup)){
926         /* Delete first, then add */
927         $usermdir = true;        
929       } elseif(($this->dn_exists($value))&&($overwrite)) {
930         
931         /* Modify instead of Add */
932         $usemodify = true;
933       }
934      
935       /* If we can't Import, return with a file error */
936       if(!$this->import_single_entry($single,$usemodify,$usermdir) ) {
937         $error= sprintf(_("Error while importing dn: '%s', please check your LDIF from line %s on!"), $line,
938                         $current_line);
939         return UNKNOWN_TOKEN_IN_LDIF_FILE;      }
940     }
942     return (INSERT_OK);
943   }
946   /* Imports a single entry */
947   function import_single_entry($str_attr,$modify,$delete)
948   {
949     if($this->reconnect) $this->connect();
951     $ret = false;
952     $rows= split("\n",$str_attr);
953     $data= false;
955     foreach($rows as $row) {
956       
957       /* Check if we use Linenumbers (when import_complete_ldif is called we use
958          Linenumbers) Linenumbers are use like this 123#attribute : value */
959       if(!empty($row)) {
960         if((strpos($row,"#")!=FALSE)&&(strpos($row,"#")<strpos($row,":"))) {
962           /* We are using line numbers 
963              Because there is a # before a : */
964           $tmp1= split("#",$row);
965           $current_line= $tmp1[0];
966           $row= $tmp1[1];
967         }
969         /* Split the line into  attribute  and value */
970         $attr   = split(":", $row);
971         $attr[0]= trim($attr[0]);  /* attribute */
972         $attr[1]= trim($attr[1]);  /* value */
974         /* Check for attributes that are used more than once */
975         if(!isset($data[$attr[0]])) {
976           $data[$attr[0]]=$attr[1];
977         } else {
978           $tmp = $data[$attr[0]];
980           if(!is_array($tmp)) {
981             $new[0]=$tmp;
982             $new[1]=$attr[1];
983             $datas[$attr[0]]['count']=1;             
984             $data[$attr[0]]=$new;
985           } else {
986             $cnt = $datas[$attr[0]]['count'];           
987             $cnt ++;
988             $data[$attr[0]][$cnt]=$attr[1];
989             $datas[$attr[0]]['count'] = $cnt;
990           }
991         }
992       }
993     } 
994     
995     /* If dn is an index of data, we should try to insert the data */
996     if(isset($data['dn'])) {
997       /* Creating Entry */
998       $this->cd($data['dn']);
1000       /* Delete existing entry */
1001       if($delete){
1002         $this->rmdir($data['dn']);
1003       }
1004       
1005       /* Create missing trees */
1006       $this->create_missing_trees($data['dn']);
1007       unset($data['dn']);
1008       
1009       /* If entry exists use modify */
1010       if(!$modify){
1011         $ret = $this->add($data);
1012       } else {
1013         $ret = $this->modify($data);
1014       }
1015     }
1017     return($ret);
1018   }
1020   
1021   function importcsv($str)
1022   {
1023     $lines = split("\n",$str);
1024     foreach($lines as $line)
1025     {
1026       /* continue if theres a comment */
1027       if(substr(trim($line),0,1)=="#"){
1028         continue;
1029       }
1031       $line= str_replace ("\t\t","\t",$line);
1032       $line= str_replace ("\t"  ,"," ,$line);
1033       echo $line;
1035       $cells = split(",",$line )  ;
1036       $linet= str_replace ("\t\t",",",$line);
1037       $cells = split("\t",$line);
1038       $count = count($cells);  
1039     }
1041   }
1045 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1046 ?>