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