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