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 }
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]] = 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();
68 /* Fill templating stuff */
69 $smarty= get_smarty();
70 $display= "";
72 $table = "";
73 foreach($this->Devices as $key => $dev){
74 $table .= $this->generateRecordConfigurationRow($key);
75 }
77 $smarty->assign("disableDialog",$this->disableDialog);
78 $smarty->assign("table",$table);;
79 $display.= $smarty->fetch(get_template_path('servDNSeditZoneEntries.tpl', TRUE));
80 return($display);
81 }
84 function save_object()
85 {
86 /* Check posts for operations ...
87 */
88 $once = true;
89 foreach($_POST as $name => $value){
91 /* Add a new Record in given object
92 */
94 $tmp = preg_replace("/^.*_(.*)_.*$/","\\1",$name);
95 $tmp2 = split("\|",$tmp);
97 /* Add new host entry
98 */
99 if((preg_match("/^UserRecord_?/",$name)) && ($once)){
100 $once = false;
101 $entry = getDNSHostEntries($this->config,"",true);
102 $entry['exists'] = true;
103 $entry['zoneName'] = strtoupper($this->attrs['cn'][0])."/".$this->zoneName;
104 $entry['RECORDS'][] = array("type" => "aRecord" , "value"=>"");
105 $this->Devices[_("New entry")] = $entry;
106 }
108 if(count($tmp2) != 2) continue;
110 $Name = base64_decode($tmp2[0]);
111 $RecordID = $tmp2[1];
113 /* Add new REcord
114 */
115 if((preg_match("/^AddRecord_/",$name)) && ($once)){
116 $once = false;
117 $this->Devices[$Name]['RECORDS'][] = $this->Devices[$Name]['RECORDS'][$RecordID];
118 }
120 /* Remove record from given dn
121 */
122 if((preg_match("/^RemoveRecord_/",$name)) && ($once)){
123 $once = false;
124 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
125 unset($this->Devices[$Name]['RECORDS'][$RecordID]);
126 }
127 }
129 /* Add PTR record
130 */
131 if((preg_match("/^AddPtr_/",$name)) && ($once)){
132 $once = false;
133 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
134 $tmp = $this->Devices[$Name]['RECORDS'][$RecordID];
135 $ip = $tmp['value'];
136 $match = preg_replace("/^[^\/]*+\//","",$this->reverseName);
137 $ip = preg_replace("/^".normalizePreg($match)."/","",$ip);
138 $ip = preg_replace("/^\./","",$ip);
139 $tmp['type'] = "pTRRecord";
140 $tmp['value'] = $ip;
141 $this->Devices[$Name]['RECORDS'][] = $tmp;
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])){
164 $this->Devices[$Name]['RECORDS'][$RecordID]['value'] = $value;
165 }
166 }
168 /* record type changed
169 */
170 if(preg_match("/^RecordTypeSelection_/",$name)){
171 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
172 $this->Devices[$Name]['RECORDS'][$RecordID]['type'] = $value;
173 }
174 }
175 }
177 /* check for renamed entries
178 */
179 foreach($_POST as $name => $value){
181 /* Extract informations out of post name
182 */
183 $tmp = preg_replace("/^.*_/","\\1",$name);
184 $tmp2 = split("\|",$tmp);
186 if(count($tmp2) != 2) continue;
188 $Name = base64_decode($tmp2[0]);
189 $RecordID = $tmp2[1];
191 /* Host renamed
192 */
193 if(preg_match("/RenameHost_/",$name)){
194 if((isset($this->Devices[$Name])) && ($Name != $value)){
196 if(isset($this->Devices[$value])){
197 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));
198 }else{
199 $this->Devices[$value] = $this->Devices[$Name];
200 unset($this->Devices[$Name]);
201 }
202 }
203 }
204 }
205 }
208 /* check something
209 */
210 function check()
211 {
212 /* Call common method to give check the hook */
213 $message= plugin::check();
215 $ldap = $this->config->get_ldap_link();
216 $ldap->cd($this->config->current['BASE']);
218 $names = array();
219 foreach($this->Devices as $DevName => $device){
221 /* Don't need to check empty values ... */
222 if(!count($device['RECORDS'])) continue;
224 /* Checking entry name
225 */
226 if(!preg_match("/^[a-z0-9_\.-]+$/i", $DevName) || (empty($DevName))){
227 $message[] = sprintf(_("Entry name '%s' contains invalid characters."), $DevName);
228 }
230 /* Renaming check for existing devices
231 */
232 if(isset($device['OrigCn']) && ($DevName != $device['OrigCn'] )){
233 $ldap->cd($this->config->current['BASE']);
234 $ldap->search("(relativeDomainName=".$DevName.")",array("relativeDomainName"));
235 if($ldap->count()){
236 $message[] = sprintf(_("Can not rename '%s' to '%s',the destination name already exists."),$device['OrigCn'],$DevName);
237 }
238 }elseif(!isset($device['OrigCn'])){
239 $ldap->cd($this->config->current['BASE']);
240 $ldap->search("(relativeDomainName=".$DevName.")",array("relativeDomainName"));
241 if($ldap->count()){
242 $message[] = sprintf(_("Can not create '%s',the destination name already exists."),$DevName);
243 }
244 }
246 /* Check names
247 */
248 if(!isset($names[$DevName])){
249 $names[$DevName] = "";
250 }else{
251 $message[] = sprintf(_("The name '%s' is used more than once."),$DevName);
252 }
254 /* Names should be written in lowercase
255 */
256 # if(strtolower($DevName) != $DevName){
257 # $message[] = sprintf(_("The host name '%s' should be written in lowercase."), $DevName);
258 # }
260 /* Check records
261 */
262 $singleEntries = array("cNAMERecord","pTRRecord");
264 $tmp = array();
265 $tmp2 = array();
266 foreach($device['RECORDS'] as $Num => $Rec){
268 /* Check for multiple use of unique record types
269 */
270 if(in_array($Rec['type'],$singleEntries)){
271 if(!isset($tmp[$Rec['type']])){
272 $tmp[$Rec['type']] = "";
273 }else{
274 $message[] = sprintf(_("The record type '%s' is a unique type and can't be defined twice."),$type);
275 }
276 }
278 /* Check for empty / duplicate entries in record array
279 */
280 if(empty($Rec['value'])){
281 $message[] = sprintf(_("There is an empty '%s' for host '%s'."),$Rec['type'],$DevName);
282 }
284 /* Check for duplicate record entries
285 */
286 if(!isset($tmp[$Rec['type']][$Rec['value']])){
287 $tmp[$Rec['type']][$Rec['value']] = "";
288 }else{
289 $message[] = sprintf(_("There is a duplicate entry in '%s' for '%s'."),$Rec['type'],$DevName);
290 }
291 }
292 }
293 return ($message);
294 }
296 function save()
297 {
298 if($this->disableDialog) return;
300 $todo = array();
302 /* Create todolist
303 */
304 foreach($this->Devices as $name => $dev){
305 if(isset($dev['OrigCn'])){
306 if(count($dev['RECORDS'])){
307 $todo[] = getDNSHostEntriesDiff($this->config,$dev['OrigCn'],$dev,$name);
308 }else{
309 $dev['exists'] = false;
310 $todo[] = getDNSHostEntriesDiff($this->config,$dev['OrigCn'],$dev,$name);
311 }
312 }else{
313 if(count($dev['RECORDS'])){
314 $todo[] = getDNSHostEntriesDiff($this->config,"",$dev,$name);
315 }else{
316 $dev['exists'] = false;
317 $todo[] = getDNSHostEntriesDiff($this->config,"",$dev,$name);
318 }
319 }
320 }
322 $tmp = array();
323 $tmp['del'] = array();
324 $tmp['add'] = array();
325 $tmp['move'] = array();
326 foreach($todo as $to){
327 foreach($to as $type => $entries){
328 $tmp[$type] = array_merge($tmp[$type],$entries);
329 }
330 }
332 /* Get ldap link
333 */
334 $ldap = $this->config->get_ldap_link();
335 $ldap->cd ($this->config->current['BASE']);
337 /* move follwoing entries
338 */
339 foreach($tmp['move'] as $src => $dst){
340 $this->recursive_move($src,$dst);
341 }
343 /* Delete dns */
344 foreach($tmp['del'] as $dn => $del){
345 $ldap->cd($dn);
346 $ldap->rmdir_recursive($dn);
347 }
349 /* Add || Update new DNS entries
350 */
351 foreach($tmp['add'] as $dn => $attrs){
352 $ldap->cd($dn);
353 $ldap->cat($dn, array('dn'));
354 if(count($ldap->fetch())){
355 $ldap->cd($dn);
356 $ldap->modify ($attrs);
357 }else{
358 $ldap->cd($dn);
359 $ldap->add($attrs);
360 }
361 }
362 }
365 /* Create html table out of given entry
366 */
367 function generateRecordConfigurationRow($objKey){
369 /* Get some basic informations
370 */
371 $obj = $this->Devices[$objKey];
372 $objectName = $objKey;
374 /* Abort if emtpy
375 */
376 if(count($obj['RECORDS']) == 0) return "";
378 /* Set title
379 */
380 $str= "<br>";
382 $hostNameOnce = true;
384 /* Walk through all defined records
385 */
386 $str.= "<table cellspacing='0' cellpadding='0'>";
387 foreach($obj['RECORDS'] as $id => $record){
389 /* Create unique post name
390 */
391 $name = base64_encode($objKey)."|".$id;
393 $str .= "<tr><td style='width:170px;'>\n";
395 /* Only first host entry name should be editable
396 */
397 if($hostNameOnce){
398 $hostNameOnce = false;
399 $str .="<input type='text' name='RenameHost_".$name."' value='".$objectName."'>\n";
400 }
402 /* Create rest. Selectbox, icons ...
403 */
404 $str .="
405 </td>
406 <td style='width:90px;'>
407 ".$this->createRecordTypeSelection($record['type'],$name)."
408 </td>
409 <td>
410 <input type='text' value='".$record['value']."' name='ValueSelection_".$name."' style='width:250px;'>
411 </td>
412 <td style='width:75px;text-align:right;'>
413 <input type='image' name='AddRecord_".$name."' src='images/list_new.png' alt='"._("Add")."' title='"._("Add")."'>
414 <input type='image' name='RemoveRecord_".$name."' src='images/edittrash.png' alt='"._("Remove")."' title='"._("Remove")."'>
415 ";
417 if($record['type'] == "aRecord"){
418 $str .="<input type='image' name='AddPtr_".$name."' src='images/network.png'
419 alt='"._("Add PTR")."' title='"._("Add PTR record")."'>";
420 }else{
421 $str .= "<img src='images/empty.png' alt=''>";
422 }
424 $str.=
425 "</td>
426 </tr>";
427 }
428 $str .="</table>";
429 return($str);
430 }
433 /* Create selectbox with all available option types
434 */
435 function createRecordTypeSelection($id,$refID){
437 $str = "\n<select name='RecordTypeSelection_".$refID."'>";
438 foreach($this->RecordTypes as $type => $atr) {
439 if($id == $type){
440 $str .="\n<option value='".$type."' selected >".strtoupper(preg_replace("/record/i","",$type))."</option>";
441 }else{
442 $str .="\n<option value='".$type."'>".strtoupper(preg_replace("/record/i","",$type))."</option>";
443 }
444 }
445 $str.= "\n</select>";
446 return($str);
447 }
450 function remove_from_parent()
451 {
452 }
454 }
456 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
457 ?>