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("cn");
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
23 var $cn;
25 function servDNSeditZoneEntries ($config,$dn, $zoneObject)
26 {
27 plugin::plugin ($config, $dn);
29 /* Initialise class
30 */
31 $this->RecordTypes = getDnsRecordTypes();
32 $this->dn = "zoneName=".$zoneObject['InitialzoneName'].",".$dn;
33 $this->zoneName = strtoupper($this->cn)."/".$zoneObject['InitialzoneName'];
34 $this->reverseName = strtoupper($this->cn)."/".$zoneObject['InitialReverseZone'];
36 /* Get ldap connection
37 */
38 $ldap = $this->config->get_ldap_link();
39 $ldap->cd($this->config->current['BASE']);
41 /* Get zone content
42 */
43 $ldap->ls("(&(objectClass=dNSZone)(!(relativeDomainName=@)))",$this->dn,array("relativeDomainName"));
45 while($attrs = $ldap->fetch()){
46 $this->Devices[$attrs['relativeDomainName'][0]] = getDNSHostEntries($config,$attrs['relativeDomainName'][0],true);
47 $this->Devices[$attrs['relativeDomainName'][0]]['OrigCn'] = $attrs['relativeDomainName'][0];
48 }
50 $ldap->cat($this->dn,array("objectClass"));
52 $this->disableDialog = true;
53 if(count($this->Devices)|| $ldap->count()){
54 $this->disableDialog = false;
55 }
56 }
58 function execute()
59 {
60 plugin::execute();
63 /* Check posts for operations ...
64 */
65 $once = true;
66 foreach($_POST as $name => $value){
68 /* Add a new Record in given object
69 */
71 $tmp = preg_replace("/^.*_(.*)_.*$/","\\1",$name);
72 $tmp2 = split("\|",$tmp);
74 /* Add new host entry
75 */
76 if((preg_match("/^UserRecord_?/",$name)) && ($once)){
77 $once = false;
78 $entry = getDNSHostEntries($this->config,"",true);
79 $entry['exists'] = true;
80 $entry['zoneName'] = $this->zoneName;
81 $entry['RECORDS'][] = array("type" => "aRecord" , "value"=>"");
82 $this->Devices[_("New entry")] = $entry;
83 }
85 if(count($tmp2) != 2) continue;
87 $Name = base64_decode($tmp2[0]);
88 $RecordID = $tmp2[1];
90 /* Add new REcord
91 */
92 if((preg_match("/^AddRecord_/",$name)) && ($once)){
93 $once = false;
94 $this->Devices[$Name]['RECORDS'][] = $this->Devices[$Name]['RECORDS'][$RecordID];
95 }
97 /* Remove record from given dn
98 */
99 if((preg_match("/^RemoveRecord_/",$name)) && ($once)){
100 $once = false;
101 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
102 unset($this->Devices[$Name]['RECORDS'][$RecordID]);
103 }
104 }
106 }
108 /* Fill templating stuff */
109 $smarty= get_smarty();
110 $display= "";
112 $table = "";
113 foreach($this->Devices as $key => $dev){
114 $table .= $this->generateRecordConfigurationRow($key);
115 }
117 $smarty->assign("disableDialog",$this->disableDialog);
118 $smarty->assign("table",$table);;
119 $display.= $smarty->fetch(get_template_path('servDNSeditZoneEntries.tpl', TRUE));
120 return($display);
121 }
124 function save_object()
125 {
126 /* Possible attributes posted
127 */
128 foreach($_POST as $name => $value){
130 /* Extract informations out of post name
131 */
132 $tmp = preg_replace("/^.*_/","\\1",$name);
133 $tmp2 = split("\|",$tmp);
135 if(count($tmp2) != 2) continue;
137 $Name = base64_decode($tmp2[0]);
138 $RecordID = $tmp2[1];
140 /* Check for value change
141 */
142 if(preg_match("/ValueSelection_/",$name)){
143 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
144 $this->Devices[$Name]['RECORDS'][$RecordID]['value'] = $value;
145 }
146 }
148 /* record type changed
149 */
150 if(preg_match("/^RecordTypeSelection_/",$name)){
151 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
152 $this->Devices[$Name]['RECORDS'][$RecordID]['type'] = $value;
153 }
154 }
155 }
157 /* check for renamed entries
158 */
159 foreach($_POST as $name => $value){
161 /* Extract informations out of post name
162 */
163 $tmp = preg_replace("/^.*_/","\\1",$name);
164 $tmp2 = split("\|",$tmp);
166 if(count($tmp2) != 2) continue;
168 $Name = base64_decode($tmp2[0]);
169 $RecordID = $tmp2[1];
171 /* Host renamed
172 */
173 if(preg_match("/RenameHost_/",$name)){
174 if((isset($this->Devices[$Name])) && ($Name != $value)){
176 if(isset($this->Devices[$value])){
177 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));
178 }else{
179 $this->Devices[$value] = $this->Devices[$Name];
180 unset($this->Devices[$Name]);
181 }
182 }
183 }
184 }
185 }
188 /* check something
189 */
190 function check()
191 {
192 /* Call common method to give check the hook */
193 $message= plugin::check();
195 $ldap = $this->config->get_ldap_link();
196 $ldap->cd($this->config->current['BASE']);
198 $names = array();
200 foreach($this->Devices as $DevName => $device){
202 /* skip checking empty attributes */
203 if(count($this->Devices[$DevName]['RECORDS']) == 0){
204 return;
205 }
207 /* Checking entry name
208 */
209 if((!is_uid($DevName)) | (empty($DevName))){
210 $message[] = sprintf(_("Entry name '%s' contains invalid characters."), $DevName);
211 }
213 /* Renaming check for existing devices
214 */
215 if(isset($device['OrigCn']) && ($DevName != $device['OrigCn'] )){
216 $ldap->cd($this->config->current['BASE']);
217 $ldap->search("(relativeDomainName=".$DevName.")",array("relativeDomainName"));
218 if($ldap->count()){
219 $message[] = sprintf(_("Can not rename '%s' to '%s',the destination name already exists."),$device['OrigCn'],$DevName);
220 }
221 }elseif(!isset($device['OrigCn'])){
222 $ldap->cd($this->config->current['BASE']);
223 $ldap->search("(relativeDomainName=".$DevName.")",array("relativeDomainName"));
224 if($ldap->count()){
225 $message[] = sprintf(_("Can not create '%s',the destination name already exists."),$DevName);
226 }
227 }
229 /* Check names
230 */
231 if(!isset($names[$DevName])){
232 $names[$DevName] = "";
233 }else{
234 $message[] = sprintf(_("The name '%s' is used more than once."),$DevName);
235 }
237 /* Names should be written in lowercase
238 */
241 if(strtolower($DevName) != $DevName){
242 $message[] = sprintf(_("The host name '%s' should be written in lowercase."), $DevName);
243 }
245 /* Check records
246 */
247 $singleEntries = array("cNAMERecord","pTRRecord");
249 $tmp = array();
250 $tmp2 = array();
251 foreach($device['RECORDS'] as $Num => $Rec){
253 /* Check for multiple use of unique record types
254 */
255 if(in_array($Rec['type'],$singleEntries)){
256 if(!isset($tmp[$Rec['type']])){
257 $tmp[$Rec['type']] = "";
258 }else{
259 $message[] = sprintf(_("The record type '%s' is a unique type and can't be defined twice."),$type);
260 }
261 }
263 /* Check for empty / duplicate entries in record array
264 */
265 if(empty($Rec['value'])){
266 $message[] = sprintf(_("There is an empty '%s' for host '%s'."),$Rec['type'],$DevName);
267 }
269 /* Check for duplicate record entries
270 */
271 if(!isset($tmp[$Rec['type']][$Rec['value']])){
272 $tmp[$Rec['type']][$Rec['value']] = "";
273 }else{
274 $message[] = sprintf(_("There is a duplicate entry in '%s' for '%s'."),$Rec['type'],$DevName);
275 }
276 }
277 }
278 return ($message);
279 }
281 function save()
282 {
283 if($this->disableDialog) return;
285 $todo = array();
288 /* Create todolist
289 */
290 foreach($this->Devices as $name => $dev){
291 if(isset($dev['OrigCn'])){
292 if(count($dev['RECORDS'])){
293 $todo[] = getDNSHostEntriesDiff($this->config,$dev['OrigCn'],$dev,$name);
294 }else{
295 $dev['exists'] = false;
296 $todo[] = getDNSHostEntriesDiff($this->config,$dev['OrigCn'],$dev,$name);
297 }
298 }else{
299 if(count($dev['RECORDS'])){
300 $todo[] = getDNSHostEntriesDiff($this->config,"",$dev,$name);
301 }else{
302 $dev['exists'] = false;
303 $todo[] = getDNSHostEntriesDiff($this->config,"",$dev,$name);
304 }
305 }
306 }
308 $tmp = array();
309 $tmp['del'] = array();
310 $tmp['add'] = array();
311 $tmp['move'] = array();
312 foreach($todo as $to){
313 foreach($to as $type => $entries){
314 $tmp[$type] = array_merge($tmp[$type],$entries);
315 }
316 }
318 /* Get ldap link
319 */
320 $ldap = $this->config->get_ldap_link();
321 $ldap->cd ($this->config->current['BASE']);
323 /* move follwoing entries
324 */
325 foreach($tmp['move'] as $src => $dst){
326 $this->recursive_move($src,$dst);
327 }
329 /* Delete dns */
330 foreach($tmp['del'] as $dn => $del){
331 $ldap->cd($dn);
332 $ldap->rmdir_recursive($dn);
333 }
335 /* Add || Update new DNS entries
336 */
337 foreach($tmp['add'] as $dn => $attrs){
338 $ldap->cd($dn);
339 $ldap->cat($dn, array('dn'));
340 if(count($ldap->fetch())){
341 $ldap->cd($dn);
342 $ldap->modify ($attrs);
343 }else{
344 $ldap->cd($dn);
345 $ldap->add($attrs);
346 }
347 }
348 }
351 /* Create html table out of given entry
352 */
353 function generateRecordConfigurationRow($objKey){
355 /* Get some basic informations
356 */
357 $obj = $this->Devices[$objKey];
358 $objectName = $objKey;
360 /* Abort if emtpy
361 */
362 if(count($obj['RECORDS']) == 0) return "";
364 /* Set title
365 */
366 $str= "<br>";
368 $hostNameOnce = true;
370 /* Walk through all defined records
371 */
372 $str.= "<table cellspacing='0' cellpadding='0'>";
373 foreach($obj['RECORDS'] as $id => $record){
375 /* Create unique post name
376 */
377 $name = base64_encode($objKey)."|".$id;
379 $str .= "<tr><td style='width:170px;'>\n";
381 /* Only first host entry name should be editable
382 */
383 if($hostNameOnce){
384 $hostNameOnce = false;
385 $str .="<input type='text' name='RenameHost_".$name."' value='".$objectName."'>\n";
386 }
388 /* Create rest. Selectbox, icons ...
389 */
390 $str .="
391 </td>
392 <td style='width:90px;'>
393 ".$this->createRecordTypeSelection($record['type'],$name)."
394 </td>
395 <td>
396 <input type='text' value='".$record['value']."' name='ValueSelection_".$name."' style='width:250px;'>
397 </td>
398 <td style='width:50px;text-align:right;'>
399 <input type='image' name='AddRecord_".$name."' src='images/list_new.png' alt='"._("Add")."' title='"._("Add")."'>
400 <input type='image' name='RemoveRecord_".$name."' src='images/edittrash.png' alt='"._("Remove")."' title='"._("Remove")."'>
401 </td>
402 </tr>";
403 }
404 $str .="</table>";
405 return($str);
406 }
409 /* Create selectbox with all available option types
410 */
411 function createRecordTypeSelection($id,$refID){
413 $str = "\n<select name='RecordTypeSelection_".$refID."'>";
414 foreach($this->RecordTypes as $type => $atr) {
415 if($id == $type){
416 $str .="\n<option value='".$type."' selected >".strtoupper(preg_replace("/record/i","",$type))."</option>";
417 }else{
418 $str .="\n<option value='".$type."'>".strtoupper(preg_replace("/record/i","",$type))."</option>";
419 }
420 }
421 $str.= "\n</select>";
422 return($str);
423 }
426 function remove_from_parent()
427 {
428 }
430 }
432 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
433 ?>