1 <?php
4 /* All available record types
5 */
6 $RecordTypes['aRecord'] = "aRecord";
7 $RecordTypes['mDRecord'] = "mDRecord";
8 $RecordTypes['mXRecord'] = "mXRecord";
9 $RecordTypes['nSRecord'] = "nSRecord";
10 $RecordTypes['pTRRecord'] = "relativeDomainName";
11 $RecordTypes['hInfoRecord'] = "hInfoRecord";
12 $RecordTypes['mInfoRecord'] = "mInfoRecord";
13 $RecordTypes['cNAMERecord'] = "relativeDomainName";
14 $RecordTypes['tXTRecord'] = "tXTRecord";
15 $RecordTypes['aFSDBRecord'] = "aFSDBRecord";
16 $RecordTypes['SigRecord'] = "SigRecord";
17 $RecordTypes['KeyRecord'] = "KeyRecord";
18 $RecordTypes['aAAARecord'] = "aAAARecord";
19 $RecordTypes['LocRecord'] = "LocRecord";
20 $RecordTypes['nXTRecord'] = "nXTRecord";
21 $RecordTypes['sRVRecord'] = "sRVRecord";
22 $RecordTypes['nAPTRRecord'] = "nAPTRRecord";
23 $RecordTypes['kXRecord'] = "kXRecord";
24 $RecordTypes['certRecord'] = "certRecord";
25 $RecordTypes['a6Record'] = "a6Record";
26 $RecordTypes['dSRecord'] = "dSRecord";
27 $RecordTypes['sSHFPRecord'] = "sSHFPRecord";
28 $RecordTypes['rRSIGRecord'] = "rRSIGRecord";
29 $RecordTypes['nSECRecord'] = "nSECRecord";
32 /* Return all record types
33 */
34 function getDnsRecordTypes($ForZones = false)
35 {
36 global $RecordTypes;
37 if($ForZones){
38 $tmp = $RecordTypes;
39 unset($tmp['cNAMERecord']);
40 unset($tmp['pTRRecord']);
41 unset($tmp['tXTRecord']);
42 return($tmp);
43 }else{
44 return($RecordTypes);
45 }
46 }
49 /* This fucntion is used to flip the ip address, for example
50 12.3.45 -> 45.3.12
51 Because some entries (like zones) are store like that 45.3.12.in-addr.arpa
52 but we want to display 12.3.45.
53 */
54 function FlipIp($ip)
55 {
56 $tmp = array_reverse(split("\.",$ip));
57 $new = "";
58 foreach($tmp as $section){
59 $new .= $section.".";
60 }
61 return(preg_replace("/.$/","",$new));
62 }
65 /* This function returns the zones specified for given host
66 */
67 function getDNSZoneEntries($config,$HostDn,$silent = false)
68 {
69 global $RecordTypes;
71 $ldap = $config->get_ldap_link();
72 $ldap->cd($config->current['BASE']);
74 /* Not all records are allowed within a zone entry
75 */
76 $SkipRecords = array("tXTRecord","cNAMERecord","pTRRecord");
78 /* Special sOArecords
79 */
80 $sOAREcords = array("0"=>"sOAprimary","1"=>"sOAmail","2"=>"sOAserial","3"=>"sOArefresh","4"=>"sOAretry","5"=>"sOAexpire","6"=>"sOAttl");
82 /* Get host entry */
83 $ldap->cat($HostDn);
84 $host_attr = $ldap->fetch();
86 /* Create tempalte for all fetched zone Data
87 */
88 $ZoneBase = array();
89 $ZoneBase['exists'] = false;
90 $ZoneBase['RECORDS'] = array();
91 $ZoneBase['zoneName'] = array();
92 $ZoneBase['dNSClass'] = array();
94 foreach($sOAREcords as $attr){
95 $ZoneBase[$attr] = "";
96 }
98 $Zones = array();
100 /* Get & Parse all zone entries
101 */
102 $ldap->ls("(&(objectClass=dNSZone)(zoneName=*)(relativeDomainName=@))",$HostDn,array("*"));
103 $tmp_res = array();
104 while($attrs = $ldap->fetch()) {
105 $tmp_res[] = $attrs;
106 }
108 /* Parse fetched zones
109 */
110 foreach($tmp_res as $attrs){
112 $zoneName = strtoupper($host_attr['cn'][0])."/".$attrs['zoneName'][0];
113 $Zones[$zoneName] = $ZoneBase;
114 $Zones[$zoneName]['exists'] = true;
116 /* Set basic attributes
117 */
118 if(isset($attrs["dNSClass"][0])){
119 $Zones[$zoneName]["dNSClass"] = $attrs["dNSClass"][0];
120 }
122 /* Set initial zone name, to be able to detect if this entry was renamed
123 */
124 $Zones[$zoneName]['InitialzoneName'] = $zoneName;
125 $Zones[$zoneName]['zoneName'] = $zoneName;
127 /* Generate SOA entry
128 */
129 if(isset($attrs['sOARecord'][0])){
130 $tmp = split("\ ",$attrs['sOARecord'][0]) ;
131 $tmp2 = array();
133 /* Assign soa vars */
134 foreach($sOAREcords as $key => $name){
135 if(isset($tmp[$key])){
136 $Zones[$zoneName][$name] = $tmp[$key];
137 }else{
138 $Zones[$zoneName][$name] = "";
139 }
140 }
141 } // ENDE SOA Record
143 /* Get record attributes
144 */
145 foreach($RecordTypes as $name => $value){
147 /* Skip some attributes
148 */
149 if(in_array($name,$SkipRecords)) continue;
151 /* If there is a record attribute
152 */
153 if(isset($attrs[$name])){
155 /* get all entries
156 */
157 for($i = 0 ; $i < $attrs[$value]['count']; $i ++){
158 $Zones[$zoneName]['RECORDS'][] = array("type"=>$name,"value"=>$attrs[$value][$i]);
159 }
160 }
161 }
163 /* Get reverse record ..
164 */
165 $ldap->ls("(&(objectClass=dNSZone)(relativeDomainName=@)(zoneName=*))",$attrs['dn'],array("zoneName"));
167 if($ldap->count() == 0){
168 if(!$silent){
169 print_red(sprintf(_("Can't find reverse zone for dns zone '%s'. Aborting parsing this zone."),$zoneName));
170 }
171 unset($Zones[$zoneName]);
172 }elseif($ldap->count()>1){
173 if(!$silent){
174 print_red(sprintf(_("Found more than one reverse zone for dns zone '%s'. Aborting parsing this zone."),$zoneName));
175 }
176 unset($Zones[$zoneName]);
177 }else{
178 $tmp = $ldap->fetch();
179 $Zones[$zoneName]['ReverseZone'] = strtoupper($host_attr['cn'][0])."/".FlipIp(str_replace(".in-addr.arpa","",$tmp['zoneName'][0]));
180 $Zones[$zoneName]['InitialReverseZone'] = strtoupper($host_attr['cn'][0])."/".FlipIp(str_replace(".in-addr.arpa","",$tmp['zoneName'][0]));
181 }
182 }
183 return($Zones);
184 }
187 /* This function compares two dns zone objects and returns an
188 * array with following indexes
189 * - delete, for dns which must be deleted (only if dns zone is removed)
190 * - rename, if a dn must be renamed, for example, the zoneName has changed
191 * - add, if there is a new dns account created
192 */
193 function getDNSZoneEntriesDiff($config,$newZones,$HostDn)
194 {
195 $oldZones = getDNSZoneEntries($config,$HostDn,true);
197 $sOAattributes = array("sOAprimary","sOAmail","sOAserial","sOArefresh","sOAretry","sOAexpire","sOAttl");
199 $move = array();
200 $add = array();
201 $del = array();
203 /* Generate a template for zones with default values
204 */
205 $zoneBase = array();
206 $zoneBase['objectClass'] = array("top","dNSZone");
207 $zoneBase['zoneName'] = "";
208 $zoneBase['relativeDomainName'] = "@";
209 $zoneBase['dNSClass'] = "IN";
210 $zoneBase['sOARecord'] = "";
212 /* Contains all renamed zoneNames
213 * For zone entry udpdates
214 */
215 $PrePareZoneEntries = array();
217 /* Walk through all zones and detect renamed/added/deleted zones ...
218 */
219 foreach($newZones as $name => $zone){
221 /* This zone was renamed
222 */
223 if((!empty($zone['InitialzoneName'])) && ($zone['InitialzoneName'] != $zone['zoneName'])){
225 /* Move old zone to new position
226 */
227 $oldDn = "zoneName=".getNameFromMix($zone['InitialzoneName']).",".$HostDn;
228 $newDn = "zoneName=".getNameFromMix($zone['zoneName']).",".$HostDn;
229 $PrePareZoneEntries[getNameFromMix($zone['InitialzoneName'])] = getNameFromMix($zone['zoneName']);
230 $move [$oldDn] = $newDn;
231 }
233 /* Get old zone if available
234 */
235 $oldZone=array();
236 if(!empty($oldZones[$zone['InitialzoneName']])){
237 $oldZone = $oldZones[$zone['InitialzoneName']];
238 }
240 /* Create forward zone entry and put it in our add queue
241 */
242 $newDn = "zoneName=".getNameFromMix($zone['zoneName']).",".$HostDn;
243 $obj = $zoneBase;
244 $obj['zoneName'] = getNameFromMix($zone['zoneName']);
246 /* Create sOARecord & add it to the obj
247 */
248 $soa = "";
249 foreach($sOAattributes as $attr){
250 $soa.=" ".$zone[$attr];
251 }
252 $obj['sOARecord'] = trim($soa);
253 $obj['nSRecord'] = $zone['sOAprimary'];
255 /* If reverse zone was renamed, move entry
256 */
257 if(!empty($zone['InitialReverseZone'])){
258 if($zone['InitialReverseZone'] != $zone['ReverseZone']){
259 $base = "zoneName=".getNameFromMix($zone['zoneName']).",".$HostDn;
260 $oldRDn = "zoneName=". FlipIp(getNameFromMix($zone['InitialReverseZone'])).".in-addr.arpa,".$base;
261 $newRDn = "zoneName=". FlipIp(getNameFromMix($zone['ReverseZone'])).".in-addr.arpa,".$base;
262 $PrePareZoneEntries[FlipIp(getNameFromMix($zone['InitialReverseZone'])).".in-addr.arpa"] = FlipIp(getNameFromMix($zone['ReverseZone'])).".in-addr.arpa";
263 $move [$oldRDn] = $newRDn;
264 }
265 }
267 /* Append record entries
268 * Set old value to array, to ensure that
269 * they will be deleted if necessary
270 */
271 if(isset($oldZone['RECORDS'])){
272 foreach($oldZone['RECORDS'] as $rec){
273 $obj[$rec['type']] = array();
274 }
275 }
277 /* Add new Records
278 */
279 foreach($zone['RECORDS'] as $rec){
280 if(!isset($obj[$rec['type']])||!is_array($obj[$rec['type']])){
281 $obj[$rec['type']] = array();
282 }
283 $obj[$rec['type']][] = $rec['value'];
284 }
286 /* Append udpated Zone Forward Entry to our add queue
287 */
288 $add[$newDn] = $obj;
290 /* Create Reverse Entry
291 * And append it to our add queue
292 */
293 $zone['ReverseZone'] = FlipIp(getNameFromMix($zone['ReverseZone'])).".in-addr.arpa";
294 $base = "zoneName=".getNameFromMix($zone['zoneName']).",".$HostDn;
295 $newRDn = "zoneName=".$zone['ReverseZone'].",".$base;
296 $rObj = $obj;
297 $rObj['zoneName']= $zone['ReverseZone'];
298 $add[$newRDn] = $rObj;
300 /* Remove currently managed zone from oldZones.
301 * this gives us the ability to detect removed zones
302 */
303 if(isset($oldZones[$zone['InitialzoneName']])){
304 unset($oldZones[$zone['InitialzoneName']]);
305 }
306 }
308 /* The rest of our oldZones must be deleted
309 * because they are no longer available in newZones anymore.
310 */
311 foreach($oldZones as $zone) {
312 $oldDn = "zoneName=".getNameFromMix($zone['InitialzoneName']).",".$HostDn;
313 $del[$oldDn] = $zone;
314 }
316 /* Check for entries which must be updated
317 */
318 $zoneUpdates = array();
319 $udpate = array();
320 if(count($PrePareZoneEntries)){
321 $ldap = $config->get_ldap_link();
323 foreach($PrePareZoneEntries as $FromZoneName => $ToZoneName){
324 $ldap->cd($HostDn);
325 $ldap->search("(&(objectClass=dNSZone)(zoneName=".$FromZoneName.")(!(relativeDomainName=@)))",array("zoneName"));
326 while($attrs = $ldap->fetch()){
327 $attr_to_change = array();
328 $attr_to_change['zoneName'] = $ToZoneName;
329 $zoneUpdates[$attrs['dn']] = $attr_to_change;
330 }
331 }
332 }
333 $ret = array("del" => $del , "move" => $move , "add" => $add,"zoneUpdates"=>$zoneUpdates);
334 return($ret);
335 }
338 /* This function returns the dns-host eintries for given
339 * name.
340 */
341 function getDNSHostEntries($config,$name,$silent = false)
342 {
343 global $RecordTypes;
345 $types = array();
346 $ret = array();
347 $ret['RECORDS'] = array();
348 $ret['dNSClass'] = "IN";
349 $ret['zoneName'] = "";
350 $ret['dNSTTL'] = "7440";
351 $ret['exists'] = false;
353 $ldap = $config->get_ldap_link();
354 $ldap->cd($config->current['BASE']);
356 /* First check all zones for an entry with the given name.
357 * If the name occurs in more than one entry alert the user ...
358 */
359 $foundIn = array();
360 $zones = getAvailableZones($config);
362 $zonesArr = array();
363 foreach($zones as $zoneMix){
364 $zoneIndex = split("/",$zoneMix);
365 if(!array_key_exists($zoneIndex[0],$zonesArr)) {
366 $zonesArr[$zoneIndex[0]] = array();
367 }
368 array_push($zonesArr[$zoneIndex[0]],$zoneIndex[1]);
369 }
371 foreach($zonesArr as $nameServer => $nameServerArr){
372 $foundInTmp = array();
373 foreach($nameServerArr as $zoneArr => $zone){
374 $zoneMix = $nameServer."/".$zone;
375 $zoneDn = getDNSZoneDN($config,$zoneMix);
376 $ldap->ls("(&(objectClass=dNSZone)(zoneName=*)(relativeDomainName=".$name.")(!(relativeDomainName=@)))", $zoneDn,$attrs = array("*"));
377 while($attrs = $ldap->fetch()){
378 $foundInTmp [$zoneMix] = $attrs['dn'];
379 $foundIn [$zoneMix] = $attrs['dn'];
380 }
381 }
382 }
384 /* No zone found which contains an entry for us
385 */
386 if(count($foundIn) == 0){
387 return($ret);
388 }
390 /* Get host informations from zone
391 */
392 $id_tmp = key($foundIn);
393 $ldap->cd($foundIn[$id_tmp]);
394 $ldap->search("(&(objectClass=dNSZone)(zoneName=*)(!(relativeDomainName=@)))",array("*"));
395 while($attrs = $ldap->fetch()){
397 /* If relative domainname == cn
398 * Try to read dnsclass / TTl / zone
399 */
400 if($attrs['relativeDomainName'][0] == $name){
401 $ret['exists'] = true;
402 $ret['zoneName'] = $id_tmp;
403 foreach(array("dNSClass","dNSTTL") as $atr){
404 if(isset($attrs[$atr][0])){
405 $ret[$atr] = $attrs[$atr][0];
406 }
407 }
408 }
410 /* Create list with all used records */
411 foreach($RecordTypes as $name => $value){
413 /* If there is a record attribute */
414 if(isset($attrs[$name])){
416 /* get all entries */
417 for($i = 0 ; $i < $attrs[$value]['count']; $i ++){
418 $types[] = array( "type" => $name,
419 "value" => $attrs[$value][$i]);
420 }
421 }
422 }
423 $ret['RECORDS'] = $types;
424 }
425 return($ret);
426 }
430 /* This function compares two dns settings and returns an
431 * array with following indexes
432 * - delete, for dns which must be deleted (only if dns account is removed)
433 * - rename, if a dn must be renamed, for example, the relativeDomainName has changed
434 * - add, if there is a new dns account created
435 */
436 function getDNSHostEntriesDiff($config,$oldName,$newEntry,$newName)
437 {
438 global $RecordTypes;
440 $oldEntry = getDNSHostEntries($config,$oldName);
442 $add = array();
443 $del = array();
444 $move = array();
446 $zones = getAvailableZones($config);
447 $specialAttributes = array("cNAMERecord","pTRRecord");
448 $newRecords = array(); // Used to remember which records are removed
449 $zoneNameMix = $newEntry['zoneName'];
450 $zoneDn = getDNSZoneDN($config,$zoneNameMix);
451 $tmp = array_flip($zones);
452 $zoneName = getNameFromMix($zoneNameMix);
454 /* If reverseZone can't be resolved ... this
455 * can't be a valid entry, so remove this account
456 */
457 if(isset($tmp[$zoneNameMix])){
458 $reverseNameMix = $tmp[$zoneNameMix];
459 $reverseDn = getDNSZoneDN($config,$reverseNameMix);
460 if(empty($reverseDn)){
461 $newEntry['exists'] = false;
462 }
463 }else{
464 $newEntry['exists'] = false;
465 }
467 /* Don't go further if there is nothing to do
468 * Is no account / was no account
469 */
470 if(($newEntry['exists'] == false )&& ($oldEntry['exists'] == false)){
471 return(array("move"=>$move,"add"=>$add,"del"=>$del));
472 }
474 /* If account was edited prepare some
475 * attributes & arrays ... if required add some
476 * dns to $move
477 */
478 if($oldEntry['exists']){
480 /* Check if the account was removed
481 */
482 if($newEntry['exists'] == false){
483 $dn = "relativeDomainName=".$oldName.",".getDNSZoneDN($config,$oldEntry['zoneName']);
484 $del[$dn] ="";
485 return(array("move"=>$move,"add"=>$add,"del"=>$del));
486 }
488 /* Check if zoneName has changed
489 */
490 if(count($newEntry['RECORDS'])){
491 if($oldEntry['zoneName'] != $newEntry['zoneName']){
492 $oldzoneDn = getDNSZoneDN($config,$oldEntry['zoneName']);
493 $dn = "relativeDomainName=".$oldName.",".$oldzoneDn;
494 $dn2= "relativeDomainName=".$oldName.",".$zoneDn;
495 $move[$dn]=$dn2;
496 }
498 /* Check if host name has changed
499 */
500 if($oldName != $newName){
501 $dn = "relativeDomainName=".$oldName.",".$zoneDn;
502 $dn2= "relativeDomainName=".$newName.",".$zoneDn;
503 $move[$dn]=$dn2;
504 $dn = "relativeDomainName=".$oldName.",".$dn2;
505 $dn2= "relativeDomainName=".$newName.",".$dn2;
506 $move[$dn]=$dn2;
507 }
508 }
510 /* Prepare record entries
511 * Fill old records with array();
512 * To ensure that they will be deleted if they stay unused
513 */
514 foreach($oldEntry['RECORDS'] as $id => $rec){
515 $newRecords[$rec['type']] = array();
516 }
517 }
519 /* There must be at least one record in our entry
520 */
521 if((!count($newEntry['RECORDS'])) || (!$newEntry['exists'])){
522 $dn = "relativeDomainName=".$newName.",".getDNSZoneDN($config,$oldEntry['zoneName']);
523 $del[$dn] ="";
524 $ret = array("move"=>$move,"add"=>$add,"del"=>$del);
525 return($ret);
526 }
528 /* Prepare temp obj
529 */
530 $baseObj = array();
531 $baseObj['objectClass'] = array("top","dNSZone");
532 $baseObj['dNSTTL'] = $newEntry['dNSTTL'];
533 $baseObj['dNSClass'] = $newEntry['dNSClass'];
534 $baseObj['zoneName'] = $zoneName;
535 $baseObj['relativeDomainName']= $newName;
537 /* Add Container Object to zone
538 * (this possibly already exists, check this before writing to ldap)
539 */
540 $baseDn = "relativeDomainName=".$newName.",".$zoneDn;
541 $add[$baseDn] = $baseObj;
543 /* Add base obejct which contains all std records
544 */
545 $stdDn = "relativeDomainName=".$newName.",".$baseDn;
546 $add[$stdDn] = $baseObj;
548 /* Set defaults. Normaly only contains old record names.
549 * The old names will be set to array, to ensure that they will be deleted.
550 * Or overwritten and filled with new values.
551 */
552 foreach($newRecords as $name => $def){
553 if(!in_array($name,$specialAttributes)){
554 $add[$stdDn][$name] = $def;
555 }
556 }
558 /* Delete all OLD special attributes.
559 */
560 foreach($oldEntry['RECORDS'] as $id => $rec){
561 if(in_array($rec['type'],$specialAttributes)){
562 $deldn= "relativeDomainName=".$rec['value'].",".$baseDn;
563 $del[$deldn] = "";
564 }
565 }
568 /* Create new record entries
569 */
570 foreach($newEntry['RECORDS'] as $id => $rec){
571 /* Create object which contains special records
572 * like pTRRecord or CNAMERecord
573 */
574 if($rec['type'] == "pTRRecord"){
575 $PTRdn= "relativeDomainName=".FlipIP($rec['value']).",".$baseDn;
576 $ptrObj = $baseObj;
577 $reverseName = getNameFromMix($reverseNameMix);
578 $ptrObj['zoneName'] = $reverseName;
579 if(!preg_match("/\.$/",$newName)){
580 $ptrObj['pTRRecord'] = preg_replace("/\.\.$/",".",$newName.".".$zoneName.".");
581 }else{
582 $ptrObj['pTRRecord'] = preg_replace("/\.\.$/",".",$newName.".");
583 }
584 $ptrObj['relativeDomainName'] = FlipIP($rec['value']);
586 $add[$PTRdn] = $ptrObj;
587 }else
588 if($rec['type'] == "cNAMERecord"){
589 $PTRdn= "relativeDomainName=".$rec['value'].",".$baseDn;
590 $ptrObj = $baseObj;
591 $ptrObj['zoneName'] = $zoneName;
592 $ptrObj['cNAMERecord'] = $newName;
593 $ptrObj['relativeDomainName'] = $rec['value'];
595 $add[$PTRdn] = $ptrObj;
596 }else{
597 /* Append basic attributes
598 */
599 $add[$stdDn][$rec['type']][] = $rec['value'];
600 }
601 } // foreach record
603 $ret = array("move"=>$move,"add"=>$add,"del"=>$del);
604 return($ret);
605 }
607 function getNameFromMix($zoneMix){
608 $ret = "";
609 if(!strstr($zoneMix, '/')) return($ret);
610 $zoneIndex = split("/",$zoneMix);
611 return($zoneIndex[1]);
612 }
614 /* returns the dn for a specified zone
615 */
616 function getDNSZoneDN($config,$zoneNameMix)
617 {
618 $ret = "";
619 if(!strstr($zoneNameMix, '/')) {
620 print_red(sprintf(_("Undefined zone name '%s'. Zone name must look like this 'server/zone.com'."),$zoneNameMix));
621 return($ret);
622 }
624 $zoneNameIndex = split("/",$zoneNameMix);
625 $zoneName = $zoneNameIndex[1];
626 $nameServer = strtolower($zoneNameIndex[0]);
627 $ldap = $config->get_ldap_link();
629 /* search for the nameserver */
630 $ldap-> cd($config->current['BASE']);
631 $ldap->search("(&(objectClass=goServer)(cn=".$nameServer."))",array("cn"));
632 if($ldap->count()){
633 $attr = $ldap->fetch();
634 } else {
635 return($ret);
636 }
638 $ldap-> cd($attr['dn']);
639 $ldap->search("(&(objectClass=dNSZone)(sOARecord=*)(zoneName=".$zoneName."))",array("zoneName"));
640 if($ldap->count()){
641 $attr = $ldap->fetch();
642 return($attr['dn']);
643 }
645 return($ret);
646 }
649 /* returns all available zones
650 * array[reverseName] = zoneName;
651 */
652 function getAvailableZones($config)
653 {
654 $ret = array();
655 $ldap = $config->get_ldap_link();
656 $ldap->cd ($config->current['BASE']);
658 /* Search for zones ...
659 */
660 $ldap->search("(&(objectClass=dNSZone)(sOARecord=*))",array("zoneName"));
662 $ForwardZones = array();
663 $ReverseZones = array();
664 $zones = array();
666 while($at = $ldap->fetch()){
667 if(preg_match("/\.in\-addr\.arpa/",$at['zoneName'][0])){
668 $ReverseZones[$at['dn']] = $at;
669 }else{
670 $ForwardZones[$at['dn']] = $at;
671 }
672 }
674 foreach($ForwardZones as $dn => $obj){
676 /* try to find reverse
677 */
678 foreach($ReverseZones as $Rdn => $Robj ){
679 if(preg_match("/".$dn."/",$Rdn)){
680 $zones[strtoupper($ldap->getCn($dn))."/".$Robj['zoneName'][0]] =
681 strtoupper($ldap->getCn($dn))."/".$obj['zoneName'][0];
682 }
683 }
684 }
685 return($zones);
686 }
688 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
689 ?>