1 <?php
3 class servdns extends plugin
4 {
5 /* attribute list for save action */
6 var $ignore_account = FALSE;
7 var $attributes = array();
8 var $objectclasses = array("whatever");
10 var $RecordTypes = array();
11 var $Zones = array();
12 var $dialog = NULL;
14 var $orig_dn = "";
16 var $DNSinitially_was_account;
18 var $dns_server_list = array("ENTRIES"=> array(),"FOR_LIST"=> array());
19 var $take_over_id = -1;
20 var $display_warning = TRUE;
22 function servdns ($config, $dn= NULL, $parent= NULL)
23 {
24 plugin::plugin ($config, $dn, $parent);
26 $this->orig_dn = $dn;
28 /* Get record types for zones
29 */
30 $this->RecordTypes = getDnsRecordTypes(true);
32 /* Get all zone Informations
33 */
34 $this->Zones = getDNSZoneEntries($config,$dn);
36 /* If there is at least one entry in this -> types, we have DNS enabled
37 */
38 if(count($this->Zones) == 0){
39 $this->is_account = false;
40 $this->dns_server_list = $this->get_list_of_dns_servers();
41 }else{
42 $this->is_account = true;
43 }
44 $this->DNSinitially_was_account = $this->is_account;
45 }
48 function get_list_of_dns_servers()
49 {
50 $ret = array("ENTRIES"=> array(),"FOR_LIST"=> array());
51 $ldap = $this->config->get_ldap_link();
52 $ldap->cd($this->config->current['BASE']);
53 $ldap->search("(&(objectClass=dNSZone)(zoneName=*))",array("dn","zoneName"));
54 $dns = array();
55 while($attrs = $ldap->fetch()){
56 /* Skip own config */
57 if($this->dn != "new" && preg_match("/".normalizePreg($this->dn)."$/",$attrs['dn'])){
58 continue;
59 }
60 $dn = preg_replace("/^zoneName=[^,]+,/","",$attrs['dn']);
61 if(preg_match("/^cn=/",$dn) && !in_array($dn,$dns)){
62 $dns[] = $dn;
63 }
64 }
65 $i = 0;
66 foreach($dns as $dn){
67 $ldap->cat($dn,array('*'));
68 if($ldap->count()){
69 $i ++;
70 $attrs = $ldap->fetch();
71 $ret['ENTRIES'][$i] = $attrs;
72 $ret['FOR_LIST'][$i] = $attrs['cn'][0];
73 }
74 }
75 return($ret);
76 }
79 function execute()
80 {
81 /* Call parent execute
82 */
83 plugin::execute();
85 /* Fill templating stuff
86 */
87 $smarty= get_smarty();
88 $smarty->assign("dns_take_over",FALSE);
89 $display= "";
92 /*****************/
93 /* Handle Take Over Actions
94 /*****************/
96 /* Give smarty the required informations */
97 $smarty->assign("dns_server_list", $this->dns_server_list['FOR_LIST']);
98 $smarty->assign("dns_server_list_cnt", count($this->dns_server_list['FOR_LIST']));
100 /* Take over requested, save id */
101 if(isset($_POST['take_over_src']) && isset($_POST['take_over'])){
102 $id = $_POST['take_over_src'];
103 if(isset($this->dns_server_list['ENTRIES'][$id])){
104 $this->take_over_id = $id;
105 }
106 }
108 /* Abort take over action */
109 if(isset($_POST['cancel_take_over'])){
110 $this->dialog =false;
111 $this->take_over_id = -1;
112 $this->dns_server_list = $this->get_list_of_dns_servers();
113 }
115 /* Display informartion about take over that will be started when saving this server
116 * and hide default dns output
117 */
118 if($this->take_over_id != -1){
119 $this->dialog = FALSE;
120 $id = $this->take_over_id;
121 $smarty->assign("dns_take_over",TRUE);
122 $warning = sprintf(_("You are going to migrate the DNS setup from server '%s'."),$this->dns_server_list['ENTRIES'][$id]['cn'][0]);
123 # $warning.= " "._("This includes 'all' DNS zones that are located within this server. Please double check if your really want to do this.");
124 $warning.= " "._("The migration will be startet when you save this system. To cancel this action, use the cancel button below.");
126 if($this->display_warning){
127 print_red($warning);
128 $this->display_warning = FALSE;
129 }
130 return($smarty->fetch(get_template_path('servdns.tpl', TRUE)));
131 }
134 /* Do we need to flip is_account state?
135 */
136 if (isset($_POST['modify_state'])){
138 /* Only change account state if allowed */
139 if($this->is_account && $this->acl == "#all#"){
140 $this->is_account= !$this->is_account;
141 $this->is_modified = true;
142 }elseif(!$this->is_account && chkacl($this->acl,"create") == ""){
143 $this->is_account= !$this->is_account;
144 $this->is_modified = true;
145 }
146 }
148 if ($this->is_account){
149 $display= $this->show_header(_("Remove DNS service"),
150 _("This server has DNS features enabled. You can disable them by clicking below."));
151 } else {
152 $display= $this->show_header(_("Add DNS service"),
153 _("This server has DNS features disabled. You can enable them by clicking below."));
154 return ($display);
155 }
158 /* Edited or Added zone
159 */
160 if((isset($_POST['SaveZoneChanges'])) && is_object($this->dialog)){
161 $this->dialog->save_object();
163 /* Check for errors
164 */
165 if(count($this->dialog->check())){
166 foreach($this->dialog->check() as $msgs){
167 print_red($msgs);
168 }
169 }else{
170 /* add new/edited zone
171 */
172 $ret = $this->dialog->save();
173 if(!$this->dialog->isNew){
174 unset($this->Zones[$this->dialog->OldZoneName]);
175 }
176 $this->Zones[$ret['zoneName']] = $ret;
177 $this->dialog = NULL;
178 }
179 }
181 /* Cancel zone edit / new
182 */
183 if(isset($_POST['CancelZoneChanges'])){
184 $this->dialog = NULL;
185 }
187 /* Add empty new zone
188 */
189 if(isset($_POST['AddZone']) && chkacl($this->acl,"servdns") == ""){
190 $this->dialog = new servdnseditZone($this->config,$this->dn);
191 }
193 /* Check for edit zone request
194 */
195 $once = false;
196 foreach( $_POST as $name => $value){
198 /* check all post for edit request
199 */
200 if(preg_match("/^editZone_/",$name)&&!$once && chkacl($this->acl,"servdns") == ""){
201 $once =true;
202 $tmp = preg_replace("/^editZone_/","",$name);
203 $tmp = base64_decode(preg_replace("/_.*$/","",$tmp));
204 $this->dialog= new servdnseditZone($this->config,$this->dn,$this->Zones[$tmp]);
205 }
207 /* check posts for delete zone
208 */
209 if(preg_match("/^delZone_/",$name)&&!$once && chkacl($this->acl,"servdns") == ""){
211 $once =true;
212 $tmp = preg_replace("/^delZone_/","",$name);
213 $tmp = base64_decode(preg_replace("/_.*$/","",$tmp));
215 /* Initiate deletion
216 */
217 $this->RemoveZone($tmp);
218 }
219 }
221 if(isset($_GET['act']) && $_GET['act'] == "edit" && isset($_GET['id'])){
222 $id = base64_decode($_GET['id']);
223 if(isset($this->Zones[$id])){
224 $this->dialog= new servdnseditZone($this->config,$this->dn,$this->Zones[$id]);
225 }
226 }
228 /* Show dialog
229 */
230 if($this->dialog!= NULL){
231 $this->dialog->save_object();
232 $this->dialog->parent = $this;
233 return($this->dialog->execute());
234 }
236 /* Create Listbox with existing Zones
237 */
238 $ZoneList = new divSelectBox("dNSZones");
239 $ZoneList -> SetHeight(300);
241 /* Add entries to divlist
242 */
243 $editImg = "<input type='image' src='images/edit.png' name='editZone_%s'>
244 <input type='image' src='images/edittrash.png' name='delZone_%s'>";
245 foreach($this->Zones as $zone => $values ){
246 $link = "<a href='?plug=".$_GET['plug']."&act=edit&id=%s'>%s</a>";
247 $ZoneList->AddEntry(array(
248 array("string" => sprintf($link,base64_encode($zone),getNameFromMix($zone))),
249 array("string" => sprintf($link,base64_encode($zone),_("Reverse zone")." : ".getNameFromMix($values['ReverseZone']))),
250 array("string" => _("TTL")." : ".$values['sOAttl']),
251 array("string" => _("Class")." : ".$values['dNSClass']),
252 array("string" => str_replace("%s",base64_encode($zone),$editImg))
253 ));
254 }
256 $smarty->assign("servdnsACL",chkacl($this->acl,"servdns"));
258 /* Display tempalte
259 */
260 $smarty->assign("ZoneList",$ZoneList->DrawList());
261 $display.= $smarty->fetch(get_template_path('servdns.tpl', TRUE));
262 return($display);
263 }
266 /* Delete specified zone
267 */
268 function RemoveZone($id)
269 {
270 $zones = $this->getUsedZoneNames();
271 $rev ="";
273 if(isset($this->Zones[$id]['InitialReverseZone'])){
274 $rev = FlipIp(getNameFromMix($this->Zones[$id]['InitialReverseZone']));
275 }elseif(isset($this->Zones[$id]['ReverseZone'])){
276 $rev = FlipIp(getNameFromMix($this->Zones[$id]['ReverseZone']));
277 }
279 $zonename = "";
280 if(isset($this->Zones[$id]['InitialzoneName'])){
281 $zonename= getNameFromMix($this->Zones[$id]['InitialzoneName']);
282 }
284 $used = array();
286 /* Add Records which use this zoneName
287 */
288 if(isset($zones[$zonename])){
289 $used = array_merge($used,$zones[$zonename]);
290 }
292 /* Add Records which uses this reverse zone
293 */
294 if(isset($zones[$rev.".in-addr.arpa"])){
295 $used = array_merge($used,$zones[$rev.".in-addr.arpa"]);
296 }
298 /* There are still entries using this configuration
299 * Abort deletion
300 */
301 if(count($used)){
302 $i = 2;
303 $str ="";
304 foreach($used as $dn){
305 if($i > 0 ){
306 $i --;
307 $str.=$dn." ";
308 }
309 }
311 /* Only show 2 dns in the error message
312 */
313 if(count($used)> 2) {
314 $str .=" ... ";
315 }
316 print_red(sprintf(_("Can't delete the selected zone, because it is still in use by these entry/entries '%s'"),trim($str)));
318 }else{
319 unset($this->Zones[$id]);
320 return(true);
321 }
322 return(false);
323 }
326 /* This funtion returns all used Zonenames
327 */
328 function getUsedZoneNames()
329 {
330 $ret = array();
331 $ldap = $this->config->get_ldap_link();
332 $ldap->cd($this->config->current['BASE']);
333 $ldap->search("(&(objectClass=dNSZone)(!(relativeDomainName=@))(zoneName=*))",array("zoneName","relativeDomainName"));
334 while($attr = $ldap->fetch()){
335 $ret[$attr['zoneName'][0]][] = $attr['dn'];
336 }
337 return($ret);
338 }
342 /* Remove dns service
343 */
344 function remove_from_parent()
345 {
346 if($this->DNSinitially_was_account){
347 $this->is_account = FALSE;
348 $bool = true;
349 foreach($this->Zones as $key => $zone){
350 $bool= $bool & $this->RemoveZone($key);
351 }
353 if($bool){
354 $this->save();
355 }
356 return($bool);
357 }
358 }
362 /* Save to LDAP */
363 function save()
364 {
366 /* Take over handling
367 * - Create list of zones managed by source server
368 * - Copy ldap entries to destination server
369 * - Remove old zone entries from source
370 */
371 if($this->take_over_id != -1){
372 $del = array();
373 $id = $this->take_over_id;
374 $src = $this->dns_server_list['ENTRIES'][$id]['dn'];
375 $ldap = $this->config->get_ldap_link();
376 $ldap->ls("(objectClass=dnsZone)",$src,array('cn'));
377 while($attrs = $ldap->fetch()){
378 $src_zone = $attrs['dn'];
379 $dst_zone = preg_replace("/".normalizePreg($src)."$/",$this->dn,$src_zone);
380 $res = plugin::recursive_move($src_zone, $dst_zone);
382 if($res){
383 $del [] = $src_zone;
384 }
385 }
386 foreach($del as $src_zone){
387 $ldap->rmdir_recursive($src_zone);
388 }
389 return;
390 }
393 $ldap = $this->config->get_ldap_link();
394 $ldap->cd($this->config->current['BASE']);
396 /* Get differences
397 */
399 $old_dn = $this->orig_dn;
400 if($old_dn == "new"){
401 $old_dn = $this->dn;
402 }
404 /* Update dns to current object dn */
405 $tmp = getDNSZoneEntriesDiff($this->config,$this->Zones,$old_dn);
406 $tmp2 = array();
407 foreach($tmp as $key1 => $data1){
408 $tmp2[$key1] = array();
409 foreach($data1 as $key2 => $data2){
410 $tmp2[$key1][preg_replace("/".normalizePreg($old_dn)."$/",$this->dn,$key2)] = $data2;
411 }
412 }
413 $tmp = $tmp2;
415 /* Updated zone entries if reverser or forward name has changed
416 * Must be done before moving entries, else the given dn is invalid
417 */
418 if(isset($tmp['zoneUpdates'])){
419 foreach($tmp['zoneUpdates'] as $dn => $attrs){
420 $ldap->cd($dn);
421 $ldap->modify($attrs);
422 show_ldap_error("Zone:".$ldap->get_error(), _("Updating DNS service failed"));
423 }
424 }
426 /* Delete dns
427 */
428 foreach($tmp['del'] as $dn => $del){
429 $for = getNameFromMix($del['InitialzoneName']);
430 $rev = FlipIp(getNameFromMix($del['InitialReverseZone'])).".in-addr.arpa";
431 $ldap->cd($dn);
432 $ldap->rmdir_recursive($dn);
433 show_ldap_error($ldap->get_error(), _("Removing DNS entries failed"));
435 /* Handle Post events */
436 if(preg_match("/^zoneName=/",$dn)){
437 $this->handle_post_events("remove",array("dn" => $dn,"zoneName" => $for));
438 $this->handle_post_events("remove",array("dn" => $dn,"zoneName" => $rev));
439 }
440 }
442 /* move follwoing entries
443 */
444 foreach($tmp['move'] as $src => $dst){
445 $this->recursive_move($src,$dst);
446 }
448 /* Add || Update new DNS entries
449 */
450 foreach($tmp['add'] as $dn => $attrs){
451 $ldap->cd($dn);
452 $ldap->cat($dn, array('dn'));
453 if($ldap->count()){
454 $ldap->cd($dn);
455 $ldap->modify ($attrs);
456 show_ldap_error($ldap->get_error(), _("Saving DNS entries failed"));
458 /* Handle Post events */
459 if(preg_match("/^zoneName=/",$dn)){
460 $this->handle_post_events("modify",array("dn" => $dn,"zoneName" => $attrs['zoneName']));
461 }
462 }else{
463 $ldap->cd($dn);
464 $ldap->add($attrs);
465 show_ldap_error($ldap->get_error(), _("Saving DNS entries failed"));
467 /* Handle Post events */
468 if(preg_match("/^zoneName=/",$dn)){
469 $this->handle_post_events("add",array("dn" => $dn,"zoneName" => $attrs['zoneName']));
470 }
471 }
472 }
473 }
474 }
475 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
476 ?>