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