swat.c updated to use new yodl generated smb.conf.5.html file for help
[samba.git] / source / web / swat.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba Web Administration Tool
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 -1
30
31 static pstring servicesf = CONFIGFILE;
32
33
34 /* we need these because we link to locking*.o */
35  void become_root(BOOL save_dir) {}
36  void unbecome_root(BOOL restore_dir) {}
37 /* We need this because we link to password.o */
38 BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd, BOOL override) {return False;}
39
40 static int enum_index(int value, struct enum_list *enumlist)
41 {
42 int i;
43         for (i=0;enumlist[i].name;i++)
44                 if (value == enumlist[i].value) break;
45         return(i);
46 }
47
48 static char *fix_backslash(char *str)
49 {
50 static char newstring[1024];
51 char *p = newstring;
52
53         while (*str) {
54                 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
55                 else *p++ = *str;
56                 ++str;
57         }
58         *p = '\0';
59         return newstring;
60 }
61
62 static char *stripspace(char *str)
63 {
64 static char newstring[1024];
65 char *p = newstring;
66
67         while (*str) {
68                 if (*str != ' ') *p++ = *str;
69                 ++str;
70         }
71         *p = '\0';
72         return newstring;
73 }
74
75 static char *make_parm_name(char *label)
76 {
77 static char parmname[1024];
78 char *p = parmname;
79
80         while (*label) {
81                 if (*label == ' ') *p++ = '_';
82                 else *p++ = *label;
83                 ++label;
84         }
85         *p = '\0';
86         return parmname;
87 }
88
89
90 /* include a lump of html in a page */
91 static int include_html(char *fname)
92 {
93         FILE *f = fopen(fname,"r");
94         char buf[1024];
95         int ret;
96
97         if (!f) {
98                 printf("ERROR: Can't open %s\n", fname);
99                 return 0;
100         }
101
102         while (!feof(f)) {
103                 ret = fread(buf, 1, sizeof(buf), f);
104                 if (ret <= 0) break;
105                 fwrite(buf, 1, ret, stdout);
106         }
107
108         fclose(f);
109         return 1;
110 }
111
112 /* start the page with standard stuff */
113 static void print_header(void)
114 {
115         if (!cgi_waspost()) {
116                 printf("Expires: 0\r\n");
117         }
118         printf("Content-type: text/html\r\n\r\n");
119
120         if (!include_html("include/header.html")) {
121                 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
122                 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
123         }
124 }
125
126
127 /* finish off the page */
128 static void print_footer(void)
129 {
130         if (!include_html("include/footer.html")) {
131                 printf("\n</BODY>\n</HTML>\n");
132         }
133 }
134
135
136
137 /* display one editable parameter in a form */
138 static void show_parameter(int snum, struct parm_struct *parm)
139 {
140         int i;
141         void *ptr = parm->ptr;
142
143         if (parm->class == P_LOCAL && snum >= 0) {
144                 ptr = lp_local_ptr(snum, ptr);
145         }
146
147         printf("<tr><td><A HREF=\"/swat/help/smb.conf.5.html#%s\">?</A> %s</td><td>", 
148                stripspace(parm->label), parm->label);
149
150         switch (parm->type) {
151         case P_CHAR:
152                 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
153                        make_parm_name(parm->label), *(char *)ptr);
154                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
155                         make_parm_name(parm->label),(char)(parm->def.cvalue));
156                 break;
157
158         case P_STRING:
159         case P_USTRING:
160                 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
161                        make_parm_name(parm->label), *(char **)ptr);
162                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
163                         make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
164                 break;
165
166         case P_GSTRING:
167         case P_UGSTRING:
168                 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
169                        make_parm_name(parm->label), (char *)ptr);
170                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
171                         make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
172                 break;
173
174         case P_BOOL:
175                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
176                 printf("<option %s>Yes", (*(BOOL *)ptr)?"selected":"");
177                 printf("<option %s>No", (*(BOOL *)ptr)?"":"selected");
178                 printf("</select>");
179                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
180                         make_parm_name(parm->label),(BOOL)(parm->def.bvalue)?0:1);
181                 break;
182
183         case P_BOOLREV:
184                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
185                 printf("<option %s>Yes", (*(BOOL *)ptr)?"":"selected");
186                 printf("<option %s>No", (*(BOOL *)ptr)?"selected":"");
187                 printf("</select>");
188                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
189                         make_parm_name(parm->label),(BOOL)(parm->def.bvalue)?1:0);
190                 break;
191
192         case P_INTEGER:
193                 printf("<input type=text size=8 name=\"parm_%s\" value=%d>", make_parm_name(parm->label), *(int *)ptr);
194                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
195                         make_parm_name(parm->label),(int)(parm->def.ivalue));
196                 break;
197
198         case P_OCTAL:
199                 printf("<input type=text size=8 name=\"parm_%s\" value=0%o>", make_parm_name(parm->label), *(int *)ptr);
200                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.value=\'0%o\'\">",
201                         make_parm_name(parm->label),(int)(parm->def.ivalue));
202                 break;
203
204         case P_ENUM:
205                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
206                 for (i=0;parm->enum_list[i].name;i++)
207                         printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
208                 printf("</select>");
209                 printf("<input type=button value=\"Set Default\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
210                         make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
211                 break;
212         case P_SEP:
213                 break;
214         }
215         printf("</td></tr>\n");
216 }
217
218 /* display a set of parameters for a service */
219 static void show_parameters(int snum, int allparameters, int advanced, int printers)
220 {
221         int i = 0;
222         struct parm_struct *parm;
223         char *heading = NULL;
224         char *last_heading = NULL;
225
226         while ((parm = lp_next_parameter(snum, &i, allparameters))) {
227                 if (snum < 0 && parm->class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
228                         continue;
229                 if (parm->class == P_SEPARATOR) {
230                         heading = parm->label;
231                         continue;
232                 }
233                 if (parm->flags & FLAG_HIDE) continue;
234                 if (!advanced) {
235                         if (!printers && !(parm->flags & FLAG_BASIC)) {
236                                 void *ptr = parm->ptr;
237
238                                 switch (parm->type) {
239                                 case P_CHAR:
240                                         if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
241                                         break;
242
243                                 case P_STRING:
244                                 case P_USTRING:
245                                         if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
246                                         break;
247
248                                 case P_GSTRING:
249                                 case P_UGSTRING:
250                                         if (!strcmp((char *)ptr,(char *)(parm->def.svalue))) continue;
251                                         break;
252
253                                 case P_BOOL:
254                                 case P_BOOLREV:
255                                         if (*(BOOL *)ptr == (BOOL)(parm->def.bvalue)) continue;
256                                         break;
257
258                                 case P_INTEGER:
259                                 case P_OCTAL:
260                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
261                                         break;
262
263
264                                 case P_ENUM:
265                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
266                                         break;
267                                 case P_SEP:
268                                         continue;
269                                 }
270                         }
271                         if (printers && !(parm->flags & FLAG_PRINT)) continue;
272                 }
273                 if (heading && heading != last_heading) {
274                         printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", heading);
275                         last_heading = heading;
276                 }
277                 show_parameter(snum, parm);
278         }
279 }
280
281
282 /* write a config file */
283 static void write_config(FILE *f, BOOL show_defaults)
284 {
285         fprintf(f, "# Samba config file created using SWAT\n");
286         fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
287         fprintf(f, "# Date: %s\n\n", timestring());
288         
289         lp_dump(f, show_defaults);      
290 }
291
292
293 /* save and reoad the smb.conf config file */
294 static int save_reload(void)
295 {
296         FILE *f;
297
298         f = fopen(servicesf,"w");
299         if (!f) {
300                 printf("failed to open %s for writing\n", servicesf);
301                 return 0;
302         }
303
304         write_config(f, False);
305         fclose(f);
306
307         lp_killunused(NULL);
308
309         if (!lp_load(servicesf,False,False,False)) {
310                 printf("Can't reload %s\n", servicesf);
311                 return 0;
312         }
313
314         return 1;
315 }
316
317
318
319 /* commit one parameter */
320 static void commit_parameter(int snum, struct parm_struct *parm, char *v)
321 {
322         int i;
323         char *s;
324
325         if (snum < 0 && parm->class == P_LOCAL) {
326                 /* this handles the case where we are changing a local
327                    variable globally. We need to change the parameter in 
328                    all shares where it is currently set to the default */
329                 for (i=0;i<lp_numservices();i++) {
330                         s = lp_servicename(i);
331                         if (s && (*s) && lp_is_default(i, parm)) {
332                                 lp_do_parameter(i, parm->label, v);
333                         }
334                 }
335         }
336
337         lp_do_parameter(snum, parm->label, v);
338 }
339
340 /* commit a set of parameters for a service */
341 static void commit_parameters(int snum)
342 {
343         int i = 0;
344         struct parm_struct *parm;
345         pstring label;
346         char *v;
347
348         while ((parm = lp_next_parameter(snum, &i, 1))) {
349                 slprintf(label, sizeof(label)-1, "parm_%s", make_parm_name(parm->label));
350                 if ((v = cgi_variable(label))) {
351                         if (parm->flags & FLAG_HIDE) continue;
352                         commit_parameter(snum, parm, v); 
353                 }
354         }
355 }
356
357
358 /* load the smb.conf file into loadparm. */
359 static void load_config(void)
360 {
361         if (!lp_load(servicesf,False,True,False)) {
362                 printf("<b>Can't load %s - using defaults</b><p>\n", 
363                        servicesf);
364         }
365 }
366
367 /* spit out the html for a link with an image */
368 static void image_link(char *name,char *hlink, char *src, int width, int height)
369 {
370         printf("<A HREF=\"%s/%s\"><img width=%d height=%d src=\"/swat/%s\" alt=\"%s\"></A>\n", 
371                cgi_baseurl(),
372                hlink, width, height, 
373                src, name);
374 }
375
376 /* display the main navigation controls at the top of each page along
377    with a title */
378 static void show_main_buttons(void)
379 {
380         image_link("Home", "", "images/home.gif", 50, 50);
381         image_link("Globals", "globals", "images/globals.gif", 50, 50);
382         image_link("Shares", "shares", "images/shares.gif", 50, 50);
383         image_link("Printers", "printers", "images/printers.gif", 50, 50);
384         image_link("Status", "status", "images/status.gif", 50, 50);
385         image_link("View Config", "viewconfig", "images/viewconfig.gif", 50, 50);
386
387         printf("<HR>\n");
388 }
389
390 /* display a welcome page  */
391 static void welcome_page(void)
392 {
393         include_html("help/welcome.html");
394 }
395
396
397 /* display the current smb.conf  */
398 static void viewconfig_page(void)
399 {
400         int full_view=0;
401
402         if (cgi_variable("full_view")) {
403                 full_view = 1;
404         }
405
406         printf("<H2>Current Config</H2>\n");
407         printf("<form method=post>\n");
408
409         if (full_view) {
410                 printf("<input type=submit name=\"normal_view\" value=\"Normal View\">\n");
411         } else {
412                 printf("<input type=submit name=\"full_view\" value=\"Full View\">\n");
413         }
414
415         printf("<p><pre>");
416         write_config(stdout, full_view);
417         printf("</pre>");
418         printf("</form>\n");
419 }
420
421
422 /* display a globals editing page  */
423 static void globals_page(void)
424 {
425         int advanced = 0;
426
427         printf("<H2>Global Variables</H2>\n");
428
429         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
430                 advanced = 1;
431
432         if (cgi_variable("Commit")) {
433                 commit_parameters(GLOBALS_SNUM);
434                 save_reload();
435         }
436
437         printf("<FORM name=\"swatform\" method=post>\n");
438
439         printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
440         printf("<input type=reset name=\"Reset Values\" value=\"Reset Values\">\n");
441         if (advanced == 0) {
442                 printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
443         } else {
444                 printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
445         }
446         printf("<p>\n");
447         
448         printf("<table>\n");
449         show_parameters(GLOBALS_SNUM, 1, advanced, 0);
450         printf("</table>\n");
451
452         if (advanced) {
453                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
454         }
455
456         printf("</FORM>\n");
457 }
458
459 /* display a shares editing page  */
460 static void shares_page(void)
461 {
462         char *share = cgi_variable("share");
463         char *s;
464         int snum=-1;
465         int i;
466         int advanced = 0;
467
468         if (share)
469                 snum = lp_servicenumber(share);
470
471         printf("<H2>Share Parameters</H2>\n");
472
473         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
474                 advanced = 1;
475
476         if (cgi_variable("Commit") && snum >= 0) {
477                 commit_parameters(snum);
478                 save_reload();
479         }
480
481         if (cgi_variable("Delete") && snum >= 0) {
482                 lp_remove_service(snum);
483                 save_reload();
484                 share = NULL;
485                 snum = -1;
486         }
487
488         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
489                 lp_copy_service(GLOBALS_SNUM, share);
490                 save_reload();
491                 snum = lp_servicenumber(share);
492         }
493
494         printf("<FORM name=\"swatform\" method=post>\n");
495
496         printf("<table>\n");
497         printf("<tr><td><input type=submit name=selectshare value=\"Choose Share\"></td>\n");
498         printf("<td><select name=share>\n");
499         if (snum < 0)
500                 printf("<option value=\" \"> \n");
501         for (i=0;i<lp_numservices();i++) {
502                 s = lp_servicename(i);
503                 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
504                         printf("<option %s value=\"%s\">%s\n", 
505                                (share && strcmp(share,s)==0)?"SELECTED":"",
506                                s, s);
507                 }
508         }
509         printf("</select></td></tr><p>");
510
511         printf("<tr><td><input type=submit name=createshare value=\"Create Share\"></td>\n");
512         printf("<td><input type=text size=30 name=newshare></td></tr>\n");
513         printf("</table>");
514
515
516         if (snum >= 0) {
517                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
518                 printf("<input type=submit name=\"Delete\" value=\"Delete Share\">\n");
519                 if (advanced == 0) {
520                         printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
521                 } else {
522                         printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
523                 }
524                 printf("<p>\n");
525         }
526
527         if (snum >= 0) {
528                 printf("<table>\n");
529                 show_parameters(snum, 1, advanced, 0);
530                 printf("</table>\n");
531         }
532
533         if (advanced) {
534                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
535         }
536
537         printf("</FORM>\n");
538 }
539
540
541 /* display a printers editing page  */
542 static void printers_page(void)
543 {
544         char *share = cgi_variable("share");
545         char *s;
546         int snum=-1;
547         int i;
548         int advanced = 0;
549
550         if (share)
551                 snum = lp_servicenumber(share);
552
553         printf("<H2>Printer Parameters</H2>\n");
554
555         if (cgi_variable("Advanced") && !cgi_variable("Basic"))
556                 advanced = 1;
557
558         if (cgi_variable("Commit") && snum >= 0) {
559                 commit_parameters(snum);
560                 save_reload();
561         }
562
563         if (cgi_variable("Delete") && snum >= 0) {
564                 lp_remove_service(snum);
565                 save_reload();
566                 share = NULL;
567                 snum = -1;
568         }
569
570         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
571                 lp_copy_service(GLOBALS_SNUM, share);
572                 snum = lp_servicenumber(share);
573                 lp_do_parameter(snum, "print ok", "Yes");
574                 save_reload();
575                 snum = lp_servicenumber(share);
576         }
577
578         printf("<FORM name=\"swatform\" method=post>\n");
579
580         printf("<table>\n");
581         printf("<tr><td><input type=submit name=selectshare value=\"Choose Printer\"></td>\n");
582         printf("<td><select name=share>\n");
583         if (snum < 0 || !lp_print_ok(snum))
584                 printf("<option value=\" \"> \n");
585         for (i=0;i<lp_numservices();i++) {
586                 s = lp_servicename(i);
587                 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
588                         printf("<option %s value=\"%s\">%s\n", 
589                                (share && strcmp(share,s)==0)?"SELECTED":"",
590                                s, s);
591                 }
592         }
593         printf("</select></td></tr><p>");
594
595         printf("<tr><td><input type=submit name=createshare value=\"Create Printer\"></td>\n");
596         printf("<td><input type=text size=30 name=newshare></td></tr>\n");
597         printf("</table>");
598
599
600         if (snum >= 0) {
601                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
602                 printf("<input type=submit name=\"Delete\" value=\"Delete Printer\">\n");
603                 if (advanced == 0) {
604                         printf("<input type=submit name=\"Advanced\" value=\"Advanced View\">\n");
605                 } else {
606                         printf("<input type=submit name=\"Basic\" value=\"Basic View\">\n");
607                 }
608                 printf("<p>\n");
609         }
610
611         if (snum >= 0) {
612                 printf("<table>\n");
613                 show_parameters(snum, 1, advanced, 1);
614                 printf("</table>\n");
615         }
616
617         if (advanced) {
618                 printf("<input type=hidden name=\"Advanced\" value=1>\n");
619         }
620
621         printf("</FORM>\n");
622 }
623
624
625
626  int main(int argc, char *argv[])
627 {
628         extern char *optarg;
629         extern int optind;
630         extern FILE *dbf;
631         int opt;
632         char *page;
633         int auth_required = 1;
634
635         /* just in case it goes wild ... */
636         alarm(300);
637
638         dbf = fopen("/dev/null", "w");
639
640         if (!dbf) dbf = stderr;
641
642         while ((opt = getopt(argc, argv,"s:a")) != EOF) {
643                 switch (opt) {
644                 case 's':
645                         pstrcpy(servicesf,optarg);
646                         break;    
647                 case 'a':
648                         auth_required = 0;
649                         break;    
650                 }
651         }
652
653         cgi_setup(SWATDIR, auth_required);
654
655         print_header();
656         
657         charset_initialise();
658
659         /* if this binary is setuid then run completely as root */
660         setuid(0);
661
662         load_config();
663
664         cgi_load_variables(NULL);
665
666         show_main_buttons();
667
668         page = cgi_pathinfo();
669
670         if (strcmp(page, "globals")==0) {
671                 globals_page();
672         } else if (strcmp(page,"shares")==0) {
673                 shares_page();
674         } else if (strcmp(page,"printers")==0) {
675                 printers_page();
676         } else if (strcmp(page,"status")==0) {
677                 status_page();
678         } else if (strcmp(page,"viewconfig")==0) {
679                 viewconfig_page();
680         } else {
681                 welcome_page();
682         }
683         
684         print_footer();
685         return 0;
686 }
687
688