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