b87d22c1e3e7c6e460b599cc4f349c31e357dbc1
1 <?php
3 class servDNSeditZoneEntries extends plugin
4 {
5 /* CLI vars */
6 var $cli_summary= "Manage server basic objects";
7 var $cli_description= "Some longer text\nfor help";
8 var $cli_parameters= array("eins" => "Eins ist toll", "zwei" => "Zwei ist noch besser");
10 /* attribute list for save action */
11 var $ignore_account = TRUE;
12 var $attributes = array();
13 var $objectclasses = array("whatever");
15 var $Devices = array();
17 var $zoneName = ""; // ZoneName of currently edited Zone
18 var $reverseName = ""; // ReverseZone of the currently edited Zone
20 var $RecordTypes = array(); // Possible record type.
22 var $disableDialog = false; // Dialog will be disabled, if this zone is new
24 function servDNSeditZoneEntries ($config,$dn, $zoneObject)
25 {
26 plugin::plugin ($config, $dn);
28 /* Initialise class
29 */
30 $this->RecordTypes = getDnsRecordTypes();
31 $this->dn = "zoneName=".$zoneObject['InitialzoneName'].",".$dn;
32 $this->zoneName = $zoneObject['InitialzoneName'];
33 $this->reverseName = $zoneObject['InitialReverseZone'];
35 /* Remove nSRecord from listed types */
36 if(isset($this->RecordTypes['nSRecord'])){
37 unset($this->RecordTypes['nSRecord']);
38 }
39 /* Remove nSRecord from listed types */
40 if(isset($this->RecordTypes['pTRRecord'])){
41 unset($this->RecordTypes['pTRRecord']);
42 }
44 /* Get ldap connection
45 */
46 $ldap = $this->config->get_ldap_link();
47 $ldap->cd($this->config->current['BASE']);
49 /* Get zone content
50 */
51 $ldap->ls("(&(objectClass=dNSZone)(!(relativeDomainName=@)))",$this->dn,array("relativeDomainName"));
53 while($attrs = $ldap->fetch()){
54 $this->Devices[$attrs['relativeDomainName'][0]] = getDNSHostEntries($config,$attrs['relativeDomainName'][0],true);
55 $this->Devices[$attrs['relativeDomainName'][0]]['OrigCn'] = $attrs['relativeDomainName'][0];
56 }
58 $ldap->cat($this->dn,array("objectClass"));
60 $this->disableDialog = true;
61 if(count($this->Devices)|| $ldap->count()){
62 $this->disableDialog = false;
63 }
64 }
66 function execute()
67 {
68 plugin::execute();
70 /* Fill templating stuff */
71 $smarty= get_smarty();
72 $display= "";
74 $table = "";
75 foreach($this->Devices as $key => $dev){
76 $table .= $this->generateRecordConfigurationRow($key);
77 }
78 print_a($this->Devices);
80 $smarty->assign("disableDialog",$this->disableDialog);
81 $smarty->assign("table",$table);;
82 $display.= $smarty->fetch(get_template_path('servDNSeditZoneEntries.tpl', TRUE));
83 return($display);
84 }
87 function save_object()
88 {
89 /* Check posts for operations ...
90 */
91 $once = true;
92 $ptr_updates = array();
93 foreach($_POST as $name => $value){
95 /* Add a new Record in given object
96 */
98 $tmp = preg_replace("/^.*_(.*)_.*$/","\\1",$name);
99 $tmp2 = split("\|",$tmp);
101 /* Add new host entry
102 */
103 if((preg_match("/^UserRecord_?/",$name)) && ($once)){
104 $once = false;
105 $entry = getDNSHostEntries($this->config,"",true);
106 $entry['exists'] = true;
107 $entry['zoneName'] = strtoupper($this->attrs['cn'][0])."/".$this->zoneName;
108 $entry['RECORDS'][] = array("type" => "aRecord" , "value"=>"");
109 $this->Devices[_("New entry")] = $entry;
110 }
112 if(count($tmp2) != 2) continue;
114 $Name = base64_decode($tmp2[0]);
115 $RecordID = $tmp2[1];
117 /* Add new REcord
118 */
119 if((preg_match("/^AddRecord_/",$name)) && ($once)){
120 $once = false;
121 $this->Devices[$Name]['RECORDS'][] = $this->Devices[$Name]['RECORDS'][$RecordID];
122 }
124 /* Remove record from given dn
125 */
126 if((preg_match("/^RemoveRecord_/",$name)) && ($once)){
127 $once = false;
128 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
129 unset($this->Devices[$Name]['RECORDS'][$RecordID]);
130 }
132 /* Check if there is at least one visible record. Else remove complete entry */
133 $visible = false;
134 foreach($this->Devices[$Name]['RECORDS'] as $rec){
135 if(in_array($rec['type'],$this->RecordTypes)){
136 $visible = true;
137 break;
138 }
139 }
140 if(!$visible && isset($this->Devices[$Name]['RECORDS'])){
141 $this->Devices[$Name]['RECORDS'] = array();
142 }
143 }
144 }
146 /* Possible attributes posted
147 */
148 foreach($_POST as $name => $value){
150 /* Extract informations out of post name
151 */
152 $tmp = preg_replace("/^.*_/","\\1",$name);
153 $tmp2 = split("\|",$tmp);
155 if(count($tmp2) != 2) continue;
157 $Name = base64_decode($tmp2[0]);
158 $RecordID = $tmp2[1];
160 /* Check for value change
161 */
162 if(preg_match("/ValueSelection_/",$name)){
163 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
165 /* Update value */
166 $old = $this->Devices[$Name]['RECORDS'][$RecordID]['value'];
167 $this->Devices[$Name]['RECORDS'][$RecordID]['value'] = $value;
169 /* Handle pTRRecord */
170 if(!isset($ptr_updates[$Name]) && $this->Devices[$Name]['RECORDS'][$RecordID]['type'] == "aRecord"){
172 $found = false;
173 $ip = $value;
174 $match = preg_replace("/^[^\/]*+\//","",$this->reverseName);
175 $ip = preg_replace("/^".normalizePreg($match)."/","",$ip);
176 $ip = preg_replace("/^\./","",$ip);
178 foreach($this->Devices[$Name]['RECORDS'] as $key => $dev){
179 if($dev['type'] == "pTRRecord"){
180 $ptr_updates[$Name] = $Name;
181 $this->Devices[$Name]['RECORDS'][$key]['value'] = $ip;
182 $found = true;
183 break;
184 }
185 }
186 if(!$found){
187 $dev = array('type'=> 'pTRRecord', 'value' => $ip);
188 $this->Devices[$Name]['RECORDS'][] = $dev;
189 }
190 }
191 }
192 }
194 /* record type changed
195 */
196 if(preg_match("/^RecordTypeSelection_/",$name)){
197 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
198 $this->Devices[$Name]['RECORDS'][$RecordID]['type'] = $value;
199 }
200 }
201 }
203 /* check for renamed entries
204 */
205 foreach($_POST as $name => $value){
207 /* Extract informations out of post name
208 */
209 $tmp = preg_replace("/^.*_/","\\1",$name);
210 $tmp2 = split("\|",$tmp);
212 if(count($tmp2) != 2) continue;
214 $Name = base64_decode($tmp2[0]);
215 $RecordID = $tmp2[1];
217 /* Host renamed
218 */
219 if(preg_match("/RenameHost_/",$name)){
220 if((isset($this->Devices[$Name])) && ($Name != $value)){
222 if(isset($this->Devices[$value])){
223 print_red(sprintf(_("Can't rename '%s' to '%s' there is already an entry with the same name in our zone editing dialog."),$Name,$value));
224 }else{
225 $this->Devices[$value] = $this->Devices[$Name];
226 unset($this->Devices[$Name]);
227 }
228 }
229 }
230 }
231 }
234 /* check something
235 */
236 function check()
237 {
238 /* Call common method to give check the hook */
239 $message= plugin::check();
241 $ldap = $this->config->get_ldap_link();
242 $ldap->cd($this->config->current['BASE']);
244 $names = array();
245 foreach($this->Devices as $DevName => $device){
247 /* Don't need to check empty values ... */
248 if(!count($device['RECORDS'])) continue;
250 /* Checking entry name
251 */
252 if(!preg_match("/^[a-z0-9_\.-]+$/i", $DevName) || (empty($DevName))){
253 $message[] = sprintf(_("Entry name '%s' contains invalid characters."), $DevName);
254 }
256 /* Renaming check for existing devices
257 */
258 if(isset($device['OrigCn']) && ($DevName != $device['OrigCn'] )){
259 $ldap->cd($this->config->current['BASE']);
260 $ldap->search("(relativeDomainName=".$DevName.")",array("relativeDomainName"));
261 if($ldap->count()){
262 $message[] = sprintf(_("Can not rename '%s' to '%s',the destination name already exists."),$device['OrigCn'],$DevName);
263 }
264 }elseif(!isset($device['OrigCn'])){
265 $ldap->cd($this->config->current['BASE']);
266 $ldap->search("(relativeDomainName=".$DevName.")",array("relativeDomainName"));
267 if($ldap->count()){
268 $message[] = sprintf(_("Can not create '%s',the destination name already exists."),$DevName);
269 }
270 }
272 /* Check names
273 */
274 if(!isset($names[$DevName])){
275 $names[$DevName] = "";
276 }else{
277 $message[] = sprintf(_("The name '%s' is used more than once."),$DevName);
278 }
280 /* Names should be written in lowercase
281 */
282 # if(strtolower($DevName) != $DevName){
283 # $message[] = sprintf(_("The host name '%s' should be written in lowercase."), $DevName);
284 # }
286 /* Check records
287 */
288 $singleEntries = array("cNAMERecord","pTRRecord");
290 $tmp = array();
291 $tmp2 = array();
292 foreach($device['RECORDS'] as $Num => $Rec){
294 /* Check for multiple use of unique record types
295 */
296 if(in_array($Rec['type'],$singleEntries)){
297 if(!isset($tmp[$Rec['type']])){
298 $tmp[$Rec['type']] = "";
299 }else{
300 $message[] = sprintf(_("The record type '%s' is a unique type and can't be defined twice."),$type);
301 }
302 }
304 /* Check for empty / duplicate entries in record array
305 */
306 if(empty($Rec['value'])){
307 $message[] = sprintf(_("There is an empty '%s' for host '%s'."),$Rec['type'],$DevName);
308 }
310 /* Check for duplicate record entries
311 */
312 if(!isset($tmp[$Rec['type']][$Rec['value']])){
313 $tmp[$Rec['type']][$Rec['value']] = "";
314 }else{
315 $message[] = sprintf(_("There is a duplicate entry in '%s' for '%s'."),$Rec['type'],$DevName);
316 }
317 }
318 }
319 return ($message);
320 }
322 function save()
323 {
324 if($this->disableDialog) return;
326 $todo = array();
330 /* Create todolist
331 */
332 foreach($this->Devices as $name => $dev){
333 if(isset($dev['OrigCn'])){
334 if(count($dev['RECORDS'])){
335 $todo[] = getDNSHostEntriesDiff($this->config,$dev['OrigCn'],$dev,$name);
336 }else{
337 $dev['exists'] = false;
338 $todo[] = getDNSHostEntriesDiff($this->config,$dev['OrigCn'],$dev,$name);
339 }
340 }else{
341 if(count($dev['RECORDS'])){
342 $todo[] = getDNSHostEntriesDiff($this->config,"",$dev,$name);
343 }else{
344 $dev['exists'] = false;
345 $todo[] = getDNSHostEntriesDiff($this->config,"",$dev,$name);
346 }
347 }
348 }
350 $tmp = array();
351 $tmp['del'] = array();
352 $tmp['add'] = array();
353 $tmp['move'] = array();
354 foreach($todo as $to){
355 foreach($to as $type => $entries){
356 $tmp[$type] = array_merge($tmp[$type],$entries);
357 }
358 }
360 /* Get ldap link
361 */
362 $ldap = $this->config->get_ldap_link();
363 $ldap->cd ($this->config->current['BASE']);
365 /* move follwoing entries
366 */
367 foreach($tmp['move'] as $src => $dst){
368 $this->recursive_move($src,$dst);
369 }
371 /* Delete dns */
372 foreach($tmp['del'] as $dn => $del){
373 $ldap->cd($dn);
374 $ldap->rmdir_recursive($dn);
375 if(is_object($this->parent->parent)){
376 $this->parent->parent->handle_post_events("remove",array("dn" => $dn));
377 }
378 }
380 /* Add || Update new DNS entries
381 */
382 foreach($tmp['add'] as $dn => $attrs){
383 $ldap->cd($dn);
384 $ldap->cat($dn, array('dn'));
385 if(count($ldap->fetch())){
386 $ldap->cd($dn);
387 $ldap->modify ($attrs);
388 if(is_object($this->parent->parent)){
389 $this->parent->parent->handle_post_events("modify",array("dn" => $dn));
390 }
391 }else{
392 $ldap->cd($dn);
393 $ldap->add($attrs);
394 if(is_object($this->parent->parent)){
395 $this->parent->parent->handle_post_events("create",array("dn" => $dn));
396 }
397 }
398 }
399 }
402 /* Create html table out of given entry
403 */
404 function generateRecordConfigurationRow($objKey){
406 /* Get some basic informations
407 */
408 $obj = $this->Devices[$objKey];
409 $objectName = $objKey;
411 /* Abort if emtpy
412 */
413 if(count($obj['RECORDS']) == 0) return "";
415 /* Set title
416 */
417 $str= "<br>";
419 $hostNameOnce = true;
421 /* Walk through all defined records
422 */
423 $str.= "<table cellspacing='0' cellpadding='0'>";
424 foreach($obj['RECORDS'] as $id => $record){
426 /* Skip not selectable entries */
427 if(!isset($this->RecordTypes [$record['type']])) {
428 continue;
429 }
431 /* Create unique post name
432 */
433 $name = base64_encode($objKey)."|".$id;
435 $str .= "<tr><td style='width:170px;'>\n";
437 /* Only first host entry name should be editable
438 */
439 if($hostNameOnce){
440 $hostNameOnce = false;
441 $str .="<input type='text' name='RenameHost_".$name."' value='".$objectName."'>\n";
442 }
444 /* Create rest. Selectbox, icons ...
445 */
446 $str .="
447 </td>
448 <td style='width:90px;'>
449 ".$this->createRecordTypeSelection($record['type'],$name)."
450 </td>
451 <td>
452 <input type='text' value='".$record['value']."' name='ValueSelection_".$name."' style='width:250px;'>
453 </td>
454 <td style='width:75px;text-align:right;'>
455 <input type='image' name='AddRecord_".$name."' src='images/list_new.png' alt='"._("Add")."' title='"._("Add")."'>
456 <input type='image' name='RemoveRecord_".$name."' src='images/edittrash.png' alt='"._("Remove")."' title='"._("Remove")."'>
457 ";
459 # if($record['type'] == "aRecord"){
460 # $str .="<input type='image' name='AddPtr_".$name."' src='images/network.png'
461 # alt='"._("Add PTR")."' title='"._("Add PTR record")."'>";
462 # }else{
463 # $str .= "<img src='images/empty.png' alt=''>";
464 # }
466 $str.=
467 "</td>
468 </tr>";
469 }
470 $str .="</table>";
471 return($str);
472 }
475 /* Create selectbox with all available option types
476 */
477 function createRecordTypeSelection($id,$refID){
479 $str = "\n<select name='RecordTypeSelection_".$refID."'>";
480 foreach($this->RecordTypes as $type => $atr) {
481 if($id == $type){
482 $str .="\n<option value='".$type."' selected >".strtoupper(preg_replace("/record/i","",$type))."</option>";
483 }else{
484 $str .="\n<option value='".$type."'>".strtoupper(preg_replace("/record/i","",$type))."</option>";
485 }
486 }
487 $str.= "\n</select>";
488 return($str);
489 }
492 function remove_from_parent()
493 {
494 }
496 }
498 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
499 ?>