added a "home" icon
[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("Home", "", "images/home.gif", 50, 50);
223         image_link("Globals", "globals", "images/globals.gif", 50, 50);
224         image_link("Shares", "shares", "images/shares.gif", 50, 50);
225         image_link("Printers", "printers", "images/printers.gif", 50, 50);
226
227         printf("<HR>\n");
228 }
229
230 /* display a welcome page  */
231 static void welcome_page(void)
232 {
233         include_html("help/welcome.html");
234 }
235
236
237 /* display a globals editing page  */
238 static void globals_page(void)
239 {
240         int advanced = 0;
241
242         printf("<H2>Global Variables</H2>\n");
243
244         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
245                 advanced = 1;
246
247         if (cgi_variable("Commit")) {
248                 commit_parameters(GLOBALS_SNUM);
249         }
250
251         printf("<FORM method=post>\n");
252
253         printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
254         if (advanced == 0) {
255                 printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
256         } else {
257                 printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
258         }
259         printf("<p>\n");
260         
261         show_parameters(GLOBALS_SNUM, 1, advanced, 0);
262
263         if (advanced) {
264                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
265         }
266
267         printf("</form>\n");
268 }
269
270 /* display a shares editing page  */
271 static void shares_page(void)
272 {
273         char *share = cgi_variable("share");
274         char *s;
275         int snum=-1;
276         int i;
277         int advanced = 0;
278
279         if (share)
280                 snum = lp_servicenumber(share);
281
282         printf("<H2>Share Parameters</H2>\n");
283
284         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
285                 advanced = 1;
286
287         if (cgi_variable("Commit") && snum >= 0) {
288                 commit_parameters(snum);
289         }
290
291         if (cgi_variable("Delete") && snum >= 0) {
292                 lp_remove_service(snum);
293                 save_reload();
294                 share = NULL;
295                 snum = -1;
296         }
297
298         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
299                 lp_copy_service(DEFAULTS_SNUM, share);
300                 save_reload();
301                 snum = lp_servicenumber(share);
302         }
303
304         printf("<FORM method=post>\n");
305
306         printf("<table>\n");
307         printf("<tr><td><input type=submit name=selectshare value=\"Choose Share\"></td>\n");
308         printf("<td><select name=share>\n");
309         if (snum < 0)
310                 printf("<option value=\" \"> \n");
311         for (i=0;i<lp_numservices();i++) {
312                 s = lp_servicename(i);
313                 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
314                         printf("<option %s value=\"%s\">%s\n", 
315                                (share && strcmp(share,s)==0)?"SELECTED":"",
316                                s, s);
317                 }
318         }
319         printf("</select></td></tr><p>");
320
321         printf("<tr><td><input type=submit name=createshare value=\"Create Share\"></td>\n");
322         printf("<td><input type=text size=30 name=newshare></td></tr>\n");
323         printf("</table>");
324
325
326         if (snum >= 0) {
327                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
328                 printf("<input type=submit name=\"Delete\" value=\"Delete Share\">\n");
329                 if (advanced == 0) {
330                         printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
331                 } else {
332                         printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
333                 }
334                 printf("<p>\n");
335         }
336
337         if (snum >= 0) {
338                 show_parameters(snum, 1, advanced, 0);
339         }
340
341         if (advanced) {
342                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
343         }
344
345         printf("</FORM>\n");
346 }
347
348
349 /* display a printers editing page  */
350 static void printers_page(void)
351 {
352         char *share = cgi_variable("share");
353         char *s;
354         int snum=-1;
355         int i;
356         int advanced = 0;
357
358         if (share)
359                 snum = lp_servicenumber(share);
360
361         printf("<H2>Printer Parameters</H2>\n");
362
363         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
364                 advanced = 1;
365
366         if (cgi_variable("Commit") && snum >= 0) {
367                 commit_parameters(snum);
368         }
369
370         if (cgi_variable("Delete") && snum >= 0) {
371                 lp_remove_service(snum);
372                 save_reload();
373                 share = NULL;
374                 snum = -1;
375         }
376
377         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
378                 lp_copy_service(DEFAULTS_SNUM, share);
379                 snum = lp_servicenumber(share);
380                 lp_do_parameter(snum, "print ok", "Yes");
381                 save_reload();
382                 snum = lp_servicenumber(share);
383         }
384
385         printf("<FORM method=post>\n");
386
387         printf("<table>\n");
388         printf("<tr><td><input type=submit name=selectshare value=\"Choose Printer\"></td>\n");
389         printf("<td><select name=share>\n");
390         if (snum < 0 || !lp_print_ok(snum))
391                 printf("<option value=\" \"> \n");
392         for (i=0;i<lp_numservices();i++) {
393                 s = lp_servicename(i);
394                 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
395                         printf("<option %s value=\"%s\">%s\n", 
396                                (share && strcmp(share,s)==0)?"SELECTED":"",
397                                s, s);
398                 }
399         }
400         printf("</select></td></tr><p>");
401
402         printf("<tr><td><input type=submit name=createshare value=\"Create Printer\"></td>\n");
403         printf("<td><input type=text size=30 name=newshare></td></tr>\n");
404         printf("</table>");
405
406
407         if (snum >= 0) {
408                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
409                 printf("<input type=submit name=\"Delete\" value=\"Delete Printer\">\n");
410                 if (advanced == 0) {
411                         printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
412                 } else {
413                         printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
414                 }
415                 printf("<p>\n");
416         }
417
418         if (snum >= 0) {
419                 show_parameters(snum, 1, advanced, 1);
420         }
421
422         if (advanced) {
423                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
424         }
425
426         printf("</FORM>\n");
427 }
428
429
430 int main(int argc, char *argv[])
431 {
432         extern char *optarg;
433         extern int optind;
434         extern FILE *dbf;
435         int opt;
436         char *page;
437         int auth_required = 1;
438
439         /* just in case it goes wild ... */
440         alarm(300);
441
442         dbf = fopen("/dev/null", "w");
443
444         if (!dbf) dbf = stderr;
445
446         while ((opt = getopt(argc, argv,"s:a")) != EOF) {
447                 switch (opt) {
448                 case 's':
449                         pstrcpy(servicesf,optarg);
450                         break;    
451                 case 'a':
452                         auth_required = 0;
453                         break;    
454                 }
455         }
456
457         cgi_setup(SWATDIR, auth_required);
458
459         print_header();
460
461         charset_initialise();
462
463         /* if this binary is setuid then run completely as root */
464         setuid(0);
465
466         load_config();
467
468         cgi_load_variables(NULL);
469
470         show_main_buttons();
471
472         page = cgi_baseurl();
473
474         if (strcmp(page, "globals")==0) {
475                 globals_page();
476         } else if (strcmp(page,"shares")==0) {
477                 shares_page();
478         } else if (strcmp(page,"printers")==0) {
479                 printers_page();
480         } else {
481                 welcome_page();
482         }
483         
484         print_footer();
485         return 0;
486 }
487
488