ea93d3ccd13ddfcd0749d2f59be4a0bac448c641
[samba.git] / source / web / swat.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    html smb.conf editing - prototype only
5    Copyright (C) Andrew Tridgell 1997-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #ifdef SYSLOG
23 #undef SYSLOG
24 #endif
25
26 #include "includes.h"
27 #include "smb.h"
28
29 #define GLOBALS_SNUM -2
30 #define DEFAULTS_SNUM -1
31
32 static pstring servicesf = CONFIGFILE;
33
34
35 /* start the page with standard stuff */
36 static void print_header(void)
37 {
38         printf("Expires: %s\r\n", http_timestring(time(NULL)));
39         printf("Content-type: text/html\r\n\r\n");
40         printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
41         printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY>\n\n");
42 }
43
44
45 /* finish off the page */
46 static void print_footer(void)
47 {
48         printf("\n</BODY>\n</HTML>\n");
49 }
50
51 /* include a lump of html in a page */
52 static void include_html(char *fname)
53 {
54         FILE *f = fopen(fname,"r");
55         char buf[1024];
56         int ret;
57
58         if (!f) {
59                 printf("ERROR: Can't open %s\n", fname);
60                 return;
61         }
62
63         while (!feof(f)) {
64                 ret = fread(buf, 1, sizeof(buf), f);
65                 if (ret <= 0) break;
66                 fwrite(buf, 1, ret, stdout);
67         }
68
69         fclose(f);
70 }
71
72
73 /* display one editable parameter */
74 static void show_parameter(int snum, struct parm_struct *parm)
75 {
76         int i;
77         void *ptr = parm->ptr;
78
79         if (parm->class == P_LOCAL) {
80                 ptr = lp_local_ptr(snum, ptr);
81         }
82
83         printf("<tr><td><A HREF=\"help/parameters.html#%s\">?</A> %s</td><td>", 
84                parm->label, parm->label);
85
86         switch (parm->type) {
87         case P_CHAR:
88                 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
89                        parm->label, *(char *)ptr);
90                 break;
91
92         case P_STRING:
93         case P_USTRING:
94                 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
95                        parm->label, *(char **)ptr);
96                 break;
97
98         case P_GSTRING:
99         case P_UGSTRING:
100                 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
101                        parm->label, (char *)ptr);
102                 break;
103
104         case P_BOOL:
105                 printf("<input type=radio name=\"parm_%s\" value=Yes %s>yes&nbsp;&nbsp;", parm->label, (*(BOOL *)ptr)?"CHECKED":"");
106                 printf("<input type=radio name=\"parm_%s\" value=No %s>no", parm->label, (*(BOOL *)ptr)?"":"CHECKED");
107                 break;
108
109         case P_BOOLREV:
110                 printf("<input type=radio name=\"parm_%s\" value=Yes %s>yes&nbsp;&nbsp;", parm->label, (*(BOOL *)ptr)?"":"CHECKED");
111                 printf("<input type=radio name=\"parm_%s\" value=No %s>no", parm->label, (*(BOOL *)ptr)?"CHECKED":"");
112                 break;
113
114         case P_INTEGER:
115                 printf("<input type=text size=8 name=\"parm_%s\" value=%d>", parm->label, *(int *)ptr);
116                 break;
117
118         case P_OCTAL:
119                 printf("<input type=text size=8 name=\"parm_%s\" value=0%o>", parm->label, *(int *)ptr);
120                 break;
121
122         case P_ENUM:
123                 for (i=0;parm->enum_list[i].name;i++)
124                         printf("<input type=radio name=\"parm_%s\" value=%s %s>%s&nbsp;&nbsp;", 
125                                parm->label, parm->enum_list[i].name, 
126                                (*(int *)ptr)==parm->enum_list[i].value?"CHECKED":"", 
127                                parm->enum_list[i].name);
128                 break;
129                         
130         }
131         printf("</td></tr>\n");
132 }
133
134 /* display a set of parameters for a service */
135 static void show_parameters(int snum, int allparameters, int advanced, int printers)
136 {
137         int i = 0;
138         struct parm_struct *parm;
139
140         printf("<table>\n");
141
142         while ((parm = lp_next_parameter(snum, &i, allparameters))) {
143                 if (parm->flags & FLAG_HIDE) continue;
144                 if (!advanced) {
145                         if (!printers && !(parm->flags & FLAG_BASIC)) continue;
146                         if (printers && !(parm->flags & FLAG_PRINT)) continue;
147                 }
148                 show_parameter(snum, parm);
149         }
150         printf("</table>\n");
151 }
152
153
154 static int save_reload(void)
155 {
156         FILE *f;
157
158         f = fopen(servicesf,"w");
159         if (!f) {
160                 printf("failed to open %s for writing\n", servicesf);
161                 return 0;
162         }
163
164         fprintf(f, "# Samba config file created using SWAT\n");
165
166         lp_dump(f);
167
168         fclose(f);
169
170         lp_killunused(NULL);
171
172         if (!lp_load(servicesf,False)) {
173                 printf("Can't reload %s\n", servicesf);
174                 return 0;
175         }
176
177         return 1;
178 }
179
180
181
182 /* commit a set of parameters for a service */
183 static void commit_parameters(int snum)
184 {
185         int i = 0;
186         struct parm_struct *parm;
187         pstring label;
188         char *v;
189
190         while ((parm = lp_next_parameter(snum, &i, 1))) {
191                 sprintf(label, "parm_%s", parm->label);
192                 if ((v = cgi_variable(label))) {
193                         lp_do_parameter(snum, parm->label, v); 
194                 }
195         }
196
197         save_reload();
198 }
199
200
201 /* load the smb.conf file into loadparm. */
202 static void load_config(void)
203 {
204         if (!lp_load(servicesf,False)) {
205                 printf("<b>Can't load %s - using defaults</b><p>\n", 
206                        servicesf);
207         }
208 }
209
210 /* spit out the html for a link with an image */
211 static void image_link(char *name,char *hlink, char *src, int width, int height)
212 {
213         printf("<A HREF=\"%s\"><img width=%d height=%d src=\"%s\" alt=\"%s\"></A>\n", hlink, width, height, src, name);
214 }
215
216 /* display the main navigation controls at the top of each page along
217    with a title */
218 static void show_main_buttons(void)
219 {
220         printf("<H2 align=center>Samba Web Administration Tool</H2>\n");
221
222         image_link("Globals", "globals", "images/globals.gif", 50, 50);
223         image_link("Shares", "shares", "images/shares.gif", 50, 50);
224         image_link("Printers", "printers", "images/printers.gif", 50, 50);
225
226         printf("<HR>\n");
227 }
228
229 /* display a welcome page  */
230 static void welcome_page(void)
231 {
232         include_html("help/welcome.html");
233 }
234
235
236 /* display a globals editing page  */
237 static void globals_page(void)
238 {
239         int advanced = 0;
240
241         printf("<H2>Global Variables</H2>\n");
242
243         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
244                 advanced = 1;
245
246         if (cgi_variable("Commit")) {
247                 commit_parameters(GLOBALS_SNUM);
248         }
249
250         printf("<FORM method=post>\n");
251
252         printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
253         if (advanced == 0) {
254                 printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
255         } else {
256                 printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
257         }
258         printf("<p>\n");
259         
260         show_parameters(GLOBALS_SNUM, 1, advanced, 0);
261
262         if (advanced) {
263                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
264         }
265
266         printf("</form>\n");
267 }
268
269 /* display a shares editing page  */
270 static void shares_page(void)
271 {
272         char *share = cgi_variable("share");
273         char *s;
274         int snum=-1;
275         int i;
276         int advanced = 0;
277
278         if (share)
279                 snum = lp_servicenumber(share);
280
281         printf("<H2>Share Parameters</H2>\n");
282
283         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
284                 advanced = 1;
285
286         if (cgi_variable("Commit") && snum >= 0) {
287                 commit_parameters(snum);
288         }
289
290         if (cgi_variable("Delete") && snum >= 0) {
291                 lp_remove_service(snum);
292                 save_reload();
293                 share = NULL;
294                 snum = -1;
295         }
296
297         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
298                 lp_copy_service(DEFAULTS_SNUM, share);
299                 save_reload();
300                 snum = lp_servicenumber(share);
301         }
302
303         printf("<FORM method=post>\n");
304
305         printf("<table>\n");
306         printf("<tr><td><input type=submit name=selectshare value=\"Choose Share\"></td>\n");
307         printf("<td><select name=share>\n");
308         if (snum < 0)
309                 printf("<option value=\" \"> \n");
310         for (i=0;i<lp_numservices();i++) {
311                 s = lp_servicename(i);
312                 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
313                         printf("<option %s value=\"%s\">%s\n", 
314                                (share && strcmp(share,s)==0)?"SELECTED":"",
315                                s, s);
316                 }
317         }
318         printf("</select></td></tr><p>");
319
320         printf("<tr><td><input type=submit name=createshare value=\"Create Share\"></td>\n");
321         printf("<td><input type=text size=30 name=newshare></td></tr>\n");
322         printf("</table>");
323
324
325         if (snum >= 0) {
326                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
327                 printf("<input type=submit name=\"Delete\" value=\"Delete Share\">\n");
328                 if (advanced == 0) {
329                         printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
330                 } else {
331                         printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
332                 }
333                 printf("<p>\n");
334         }
335
336         if (snum >= 0) {
337                 show_parameters(snum, 1, advanced, 0);
338         }
339
340         if (advanced) {
341                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
342         }
343
344         printf("</FORM>\n");
345 }
346
347
348 /* display a printers editing page  */
349 static void printers_page(void)
350 {
351         char *share = cgi_variable("share");
352         char *s;
353         int snum=-1;
354         int i;
355         int advanced = 0;
356
357         if (share)
358                 snum = lp_servicenumber(share);
359
360         printf("<H2>Printer Parameters</H2>\n");
361
362         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
363                 advanced = 1;
364
365         if (cgi_variable("Commit") && snum >= 0) {
366                 commit_parameters(snum);
367         }
368
369         if (cgi_variable("Delete") && snum >= 0) {
370                 lp_remove_service(snum);
371                 save_reload();
372                 share = NULL;
373                 snum = -1;
374         }
375
376         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
377                 lp_copy_service(DEFAULTS_SNUM, share);
378                 snum = lp_servicenumber(share);
379                 lp_do_parameter(snum, "print ok", "Yes");
380                 save_reload();
381                 snum = lp_servicenumber(share);
382         }
383
384         printf("<FORM method=post>\n");
385
386         printf("<table>\n");
387         printf("<tr><td><input type=submit name=selectshare value=\"Choose Printer\"></td>\n");
388         printf("<td><select name=share>\n");
389         if (snum < 0 || !lp_print_ok(snum))
390                 printf("<option value=\" \"> \n");
391         for (i=0;i<lp_numservices();i++) {
392                 s = lp_servicename(i);
393                 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
394                         printf("<option %s value=\"%s\">%s\n", 
395                                (share && strcmp(share,s)==0)?"SELECTED":"",
396                                s, s);
397                 }
398         }
399         printf("</select></td></tr><p>");
400
401         printf("<tr><td><input type=submit name=createshare value=\"Create Printer\"></td>\n");
402         printf("<td><input type=text size=30 name=newshare></td></tr>\n");
403         printf("</table>");
404
405
406         if (snum >= 0) {
407                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
408                 printf("<input type=submit name=\"Delete\" value=\"Delete Printer\">\n");
409                 if (advanced == 0) {
410                         printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
411                 } else {
412                         printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
413                 }
414                 printf("<p>\n");
415         }
416
417         if (snum >= 0) {
418                 show_parameters(snum, 1, advanced, 1);
419         }
420
421         if (advanced) {
422                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
423         }
424
425         printf("</FORM>\n");
426 }
427
428
429 int main(int argc, char *argv[])
430 {
431         extern char *optarg;
432         extern int optind;
433         extern FILE *dbf;
434         int opt;
435         char *page;
436         int auth_required = 1;
437
438         /* just in case it goes wild ... */
439         alarm(300);
440
441         dbf = fopen("/dev/null", "w");
442
443         if (!dbf) dbf = stderr;
444
445         while ((opt = getopt(argc, argv,"s:a")) != EOF) {
446                 switch (opt) {
447                 case 's':
448                         pstrcpy(servicesf,optarg);
449                         break;    
450                 case 'a':
451                         auth_required = 0;
452                         break;    
453                 }
454         }
455
456         cgi_setup(SWATDIR, auth_required);
457
458         print_header();
459
460         charset_initialise();
461
462         /* if this binary is setuid then run completely as root */
463         setuid(0);
464
465         load_config();
466
467         cgi_load_variables(NULL);
468
469         show_main_buttons();
470
471         page = cgi_baseurl();
472
473         if (strcmp(page, "globals")==0) {
474                 globals_page();
475         } else if (strcmp(page,"shares")==0) {
476                 shares_page();
477         } else if (strcmp(page,"printers")==0) {
478                 printers_page();
479         } else {
480                 welcome_page();
481         }
482         
483         print_footer();
484         return 0;
485 }
486
487