Fix swat. Bug #5613.
[samba.git] / source / web / swat.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba Web Administration Tool
4    Version 3.0.0
5    Copyright (C) Andrew Tridgell 1997-2002
6    Copyright (C) John H Terpstra 2002
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /**
23  * @defgroup swat SWAT - Samba Web Administration Tool
24  * @{ 
25  * @file swat.c
26  *
27  * @brief Samba Web Administration Tool.
28  **/
29
30 #include "includes.h"
31 #include "web/swat_proto.h"
32
33 static int demo_mode = False;
34 static int passwd_only = False;
35 static bool have_write_access = False;
36 static bool have_read_access = False;
37 static int iNumNonAutoPrintServices = 0;
38
39 /*
40  * Password Management Globals
41  */
42 #define SWAT_USER "username"
43 #define OLD_PSWD "old_passwd"
44 #define NEW_PSWD "new_passwd"
45 #define NEW2_PSWD "new2_passwd"
46 #define CHG_S_PASSWD_FLAG "chg_s_passwd_flag"
47 #define CHG_R_PASSWD_FLAG "chg_r_passwd_flag"
48 #define ADD_USER_FLAG "add_user_flag"
49 #define DELETE_USER_FLAG "delete_user_flag"
50 #define DISABLE_USER_FLAG "disable_user_flag"
51 #define ENABLE_USER_FLAG "enable_user_flag"
52 #define RHOST "remote_host"
53
54 #define _(x) lang_msg_rotate(talloc_tos(),x)
55
56 /****************************************************************************
57 ****************************************************************************/
58 static int enum_index(int value, const struct enum_list *enumlist)
59 {
60         int i;
61         for (i=0;enumlist[i].name;i++)
62                 if (value == enumlist[i].value) break;
63         return(i);
64 }
65
66 static char *fix_backslash(const char *str)
67 {
68         static char newstring[1024];
69         char *p = newstring;
70
71         while (*str) {
72                 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
73                 else *p++ = *str;
74                 ++str;
75         }
76         *p = '\0';
77         return newstring;
78 }
79
80 static const char *fix_quotes(TALLOC_CTX *ctx, const char *str)
81 {
82         char *newstring = NULL;
83         char *p = NULL;
84         size_t newstring_len;
85         int quote_len = strlen("&quot;");
86
87         /* Count the number of quotes. */
88         newstring_len = 1;
89         p = (char *) str;
90         while (*p) {
91                 if ( *p == '\"') {
92                         newstring_len += quote_len;
93                 } else {
94                         newstring_len++;
95                 }
96                 ++p;
97         }
98         newstring = TALLOC_ARRAY(ctx, char, newstring_len);
99         if (!newstring) {
100                 return "";
101         }
102         for (p = newstring; *str; str++) {
103                 if ( *str == '\"') {
104                         strncpy( p, "&quot;", quote_len);
105                         p += quote_len;
106                 } else {
107                         *p++ = *str;
108                 }
109         }
110         *p = '\0';
111         return newstring;
112 }
113
114 static char *stripspaceupper(const char *str)
115 {
116         static char newstring[1024];
117         char *p = newstring;
118
119         while (*str) {
120                 if (*str != ' ') *p++ = toupper_ascii(*str);
121                 ++str;
122         }
123         *p = '\0';
124         return newstring;
125 }
126
127 static char *make_parm_name(const char *label)
128 {
129         static char parmname[1024];
130         char *p = parmname;
131
132         while (*label) {
133                 if (*label == ' ') *p++ = '_';
134                 else *p++ = *label;
135                 ++label;
136         }
137         *p = '\0';
138         return parmname;
139 }
140
141 /****************************************************************************
142   include a lump of html in a page 
143 ****************************************************************************/
144 static int include_html(const char *fname)
145 {
146         int fd;
147         char buf[1024];
148         int ret;
149
150         fd = web_open(fname, O_RDONLY, 0);
151
152         if (fd == -1) {
153                 printf(_("ERROR: Can't open %s"), fname);
154                 printf("\n");
155                 return 0;
156         }
157
158         while ((ret = read(fd, buf, sizeof(buf))) > 0) {
159                 write(1, buf, ret);
160         }
161
162         close(fd);
163         return 1;
164 }
165
166 /****************************************************************************
167   start the page with standard stuff 
168 ****************************************************************************/
169 static void print_header(void)
170 {
171         if (!cgi_waspost()) {
172                 printf("Expires: 0\r\n");
173         }
174         printf("Content-type: text/html\r\n\r\n");
175
176         if (!include_html("include/header.html")) {
177                 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
178                 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
179         }
180 }
181
182 /* *******************************************************************
183    show parameter label with translated name in the following form
184    because showing original and translated label in one line looks
185    too long, and showing translated label only is unusable for
186    heavy users.
187    -------------------------------
188    HELP       security   [combo box][button]
189    SECURITY
190    -------------------------------
191    (capital words are translated by gettext.)
192    if no translation is available, then same form as original is
193    used.
194    "i18n_translated_parm" class is used to change the color of the
195    translated parameter with CSS.
196    **************************************************************** */
197 static const char *get_parm_translated(TALLOC_CTX *ctx,
198         const char* pAnchor, const char* pHelp, const char* pLabel)
199 {
200         const char *pTranslated = _(pLabel);
201         char *output;
202         if(strcmp(pLabel, pTranslated) != 0) {
203                 output = talloc_asprintf(ctx,
204                   "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s <br><span class=\"i18n_translated_parm\">%s</span>",
205                    pAnchor, pHelp, pLabel, pTranslated);
206                 return output;
207         }
208         output = talloc_asprintf(ctx,
209           "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s",
210           pAnchor, pHelp, pLabel);
211         return output;
212 }
213 /****************************************************************************
214  finish off the page
215 ****************************************************************************/
216 static void print_footer(void)
217 {
218         if (!include_html("include/footer.html")) {
219                 printf("\n</BODY>\n</HTML>\n");
220         }
221 }
222
223 /****************************************************************************
224   display one editable parameter in a form
225 ****************************************************************************/
226 static void show_parameter(int snum, struct parm_struct *parm)
227 {
228         int i;
229         void *ptr = parm->ptr;
230         char *utf8_s1, *utf8_s2;
231         size_t converted_size;
232         TALLOC_CTX *ctx = talloc_stackframe();
233
234         if (parm->p_class == P_LOCAL && snum >= 0) {
235                 ptr = lp_local_ptr(snum, ptr);
236         }
237
238         printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
239                                 stripspaceupper(parm->label), _("Help"), parm->label));
240         switch (parm->type) {
241         case P_CHAR:
242                 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
243                        make_parm_name(parm->label), *(char *)ptr);
244                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
245                         _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
246                 break;
247
248         case P_LIST:
249                 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
250                         make_parm_name(parm->label));
251                 if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
252                         char **list = *(char ***)ptr;
253                         for (;*list;list++) {
254                                 /* enclose in HTML encoded quotes if the string contains a space */
255                                 if ( strchr_m(*list, ' ') ) {
256                                         push_utf8_allocate(&utf8_s1, *list, &converted_size);
257                                         push_utf8_allocate(&utf8_s2, ((*(list+1))?", ":""), &converted_size);
258                                         printf("&quot;%s&quot;%s", utf8_s1, utf8_s2);
259                                 } else {
260                                         push_utf8_allocate(&utf8_s1, *list, &converted_size);
261                                         push_utf8_allocate(&utf8_s2, ((*(list+1))?", ":""), &converted_size);
262                                         printf("%s%s", utf8_s1, utf8_s2);
263                                 }
264                                 SAFE_FREE(utf8_s1);
265                                 SAFE_FREE(utf8_s2);
266                         }
267                 }
268                 printf("\">");
269                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
270                         _("Set Default"), make_parm_name(parm->label));
271                 if (parm->def.lvalue) {
272                         char **list = (char **)(parm->def.lvalue);
273                         for (; *list; list++) {
274                                 /* enclose in HTML encoded quotes if the string contains a space */
275                                 if ( strchr_m(*list, ' ') )
276                                         printf("&quot;%s&quot;%s", *list, ((*(list+1))?", ":""));
277                                 else
278                                         printf("%s%s", *list, ((*(list+1))?", ":""));
279                         }
280                 }
281                 printf("\'\">");
282                 break;
283
284         case P_STRING:
285         case P_USTRING:
286                 push_utf8_allocate(&utf8_s1, *(char **)ptr, &converted_size);
287                 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
288                        make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
289                 SAFE_FREE(utf8_s1);
290                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
291                         _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
292                 break;
293
294         case P_BOOL:
295                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
296                 printf("<option %s>Yes", (*(bool *)ptr)?"selected":"");
297                 printf("<option %s>No", (*(bool *)ptr)?"":"selected");
298                 printf("</select>");
299                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
300                         _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?0:1);
301                 break;
302
303         case P_BOOLREV:
304                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
305                 printf("<option %s>Yes", (*(bool *)ptr)?"":"selected");
306                 printf("<option %s>No", (*(bool *)ptr)?"selected":"");
307                 printf("</select>");
308                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
309                         _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?1:0);
310                 break;
311
312         case P_INTEGER:
313                 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
314                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
315                         _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
316                 break;
317
318         case P_OCTAL: {
319                 char *o;
320                 o = octal_string(*(int *)ptr);
321                 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
322                        make_parm_name(parm->label), o);
323                 TALLOC_FREE(o);
324                 o = octal_string((int)(parm->def.ivalue));
325                 printf("<input type=button value=\"%s\" "
326                        "onClick=\"swatform.parm_%s.value=\'%s\'\">",
327                        _("Set Default"), make_parm_name(parm->label), o);
328                 TALLOC_FREE(o);
329                 break;
330         }
331
332         case P_ENUM:
333                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
334                 for (i=0;parm->enum_list[i].name;i++) {
335                         if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
336                                 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
337                         }
338                 }
339                 printf("</select>");
340                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
341                         _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
342                 break;
343         case P_SEP:
344                 break;
345         }
346         printf("</td></tr>\n");
347         TALLOC_FREE(ctx);
348 }
349
350 /****************************************************************************
351   display a set of parameters for a service 
352 ****************************************************************************/
353 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
354 {
355         int i = 0;
356         struct parm_struct *parm;
357         const char *heading = NULL;
358         const char *last_heading = NULL;
359
360         while ((parm = lp_next_parameter(snum, &i, allparameters))) {
361                 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
362                         continue;
363                 if (parm->p_class == P_SEPARATOR) {
364                         heading = parm->label;
365                         continue;
366                 }
367                 if (parm->flags & FLAG_HIDE) continue;
368                 if (snum >= 0) {
369                         if (printers & !(parm->flags & FLAG_PRINT)) continue;
370                         if (!printers & !(parm->flags & FLAG_SHARE)) continue;
371                 }
372
373                 if (!( parm_filter & FLAG_ADVANCED )) {
374                         if (!(parm->flags & FLAG_BASIC)) {
375                                         void *ptr = parm->ptr;
376
377                                 if (parm->p_class == P_LOCAL && snum >= 0) {
378                                         ptr = lp_local_ptr(snum, ptr);
379                                 }
380
381                                 switch (parm->type) {
382                                 case P_CHAR:
383                                         if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
384                                         break;
385
386                                 case P_LIST:
387                                         if (!str_list_compare(*(char ***)ptr, (char **)(parm->def.lvalue))) continue;
388                                         break;
389
390                                 case P_STRING:
391                                 case P_USTRING:
392                                         if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
393                                         break;
394
395                                 case P_BOOL:
396                                 case P_BOOLREV:
397                                         if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
398                                         break;
399
400                                 case P_INTEGER:
401                                 case P_OCTAL:
402                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
403                                         break;
404
405
406                                 case P_ENUM:
407                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
408                                         break;
409                                 case P_SEP:
410                                         continue;
411                                         }
412                         }
413                         if (printers && !(parm->flags & FLAG_PRINT)) continue;
414                 }
415
416                 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
417                 
418                 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
419                 
420                 if (heading && heading != last_heading) {
421                         printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
422                         last_heading = heading;
423                 }
424                 show_parameter(snum, parm);
425         }
426 }
427
428 /****************************************************************************
429   load the smb.conf file into loadparm.
430 ****************************************************************************/
431 static bool load_config(bool save_def)
432 {
433         return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
434 }
435
436 /****************************************************************************
437   write a config file 
438 ****************************************************************************/
439 static void write_config(FILE *f, bool show_defaults)
440 {
441         TALLOC_CTX *ctx = talloc_stackframe();
442
443         fprintf(f, "# Samba config file created using SWAT\n");
444         fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
445         fprintf(f, "# Date: %s\n\n", current_timestring(ctx, False));
446         
447         lp_dump(f, show_defaults, iNumNonAutoPrintServices);
448
449         TALLOC_FREE(ctx);
450 }
451
452 /****************************************************************************
453   save and reload the smb.conf config file 
454 ****************************************************************************/
455 static int save_reload(int snum)
456 {
457         FILE *f;
458         struct stat st;
459
460         f = sys_fopen(get_dyn_CONFIGFILE(),"w");
461         if (!f) {
462                 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
463                 printf("\n");
464                 return 0;
465         }
466
467         /* just in case they have used the buggy xinetd to create the file */
468         if (fstat(fileno(f), &st) == 0 &&
469             (st.st_mode & S_IWOTH)) {
470 #if defined HAVE_FCHMOD
471                 fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
472 #else
473                 chmod(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
474 #endif
475         }
476
477         write_config(f, False);
478         if (snum)
479                 lp_dump_one(f, False, snum);
480         fclose(f);
481
482         lp_kill_all_services();
483
484         if (!load_config(False)) {
485                 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
486                 printf("\n");
487                 return 0;
488         }
489         iNumNonAutoPrintServices = lp_numservices();
490         load_printers();
491
492         return 1;
493 }
494
495 /****************************************************************************
496   commit one parameter 
497 ****************************************************************************/
498 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
499 {
500         int i;
501         char *s;
502
503         if (snum < 0 && parm->p_class == P_LOCAL) {
504                 /* this handles the case where we are changing a local
505                    variable globally. We need to change the parameter in 
506                    all shares where it is currently set to the default */
507                 for (i=0;i<lp_numservices();i++) {
508                         s = lp_servicename(i);
509                         if (s && (*s) && lp_is_default(i, parm)) {
510                                 lp_do_parameter(i, parm->label, v);
511                         }
512                 }
513         }
514
515         lp_do_parameter(snum, parm->label, v);
516 }
517
518 /****************************************************************************
519   commit a set of parameters for a service 
520 ****************************************************************************/
521 static void commit_parameters(int snum)
522 {
523         int i = 0;
524         struct parm_struct *parm;
525         char *label;
526         const char *v;
527
528         while ((parm = lp_next_parameter(snum, &i, 1))) {
529                 if (asprintf(&label, "parm_%s", make_parm_name(parm->label)) > 0) {
530                         if ((v = cgi_variable(label)) != NULL) {
531                                 if (parm->flags & FLAG_HIDE)
532                                         continue;
533                                 commit_parameter(snum, parm, v);
534                         }
535                         SAFE_FREE(label);
536                 }
537         }
538 }
539
540 /****************************************************************************
541   spit out the html for a link with an image 
542 ****************************************************************************/
543 static void image_link(const char *name, const char *hlink, const char *src)
544 {
545         printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n", 
546                cgi_baseurl(), hlink, src, name);
547 }
548
549 /****************************************************************************
550   display the main navigation controls at the top of each page along
551   with a title 
552 ****************************************************************************/
553 static void show_main_buttons(void)
554 {
555         char *p;
556         
557         if ((p = cgi_user_name()) && strcmp(p, "root")) {
558                 printf(_("Logged in as <b>%s</b>"), p);
559                 printf("<p>\n");
560         }
561
562         image_link(_("Home"), "", "images/home.gif");
563         if (have_write_access) {
564                 image_link(_("Globals"), "globals", "images/globals.gif");
565                 image_link(_("Shares"), "shares", "images/shares.gif");
566                 image_link(_("Printers"), "printers", "images/printers.gif");
567                 image_link(_("Wizard"), "wizard", "images/wizard.gif");
568         }
569    /* root always gets all buttons, otherwise look for -P */
570         if ( have_write_access || (!passwd_only && have_read_access) ) {
571                 image_link(_("Status"), "status", "images/status.gif");
572                 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
573         }
574         image_link(_("Password Management"), "passwd", "images/passwd.gif");
575
576         printf("<HR>\n");
577 }
578
579 /****************************************************************************
580  * Handle Display/Edit Mode CGI
581  ****************************************************************************/
582 static void ViewModeBoxes(int mode)
583 {
584         printf("<p>%s:&nbsp;\n", _("Current View Is"));
585         printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
586         printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
587         printf("<br>%s:&nbsp;\n", _("Change View To"));
588         printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
589         printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
590         printf("</p><br>\n");
591 }
592
593 /****************************************************************************
594   display a welcome page  
595 ****************************************************************************/
596 static void welcome_page(void)
597 {
598         if (file_exist("help/welcome.html", NULL)) {
599                 include_html("help/welcome.html");
600         } else {
601                 include_html("help/welcome-no-samba-doc.html");
602         }
603 }
604
605 /****************************************************************************
606   display the current smb.conf  
607 ****************************************************************************/
608 static void viewconfig_page(void)
609 {
610         int full_view=0;
611
612         if (cgi_variable("full_view")) {
613                 full_view = 1;
614         }
615
616         printf("<H2>%s</H2>\n", _("Current Config"));
617         printf("<form method=post>\n");
618
619         if (full_view) {
620                 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
621         } else {
622                 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
623         }
624
625         printf("<p><pre>");
626         write_config(stdout, full_view);
627         printf("</pre>");
628         printf("</form>\n");
629 }
630
631 /****************************************************************************
632   second screen of the wizard ... Fetch Configuration Parameters
633 ****************************************************************************/
634 static void wizard_params_page(void)
635 {
636         unsigned int parm_filter = FLAG_WIZARD;
637
638         /* Here we first set and commit all the parameters that were selected
639            in the previous screen. */
640
641         printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
642
643         if (cgi_variable("Commit")) {
644                 commit_parameters(GLOBAL_SECTION_SNUM);
645                 save_reload(0);
646         }
647
648         printf("<form name=\"swatform\" method=post action=wizard_params>\n");
649
650         if (have_write_access) {
651                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
652         }
653
654         printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
655         printf("<p>\n");
656         
657         printf("<table>\n");
658         show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
659         printf("</table>\n");
660         printf("</form>\n");
661 }
662
663 /****************************************************************************
664   Utility to just rewrite the smb.conf file - effectively just cleans it up
665 ****************************************************************************/
666 static void rewritecfg_file(void)
667 {
668         commit_parameters(GLOBAL_SECTION_SNUM);
669         save_reload(0);
670         printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
671 }
672
673 /****************************************************************************
674   wizard to create/modify the smb.conf file
675 ****************************************************************************/
676 static void wizard_page(void)
677 {
678         /* Set some variables to collect data from smb.conf */
679         int role = 0;
680         int winstype = 0;
681         int have_home = -1;
682         int HomeExpo = 0;
683         int SerType = 0;
684
685         if (cgi_variable("Rewrite")) {
686                 (void) rewritecfg_file();
687                 return;
688         }
689
690         if (cgi_variable("GetWizardParams")){
691                 (void) wizard_params_page();
692                 return;
693         }
694
695         if (cgi_variable("Commit")){
696                 SerType = atoi(cgi_variable_nonull("ServerType"));
697                 winstype = atoi(cgi_variable_nonull("WINSType"));
698                 have_home = lp_servicenumber(HOMES_NAME);
699                 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
700
701                 /* Plain text passwords are too badly broken - use encrypted passwords only */
702                 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
703                 
704                 switch ( SerType ){
705                         case 0:
706                                 /* Stand-alone Server */
707                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
708                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
709                                 break;
710                         case 1:
711                                 /* Domain Member */
712                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
713                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
714                                 break;
715                         case 2:
716                                 /* Domain Controller */
717                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
718                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
719                                 break;
720                 }
721                 switch ( winstype ) {
722                         case 0:
723                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
724                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
725                                 break;
726                         case 1:
727                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
728                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
729                                 break;
730                         case 2:
731                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
732                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
733                                 break;
734                 }
735
736                 /* Have to create Homes share? */
737                 if ((HomeExpo == 1) && (have_home == -1)) {
738                         const char *unix_share = HOMES_NAME;
739
740                         load_config(False);
741                         lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
742                         have_home = lp_servicenumber(HOMES_NAME);
743                         lp_do_parameter( have_home, "read only", "No");
744                         lp_do_parameter( have_home, "valid users", "%S");
745                         lp_do_parameter( have_home, "browseable", "No");
746                         commit_parameters(have_home);
747                         save_reload(have_home);
748                 }
749
750                 /* Need to Delete Homes share? */
751                 if ((HomeExpo == 0) && (have_home != -1)) {
752                         lp_remove_service(have_home);
753                         have_home = -1;
754                 }
755
756                 commit_parameters(GLOBAL_SECTION_SNUM);
757                 save_reload(0);
758         }
759         else
760         {
761                 /* Now determine smb.conf WINS settings */
762                 if (lp_wins_support())
763                         winstype = 1;
764                 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
765                         winstype = 2;
766
767                 /* Do we have a homes share? */
768                 have_home = lp_servicenumber(HOMES_NAME);
769         }
770         if ((winstype == 2) && lp_wins_support())
771                 winstype = 3;
772
773         role = lp_server_role();
774         
775         /* Here we go ... */
776         printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
777         printf("<form method=post action=wizard>\n");
778
779         if (have_write_access) {
780                 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
781                 printf("%s", _("The same will happen if you press the commit button."));
782                 printf("<br><br>\n");
783                 printf("<center>");
784                 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> &nbsp;&nbsp;",_("Rewrite smb.conf file"));
785                 printf("<input type=submit name=\"Commit\" value=\"%s\"> &nbsp;&nbsp;",_("Commit"));
786                 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
787                 printf("</center>\n");
788         }
789
790         printf("<hr>");
791         printf("<center><table border=0>");
792         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Server Type"));
793         printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s&nbsp;</td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
794         printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member")); 
795         printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
796         printf("</tr>\n");
797         if (role == ROLE_DOMAIN_BDC) {
798                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
799         }
800         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Configure WINS As"));
801         printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s&nbsp;</td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
802         printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s&nbsp;</td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
803         printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s&nbsp;</td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
804         printf("</tr>\n");
805         printf("<tr><td></td><td></td><td></td><td>%s&nbsp;<input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
806
807         /* Print out the list of wins servers */
808         if(lp_wins_server_list()) {
809                 int i;
810                 const char **wins_servers = lp_wins_server_list();
811                 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
812         }
813         
814         printf("\"></td></tr>\n");
815         if (winstype == 3) {
816                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Error: WINS Server Mode and WINS Support both set in smb.conf"));
817                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
818         }
819         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Expose Home Directories"));
820         printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
821         printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
822         printf("<td></td></tr>\n");
823         
824         /* Enable this when we are ready ....
825          * printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Is Print Server"));
826          * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
827          * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
828          * printf("<td></td></tr>\n");
829          */
830         
831         printf("</table></center>");
832         printf("<hr>");
833
834         printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
835         printf("</form>\n");
836 }
837
838
839 /****************************************************************************
840   display a globals editing page  
841 ****************************************************************************/
842 static void globals_page(void)
843 {
844         unsigned int parm_filter = FLAG_BASIC;
845         int mode = 0;
846
847         printf("<H2>%s</H2>\n", _("Global Parameters"));
848
849         if (cgi_variable("Commit")) {
850                 commit_parameters(GLOBAL_SECTION_SNUM);
851                 save_reload(0);
852         }
853
854         if ( cgi_variable("ViewMode") )
855                 mode = atoi(cgi_variable_nonull("ViewMode"));
856         if ( cgi_variable("BasicMode"))
857                 mode = 0;
858         if ( cgi_variable("AdvMode"))
859                 mode = 1;
860
861         printf("<form name=\"swatform\" method=post action=globals>\n");
862
863         ViewModeBoxes( mode );
864         switch ( mode ) {
865                 case 0:
866                         parm_filter = FLAG_BASIC;
867                         break;
868                 case 1:
869                         parm_filter = FLAG_ADVANCED;
870                         break;
871         }
872         printf("<br>\n");
873         if (have_write_access) {
874                 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
875                         _("Commit Changes"));
876         }
877
878         printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", 
879                  _("Reset Values"));
880
881         printf("<p>\n");
882         printf("<table>\n");
883         show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
884         printf("</table>\n");
885         printf("</form>\n");
886 }
887
888 /****************************************************************************
889   display a shares editing page. share is in unix codepage, 
890 ****************************************************************************/
891 static void shares_page(void)
892 {
893         const char *share = cgi_variable("share");
894         char *s;
895         char *utf8_s;
896         int snum = -1;
897         int i;
898         int mode = 0;
899         unsigned int parm_filter = FLAG_BASIC;
900         size_t converted_size;
901
902         if (share)
903                 snum = lp_servicenumber(share);
904
905         printf("<H2>%s</H2>\n", _("Share Parameters"));
906
907         if (cgi_variable("Commit") && snum >= 0) {
908                 commit_parameters(snum);
909                 save_reload(0);
910                 snum = lp_servicenumber(share);
911         }
912
913         if (cgi_variable("Delete") && snum >= 0) {
914                 lp_remove_service(snum);
915                 save_reload(0);
916                 share = NULL;
917                 snum = -1;
918         }
919
920         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
921                 snum = lp_servicenumber(share);
922                 if (snum < 0) {
923                         load_config(False);
924                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
925                         snum = lp_servicenumber(share);
926                         save_reload(snum);
927                         snum = lp_servicenumber(share);
928                 }
929         }
930
931         printf("<FORM name=\"swatform\" method=post>\n");
932
933         printf("<table>\n");
934
935         if ( cgi_variable("ViewMode") )
936                 mode = atoi(cgi_variable_nonull("ViewMode"));
937         if ( cgi_variable("BasicMode"))
938                 mode = 0;
939         if ( cgi_variable("AdvMode"))
940                 mode = 1;
941
942         ViewModeBoxes( mode );
943         switch ( mode ) {
944                 case 0:
945                         parm_filter = FLAG_BASIC;
946                         break;
947                 case 1:
948                         parm_filter = FLAG_ADVANCED;
949                         break;
950         }
951         printf("<br><tr>\n");
952         printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
953         printf("<td><select name=share>\n");
954         if (snum < 0)
955                 printf("<option value=\" \"> \n");
956         for (i=0;i<lp_numservices();i++) {
957                 s = lp_servicename(i);
958                 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
959                         push_utf8_allocate(&utf8_s, s, &converted_size);
960                         printf("<option %s value=\"%s\">%s\n", 
961                                (share && strcmp(share,s)==0)?"SELECTED":"",
962                                utf8_s, utf8_s);
963                         SAFE_FREE(utf8_s);
964                 }
965         }
966         printf("</select></td>\n");
967         if (have_write_access) {
968                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
969         }
970         printf("</tr>\n");
971         printf("</table>");
972         printf("<table>");
973         if (have_write_access) {
974                 printf("<tr>\n");
975                 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
976                 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
977         }
978         printf("</table>");
979
980
981         if (snum >= 0) {
982                 if (have_write_access) {
983                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
984                 }
985
986                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
987                 printf("<p>\n");
988         }
989
990         if (snum >= 0) {
991                 printf("<table>\n");
992                 show_parameters(snum, 1, parm_filter, 0);
993                 printf("</table>\n");
994         }
995
996         printf("</FORM>\n");
997 }
998
999 /*************************************************************
1000 change a password either locally or remotely
1001 *************************************************************/
1002 static bool change_password(const char *remote_machine, const char *user_name, 
1003                             const char *old_passwd, const char *new_passwd, 
1004                                 int local_flags)
1005 {
1006         NTSTATUS ret;
1007         char *err_str = NULL;
1008         char *msg_str = NULL;
1009
1010         if (demo_mode) {
1011                 printf("%s\n<p>", _("password change in demo mode rejected"));
1012                 return False;
1013         }
1014         
1015         if (remote_machine != NULL) {
1016                 ret = remote_password_change(remote_machine, user_name,
1017                                              old_passwd, new_passwd, &err_str);
1018                 if (err_str != NULL)
1019                         printf("%s\n<p>", err_str);
1020                 SAFE_FREE(err_str);
1021                 return NT_STATUS_IS_OK(ret);
1022         }
1023
1024         if(!initialize_password_db(True, NULL)) {
1025                 printf("%s\n<p>", _("Can't setup password database vectors."));
1026                 return False;
1027         }
1028         
1029         ret = local_password_change(user_name, local_flags, new_passwd,
1030                                         &err_str, &msg_str);
1031
1032         if(msg_str)
1033                 printf("%s\n<p>", msg_str);
1034         if(err_str)
1035                 printf("%s\n<p>", err_str);
1036
1037         SAFE_FREE(msg_str);
1038         SAFE_FREE(err_str);
1039         return NT_STATUS_IS_OK(ret);
1040 }
1041
1042 /****************************************************************************
1043   do the stuff required to add or change a password 
1044 ****************************************************************************/
1045 static void chg_passwd(void)
1046 {
1047         const char *host;
1048         bool rslt;
1049         int local_flags = 0;
1050
1051         /* Make sure users name has been specified */
1052         if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1053                 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1054                 return;
1055         }
1056
1057         /*
1058          * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1059          * so if that's what we're doing, skip the rest of the checks
1060          */
1061         if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1062
1063                 /*
1064                  * If current user is not root, make sure old password has been specified 
1065                  * If REMOTE change, even root must provide old password 
1066                  */
1067                 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1068                     ((cgi_variable(CHG_R_PASSWD_FLAG)) &&  (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1069                         printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1070                         return;
1071                 }
1072
1073                 /* If changing a users password on a remote hosts we have to know what host */
1074                 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1075                         printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1076                         return;
1077                 }
1078
1079                 /* Make sure new passwords have been specified */
1080                 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1081                     (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1082                         printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1083                         return;
1084                 }
1085
1086                 /* Make sure new passwords was typed correctly twice */
1087                 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1088                         printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1089                         return;
1090                 }
1091         }
1092
1093         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1094                 host = cgi_variable(RHOST);
1095         } else if (am_root()) {
1096                 host = NULL;
1097         } else {
1098                 host = "127.0.0.1";
1099         }
1100
1101         /*
1102          * Set up the local flags.
1103          */
1104
1105         local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1106         local_flags |= (cgi_variable(ADD_USER_FLAG) ?  LOCAL_SET_PASSWORD : 0);
1107         local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1108         local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1109         local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1110         local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1111         
1112
1113         rslt = change_password(host,
1114                                cgi_variable_nonull(SWAT_USER),
1115                                cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1116                                    local_flags);
1117
1118         if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1119                 printf("<p>");
1120                 if (rslt == True) {
1121                         printf(_(" The passwd for '%s' has been changed."), cgi_variable_nonull(SWAT_USER));
1122                         printf("\n");
1123                 } else {
1124                         printf(_(" The passwd for '%s' has NOT been changed."), cgi_variable_nonull(SWAT_USER));
1125                         printf("\n");
1126                 }
1127         }
1128         
1129         return;
1130 }
1131
1132 /****************************************************************************
1133   display a password editing page  
1134 ****************************************************************************/
1135 static void passwd_page(void)
1136 {
1137         const char *new_name = cgi_user_name();
1138
1139         /* 
1140          * After the first time through here be nice. If the user
1141          * changed the User box text to another users name, remember it.
1142          */
1143         if (cgi_variable(SWAT_USER)) {
1144                 new_name = cgi_variable_nonull(SWAT_USER);
1145         } 
1146
1147         if (!new_name) new_name = "";
1148
1149         printf("<H2>%s</H2>\n", _("Server Password Management"));
1150
1151         printf("<FORM name=\"swatform\" method=post>\n");
1152
1153         printf("<table>\n");
1154
1155         /* 
1156          * Create all the dialog boxes for data collection
1157          */
1158         printf("<tr><td> %s : </td>\n", _("User Name"));
1159         printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1160         if (!am_root()) {
1161                 printf("<tr><td> %s : </td>\n", _("Old Password"));
1162                 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1163         }
1164         printf("<tr><td> %s : </td>\n", _("New Password"));
1165         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1166         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1167         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1168         printf("</table>\n");
1169
1170         /*
1171          * Create all the control buttons for requesting action
1172          */
1173         printf("<input type=submit name=%s value=\"%s\">\n", 
1174                CHG_S_PASSWD_FLAG, _("Change Password"));
1175         if (demo_mode || am_root()) {
1176                 printf("<input type=submit name=%s value=\"%s\">\n",
1177                        ADD_USER_FLAG, _("Add New User"));
1178                 printf("<input type=submit name=%s value=\"%s\">\n",
1179                        DELETE_USER_FLAG, _("Delete User"));
1180                 printf("<input type=submit name=%s value=\"%s\">\n", 
1181                        DISABLE_USER_FLAG, _("Disable User"));
1182                 printf("<input type=submit name=%s value=\"%s\">\n", 
1183                        ENABLE_USER_FLAG, _("Enable User"));
1184         }
1185         printf("<p></FORM>\n");
1186
1187         /*
1188          * Do some work if change, add, disable or enable was
1189          * requested. It could be this is the first time through this
1190          * code, so there isn't anything to do.  */
1191         if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1192             (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
1193                 chg_passwd();           
1194         }
1195
1196         printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1197
1198         printf("<FORM name=\"swatform\" method=post>\n");
1199
1200         printf("<table>\n");
1201
1202         /* 
1203          * Create all the dialog boxes for data collection
1204          */
1205         printf("<tr><td> %s : </td>\n", _("User Name"));
1206         printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1207         printf("<tr><td> %s : </td>\n", _("Old Password"));
1208         printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1209         printf("<tr><td> %s : </td>\n", _("New Password"));
1210         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1211         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1212         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1213         printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1214         printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1215
1216         printf("</table>");
1217
1218         /*
1219          * Create all the control buttons for requesting action
1220          */
1221         printf("<input type=submit name=%s value=\"%s\">", 
1222                CHG_R_PASSWD_FLAG, _("Change Password"));
1223
1224         printf("<p></FORM>\n");
1225
1226         /*
1227          * Do some work if a request has been made to change the
1228          * password somewhere other than the server. It could be this
1229          * is the first time through this code, so there isn't
1230          * anything to do.  */
1231         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1232                 chg_passwd();           
1233         }
1234
1235 }
1236
1237 /****************************************************************************
1238   display a printers editing page  
1239 ****************************************************************************/
1240 static void printers_page(void)
1241 {
1242         const char *share = cgi_variable("share");
1243         char *s;
1244         int snum=-1;
1245         int i;
1246         int mode = 0;
1247         unsigned int parm_filter = FLAG_BASIC;
1248
1249         if (share)
1250                 snum = lp_servicenumber(share);
1251
1252         printf("<H2>%s</H2>\n", _("Printer Parameters"));
1253  
1254         printf("<H3>%s</H3>\n", _("Important Note:"));
1255         printf(_("Printer names marked with [*] in the Choose Printer drop-down box "));
1256         printf(_("are autoloaded printers from "));
1257         printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1258         printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1259
1260         if (cgi_variable("Commit") && snum >= 0) {
1261                 commit_parameters(snum);
1262                 if (snum >= iNumNonAutoPrintServices)
1263                     save_reload(snum);
1264                 else
1265                     save_reload(0);
1266                 snum = lp_servicenumber(share);
1267         }
1268
1269         if (cgi_variable("Delete") && snum >= 0) {
1270                 lp_remove_service(snum);
1271                 save_reload(0);
1272                 share = NULL;
1273                 snum = -1;
1274         }
1275
1276         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1277                 snum = lp_servicenumber(share);
1278                 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1279                         load_config(False);
1280                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
1281                         snum = lp_servicenumber(share);
1282                         lp_do_parameter(snum, "print ok", "Yes");
1283                         save_reload(snum);
1284                         snum = lp_servicenumber(share);
1285                 }
1286         }
1287
1288         printf("<FORM name=\"swatform\" method=post>\n");
1289
1290         if ( cgi_variable("ViewMode") )
1291                 mode = atoi(cgi_variable_nonull("ViewMode"));
1292         if ( cgi_variable("BasicMode"))
1293                 mode = 0;
1294         if ( cgi_variable("AdvMode"))
1295                 mode = 1;
1296
1297         ViewModeBoxes( mode );
1298         switch ( mode ) {
1299                 case 0:
1300                         parm_filter = FLAG_BASIC;
1301                         break;
1302                 case 1:
1303                         parm_filter = FLAG_ADVANCED;
1304                         break;
1305         }
1306         printf("<table>\n");
1307         printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1308         printf("<td><select name=\"share\">\n");
1309         if (snum < 0 || !lp_print_ok(snum))
1310                 printf("<option value=\" \"> \n");
1311         for (i=0;i<lp_numservices();i++) {
1312                 s = lp_servicename(i);
1313                 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1314                     if (i >= iNumNonAutoPrintServices)
1315                         printf("<option %s value=\"%s\">[*]%s\n",
1316                                (share && strcmp(share,s)==0)?"SELECTED":"",
1317                                s, s);
1318                     else
1319                         printf("<option %s value=\"%s\">%s\n", 
1320                                (share && strcmp(share,s)==0)?"SELECTED":"",
1321                                s, s);
1322                 }
1323         }
1324         printf("</select></td>");
1325         if (have_write_access) {
1326                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1327         }
1328         printf("</tr>");
1329         printf("</table>\n");
1330
1331         if (have_write_access) {
1332                 printf("<table>\n");
1333                 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1334                 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1335                 printf("</table>");
1336         }
1337
1338
1339         if (snum >= 0) {
1340                 if (have_write_access) {
1341                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1342                 }
1343                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1344                 printf("<p>\n");
1345         }
1346
1347         if (snum >= 0) {
1348                 printf("<table>\n");
1349                 show_parameters(snum, 1, parm_filter, 1);
1350                 printf("</table>\n");
1351         }
1352         printf("</FORM>\n");
1353 }
1354
1355 /*
1356   when the _() translation macro is used there is no obvious place to free
1357   the resulting string and there is no easy way to give a static pointer.
1358   All we can do is rotate between some static buffers and hope a single d_printf()
1359   doesn't have more calls to _() than the number of buffers
1360 */
1361
1362 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1363 {
1364         const char *msgstr;
1365         const char *ret;
1366
1367         msgstr = lang_msg(msgid);
1368         if (!msgstr) {
1369                 return msgid;
1370         }
1371
1372         ret = talloc_strdup(ctx, msgstr);
1373
1374         lang_msg_free(msgstr);
1375         if (!ret) {
1376                 return msgid;
1377         }
1378
1379         return ret;
1380 }
1381
1382 /**
1383  * main function for SWAT.
1384  **/
1385  int main(int argc, char *argv[])
1386 {
1387         const char *page;
1388         poptContext pc;
1389         struct poptOption long_options[] = {
1390                 POPT_AUTOHELP
1391                 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1392                 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" }, 
1393                 POPT_COMMON_SAMBA
1394                 POPT_TABLEEND
1395         };
1396         TALLOC_CTX *frame = talloc_stackframe();
1397
1398         fault_setup(NULL);
1399         umask(S_IWGRP | S_IWOTH);
1400
1401 #if defined(HAVE_SET_AUTH_PARAMETERS)
1402         set_auth_parameters(argc, argv);
1403 #endif /* HAVE_SET_AUTH_PARAMETERS */
1404
1405         /* just in case it goes wild ... */
1406         alarm(300);
1407
1408         setlinebuf(stdout);
1409
1410         /* we don't want any SIGPIPE messages */
1411         BlockSignals(True,SIGPIPE);
1412
1413         dbf = x_fopen("/dev/null", O_WRONLY, 0);
1414         if (!dbf) dbf = x_stderr;
1415
1416         /* we don't want stderr screwing us up */
1417         close(2);
1418         open("/dev/null", O_WRONLY);
1419
1420         pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1421
1422         /* Parse command line options */
1423
1424         while(poptGetNextOpt(pc) != -1) { }
1425
1426         poptFreeContext(pc);
1427
1428         load_case_tables();
1429
1430         setup_logging(argv[0],False);
1431         load_config(True);
1432         load_interfaces();
1433         iNumNonAutoPrintServices = lp_numservices();
1434         load_printers();
1435
1436         cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1437
1438         print_header();
1439
1440         cgi_load_variables();
1441
1442         if (!file_exist(get_dyn_CONFIGFILE(), NULL)) {
1443                 have_read_access = True;
1444                 have_write_access = True;
1445         } else {
1446                 /* check if the authenticated user has write access - if not then
1447                    don't show write options */
1448                 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1449
1450                 /* if the user doesn't have read access to smb.conf then
1451                    don't let them view it */
1452                 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1453         }
1454
1455         show_main_buttons();
1456
1457         page = cgi_pathinfo();
1458
1459         /* Root gets full functionality */
1460         if (have_read_access && strcmp(page, "globals")==0) {
1461                 globals_page();
1462         } else if (have_read_access && strcmp(page,"shares")==0) {
1463                 shares_page();
1464         } else if (have_read_access && strcmp(page,"printers")==0) {
1465                 printers_page();
1466         } else if (have_read_access && strcmp(page,"status")==0) {
1467                 status_page();
1468         } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1469                 viewconfig_page();
1470         } else if (strcmp(page,"passwd")==0) {
1471                 passwd_page();
1472         } else if (have_read_access && strcmp(page,"wizard")==0) {
1473                 wizard_page();
1474         } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1475                 wizard_params_page();
1476         } else if (have_read_access && strcmp(page,"rewritecfg")==0) {
1477                 rewritecfg_file();
1478         } else {
1479                 welcome_page();
1480         }
1481
1482         print_footer();
1483
1484         TALLOC_FREE(frame);
1485         return 0;
1486 }
1487
1488 /** @} **/