d2779828baf2f93336700ad7d20bd8e13a9e1d8b
1 <?php
3 class servdns extends goService
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();
13 var $orig_dn = "";
15 var $initially_was_account;
17 /* ServerService tab vars */
18 var $conflicts = array("servdns");
19 var $DisplayName = "";
20 var $StatusFlag = "";
21 var $view_logged = FALSE;
23 var $dns_server_list = array("ENTRIES"=> array(),"FOR_LIST"=> array());
24 var $take_over_id = -1;
27 function servdns (&$config, $dn= NULL, $parent= NULL)
28 {
29 plugin::plugin ($config, $dn, $parent);
31 $this->DisplayName = _("DNS service");
33 $this->orig_dn = $dn;
35 /* Get record types for zones
36 */
37 $this->RecordTypes = DNS::getDnsRecordTypes(true);
39 /* Get all zone Informations
40 */
41 $this->Zones = DNS::getDNSZoneEntries($config,$dn);
43 /* If there is at least one entry in this -> types, we have DNS enabled
44 */
45 if(count($this->Zones) == 0){
46 $this->is_account = false;
47 $this->dns_server_list = $this->get_list_of_dns_servers();
48 }else{
49 $this->is_account = true;
50 }
51 $this->initially_was_account = $this->is_account;
52 }
55 function get_list_of_dns_servers()
56 {
57 $ret = array("ENTRIES"=> array(),"FOR_LIST"=> array());
58 $ldap = $this->config->get_ldap_link();
59 $ldap->cd($this->config->current['BASE']);
60 $ldap->search("(&(objectClass=dNSZone)(zoneName=*))",array("dn","zoneName"));
61 $dns = array();
62 while($attrs = $ldap->fetch()){
63 /* Skip own config */
64 if($this->dn != "new" && preg_match("/".normalizePreg($this->dn)."$/",$attrs['dn'])){
65 continue;
66 }
67 $dn = preg_replace("/^zoneName=[^,]+,/","",$attrs['dn']);
68 if(preg_match("/^cn=/",$dn) && !in_array($dn,$dns)){
69 $dns[] = $dn;
70 }
71 }
72 $i = 0;
73 foreach($dns as $dn){
74 $ldap->cat($dn,array('*'));
75 if($ldap->count()){
76 $i ++;
77 $attrs = $ldap->fetch();
78 $ret['ENTRIES'][$i] = $attrs;
79 $ret['FOR_LIST'][$i] = $attrs['cn'][0];
80 }
81 }
82 return($ret);
83 }
86 function get_dns_info_string($id)
87 {
88 $ret="";
89 $ldap = $this->config->get_ldap_link();
90 $ldap->cd($this->dns_server_list['ENTRIES'][$id]['dn']);
91 $ldap->search("(|(zoneName=*)(relativeDomainName=*))",array("dn"));
92 while($attrs = $ldap->fetch()){
93 $ret .= $attrs['dn']."\n";
94 }
95 return($ret);
96 }
99 function execute()
100 {
101 /* Call parent execute
102 */
103 plugin::execute();
105 if($this->is_account && !$this->view_logged){
106 $this->view_logged = TRUE;
107 new log("view","server/".get_class($this),$this->dn);
108 }
110 /* Fill templating stuff
111 */
112 $smarty= get_smarty();
113 $smarty->assign("dns_take_over",FALSE);
114 $smarty->assign("is_createable",$this->acl_is_createable());
115 $display= "";
118 $this->initially_was_account= $this->is_account;
119 /*****************/
120 /* Handle Take Over Actions
121 /*****************/
123 /* Give smarty the required informations */
124 $smarty->assign("dns_server_list", $this->dns_server_list['FOR_LIST']);
125 $smarty->assign("dns_server_list_cnt", count($this->dns_server_list['FOR_LIST']));
127 /* Take over requested, save id */
128 if(isset($_POST['take_over_src']) && isset($_POST['take_over'])){
129 $id = $_POST['take_over_src'];
130 if(isset($this->dns_server_list['ENTRIES'][$id])){
131 $this->take_over_id = $id;
132 }
133 }
135 /* Abort take over action */
136 if(isset($_POST['cancel_take_over'])){
137 $this->dialog =false;
138 $this->take_over_id = -1;
139 $this->dns_server_list = $this->get_list_of_dns_servers();
140 }
142 /* Display informartion about take over that will be started when saving this server
143 * and hide default dns output
144 */
145 if($this->take_over_id != -1){
146 $this->dialog = FALSE;
147 $id = $this->take_over_id;
148 $info = $this->get_dns_info_string($id);
149 $smarty->assign("dns_take_over",TRUE);
150 $smarty->assign("info",$info);
151 $warning = sprintf(_("You are going to migrate the DNS setup from server '%s'."),$this->dns_server_list['ENTRIES'][$id]['cn'][0]);
152 $warning2 = _("The migration will be started when you save this system. To cancel this action, use the cancel button below.");
153 $smarty->assign("warning",$warning);
154 $smarty->assign("warning2",$warning2);
155 return($smarty->fetch(get_template_path('servdns.tpl', TRUE, dirname(__FILE__))));
156 }
159 /* Do we need to flip is_account state?
160 */
161 if (isset($_POST['modify_state'])){
162 $this->is_account= !$this->is_account;
163 }
165 if ($this->is_account){
166 $display= $this->show_disable_header(_("Remove DNS service"),
167 _("This server has DNS features enabled. You can disable them by clicking below."));
168 } else {
169 $display= $this->show_enable_header(_("Add DNS service"),
170 _("This server has DNS features disabled. You can enable them by clicking below."));
171 return ($display);
172 }
175 /* Edited or Added zone
176 */
177 if(isset($_POST['SaveZoneChanges'])){
178 $this->dialog->save_object();
180 /* Check for errors
181 */
182 if(count($this->dialog->check())){
183 foreach($this->dialog->check() as $msgs){
184 msg_dialog::display(_("Error"), $msgs, ERROR_DIALOG);
185 }
186 }else{
187 /* add new/edited zone
188 */
189 $ret = $this->dialog->save();
190 if(!$this->dialog->isNew){
191 unset($this->Zones[$this->dialog->OldZoneName]);
192 }
193 $this->Zones[$ret['zoneName']] = $ret;
194 $this->dialog = FALSE;
195 }
196 }
198 /* Cancel zone edit / new
199 */
200 if(isset($_POST['CancelZoneChanges'])){
201 $this->dialog = FALSE;
202 }
204 /* Add empty new zone
205 */
206 if(isset($_POST['AddZone'])){
207 $this->dialog = new servdnseditZone($this->config,$this->dn);
208 }
210 /* Check for edit zone request
211 */
212 $once = false;
213 foreach( $_POST as $name => $value){
215 /* check all post for edit request
216 */
217 if(preg_match("/^editZone_/",$name)&&!$once){
218 $once =true;
219 $tmp = preg_replace("/^editZone_/","",$name);
220 $tmp = base64_decode(preg_replace("/_.*$/","",$tmp));
221 $this->dialog= new servdnseditZone($this->config,$this->dn,$this->Zones[$tmp]);
222 }
224 /* check posts for delete zone
225 */
226 if(preg_match("/^delZone_/",$name)&&!$once){
228 $once =true;
229 $tmp = preg_replace("/^delZone_/","",$name);
230 $tmp = base64_decode(preg_replace("/_.*$/","",$tmp));
232 /* Initiate deletion
233 */
234 $this->RemoveZone($tmp);
235 }
236 }
238 if(isset($_GET['act']) && $_GET['act'] == "edit" && isset($_GET['id'])){
239 $id = base64_decode($_GET['id']);
240 if(isset($this->Zones[$id])){
241 $this->dialog= new servdnseditZone($this->config,$this->dn,$this->Zones[$id]);
242 }
243 }
245 if(isset($_GET['act']) && $_GET['act'] == "edit" && isset($_GET['id'])){
246 $id = base64_decode($_GET['id']);
247 if(isset($this->Zones[$id])){
248 $this->dialog= new servdnseditZone($this->config,$this->dn,$this->Zones[$id]);
249 }
250 }
252 /* Show dialog
253 */
254 if(is_object($this->dialog)){
255 $this->dialog->save_object();
256 $this->dialog->parent = $this;
257 return($this->dialog->execute());
258 }
260 /* Create Listbox with existing Zones
261 */
262 $ZoneList = new divSelectBox("dNSZones");
263 $ZoneList -> SetHeight(254);
265 /* Add entries to divlist
266 */
267 $editImg = "<input type='image' src='images/lists/edit.png' name='editZone_%s'>";
268 if($this->acl_is_removeable()){
269 $editImg.= "<input type='image' src='images/lists/trash.png' name='delZone_%s'>";
270 }
272 $link = "<a href='?plug=".$_GET['plug']."&act=edit&id=%s'>%s</a>";
273 foreach($this->Zones as $zone => $values ){
274 $ZoneList->AddEntry(array(
275 array("string" => sprintf($link,base64_encode($zone),($zone))),
276 array("string" => sprintf($link,base64_encode($zone),_("Reverse zone")." : ".($values['ReverseZone']))),
277 array("string" => _("TTL")." : ".$values['sOAttl']),
278 array("string" => _("Class")." : ".$values['dNSClass']),
279 array("string" =>str_replace("%s",base64_encode($zone),$editImg))
280 ));
281 }
283 /* Display tempalte
284 */
285 $smarty->assign("ZoneList",$ZoneList->DrawList());
286 $display.= $smarty->fetch(get_template_path('servdns.tpl', TRUE, dirname(__FILE__)));
287 return($display);
288 }
291 /* Delete specified zone
292 */
293 function RemoveZone($id)
294 {
295 $zones = $this->getUsedZoneNames();
297 if(isset($this->Zones[$id]['InitialReverseZone'])){
298 $rev = DNS::FlipIp($this->Zones[$id]['InitialReverseZone']);
299 }else{
300 $rev = DNS::FlipIp($this->Zones[$id]['ReverseZone']);
301 }
303 $zonename = "";
304 if(isset($this->Zones[$id]['InitialzoneName'])){
305 $zonename= $this->Zones[$id]['InitialzoneName'];
306 }
308 $used = array();
310 /* Add Records which use this zoneName
311 */
312 if(isset($zones[$zonename])){
313 $used = array_merge($used,$zones[$zonename]);
314 }
316 /* Add Records which uses this reverse zone
317 */
318 if(isset($zones[$rev.".in-addr.arpa"])){
319 $used = array_merge($used,$zones[$rev.".in-addr.arpa"]);
320 }
322 /* There are still entries using this configuration
323 * Abort deletion
324 */
325 if(count($used)){
326 $i = 2;
327 $str ="";
328 foreach($used as $dn){
329 if($i > 0 && !preg_match("/,relativeDomainName=/",$dn)){
330 $i --;
331 $name = preg_replace("/^[^=]+=([^,]*),.*$/","\\1",$dn);
332 $zone = preg_replace("/^.*zoneName=([^,]*),.*$/","\\1",$dn);
333 $str.= $name.".".$zone." ";
334 }
335 }
337 /* Only show 2 dns in the error message
338 */
339 if(count($used)> 2) {
340 $str .=" ... ";
341 }
342 msg_dialog::display(_("Error"), sprintf(_("Cannot delete the selected zone. It is still in use by '%s'"), trim($str)), ERROR_DIALOG);
343 return(false);
344 }else{
345 unset($this->Zones[$id]);
346 return(true);
347 }
348 }
351 /* This funtion returns all used Zonenames
352 */
353 function getUsedZoneNames()
354 {
355 $ret = array();
356 $ldap = $this->config->get_ldap_link();
357 $ldap->cd($this->config->current['BASE']);
358 $ldap->search("(&(objectClass=dNSZone)(!(relativeDomainName=@))(zoneName=*))",array("zoneName","relativeDomainName"));
359 while($attr = $ldap->fetch()){
360 $ret[$attr['zoneName'][0]][] = $attr['dn'];
361 }
362 return($ret);
363 }
366 /* Remove dns service
367 */
368 function remove_from_parent()
369 {
370 if($this->initially_was_account){
371 $bool = true;
372 $this->is_account = FALSE;
373 foreach($this->Zones as $key => $zone){
374 $bool= $bool & $this->RemoveZone($key);
375 }
377 if($bool){
378 $this->save();
379 }
380 return($bool);
381 }
382 }
385 /* Save to LDAP */
386 function save()
387 {
389 /* Take over handling
390 * - Create list of zones managed by source server
391 * - Copy ldap entries to destination server
392 * - Remove old zone entries from source
393 */
394 if($this->take_over_id != -1){
395 $del = array();
396 $id = $this->take_over_id;
397 $src = $this->dns_server_list['ENTRIES'][$id]['dn'];
398 $ldap = $this->config->get_ldap_link();
399 $ldap->ls("(objectClass=dnsZone)",$src,array('cn'));
400 while($attrs = $ldap->fetch()){
401 $src_zone = $attrs['dn'];
402 $dst_zone = preg_replace("/".normalizePreg($src)."$/",$this->dn,$src_zone);
403 $res = plugin::recursive_move($src_zone, $dst_zone);
405 if($res){
406 $del [] = $src_zone;
407 }
408 }
409 foreach($del as $src_zone){
410 $ldap->rmdir_recursive($src_zone);
411 }
412 return;
413 }
415 /* Save zone editor changes now */
416 foreach($this->Zones as $name => $zone){
417 if(isset($zone['zoneEditor'] ) && $zone['zoneEditor'] != NULL && is_object($zone['zoneEditor'])){
418 $zone['zoneEditor']->save();
419 unset($this->Zones[$name]['zoneEditor']);;
420 }
421 }
423 $ldap = $this->config->get_ldap_link();
424 $ldap->cd($this->config->current['BASE']);
426 /* Get differences
427 */
428 $old_dn = $this->orig_dn;
429 if($old_dn == "new"){
430 $old_dn = $this->dn;
431 }
433 /* Update dns to current object dn */
434 $tmp = DNS::getDNSZoneEntriesDiff($this->config,$this->Zones,$old_dn);
435 $tmp2 = array();
436 foreach($tmp as $key1 => $data1){
437 $tmp2[$key1] = array();
438 foreach($data1 as $key2 => $data2){
439 $tmp2[$key1][preg_replace("/".normalizePreg($old_dn)."$/",$this->dn,$key2)] = $data2;
440 }
441 }
442 $tmp = $tmp2;
444 /* Updated zone entries if reverser or forward name has changed
445 * Must be done before moving entries, else the given dn is invalid
446 */
447 if(isset($tmp['zoneUpdates'])){
448 foreach($tmp['zoneUpdates'] as $dn => $attrs){
449 $ldap->cd($dn);
450 $ldap->modify($attrs);
451 new log("modify","unknown/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
452 if (!$ldap->success()){
453 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
454 }
455 }
456 }
458 /* Delete dns
459 */
460 foreach($tmp['del'] as $dn => $del){
462 $for = $del['InitialzoneName'];
463 $rev = DNS::FlipIp($del['InitialReverseZone']).".in-addr.arpa";
465 $ldap->cd($dn);
466 $ldap->rmdir_recursive($dn);
467 new log("remove","unknown/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
468 if (!$ldap->success()){
469 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
470 }
472 /* Handle Post events */
473 if(preg_match("/^zoneName=/",$dn)){
474 # $this->handle_post_events("remove",array("dn" => $dn,"zoneName" => $for));
475 # $this->handle_post_events("remove",array("dn" => $dn,"zoneName" => $rev));
476 }
477 }
479 /* move follwoing entries
480 */
481 foreach($tmp['move'] as $src => $dst){
482 $this->recursive_move($src,$dst);
483 }
485 /* Add || Update new DNS entries
486 */
487 foreach($tmp['add'] as $dn => $attrs){
488 $ldap->cd($dn);
489 $ldap->cat($dn, array('dn'));
490 if($ldap->fetch()){
491 $ldap->cd($dn);
492 $ldap->modify ($attrs);
493 if (!$ldap->success()){
494 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
495 }
497 /* Handle Post events */
498 if(preg_match("/^zoneName=/",$dn)){
499 # $this->handle_post_events("modify",array("dn" => $dn,"zoneName" => $attrs['zoneName']));
500 }
501 }else{
502 $ldap->cd($dn);
503 $ldap->add($attrs);
504 if (!$ldap->success()){
505 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_ADD, get_class()));
506 }
508 /* Handle Post events */
509 if(preg_match("/^zoneName=/",$dn)){
510 # $this->handle_post_events("add",array("dn" => $dn,"zoneName" => $attrs['zoneName']));
511 }
512 }
513 }
514 $this->handle_post_events("modify");
515 }
518 /* Directly save new status flag */
519 function setStatus($value)
520 {
521 if($value == "none") return;
522 if(!$this->initially_was_account) return;
523 if(empty($this->StatusFlag)) return;
524 $ldap = $this->config->get_ldap_link();
525 $ldap->cd($this->dn);
526 $ldap->cat($this->dn,array("objectClass"));
527 if($ldap->count()){
529 $tmp = $ldap->fetch();
530 for($i = 0; $i < $tmp['objectClass']['count']; $i ++){
531 $attrs['objectClass'][] = $tmp['objectClass'][$i];
532 }
533 $flag = $this->StatusFlag;
534 $attrs[$flag] = $value;
535 $this->$flag = $value;
536 $ldap->modify($attrs);
537 if (!$ldap->success()){
538 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
539 }
540 $this->action_hook();
541 }
542 }
545 function getListEntry()
546 {
547 $fields = goService::getListEntry();
548 $fields['Message'] = _("DNS service");
549 $fields['AllowEdit'] = true;
550 return($fields);
551 }
554 /* Get updates for status flag */
555 function updateStatusState()
556 {
557 if(empty($this->StatusFlag)) return;
559 $attrs = array();
560 $flag = $this->StatusFlag;
561 $ldap = $this->config->get_ldap_link();
562 $ldap->cd($this->cn);
563 $ldap->cat($this->dn,array($flag));
564 if($ldap->count()){
565 $attrs = $ldap->fetch();
566 }
567 if(isset($attrs[$flag][0])){
568 $this->$flag = $attrs[$flag][0];
569 }
570 }
573 /* Return plugin informations for acl handling */
574 static function plInfo()
575 {
576 return (array(
577 "plShortName" => _("DNS service"),
578 "plDescription" => _("DNS service")." ("._("Services").")",
579 "plSelfModify" => FALSE,
580 "plDepends" => array(),
581 "plPriority" => 83,
582 "plSection" => array("administration"),
583 "plCategory" => array("server"),
585 "plProvidedAcls"=> array(
586 "zoneName" =>_("Zone name"),
587 "ReverseZone" =>_("Reverse zone"),
588 "sOAprimary" =>_("Primary dns server"),
589 "sOAmail" =>_("Mail address"),
590 "sOAserial" =>_("Serial"),
591 "sOArefresh" =>_("Refresh"),
592 "sOAretry" =>_("Retry"),
593 "sOAexpire" =>_("Expire"),
594 "sOAttl" =>_("TTL"),
595 "zoneRecords" =>_("Zone records"))
596 ));
597 }
599 }
600 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
601 ?>