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