Handle hostnames with upper-case letters
[webmin.git] / lpadmin / printconf-driver.pl
1 # printconf-driver.pl
2 # Functions for printer drivers as created by redhat 7.1
3
4 $mf_wrapper = "/usr/share/printconf/mf_wrapper";
5 @overview_files = ( "/usr/share/printconf/foomatic/data/00-overview.foo",
6                     "/usr/share/printconf/foomatic/rh-data/00-overview.foo" );
7 $mfomatic = "/usr/share/printconf/foomatic/mfomatic";
8 $ps_wrapper= "/usr/share/printconf/util/mf_postscript_wrapper";
9 $text_filter = "pipe/postscript/ /usr/bin/mpage -b ifdef(`PAGEsize', PAGEsize, Letter) -1 -o -P- -";
10 $default_filter = "cat/text/";
11 $smb_driver = "/usr/share/printconf/smbprint";
12
13 @paper_sizes = ( 'Letter', 'Legal', 'Executive',
14                  'A5', 'A4', 'A3' );
15
16 # is_windows_driver(path, &printer)
17 # Returns a driver structure if some path is a windows driver
18 sub is_windows_driver
19 {
20 local $sd = "$config{'spool_dir'}/$_[1]->{'name'}";
21 if ($_[1]->{'dev'} eq "|$smb_driver" && -r "$sd/script.cfg") {
22         # Looks like a redhat SMB driver
23         local %sconfig;
24         &read_env_file("$sd/script.cfg", \%sconfig);
25         $sconfig{'share'} =~ /^\\\\(.*)\\(.*)$/;
26         return { 'server' => $1,
27                  'share' => $2,
28                  'user' => $sconfig{'user'},
29                  'pass' => $sconfig{'password'},
30                  'workgroup' => $sconfig{'workgroup'},
31                  'program' => $_[0] };
32         }
33 return undef;
34
35 }
36
37 # is_driver(path, &printer)
38 # Returns a structure containing the details of a driver
39 # XXX do we need to support old redhat drivers?
40 sub is_driver
41 {
42 if (!$_[0]) {
43         return { 'mode' => 0,
44                  'desc' => "$text{'redhat_none'}" };
45         }
46 local $sd = "$config{'spool_dir'}/$_[1]->{'name'}";
47 if ($_[0] eq $mf_wrapper && -r "$sd/mf.cfg") {
48         # Looks like a new printconf driver
49         local %define;
50         &read_m4_file("$sd/mf.cfg", \%define);
51         if ($define{'PSfilter'} =~
52             /^filter\s+$ps_wrapper.*\s(\S+)-(\d+)\.foo$/) {
53                 # Has printer driver
54                 return { 'mode' => 1,
55                          'driver' => $1,
56                          'id' => $2,
57                          'paper' => $define{'PAGEsize'},
58                          'make' => $define{'MAKE'},
59                          'model' => $define{'MODEL'},
60                          'desc' => "$define{'MAKE'} $define{'MODEL'}" };
61                 }
62         elsif ($define{'PSfilter'} =~ /^filter\s+$ps_wrapper\s*$/) {
63                 # Postscript printer
64                 return { 'mode' => 1,
65                          'postscript' => 1,
66                          'paper' => $define{'PAGEsize'},
67                          'desc' => 'Postscript printer' };
68                 }
69         elsif ($define{'PSfilter'} eq 'text' &&
70                $define{'TEXTfilter'} eq 'text') {
71                 # Text only printer
72                 return { 'mode' => 1,
73                          'text' => 1,
74                          'desc' => 'Text printer' };
75                 }
76         }
77
78 # Some other kind of driver
79 return { 'mode' => 2,
80          'file' => $_[0],
81          'desc' => $_[0] };
82 }
83
84 # read_m4_file(file, &hash)
85 sub read_m4_file
86 {
87 open(CFG, $_[0]);
88 while(<CFG>) {
89         s/#.*$//; s/\r|\n//g;
90         if (/^\s*define\(([A-Za-z0-9\_]+)\s*,\s*`([^']*)'\)/) {
91                 $_[1]->{$1} = $2;
92                 }
93         elsif (/^\s*define\(([A-Za-z0-9\_]+)\s*,\s*([^\s\)]+)\)/) {
94                 $_[1]->{$1} = $2;
95                 }
96         }
97 close(CFG);
98 }
99
100 # create_windows_driver(&printer, &driver)
101 # Creates a new windows printer driver
102 sub create_windows_driver
103 {
104 local $sd = "$config{'spool_dir'}/$_[0]->{'name'}";
105
106 # Create the config file and driver
107 local %sconfig;
108 &read_file("$sd/script.cfg", \%sconfig);
109 $sconfig{'share'} = "\\\\$_[1]->{'server'}\\$_[1]->{'share'}";
110 $sconfig{'hostip'} = $_[1]->{'server'} eq $config{'hostip'} ?
111                         $sconfig{'hostip'} : undef;
112 $sconfig{'user'} = $_[1]->{'user'};
113 $sconfig{'password'} = $_[1]->{'pass'};
114 $sconfig{'workgroup'} = $_[1]->{'workgroup'};
115 &lock_file($sd);
116 mkdir($sd, 0755);
117 &unlock_file($sd);
118 &open_lock_tempfile(ENV, ">$sd/script.cfg");
119 &print_tempfile(ENV, "share='$sconfig{'share'}'\n");
120 &print_tempfile(ENV, "hostip=$sconfig{'hostip'}\n");
121 &print_tempfile(ENV, "user='$sconfig{'user'}'\n");
122 &print_tempfile(ENV, "password='$sconfig{'password'}'\n");
123 &print_tempfile(ENV, "workgroup='$sconfig{'workgroup'}'\n");
124 &close_tempfile(ENV);
125
126 # Set the print device
127 $_[0]->{'dev'} = "|$smb_driver";
128 return $_[1]->{'program'};
129 }
130
131 # create_driver(&printer, &driver)
132 # Creates a new local printer driver and returns the path
133 sub create_driver
134 {
135 local ($prn, $drv) = @_;
136 if ($drv->{'mode'} == 0) {
137         return undef;
138         }
139 elsif ($drv->{'mode'} == 2) {
140         return $drv->{'file'};
141         }
142 else {
143         # Create the config file
144         local $sd = "$config{'spool_dir'}/$_[0]->{'name'}";
145         mkdir($sd, 0755);
146         &lock_file("$sd/mf.cfg");
147         if ($drv->{'text'}) {
148                 %driver = ( 'MAKE', '',
149                             'MODEL', '',
150                             'COLOR', '',
151                             'PAGEsize', $_[1]->{'paper'},
152                             'TEXTfilter', 'text',
153                             'PSfilter', 'text',
154                             'PCLfilter', 'reject',
155                             'PJLfilter', 'reject',
156                             'DEFAULTfilter', $default_filter );
157                 }
158         elsif ($drv->{'postscript'}) {
159                 %driver = ( 'MAKE', '',
160                             'MODEL', '',
161                             'COLOR', '',
162                             'PAGEsize', $_[1]->{'paper'},
163                             'TEXTfilter', $text_filter,
164                             'PSfilter', "filter $ps_wrapper ",
165                             'PCLfilter', 'cat',
166                             'PJLfilter', 'cat',
167                             'DEFAULTfilter', $default_filter );
168                 }
169         else {
170                 local $base = "$drv->{'driver'}-$drv->{'id'}.foo";
171                 local $path;
172                 foreach $f (@overview_files) {
173                         local $d = $f; $d =~ s/\/[^\/]+$//;
174                         $path = "$d/$base" if (-r "$d/$base");
175                         }
176                 &system_logged("cp $path $sd");
177                 &read_m4_file("$sd/mf.cfg", \%driver);
178                 $driver{'MAKE'} = $drv->{'make'};
179                 $driver{'MODEL'} = $drv->{'model'};
180                 $driver{'COLOR'} = 'true';      # ???
181                 $driver{'PSfilter'} = "filter $ps_wrapper --mfomatic -d $base";
182                 $driver{'TEXTfilter'} = $text_filter;
183                 $driver{'PCLfilter'} = 'cat';
184                 $driver{'PJLfilter'} = 'cat';
185                 $driver{'PAGEsize'} = $_[1]->{'paper'};
186                 $driver{'DEFAULTfilter'} = $default_filter;
187                 }
188         &open_tempfile(CFG, ">$sd/mf.cfg");
189         foreach $d (keys %driver) {
190                 if ($driver{$d} =~ /`|'/) {
191                         &print_tempfile(CFG, "define($d, $driver{$d})dnl\n");
192                         }
193                 else {
194                         &print_tempfile(CFG, "define($d, `$driver{$d}')dnl\n");
195                         }
196                 }
197         &close_tempfile(CFG);
198         &unlock_file("$sd/mf.cfg");
199         return $mf_wrapper;
200         }
201 }
202
203 # delete_driver(name)
204 sub delete_driver
205 {
206 local $sd = "$config{'spool_dir'}/$_[0]";
207 unlink("$sd/mf.cfg", "$sd/account");
208 }
209
210 # driver_input(&printer, &driver)
211 sub driver_input
212 {
213 local ($prn, $drv) = @_;
214
215 printf "<tr> <td><input type=radio name=mode value=0 %s> %s</td>\n",
216         $drv->{'mode'} == 0 ? "checked" : "", $text{'redhat_none'};
217 print "<td>($text{'redhat_nonemsg'})</td> </tr>\n";
218
219 printf "<tr> <td><input type=radio name=mode value=2 %s> %s</td>\n",
220         $drv->{'mode'} == 2 ? "checked" : "", $text{'redhat_prog'};
221 printf "<td><input name=iface value=\"%s\" size=35></td> </tr>\n",
222         $drv->{'mode'} == 2 ? $drv->{'file'} : "";
223
224 printf "<tr> <td valign=top><input type=radio name=mode value=1 %s>\n",
225         $drv->{'mode'} == 1 ? "checked" : "";
226 print "$text{'redhat_driver'}</td> <td><table width=100%>";
227
228 print "<tr> <td valign=top><b>$text{'redhat_printer2'}</b></td>\n";
229 print "<td><select name=printer size=10 onChange='setdriver(0)'>\n";
230 printf "<option value=%s %s>%s\n",
231         'text', $drv->{'text'} ? 'selected' : '', "Text printer";
232 printf "<option value=%s %s>%s\n",
233         'postscript', $drv->{'postscript'} ? 'selected' : '',
234         "Postscript printer";
235
236 local $list = &list_printconf_drivers();
237 local $select_driver = 0;
238 foreach $k (sort { lc($a) cmp lc($b) } keys %$list) {
239         foreach $m (@{$list->{$k}}) {
240                 next if (!@{$m->{'drivers'}});
241                 printf "<option value='%s' %s>%s\n",
242                         join(";", $m->{'id'}, @{$m->{'drivers'}}),
243                         $drv->{'make'} eq $k &&
244                         $drv->{'model'} eq $m->{'model'} ? 'selected' : '',
245                         "$k $m->{'model'}";
246                 if ($drv->{'make'} eq $k && $drv->{'model'} eq $m->{'model'}) {
247                         $select_driver = &indexof($drv->{'driver'},
248                                                   @{$m->{'drivers'}});
249                         }
250                 }
251         }
252 print "</select><select name=driver size=10 width=100></select></td> </tr>\n";
253
254 local $foundp = 0;
255 print "<tr> <td><b>$text{'redhat_paper'}</b></td> <td><select name=paper>\n";
256 print "<option value='' selected>$text{'redhat_none'}\n" if (!$drv->{'paper'});
257 foreach $p (@paper_sizes) {
258         printf "<option %s>%s\n",
259                 $drv->{'paper'} eq $p ? 'selected' : '', $p;
260         $foundp++ if ($drv->{'paper'} eq $p);
261         }
262 printf "<option selected>$drv->{'paper'}\n" if (!$foundp && $drv->{'paper'});
263 print "</select></td> </tr>\n";
264
265 print "</table></td></tr>\n";
266 return <<EOF;
267 <script>
268 function setdriver(sel)
269 {
270 var idx = document.forms[0].printer.selectedIndex;
271 var v = new String(document.forms[0].printer.options[idx].value);
272 var vv = v.split(";");
273 var driver = document.forms[0].driver;
274 driver.length = 0;
275 for(var i=1; i<vv.length; i++) {
276         driver.options[i-1] = new Option(vv[i], vv[i]);
277         }
278 if (driver.length > 0) {
279         driver.options[sel].selected = true;
280         }
281 }
282 setdriver($select_driver);
283 </script>
284 EOF
285 }
286
287 # parse_driver()
288 # Parse driver selection from %in and return a driver structure
289 sub parse_driver
290 {
291 if ($in{'mode'} == 0) {
292         return { 'mode' => 0 };
293         }
294 elsif ($in{'mode'} == 2) {
295         (-x $in{'iface'}) || &error(&text('redhat_eprog', $in{'iface'}));
296         return { 'mode' => 2,
297                  'file' => $in{'iface'} };
298         }
299 else {
300         $in{'printer'} || &error($text{'redhat_edriver'});
301         if ($in{'printer'} eq 'text') {
302                 return { 'mode' => 1,
303                          'paper' => $in{'paper'},
304                          'text' => 1 };
305                 }
306         elsif ($in{'printer'} eq 'postscript') {
307                 return { 'mode' => 1,
308                          'paper' => $in{'paper'},
309                          'postscript' => 1 };
310                 }
311         else {
312                 $in{'driver'} || &error($text{'redhat_edriver'});
313                 local @p = split(/;/, $in{'printer'});
314                 local $list = &list_printconf_drivers();
315                 local ($make, $model);
316                 foreach $k (keys %$list) {
317                         foreach $m (@{$list->{$k}}) {
318                                 if ($m->{'id'} == $p[0]) {
319                                         $make = $k;
320                                         $model = $m->{'model'};
321                                         }
322                                 }
323                         }
324                 return { 'mode' => 1,
325                          'paper' => $in{'paper'},
326                          'id' => $p[0],
327                          'make' => $make,
328                          'model' => $model,
329                          'driver' => $in{'driver'} };
330                 }
331         }
332 }
333
334 # list_printconf_drivers()
335 sub list_printconf_drivers
336 {
337 local %rv;
338 foreach $ov (@overview_files) {
339         next if (!-r $ov);
340         local $VAR1;
341         eval { do $ov };
342         next if ($@);
343         foreach $k (keys %$VAR1) {
344                 foreach $m (@{$VAR1->{$k}}) {
345                         push(@{$rv{$k}}, $m);
346                         }
347                 }
348         }
349 return \%rv;
350 }
351