1 /*
2  * $Id: mailinglist.c,v 1.5.2.15 2009/03/09 01:35:01 tomcollins Exp $
3  * Copyright (C) 1999-2004 Inter7 Internet Technologies, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18  *
19  */
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <unistd.h>
29 #include <pwd.h>
30 #include <dirent.h>
31 #include <errno.h>
32 
33 #include <vpopmail_config.h>
34 /* undef some macros that get redefined in config.h below */
35 #undef PACKAGE_NAME
36 #undef PACKAGE_STRING
37 #undef PACKAGE_TARNAME
38 #undef PACKAGE_VERSION
39 #include <vpopmail.h>
40 
41 #include "cgi.h"
42 #include "config.h"
43 #include "limits.h"
44 #include "mailinglist.h"
45 #include "printh.h"
46 #include "qmailadmin.h"
47 #include "qmailadminx.h"
48 #include "show.h"
49 #include "template.h"
50 #include "util.h"
51 
52 char dotqmail_name[MAX_FILE_NAME];
53 char replyto_addr[256];
54 int replyto;
55 int dotnum;
56 int checkopt[256];    /* used to display mailing list options */
57 
58 #define REPLYTO_SENDER 1
59 #define REPLYTO_LIST 2
60 #define REPLYTO_ADDRESS 3
61 
62 void set_options();
63 void default_options();
64 
show_mailing_lists(char * user,char * dom,time_t mytime)65 void show_mailing_lists(char *user, char *dom, time_t mytime)
66 {
67   if ( AdminType!=DOMAIN_ADMIN ) {
68     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
69     vclose();
70     exit(0);
71   }
72 
73   /* see if there's anything to display */
74   count_mailinglists();
75    if ( CurMailingLists == 0 ) {
76     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[231]);
77     show_menu(Username, Domain, Mytime);
78     vclose();
79     exit(0);
80   }
81 
82    if ( MaxMailingLists == 0 ) {
83     return;
84   }
85   send_template( "show_mailinglist.html" );
86 }
87 
show_mailing_list_line(char * user,char * dom,time_t mytime,char * dir)88 void show_mailing_list_line(char *user, char* dom, time_t mytime, char *dir)
89 {
90   DIR *mydir;
91   struct dirent *mydirent;
92   FILE *fs;
93   char *addr;
94   char testfn[MAX_FILE_NAME];
95   int i;
96 
97   if ( AdminType!=DOMAIN_ADMIN ) {
98     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
99     vclose();
100     exit(0);
101   }
102 
103    if ( MaxMailingLists == 0 ) {
104     return;
105   }
106 
107   if ( (mydir = opendir(".")) == NULL ) {
108     printf ("<tr><td>%s %d</tr><td>", html_text[143], 1);
109     return;
110   }
111 
112   /* First display the title row */
113   printf ("<tr bgcolor=\"#cccccc\">");
114   printf ("<th align=center><font size=2>%s</font></th>", html_text[72]);
115 #ifdef EZMLMIDX
116   printf ("<th align=center><font size=2>%s</font></th>", html_text[71]);
117 #endif
118   printf ("<th align=center><font size=2>%s</font></th>", html_text[81]);
119   printf ("<th align=center><font size=2>%s</font></th>", html_text[83]);
120   printf ("<th align=center><font size=2>%s</font></th>", html_text[84]);
121   printf ("<th align=center><font size=2>%s</font></th>", html_text[85]);
122 #ifdef EZMLMIDX
123   printf ("<th align=center><font size=2>%s</font></th>", html_text[86]);
124   printf ("<th align=center><font size=2>%s</font></th>", html_text[87]);
125   printf ("<th align=center><font size=2>%s</font></th>", html_text[88]);
126   printf ("<th align=center><font size=2>%s</font></th>", html_text[237]);
127   printf ("<th align=center><font size=2>%s</font></th>", html_text[238]);
128   printf ("<th align=center><font size=2>%s</font></th>", html_text[239]);
129 #endif
130   printf ("</tr>\n");
131 
132   sort_init();
133 
134   /* Now, display each list */
135   while( (mydirent=readdir(mydir)) != NULL ) {
136     if ( strncmp(".qmail-", mydirent->d_name, 7) == 0 ) {
137       if ( (fs=fopen(mydirent->d_name,"r"))==NULL) {
138 #ifdef EZMLMIDX
139         printf ("<tr><td colspan=12>%s %s</td></tr>\n", html_text[144], mydirent->d_name);
140 #else
141         printf ("<tr><td colspan=5>%s %s</td></tr>\n", html_text[144], mydirent->d_name);
142 #endif
143         continue;
144       }
145       fgets(TmpBuf2, sizeof(TmpBuf2), fs);
146       fclose(fs);
147       if ( strstr( TmpBuf2, "ezmlm-reject") != 0 ) {
148         sort_add_entry (&mydirent->d_name[7], 0);
149       }
150     }
151   }
152   closedir(mydir);
153   sort_dosort();
154 
155   for (i = 0; (addr = sort_get_entry(i)); ++i) {
156     sprintf (testfn, ".qmail-%s-digest-owner", addr);
157     /* convert ':' in addr to '.' */
158     str_replace (addr, ':', '.');
159 
160     printf ("<tr>");
161     qmail_button(addr, "delmailinglist", user, dom, mytime, "trash.png");
162 
163 #ifdef EZMLMIDX
164     qmail_button(addr, "modmailinglist", user, dom, mytime, "modify.png");
165 #endif
166     printh ("<td align=left>%H</td>\n", addr);
167 
168     qmail_button(addr, "addlistuser", user, dom, mytime, "delete.png");
169     qmail_button(addr, "dellistuser", user, dom, mytime, "delete.png");
170     qmail_button(addr, "showlistusers", user, dom, mytime, "delete.png");
171 
172 #ifdef EZMLMIDX
173     qmail_button(addr, "addlistmod", user, dom, mytime, "delete.png");
174     qmail_button(addr, "dellistmod", user, dom, mytime, "delete.png");
175     qmail_button(addr, "showlistmod", user, dom, mytime, "delete.png");
176 
177     /* Is it a digest list? */
178     if ( (fs=fopen(testfn,"r"))==NULL) {
179       /* not a digest list */
180       printf ("<TD COLSPAN=3> </TD>");
181     } else {
182       qmail_button(addr, "addlistdig", user, dom, mytime, "delete.png");
183       qmail_button(addr, "dellistdig", user, dom, mytime, "delete.png");
184       qmail_button(addr, "showlistdig", user, dom, mytime, "delete.png");
185       fclose(fs);
186     }
187 #endif
188     printf ("</tr>\n");
189   }
190   sort_cleanup();
191 }
192 
is_mailing_list(FILE * fs)193 int is_mailing_list(FILE *fs)
194 {
195        while (!feof(fs)) {
196                fgets( TmpBuf2, sizeof(TmpBuf2), fs);
197                if ( strstr( TmpBuf2, "ezmlm-reject") != 0 ||
198                     strstr( TmpBuf2, "ezmlm-send")   != 0 )
199                        return -1;
200        }
201        return 0;
202 }
203 
204 /* mailing list lines on the add user page */
show_mailing_list_line2(char * user,char * dom,time_t mytime,char * dir)205 void show_mailing_list_line2(char *user, char *dom, time_t mytime, char *dir)
206 {
207  DIR *mydir;
208  struct dirent *mydirent;
209  FILE *fs;
210  char *addr;
211  int i;
212  int listcount;
213 
214   if ( AdminType!=DOMAIN_ADMIN ) {
215     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
216     vclose();
217     exit(0);
218   }
219 
220   if (*EZMLMDIR == 'n' || MaxMailingLists == 0 ) {
221     return;
222   }
223 
224   if ( (mydir = opendir(".")) == NULL ) {
225     printf ("%s %d<BR>\n", html_text[143], 1);
226     return;
227   }
228 
229   listcount = 0;
230   sort_init();
231 
232   while( (mydirent=readdir(mydir)) != NULL ) {
233     if ( strncmp(".qmail-", mydirent->d_name, 7) == 0 ) {
234       if ( (fs=fopen(mydirent->d_name,"r"))==NULL) {
235         printf ("%s %s<br>\n",
236           html_text[144], mydirent->d_name);
237         continue;
238       }
239       fgets( TmpBuf2, sizeof(TmpBuf2), fs);
240       fclose(fs);
241       if ( strstr( TmpBuf2, "ezmlm-reject") != 0 ) {
242         sort_add_entry (&mydirent->d_name[7], 0);
243         listcount++;
244       }
245     }
246   }
247   closedir(mydir);
248 
249   /* if there aren't any lists, don't display anything */
250   if (listcount == 0) {
251     sort_cleanup();
252     return;
253   }
254 
255   printf ("<hr><table width=100%% cellpadding=1 cellspacing=0 border=0");
256   printf (" align=center bgcolor=\"#000000\"><tr><td>");
257   printf ("<table width=100%% cellpadding=0 cellspacing=0 border=0 bgcolor=\"#e6e6e6\">");
258   printf ("<tr><th bgcolor=\"#000000\" colspan=2>");
259   printf ("<font color=\"#ffffff\">%s</font></th>\n",
260     html_text[95]);
261 
262   sort_dosort();
263 
264   printf ("<INPUT NAME=number_of_mailinglist TYPE=hidden VALUE=%d>\n", listcount);
265   for (i = 0; i < listcount; ++i)
266   {
267     addr = sort_get_entry(i);
268     str_replace (addr, ':', '.');
269     printh ("<TR><TD ALIGN=RIGHT><INPUT NAME=\"subscribe%d\" TYPE=checkbox VALUE=\"%H\"></TD>", i, addr);
270     printh ("<TD align=LEFT>%H@%H</TD></TR>", addr, Domain);
271   }
272   printf ("</table></td></tr></table>\n");
273   sort_cleanup();
274 }
275 
addmailinglist()276 void addmailinglist()
277 {
278   if ( AdminType!=DOMAIN_ADMIN ) {
279     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
280     vclose();
281     exit(0);
282   }
283 
284   count_mailinglists();
285   load_limits();
286   if ( MaxMailingLists != -1 && CurMailingLists >= MaxMailingLists ) {
287     printf ("%s %d\n", html_text[184],
288       MaxMailingLists);
289     show_menu(Username, Domain, Mytime);
290     vclose();
291     exit(0);
292   }
293 
294   /* set up default options for new list */
295   default_options();
296 
297 #ifdef EZMLMIDX
298   send_template( "add_mailinglist-idx.html" );
299 #else
300   send_template( "add_mailinglist-no-idx.html" );
301 #endif
302 
303 }
304 
delmailinglist()305 void delmailinglist()
306 {
307   if ( AdminType!=DOMAIN_ADMIN ) {
308     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
309     vclose();
310     exit(0);
311   }
312 
313   send_template( "del_mailinglist_confirm.html" );
314 }
315 
delmailinglistnow()316 void delmailinglistnow()
317 {
318  DIR *mydir;
319  struct dirent *mydirent;
320 
321   if ( AdminType!=DOMAIN_ADMIN ) {
322     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
323     vclose();
324     exit(0);
325   }
326 
327   if (fixup_local_name (ActionUser)) {
328     // invalid address given, abort
329     vclose();
330     exit(0);
331   }
332 
333   if ( (mydir = opendir(".")) == NULL ) {
334     printf ("%s %d<BR>\n", html_text[143], 1);
335     printf ("</table>");
336     return;
337   }
338 
339 #ifdef ONCHANGE_SCRIPT
340   snprintf ( onchange_buf , MAX_BUFF , "%s@%s" , ActionUser , Domain ) ;
341   call_onchange ( "delmailinglist" ) ;
342 #endif
343 
344   /* make dotqmail name */
345   strcpy(dotqmail_name, ActionUser);
346   for(dotnum=0;dotqmail_name[dotnum]!='\0';dotnum++) {
347     if(dotqmail_name[dotnum]=='.') dotqmail_name[dotnum] = ':';
348   }
349 
350   sprintf(TmpBuf2, ".qmail-%s", dotqmail_name);
351   sprintf(TmpBuf3, ".qmail-%s-", dotqmail_name);
352   while( (mydirent=readdir(mydir)) != NULL ) {
353 
354     /* delete the main .qmail-"list" file */
355     if ( strcmp(TmpBuf2, mydirent->d_name) == 0 ) {
356       if ( unlink(mydirent->d_name) != 0 ) {
357         ack("185", TmpBuf2);
358       }
359 
360     /* delete secondary .qmail-"list"-* files */
361     } else if ( strncmp(TmpBuf3, mydirent->d_name, strlen(TmpBuf3)) == 0 ) {
362       if ( unlink(mydirent->d_name) != 0 ) {
363         ack("185", TmpBuf2);
364       }
365     }
366   }
367   closedir(mydir);
368 
369 
370   sprintf(TmpBuf2, "%s/%s", RealDir, ActionUser);
371   vdelfiles(TmpBuf2);
372 
373     count_mailinglists();
374   snprinth (StatusMessage, sizeof(StatusMessage), "%s %H\n", html_text[186], ActionUser);
375     if ( CurMailingLists == 0 ) {
376         show_menu(Username, Domain, Mytime);
377     } else {
378     show_mailing_lists(Username, Domain, Mytime);
379   }
380 
381 }
382 
383 /* sets the Reply-To header in header* files based on form fields
384  * designed to be called by ezmlm_make() (after calling ezmlm-make)
385  * Replaces the "Reply-To" line in <filename> with <newtext>.
386  */
ezmlm_setreplyto(char * filename,char * newtext)387 void ezmlm_setreplyto (char *filename, char *newtext)
388 {
389   FILE *headerfile, *temp;
390   char realfn[256];
391   char tempfn[256];
392   char buf[256];
393 
394   sprintf (realfn, "%s/%s/%s", RealDir, ActionUser, filename);
395   sprintf (tempfn, "%s.tmp", realfn);
396 
397   headerfile = fopen(realfn, "r");
398   if (!headerfile) return;
399   temp = fopen(tempfn, "w");
400   if (!temp) { fclose (headerfile); return; }
401 
402   /* copy contents to new file, except for Reply-To header */
403   while (fgets (buf, sizeof(buf), headerfile) != NULL) {
404     if (strncasecmp ("Reply-To", buf, 8) != 0) {
405       fputs (buf, temp);
406     }
407   }
408 
409   fputs (newtext, temp);
410 
411   fclose (headerfile);
412   fclose (temp);
413   unlink (realfn);
414   rename (tempfn, realfn);
415 }
416 
ezmlm_make(int newlist)417 void ezmlm_make (int newlist)
418 {
419   FILE * file;
420   int pid;
421 
422 #ifdef EZMLMIDX
423   char list_owner[MAX_BUFF];
424   char owneremail[MAX_BUFF+5];
425 #endif
426   char options[MAX_BUFF];
427   char *arguments[MAX_BUFF];
428   int argc;
429   int i=0;
430   char tmp[MAX_BUFF];
431   char *tmpstr;
432   char loop_ch[64];
433   int  loop;
434 
435   /* Initialize listopt to be a string of the characters A-Z, with each one
436    * set to the correct case (e.g., A or a) to match the expected behavior
437    * of not checking any checkboxes.  Leave other letters blank.
438    * NOTE: Leave F out, since we handle it manually.
439    */
440   char listopt[] = "A  D   hIj L N pQRST      ";
441 
442   if ( AdminType!=DOMAIN_ADMIN ) {
443     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
444     vclose();
445     exit(0);
446   }
447 
448   if ( fixup_local_name(ActionUser) ) {
449     snprinth (StatusMessage, sizeof(StatusMessage), "%s %H\n", html_text[188], ActionUser);
450     addmailinglist();
451     vclose();
452     exit(0);
453   }
454 
455   /* update listopt based on user selections */
456   for (loop = 0; loop < 20; loop++) {
457     sprintf(tmp, "opt%d=", loop);
458     GetValue(TmpCGI, loop_ch, tmp, sizeof(loop_ch));
459     for (tmpstr = loop_ch; *tmpstr; tmpstr++)
460     {
461       if ((*tmpstr >= 'A') && (*tmpstr <= 'Z')) {
462         listopt[*tmpstr-'A'] = *tmpstr;
463       } else if ((*tmpstr >= 'a') && (*tmpstr <= 'z')) {
464         listopt[*tmpstr-'a'] = *tmpstr;
465       }
466     }
467   }
468 
469   /* don't allow option c, force option e if modifying existing list */
470   listopt[2] = ' ';
471   listopt[4] = newlist ? ' ' : 'e';
472 
473   argc=0;
474   arguments[argc++] = "ezmlm-make";
475 
476 #ifdef EZMLMIDX
477   /* check the list owner entry */
478   GetValue(TmpCGI, list_owner, "listowner=", sizeof(list_owner)); // Get the listowner
479   if ( strlen(list_owner) > 0 ) {
480     sprintf (owneremail, "-5%s", list_owner);
481     arguments[argc++] = owneremail;
482   }
483 #endif
484 
485   /* build the option string */
486   tmpstr = options;
487   arguments[argc++] = tmpstr;
488   *tmpstr++ = '-';
489 #ifndef EZMLMIDX
490   /* non idx list, only allows options A and P */
491   *tmpstr++ = listopt[0];        /* a or A */
492   *tmpstr++ = listopt['p'-'a'];  /* p or P */
493   *tmpstr++ = 0;   /* add NULL terminator */
494 #else
495   /* ignore options v-z, but test a-u */
496   for (i = 0; i <= ('u'-'a'); i++)
497   {
498     if (listopt[i] != ' ') {
499       *tmpstr++ = listopt[i];
500     }
501   }
502   *tmpstr++ = 0;   /* add NULL terminator */
503 
504   /* check for sql support */
505   GetValue(TmpCGI, tmp, "sqlsupport=", sizeof(tmp));
506   if( strlen(tmp) > 0 ) {
507     arguments[argc++] = tmpstr;
508     tmpstr += sprintf (tmpstr, "%s", tmp) + 1;
509     arguments[argc++] = tmpstr;
510     for(loop = 1; loop <= NUM_SQL_OPTIONS; loop++) {
511       sprintf(tmp, "sql%d=", loop);
512       GetValue(TmpCGI, loop_ch, tmp, sizeof(loop_ch));
513       tmpstr += sprintf (tmpstr, "%s:", loop_ch);
514     }
515     /* remove trailing : */
516     tmpstr--;
517     *tmpstr++ = 0;
518   }
519 #endif
520 
521   /* make dotqmail name */
522   strcpy(dotqmail_name, ActionUser);
523   for(dotnum=0;dotqmail_name[dotnum]!='\0';dotnum++) {
524     if(dotqmail_name[dotnum]=='.') dotqmail_name[dotnum] = ':';
525   }
526   pid=fork();
527   if (pid==0) {
528     sprintf(TmpBuf1, "%s/ezmlm-make", EZMLMDIR);
529     sprintf(TmpBuf2, "%s/%s", RealDir, ActionUser);
530     sprintf(TmpBuf3, "%s/.qmail-%s", RealDir, dotqmail_name);
531 
532     arguments[argc++]=TmpBuf2;
533     arguments[argc++]=TmpBuf3;
534     arguments[argc++]=ActionUser;
535     arguments[argc++]=Domain;
536     arguments[argc]=NULL;
537 
538     execv(TmpBuf1, arguments);
539     exit(127);
540   } else {
541     wait(&pid);
542   }
543 
544   /*
545    * ezmlm-make -e leaves .qmail-listname-(accept||reject) links for some reason.
546    * (causing file permission errors in "show mailing lists") Also, it doesn't
547    * delete dir/digest/ when turning off digests.  This section cleans up...
548    */
549   if(listopt['M'-'A'] == 'M') { /* moderation off */
550     sprintf(tmp, "%s/.qmail-%s-accept-default", RealDir, dotqmail_name);
551     unlink (tmp);
552     sprintf(tmp, "%s/.qmail-%s-reject-default", RealDir, dotqmail_name);
553     unlink (tmp);
554   }
555   if(listopt['D'-'A'] == 'D') { /* digest off */
556     sprintf(tmp, "%s/.qmail-%s-digest-return-default", RealDir, dotqmail_name);
557     unlink (tmp);
558     sprintf(tmp, "%s/.qmail-%s-digest-owner", RealDir, dotqmail_name);
559     unlink (tmp);
560 
561     /* delete the digest directory */
562     sprintf(tmp, "%s/%s/digest", RealDir, ActionUser);
563     vdelfiles(tmp);
564     chdir(RealDir);
565   }
566 
567   /* Check for prefix setting */
568   GetValue(TmpCGI, tmp, "prefix=", sizeof(tmp));
569 
570   /* strip leading '[' and trailing ']' from tmp */
571   tmpstr = strchr (tmp, ']');
572   if (tmpstr != NULL) *tmpstr = '\0';
573   tmpstr = tmp;
574   while (*tmpstr == '[') tmpstr++;
575 
576   /* Create (or delete) the file as appropriate */
577   sprintf(TmpBuf, "%s/%s/prefix", RealDir, ActionUser);
578   if (strlen(tmp) > 0)
579   {
580     file=fopen(TmpBuf , "w");
581     if (file)
582     {
583       fprintf(file, "[%s]", tmpstr);
584       fclose(file);
585     }
586   }
587   else
588   {
589     unlink (TmpBuf);
590   }
591 
592     /* set Reply-To header */
593     GetValue (TmpCGI, TmpBuf, "replyto=", sizeof(TmpBuf));
594     replyto = atoi(TmpBuf);
595     if (replyto == REPLYTO_SENDER) {
596         /* ezmlm shouldn't remove/add Reply-To header */
597         ezmlm_setreplyto ("headeradd", "");
598         ezmlm_setreplyto ("headerremove", "");
599     } else {
600         if (replyto == REPLYTO_ADDRESS) {
601             GetValue (TmpCGI, replyto_addr, "replyaddr=", sizeof(replyto_addr));
602             sprintf (TmpBuf, "Reply-To: %s\n", replyto_addr);
603         } else {  /* REPLYTO_LIST */
604             strcpy (TmpBuf, "Reply-To: <#l#>@<#h#>\n");
605             }
606         ezmlm_setreplyto ("headeradd", TmpBuf);
607         ezmlm_setreplyto ("headerremove", "Reply-To");
608     }
609 
610   /* update inlocal file */
611   sprintf(TmpBuf, "%s/%s/inlocal", RealDir, ActionUser);
612   if ((file=fopen(TmpBuf, "w")) != NULL) {
613     fprintf(file, "%s-%s", Domain, ActionUser);
614     fclose(file);
615   }
616 
617 #ifdef EZMLMIDX
618   /* if this is a new list, add owner as subscriber */
619   if (newlist && (*list_owner != '\0')) {
620     ezmlm_sub ("", list_owner);
621     if (listopt['M'-'A'] == 'm') { /* moderation on */
622       /* add owner as moderator/remote admin as well */
623       ezmlm_sub ("mod", list_owner);
624     }
625   }
626 #endif
627 }
628 
addmailinglistnow()629 void addmailinglistnow()
630 {
631   count_mailinglists();
632   load_limits();
633   if ( MaxMailingLists != -1 && CurMailingLists >= MaxMailingLists ) {
634     printf ("%s %d\n", html_text[184],
635       MaxMailingLists);
636     show_menu(Username, Domain, Mytime);
637     vclose();
638     exit(0);
639   }
640 
641   if ( check_local_user(ActionUser) ) {
642     snprinth (StatusMessage, sizeof(StatusMessage), "%s %H\n", html_text[175], ActionUser);
643     addmailinglist();
644     vclose();
645     exit(0);
646   }
647 
648   ezmlm_make(1);
649 
650 #ifdef ONCHANGE_SCRIPT
651   snprintf ( onchange_buf , MAX_BUFF , "%s@%s" , ActionUser , Domain ) ;
652   call_onchange ( "addmailinglist" ) ;
653 #endif
654 
655   snprinth (StatusMessage, sizeof(StatusMessage), "%s %H@%H\n", html_text[187],
656           ActionUser, Domain);
657   show_mailing_lists(Username, Domain, Mytime);
658 }
659 
show_list_group_now(int mod)660 void show_list_group_now(int mod)
661 {
662   /* mod = 0 for subscribers, 1 for moderators, 2 for digest users */
663 
664  FILE *fs;
665  int handles[2],pid,z = 0,subuser_count = 0;
666  char buf[256];
667  char *addr;
668 
669   if ( AdminType!=DOMAIN_ADMIN ) {
670     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
671     vclose();
672     exit(0);
673   }
674 
675   lowerit(ActionUser);
676   pipe(handles);
677 
678   pid=fork();
679   if (pid==0) {
680     close(handles[0]);
681     dup2(handles[1],fileno(stdout));
682     sprintf(TmpBuf1, "%s/ezmlm-list", EZMLMDIR);
683     if(mod == 1) {
684         sprintf(TmpBuf2, "%s/%s/mod", RealDir, ActionUser);
685     } else if(mod == 2) {
686         sprintf(TmpBuf2, "%s/%s/digest", RealDir, ActionUser);
687     } else {
688         sprintf(TmpBuf2, "%s/%s/", RealDir, ActionUser);
689     }
690     execl(TmpBuf1, "ezmlm-list", TmpBuf2, NULL);
691     exit(127);
692   } else {
693     close(handles[1]);
694     fs = fdopen(handles[0],"r");
695 
696     /* Load subscriber/moderator list */
697 
698     sort_init();
699     while( (fgets(buf, sizeof(buf), fs)!= NULL)) {
700       sort_add_entry (buf, '\n');   /* don't copy newline */
701       subuser_count++;
702     }
703 
704     sort_dosort();
705 
706     /* Display subscriber/moderator/digest list, along with delete button */
707     if(mod == 1) {
708         strcpy(TmpBuf, "228"); strcpy(TmpBuf1, "220");
709         /* strcpy(TmpBuf2, "087"); */
710     } else if(mod == 2) {
711         strcpy(TmpBuf, "244"); strcpy(TmpBuf1, "246");
712         /* strcpy(TmpBuf2, "245"); */
713     } else {
714         strcpy(TmpBuf, "230"); strcpy(TmpBuf1, "222");
715         /* strcpy(TmpBuf2, "084"); */
716     }
717     strcpy(TmpBuf2, "072");
718     printf ("<TABLE border=0 width=\"100%%\">\n");
719     printf (" <TR>\n");
720     printf ("  <TH align=left COLSPAN=4><B>%s</B> %d<BR><BR></TH>\n", get_html_text(TmpBuf), subuser_count);
721     printf (" </TR>\n");
722     printf (" <TR align=center bgcolor=%s>\n", get_color_text("002"));
723     printf ("  <TH align=center><b><font size=2>%s</font></b></TH>\n", get_html_text(TmpBuf2));
724     printf ("  <TH align=center><b><font size=2>%s</font></b></TH>\n", get_html_text(TmpBuf1));
725     printf ("  <TH align=center><b><font size=2>%s</font></b></TH>\n", get_html_text(TmpBuf2));
726     printf ("  <TH align=center><b><font size=2>%s</font></b></TH>\n", get_html_text(TmpBuf1));
727     printf (" </TR>\n");
728 
729     if(mod == 1) {
730         strcpy(TmpBuf, "dellistmodnow");
731     } else if(mod == 2) {
732         strcpy(TmpBuf, "dellistdignow");
733     } else {
734         strcpy(TmpBuf, "dellistusernow");
735     }
736     for(z = 0; (addr = sort_get_entry(z)); ++z) {
737       printf (" <TR align=center>");
738       printh ("  <TD align=right><A href=\"%s&modu=%C&newu=%C\"><IMG src=\"%s/trash.png\" border=0></A></TD>\n",
739         cgiurl(TmpBuf), ActionUser, addr, IMAGEURL);
740       printh ("  <TD align=left>%H</TD>\n", addr);
741       ++z;
742       if( (addr = sort_get_entry(z)) ) {
743         printh ("  <TD align=right><A href=\"%s&modu=%C&newu=%C\"><IMG src=\"%s/trash.png\" border=0></A></TD>\n",
744           cgiurl(TmpBuf), ActionUser, addr, IMAGEURL);
745       printh ("  <TD align=left>%H</TD>\n", addr);
746       } else {
747         printf ("  <TD COLSPAN=2> </TD>");
748       }
749       printf (" </TR>");
750     }
751 
752     sort_cleanup();
753 
754     printf ("</TABLE>");
755     fclose(fs); close(handles[0]);
756     wait(&pid);
757     snprintf (StatusMessage, sizeof(StatusMessage), "%s\n", html_text[190]);
758     /* printf (get_html_text("END_LIST_NAMES")); */
759 
760   }
761 }
762 
show_list_group(char * template)763 void show_list_group(char *template)
764 {
765   if (AdminType != DOMAIN_ADMIN) {
766     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
767     vclose();
768     exit(0);
769   }
770 
771   if (MaxMailingLists == 0) {
772     return;
773   }
774 
775   send_template(template);
776 }
777 
addlistgroup(char * template)778 void addlistgroup (char *template)
779 {
780   if ( AdminType!=DOMAIN_ADMIN ) {
781     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
782     vclose();
783     exit(0);
784   }
785   send_template(template);
786 }
787 
addlistuser()788 void addlistuser() { addlistgroup( "add_listuser.html" ); }
addlistmod()789 void addlistmod() { addlistgroup( "add_listmod.html" ); }
addlistdig()790 void addlistdig() { addlistgroup( "add_listdig.html" ); }
791 
792 /* returns 0 for success */
ezmlm_sub(char * dir,char * email)793 int ezmlm_sub (char *dir, char *email)
794 {
795  int pid;
796  char subpath[MAX_BUFF];
797  char listpath[MAX_BUFF];
798 
799   pid=fork();
800   if (pid==0) {
801     snprintf(subpath, sizeof(subpath), "%s/ezmlm-sub", EZMLMDIR);
802     snprintf(listpath, sizeof(listpath), "%s/%s/%s",
803       RealDir, ActionUser, dir);
804     execl(subpath, "ezmlm-sub", listpath, email, NULL);
805     exit(127);
806   } else wait(&pid);
807 
808   /* need to check exit code for failure somehow */
809 
810   return 0;
811 }
812 
addlistgroupnow(int mod)813 void addlistgroupnow (int mod)
814 {
815   // mod = 0 for subscribers, 1 for moderators, 2 for digest subscribers
816 
817   if ( AdminType!=DOMAIN_ADMIN ) {
818     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
819     vclose();
820     exit(0);
821   }
822 
823   lowerit(ActionUser);
824 
825   if ( check_email_addr(Newu) ) {
826     snprinth (StatusMessage, sizeof(StatusMessage), "%s %H\n", html_text[148], Newu);
827     if (mod == 1) {
828       addlistmod();
829     } else if (mod == 2) {
830       addlistdig();
831     } else {
832       addlistuser();
833     }
834     vclose();
835     exit(0);
836   }
837 
838   if(mod == 1 ) {
839     ezmlm_sub ("mod", Newu);
840     snprinth (StatusMessage, sizeof(StatusMessage), "%H %s %H@%H\n", Newu,
841         html_text[194], ActionUser, Domain);
842     send_template( "add_listmod.html" );
843   } else if(mod == 2) {
844     ezmlm_sub ("digest", Newu);
845     snprinth (StatusMessage, sizeof(StatusMessage), "%H %s %H@%H\n", Newu,
846         html_text[240], ActionUser, Domain);
847     send_template( "add_listdig.html" );
848   } else {
849     ezmlm_sub ("", Newu);
850     snprinth (StatusMessage, sizeof(StatusMessage), "%H %s %H@%H\n", Newu,
851         html_text[193], ActionUser, Domain);
852     send_template( "add_listuser.html" );
853   }
854   vclose();
855   exit(0);
856 }
857 
dellistgroup(char * template)858 void dellistgroup(char *template)
859 {
860   if ( AdminType!=DOMAIN_ADMIN ) {
861     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
862     vclose();
863     exit(0);
864   }
865 
866   send_template(template);
867 }
868 
dellistgroupnow(int mod)869 void dellistgroupnow(int mod)
870 {
871  int pid;
872  char *p;
873 
874   if ( AdminType!=DOMAIN_ADMIN ) {
875     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
876     vclose();
877     exit(0);
878   }
879 
880   lowerit(Newu);
881 
882   // for dealing with AOL spam complaints, if address doesn't contain @,
883   // but does contain '=', change the '=' to '@'.
884   if (! strchr (Newu, '@')) {
885     if ((p = strchr (Newu, '='))) *p = '@';
886   }
887 
888   pid=fork();
889   if (pid==0) {
890     sprintf(TmpBuf1, "%s/ezmlm-unsub", EZMLMDIR);
891     if(mod == 1) {
892         sprintf(TmpBuf2, "%s/%s/mod", RealDir, ActionUser);
893     } else if(mod == 2 ) {
894         sprintf(TmpBuf2, "%s/%s/digest", RealDir, ActionUser);
895     } else {
896         sprintf(TmpBuf2, "%s/%s/", RealDir, ActionUser);
897     }
898     execl(TmpBuf1, "ezmlm-unsub", TmpBuf2, Newu, NULL);
899     exit(127);
900   } else wait(&pid);
901 
902   if(mod == 1) {
903     snprinth (StatusMessage, sizeof(StatusMessage), "%H %s %H@%H\n", Newu, html_text[197],
904         ActionUser, Domain);
905   } else if(mod == 2) {
906     snprinth (StatusMessage, sizeof(StatusMessage), "%H %s %H@%H\n", Newu, html_text[242],
907         ActionUser, Domain);
908   } else {
909     snprinth (StatusMessage, sizeof(StatusMessage), "%H %s %H@%H\n", Newu, html_text[203],
910         ActionUser, Domain);
911   }
912   show_mailing_lists(Username, Domain, Mytime);
913   vclose();
914   exit(0);
915 }
916 
count_mailinglists()917 void count_mailinglists()
918 {
919  DIR *mydir;
920  struct dirent *mydirent;
921  FILE *fs;
922 
923   if ( (mydir = opendir(".")) == NULL ) {
924     printf ("%s %d<BR>\n", html_text[143], 1);
925     printf ("</table>");
926     return;
927   }
928 
929 
930   CurMailingLists = 0;
931   while( (mydirent=readdir(mydir)) != NULL ) {
932     if ( strncmp(".qmail-", mydirent->d_name, 7) == 0 ) {
933       if ( (fs=fopen(mydirent->d_name,"r"))==NULL) {
934         printf (html_text[144], mydirent->d_name);
935         continue;
936       }
937       fgets( TmpBuf2, sizeof(TmpBuf2), fs);
938       if ( strstr( TmpBuf2, "ezmlm-reject") != 0 ) {
939         ++CurMailingLists;
940       }
941       fclose(fs);
942     }
943   }
944   closedir(mydir);
945 
946 }
947 
modmailinglist()948 void modmailinglist()
949 {
950   /* name of list to modify is stored in ActionUser */
951  int i;
952  FILE *fs;
953 
954   if ( AdminType!=DOMAIN_ADMIN ) {
955     snprintf (StatusMessage, sizeof(StatusMessage), "%s", html_text[142]);
956     vclose();
957     exit(0);
958   }
959 
960   strcpy (Alias, "");  /* initialize Alias (list owner) to empty string */
961 
962   /* get the current listowner and copy it to Alias */
963   strcpy (dotqmail_name, ActionUser);
964   str_replace (dotqmail_name, '.', ':');
965   sprintf(TmpBuf, ".qmail-%s-owner", dotqmail_name);
966   if((fs=fopen(TmpBuf, "r"))!=NULL) {
967     while(fgets(TmpBuf2, sizeof(TmpBuf2), fs)) {
968       if(strstr(TmpBuf2, "@")!=NULL) {
969         /* strip leading & if present */
970         sprintf(Alias, "%s", (*TmpBuf2 == '&' ? (TmpBuf2 + 1) : TmpBuf2) );
971         i = strlen(Alias); --i; Alias[i] = '\0'; /* strip newline */
972       }
973     }
974     fclose(fs);
975   }
976 
977   /* set default to "replies go to original sender" */
978   replyto = REPLYTO_SENDER;  /* default */
979   *replyto_addr = '\0';
980   sprintf(TmpBuf, "%s/headeradd", ActionUser);
981   /* get the Reply-To setting for the list */
982   if ((fs = fopen (TmpBuf, "r")) != NULL) {
983     while (fgets (TmpBuf2, sizeof(TmpBuf2), fs)) {
984       if (strncasecmp ("Reply-To: ", TmpBuf2, 10) == 0) {
985         i = strlen(TmpBuf2); --i; TmpBuf2[i] = '\0'; /* strip newline */
986         if (strcmp ("<#l#>@<#h#>", TmpBuf2 + 10) == 0) {
987           replyto = REPLYTO_LIST;
988         } else {
989           replyto = REPLYTO_ADDRESS;
990           strcpy (replyto_addr, TmpBuf2 + 10);
991         }
992       }
993     }
994     fclose(fs);
995   }
996 
997   /* read in options for the current list */
998   set_options();
999 
1000 #ifdef EZMLMIDX
1001   send_template( "mod_mailinglist-idx.html" );
1002 #else
1003   send_template( "show_mailinglists.html" );
1004 #endif
1005 
1006 }
1007 
modmailinglistnow()1008 void modmailinglistnow()
1009 {
1010   ezmlm_make(0);
1011 
1012   snprinth (StatusMessage, sizeof(StatusMessage), "%s %H@%H\n", html_text[226],
1013     ActionUser, Domain);
1014   show_mailing_lists(Username, Domain, Mytime);
1015 }
1016 
build_list_value(char * param,char * color,char * opt1,int desc1,char * opt2,int desc2,int checked)1017 void build_list_value(char *param, char *color, char *opt1, int desc1, char *opt2, int desc2, int checked)
1018 {
1019   printf ("<tr bgcolor=%s>\n", get_color_text(color));
1020   printf ("  <td>\n");
1021   printf ("    <input type=radio name=%s value=%s%s></td>\n", param, opt1, checked ? "" : " CHECKED");
1022   printf ("  <td>%s</td>\n", html_text[desc1]);
1023   printf ("  <td>\n");
1024   printf ("    <input type=radio name=%s value=%s%s></td>\n", param, opt2, checked ? " CHECKED" : "");
1025   printf ("  <td>%s</td>\n", html_text[desc2]);
1026   printf ("</tr>\n");
1027 }
1028 
build_option_str(char * type,char * param,char * options,char * description)1029 void build_option_str (char *type, char *param, char *options, char *description)
1030 {
1031   int selected;
1032   char *optptr;
1033 
1034   selected = 1;
1035   for (optptr = options; *optptr; optptr++)
1036   {
1037     selected = selected && checkopt[(int) *optptr];
1038   }
1039   /* selected is now true if all options for this radio button are true */
1040 
1041   printh ("<INPUT TYPE=%s NAME=\"%H\" VALUE=\"%H\"%s> %s\n",
1042     type, param, options, selected ? " CHECKED" : "", description);
1043 }
1044 
file_exists(char * filename)1045 int file_exists (char *filename)
1046 {
1047   FILE *fs;
1048   if( (fs=fopen(filename, "r")) !=NULL ) {
1049     fclose(fs);
1050     return 1;
1051   } else {
1052     return 0;
1053   }
1054 }
1055 
get_ezmlmidx_line_arguments(char * line,char * program,char argument)1056 int get_ezmlmidx_line_arguments(char *line, char *program, char argument)
1057 {
1058   char *begin;
1059   char *end;
1060   char *arg;
1061 
1062   // does line contain program name?
1063   if ((strstr(line, program)) != NULL) {
1064     // find the options
1065     begin=strchr(line, ' ');
1066     begin++;
1067     if (*begin == '-') {
1068       end=strchr(begin, ' ');
1069       arg=strchr(begin, argument);
1070       // if arg is found && it's in the options (before the trailing space), return 1
1071       if (arg && (arg < end)) return 1;
1072     }
1073   }
1074   return 0;
1075 }
1076 
set_options()1077 void set_options() {
1078  char c;
1079  FILE *fs;
1080 
1081   /*
1082    * Note that with ezmlm-idx it might be possible to replace most
1083    * of this code by reading the config file in the list's directory.
1084    */
1085 
1086   /* make dotqmail name (ActionUser with '.' replaced by ':') */
1087   strcpy(dotqmail_name, ActionUser);
1088   for(dotnum=0;dotqmail_name[dotnum]!='\0';dotnum++) {
1089     if(dotqmail_name[dotnum]=='.') dotqmail_name[dotnum] = ':';
1090   }
1091 
1092   // default to false for lowercase letters
1093   for (c = 'a'; c <= 'z'; checkopt[(int) c++] = 0);
1094 
1095   // figure out some options in the -default file
1096   sprintf(TmpBuf, ".qmail-%s-default", dotqmail_name);
1097   if( (fs=fopen(TmpBuf, "r")) !=NULL ) {
1098     while(fgets(TmpBuf2, sizeof(TmpBuf2), fs)) {
1099       if((get_ezmlmidx_line_arguments(TmpBuf2, "ezmlm-get", 'P')) > 0) {
1100         checkopt['b'] = 1;
1101       }
1102       if((get_ezmlmidx_line_arguments(TmpBuf2, "ezmlm-get", 's')) > 0) {
1103         checkopt['g'] = 1;
1104       }
1105       if((get_ezmlmidx_line_arguments(TmpBuf2, "ezmlm-manage", 'S')) > 0) {
1106         checkopt['h'] = 1;
1107       }
1108       if((get_ezmlmidx_line_arguments(TmpBuf2, "ezmlm-manage", 'U')) > 0) {
1109         checkopt['j'] = 1;
1110       }
1111       if((get_ezmlmidx_line_arguments(TmpBuf2, "ezmlm-manage", 'l')) > 0) {
1112         checkopt['l'] = 1;
1113       }
1114       if((get_ezmlmidx_line_arguments(TmpBuf2, "ezmlm-manage", 'e')) > 0) {
1115         checkopt['n'] = 1;
1116       }
1117       if((strstr(TmpBuf2, "ezmlm-request")) != 0) {
1118         checkopt['q'] = 1;
1119       }
1120     }
1121     fclose(fs);
1122   }
1123 
1124   // figure out some options in the -accept-default file
1125   sprintf(TmpBuf, ".qmail-%s-accept-default", dotqmail_name);
1126   if( (fs=fopen(TmpBuf, "r")) !=NULL ) {
1127     while(fgets(TmpBuf2, sizeof(TmpBuf2), fs)) {
1128       if(strstr(TmpBuf2, "ezmlm-archive") !=0) {
1129         checkopt['i'] = 1;
1130       }
1131     }
1132     fclose(fs);
1133   }
1134 
1135   // figure out some options in the qmail file
1136   sprintf(TmpBuf, ".qmail-%s", dotqmail_name);
1137   if( (fs=fopen(TmpBuf, "r")) !=NULL ) {
1138     while(fgets(TmpBuf2, sizeof(TmpBuf2), fs)) {
1139       if((get_ezmlmidx_line_arguments(TmpBuf2, "ezmlm-store", 'P')) > 0) {
1140         checkopt['o'] = 1;
1141       }
1142       if((strstr(TmpBuf2, "ezmlm-gate")) != 0 || (strstr(TmpBuf2, "ezmlm-issubn")) != 0) {
1143         checkopt['u'] = 1;
1144       }
1145       if(strstr(TmpBuf2, "ezmlm-archive") !=0) {
1146         checkopt['i'] = 1;
1147       }
1148     }
1149     fclose(fs);
1150   }
1151 
1152   sprintf(TmpBuf, ".qmail-%s-accept-default", dotqmail_name);
1153   checkopt['m'] = file_exists(TmpBuf);
1154 
1155   sprintf(TmpBuf, "%s/archived", ActionUser);
1156   checkopt['a'] = file_exists(TmpBuf);
1157 
1158   sprintf(TmpBuf, "%s/digest/bouncer", ActionUser);
1159   checkopt['d'] = file_exists(TmpBuf);
1160 
1161   sprintf(TmpBuf, "%s/prefix", ActionUser);
1162   checkopt['f'] = file_exists(TmpBuf);
1163 
1164   sprintf(TmpBuf, "%s/public", ActionUser);
1165   checkopt['p'] = file_exists(TmpBuf);
1166 
1167   sprintf(TmpBuf, "%s/remote", ActionUser);
1168   checkopt['r'] = file_exists(TmpBuf);
1169 
1170   sprintf(TmpBuf, "%s/modsub", ActionUser);
1171   checkopt['s'] = file_exists(TmpBuf);
1172 
1173   sprintf(TmpBuf, "%s/text/trailer", ActionUser);
1174   checkopt['t'] = file_exists(TmpBuf);
1175 
1176   /* update the uppercase option letters (just the opposite of the lowercase) */
1177   for (c = 'A'; c <= 'Z'; c++)
1178   {
1179     checkopt[(int) c] = !checkopt[(int) (c - 'A' + 'a')];
1180   }
1181 }
1182 
default_options()1183 void default_options() {
1184   char c;
1185 
1186   *dotqmail_name = '\0';
1187   replyto = REPLYTO_SENDER;
1188   *replyto_addr = '\0';
1189 
1190   /* These are currently set to defaults for a good, generic list.
1191    * Basically, make it safe/friendly and don't turn anything extra on.
1192    */
1193 
1194   /* for the options below, use 1 for "on" or "yes" */
1195   checkopt['a'] = 1; /* Archive */
1196   checkopt['b'] = 1; /* Moderator-only access to archive */
1197   checkopt['c'] = 0; /* ignored */
1198   checkopt['d'] = 0; /* Digest */
1199   checkopt['e'] = 0; /* ignored */
1200   checkopt['f'] = 1; /* Prefix */
1201   checkopt['g'] = 1; /* Guard Archive */
1202   checkopt['h'] = 0; /* Subscribe doesn't require conf */
1203   checkopt['i'] = 0; /* Indexed */
1204   checkopt['j'] = 0; /* Unsubscribe doesn't require conf */
1205   checkopt['k'] = 0; /* Create a blocked sender list */
1206   checkopt['l'] = 0; /* Remote admins can access subscriber list */
1207   checkopt['m'] = 0; /* Moderated */
1208   checkopt['n'] = 0; /* Remote admins can edit text files */
1209   checkopt['o'] = 0; /* Others rejected (for Moderated lists only */
1210   checkopt['p'] = 1; /* Public */
1211   checkopt['q'] = 1; /* Service listname-request */
1212   checkopt['r'] = 0; /* Remote Administration */
1213   checkopt['s'] = 0; /* Subscriptions are moderated */
1214   checkopt['t'] = 0; /* Add Trailer to outgoing messages */
1215   checkopt['u'] = 1; /* Only subscribers can post */
1216   checkopt['v'] = 0; /* ignored */
1217   checkopt['w'] = 0; /* special ezmlm-warn handling (ignored) */
1218   checkopt['x'] = 0; /* enable some extras (ignored) */
1219   checkopt['y'] = 0; /* ignored */
1220   checkopt['z'] = 0; /* ignored */
1221 
1222   /* update the uppercase option letters (just the opposite of the lowercase) */
1223   for (c = 'A'; c <= 'Z'; c++)
1224   {
1225     checkopt[(int) c] = !checkopt[(int) (c - 'A' + 'a')];
1226   }
1227 }
1228 
show_current_list_values()1229 void show_current_list_values() {
1230  FILE *fs;
1231  int sqlfileok = 0;
1232  int usesql = 0;
1233  int i=0,j;
1234  char checked1[MAX_BUFF] = "";
1235  char listname[128];
1236  int checked;
1237 
1238   /* Note that we do not support the following list options:
1239    *   k - posts from addresses in listname/deny are rejected
1240    *   x - strip annoying MIME parts (spreadsheets, rtf, html, etc.)
1241    *   0 - make the list a sublist of another list
1242    *   3 - replace the From: header with another address
1243    *   4 - digest options (limits related to sending digest out)
1244    *   7, 8, 9 - break moderators up into message, subscription and admin
1245    */
1246 
1247   /* IMPORTANT: If you change the behavior of the checkboxes, you need
1248    * to update the default settings in modmailinglistnow so qmailadmin
1249    * will use the proper settings when a checkbox isn't checked.
1250    */
1251 
1252   if (*dotqmail_name) { /* modifying an existing list */
1253     snprinth (listname, sizeof(listname), "%H", dotqmail_name);
1254     str_replace (listname, ':', '.');
1255   } else {
1256     sprintf (listname, "<I>%s</I>", html_text[261]);
1257   }
1258 
1259   /* Posting Messages */
1260   printf ("<P><B><U>%s</U></B><BR>\n", html_text[262]);
1261   build_option_str ("RADIO", "opt1", "MU", html_text[263]);
1262   printf ("<BR>\n");
1263   build_option_str ("RADIO", "opt1", "Mu", html_text[264]);
1264   printf ("<BR>\n");
1265   build_option_str ("RADIO", "opt1", "mu", html_text[265]);
1266   printf ("<BR>\n");
1267   build_option_str ("RADIO", "opt1", "mUo", html_text[266]);
1268   printf ("<BR>\n");
1269   build_option_str ("RADIO", "opt1", "mUO", html_text[267]);
1270   printf ("</P>\n");
1271 
1272   /* List Options */
1273   printf ("<P><B><U>%s</U></B><BR>\n", html_text[268]);
1274   /* this next option isn't necessary since we use the edit box to
1275    * set/delete the prefix
1276   sprintf (TmpBuf, html_text[269], listname);
1277   build_option_str ("CHECKBOX", "opt3", "f", TmpBuf);
1278   printf ("<BR>\n");
1279   */
1280   printf ("<TABLE><TR><TD ROWSPAN=3 VALIGN=TOP>%s</TD>",
1281     html_text[310]);
1282   printf ("<TD><INPUT TYPE=RADIO NAME=\"replyto\" VALUE=\"%d\"%s>%s</TD></TR>\n",
1283     REPLYTO_SENDER, (replyto == REPLYTO_SENDER) ? " CHECKED" : "", html_text[311]);
1284   printf ("<TR><TD><INPUT TYPE=RADIO NAME=\"replyto\" VALUE=\"%d\"%s>%s</TD></TR>\n",
1285     REPLYTO_LIST, (replyto == REPLYTO_LIST) ? " CHECKED" : "", html_text[312]);
1286   printf ("<TR><TD><INPUT TYPE=RADIO NAME=\"replyto\" VALUE=\"%d\"%s>%s ",
1287     REPLYTO_ADDRESS, (replyto == REPLYTO_ADDRESS) ? " CHECKED" : "", html_text[313]);
1288   printh ("<INPUT TYPE=TEXT NAME=\"replyaddr\" VALUE=\"%H\" SIZE=30></TD></TR>\n",
1289     replyto_addr);
1290   printf ("</TABLE><BR>\n");
1291   build_option_str ("CHECKBOX", "opt4", "t", html_text[270]);
1292   printf ("<BR>\n");
1293   build_option_str ("CHECKBOX", "opt5", "d", html_text[271]);
1294   sprintf (TmpBuf, html_text[272], listname);
1295   printf ("<SMALL>(%s)</SMALL>", TmpBuf);
1296   printf ("<BR>\n");
1297   sprintf (TmpBuf, html_text[273], listname);
1298   build_option_str ("CHECKBOX", "opt6", "q", TmpBuf);
1299   printf ("<BR>\n");
1300   sprintf (TmpBuf, html_text[274], listname, listname, listname);
1301   printf ("&nbsp; &nbsp; <SMALL>(%s)</SMALL></P>", TmpBuf);
1302 
1303   /* Remote Administration */
1304   printf ("<P><B><U>%s</U></B><BR>\n", html_text[275]);
1305   build_option_str ("CHECKBOX", "opt7", "r", html_text[276]);
1306   printf ("<BR>\n");
1307   build_option_str ("CHECKBOX", "opt8", "P", html_text[277]);
1308   printf ("<SMALL>(%s)</SMALL><BR>", html_text[278]);
1309   printf ("<TABLE><TR><TD ROWSPAN=2 VALIGN=TOP>%s</TD>",
1310     html_text[279]);
1311   printf ("<TD>");
1312   build_option_str ("CHECKBOX", "opt9", "l", html_text[280]);
1313   printf ("</TD>\n</TR><TR>\n<TD>");
1314   build_option_str ("CHECKBOX", "opt10", "n", html_text[281]);
1315   printf ("<SMALL>(%s)</SMALL>.</TD>\n", html_text[282]);
1316   printf ("</TR></TABLE>\n</P>\n");
1317 
1318   printf ("<P><B><U>%s</U></B><BR>\n", html_text[283]);
1319   printf ("%s<BR>\n&nbsp; &nbsp; ", html_text[284]);
1320   build_option_str ("CHECKBOX", "opt11", "H", html_text[285]);
1321   printf ("<BR>\n&nbsp; &nbsp; ");
1322   build_option_str ("CHECKBOX", "opt12", "s", html_text[286]);
1323   printf ("<BR>\n%s<BR>\n&nbsp; &nbsp; ", html_text[287]);
1324   build_option_str ("CHECKBOX", "opt13", "J", html_text[285]);
1325   printf ("<BR>\n");
1326   printf ("<SMALL>%s</SMALL>\n</P>\n", html_text[288]);
1327 
1328   printf ("<P><B><U>%s</U></B><BR>\n", html_text[289]);
1329   build_option_str ("CHECKBOX", "opt14", "a", html_text[290]);
1330   printf (" &nbsp; %s\n<SELECT NAME=\"opt15\">", html_text[292]);
1331   printf ("<OPTION VALUE=\"BG\"%s>%s\n",
1332   	checkopt['B'] && checkopt['G'] ? " SELECTED" : "", html_text[293]);
1333   printf ("<OPTION VALUE=\"Bg\"%s>%s\n",
1334   	checkopt['B'] && checkopt['g'] ? " SELECTED" : "", html_text[294]);
1335   printf ("<OPTION VALUE=\"b\"%s>%s\n",
1336   	checkopt['b'] ? " SELECTED" : "", html_text[295]);
1337   printf ("</SELECT>.");
1338   printf ("<BR>\n");
1339   /* note that if user doesn't have ezmlm-cgi installed, it might be
1340      a good idea to default to having option i off. */
1341   build_option_str ("CHECKBOX", "opt16", "i", html_text[291]);
1342   printf ("</P>\n");
1343 
1344   /***********************/
1345   /* begin MySQL options */
1346   /***********************/
1347 
1348   /* See if sql is turned on */
1349   checked = 0;
1350   sprintf(TmpBuf, "%s/sql", ActionUser);
1351   if( (fs=fopen(TmpBuf, "r")) !=NULL ) {
1352     checked = 1;
1353     while(fgets(TmpBuf2, sizeof(TmpBuf2), fs)) {
1354       strcpy(TmpBuf1, TmpBuf2);
1355       i = strlen(TmpBuf1); --i; TmpBuf1[i] = 0; /* take off newline */
1356       if((strstr(TmpBuf1, ":")) != NULL) {
1357         sqlfileok = 1;
1358       }
1359     }
1360     usesql = 1;
1361     fclose(fs);
1362   }
1363 #ifdef ENABLE_MYSQL
1364   printf ("<P><B><U>%s</U></B><BR>\n", html_text[99]);
1365   printf ("<input type=checkbox name=\"sqlsupport\" value=\"-6\"%s> %s",
1366     checked ? " CHECKED" : "", html_text[53]);
1367 
1368   /* parse dir/sql file for SQL settings */
1369   printf ("    <table cellpadding=0 cellspacing=2 border=0>\n");
1370 #else
1371   if (checked)
1372     printf ("<INPUT TYPE=HIDDEN NAME=sqlsupport VALUE=\"-6\">\n");
1373 #endif
1374 
1375   /* get hostname */
1376   strcpy(checked1, "localhost");
1377   if(usesql == 1 && sqlfileok == 1) {
1378     strncpy(TmpBuf3, TmpBuf1, 1);
1379     if((strstr(TmpBuf3, ":")) == NULL) {
1380       for(i=0,j=0;TmpBuf1[i]!=':'&&TmpBuf1[i]!='\0';++j,++i) checked1[j] = TmpBuf1[i];
1381       checked1[j] = '\0';
1382     }
1383   }
1384 
1385 #ifdef ENABLE_MYSQL
1386   printf ("      <tr>\n");
1387   printf ("        <td ALIGN=RIGHT>%s:\n", html_text[54]);
1388   printf ("          </td><td>\n");
1389   printh ("          <input type=text name=sql1 value=\"%H\"></td>\n", checked1);
1390 #else
1391   printh ("<INPUT TYPE=HIDDEN NAME=sql1 VALUE=\"%H\">\n", checked1);
1392 #endif
1393 
1394   /* get port */
1395   strcpy(checked1, "3306");
1396   if(usesql == 1 && sqlfileok == 1) {
1397     strncpy(TmpBuf3, &TmpBuf1[++i], 1);
1398     if((strstr(TmpBuf3, ":")) == NULL) {
1399       for(j=0;TmpBuf1[i]!=':'&&TmpBuf1[i]!='\0';++j,++i) checked1[j] = TmpBuf1[i];
1400       checked1[j] = '\0';
1401     }
1402   }
1403 #ifdef ENABLE_MYSQL
1404   printf ("        <td ALIGN=RIGHT>%s:\n", html_text[55]);
1405   printf ("          </td><td>\n");
1406   printh ("          <input type=text size=7 name=sql2 value=\"%H\"></td>\n", checked1);
1407   printf ("      </tr>\n");
1408 #else
1409   printh ("<INPUT TYPE=HIDDEN NAME=sql2 VALUE=\"%H\">\n", checked1);
1410 #endif
1411 
1412   /* get user */
1413   strcpy(checked1, "");
1414   if(usesql == 1 && sqlfileok == 1) {
1415     strncpy(TmpBuf3, &TmpBuf1[++i], 1);
1416     if((strstr(TmpBuf3, ":")) == NULL) {
1417       for(j=0;TmpBuf1[i]!=':'&&TmpBuf1[i]!='\0';++j,++i) checked1[j] = TmpBuf1[i];
1418       checked1[j] = '\0';
1419     }
1420   }
1421 #ifdef ENABLE_MYSQL
1422   printf ("      <tr>\n");
1423   printf ("        <td ALIGN=RIGHT>%s:\n", html_text[56]);
1424   printf ("          </td><td>\n");
1425   printh ("          <input type=text name=sql3 value=\"%H\"></td>\n", checked1);
1426 #else
1427   printh ("<INPUT TYPE=HIDDEN NAME=sql3 VALUE=\"%H\">\n", checked1);
1428 #endif
1429 
1430   /* get password */
1431   strcpy(checked1, "");
1432   if(usesql == 1 && sqlfileok == 1) {
1433     strncpy(TmpBuf3, &TmpBuf1[++i], 1);
1434     if((strstr(TmpBuf3, ":")) == NULL) {
1435       for(j=0;TmpBuf1[i]!=':'&&TmpBuf1[i]!='\0';++j,++i) checked1[j] = TmpBuf1[i];
1436       checked1[j] = '\0';
1437     }
1438   }
1439 #ifdef ENABLE_MYSQL
1440   printf ("        <td ALIGN=RIGHT>%s:\n", html_text[57]);
1441   printf ("          </td><td>\n");
1442   printh ("          <input type=text name=sql4 value=\"%H\"></td>\n", checked1);
1443   printf ("      </tr>\n");
1444 #else
1445   printh ("<INPUT TYPE=HIDDEN NAME=sql4 VALUE=\"%H\">\n", checked1);
1446 #endif
1447 
1448   /* get database name */
1449   strcpy(checked1, "");
1450   if(usesql == 1 && sqlfileok == 1) {
1451     strncpy(TmpBuf3, &TmpBuf1[++i], 1);
1452     if((strstr(TmpBuf3, ":")) == NULL) {
1453       for(j=0;TmpBuf1[i]!=':'&&TmpBuf1[i]!='\0';++j,++i) checked1[j] = TmpBuf1[i];
1454       checked1[j] = '\0';
1455     }
1456   }
1457 #ifdef ENABLE_MYSQL
1458   printf ("      <tr>\n");
1459   printf ("        <td ALIGN=RIGHT>%s:\n", html_text[58]);
1460   printf ("          </td><td>\n");
1461   printh ("          <input type=text name=sql5 value=\"%H\"></td>\n", checked1);
1462 #else
1463   printh ("<INPUT TYPE=HIDDEN NAME=sql5 VALUE=\"%H\">\n", checked1);
1464 #endif
1465 
1466   /* get table name */
1467   strcpy(checked1, "ezmlm");
1468   if(usesql == 1 && sqlfileok == 1) {
1469     ++i;
1470     if(strlen(TmpBuf1) != i) {
1471       for(j=0;TmpBuf1[i]!=':'&&TmpBuf1[i]!='\0';++j,++i) checked1[j] = TmpBuf1[i];
1472       checked1[j] = '\0';
1473     }
1474   }
1475 #ifdef ENABLE_MYSQL
1476   printf ("        <td ALIGN=RIGHT>%s:\n", html_text[59]);
1477   printf ("          </td><td>\n");
1478   printh ("          <input type=text name=\"sql6\" value=\"%H\"></td>\n", checked1);
1479   printf ("      </tr>\n");
1480   printf ("    </table>\n");
1481 #else
1482   printh ("<INPUT TYPE=HIDDEN NAME=sql6 VALUE=\"%H\">\n", checked1);
1483 #endif
1484 
1485 }
1486 
get_mailinglist_prefix(char * prefix)1487 int get_mailinglist_prefix(char* prefix)
1488 {
1489   char buffer[MAX_BUFF];
1490   char *b, *p;
1491   FILE* file;
1492 
1493   sprintf(buffer, "%s/%s/prefix", RealDir, ActionUser);
1494   file=fopen(buffer , "r");
1495 
1496   if (file)
1497   {
1498     fgets(buffer, sizeof(buffer), file);
1499     fclose(file);
1500 
1501     b = buffer;
1502     p = prefix;
1503     while (*b == '[') b++;
1504     while ((*b != ']') && (*b != '\n') && (*b != '\0')) *p++ = *b++;
1505     *p++ = '\0';
1506   }
1507   else
1508   {
1509     return 1;
1510   }
1511   return 0;
1512 }
1513 
1514