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 /* Get ldap connection
36 */
37 $ldap = $this->config->get_ldap_link();
38 $ldap->cd($this->config->current['BASE']);
40 /* Get zone content
41 */
42 $ldap->ls("(&(objectClass=dNSZone)(!(relativeDomainName=@)))",$this->dn,array("relativeDomainName"));
44 while($attrs = $ldap->fetch()){
45 $this->Devices[$attrs['relativeDomainName'][0]] = getDNSHostEntries($config,$attrs['relativeDomainName'][0],true);
46 $this->Devices[$attrs['relativeDomainName'][0]]['OrigCn'] = $attrs['relativeDomainName'][0];
47 }
49 $ldap->cat($this->dn,array("objectClass"));
51 $this->disableDialog = true;
52 if(count($this->Devices)|| $ldap->count()){
53 $this->disableDialog = false;
54 }
55 }
57 function execute()
58 {
59 plugin::execute();
62 /* Check posts for operations ...
63 */
64 $once = true;
65 foreach($_POST as $name => $value){
67 /* Add a new Record in given object
68 */
70 $tmp = preg_replace("/^.*_(.*)_.*$/","\\1",$name);
71 $tmp2 = split("\|",$tmp);
73 /* Add new host entry
74 */
75 if((preg_match("/^UserRecord_?/",$name)) && ($once)){
76 $once = false;
77 $entry = getDNSHostEntries($this->config,"",true);
78 $entry['exists'] = true;
79 $entry['zoneName'] = strtoupper($this->attrs['cn'][0])."/".$this->zoneName;
80 $entry['RECORDS'][] = array("type" => "aRecord" , "value"=>"");
81 $this->Devices[_("New entry")] = $entry;
82 }
84 if(count($tmp2) != 2) continue;
86 $Name = base64_decode($tmp2[0]);
87 $RecordID = $tmp2[1];
89 /* Add new REcord
90 */
91 if((preg_match("/^AddRecord_/",$name)) && ($once)){
92 $once = false;
93 $this->Devices[$Name]['RECORDS'][] = $this->Devices[$Name]['RECORDS'][$RecordID];
94 }
96 /* Remove record from given dn
97 */
98 if((preg_match("/^RemoveRecord_/",$name)) && ($once)){
99 $once = false;
100 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
101 unset($this->Devices[$Name]['RECORDS'][$RecordID]);
102 }
103 }
105 }
107 /* Fill templating stuff */
108 $smarty= get_smarty();
109 $display= "";
111 $table = "";
112 foreach($this->Devices as $key => $dev){
113 $table .= $this->generateRecordConfigurationRow($key);
114 }
116 $smarty->assign("disableDialog",$this->disableDialog);
117 $smarty->assign("table",$table);;
118 $display.= $smarty->fetch(get_template_path('servDNSeditZoneEntries.tpl', TRUE));
119 return($display);
120 }
123 function save_object()
124 {
125 /* Possible attributes posted
126 */
127 foreach($_POST as $name => $value){
129 /* Extract informations out of post name
130 */
131 $tmp = preg_replace("/^.*_/","\\1",$name);
132 $tmp2 = split("\|",$tmp);
134 if(count($tmp2) != 2) continue;
136 $Name = base64_decode($tmp2[0]);
137 $RecordID = $tmp2[1];
139 /* Check for value change
140 */
141 if(preg_match("/ValueSelection_/",$name)){
142 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
143 $this->Devices[$Name]['RECORDS'][$RecordID]['value'] = $value;
144 }
145 }
147 /* record type changed
148 */
149 if(preg_match("/^RecordTypeSelection_/",$name)){
150 if(isset($this->Devices[$Name]['RECORDS'][$RecordID])){
151 $this->Devices[$Name]['RECORDS'][$RecordID]['type'] = $value;
152 }
153 }
154 }
156 /* check for renamed entries
157 */
158 foreach($_POST as $name => $value){
160 /* Extract informations out of post name
161 */
162 $tmp = preg_replace("/^.*_/","\\1",$name);
163 $tmp2 = split("\|",$tmp);
165 if(count($tmp2) != 2) continue;
167 $Name = base64_decode($tmp2[0]);
168 $RecordID = $tmp2[1];
170 /* Host renamed
171 */
172 if(preg_match("/RenameHost_/",$name)){
173 if((isset($this->Devices[$Name])) && ($Name != $value)){
175 if(isset($this->Devices[$value])){
176 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));
177 }else{
178 $this->Devices[$value] = $this->Devices[$Name];
179 unset($this->Devices[$Name]);
180 }
181 }
182 }
183 }
184 }
187 /* check something
188 */
189 function check()
190 {
191 /* Call common method to give check the hook */
192 $message= plugin::check();
194 $ldap = $this->config->get_ldap_link();
195 $ldap->cd($this->config->current['BASE']);
197 $names = array();
198 foreach($this->Devices as $DevName => $device){
200 /* Don't need to check empty values ... */
201 if(!count($device['RECORDS'])) continue;
203 /* Checking entry name
204 */
205 if((!is_uid($DevName)) | (empty($DevName))){
206 $message[] = sprintf(_("Entry name '%s' contains invalid characters."), $DevName);
207 }
209 /* Renaming check for existing devices
210 */
211 if(isset($device['OrigCn']) && ($DevName != $device['OrigCn'] )){
212 $ldap->cd($this->config->current['BASE']);
213 $ldap->search("(relativeDomainName=".$DevName.")",array("relativeDomainName"));
214 if($ldap->count()){
215 $message[] = sprintf(_("Can not rename '%s' to '%s',the destination name already exists."),$device['OrigCn'],$DevName);
216 }
217 }elseif(!isset($device['OrigCn'])){
218 $ldap->cd($this->config->current['BASE']);
219 $ldap->search("(relativeDomainName=".$DevName.")",array("relativeDomainName"));
220 if($ldap->count()){
221 $message[] = sprintf(_("Can not create '%s',the destination name already exists."),$DevName);
222 }
223 }
225 /* Check names
226 */
227 if(!isset($names[$DevName])){
228 $names[$DevName] = "";
229 }else{
230 $message[] = sprintf(_("The name '%s' is used more than once."),$DevName);
231 }
233 /* Names should be written in lowercase
234 */
235 # if(strtolower($DevName) != $DevName){
236 # $message[] = sprintf(_("The host name '%s' should be written in lowercase."), $DevName);
237 # }
239 /* Check records
240 */
241 $singleEntries = array("cNAMERecord","pTRRecord");
243 $tmp = array();
244 $tmp2 = array();
245 foreach($device['RECORDS'] as $Num => $Rec){
247 /* Check for multiple use of unique record types
248 */
249 if(in_array($Rec['type'],$singleEntries)){
250 if(!isset($tmp[$Rec['type']])){
251 $tmp[$Rec['type']] = "";
252 }else{
253 $message[] = sprintf(_("The record type '%s' is a unique type and can't be defined twice."),$type);
254 }
255 }
257 /* Check for empty / duplicate entries in record array
258 */
259 if(empty($Rec['value'])){
260 $message[] = sprintf(_("There is an empty '%s' for host '%s'."),$Rec['type'],$DevName);
261 }
263 /* Check for duplicate record entries
264 */
265 if(!isset($tmp[$Rec['type']][$Rec['value']])){
266 $tmp[$Rec['type']][$Rec['value']] = "";
267 }else{
268 $message[] = sprintf(_("There is a duplicate entry in '%s' for '%s'."),$Rec['type'],$DevName);
269 }
270 }
271 }
272 return ($message);
273 }
275 function save()
276 {
277 if($this->disableDialog) return;
279 $todo = array();
281 /* Create todolist
282 */
283 foreach($this->Devices as $name => $dev){
284 if(isset($dev['OrigCn'])){
285 if(count($dev['RECORDS'])){
286 $todo[] = getDNSHostEntriesDiff($this->config,$dev['OrigCn'],$dev,$name);
287 }else{
288 $dev['exists'] = false;
289 $todo[] = getDNSHostEntriesDiff($this->config,$dev['OrigCn'],$dev,$name);
290 }
291 }else{
292 if(count($dev['RECORDS'])){
293 $todo[] = getDNSHostEntriesDiff($this->config,"",$dev,$name);
294 }else{
295 $dev['exists'] = false;
296 $todo[] = getDNSHostEntriesDiff($this->config,"",$dev,$name);
297 }
298 }
299 }
301 $tmp = array();
302 $tmp['del'] = array();
303 $tmp['add'] = array();
304 $tmp['move'] = array();
305 foreach($todo as $to){
306 foreach($to as $type => $entries){
307 $tmp[$type] = array_merge($tmp[$type],$entries);
308 }
309 }
311 /* Get ldap link
312 */
313 $ldap = $this->config->get_ldap_link();
314 $ldap->cd ($this->config->current['BASE']);
316 /* move follwoing entries
317 */
318 foreach($tmp['move'] as $src => $dst){
319 $this->recursive_move($src,$dst);
320 }
322 /* Delete dns */
323 foreach($tmp['del'] as $dn => $del){
324 $ldap->cd($dn);
325 $ldap->rmdir_recursive($dn);
326 }
328 /* Add || Update new DNS entries
329 */
330 foreach($tmp['add'] as $dn => $attrs){
331 $ldap->cd($dn);
332 $ldap->cat($dn, array('dn'));
333 if(count($ldap->fetch())){
334 $ldap->cd($dn);
335 $ldap->modify ($attrs);
336 }else{
337 $ldap->cd($dn);
338 $ldap->add($attrs);
339 }
340 }
341 }
344 /* Create html table out of given entry
345 */
346 function generateRecordConfigurationRow($objKey){
348 /* Get some basic informations
349 */
350 $obj = $this->Devices[$objKey];
351 $objectName = $objKey;
353 /* Abort if emtpy
354 */
355 if(count($obj['RECORDS']) == 0) return "";
357 /* Set title
358 */
359 $str= "<br>";
361 $hostNameOnce = true;
363 /* Walk through all defined records
364 */
365 $str.= "<table cellspacing='0' cellpadding='0'>";
366 foreach($obj['RECORDS'] as $id => $record){
368 /* Create unique post name
369 */
370 $name = base64_encode($objKey)."|".$id;
372 $str .= "<tr><td style='width:170px;'>\n";
374 /* Only first host entry name should be editable
375 */
376 if($hostNameOnce){
377 $hostNameOnce = false;
378 $str .="<input type='text' name='RenameHost_".$name."' value='".$objectName."'>\n";
379 }
381 /* Create rest. Selectbox, icons ...
382 */
383 $str .="
384 </td>
385 <td style='width:90px;'>
386 ".$this->createRecordTypeSelection($record['type'],$name)."
387 </td>
388 <td>
389 <input type='text' value='".$record['value']."' name='ValueSelection_".$name."' style='width:250px;'>
390 </td>
391 <td style='width:50px;text-align:right;'>
392 <input type='image' name='AddRecord_".$name."' src='images/list_new.png' alt='"._("Add")."' title='"._("Add")."'>
393 <input type='image' name='RemoveRecord_".$name."' src='images/edittrash.png' alt='"._("Remove")."' title='"._("Remove")."'>
394 </td>
395 </tr>";
396 }
397 $str .="</table>";
398 return($str);
399 }
402 /* Create selectbox with all available option types
403 */
404 function createRecordTypeSelection($id,$refID){
406 $str = "\n<select name='RecordTypeSelection_".$refID."'>";
407 foreach($this->RecordTypes as $type => $atr) {
408 if($id == $type){
409 $str .="\n<option value='".$type."' selected >".strtoupper(preg_replace("/record/i","",$type))."</option>";
410 }else{
411 $str .="\n<option value='".$type."'>".strtoupper(preg_replace("/record/i","",$type))."</option>";
412 }
413 }
414 $str.= "\n</select>";
415 return($str);
416 }
419 function remove_from_parent()
420 {
421 }
423 }
425 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
426 ?>