Handle hostnames with upper-case letters
[webmin.git] / bind8 / mass_create.cgi
1 #!/usr/local/bin/perl
2 # Actually create multiple zones
3
4 require './bind8-lib.pl';
5 &ReadParseMime();
6 &ui_print_unbuffered_header(undef, $text{'mass_title'}, "");
7 &error_setup($text{'mass_err'});
8 $conf = &get_config();
9 $access{'ro'} && &error($text{'master_ero'});
10
11 # Check if the template needs IPs
12 if ($in{'tmpl'}) {
13         for($i=0; $config{"tmpl_$i"}; $i++) {
14                 @c = split(/\s+/, $config{"tmpl_$i"}, 3);
15                 if ($c[1] eq 'A' && !$c[2]) {
16                         $tmpl_ip++;
17                         }
18                 }
19         }
20
21 # Build map of taken zones
22 if ($in{'view'} ne '') {
23         # In some view
24         @zones = grep { $_->{'viewindex'} eq $in{'view'} &&
25                         $_->{'type'} ne 'view' }
26                       &list_zone_names();
27         $view = $conf->[$in{'view'}];
28         &can_edit_view($view) || &error($text{'mass_eviewcannot'});
29         $vn = $view->{'value'};
30         }
31 else {
32         # At top-level
33         @zones = grep { !$_->{'view'} && $_->{'type'} ne 'view' }
34                       &list_zone_names();
35         $vn = undef;
36         }
37 %taken = map { $_->{'name'}, $_ } @zones;
38
39 # Get zone defaults
40 &get_zone_defaults(\%zd);
41
42 if ($in{'local'}) {
43         &allowed_zone_file(\%access, $in{'local'}) ||
44                 &error($text{'mass_elocalcannot'});
45         $local = &read_file_contents($in{'local'});
46         $local || &error($text{'mass_elocal'});
47         print "<b>",&text('mass_dolocal', "<tt>$in{'local'}</tt>"),"</b><br>\n";
48         &execute_batchfile($local);
49         print "<b>",$text{'mass_done'},"</b><p>\n";
50         }
51 if ($in{'upload'}) {
52         print "<b>",&text('mass_doupload'),"</b><br>\n";
53         &execute_batchfile($in{'upload'});
54         print "<b>",$text{'mass_done'},"</b><p>\n";
55         }
56 if ($in{'text'}) {
57         print "<b>",&text('mass_dotext'),"</b><br>\n";
58         &execute_batchfile($in{'text'});
59         print "<b>",$text{'mass_done'},"</b><p>\n";
60         }
61
62 &webmin_log("mass", undef, $zonecount);
63 &ui_print_footer("", $text{'index_return'});
64
65 # execute_batchfile(data)
66 sub execute_batchfile
67 {
68 local @lines = split(/[\r\n]+/, $_[0]);
69 local $l;
70 local $lnum = 0;
71 foreach $l (@lines) {
72         $lnum++;
73         local @w = split(/:/, $l);
74         local $dom = $w[0];
75         if ($dom !~ /^[a-z0-9\.\-\_]+$/) {
76                 &line_error($l, $text{'mass_edom'});
77                 next;
78                 }
79         local $isrev = 0;
80         if (&check_ipaddress($dom)) {
81                 $dom = &ip_to_arpa($dom);
82                 $isrev = 1;
83                 }
84
85         # Check for a clash
86         if ($taken{$dom}) {
87                 &line_error($l, $text{'mass_etaken'});
88                 next;
89                 }
90
91         # Get the IP addresses
92         local @mips = split(/\s+/, $w[3]);
93         foreach $mip (@mips) {
94                 if (!&check_ipaddress($mip)) {
95                         &line_error($l, $text{'mass_eip'});
96                         next;
97                         }
98                 }
99
100         local $type = $w[1] || "master";
101         local $file = $w[2];
102         local $dir;
103         if ($type eq "master") {
104                 # Creating a master zone
105                 if (!$access{'master'}) {
106                         &line_error($l, $text{'mcreate_ecannot'});
107                         next;
108                         }
109
110                 # Work out the base
111                 $base = $config{'master_dir'} ? $config{'master_dir'} :
112                         $access{'dir'} eq '/' ? &base_directory($conf) :
113                                                 $access{'dir'};
114                 if ($base !~ /^([a-z]:)?\//) {
115                         # Master dir is relative .. make absolute
116                         $base = &base_directory()."/".$base;
117                         }
118
119                 # Make sure a template IP was given, if needed
120                 if ($tmpl_ip && !@mips) {
121                         &line_error($l, $text{'mass_etmpl'});
122                         next;
123                         }
124
125                 # Work out the filename
126                 if ($file) {
127                         if ($file !~ /^\//) {
128                                 $file = $base."/".$file;
129                                 }
130                         if (!&allowed_zone_file(\%access, $file)) {
131                                 &line_error($l, &text('create_efile2', $file));
132                                 next;
133                                 }
134                         }
135                 else {
136                         $file = &automatic_filename($dom, $isrev, $base, $vn);
137                         }
138                 if (-r &make_chroot($file)) {
139                         &line_error($l, &text('create_efile4', $file));
140                         next;
141                         }
142
143                 # Create the zone file and initial records
144                 local $master = $config{'default_prins'} ||
145                                 &get_system_hostname();
146                 $master =~ s/\.$//;
147                 $master .= ".";
148                 local $email = $config{'tmpl_email'} || "root\@$master";
149                 $email = &email_to_dotted($email);
150                 &create_master_records($file, $dom, $master, $email,
151                                        $zd{'refresh'}.$zd{'refunit'},
152                                        $zd{'retry'}.$zd{'retunit'},
153                                        $zd{'expiry'}.$zd{'expunit'},
154                                        $zd{'minimum'}.$zd{'minunit'},
155                                        1,
156                                        $in{'onslave'} && $access{'remote'},
157                                        $in{'tmpl'}, $mips[0]);
158
159                 # Create the zone directive
160                 $dir = { 'name' => 'zone',
161                          'values' => [ $dom ],
162                          'type' => 1,
163                          'members' => [ { 'name' => 'type',
164                                           'values' => [ 'master' ] },
165                                         { 'name' => 'file',
166                                           'values' => [ $file ] } ]
167                         };
168                 }
169         elsif ($type eq "slave" || $type eq "stub") {
170                 # Creating a slave or stub zone
171                 if (!$access{'slave'}) {
172                         &line_error($l, $text{'screate_ecannot1'});
173                         next;
174                         }
175
176                 # Work out the base
177                 $base = $config{'slave_dir'} ? $config{'slave_dir'} :
178                         $access{'dir'} eq '/' ? &base_directory($conf) :
179                                                 $access{'dir'};
180                 if ($base !~ /^([a-z]:)?\//) {
181                         # Slave dir is relative .. make absolute
182                         $base = &base_directory()."/".$base;
183                         }
184
185                 # Make sure some master IPs were given
186                 if (!@mips) {
187                         &line_error($l, $text{'mass_emips'});
188                         next;
189                         }
190
191                 # Work out the filename
192                 if ($file eq "none") {
193                         $file = undef;  # no file!
194                         }
195                 elsif ($file) {
196                         if ($file !~ /^\//) {
197                                 $file = $base."/".$file;
198                                 }
199                         if (!&allowed_zone_file(\%access, $file)) {
200                                 &line_error($l, &text('create_efile2', $file));
201                                 next;
202                                 }
203                         }
204                 else {
205                         $file = &automatic_filename($dom, $isrev, $base, $vn);
206                         }
207
208                 # Create the file now
209                 if ($file) {
210                         if (!open(ZONE, ">".&make_chroot($file))) {
211                                 &line_error($l, &text('create_efile3',
212                                                       $file, $!));
213                                 next;
214                                 }
215                         close(ZONE);
216                         &set_ownership(&make_chroot($file));
217                         }
218
219                 # Create the structure
220                 local @mdirs = map { { 'name' => $_ } } @mips;
221                 local $masters = { 'name' => 'masters',
222                                    'type' => 1,
223                                    'members' => \@mdirs };
224                 $dir = { 'name' => 'zone',
225                          'values' => [ $dom ],
226                          'type' => 1,
227                          'members' => [ { 'name' => 'type',
228                                           'values' => [ $type ] },
229                                         $masters
230                                       ]
231                         };
232                 if ($file) {
233                         push(@{$dir->{'members'}},
234                                 { 'name' => 'file',
235                                   'values' => [ $file ] });
236                         }
237                 }
238         elsif ($type eq "forward") {
239                 # Creating a forward
240                 if (!$access{'forward'}) {
241                         &line_error($l, $text{'fcreate_ecannot'});
242                         next;
243                         }
244
245                 # Make sure some master IPs were given
246                 if (!@mips) {
247                         &line_error($l, $text{'mass_emips'});
248                         next;
249                         }
250
251                 # Create the structure
252                 local @mdirs = map { { 'name' => $_ } } @mips;
253                 local $masters = { 'name' => 'forwarders',
254                                    'type' => 1,
255                                    'members' => \@mdirs };
256                 $dir = { 'name' => 'zone',
257                          'values' => [ $dom ],
258                          'type' => 1,
259                          'members' => [ { 'name' => 'type',
260                                           'values' => [ 'forward' ] },
261                                         $masters
262                                       ]
263                         };
264                 }
265
266         else {
267                 &line_error($l, $text{'mass_etype'});
268                 next;
269                 }
270
271         if ($dir) {
272                 # Add the zone structure
273                 &create_zone($dir, $conf, $in{'view'});
274                 &set_ownership(&make_chroot($named_conf));
275                 &add_zone_access($dom);
276                 $taken{$dom}++;
277                 &line_ok($dom, $type);
278                 $zonecount++;
279                 }
280
281         if ($type eq "master" && $in{'onslave'} && $access{'remote'}) {
282                 # Create on slave servers
283                 local @slaveerrs = &create_on_slaves($dom,
284                   $config{'this_ip'} || &to_ipaddress(&get_system_hostname()),
285                   undef, undef, $vn);
286                 print "&nbsp;&nbsp;\n";
287                 if (@slaveerrs) {
288                         $serrs = join(", ", map { "$_->[0]->{'host'} : $_->[1]" } @slaveerrs);
289                         print "<font color=#ff0000>",
290                               &text('mass_eonslave', $serrs),"</font><br>\n";
291                         }
292                 else {
293                         print &text('mass_addedslaves', $dom),"<br>\n";
294                         }
295                 }
296         }
297 }
298
299 sub line_error
300 {
301 print "<font color=#ff0000>",&text('mass_eline', $lnum, $_[1], $_[0]),
302       "</font><br>\n";
303 }
304
305 sub line_ok
306 {
307 print &text('mass_added'.$_[1], $_[0]),"<br>\n";
308 }
309