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