s3-debug Impove setup_logging() to specify logging to stderr
[kai/samba.git] / source3 / web / swat.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba Web Administration Tool
4    Version 3.0.0
5    Copyright (C) Andrew Tridgell 1997-2002
6    Copyright (C) John H Terpstra 2002
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /**
23  * @defgroup swat SWAT - Samba Web Administration Tool
24  * @{ 
25  * @file swat.c
26  *
27  * @brief Samba Web Administration Tool.
28  **/
29
30 #include "includes.h"
31 #include "popt_common.h"
32 #include "web/swat_proto.h"
33
34 static int demo_mode = False;
35 static int passwd_only = False;
36 static bool have_write_access = False;
37 static bool have_read_access = False;
38 static int iNumNonAutoPrintServices = 0;
39
40 /*
41  * Password Management Globals
42  */
43 #define SWAT_USER "username"
44 #define OLD_PSWD "old_passwd"
45 #define NEW_PSWD "new_passwd"
46 #define NEW2_PSWD "new2_passwd"
47 #define CHG_S_PASSWD_FLAG "chg_s_passwd_flag"
48 #define CHG_R_PASSWD_FLAG "chg_r_passwd_flag"
49 #define ADD_USER_FLAG "add_user_flag"
50 #define DELETE_USER_FLAG "delete_user_flag"
51 #define DISABLE_USER_FLAG "disable_user_flag"
52 #define ENABLE_USER_FLAG "enable_user_flag"
53 #define RHOST "remote_host"
54
55 #define _(x) lang_msg_rotate(talloc_tos(),x)
56
57 /****************************************************************************
58 ****************************************************************************/
59 static int enum_index(int value, const struct enum_list *enumlist)
60 {
61         int i;
62         for (i=0;enumlist[i].name;i++)
63                 if (value == enumlist[i].value) break;
64         return(i);
65 }
66
67 static char *fix_backslash(const char *str)
68 {
69         static char newstring[1024];
70         char *p = newstring;
71
72         while (*str) {
73                 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
74                 else *p++ = *str;
75                 ++str;
76         }
77         *p = '\0';
78         return newstring;
79 }
80
81 static const char *fix_quotes(TALLOC_CTX *ctx, const char *str)
82 {
83         char *newstring = NULL;
84         char *p = NULL;
85         size_t newstring_len;
86         int quote_len = strlen("&quot;");
87
88         /* Count the number of quotes. */
89         newstring_len = 1;
90         p = (char *) str;
91         while (*p) {
92                 if ( *p == '\"') {
93                         newstring_len += quote_len;
94                 } else {
95                         newstring_len++;
96                 }
97                 ++p;
98         }
99         newstring = TALLOC_ARRAY(ctx, char, newstring_len);
100         if (!newstring) {
101                 return "";
102         }
103         for (p = newstring; *str; str++) {
104                 if ( *str == '\"') {
105                         strncpy( p, "&quot;", quote_len);
106                         p += quote_len;
107                 } else {
108                         *p++ = *str;
109                 }
110         }
111         *p = '\0';
112         return newstring;
113 }
114
115 static char *stripspaceupper(const char *str)
116 {
117         static char newstring[1024];
118         char *p = newstring;
119
120         while (*str) {
121                 if (*str != ' ') *p++ = toupper_ascii(*str);
122                 ++str;
123         }
124         *p = '\0';
125         return newstring;
126 }
127
128 static char *make_parm_name(const char *label)
129 {
130         static char parmname[1024];
131         char *p = parmname;
132
133         while (*label) {
134                 if (*label == ' ') *p++ = '_';
135                 else *p++ = *label;
136                 ++label;
137         }
138         *p = '\0';
139         return parmname;
140 }
141
142 /****************************************************************************
143   include a lump of html in a page 
144 ****************************************************************************/
145 static int include_html(const char *fname)
146 {
147         int fd;
148         char buf[1024];
149         int ret;
150
151         fd = web_open(fname, O_RDONLY, 0);
152
153         if (fd == -1) {
154                 printf(_("ERROR: Can't open %s"), fname);
155                 printf("\n");
156                 return 0;
157         }
158
159         while ((ret = read(fd, buf, sizeof(buf))) > 0) {
160                 if (write(1, buf, ret) == -1) {
161                         break;
162                 }
163         }
164
165         close(fd);
166         return 1;
167 }
168
169 /****************************************************************************
170   start the page with standard stuff 
171 ****************************************************************************/
172 static void print_header(void)
173 {
174         if (!cgi_waspost()) {
175                 printf("Expires: 0\r\n");
176         }
177         printf("Content-type: text/html\r\n\r\n");
178
179         if (!include_html("include/header.html")) {
180                 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
181                 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
182         }
183 }
184
185 /* *******************************************************************
186    show parameter label with translated name in the following form
187    because showing original and translated label in one line looks
188    too long, and showing translated label only is unusable for
189    heavy users.
190    -------------------------------
191    HELP       security   [combo box][button]
192    SECURITY
193    -------------------------------
194    (capital words are translated by gettext.)
195    if no translation is available, then same form as original is
196    used.
197    "i18n_translated_parm" class is used to change the color of the
198    translated parameter with CSS.
199    **************************************************************** */
200 static const char *get_parm_translated(TALLOC_CTX *ctx,
201         const char* pAnchor, const char* pHelp, const char* pLabel)
202 {
203         const char *pTranslated = _(pLabel);
204         char *output;
205         if(strcmp(pLabel, pTranslated) != 0) {
206                 output = talloc_asprintf(ctx,
207                   "<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>",
208                    pAnchor, pHelp, pLabel, pTranslated);
209                 return output;
210         }
211         output = talloc_asprintf(ctx,
212           "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s",
213           pAnchor, pHelp, pLabel);
214         return output;
215 }
216 /****************************************************************************
217  finish off the page
218 ****************************************************************************/
219 static void print_footer(void)
220 {
221         if (!include_html("include/footer.html")) {
222                 printf("\n</BODY>\n</HTML>\n");
223         }
224 }
225
226 /****************************************************************************
227   display one editable parameter in a form
228 ****************************************************************************/
229 static void show_parameter(int snum, struct parm_struct *parm)
230 {
231         int i;
232         void *ptr = parm->ptr;
233         char *utf8_s1, *utf8_s2;
234         size_t converted_size;
235         TALLOC_CTX *ctx = talloc_stackframe();
236
237         if (parm->p_class == P_LOCAL && snum >= 0) {
238                 ptr = lp_local_ptr_by_snum(snum, ptr);
239         }
240
241         printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
242                                 stripspaceupper(parm->label), _("Help"), parm->label));
243         switch (parm->type) {
244         case P_CHAR:
245                 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
246                        make_parm_name(parm->label), *(char *)ptr);
247                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
248                         _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
249                 break;
250
251         case P_LIST:
252                 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
253                         make_parm_name(parm->label));
254                 if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
255                         char **list = *(char ***)ptr;
256                         for (;*list;list++) {
257                                 /* enclose in HTML encoded quotes if the string contains a space */
258                                 if ( strchr_m(*list, ' ') ) {
259                                         push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
260                                         push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
261                                         printf("&quot;%s&quot;%s", utf8_s1, utf8_s2);
262                                 } else {
263                                         push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
264                                         push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
265                                         printf("%s%s", utf8_s1, utf8_s2);
266                                 }
267                                 TALLOC_FREE(utf8_s1);
268                                 TALLOC_FREE(utf8_s2);
269                         }
270                 }
271                 printf("\">");
272                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
273                         _("Set Default"), make_parm_name(parm->label));
274                 if (parm->def.lvalue) {
275                         char **list = (char **)(parm->def.lvalue);
276                         for (; *list; list++) {
277                                 /* enclose in HTML encoded quotes if the string contains a space */
278                                 if ( strchr_m(*list, ' ') )
279                                         printf("&quot;%s&quot;%s", *list, ((*(list+1))?", ":""));
280                                 else
281                                         printf("%s%s", *list, ((*(list+1))?", ":""));
282                         }
283                 }
284                 printf("\'\">");
285                 break;
286
287         case P_STRING:
288         case P_USTRING:
289                 push_utf8_talloc(talloc_tos(), &utf8_s1, *(char **)ptr, &converted_size);
290                 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
291                        make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
292                 TALLOC_FREE(utf8_s1);
293                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
294                         _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
295                 break;
296
297         case P_BOOL:
298                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
299                 printf("<option %s>Yes", (*(bool *)ptr)?"selected":"");
300                 printf("<option %s>No", (*(bool *)ptr)?"":"selected");
301                 printf("</select>");
302                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
303                         _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?0:1);
304                 break;
305
306         case P_BOOLREV:
307                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
308                 printf("<option %s>Yes", (*(bool *)ptr)?"":"selected");
309                 printf("<option %s>No", (*(bool *)ptr)?"selected":"");
310                 printf("</select>");
311                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
312                         _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?1:0);
313                 break;
314
315         case P_INTEGER:
316                 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
317                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
318                         _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
319                 break;
320
321         case P_OCTAL: {
322                 char *o;
323                 o = octal_string(*(int *)ptr);
324                 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
325                        make_parm_name(parm->label), o);
326                 TALLOC_FREE(o);
327                 o = octal_string((int)(parm->def.ivalue));
328                 printf("<input type=button value=\"%s\" "
329                        "onClick=\"swatform.parm_%s.value=\'%s\'\">",
330                        _("Set Default"), make_parm_name(parm->label), o);
331                 TALLOC_FREE(o);
332                 break;
333         }
334
335         case P_ENUM:
336                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
337                 for (i=0;parm->enum_list[i].name;i++) {
338                         if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
339                                 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
340                         }
341                 }
342                 printf("</select>");
343                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
344                         _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
345                 break;
346         case P_SEP:
347                 break;
348         }
349         printf("</td></tr>\n");
350         TALLOC_FREE(ctx);
351 }
352
353 /****************************************************************************
354   display a set of parameters for a service 
355 ****************************************************************************/
356 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
357 {
358         int i = 0;
359         struct parm_struct *parm;
360         const char *heading = NULL;
361         const char *last_heading = NULL;
362
363         while ((parm = lp_next_parameter(snum, &i, allparameters))) {
364                 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
365                         continue;
366                 if (parm->p_class == P_SEPARATOR) {
367                         heading = parm->label;
368                         continue;
369                 }
370                 if (parm->flags & FLAG_HIDE) continue;
371                 if (snum >= 0) {
372                         if (printers & !(parm->flags & FLAG_PRINT)) continue;
373                         if (!printers & !(parm->flags & FLAG_SHARE)) continue;
374                 }
375
376                 if (!( parm_filter & FLAG_ADVANCED )) {
377                         if (!(parm->flags & FLAG_BASIC)) {
378                                         void *ptr = parm->ptr;
379
380                                 if (parm->p_class == P_LOCAL && snum >= 0) {
381                                         ptr = lp_local_ptr_by_snum(snum, ptr);
382                                 }
383
384                                 switch (parm->type) {
385                                 case P_CHAR:
386                                         if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
387                                         break;
388
389                                 case P_LIST:
390                                         if (!str_list_equal(*(const char ***)ptr, 
391                                                             (const char **)(parm->def.lvalue))) continue;
392                                         break;
393
394                                 case P_STRING:
395                                 case P_USTRING:
396                                         if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
397                                         break;
398
399                                 case P_BOOL:
400                                 case P_BOOLREV:
401                                         if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
402                                         break;
403
404                                 case P_INTEGER:
405                                 case P_OCTAL:
406                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
407                                         break;
408
409
410                                 case P_ENUM:
411                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
412                                         break;
413                                 case P_SEP:
414                                         continue;
415                                         }
416                         }
417                         if (printers && !(parm->flags & FLAG_PRINT)) continue;
418                 }
419
420                 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
421
422                 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
423
424                 if (heading && heading != last_heading) {
425                         printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
426                         last_heading = heading;
427                 }
428                 show_parameter(snum, parm);
429         }
430 }
431
432 /****************************************************************************
433   load the smb.conf file into loadparm.
434 ****************************************************************************/
435 static bool load_config(bool save_def)
436 {
437         return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
438 }
439
440 /****************************************************************************
441   write a config file 
442 ****************************************************************************/
443 static void write_config(FILE *f, bool show_defaults)
444 {
445         TALLOC_CTX *ctx = talloc_stackframe();
446
447         fprintf(f, "# Samba config file created using SWAT\n");
448         fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
449         fprintf(f, "# Date: %s\n\n", current_timestring(ctx, False));
450
451         lp_dump(f, show_defaults, iNumNonAutoPrintServices);
452
453         TALLOC_FREE(ctx);
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(get_dyn_CONFIGFILE(),"w");
465         if (!f) {
466                 printf(_("failed to open %s for writing"), get_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(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
478 #endif
479         }
480
481         write_config(f, False);
482         if (snum >= 0)
483                 lp_dump_one(f, False, snum);
484         fclose(f);
485
486         lp_kill_all_services();
487
488         if (!load_config(False)) {
489                 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
490                 printf("\n");
491                 return 0;
492         }
493         iNumNonAutoPrintServices = lp_numservices();
494         load_printers(server_event_context(), server_messaging_context());
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")) {
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(-1);
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(-1);
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                         have_home = lp_servicenumber(HOMES_NAME);
747                         lp_do_parameter( have_home, "read only", "No");
748                         lp_do_parameter( have_home, "valid users", "%S");
749                         lp_do_parameter( have_home, "browseable", "No");
750                         commit_parameters(have_home);
751                         save_reload(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(-1);
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(-1);
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         size_t converted_size;
905
906         if (share)
907                 snum = lp_servicenumber(share);
908
909         printf("<H2>%s</H2>\n", _("Share Parameters"));
910
911         if (cgi_variable("Commit") && snum >= 0) {
912                 commit_parameters(snum);
913                 save_reload(-1);
914                 snum = lp_servicenumber(share);
915         }
916
917         if (cgi_variable("Delete") && snum >= 0) {
918                 lp_remove_service(snum);
919                 save_reload(-1);
920                 share = NULL;
921                 snum = -1;
922         }
923
924         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
925                 snum = lp_servicenumber(share);
926                 if (snum < 0) {
927                         load_config(False);
928                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
929                         snum = lp_servicenumber(share);
930                         save_reload(snum);
931                         snum = lp_servicenumber(share);
932                 }
933         }
934
935         printf("<FORM name=\"swatform\" method=post>\n");
936
937         printf("<table>\n");
938
939         if ( cgi_variable("ViewMode") )
940                 mode = atoi(cgi_variable_nonull("ViewMode"));
941         if ( cgi_variable("BasicMode"))
942                 mode = 0;
943         if ( cgi_variable("AdvMode"))
944                 mode = 1;
945
946         ViewModeBoxes( mode );
947         switch ( mode ) {
948                 case 0:
949                         parm_filter = FLAG_BASIC;
950                         break;
951                 case 1:
952                         parm_filter = FLAG_ADVANCED;
953                         break;
954         }
955         printf("<br><tr>\n");
956         printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
957         printf("<td><select name=share>\n");
958         if (snum < 0)
959                 printf("<option value=\" \"> \n");
960         for (i=0;i<lp_numservices();i++) {
961                 s = lp_servicename(i);
962                 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
963                         push_utf8_talloc(talloc_tos(), &utf8_s, s, &converted_size);
964                         printf("<option %s value=\"%s\">%s\n", 
965                                (share && strcmp(share,s)==0)?"SELECTED":"",
966                                utf8_s, utf8_s);
967                         TALLOC_FREE(utf8_s);
968                 }
969         }
970         printf("</select></td>\n");
971         if (have_write_access) {
972                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
973         }
974         printf("</tr>\n");
975         printf("</table>");
976         printf("<table>");
977         if (have_write_access) {
978                 printf("<tr>\n");
979                 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
980                 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
981         }
982         printf("</table>");
983
984
985         if (snum >= 0) {
986                 if (have_write_access) {
987                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
988                 }
989
990                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
991                 printf("<p>\n");
992         }
993
994         if (snum >= 0) {
995                 printf("<table>\n");
996                 show_parameters(snum, 1, parm_filter, 0);
997                 printf("</table>\n");
998         }
999
1000         printf("</FORM>\n");
1001 }
1002
1003 /*************************************************************
1004 change a password either locally or remotely
1005 *************************************************************/
1006 static bool change_password(const char *remote_machine, const char *user_name, 
1007                             const char *old_passwd, const char *new_passwd, 
1008                                 int local_flags)
1009 {
1010         NTSTATUS ret;
1011         char *err_str = NULL;
1012         char *msg_str = NULL;
1013
1014         if (demo_mode) {
1015                 printf("%s\n<p>", _("password change in demo mode rejected"));
1016                 return False;
1017         }
1018
1019         if (remote_machine != NULL) {
1020                 ret = remote_password_change(remote_machine, user_name,
1021                                              old_passwd, new_passwd, &err_str);
1022                 if (err_str != NULL)
1023                         printf("%s\n<p>", err_str);
1024                 SAFE_FREE(err_str);
1025                 return NT_STATUS_IS_OK(ret);
1026         }
1027
1028         if(!initialize_password_db(True, NULL)) {
1029                 printf("%s\n<p>", _("Can't setup password database vectors."));
1030                 return False;
1031         }
1032
1033         ret = local_password_change(user_name, local_flags, new_passwd,
1034                                         &err_str, &msg_str);
1035
1036         if(msg_str)
1037                 printf("%s\n<p>", msg_str);
1038         if(err_str)
1039                 printf("%s\n<p>", err_str);
1040
1041         SAFE_FREE(msg_str);
1042         SAFE_FREE(err_str);
1043         return NT_STATUS_IS_OK(ret);
1044 }
1045
1046 /****************************************************************************
1047   do the stuff required to add or change a password 
1048 ****************************************************************************/
1049 static void chg_passwd(void)
1050 {
1051         const char *host;
1052         bool rslt;
1053         int local_flags = 0;
1054
1055         /* Make sure users name has been specified */
1056         if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1057                 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1058                 return;
1059         }
1060
1061         /*
1062          * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1063          * so if that's what we're doing, skip the rest of the checks
1064          */
1065         if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1066
1067                 /*
1068                  * If current user is not root, make sure old password has been specified 
1069                  * If REMOTE change, even root must provide old password 
1070                  */
1071                 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1072                     ((cgi_variable(CHG_R_PASSWD_FLAG)) &&  (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1073                         printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1074                         return;
1075                 }
1076
1077                 /* If changing a users password on a remote hosts we have to know what host */
1078                 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1079                         printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1080                         return;
1081                 }
1082
1083                 /* Make sure new passwords have been specified */
1084                 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1085                     (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1086                         printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1087                         return;
1088                 }
1089
1090                 /* Make sure new passwords was typed correctly twice */
1091                 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1092                         printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1093                         return;
1094                 }
1095         }
1096
1097         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1098                 host = cgi_variable(RHOST);
1099         } else if (am_root()) {
1100                 host = NULL;
1101         } else {
1102                 host = "127.0.0.1";
1103         }
1104
1105         /*
1106          * Set up the local flags.
1107          */
1108
1109         local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1110         local_flags |= (cgi_variable(ADD_USER_FLAG) ?  LOCAL_SET_PASSWORD : 0);
1111         local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1112         local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1113         local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1114         local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1115
1116         rslt = change_password(host,
1117                                cgi_variable_nonull(SWAT_USER),
1118                                cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1119                                    local_flags);
1120
1121         if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1122                 printf("<p>");
1123                 if (rslt == True) {
1124                         printf(_(" The passwd for '%s' has been changed."), cgi_variable_nonull(SWAT_USER));
1125                         printf("\n");
1126                 } else {
1127                         printf(_(" The passwd for '%s' has NOT been changed."), cgi_variable_nonull(SWAT_USER));
1128                         printf("\n");
1129                 }
1130         }
1131
1132         return;
1133 }
1134
1135 /****************************************************************************
1136   display a password editing page  
1137 ****************************************************************************/
1138 static void passwd_page(void)
1139 {
1140         const char *new_name = cgi_user_name();
1141
1142         /* 
1143          * After the first time through here be nice. If the user
1144          * changed the User box text to another users name, remember it.
1145          */
1146         if (cgi_variable(SWAT_USER)) {
1147                 new_name = cgi_variable_nonull(SWAT_USER);
1148         } 
1149
1150         if (!new_name) new_name = "";
1151
1152         printf("<H2>%s</H2>\n", _("Server Password Management"));
1153
1154         printf("<FORM name=\"swatform\" method=post>\n");
1155
1156         printf("<table>\n");
1157
1158         /* 
1159          * Create all the dialog boxes for data collection
1160          */
1161         printf("<tr><td> %s : </td>\n", _("User Name"));
1162         printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1163         if (!am_root()) {
1164                 printf("<tr><td> %s : </td>\n", _("Old Password"));
1165                 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1166         }
1167         printf("<tr><td> %s : </td>\n", _("New Password"));
1168         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1169         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1170         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1171         printf("</table>\n");
1172
1173         /*
1174          * Create all the control buttons for requesting action
1175          */
1176         printf("<input type=submit name=%s value=\"%s\">\n", 
1177                CHG_S_PASSWD_FLAG, _("Change Password"));
1178         if (demo_mode || am_root()) {
1179                 printf("<input type=submit name=%s value=\"%s\">\n",
1180                        ADD_USER_FLAG, _("Add New User"));
1181                 printf("<input type=submit name=%s value=\"%s\">\n",
1182                        DELETE_USER_FLAG, _("Delete User"));
1183                 printf("<input type=submit name=%s value=\"%s\">\n", 
1184                        DISABLE_USER_FLAG, _("Disable User"));
1185                 printf("<input type=submit name=%s value=\"%s\">\n", 
1186                        ENABLE_USER_FLAG, _("Enable User"));
1187         }
1188         printf("<p></FORM>\n");
1189
1190         /*
1191          * Do some work if change, add, disable or enable was
1192          * requested. It could be this is the first time through this
1193          * code, so there isn't anything to do.  */
1194         if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1195             (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
1196                 chg_passwd();           
1197         }
1198
1199         printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1200
1201         printf("<FORM name=\"swatform\" method=post>\n");
1202
1203         printf("<table>\n");
1204
1205         /* 
1206          * Create all the dialog boxes for data collection
1207          */
1208         printf("<tr><td> %s : </td>\n", _("User Name"));
1209         printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1210         printf("<tr><td> %s : </td>\n", _("Old Password"));
1211         printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1212         printf("<tr><td> %s : </td>\n", _("New Password"));
1213         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1214         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1215         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1216         printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1217         printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1218
1219         printf("</table>");
1220
1221         /*
1222          * Create all the control buttons for requesting action
1223          */
1224         printf("<input type=submit name=%s value=\"%s\">", 
1225                CHG_R_PASSWD_FLAG, _("Change Password"));
1226
1227         printf("<p></FORM>\n");
1228
1229         /*
1230          * Do some work if a request has been made to change the
1231          * password somewhere other than the server. It could be this
1232          * is the first time through this code, so there isn't
1233          * anything to do.  */
1234         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1235                 chg_passwd();           
1236         }
1237
1238 }
1239
1240 /****************************************************************************
1241   display a printers editing page  
1242 ****************************************************************************/
1243 static void printers_page(void)
1244 {
1245         const char *share = cgi_variable("share");
1246         char *s;
1247         int snum=-1;
1248         int i;
1249         int mode = 0;
1250         unsigned int parm_filter = FLAG_BASIC;
1251
1252         if (share)
1253                 snum = lp_servicenumber(share);
1254
1255         printf("<H2>%s</H2>\n", _("Printer Parameters"));
1256  
1257         printf("<H3>%s</H3>\n", _("Important Note:"));
1258         printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1259         printf("%s",_("are autoloaded printers from "));
1260         printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1261         printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1262
1263         if (cgi_variable("Commit") && snum >= 0) {
1264                 commit_parameters(snum);
1265                 if (snum >= iNumNonAutoPrintServices)
1266                     save_reload(snum);
1267                 else
1268                     save_reload(-1);
1269                 snum = lp_servicenumber(share);
1270         }
1271
1272         if (cgi_variable("Delete") && snum >= 0) {
1273                 lp_remove_service(snum);
1274                 save_reload(-1);
1275                 share = NULL;
1276                 snum = -1;
1277         }
1278
1279         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1280                 snum = lp_servicenumber(share);
1281                 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1282                         load_config(False);
1283                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
1284                         snum = lp_servicenumber(share);
1285                         lp_do_parameter(snum, "print ok", "Yes");
1286                         save_reload(snum);
1287                         snum = lp_servicenumber(share);
1288                 }
1289         }
1290
1291         printf("<FORM name=\"swatform\" method=post>\n");
1292
1293         if ( cgi_variable("ViewMode") )
1294                 mode = atoi(cgi_variable_nonull("ViewMode"));
1295         if ( cgi_variable("BasicMode"))
1296                 mode = 0;
1297         if ( cgi_variable("AdvMode"))
1298                 mode = 1;
1299
1300         ViewModeBoxes( mode );
1301         switch ( mode ) {
1302                 case 0:
1303                         parm_filter = FLAG_BASIC;
1304                         break;
1305                 case 1:
1306                         parm_filter = FLAG_ADVANCED;
1307                         break;
1308         }
1309         printf("<table>\n");
1310         printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1311         printf("<td><select name=\"share\">\n");
1312         if (snum < 0 || !lp_print_ok(snum))
1313                 printf("<option value=\" \"> \n");
1314         for (i=0;i<lp_numservices();i++) {
1315                 s = lp_servicename(i);
1316                 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1317                     if (i >= iNumNonAutoPrintServices)
1318                         printf("<option %s value=\"%s\">[*]%s\n",
1319                                (share && strcmp(share,s)==0)?"SELECTED":"",
1320                                s, s);
1321                     else
1322                         printf("<option %s value=\"%s\">%s\n", 
1323                                (share && strcmp(share,s)==0)?"SELECTED":"",
1324                                s, s);
1325                 }
1326         }
1327         printf("</select></td>");
1328         if (have_write_access) {
1329                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1330         }
1331         printf("</tr>");
1332         printf("</table>\n");
1333
1334         if (have_write_access) {
1335                 printf("<table>\n");
1336                 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1337                 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1338                 printf("</table>");
1339         }
1340
1341
1342         if (snum >= 0) {
1343                 if (have_write_access) {
1344                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1345                 }
1346                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1347                 printf("<p>\n");
1348         }
1349
1350         if (snum >= 0) {
1351                 printf("<table>\n");
1352                 show_parameters(snum, 1, parm_filter, 1);
1353                 printf("</table>\n");
1354         }
1355         printf("</FORM>\n");
1356 }
1357
1358 /*
1359   when the _() translation macro is used there is no obvious place to free
1360   the resulting string and there is no easy way to give a static pointer.
1361   All we can do is rotate between some static buffers and hope a single d_printf()
1362   doesn't have more calls to _() than the number of buffers
1363 */
1364
1365 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1366 {
1367         const char *msgstr;
1368         const char *ret;
1369
1370         msgstr = lang_msg(msgid);
1371         if (!msgstr) {
1372                 return msgid;
1373         }
1374
1375         ret = talloc_strdup(ctx, msgstr);
1376
1377         lang_msg_free(msgstr);
1378         if (!ret) {
1379                 return msgid;
1380         }
1381
1382         return ret;
1383 }
1384
1385 /**
1386  * main function for SWAT.
1387  **/
1388  int main(int argc, char *argv[])
1389 {
1390         const char *page;
1391         poptContext pc;
1392         struct poptOption long_options[] = {
1393                 POPT_AUTOHELP
1394                 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1395                 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" }, 
1396                 POPT_COMMON_SAMBA
1397                 POPT_TABLEEND
1398         };
1399         TALLOC_CTX *frame = talloc_stackframe();
1400
1401         fault_setup(NULL);
1402         umask(S_IWGRP | S_IWOTH);
1403
1404 #if defined(HAVE_SET_AUTH_PARAMETERS)
1405         set_auth_parameters(argc, argv);
1406 #endif /* HAVE_SET_AUTH_PARAMETERS */
1407
1408         /* just in case it goes wild ... */
1409         alarm(300);
1410
1411         setlinebuf(stdout);
1412
1413         /* we don't want any SIGPIPE messages */
1414         BlockSignals(True,SIGPIPE);
1415
1416         debug_set_logfile("/dev/null");
1417
1418         /* we don't want stderr screwing us up */
1419         close(2);
1420         open("/dev/null", O_WRONLY);
1421         setup_logging("swat", DEBUG_FILE);
1422
1423         pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1424
1425         /* Parse command line options */
1426
1427         while(poptGetNextOpt(pc) != -1) { }
1428
1429         poptFreeContext(pc);
1430
1431         load_case_tables();
1432         
1433         /* This should set a more apporiate log file */
1434         load_config(True);
1435         reopen_logs();
1436         load_interfaces();
1437         iNumNonAutoPrintServices = lp_numservices();
1438         load_printers(server_event_context(), server_messaging_context());
1439
1440         cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1441
1442         print_header();
1443
1444         cgi_load_variables();
1445
1446         if (!file_exist(get_dyn_CONFIGFILE())) {
1447                 have_read_access = True;
1448                 have_write_access = True;
1449         } else {
1450                 /* check if the authenticated user has write access - if not then
1451                    don't show write options */
1452                 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1453
1454                 /* if the user doesn't have read access to smb.conf then
1455                    don't let them view it */
1456                 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1457         }
1458
1459         show_main_buttons();
1460
1461         page = cgi_pathinfo();
1462
1463         /* Root gets full functionality */
1464         if (have_read_access && strcmp(page, "globals")==0) {
1465                 globals_page();
1466         } else if (have_read_access && strcmp(page,"shares")==0) {
1467                 shares_page();
1468         } else if (have_read_access && strcmp(page,"printers")==0) {
1469                 printers_page();
1470         } else if (have_read_access && strcmp(page,"status")==0) {
1471                 status_page();
1472         } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1473                 viewconfig_page();
1474         } else if (strcmp(page,"passwd")==0) {
1475                 passwd_page();
1476         } else if (have_read_access && strcmp(page,"wizard")==0) {
1477                 wizard_page();
1478         } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1479                 wizard_params_page();
1480         } else if (have_read_access && strcmp(page,"rewritecfg")==0) {
1481                 rewritecfg_file();
1482         } else {
1483                 welcome_page();
1484         }
1485
1486         print_footer();
1487
1488         TALLOC_FREE(frame);
1489         return 0;
1490 }
1491
1492 /** @} **/