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