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