[gosa.git] / gosa-plugins / dns / admin / systems / services / dns / class_servDNSeditZoneEntries.inc
1 <?php
3 class servDNSeditZoneEntries extends plugin
4 {
5 /* attribute list for save action */
6 var $ignore_account = TRUE;
7 var $attributes = array();
8 var $objectclasses = array("whatever");
10 var $Devices = array();
12 var $zoneName = ""; // ZoneName of currently edited Zone
13 var $reverseName = ""; // ReverseZone of the currently edited Zone
15 var $RecordTypes = array(); // Possible record type.
17 var $disableDialog = false; // Dialog will be disabled, if this zone is new
20 function servDNSeditZoneEntries (&$config,$dn, &$zoneObject)
21 {
22 plugin::plugin ($config, $dn);
24 /* Initialise class
25 */
26 $this->RecordTypes = DNS::getDnsRecordTypes();
27 $this->dn = "zoneName=".$zoneObject['InitialzoneName'].",".$dn;
28 $this->zoneName = $zoneObject['InitialzoneName'];
29 $this->reverseName = $zoneObject['InitialReverseZone'];
31 /* Remove nSRecord from listed types */
32 if(isset($this->RecordTypes['nSRecord'])){
33 unset($this->RecordTypes['nSRecord']);
34 }
35 /* Remove nSRecord from listed types */
36 if(isset($this->RecordTypes['pTRRecord'])){
37 unset($this->RecordTypes['pTRRecord']);
38 }
40 /* Get ldap connection
41 */
42 $ldap = $this->config->get_ldap_link();
43 $ldap->cd($this->config->current['BASE']);
45 /* Get zone content
46 */
47 $ldap->ls("(&(objectClass=dNSZone)(!(relativeDomainName=@)))",$this->dn,array("relativeDomainName"));
49 while($attrs = $ldap->fetch()){
50 $this->Devices[$attrs['relativeDomainName'][0]] = DNS::getDNSHostEntries($config,$attrs['relativeDomainName'][0],true);
51 $this->Devices[$attrs['relativeDomainName'][0]]['OrigCn'] = $attrs['relativeDomainName'][0];
52 }
54 $ldap->cat($this->dn,array("objectClass"));
56 $this->disableDialog = true;
57 if(count($this->Devices)|| $ldap->count()){
58 $this->disableDialog = false;
59 }
60 }
62 function execute()
63 {
64 plugin::execute();
66 /* Fill templating stuff */
67 $smarty= get_smarty();
68 $display= "";
70 $table = "";
71 foreach($this->Devices as $key => $dev){
72 $table .= $this->generateRecordConfigurationRow($key);
73 }
75 $smarty->assign("disableDialog",$this->disableDialog);
76 $smarty->assign("table",$table);;
77 $display.= $smarty->fetch(get_template_path('servDNSeditZoneEntries.tpl', TRUE, dirname(__FILE__)));
78 return($display);
79 }
82 function save_object()
83 {
84 /* Check posts for operations ...
85 */
86 $once = true;
87 $ptr_updates = array();
88 foreach($_POST as $name => $value){
90 /* Add a new Record in given object
91 */
93 $tmp = preg_replace("/^.*_(.*)_.*$/","\\1",$name);
94 $tmp2 = split("\|",$tmp);
96 /* Add new host entry
97 */
98 if((preg_match("/^UserRecord_?/",$name)) && ($once)){
99 $once = false;
100 $entry = DNS::getDNSHostEntries($this->config,"",true);
101 $entry['exists'] = true;
102 $entry['zoneName'] = strtoupper($this->attrs['cn'][0])."/".$this->zoneName;
103 $entry['RECORDS'][] = array("type" => "aRecord" , "value"=>"");
104 $this->Devices[_("New entry")] = $entry;
105 }
107 if(count($tmp2) != 2) continue;
109 $Name = base64_decode($tmp2[0]);
110 $RecordID = $tmp2[1];
112 /* Add new REcord
113 */
114 if((preg_match("/^AddRecord_/",$name)) && ($once)){
115 $once = false;
116 $this->Devices[$Name]['RECORDS'][] = $this->Devices[$Name]['RECORDS'][$RecordID];
117 }
119 /* Remove record from given dn
120 */
121 if((preg_match("/^RemoveRecord_/",$name)) && ($once)){
122 $once = false;
123 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
124 unset($this->Devices[$Name]['RECORDS'][$RecordID]);
125 }
127 /* Check if there is at least one visible record. Else remove complete entry */
128 $visible = false;
129 foreach($this->Devices[$Name]['RECORDS'] as $rec){
130 if(in_array($rec['type'],$this->RecordTypes)){
131 $visible = true;
132 break;
133 }
134 }
135 if(!$visible && isset($this->Devices[$Name]['RECORDS'])){
136 $this->Devices[$Name]['RECORDS'] = array();
137 }
138 }
139 }
141 /* Possible attributes posted
142 */
143 foreach($_POST as $name => $value){
145 /* Extract informations out of post name
146 */
147 $tmp = preg_replace("/^.*_/","\\1",$name);
148 $tmp2 = split("\|",$tmp);
150 if(count($tmp2) != 2) continue;
152 $Name = base64_decode($tmp2[0]);
153 $RecordID = $tmp2[1];
155 /* Check for value change
156 */
157 if(preg_match("/ValueSelection_/",$name)){
158 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
160 /* Update value */
161 $old = $this->Devices[$Name]['RECORDS'][$RecordID]['value'];
162 $this->Devices[$Name]['RECORDS'][$RecordID]['value'] = $value;
164 /* Handle pTRRecord */
165 if(!isset($ptr_updates[$Name]) && $this->Devices[$Name]['RECORDS'][$RecordID]['type'] == "aRecord"){
167 $found = false;
168 $ip = $value;
169 $match = preg_replace("/^[^\/]*+\//","",$this->reverseName);
170 $ip = preg_replace("/^".normalizePreg($match)."/","",$ip);
171 $ip = preg_replace("/^\./","",$ip);
173 foreach($this->Devices[$Name]['RECORDS'] as $key => $dev){
174 if($dev['type'] == "pTRRecord"){
175 $ptr_updates[$Name] = $Name;
176 $this->Devices[$Name]['RECORDS'][$key]['value'] = $ip;
177 $found = true;
178 break;
179 }
180 }
181 if(!$found){
182 $dev = array('type'=> 'pTRRecord', 'value' => $ip);
183 $this->Devices[$Name]['RECORDS'][] = $dev;
184 }
185 }
186 }
187 }
189 /* record type changed
190 */
191 if(preg_match("/^RecordTypeSelection_/",$name)){
192 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
193 $this->Devices[$Name]['RECORDS'][$RecordID]['type'] = $value;
194 }
195 }
196 }
198 /* check for renamed entries
199 */
200 foreach($_POST as $name => $value){
202 /* Extract informations out of post name
203 */
204 $tmp = preg_replace("/^.*_/","\\1",$name);
205 $tmp2 = split("\|",$tmp);
207 if(count($tmp2) != 2) continue;
209 $Name = base64_decode($tmp2[0]);
210 $RecordID = $tmp2[1];
212 /* Host renamed
213 */
214 if(preg_match("/RenameHost_/",$name)){
215 if((isset($this->Devices[$Name])) && ($Name != $value)){
217 if(isset($this->Devices[$value])){
218 msg_dialog::display(_("Error"), sprintf(_("Cannot rename '%s' to '%s'. Name is already in use!"), $Name, $value), ERROR_DIALOG);
219 }else{
220 $this->Devices[$value] = $this->Devices[$Name];
221 unset($this->Devices[$Name]);
222 }
223 }
224 }
225 }
226 }
229 /* check something
230 */
231 function check()
232 {
233 /* Call common method to give check the hook */
234 $message= plugin::check();
236 $ldap = $this->config->get_ldap_link();
237 $ldap->cd($this->config->current['BASE']);
239 $names = array();
240 foreach($this->Devices as $DevName => $device){
242 /* Don't need to check empty values ... */
243 if(!count($device['RECORDS'])) continue;
245 /* Checking entry name
246 */
247 if(!preg_match("/^[a-z0-9_\.-]+$/i", $DevName) || (empty($DevName))){
248 $message[] = msgPool::invalid(_("Name"),$DevName,"/[a-z0-9_\.-]/i");
249 }
251 /* Renaming check for existing devices
252 */
253 if(isset($device['OrigCn']) && ($DevName != $device['OrigCn'] )){
254 $ldap->cd($this->config->current['BASE']);
255 $ldap->search("(relativeDomainName=".$DevName.")",array("relativeDomainName"));
256 if($ldap->count()){
257 $message[] = sprintf(_("Cannot rename '%s' to '%s'. Entry is already in use."),$device['OrigCn'],$DevName);
258 }
259 }elseif(!isset($device['OrigCn'])){
260 $ldap->cd($this->config->current['BASE']);
261 $ldap->search("(relativeDomainName=".$DevName.")",array("relativeDomainName"));
262 if($ldap->count()){
263 $message[] = sprintf(_("Cannot create '%s'. Entry is already in use."),$DevName);
264 }
265 }
267 /* Check names
268 */
269 if(!isset($names[$DevName])){
270 $names[$DevName] = "";
271 }else{
272 $message[] = sprintf(_("Entry '%s' is used more than once."),$DevName);
273 }
275 /* Names should be written in lowercase
276 */
277 # if(strtolower($DevName) != $DevName){
278 # $message[] = sprintf(_("The host name '%s' should be written in lowercase."), $DevName);
279 # }
281 /* Check records
282 */
283 $singleEntries = array("cNAMERecord","pTRRecord");
285 $tmp = array();
286 $tmp2 = array();
287 foreach($device['RECORDS'] as $Num => $Rec){
289 /* Check for multiple use of unique record types
290 */
291 if(in_array($Rec['type'],$singleEntries)){
292 if(!isset($tmp[$Rec['type']])){
293 $tmp[$Rec['type']] = "";
294 }else{
295 $message[] = sprintf(_("%s records cannot be used more than once."),$Rec['type']);
296 }
297 }
299 /* Check for empty / duplicate entries in record array
300 */
301 if(empty($Rec['value'])){
302 $message[] = sprintf(_("Please fix the empty %s record for entry '%s'."),$Rec['type'],$DevName);
303 }
305 /* Check for duplicate record entries
306 */
307 if(!isset($tmp[$Rec['type']][$Rec['value']])){
308 $tmp[$Rec['type']][$Rec['value']] = "";
309 }else{
310 $message[] = sprintf(_("Please fix the duplicate %s record for entry '%s'."),$Rec['type'],$DevName);
311 }
312 }
313 }
314 return ($message);
315 }
318 function save()
319 {
320 if($this->disableDialog) return;
322 $todo = array();
326 /* Create todolist
327 */
328 foreach($this->Devices as $name => $dev){
329 if(isset($dev['OrigCn'])){
330 if(count($dev['RECORDS'])){
331 $todo[] = DNS::getDNSHostEntriesDiff($this->config,$dev['OrigCn'],$dev,$name);
332 }else{
333 $dev['exists'] = false;
334 $todo[] = DNS::getDNSHostEntriesDiff($this->config,$dev['OrigCn'],$dev,$name);
335 }
336 }else{
337 if(count($dev['RECORDS'])){
338 $todo[] = DNS::getDNSHostEntriesDiff($this->config,"",$dev,$name);
339 }else{
340 $dev['exists'] = false;
341 $todo[] = DNS::getDNSHostEntriesDiff($this->config,"",$dev,$name);
342 }
343 }
344 }
346 $tmp = array();
347 $tmp['del'] = array();
348 $tmp['add'] = array();
349 $tmp['move'] = array();
350 foreach($todo as $to){
351 foreach($to as $type => $entries){
352 $tmp[$type] = array_merge($tmp[$type],$entries);
353 }
354 }
356 /* Get ldap link
357 */
358 $ldap = $this->config->get_ldap_link();
359 $ldap->cd ($this->config->current['BASE']);
361 /* move follwoing entries
362 */
363 foreach($tmp['move'] as $src => $dst){
364 $this->recursive_move($src,$dst);
365 }
367 /* Delete dns */
368 foreach($tmp['del'] as $dn => $del){
369 $ldap->cd($dn);
370 $ldap->rmdir_recursive($dn);
371 if(is_object($this->parent->parent)){
372 $this->parent->parent->handle_post_events("remove",array("dn" => $dn));
373 }
374 }
376 /* Add || Update new DNS entries
377 */
378 foreach($tmp['add'] as $dn => $attrs){
379 $ldap->cd($dn);
380 $ldap->cat($dn, array('dn'));
381 if(count($ldap->fetch())){
382 $ldap->cd($dn);
383 $ldap->modify ($attrs);
384 if(is_object($this->parent->parent)){
385 $this->parent->parent->handle_post_events("modify",array("dn" => $dn));
386 }
387 }else{
388 $ldap->cd($dn);
389 $ldap->add($attrs);
390 if(is_object($this->parent->parent)){
391 $this->parent->parent->handle_post_events("create",array("dn" => $dn));
392 }
393 }
394 }
395 }
398 /* Create html table out of given entry
399 */
400 function generateRecordConfigurationRow($objKey){
402 /* Get some basic informations
403 */
404 $obj = $this->Devices[$objKey];
405 $objectName = $objKey;
407 /* Abort if emtpy
408 */
409 if(count($obj['RECORDS']) == 0) return "";
411 /* Set title
412 */
413 $str= "<br>";
415 $hostNameOnce = true;
417 /* Walk through all defined records
418 */
419 $str.= "<table cellspacing='0' cellpadding='0'>";
420 foreach($obj['RECORDS'] as $id => $record){
422 /* Skip not selectable entries */
423 if(!isset($this->RecordTypes [$record['type']])) {
424 continue;
425 }
427 /* Create unique post name
428 */
429 $name = base64_encode($objKey)."|".$id;
431 $str .= "<tr><td style='width:170px;'>\n";
433 /* Only first host entry name should be editable
434 */
435 if($hostNameOnce){
436 $hostNameOnce = false;
437 $str .="<input type='text' name='RenameHost_".$name."' value='".$objectName."'>\n";
438 }
440 /* Create rest. Selectbox, icons ...
441 */
442 $str .="
443 </td>
444 <td style='width:90px;'>
445 ".$this->createRecordTypeSelection($record['type'],$name)."
446 </td>
447 <td>
448 <input type='text' value='".$record['value']."' name='ValueSelection_".$name."' style='width:250px;'>
449 </td>
450 <td style='width:75px;text-align:right;'>
451 <input type='image' name='AddRecord_".$name."' src='images/list_new.png' alt='"._("Add")."' title='"._("Add")."'>
452 <input type='image' name='RemoveRecord_".$name."' src='images/lists/trash.png' alt='"._("Remove")."' title='"._("Remove")."'>
453 ";
455 $str.=
456 "</td>
457 </tr>";
458 }
459 $str .="</table>";
460 return($str);
461 }
464 /* Create selectbox with all available option types
465 */
466 function createRecordTypeSelection($id,$refID){
468 $str = "\n<select name='RecordTypeSelection_".$refID."'>";
469 foreach($this->RecordTypes as $type => $atr) {
470 if($id == $type){
471 $str .="\n<option value='".$type."' selected >".strtoupper(preg_replace("/record/i","",$type))."</option>";
472 }else{
473 $str .="\n<option value='".$type."'>".strtoupper(preg_replace("/record/i","",$type))."</option>";
474 }
475 }
476 $str.= "\n</select>";
477 return($str);
478 }
481 function remove_from_parent()
482 {
483 }
485 }
487 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
488 ?>