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;
641 $tag= "";
643 foreach ($l as $part){
644 $cdn= "$part,$cdn";
646 /* Ignore referrals */
647 $found= false;
648 foreach($this->referrals as $ref){
649 $base= preg_replace('!^[^:]+://[^/]+/([^?]+).*$!', '\\1', $ref['URL']);
650 if ($base == $cdn){
651 $found= true;
652 break;
653 }
654 }
655 if ($found){
656 continue;
657 }
659 $this->cat ($cdn);
660 $attrs= $this->fetch();
662 /* Create missing entry? */
663 if (count ($attrs)){
665 /* Catch the tag - if present */
666 if (isset($attrs['gosaUnitTag'][0])){
667 $tag= $attrs['gosaUnitTag'][0];
668 }
670 } else {
671 $type= preg_replace('/^([^=]+)=.*$/', '\\1', $cdn);
672 $param= preg_replace('/^[^=]+=([^,]+),.*$/', '\\1', $cdn);
674 $na= array();
675 switch ($type){
676 case 'ou':
677 if ($tag != ""){
678 $na["objectClass"]= array("organizationalUnit", "gosaAdministrativeUnitTag");
679 $na["gosaUnitTag"]= $tag;
680 } else {
681 $na["objectClass"]= "organizationalUnit";
682 }
683 $na["ou"]= $param;
684 break;
685 case 'dc':
686 if ($tag != ""){
687 $na["objectClass"]= array("dcObject", "top", "locality", "gosaAdministrativeUnitTag");
688 $na["gosaUnitTag"]= $tag;
689 } else {
690 $na["objectClass"]= array("dcObject", "top", "locality");
691 }
692 $na["dc"]= $param;
693 break;
694 default:
695 print_red(sprintf(_("Autocreation of type '%s' is currently not supported. Please report to the GOsa team."), $type));
696 echo $_SESSION['errors'];
697 exit;
698 }
699 $this->cd($cdn);
700 $this->add($na);
701 }
702 }
703 }
705 function recursive_remove()
706 {
707 $delarray= array();
709 /* Get sorted list of dn's to delete */
710 $this->search ("(objectClass=*)");
711 while ($this->fetch()){
712 $deldn= $this->getDN();
713 $delarray[$deldn]= strlen($deldn);
714 }
715 arsort ($delarray);
716 reset ($delarray);
718 /* Delete all dn's in subtree */
719 foreach ($delarray as $key => $value){
720 $this->rmdir($key);
721 }
722 }
724 function get_attribute($dn, $name,$r_array=0)
725 {
726 $data= "";
727 if ($this->reconnect) $this->connect();
728 $sr= @ldap_read($this->cid, $this->fix($dn), "objectClass=*", array("$name"));
730 /* fill data from LDAP */
731 if ($sr) {
732 $ei= @ldap_first_entry($this->cid, $sr);
733 if ($ei) {
734 if ($info= @ldap_get_values_len($this->cid, $ei, "$name")){
735 $data= $info[0];
736 }
738 }
739 }
740 if($r_array==0)
741 return ($data);
742 else
743 return ($info);
746 }
750 function get_additional_error()
751 {
752 $error= "";
753 @ldap_get_option ($this->cid, LDAP_OPT_ERROR_STRING, $error);
754 return ($error);
755 }
757 function get_error()
758 {
759 if ($this->error == 'Success'){
760 return $this->error;
761 } else {
762 $error= $this->error." (".$this->get_additional_error().")";
763 return $error;
764 }
765 }
767 function get_credentials($url, $referrals= NULL)
768 {
769 $ret= array();
770 $url= preg_replace('!\?\?.*$!', '', $url);
771 $server= preg_replace('!^([^:]+://[^/]+)/.*$!', '\\1', $url);
773 if ($referrals == NULL){
774 $referrals= $this->referrals;
775 }
777 if (isset($referrals[$server])){
778 return ($referrals[$server]);
779 } else {
780 $ret['ADMIN']= $this->fix($this->binddn);
781 $ret['PASSWORD']= $this->bindpw;
782 }
784 return ($ret);
785 }
788 function gen_ldif ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE)
789 {
790 $display= "";
792 if ($recursive){
793 $this->cd($dn);
794 $this->search("$filter", array('dn'));
795 while ($attrs= $this->fetch()){
796 $display.= $this->gen_one_entry($attrs['dn'], $filter, $attributes);
797 $display.= "\n";
798 }
799 } else {
800 $display.= $this->gen_one_entry($dn);
801 }
803 return ($display);
804 }
806 function gen_xls ($dn, $filter= "(objectClass=*)", $attributes= array('*'), $recursive= TRUE,$r_array=0)
807 {
808 $display= "";
810 $this->cd($dn);
811 $this->search("$filter");
813 $i=0;
814 while ($attrs= $this->fetch()){
815 $j=0;
817 foreach ($attributes as $at){
818 $display[$i][$j]= $this->get_attribute($attrs['dn'], $at,$r_array);
819 $j++;
820 }
822 $i++;
823 }
825 return ($display);
826 }
829 function gen_one_entry($dn, $filter= "(objectClass=*)" , $name= array("*"))
830 {
831 $ret = "";
832 $data = "";
833 if($this->reconnect){
834 $this->connect();
835 }
837 /* Searching Ldap Tree */
838 $sr= @ldap_read($this->cid, $this->fix($dn), $filter, $name);
840 /* Get the first entry */
841 $entry= @ldap_first_entry($this->cid, $sr);
843 /* Get all attributes related to that Objekt */
844 $atts = array();
846 /* Assemble dn */
847 $atts[0]['name'] = "dn";
848 $atts[0]['value'] = array('count' => 1, 0 => $dn);
850 /* Reset index */
851 $i = 1 ;
852 $identifier = array();
853 $attribute= @ldap_first_attribute($this->cid,$entry,$identifier);
854 while ($attribute) {
855 $i++;
856 $atts[$i]['name'] = $attribute;
857 $atts[$i]['value'] = @ldap_get_values_len($this->cid, $entry, "$attribute");
859 /* Next one */
860 $attribute= @ldap_next_attribute($this->cid,$entry,$identifier);
861 }
863 foreach($atts as $at)
864 {
865 for ($i= 0; $i<$at['value']['count']; $i++){
867 /* Check if we must encode the data */
868 if(!preg_match('/^[a-z0-9+@#.=, \/ -]+$/i', $at['value'][$i])) {
869 $ret .= $at['name'].":: ".base64_encode($at['value'][$i])."\n";
870 } else {
871 $ret .= $at['name'].": ".$at['value'][$i]."\n";
872 }
873 }
874 }
876 return($ret);
877 }
880 function dn_exists($dn)
881 {
882 return @ldap_list($this->cid, $this->fix($dn), "(objectClass=*)", array("objectClass"));
883 }
887 function import_complete_ldif($str_attr,&$error,$overwrite,$cleanup)
888 {
889 if($this->reconnect) $this->connect();
891 /* First we have to splitt the string ito detect empty lines
892 An empty line indicates an new Entry */
893 $entries = split("\n",$str_attr);
895 $data = "";
896 $cnt = 0;
897 $current_line = 0;
899 /* Every single line ... */
900 foreach($entries as $entry) {
901 $current_line ++;
903 /* Removing Spaces to ..
904 .. test if a new entry begins */
905 $tmp = str_replace(" ","",$data );
907 /* .. prevent empty lines in an entry */
908 $tmp2 = str_replace(" ","",$entry);
910 /* If the Block ends (Empty Line) */
911 if((empty($entry))&&(!empty($tmp))) {
912 /* Add collected lines as a complete block */
913 $all[$cnt] = $data;
914 $cnt ++;
915 $data ="";
916 } else {
918 /* Append lines ... */
919 if(!empty($tmp2)) {
920 /* check if we need base64_decode for this line */
921 if(ereg("::",$tmp2))
922 {
923 $encoded = split("::",$entry);
924 $attr = $encoded[0];
925 $value = base64_decode($encoded[1]);
926 /* Add linenumber */
927 $data .= $current_line."#".$attr.":".$value."\n";
928 }
929 else
930 {
931 /* Add Linenumber */
932 $data .= $current_line."#".$entry."\n";
933 }
934 }
935 }
936 }
938 /* The Data we collected is not in the array all[];
939 For example the Data is stored like this..
941 all[0] = "1#dn : .... \n
942 2#ObjectType: person \n ...."
944 Now we check every insertblock and try to insert */
945 foreach ( $all as $single) {
946 $lineone = split("\n",$single);
947 $ndn = split("#", $lineone[0]);
948 $line = $ndn[1];
950 $dnn = split (":",$line);
951 $current_line = $ndn[0];
952 $dn = $dnn[0];
953 $value = $dnn[1];
955 /* Every block must begin with a dn */
956 if($dn != "dn") {
957 $error= sprintf(_("This is not a valid DN: '%s'. A block for import should begin with 'dn: ...' in line %s"), $line, $current_line);
958 return -2;
959 }
961 /* Should we use Modify instead of Add */
962 $usemodify= false;
964 /* Delete before insert */
965 $usermdir= false;
967 /* The dn address already exists! */
968 if (($this->dn_exists($value))&&((!$overwrite)&&(!$cleanup))) {
970 $error= sprintf(_("The dn: '%s' (from line %s) already exists in the LDAP database."), $line, $current_line);
971 return ALREADY_EXISTING_ENTRY;
973 } elseif(($this->dn_exists($value))&&($cleanup)){
975 /* Delete first, then add */
976 $usermdir = true;
978 } elseif(($this->dn_exists($value))&&($overwrite)) {
980 /* Modify instead of Add */
981 $usemodify = true;
982 }
984 /* If we can't Import, return with a file error */
985 if(!$this->import_single_entry($single,$usemodify,$usermdir) ) {
986 $error= sprintf(_("Error while importing dn: '%s', please check your LDIF from line %s on!"), $line,
987 $current_line);
988 return UNKNOWN_TOKEN_IN_LDIF_FILE; }
989 }
991 return (INSERT_OK);
992 }
995 /* Imports a single entry */
996 function import_single_entry($str_attr,$modify,$delete)
997 {
998 if($this->reconnect) $this->connect();
1000 $ret = false;
1001 $rows= split("\n",$str_attr);
1002 $data= false;
1004 foreach($rows as $row) {
1006 /* Check if we use Linenumbers (when import_complete_ldif is called we use
1007 Linenumbers) Linenumbers are use like this 123#attribute : value */
1008 if(!empty($row)) {
1009 if((strpos($row,"#")!=FALSE)&&(strpos($row,"#")<strpos($row,":"))) {
1011 /* We are using line numbers
1012 Because there is a # before a : */
1013 $tmp1= split("#",$row);
1014 $current_line= $tmp1[0];
1015 $row= $tmp1[1];
1016 }
1018 /* Split the line into attribute and value */
1019 $attr = split(":", $row);
1020 $attr[0]= trim($attr[0]); /* attribute */
1021 $attr[1]= trim($attr[1]); /* value */
1023 /* Check for attributes that are used more than once */
1024 if(!isset($data[$attr[0]])) {
1025 $data[$attr[0]]=$attr[1];
1026 } else {
1027 $tmp = $data[$attr[0]];
1029 if(!is_array($tmp)) {
1030 $new[0]=$tmp;
1031 $new[1]=$attr[1];
1032 $datas[$attr[0]]['count']=1;
1033 $data[$attr[0]]=$new;
1034 } else {
1035 $cnt = $datas[$attr[0]]['count'];
1036 $cnt ++;
1037 $data[$attr[0]][$cnt]=$attr[1];
1038 $datas[$attr[0]]['count'] = $cnt;
1039 }
1040 }
1041 }
1042 }
1044 /* If dn is an index of data, we should try to insert the data */
1045 if(isset($data['dn'])) {
1046 /* Creating Entry */
1047 $this->cd($data['dn']);
1049 /* Delete existing entry */
1050 if($delete){
1051 $this->rmdir($data['dn']);
1052 }
1054 /* Create missing trees */
1055 $this->create_missing_trees($data['dn']);
1056 unset($data['dn']);
1058 /* If entry exists use modify */
1059 if(!$modify){
1060 $ret = $this->add($data);
1061 } else {
1062 $ret = $this->modify($data);
1063 }
1064 }
1066 return($ret);
1067 }
1070 function importcsv($str)
1071 {
1072 $lines = split("\n",$str);
1073 foreach($lines as $line)
1074 {
1075 /* continue if theres a comment */
1076 if(substr(trim($line),0,1)=="#"){
1077 continue;
1078 }
1080 $line= str_replace ("\t\t","\t",$line);
1081 $line= str_replace ("\t" ,"," ,$line);
1082 echo $line;
1084 $cells = split(",",$line ) ;
1085 $linet= str_replace ("\t\t",",",$line);
1086 $cells = split("\t",$line);
1087 $count = count($cells);
1088 }
1090 }
1092 function get_objectclasses()
1093 {
1094 $objectclasses = array();
1096 # Get base to look for schema
1097 $sr = @ldap_read ($this->cid, NULL, "objectClass=*", array("subschemaSubentry"));
1098 $attr = @ldap_get_entries($this->cid,$sr);
1099 if (!isset($attr[0]['subschemasubentry'][0])){
1100 return array();
1101 }
1103 # Get list of objectclasses
1104 $nb= $attr[0]['subschemasubentry'][0];
1105 $objectclasses= array();
1106 $sr= ldap_read ($this->cid, $nb, "objectClass=*", array("objectclasses"));
1107 $attrs= ldap_get_entries($this->cid,$sr);
1108 if (!isset($attrs[0])){
1109 return array();
1110 }
1111 foreach ($attrs[0]['objectclasses'] as $val){
1112 $name= preg_replace("/^.* NAME\s+\(*\s*'([^']+)'\s*\)*.*$/", '\\1', $val);
1113 if ($name != $val){
1114 $objectclasses[$name]= $val;
1115 }
1116 }
1118 return $objectclasses;
1119 }
1121 }
1123 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1124 ?>