Handle hostnames with upper-case letters
[webmin.git] / burner / save_profile.cgi
1 #!/usr/local/bin/perl
2 # Save, update or delete a burn profile, and maybe start the burn process
3
4 require './burner-lib.pl';
5 &ReadParse();
6 &error_setup($text{'save_err'});
7
8 if ($in{'id'}) {
9         $profile = &get_profile($in{'id'});
10         &can_use_profile($profile) || &error($text{'edit_ecannot'});
11         }
12 else {
13         $profile = { 'type' => $in{'type'} };
14         $access{'create'} || &error($text{'edit_ecannot'});
15         }
16
17 if (!$access{'edit'}) {
18         # No need to save, because we cannot
19         }
20 elsif ($in{'delete'}) {
21         # Just delete a profile
22         &delete_profile($profile);
23         }
24 else {
25         # Validate inputs
26         $in{'name'} || &error($text{'save_ename'});
27         $profile->{'name'} = $in{'name'};
28         if ($profile->{'type'} == 1) {
29                 # Validate single ISO inputs
30                 -r $in{'iso'} || &error($text{'save_eiso'});
31                 &can_directory($in{'iso'}) || &error($text{'save_ecannot1'});
32                 $profile->{'iso'} = $in{'iso'};
33                 $profile->{'isosize'} = $in{'isosize'};
34                 }
35         elsif ($profile->{'type'} == 2) {
36                 # Validate multi-directory inputs
37                 foreach $k (keys %$profile) {
38                         delete($profile->{$k}) if ($k =~ /^(source_|dest_)/);
39                         }
40                 local $j = 0;
41                 for($i=0; defined($s = $in{"source_$i"}); $i++) {
42                         next if (!$s);
43                         -d $s || -r $s || &error(&text('save_esource', $s));
44                         &can_directory($s) ||
45                                 &error(&text('save_ecannot2', $s));
46                         $in{"dest_$i"} =~ /^\/\S*$/ ||
47                                 &error(&text('save_edest', $s));
48                         $profile->{"source_$j"} = $s;
49                         $profile->{"dest_$j"} = $in{"dest_$i"};
50                         $j++;
51                         }
52                 $j || &error($text{'save_edirs'});
53                 $profile->{'rock'} = $in{'rock'};
54                 $profile->{'joliet'} = $in{'joliet'};
55                 $profile->{'netatalk'} = $in{'netatalk'};
56                 $profile->{'cap'} = $in{'cap'};
57                 $profile->{'long'} = $in{'long'};
58                 $profile->{'trans'} = $in{'trans'};
59                 $profile->{'volid'} = $in{'volid'};
60                 }
61         elsif ($profile->{'type'} == 3) {
62                 # Validate audio track inputs .. each must be either an
63                 # mp3 file or a directory
64                 foreach $k (keys %$profile) {
65                         delete($profile->{$k}) if ($k =~ /^source_/);
66                         }
67                 local $j = 0;
68                 for($i=0; defined($s = $in{"source_$i"}); $i++) {
69                         next if (!$s);
70                         -d $s || -r $s || &error(&text('save_emp3', $s));
71                         &can_directory($s) ||
72                                 &error(&text('save_ecannot3', $s));
73                         $profile->{"source_$j"} = $s;
74                         $j++;
75                         }
76                 $j || &error($text{'save_emp3s'});
77                 }
78         elsif ($profile->{'type'} == 4) {
79                 # Validate device file inputs
80                 if ($in{'sdev'} eq '') {
81                         -r $in{'other'} || &error($text{'save_eother'});
82                         $profile->{'sdev'} = $in{'other'};
83                         $profile->{'sdesc'} = $in{'other'};
84                         }
85                 else {
86                         $profile->{'sdev'} = $in{'sdev'};
87                         foreach $d (&list_cdrecord_devices()) {
88                                 $profile->{'sdesc'} = $d->{'name'}
89                                         if ($d->{'dev'} eq $profile->{'sdev'});
90                                 }
91                         }
92                 &can_directory($profile->{'sdev'}) ||
93                         &error($text{'save_ecannot4'});
94                 $profile->{'fly'} = $in{'fly'};
95                 $profile->{'srcdrv'} = $in{'srcdrv'};
96                 $profile->{'dstdrv'} = $in{'dstdrv'};
97                 }
98
99         # Save or create the profile
100         &save_profile($profile);
101         if ($in{'new'} && !&can_use_profile($profile)) {
102                 # Add to this user's ACL
103                 $access{'profiles'} = join(" ", split(/\s+/,
104                                 $access{'profiles'}), $profile->{'id'});
105                 &save_module_acl(\%access);
106                 }
107         }
108
109 if ($in{'burn'} || $in{'test'}) {
110         &ui_print_unbuffered_header(undef, $text{'burn_title'}, "");
111
112         if (!$config{'dev'}) {
113                 # Cannot burn until device is set
114                 print "<p>",&text('burn_edev', "edit_dev.cgi"),"<p>\n";
115                 &ui_print_footer("", $text{"index_return"});
116                 exit;
117                 }
118
119         local ($iso, $temp, $msg);
120         if ($profile->{'type'} == 1) {
121                 # No preparation to do
122                 $iso = $profile->{'iso'};
123                 $temp = 0;
124                 $msg = &text($in{'test'} ? 'burn_rutest1' : 'burn_rusure1',
125                              "<tt>$iso</tt>");
126                 }
127         elsif ($profile->{'type'} == 2) {
128                 # Need to build the ISO image
129                 $temp = 1;
130                 $iso = $config{'temp'} ? "$config{'temp'}/burner.iso"
131                                        : &tempname("burner.iso");
132                 local $cmd = "$config{'mkisofs'} -graft-points -o $iso";
133                 $cmd .= " -J" if ($profile->{'joliet'});
134                 $cmd .= " --netatalk" if ($profile->{'netatalk'});
135                 $cmd .= " --cap" if ($profile->{'cap'});
136                 $cmd .= " -l" if ($profile->{'long'});
137                 $cmd .= " -T" if ($profile->{'trans'});
138                 if ($profile->{'rock'} == 2) {
139                         $cmd .= " -r";
140                         }
141                 elsif ($profile->{'rock'} == 1) {
142                         $cmd .= " -R";
143                         }
144                 if ($profile->{'volid'}) {
145                         $cmd .= " -V '$profile->{'volid'}'";
146                         }
147                 $cmd .= " -N" if ($config{'novers'});
148                 $cmd .= " -U" if ($config{'notrans'});
149                 $cmd .= " -f" if ($config{'fsyms'});
150                 $cmd .= " -nobak" if ($config{'nobak'});
151                 for($i=0; defined($profile->{"source_$i"}); $i++) {
152                         local $d = quotemeta($profile->{"dest_$i"});
153                         $d .= "/" if ($d !~ /\/$/);
154                         $cmd .= " ".$d."=".quotemeta($profile->{"source_$i"});
155                         }
156
157                 print "<b>",&text('burn_mheader', "<tt>$cmd</tt>"),"</b><br>\n";
158                 print "<pre>";
159                 open(MAKE, "$cmd 2>&1 |");
160                 while(<MAKE>) {
161                         print &html_escape($_);
162                         }
163                 close(MAKE);
164                 print "</pre>\n";
165                 if ($?) {
166                         # Failed! No point going on ..
167                         unlink($iso);
168                         print "<b>$text{'burn_mfailed'}</b><br>\n";
169                         &ui_print_footer("", $text{'index_return'});
170                         exit;
171                         }
172                 $msg = $in{'test'} ? $text{'burn_rutest2'}
173                                    : $text{'burn_rusure2'};
174
175                 # Check the size of the resulting ISO
176                 local @st = stat($iso);
177                 local $mb = int($st[7]/(1024*1024));
178                 if ($mb > 700) {
179                         print "<b>",&text('burn_700', $mb),"</b><br>\n";
180                         }
181                 elsif ($mb > 650) {
182                         print "<b>",&text('burn_650', $mb),"</b><br>\n";
183                         }
184                 else {
185                         print &text('burn_size', $mb, 650),"<br>\n";
186                         }
187                 }
188         elsif ($profile->{'type'} == 3) {
189                 # To convert MP3s into data suitable for CDs, run
190                 # mpg123 -s -r 44100 file.mp3 >file.raw
191                 #
192                 # To burn to a CD, run
193                 # cdrecord dev=0,0,0 -v -audio -swab -pad speed=8 *.raw
194                 $temp = 1;
195                 $audio = $config{'temp'} ? "$config{'temp'}/burner.audio"
196                                          : &tempname("burner.audio");
197                 system("rm -rf $audio >/dev/null 2>&1");
198                 mkdir($audio, 0755);
199                 local (@srcs, $src);
200                 for($i=0; defined($src = $profile->{"source_$i"}); $i++) {
201                         if (-d $src) {
202                                 opendir(DIR, $src);
203                                 foreach $m (sort { $a cmp $b } readdir(DIR)) {
204                                         push(@srcs, "$src/$m")
205                                             if ($m !~ /^\./ && -r "$src/$m");
206                                         }
207                                 closedir(DIR);
208                                 }
209                         else {
210                                 push(@srcs, $src);
211                                 }
212                         }
213                 if (!@srcs) {
214                         # No files to burn
215                         print "<b>$text{'burn_nomp3s'}</b><br>\n";
216                         &ui_print_footer("", $text{'index_return'});
217                         exit;
218                         }
219
220                 local $mp3_basecmd = "$config{'mpg123'} -s -r 44100";
221                 local $wav_basecmd = "$config{'sox'} -V";
222                 print "<b>",&text('burn_mp3header', "<tt>$basecmd</tt>"),
223                       "</b><br>\n";
224                 print "<pre>";
225                 local $size;
226                 local $errors;
227                 for($i=0; $i<@srcs; $i++) {
228                         print "<b>$srcs[$i]</b><br>\n";
229                         local $dst = sprintf "%s/track-%3.3d.raw", $audio, $i;
230                         local $q = quotemeta($srcs[$i]);
231                         if ($srcs[$i] =~ /\.(mp3|mp2|mpg|mpeg)$/i) {
232                                 # Convert from MP3
233                                 open(MPG, "$mp3_basecmd $q 2>&1 >$dst |");
234                                 while(<MPG>) {
235                                         next if (/^High Performance/i ||
236                                                  /^Version\s+(\S+)/i ||
237                                                  /^Uses code from various people/i ||
238                                                  /^THIS SOFTWARE COMES WITH/i ||
239                                                  /^Directory: /i ||
240                                                  !/\S/);
241                                         print &html_escape($_);
242                                         }
243                                 close(MPG);
244                                 }
245                         elsif ($srcs[$i] =~ /\.(wav|ogg)$/i) {
246                                 # Convert from WAV or OGG
247                                 open(SOX, "$wav_basecmd $q -r 44100 $dst 2>&1 |");
248                                 while(<SOX>) {
249                                         print &html_escape($_);
250                                         }
251                                 close(SOX);
252                                 }
253                         if ($?) {
254                                 $errors++;
255                                 }
256                         else {
257                                 local @st = stat($dst);
258                                 $size += $st[7];
259                                 }
260                         print "<p>\n";
261                         }
262                 print "</pre>";
263                 if (!$size) {
264                         # Totally failed! No point going on ..
265                         system("rm -rf ".quotemeta($audio)." >/dev/null 2>&1");
266                         print "<b>$text{'burn_mp3failed'}</b><br>\n";
267                         &ui_print_footer("", $text{'index_return'});
268                         exit;
269                         }
270                 elsif ($errors) {
271                         # Some errors occurred
272                         print "<b>$text{'burn_mp3failed2'}</b><p>\n";
273                         }
274                 $msg = $in{'test'} ? $text{'burn_rutest3'}
275                                    : $text{'burn_rusure3'};
276
277                 # Check the total size
278                 local $mb = int($size/(1024*1024));
279                 if ($mb > 746) {
280                         print "<b>",&text('burn_746', $mb),"</b><br>\n";
281                         }
282                 elsif ($mb > 807) {
283                         print "<b>",&text('burn_807', $mb),"</b><br>\n";
284                         }
285                 else {
286                         print &text('burn_mp3size', $mb, 746),"<br>\n";
287                         }
288                 }
289         elsif ($profile->{'type'} == 4) {
290                 # No preparation to do for a copy
291                 $iso = $profile->{'sdev'};
292                 $temp = 0;
293                 $msg = &text('burn_rusure4', $profile->{'sdesc'});
294                 }
295
296         if ($in{'ask'}) {
297                 # Show confirm page
298                 print "<center><form action=burn.cgi>\n";
299                 print "<input type=hidden name=iso value='$iso'>\n";
300                 print "<input type=hidden name=audio value='$audio'>\n";
301                 print "<input type=hidden name=temp value='$temp'>\n";
302                 print "<input type=hidden name=id value='$profile->{'id'}'>\n";
303                 printf "<input type=hidden name=test value='%d'>\n",
304                         $in{'test'} ? 1 : 0;
305                 print "<b>$msg</b><p>\n";
306                 print "<input type=submit name=ok value='$text{'burn_ok'}'>\n";
307                 if ($temp) {
308                         print "<input type=submit name=cancel value='$text{'burn_cancel'}'>\n";
309                         }
310                 if (!$in{'test'}) {
311                         print "<br>$text{'burn_eject'}\n";
312                         print "<input type=radio name=eject value=1> $text{'yes'}\n";
313                         print "<input type=radio name=eject value=0 checked> $text{'no'}\n";
314                         }
315                 if ($profile->{'type'} != 4 ||
316                     $profile->{'sdev'} ne $config{'dev'}) {
317                         printf "<br>$text{'burn_bg'}\n";
318                         print "<input type=radio name=bg value=1> $text{'yes'}\n";
319                         print "<input type=radio name=bg value=0 checked> $text{'no'}\n";
320                         }
321
322                 if ($profile->{'type'} != 4) {
323                         print "<br>$text{'burn_blank'} <select name=blank>\n";
324                         print "<option value='' selected> $text{'no'}\n";
325                         print "<option value=fast> $text{'burn_bfast'}\n";
326                         print "<option value=all> $text{'burn_ball'}\n";
327                         print "</select>\n";
328                         }
329                 print "</form></center>\n";
330                 }
331         else {
332                 # Redirect to the burn page
333                 print "<script>document.location = \"burn.cgi?iso=$iso&audio=$audio&temp=$temp&id=$profile->{'id'}&test=",$in{'test'} ? 1 : 0,"\";</script>\n";
334                 }
335
336         &ui_print_footer("", $text{'index_return'});
337         }
338 else {
339         &redirect("");
340         }
341