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