3
class servdnseditZone extends plugin
5
/* attribute list for save action */
6
var $ignore_account= TRUE;
7
var $attributes = array("zoneName","ReverseZone","dNSClass",
8
"sOAprimary","sOAmail","sOAserial","sOArefresh","sOAretry","sOAexpire","sOAttl");
9
var $objectclasses = array("whatever");
11
var $RecordTypes = array();
13
var $ReverseZone = "";
20
var $sOArefresh = "3600";
21
var $sOAretry = "1800";
22
var $sOAexpire = "720000";
25
var $Records = array();
26
var $mXRecords = array();
28
var $OldZoneName = ""; // To detect changes made with this edit
29
var $OldReverseZone = "";
31
var $InitialReverseZone = "";
32
var $InitialzoneName = "";
33
var $NetworkClass = "A" ; // One out of A,B,C
37
var $zoneEditor = NULL;
41
var $ZoneObject = array();
42
var $Zone_is_used = FALSE;
44
function servdnseditZone (&$config, $dn= NULL,$attrs = array())
46
plugin::plugin ($config, $dn);
48
/* All types with required attrs */
49
$this->RecordTypes = DNS::getDnsRecordTypes(true);
52
$this->OldZoneName = "";
53
$this->OldReverseZone = "";
55
$this->sOAserial = date("Ymd")."1";
57
$this->InitialzoneName = "";//$attrs['InitialzoneName'];
58
$this->InitialReverseZone = "";//$attrs['InitialReverseZone'];
60
$this->ZoneObject = $attrs;
62
if(isset($attrs['zoneEditor'])){
63
$this->zoneEditor = $attrs['zoneEditor'];
65
$this->OldZoneName = $attrs['zoneName'];
66
$this->OldReverseZone = $attrs['ReverseZone'];
68
$this->InitialzoneName = $attrs['InitialzoneName'];
69
$this->InitialReverseZone = $attrs['InitialReverseZone'];
73
foreach($this->attributes as $value){
74
$this->$value = $attrs[$value];
77
$this->sOAmail = preg_replace("/\./","@",$this->sOAmail,1);
78
$this->sOAmail = preg_replace("/\.$/","",$this->sOAmail);
79
$this->sOAprimary = preg_replace("/\.$/","",$this->sOAprimary);
80
$this->zoneName = preg_replace("/\.$/","",$this->zoneName);
82
if(isset($attrs['RECORDS'])){
83
$this->Records = $attrs['RECORDS'];
87
foreach($this->Records as $key => $rec){
88
if($rec['type'] == "mXRecord"){
89
$tmp = explode(" ",$rec['value']);
90
$rec['value'] = $rec['value'];
91
$tmp2[$tmp[0]] = $rec;
92
unset($this->Records[$key]);
94
if($rec['type'] == "nSRecord" && preg_match("/".preg_quote($this->sOAprimary, '/')."/",$rec['value'])){
95
unset($this->Records[$key]);
98
if(count($tmp2) != 0){
102
$this->mXRecords = $tmp2;
104
$this->mXRecords = array();
105
$this->Records = array();
109
if(preg_match("/^".$str."/",$this->sOAserial)){
110
$this->sOAserial = $this->sOAserial + 1;
112
$this->sOAserial = date("Ymd")."01";
115
/* Check if this used, in this case disable forward and reverse configuration */
116
$tmp = $this->getUsedZoneNames();
117
$this->Zone_is_used = FALSE;
118
if(isset($tmp[DNS::FlipIp($this->InitialReverseZone).".in-addr.arpa."])){
119
$this->Zone_is_used = TRUE;
123
/* Detect Network class */
124
if(!empty($this->ReverseZone)){
126
$dots = count(explode(".",$this->ReverseZone));
128
$this->NetworkClass = "A";
129
$this->ReverseZone .= ".0.0.0";
131
$this->NetworkClass = "B";
132
$this->ReverseZone .= ".0.0";
134
$this->NetworkClass = "C";
135
$this->ReverseZone .= ".0";
140
$this->mxList = new sortableListing();
141
$this->mxList->setDeleteable(true);
142
$this->mxList->setInstantDelete(true);
143
$this->mxList->setEditable(false);
144
$this->mxList->setWidth("100%");
145
$this->mxList->setHeight("100px");
146
$this->mxList->setHeader(array(_("Priority"),_("Record")));
147
$this->mxList->setColspecs(array('40px','*','20px'));
148
$this->mxList->setDefaultSortColumn(0);
155
/* Call parent execute */
158
/* Fill templating stuff */
159
$smarty= get_smarty();
161
$smarty->assign("Zone_is_used",$this->Zone_is_used);
162
$ui = get_userinfo();
165
All acls are defined in our parent class.
167
$tmp = $this->parent->plInfo();
168
foreach($tmp['plProvidedAcls'] as $name => $desc){
169
$smarty->assign($name."ACL", $this->parent->getacl($name));
174
/* Open Zone Entry Edit Dialog
176
if(!count($this->ZoneObject)){
177
$smarty->assign("AllowZoneEdit" , false);
179
$smarty->assign("AllowZoneEdit" , true);
181
if(isset($_POST['EditZoneEntries']) && $this->parent->acl_is_readable("zoneEditor")){
182
if($this->zoneEditor == NULL){
183
$this->zoneEditor= new servDNSeditZoneEntries($this->config,$this->dn,$this->ZoneObject);
184
$this->zoneEditor->acl = $this->parent->getacl("zoneEditor");
185
$this->zoneEditor->parent = $this;
187
$this->dialog = $this->zoneEditor;
191
/* Save Zone Entry Edit Dialog
193
if(isset($_POST['SaveZoneEntryChanges'])){
194
$this->dialog->save_object();
195
if(count($this->dialog->check())){
196
$msgs = $this->dialog->check();
197
foreach($msgs as $msg){
198
msg_dialog::display(_("Error"), $msg , ERROR_DIALOG);
201
$this->zoneEditor = clone $this->dialog;
202
$this->dialog = FALSE;
203
# $rev = DNS::FlipIp(DNS::getNameFromMix($this->InitialReverseZone)).".in-addr.arpa";
204
# $for = DNS::getNameFromMix($this->InitialzoneName);
206
# $this->parent->handle_post_events("modify",array("dn" => $this->dn,"zoneName" => $rev));
207
# $this->parent->handle_post_events("modify",array("dn" => $this->dn,"zoneName" => $for));
208
# $this->dialog = false;
212
/* Cancel Zone Entrie Edit Dialog
214
if(isset($_POST['CancelZoneEntryChanges'])){
215
$this->dialog = false;
218
/* Display any type of open dialogs
220
if(is_object($this->dialog)){
221
$this->dialog->save_object();
222
return($this->dialog->execute());
226
$this->mxList->save_object();
227
$action = $this->mxList->getAction();
228
if($action['action'] == 'delete' || $action['action'] == 'reorder'){
229
$this->mXRecords = $this->mxList->getMaintainedData();
232
if($this->parent->acl_is_writeable("mXRecord")){
233
if((isset($_POST['AddMXRecord'])) && (!empty($_POST['StrMXRecord']))){
234
$rec = get_post('StrMXRecord');
235
if(preg_match("/^[0-9]* /", $rec) && count(preg_split("/ /", $rec)) == 2){
236
list($prio,$value) = preg_split("/ /", $rec);
237
$this->mXRecords[$prio] = array("type"=>"mXRecord","value"=>trim($rec));
239
msg_dialog::display(_("Warning"), msgPool::invalid(_("MxRecord"), "","", "20 mx.record.entry"), WARNING_DIALOG);
243
/* Handle Post events */
245
foreach($_POST as $name => $value){
247
/* Delete record if requested */
248
if((preg_match("/RemoveRecord_/",$name))&&($once)){
250
$id= preg_replace("/RemoveRecord_/","",$name);
251
unset($this->Records[$id]);
255
/* Add new Zonerecord */
256
if(isset($_POST['AddNewRecord'])){
257
$this->Records[] = array("type"=>"aRecord","value"=>"");
262
foreach($this->attributes as $name){
263
$smarty->assign($name, set_post($this->$name));
267
$this->mxList->setAcl($this->parent->getacl("mXRecord"));
269
foreach($this->mXRecords as $key => $record){
270
list($prio, $value) = preg_split("/ /", $record['value']);
271
$lData[$prio] = array('data'=>array($prio, $value));
273
$this->mxList->setListData($this->mXRecords, $lData);
274
$this->mxList->update();
276
/* Assign records list */
277
$smarty->assign("NotNew", false);
278
$smarty->assign("Mxrecords", $this->mxList->render());
279
$smarty->assign("records" , $this->generateRecordsList());
280
$smarty->assign("NetworkClass", set_post($this->NetworkClass));
281
$smarty->assign("NetworkClasses", array("A"=>"255.0.0.0 (Class A)","B"=>"255.255.0.0 (Class B)","C"=>"255.255.255.0 (Class C)"));
283
/* Display tempalte */
284
$display.= $smarty->fetch(get_template_path('servdnseditzone.tpl', TRUE, dirname(__FILE__)));
288
function remove_from_parent()
292
/* Save data to object */
293
function save_object()
295
plugin::save_object();
297
if(!is_object($this->parent)) return;
299
if($this->parent->acl_is_writeable("zoneRecords")){
300
foreach($this->Records as $id => $value){
301
if(isset($_POST['RecordTypeSelectedFor_'.$id])){
302
$this->Records[$id]['type'] = get_post('RecordTypeSelectedFor_'.$id);
304
if(isset($_POST['RecordValue_'.$id])){
305
$this->Records[$id]['value'] = get_post('RecordValue_'.$id);
309
if(isset($_POST['NetworkClass']) && !$this->Zone_is_used && $this->parent->acl_is_writeable("NetworkClass")){
310
$this->NetworkClass = get_post('NetworkClass');
315
/* Check supplied data */
318
/* Call common method to give check the hook */
319
$message= plugin::check();
321
/* Check if zoneName is already in use */
322
$usedZones = $this->getUsedZoneNames();
323
if($this->OldZoneName == "" && !empty($this->zoneName)){
324
$tmp = trim($this->zoneName,".").".";
325
if(isset($usedZones[$tmp])){
326
$message[] = msgPool::duplicated(_("Zone name"));
330
if(empty($this->zoneName)){
331
$message[] = msgPool::required(_("Zone name"));
334
if(empty($this->ReverseZone)){
335
$message[] = msgPool::required(_("Reverse zone"));
338
if($this->zoneName != strtolower($this->zoneName)){
339
$message[] = msgPool::invalid(_("Zone name"),"","",_("Only lowercase allowed"));
342
if(!is_numeric($this->sOAserial)){
343
$message[] = msgPool::invalid(_("Serial"),$this->sOAserial,"/[0-9]/");
346
if(!is_numeric($this->sOArefresh)){
347
$message[] = msgPool::invalid(_("Refresh"),$this->sOArefresh,"/[0-9]/");
350
if(!is_numeric($this->sOAttl)){
351
$message[] = msgPool::invalid(_("Time to life"),$this->sOAttl,"/[0-9]/");
354
if(!is_numeric($this->sOAexpire)){
355
$message[] = msgPool::invalid(_("Expire"),$this->sOAexpire,"/[0-9]/");
358
if(!is_numeric($this->sOAretry)){
359
$message[] = msgPool::invalid(_("Retry"),$this->sOAretry,"/[0-9]/");
362
foreach($this->Records as $name => $values){
363
/* only lower-case is allowed in record entries ... */
364
if($values['value'] != strtolower($values['value'])){
365
$message[] = msgPool::invalid($values['type'],"","",_("Only lowercase allowed"));
369
/* Check class for given Zone Address */
370
$addr = preg_replace("/^[^\/]*+\//","",$this->ReverseZone);
372
/* Check for valid&complete IP address */
373
if(!tests::is_ip($addr)){
374
$message[] = msgPool::invalid(_("Network address"));
377
// Ensure that we do not use reverse zones twice.
378
// this currently not supported by GOsa.
379
$zones = DNS::getDNSZoneEntries($this->config,$this->dn);
380
switch($this->NetworkClass){
381
case 'C' : $test = preg_replace("/\.[0-9]*$/","",$this->ReverseZone);break;
382
case 'B' : $test = preg_replace("/\.[0-9]*\.[0-9]*$/","",$this->ReverseZone);break;
383
case 'A' : $test = preg_replace("/\.[0-9]*\.[0-9]*\.[0-9]*$/","",$this->ReverseZone);break;
384
default : trigger_error("Invalid network class given '".$this->NetworkClass."'");
386
foreach($zones as $name => $data){
387
if($data['ReverseZone'] == $test && $data['zoneName'] != $this->InitialzoneName){
388
$message[] = msgPool::duplicated(_("Network address"));
392
/* Check if given address matches selected network class */
393
switch($this->NetworkClass){
395
if(!preg_match("/^[0-9]*\.0\.0\.0$/",$addr)){
396
$message[] = sprintf(_("The specified network address and the network class (%s/%s) do not match!"), $this->NetworkClass, "255.0.0.0");
401
if(!preg_match("/^[0-9]*\.[0-9]*\.0\.0$/",$addr)){
402
$message[] = sprintf(_("The specified network address and the network class (%s/%s) do not match!"), $this->NetworkClass, "255.255.0.0");
407
if(!preg_match("/^[0-9]*\.[0-9]*\.[0-9]*\.0$/",$addr)){
408
$message[] = sprintf(_("The specified network address and the network class (%s/%s) do not match!"), $this->NetworkClass, "255.255.255.0");
412
default : $message[] = msgPool::invalid(_("Network class"),$this->NetworkClass);
419
/* This funtion returns all used Zonenames
421
function getUsedZoneNames()
424
$ldap = $this->config->get_ldap_link();
425
$ldap->cd($this->config->current['BASE']);
426
$ldap->search("(&(objectClass=dNSZone)(!(relativeDomainName=@))(zoneName=*))",array("zoneName","relativeDomainName"));
427
while($attr = $ldap->fetch()){
428
$ret[$attr['zoneName'][0]][] = $attr['dn'];
438
foreach($this->attributes as $name){
439
$ret[$name] = $this->$name;
444
foreach($this->mXRecords as $key => $rec){
445
$this->Records[] = $rec;
448
$ret['RECORDS'] = $this->Records;
450
switch($this->NetworkClass){
451
case 'C' : $ret['ReverseZone']= preg_replace("/\.[0-9]*$/","",$this->ReverseZone);break;
452
case 'B' : $ret['ReverseZone']= preg_replace("/\.[0-9]*\.[0-9]*$/","",$this->ReverseZone);break;
453
case 'A' : $ret['ReverseZone']= preg_replace("/\.[0-9]*\.[0-9]*\.[0-9]*$/","",$this->ReverseZone);break;
454
default : trigger_error("Invalid network class given '".$this->NetworkClass."'");
457
$ret['InitialReverseZone']= $this->InitialReverseZone;
458
$ret['InitialzoneName'] = $this->InitialzoneName;
460
$ret['sOAmail'] = preg_replace("/\@/",".",$this->sOAmail);
462
foreach(array("sOAprimary","zoneName","sOAmail") as $attr){
464
// Append trailing dots if we've full qualified host names.
465
if(!preg_match("/\.$/",$ret[$attr])){
466
if(!tests::is_ip($ret[$attr]) && preg_match("/\./",$ret[$attr])){
467
$ret[$attr] = $ret[$attr].".";
472
$ret['RECORDS'][] = array("type" => "nSRecord","value" => $ret['sOAprimary']) ;
474
$ret['zoneEditor'] = $this->zoneEditor;
479
/* This function generate a table row for each used record.
480
This table row displays the recordtype in a select box
481
and the specified value for the record, and a remove button.
482
The last element of the table also got an 'add' button.
484
function generateRecordsList($changeStateForRecords="")
486
$changeStateForRecords = "";
488
$str = "<table summary=''>";
489
foreach($this->Records as $key => $entry){
491
if($entry['type'] == "mXRecord") continue;
493
$changeStateForRecords.= "changeState('RecordTypeSelectedFor_".$key."');\n";
494
$changeStateForRecords.= "changeState('RecordValue_".$key."');\n";
495
$changeStateForRecords.= "changeState('RemoveRecord_".$key."');\n";
499
" <td>".$this->generateRecordListBox($entry['type'],"RecordTypeSelectedFor_".$key)."</td>".
501
" <input type='text' value='".$entry['value']."' ".
502
" name='RecordValue_".$key."' id='RecordValue_".$key."'>".
505
" <button type='submit' name='RemoveRecord_".$key."' id='RemoveRecord_".$key."'>"._("Delete")."</button>".
512
" <td colspan=2></td><td>".
513
" <button type='submit' name='AddNewRecord'>"._("Add")."</button>".
520
/* This function generates a select box out of $this->RecordTypes options.
521
The Parameter $selected is used to predefine an attribute.
522
$name is used to specify a post name
524
function generateRecordListBox($selected,$name)
526
$str = "<select name='".$name."' id='".$name."'>";
527
foreach($this->RecordTypes as $type => $value){
529
if(preg_match("/^mXRecord$/i",$value)) continue;
532
if($type == $selected){
535
$str.="\n <option value='".$type."' ".$use.">".strtoupper(preg_replace("/record/i","",$type))."</option>";
542
function acl_is_writeable($attribute,$skip_write = FALSE)
544
if($this->read_only) return(FALSE);
546
return preg_match('/w/', $ui->get_permissions($this->acl_base, $this->acl_category."servdns", $attribute, $skip_write));
550
// vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler: